18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/drivers/message/fusion/mptbase.c 38c2ecf20Sopenharmony_ci * This is the Fusion MPT base driver which supports multiple 48c2ecf20Sopenharmony_ci * (SCSI + LAN) specialized protocol drivers. 58c2ecf20Sopenharmony_ci * For use with LSI PCI chip/adapter(s) 68c2ecf20Sopenharmony_ci * running LSI Fusion MPT (Message Passing Technology) firmware. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright (c) 1999-2008 LSI Corporation 98c2ecf20Sopenharmony_ci * (mailto:DL-MPTFusionLinux@lsi.com) 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci This program is free software; you can redistribute it and/or modify 158c2ecf20Sopenharmony_ci it under the terms of the GNU General Public License as published by 168c2ecf20Sopenharmony_ci the Free Software Foundation; version 2 of the License. 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci This program is distributed in the hope that it will be useful, 198c2ecf20Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 208c2ecf20Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 218c2ecf20Sopenharmony_ci GNU General Public License for more details. 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci NO WARRANTY 248c2ecf20Sopenharmony_ci THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR 258c2ecf20Sopenharmony_ci CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT 268c2ecf20Sopenharmony_ci LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, 278c2ecf20Sopenharmony_ci MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is 288c2ecf20Sopenharmony_ci solely responsible for determining the appropriateness of using and 298c2ecf20Sopenharmony_ci distributing the Program and assumes all risks associated with its 308c2ecf20Sopenharmony_ci exercise of rights under this Agreement, including but not limited to 318c2ecf20Sopenharmony_ci the risks and costs of program errors, damage to or loss of data, 328c2ecf20Sopenharmony_ci programs or equipment, and unavailability or interruption of operations. 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci DISCLAIMER OF LIABILITY 358c2ecf20Sopenharmony_ci NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY 368c2ecf20Sopenharmony_ci DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 378c2ecf20Sopenharmony_ci DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND 388c2ecf20Sopenharmony_ci ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 398c2ecf20Sopenharmony_ci TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 408c2ecf20Sopenharmony_ci USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED 418c2ecf20Sopenharmony_ci HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci You should have received a copy of the GNU General Public License 448c2ecf20Sopenharmony_ci along with this program; if not, write to the Free Software 458c2ecf20Sopenharmony_ci Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 468c2ecf20Sopenharmony_ci*/ 478c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#include <linux/kernel.h> 508c2ecf20Sopenharmony_ci#include <linux/module.h> 518c2ecf20Sopenharmony_ci#include <linux/errno.h> 528c2ecf20Sopenharmony_ci#include <linux/init.h> 538c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 548c2ecf20Sopenharmony_ci#include <linux/slab.h> 558c2ecf20Sopenharmony_ci#include <linux/types.h> 568c2ecf20Sopenharmony_ci#include <linux/pci.h> 578c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 588c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 598c2ecf20Sopenharmony_ci#include <linux/delay.h> 608c2ecf20Sopenharmony_ci#include <linux/interrupt.h> /* needed for in_interrupt() proto */ 618c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 628c2ecf20Sopenharmony_ci#include <linux/kthread.h> 638c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#include "mptbase.h" 668c2ecf20Sopenharmony_ci#include "lsi/mpi_log_fc.h" 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 698c2ecf20Sopenharmony_ci#define my_NAME "Fusion MPT base driver" 708c2ecf20Sopenharmony_ci#define my_VERSION MPT_LINUX_VERSION_COMMON 718c2ecf20Sopenharmony_ci#define MYNAM "mptbase" 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciMODULE_AUTHOR(MODULEAUTHOR); 748c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(my_NAME); 758c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 768c2ecf20Sopenharmony_ciMODULE_VERSION(my_VERSION); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* 798c2ecf20Sopenharmony_ci * cmd line parameters 808c2ecf20Sopenharmony_ci */ 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic int mpt_msi_enable_spi; 838c2ecf20Sopenharmony_cimodule_param(mpt_msi_enable_spi, int, 0); 848c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpt_msi_enable_spi, 858c2ecf20Sopenharmony_ci " Enable MSI Support for SPI controllers (default=0)"); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic int mpt_msi_enable_fc; 888c2ecf20Sopenharmony_cimodule_param(mpt_msi_enable_fc, int, 0); 898c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpt_msi_enable_fc, 908c2ecf20Sopenharmony_ci " Enable MSI Support for FC controllers (default=0)"); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic int mpt_msi_enable_sas; 938c2ecf20Sopenharmony_cimodule_param(mpt_msi_enable_sas, int, 0); 948c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpt_msi_enable_sas, 958c2ecf20Sopenharmony_ci " Enable MSI Support for SAS controllers (default=0)"); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic int mpt_channel_mapping; 988c2ecf20Sopenharmony_cimodule_param(mpt_channel_mapping, int, 0); 998c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpt_channel_mapping, " Mapping id's to channels (default=0)"); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic int mpt_debug_level; 1028c2ecf20Sopenharmony_cistatic int mpt_set_debug_level(const char *val, const struct kernel_param *kp); 1038c2ecf20Sopenharmony_cimodule_param_call(mpt_debug_level, mpt_set_debug_level, param_get_int, 1048c2ecf20Sopenharmony_ci &mpt_debug_level, 0600); 1058c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpt_debug_level, 1068c2ecf20Sopenharmony_ci " debug level - refer to mptdebug.h - (default=0)"); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ciint mpt_fwfault_debug; 1098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_fwfault_debug); 1108c2ecf20Sopenharmony_cimodule_param(mpt_fwfault_debug, int, 0600); 1118c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mpt_fwfault_debug, 1128c2ecf20Sopenharmony_ci "Enable detection of Firmware fault and halt Firmware on fault - (default=0)"); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic char MptCallbacksName[MPT_MAX_PROTOCOL_DRIVERS] 1158c2ecf20Sopenharmony_ci [MPT_MAX_CALLBACKNAME_LEN+1]; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#ifdef MFCNT 1188c2ecf20Sopenharmony_cistatic int mfcounter = 0; 1198c2ecf20Sopenharmony_ci#define PRINT_MF_COUNT 20000 1208c2ecf20Sopenharmony_ci#endif 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1238c2ecf20Sopenharmony_ci/* 1248c2ecf20Sopenharmony_ci * Public data... 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#define WHOINIT_UNKNOWN 0xAA 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * Private data... 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci /* Adapter link list */ 1348c2ecf20Sopenharmony_ciLIST_HEAD(ioc_list); 1358c2ecf20Sopenharmony_ci /* Callback lookup table */ 1368c2ecf20Sopenharmony_cistatic MPT_CALLBACK MptCallbacks[MPT_MAX_PROTOCOL_DRIVERS]; 1378c2ecf20Sopenharmony_ci /* Protocol driver class lookup table */ 1388c2ecf20Sopenharmony_cistatic int MptDriverClass[MPT_MAX_PROTOCOL_DRIVERS]; 1398c2ecf20Sopenharmony_ci /* Event handler lookup table */ 1408c2ecf20Sopenharmony_cistatic MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; 1418c2ecf20Sopenharmony_ci /* Reset handler lookup table */ 1428c2ecf20Sopenharmony_cistatic MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; 1438c2ecf20Sopenharmony_cistatic struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 1468c2ecf20Sopenharmony_cistatic struct proc_dir_entry *mpt_proc_root_dir; 1478c2ecf20Sopenharmony_ci#endif 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * Driver Callback Index's 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_cistatic u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS; 1538c2ecf20Sopenharmony_cistatic u8 last_drv_idx; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 1568c2ecf20Sopenharmony_ci/* 1578c2ecf20Sopenharmony_ci * Forward protos... 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_cistatic irqreturn_t mpt_interrupt(int irq, void *bus_id); 1608c2ecf20Sopenharmony_cistatic int mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, 1618c2ecf20Sopenharmony_ci MPT_FRAME_HDR *reply); 1628c2ecf20Sopenharmony_cistatic int mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, 1638c2ecf20Sopenharmony_ci u32 *req, int replyBytes, u16 *u16reply, int maxwait, 1648c2ecf20Sopenharmony_ci int sleepFlag); 1658c2ecf20Sopenharmony_cistatic int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag); 1668c2ecf20Sopenharmony_cistatic void mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev); 1678c2ecf20Sopenharmony_cistatic void mpt_adapter_disable(MPT_ADAPTER *ioc); 1688c2ecf20Sopenharmony_cistatic void mpt_adapter_dispose(MPT_ADAPTER *ioc); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); 1718c2ecf20Sopenharmony_cistatic int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); 1728c2ecf20Sopenharmony_cistatic int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); 1738c2ecf20Sopenharmony_cistatic int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); 1748c2ecf20Sopenharmony_cistatic int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); 1758c2ecf20Sopenharmony_cistatic int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); 1768c2ecf20Sopenharmony_cistatic int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); 1778c2ecf20Sopenharmony_cistatic int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); 1788c2ecf20Sopenharmony_cistatic int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); 1798c2ecf20Sopenharmony_cistatic int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); 1808c2ecf20Sopenharmony_cistatic int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); 1818c2ecf20Sopenharmony_cistatic int PrimeIocFifos(MPT_ADAPTER *ioc); 1828c2ecf20Sopenharmony_cistatic int WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag); 1838c2ecf20Sopenharmony_cistatic int WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag); 1848c2ecf20Sopenharmony_cistatic int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); 1858c2ecf20Sopenharmony_cistatic int GetLanConfigPages(MPT_ADAPTER *ioc); 1868c2ecf20Sopenharmony_cistatic int GetIoUnitPage2(MPT_ADAPTER *ioc); 1878c2ecf20Sopenharmony_ciint mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); 1888c2ecf20Sopenharmony_cistatic int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); 1898c2ecf20Sopenharmony_cistatic int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); 1908c2ecf20Sopenharmony_cistatic void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); 1918c2ecf20Sopenharmony_cistatic void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); 1928c2ecf20Sopenharmony_cistatic void mpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc); 1938c2ecf20Sopenharmony_cistatic int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, 1948c2ecf20Sopenharmony_ci int sleepFlag); 1958c2ecf20Sopenharmony_cistatic int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); 1968c2ecf20Sopenharmony_cistatic int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); 1978c2ecf20Sopenharmony_cistatic int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 2008c2ecf20Sopenharmony_cistatic int mpt_summary_proc_show(struct seq_file *m, void *v); 2018c2ecf20Sopenharmony_cistatic int mpt_version_proc_show(struct seq_file *m, void *v); 2028c2ecf20Sopenharmony_cistatic int mpt_iocinfo_proc_show(struct seq_file *m, void *v); 2038c2ecf20Sopenharmony_ci#endif 2048c2ecf20Sopenharmony_cistatic void mpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic int ProcessEventNotification(MPT_ADAPTER *ioc, 2078c2ecf20Sopenharmony_ci EventNotificationReply_t *evReply, int *evHandlers); 2088c2ecf20Sopenharmony_cistatic void mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); 2098c2ecf20Sopenharmony_cistatic void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); 2108c2ecf20Sopenharmony_cistatic void mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info); 2118c2ecf20Sopenharmony_cistatic void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info , u8 cb_idx); 2128c2ecf20Sopenharmony_cistatic int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); 2138c2ecf20Sopenharmony_cistatic void mpt_inactive_raid_list_free(MPT_ADAPTER *ioc); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/* module entry point */ 2168c2ecf20Sopenharmony_cistatic int __init fusion_init (void); 2178c2ecf20Sopenharmony_cistatic void __exit fusion_exit (void); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci#define CHIPREG_READ32(addr) readl_relaxed(addr) 2208c2ecf20Sopenharmony_ci#define CHIPREG_READ32_dmasync(addr) readl(addr) 2218c2ecf20Sopenharmony_ci#define CHIPREG_WRITE32(addr,val) writel(val, addr) 2228c2ecf20Sopenharmony_ci#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr) 2238c2ecf20Sopenharmony_ci#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr) 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic void 2268c2ecf20Sopenharmony_cipci_disable_io_access(struct pci_dev *pdev) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci u16 command_reg; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &command_reg); 2318c2ecf20Sopenharmony_ci command_reg &= ~1; 2328c2ecf20Sopenharmony_ci pci_write_config_word(pdev, PCI_COMMAND, command_reg); 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic void 2368c2ecf20Sopenharmony_cipci_enable_io_access(struct pci_dev *pdev) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci u16 command_reg; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &command_reg); 2418c2ecf20Sopenharmony_ci command_reg |= 1; 2428c2ecf20Sopenharmony_ci pci_write_config_word(pdev, PCI_COMMAND, command_reg); 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic int mpt_set_debug_level(const char *val, const struct kernel_param *kp) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci int ret = param_set_int(val, kp); 2488c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (ret) 2518c2ecf20Sopenharmony_ci return ret; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci list_for_each_entry(ioc, &ioc_list, list) 2548c2ecf20Sopenharmony_ci ioc->debug_level = mpt_debug_level; 2558c2ecf20Sopenharmony_ci return 0; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci/** 2598c2ecf20Sopenharmony_ci * mpt_get_cb_idx - obtain cb_idx for registered driver 2608c2ecf20Sopenharmony_ci * @dclass: class driver enum 2618c2ecf20Sopenharmony_ci * 2628c2ecf20Sopenharmony_ci * Returns cb_idx, or zero means it wasn't found 2638c2ecf20Sopenharmony_ci **/ 2648c2ecf20Sopenharmony_cistatic u8 2658c2ecf20Sopenharmony_cimpt_get_cb_idx(MPT_DRIVER_CLASS dclass) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci u8 cb_idx; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) 2708c2ecf20Sopenharmony_ci if (MptDriverClass[cb_idx] == dclass) 2718c2ecf20Sopenharmony_ci return cb_idx; 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/** 2768c2ecf20Sopenharmony_ci * mpt_is_discovery_complete - determine if discovery has completed 2778c2ecf20Sopenharmony_ci * @ioc: per adatper instance 2788c2ecf20Sopenharmony_ci * 2798c2ecf20Sopenharmony_ci * Returns 1 when discovery completed, else zero. 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_cistatic int 2828c2ecf20Sopenharmony_cimpt_is_discovery_complete(MPT_ADAPTER *ioc) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci ConfigExtendedPageHeader_t hdr; 2858c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 2868c2ecf20Sopenharmony_ci SasIOUnitPage0_t *buffer; 2878c2ecf20Sopenharmony_ci dma_addr_t dma_handle; 2888c2ecf20Sopenharmony_ci int rc = 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t)); 2918c2ecf20Sopenharmony_ci memset(&cfg, 0, sizeof(CONFIGPARMS)); 2928c2ecf20Sopenharmony_ci hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; 2938c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 2948c2ecf20Sopenharmony_ci hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; 2958c2ecf20Sopenharmony_ci cfg.cfghdr.ehdr = &hdr; 2968c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if ((mpt_config(ioc, &cfg))) 2998c2ecf20Sopenharmony_ci goto out; 3008c2ecf20Sopenharmony_ci if (!hdr.ExtPageLength) 3018c2ecf20Sopenharmony_ci goto out; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, 3048c2ecf20Sopenharmony_ci &dma_handle); 3058c2ecf20Sopenharmony_ci if (!buffer) 3068c2ecf20Sopenharmony_ci goto out; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci cfg.physAddr = dma_handle; 3098c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if ((mpt_config(ioc, &cfg))) 3128c2ecf20Sopenharmony_ci goto out_free_consistent; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (!(buffer->PhyData[0].PortFlags & 3158c2ecf20Sopenharmony_ci MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS)) 3168c2ecf20Sopenharmony_ci rc = 1; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci out_free_consistent: 3198c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, 3208c2ecf20Sopenharmony_ci buffer, dma_handle); 3218c2ecf20Sopenharmony_ci out: 3228c2ecf20Sopenharmony_ci return rc; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci/** 3278c2ecf20Sopenharmony_ci * mpt_remove_dead_ioc_func - kthread context to remove dead ioc 3288c2ecf20Sopenharmony_ci * @arg: input argument, used to derive ioc 3298c2ecf20Sopenharmony_ci * 3308c2ecf20Sopenharmony_ci * Return 0 if controller is removed from pci subsystem. 3318c2ecf20Sopenharmony_ci * Return -1 for other case. 3328c2ecf20Sopenharmony_ci */ 3338c2ecf20Sopenharmony_cistatic int mpt_remove_dead_ioc_func(void *arg) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; 3368c2ecf20Sopenharmony_ci struct pci_dev *pdev; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci if (!ioc) 3398c2ecf20Sopenharmony_ci return -1; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci pdev = ioc->pcidev; 3428c2ecf20Sopenharmony_ci if (!pdev) 3438c2ecf20Sopenharmony_ci return -1; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci pci_stop_and_remove_bus_device_locked(pdev); 3468c2ecf20Sopenharmony_ci return 0; 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci/** 3528c2ecf20Sopenharmony_ci * mpt_fault_reset_work - work performed on workq after ioc fault 3538c2ecf20Sopenharmony_ci * @work: input argument, used to derive ioc 3548c2ecf20Sopenharmony_ci * 3558c2ecf20Sopenharmony_ci**/ 3568c2ecf20Sopenharmony_cistatic void 3578c2ecf20Sopenharmony_cimpt_fault_reset_work(struct work_struct *work) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = 3608c2ecf20Sopenharmony_ci container_of(work, MPT_ADAPTER, fault_reset_work.work); 3618c2ecf20Sopenharmony_ci u32 ioc_raw_state; 3628c2ecf20Sopenharmony_ci int rc; 3638c2ecf20Sopenharmony_ci unsigned long flags; 3648c2ecf20Sopenharmony_ci MPT_SCSI_HOST *hd; 3658c2ecf20Sopenharmony_ci struct task_struct *p; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (ioc->ioc_reset_in_progress || !ioc->active) 3688c2ecf20Sopenharmony_ci goto out; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci ioc_raw_state = mpt_GetIocState(ioc, 0); 3728c2ecf20Sopenharmony_ci if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_MASK) { 3738c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "%s: IOC is non-operational !!!!\n", 3748c2ecf20Sopenharmony_ci ioc->name, __func__); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* 3778c2ecf20Sopenharmony_ci * Call mptscsih_flush_pending_cmds callback so that we 3788c2ecf20Sopenharmony_ci * flush all pending commands back to OS. 3798c2ecf20Sopenharmony_ci * This call is required to aovid deadlock at block layer. 3808c2ecf20Sopenharmony_ci * Dead IOC will fail to do diag reset,and this call is safe 3818c2ecf20Sopenharmony_ci * since dead ioc will never return any command back from HW. 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_ci hd = shost_priv(ioc->sh); 3848c2ecf20Sopenharmony_ci ioc->schedule_dead_ioc_flush_running_cmds(hd); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci /*Remove the Dead Host */ 3878c2ecf20Sopenharmony_ci p = kthread_run(mpt_remove_dead_ioc_func, ioc, 3888c2ecf20Sopenharmony_ci "mpt_dead_ioc_%d", ioc->id); 3898c2ecf20Sopenharmony_ci if (IS_ERR(p)) { 3908c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 3918c2ecf20Sopenharmony_ci "%s: Running mpt_dead_ioc thread failed !\n", 3928c2ecf20Sopenharmony_ci ioc->name, __func__); 3938c2ecf20Sopenharmony_ci } else { 3948c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 3958c2ecf20Sopenharmony_ci "%s: Running mpt_dead_ioc thread success !\n", 3968c2ecf20Sopenharmony_ci ioc->name, __func__); 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci return; /* don't rearm timer */ 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if ((ioc_raw_state & MPI_IOC_STATE_MASK) 4028c2ecf20Sopenharmony_ci == MPI_IOC_STATE_FAULT) { 4038c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "IOC is in FAULT state (%04xh)!!!\n", 4048c2ecf20Sopenharmony_ci ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK); 4058c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "Issuing HardReset from %s!!\n", 4068c2ecf20Sopenharmony_ci ioc->name, __func__); 4078c2ecf20Sopenharmony_ci rc = mpt_HardResetHandler(ioc, CAN_SLEEP); 4088c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "%s: HardReset: %s\n", ioc->name, 4098c2ecf20Sopenharmony_ci __func__, (rc == 0) ? "success" : "failed"); 4108c2ecf20Sopenharmony_ci ioc_raw_state = mpt_GetIocState(ioc, 0); 4118c2ecf20Sopenharmony_ci if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) 4128c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "IOC is in FAULT state after " 4138c2ecf20Sopenharmony_ci "reset (%04xh)\n", ioc->name, ioc_raw_state & 4148c2ecf20Sopenharmony_ci MPI_DOORBELL_DATA_MASK); 4158c2ecf20Sopenharmony_ci } else if (ioc->bus_type == SAS && ioc->sas_discovery_quiesce_io) { 4168c2ecf20Sopenharmony_ci if ((mpt_is_discovery_complete(ioc))) { 4178c2ecf20Sopenharmony_ci devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "clearing " 4188c2ecf20Sopenharmony_ci "discovery_quiesce_io flag\n", ioc->name)); 4198c2ecf20Sopenharmony_ci ioc->sas_discovery_quiesce_io = 0; 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci out: 4248c2ecf20Sopenharmony_ci /* 4258c2ecf20Sopenharmony_ci * Take turns polling alternate controller 4268c2ecf20Sopenharmony_ci */ 4278c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 4288c2ecf20Sopenharmony_ci ioc = ioc->alt_ioc; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci /* rearm the timer */ 4318c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 4328c2ecf20Sopenharmony_ci if (ioc->reset_work_q) 4338c2ecf20Sopenharmony_ci queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work, 4348c2ecf20Sopenharmony_ci msecs_to_jiffies(MPT_POLLING_INTERVAL)); 4358c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* 4408c2ecf20Sopenharmony_ci * Process turbo (context) reply... 4418c2ecf20Sopenharmony_ci */ 4428c2ecf20Sopenharmony_cistatic void 4438c2ecf20Sopenharmony_cimpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf = NULL; 4468c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mr = NULL; 4478c2ecf20Sopenharmony_ci u16 req_idx = 0; 4488c2ecf20Sopenharmony_ci u8 cb_idx; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n", 4518c2ecf20Sopenharmony_ci ioc->name, pa)); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) { 4548c2ecf20Sopenharmony_ci case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT: 4558c2ecf20Sopenharmony_ci req_idx = pa & 0x0000FFFF; 4568c2ecf20Sopenharmony_ci cb_idx = (pa & 0x00FF0000) >> 16; 4578c2ecf20Sopenharmony_ci mf = MPT_INDEX_2_MFPTR(ioc, req_idx); 4588c2ecf20Sopenharmony_ci break; 4598c2ecf20Sopenharmony_ci case MPI_CONTEXT_REPLY_TYPE_LAN: 4608c2ecf20Sopenharmony_ci cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER); 4618c2ecf20Sopenharmony_ci /* 4628c2ecf20Sopenharmony_ci * Blind set of mf to NULL here was fatal 4638c2ecf20Sopenharmony_ci * after lan_reply says "freeme" 4648c2ecf20Sopenharmony_ci * Fix sort of combined with an optimization here; 4658c2ecf20Sopenharmony_ci * added explicit check for case where lan_reply 4668c2ecf20Sopenharmony_ci * was just returning 1 and doing nothing else. 4678c2ecf20Sopenharmony_ci * For this case skip the callback, but set up 4688c2ecf20Sopenharmony_ci * proper mf value first here:-) 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_ci if ((pa & 0x58000000) == 0x58000000) { 4718c2ecf20Sopenharmony_ci req_idx = pa & 0x0000FFFF; 4728c2ecf20Sopenharmony_ci mf = MPT_INDEX_2_MFPTR(ioc, req_idx); 4738c2ecf20Sopenharmony_ci mpt_free_msg_frame(ioc, mf); 4748c2ecf20Sopenharmony_ci mb(); 4758c2ecf20Sopenharmony_ci return; 4768c2ecf20Sopenharmony_ci break; 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); 4798c2ecf20Sopenharmony_ci break; 4808c2ecf20Sopenharmony_ci case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET: 4818c2ecf20Sopenharmony_ci cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER); 4828c2ecf20Sopenharmony_ci mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); 4838c2ecf20Sopenharmony_ci break; 4848c2ecf20Sopenharmony_ci default: 4858c2ecf20Sopenharmony_ci cb_idx = 0; 4868c2ecf20Sopenharmony_ci BUG(); 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci /* Check for (valid) IO callback! */ 4908c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || 4918c2ecf20Sopenharmony_ci MptCallbacks[cb_idx] == NULL) { 4928c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", 4938c2ecf20Sopenharmony_ci __func__, ioc->name, cb_idx); 4948c2ecf20Sopenharmony_ci goto out; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (MptCallbacks[cb_idx](ioc, mf, mr)) 4988c2ecf20Sopenharmony_ci mpt_free_msg_frame(ioc, mf); 4998c2ecf20Sopenharmony_ci out: 5008c2ecf20Sopenharmony_ci mb(); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic void 5048c2ecf20Sopenharmony_cimpt_reply(MPT_ADAPTER *ioc, u32 pa) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf; 5078c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mr; 5088c2ecf20Sopenharmony_ci u16 req_idx; 5098c2ecf20Sopenharmony_ci u8 cb_idx; 5108c2ecf20Sopenharmony_ci int freeme; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci u32 reply_dma_low; 5138c2ecf20Sopenharmony_ci u16 ioc_stat; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* non-TURBO reply! Hmmm, something may be up... 5168c2ecf20Sopenharmony_ci * Newest turbo reply mechanism; get address 5178c2ecf20Sopenharmony_ci * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* Map DMA address of reply header to cpu address. 5218c2ecf20Sopenharmony_ci * pa is 32 bits - but the dma address may be 32 or 64 bits 5228c2ecf20Sopenharmony_ci * get offset based only only the low addresses 5238c2ecf20Sopenharmony_ci */ 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci reply_dma_low = (pa <<= 1); 5268c2ecf20Sopenharmony_ci mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + 5278c2ecf20Sopenharmony_ci (reply_dma_low - ioc->reply_frames_low_dma)); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); 5308c2ecf20Sopenharmony_ci cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; 5318c2ecf20Sopenharmony_ci mf = MPT_INDEX_2_MFPTR(ioc, req_idx); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", 5348c2ecf20Sopenharmony_ci ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); 5358c2ecf20Sopenharmony_ci DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* Check/log IOC log info 5388c2ecf20Sopenharmony_ci */ 5398c2ecf20Sopenharmony_ci ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); 5408c2ecf20Sopenharmony_ci if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { 5418c2ecf20Sopenharmony_ci u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); 5428c2ecf20Sopenharmony_ci if (ioc->bus_type == FC) 5438c2ecf20Sopenharmony_ci mpt_fc_log_info(ioc, log_info); 5448c2ecf20Sopenharmony_ci else if (ioc->bus_type == SPI) 5458c2ecf20Sopenharmony_ci mpt_spi_log_info(ioc, log_info); 5468c2ecf20Sopenharmony_ci else if (ioc->bus_type == SAS) 5478c2ecf20Sopenharmony_ci mpt_sas_log_info(ioc, log_info, cb_idx); 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (ioc_stat & MPI_IOCSTATUS_MASK) 5518c2ecf20Sopenharmony_ci mpt_iocstatus_info(ioc, (u32)ioc_stat, mf); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci /* Check for (valid) IO callback! */ 5548c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || 5558c2ecf20Sopenharmony_ci MptCallbacks[cb_idx] == NULL) { 5568c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", 5578c2ecf20Sopenharmony_ci __func__, ioc->name, cb_idx); 5588c2ecf20Sopenharmony_ci freeme = 0; 5598c2ecf20Sopenharmony_ci goto out; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci freeme = MptCallbacks[cb_idx](ioc, mf, mr); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci out: 5658c2ecf20Sopenharmony_ci /* Flush (non-TURBO) reply with a WRITE! */ 5668c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci if (freeme) 5698c2ecf20Sopenharmony_ci mpt_free_msg_frame(ioc, mf); 5708c2ecf20Sopenharmony_ci mb(); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 5748c2ecf20Sopenharmony_ci/** 5758c2ecf20Sopenharmony_ci * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. 5768c2ecf20Sopenharmony_ci * @irq: irq number (not used) 5778c2ecf20Sopenharmony_ci * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure 5788c2ecf20Sopenharmony_ci * 5798c2ecf20Sopenharmony_ci * This routine is registered via the request_irq() kernel API call, 5808c2ecf20Sopenharmony_ci * and handles all interrupts generated from a specific MPT adapter 5818c2ecf20Sopenharmony_ci * (also referred to as a IO Controller or IOC). 5828c2ecf20Sopenharmony_ci * This routine must clear the interrupt from the adapter and does 5838c2ecf20Sopenharmony_ci * so by reading the reply FIFO. Multiple replies may be processed 5848c2ecf20Sopenharmony_ci * per single call to this routine. 5858c2ecf20Sopenharmony_ci * 5868c2ecf20Sopenharmony_ci * This routine handles register-level access of the adapter but 5878c2ecf20Sopenharmony_ci * dispatches (calls) a protocol-specific callback routine to handle 5888c2ecf20Sopenharmony_ci * the protocol-specific details of the MPT request completion. 5898c2ecf20Sopenharmony_ci */ 5908c2ecf20Sopenharmony_cistatic irqreturn_t 5918c2ecf20Sopenharmony_cimpt_interrupt(int irq, void *bus_id) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = bus_id; 5948c2ecf20Sopenharmony_ci u32 pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (pa == 0xFFFFFFFF) 5978c2ecf20Sopenharmony_ci return IRQ_NONE; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* 6008c2ecf20Sopenharmony_ci * Drain the reply FIFO! 6018c2ecf20Sopenharmony_ci */ 6028c2ecf20Sopenharmony_ci do { 6038c2ecf20Sopenharmony_ci if (pa & MPI_ADDRESS_REPLY_A_BIT) 6048c2ecf20Sopenharmony_ci mpt_reply(ioc, pa); 6058c2ecf20Sopenharmony_ci else 6068c2ecf20Sopenharmony_ci mpt_turbo_reply(ioc, pa); 6078c2ecf20Sopenharmony_ci pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); 6088c2ecf20Sopenharmony_ci } while (pa != 0xFFFFFFFF); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci return IRQ_HANDLED; 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 6148c2ecf20Sopenharmony_ci/** 6158c2ecf20Sopenharmony_ci * mptbase_reply - MPT base driver's callback routine 6168c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 6178c2ecf20Sopenharmony_ci * @req: Pointer to original MPT request frame 6188c2ecf20Sopenharmony_ci * @reply: Pointer to MPT reply frame (NULL if TurboReply) 6198c2ecf20Sopenharmony_ci * 6208c2ecf20Sopenharmony_ci * MPT base driver's callback routine; all base driver 6218c2ecf20Sopenharmony_ci * "internal" request/reply processing is routed here. 6228c2ecf20Sopenharmony_ci * Currently used for EventNotification and EventAck handling. 6238c2ecf20Sopenharmony_ci * 6248c2ecf20Sopenharmony_ci * Returns 1 indicating original alloc'd request frame ptr 6258c2ecf20Sopenharmony_ci * should be freed, or 0 if it shouldn't. 6268c2ecf20Sopenharmony_ci */ 6278c2ecf20Sopenharmony_cistatic int 6288c2ecf20Sopenharmony_cimptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci EventNotificationReply_t *pEventReply; 6318c2ecf20Sopenharmony_ci u8 event; 6328c2ecf20Sopenharmony_ci int evHandlers; 6338c2ecf20Sopenharmony_ci int freereq = 1; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci switch (reply->u.hdr.Function) { 6368c2ecf20Sopenharmony_ci case MPI_FUNCTION_EVENT_NOTIFICATION: 6378c2ecf20Sopenharmony_ci pEventReply = (EventNotificationReply_t *)reply; 6388c2ecf20Sopenharmony_ci evHandlers = 0; 6398c2ecf20Sopenharmony_ci ProcessEventNotification(ioc, pEventReply, &evHandlers); 6408c2ecf20Sopenharmony_ci event = le32_to_cpu(pEventReply->Event) & 0xFF; 6418c2ecf20Sopenharmony_ci if (pEventReply->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) 6428c2ecf20Sopenharmony_ci freereq = 0; 6438c2ecf20Sopenharmony_ci if (event != MPI_EVENT_EVENT_CHANGE) 6448c2ecf20Sopenharmony_ci break; 6458c2ecf20Sopenharmony_ci fallthrough; 6468c2ecf20Sopenharmony_ci case MPI_FUNCTION_CONFIG: 6478c2ecf20Sopenharmony_ci case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: 6488c2ecf20Sopenharmony_ci ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; 6498c2ecf20Sopenharmony_ci ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_RF_VALID; 6508c2ecf20Sopenharmony_ci memcpy(ioc->mptbase_cmds.reply, reply, 6518c2ecf20Sopenharmony_ci min(MPT_DEFAULT_FRAME_SIZE, 6528c2ecf20Sopenharmony_ci 4 * reply->u.reply.MsgLength)); 6538c2ecf20Sopenharmony_ci if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { 6548c2ecf20Sopenharmony_ci ioc->mptbase_cmds.status &= ~MPT_MGMT_STATUS_PENDING; 6558c2ecf20Sopenharmony_ci complete(&ioc->mptbase_cmds.done); 6568c2ecf20Sopenharmony_ci } else 6578c2ecf20Sopenharmony_ci freereq = 0; 6588c2ecf20Sopenharmony_ci if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_FREE_MF) 6598c2ecf20Sopenharmony_ci freereq = 1; 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci case MPI_FUNCTION_EVENT_ACK: 6628c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 6638c2ecf20Sopenharmony_ci "EventAck reply received\n", ioc->name)); 6648c2ecf20Sopenharmony_ci break; 6658c2ecf20Sopenharmony_ci default: 6668c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 6678c2ecf20Sopenharmony_ci "Unexpected msg function (=%02Xh) reply received!\n", 6688c2ecf20Sopenharmony_ci ioc->name, reply->u.hdr.Function); 6698c2ecf20Sopenharmony_ci break; 6708c2ecf20Sopenharmony_ci } 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci /* 6738c2ecf20Sopenharmony_ci * Conditionally tell caller to free the original 6748c2ecf20Sopenharmony_ci * EventNotification/EventAck/unexpected request frame! 6758c2ecf20Sopenharmony_ci */ 6768c2ecf20Sopenharmony_ci return freereq; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 6808c2ecf20Sopenharmony_ci/** 6818c2ecf20Sopenharmony_ci * mpt_register - Register protocol-specific main callback handler. 6828c2ecf20Sopenharmony_ci * @cbfunc: callback function pointer 6838c2ecf20Sopenharmony_ci * @dclass: Protocol driver's class (%MPT_DRIVER_CLASS enum value) 6848c2ecf20Sopenharmony_ci * @func_name: call function's name 6858c2ecf20Sopenharmony_ci * 6868c2ecf20Sopenharmony_ci * This routine is called by a protocol-specific driver (SCSI host, 6878c2ecf20Sopenharmony_ci * LAN, SCSI target) to register its reply callback routine. Each 6888c2ecf20Sopenharmony_ci * protocol-specific driver must do this before it will be able to 6898c2ecf20Sopenharmony_ci * use any IOC resources, such as obtaining request frames. 6908c2ecf20Sopenharmony_ci * 6918c2ecf20Sopenharmony_ci * NOTES: The SCSI protocol driver currently calls this routine thrice 6928c2ecf20Sopenharmony_ci * in order to register separate callbacks; one for "normal" SCSI IO; 6938c2ecf20Sopenharmony_ci * one for MptScsiTaskMgmt requests; one for Scan/DV requests. 6948c2ecf20Sopenharmony_ci * 6958c2ecf20Sopenharmony_ci * Returns u8 valued "handle" in the range (and S.O.D. order) 6968c2ecf20Sopenharmony_ci * {N,...,7,6,5,...,1} if successful. 6978c2ecf20Sopenharmony_ci * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be 6988c2ecf20Sopenharmony_ci * considered an error by the caller. 6998c2ecf20Sopenharmony_ci */ 7008c2ecf20Sopenharmony_ciu8 7018c2ecf20Sopenharmony_cimpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass, char *func_name) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci u8 cb_idx; 7048c2ecf20Sopenharmony_ci last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci /* 7078c2ecf20Sopenharmony_ci * Search for empty callback slot in this order: {N,...,7,6,5,...,1} 7088c2ecf20Sopenharmony_ci * (slot/handle 0 is reserved!) 7098c2ecf20Sopenharmony_ci */ 7108c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 7118c2ecf20Sopenharmony_ci if (MptCallbacks[cb_idx] == NULL) { 7128c2ecf20Sopenharmony_ci MptCallbacks[cb_idx] = cbfunc; 7138c2ecf20Sopenharmony_ci MptDriverClass[cb_idx] = dclass; 7148c2ecf20Sopenharmony_ci MptEvHandlers[cb_idx] = NULL; 7158c2ecf20Sopenharmony_ci last_drv_idx = cb_idx; 7168c2ecf20Sopenharmony_ci strlcpy(MptCallbacksName[cb_idx], func_name, 7178c2ecf20Sopenharmony_ci MPT_MAX_CALLBACKNAME_LEN+1); 7188c2ecf20Sopenharmony_ci break; 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci } 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci return last_drv_idx; 7238c2ecf20Sopenharmony_ci} 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 7268c2ecf20Sopenharmony_ci/** 7278c2ecf20Sopenharmony_ci * mpt_deregister - Deregister a protocol drivers resources. 7288c2ecf20Sopenharmony_ci * @cb_idx: previously registered callback handle 7298c2ecf20Sopenharmony_ci * 7308c2ecf20Sopenharmony_ci * Each protocol-specific driver should call this routine when its 7318c2ecf20Sopenharmony_ci * module is unloaded. 7328c2ecf20Sopenharmony_ci */ 7338c2ecf20Sopenharmony_civoid 7348c2ecf20Sopenharmony_cimpt_deregister(u8 cb_idx) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { 7378c2ecf20Sopenharmony_ci MptCallbacks[cb_idx] = NULL; 7388c2ecf20Sopenharmony_ci MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; 7398c2ecf20Sopenharmony_ci MptEvHandlers[cb_idx] = NULL; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci last_drv_idx++; 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci} 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 7468c2ecf20Sopenharmony_ci/** 7478c2ecf20Sopenharmony_ci * mpt_event_register - Register protocol-specific event callback handler. 7488c2ecf20Sopenharmony_ci * @cb_idx: previously registered (via mpt_register) callback handle 7498c2ecf20Sopenharmony_ci * @ev_cbfunc: callback function 7508c2ecf20Sopenharmony_ci * 7518c2ecf20Sopenharmony_ci * This routine can be called by one or more protocol-specific drivers 7528c2ecf20Sopenharmony_ci * if/when they choose to be notified of MPT events. 7538c2ecf20Sopenharmony_ci * 7548c2ecf20Sopenharmony_ci * Returns 0 for success. 7558c2ecf20Sopenharmony_ci */ 7568c2ecf20Sopenharmony_ciint 7578c2ecf20Sopenharmony_cimpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc) 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) 7608c2ecf20Sopenharmony_ci return -1; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci MptEvHandlers[cb_idx] = ev_cbfunc; 7638c2ecf20Sopenharmony_ci return 0; 7648c2ecf20Sopenharmony_ci} 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 7678c2ecf20Sopenharmony_ci/** 7688c2ecf20Sopenharmony_ci * mpt_event_deregister - Deregister protocol-specific event callback handler 7698c2ecf20Sopenharmony_ci * @cb_idx: previously registered callback handle 7708c2ecf20Sopenharmony_ci * 7718c2ecf20Sopenharmony_ci * Each protocol-specific driver should call this routine 7728c2ecf20Sopenharmony_ci * when it does not (or can no longer) handle events, 7738c2ecf20Sopenharmony_ci * or when its module is unloaded. 7748c2ecf20Sopenharmony_ci */ 7758c2ecf20Sopenharmony_civoid 7768c2ecf20Sopenharmony_cimpt_event_deregister(u8 cb_idx) 7778c2ecf20Sopenharmony_ci{ 7788c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) 7798c2ecf20Sopenharmony_ci return; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci MptEvHandlers[cb_idx] = NULL; 7828c2ecf20Sopenharmony_ci} 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 7858c2ecf20Sopenharmony_ci/** 7868c2ecf20Sopenharmony_ci * mpt_reset_register - Register protocol-specific IOC reset handler. 7878c2ecf20Sopenharmony_ci * @cb_idx: previously registered (via mpt_register) callback handle 7888c2ecf20Sopenharmony_ci * @reset_func: reset function 7898c2ecf20Sopenharmony_ci * 7908c2ecf20Sopenharmony_ci * This routine can be called by one or more protocol-specific drivers 7918c2ecf20Sopenharmony_ci * if/when they choose to be notified of IOC resets. 7928c2ecf20Sopenharmony_ci * 7938c2ecf20Sopenharmony_ci * Returns 0 for success. 7948c2ecf20Sopenharmony_ci */ 7958c2ecf20Sopenharmony_ciint 7968c2ecf20Sopenharmony_cimpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func) 7978c2ecf20Sopenharmony_ci{ 7988c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) 7998c2ecf20Sopenharmony_ci return -1; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci MptResetHandlers[cb_idx] = reset_func; 8028c2ecf20Sopenharmony_ci return 0; 8038c2ecf20Sopenharmony_ci} 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 8068c2ecf20Sopenharmony_ci/** 8078c2ecf20Sopenharmony_ci * mpt_reset_deregister - Deregister protocol-specific IOC reset handler. 8088c2ecf20Sopenharmony_ci * @cb_idx: previously registered callback handle 8098c2ecf20Sopenharmony_ci * 8108c2ecf20Sopenharmony_ci * Each protocol-specific driver should call this routine 8118c2ecf20Sopenharmony_ci * when it does not (or can no longer) handle IOC reset handling, 8128c2ecf20Sopenharmony_ci * or when its module is unloaded. 8138c2ecf20Sopenharmony_ci */ 8148c2ecf20Sopenharmony_civoid 8158c2ecf20Sopenharmony_cimpt_reset_deregister(u8 cb_idx) 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) 8188c2ecf20Sopenharmony_ci return; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci MptResetHandlers[cb_idx] = NULL; 8218c2ecf20Sopenharmony_ci} 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 8248c2ecf20Sopenharmony_ci/** 8258c2ecf20Sopenharmony_ci * mpt_device_driver_register - Register device driver hooks 8268c2ecf20Sopenharmony_ci * @dd_cbfunc: driver callbacks struct 8278c2ecf20Sopenharmony_ci * @cb_idx: MPT protocol driver index 8288c2ecf20Sopenharmony_ci */ 8298c2ecf20Sopenharmony_ciint 8308c2ecf20Sopenharmony_cimpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc; 8338c2ecf20Sopenharmony_ci const struct pci_device_id *id; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) 8368c2ecf20Sopenharmony_ci return -EINVAL; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci /* call per pci device probe entry point */ 8418c2ecf20Sopenharmony_ci list_for_each_entry(ioc, &ioc_list, list) { 8428c2ecf20Sopenharmony_ci id = ioc->pcidev->driver ? 8438c2ecf20Sopenharmony_ci ioc->pcidev->driver->id_table : NULL; 8448c2ecf20Sopenharmony_ci if (dd_cbfunc->probe) 8458c2ecf20Sopenharmony_ci dd_cbfunc->probe(ioc->pcidev, id); 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci return 0; 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 8528c2ecf20Sopenharmony_ci/** 8538c2ecf20Sopenharmony_ci * mpt_device_driver_deregister - DeRegister device driver hooks 8548c2ecf20Sopenharmony_ci * @cb_idx: MPT protocol driver index 8558c2ecf20Sopenharmony_ci */ 8568c2ecf20Sopenharmony_civoid 8578c2ecf20Sopenharmony_cimpt_device_driver_deregister(u8 cb_idx) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct mpt_pci_driver *dd_cbfunc; 8608c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) 8638c2ecf20Sopenharmony_ci return; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci dd_cbfunc = MptDeviceDriverHandlers[cb_idx]; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci list_for_each_entry(ioc, &ioc_list, list) { 8688c2ecf20Sopenharmony_ci if (dd_cbfunc->remove) 8698c2ecf20Sopenharmony_ci dd_cbfunc->remove(ioc->pcidev); 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci MptDeviceDriverHandlers[cb_idx] = NULL; 8738c2ecf20Sopenharmony_ci} 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 8778c2ecf20Sopenharmony_ci/** 8788c2ecf20Sopenharmony_ci * mpt_get_msg_frame - Obtain an MPT request frame from the pool 8798c2ecf20Sopenharmony_ci * @cb_idx: Handle of registered MPT protocol driver 8808c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 8818c2ecf20Sopenharmony_ci * 8828c2ecf20Sopenharmony_ci * Obtain an MPT request frame from the pool (of 1024) that are 8838c2ecf20Sopenharmony_ci * allocated per MPT adapter. 8848c2ecf20Sopenharmony_ci * 8858c2ecf20Sopenharmony_ci * Returns pointer to a MPT request frame or %NULL if none are available 8868c2ecf20Sopenharmony_ci * or IOC is not active. 8878c2ecf20Sopenharmony_ci */ 8888c2ecf20Sopenharmony_ciMPT_FRAME_HDR* 8898c2ecf20Sopenharmony_cimpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf; 8928c2ecf20Sopenharmony_ci unsigned long flags; 8938c2ecf20Sopenharmony_ci u16 req_idx; /* Request index */ 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci /* validate handle and ioc identifier */ 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci#ifdef MFCNT 8988c2ecf20Sopenharmony_ci if (!ioc->active) 8998c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame " 9008c2ecf20Sopenharmony_ci "returning NULL!\n", ioc->name); 9018c2ecf20Sopenharmony_ci#endif 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci /* If interrupts are not attached, do not return a request frame */ 9048c2ecf20Sopenharmony_ci if (!ioc->active) 9058c2ecf20Sopenharmony_ci return NULL; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->FreeQlock, flags); 9088c2ecf20Sopenharmony_ci if (!list_empty(&ioc->FreeQ)) { 9098c2ecf20Sopenharmony_ci int req_offset; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, 9128c2ecf20Sopenharmony_ci u.frame.linkage.list); 9138c2ecf20Sopenharmony_ci list_del(&mf->u.frame.linkage.list); 9148c2ecf20Sopenharmony_ci mf->u.frame.linkage.arg1 = 0; 9158c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */ 9168c2ecf20Sopenharmony_ci req_offset = (u8 *)mf - (u8 *)ioc->req_frames; 9178c2ecf20Sopenharmony_ci /* u16! */ 9188c2ecf20Sopenharmony_ci req_idx = req_offset / ioc->req_sz; 9198c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); 9208c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; 9218c2ecf20Sopenharmony_ci /* Default, will be changed if necessary in SG generation */ 9228c2ecf20Sopenharmony_ci ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; 9238c2ecf20Sopenharmony_ci#ifdef MFCNT 9248c2ecf20Sopenharmony_ci ioc->mfcnt++; 9258c2ecf20Sopenharmony_ci#endif 9268c2ecf20Sopenharmony_ci } 9278c2ecf20Sopenharmony_ci else 9288c2ecf20Sopenharmony_ci mf = NULL; 9298c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->FreeQlock, flags); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci#ifdef MFCNT 9328c2ecf20Sopenharmony_ci if (mf == NULL) 9338c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! " 9348c2ecf20Sopenharmony_ci "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt, 9358c2ecf20Sopenharmony_ci ioc->req_depth); 9368c2ecf20Sopenharmony_ci mfcounter++; 9378c2ecf20Sopenharmony_ci if (mfcounter == PRINT_MF_COUNT) 9388c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name, 9398c2ecf20Sopenharmony_ci ioc->mfcnt, ioc->req_depth); 9408c2ecf20Sopenharmony_ci#endif 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n", 9438c2ecf20Sopenharmony_ci ioc->name, cb_idx, ioc->id, mf)); 9448c2ecf20Sopenharmony_ci return mf; 9458c2ecf20Sopenharmony_ci} 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 9488c2ecf20Sopenharmony_ci/** 9498c2ecf20Sopenharmony_ci * mpt_put_msg_frame - Send a protocol-specific MPT request frame to an IOC 9508c2ecf20Sopenharmony_ci * @cb_idx: Handle of registered MPT protocol driver 9518c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 9528c2ecf20Sopenharmony_ci * @mf: Pointer to MPT request frame 9538c2ecf20Sopenharmony_ci * 9548c2ecf20Sopenharmony_ci * This routine posts an MPT request frame to the request post FIFO of a 9558c2ecf20Sopenharmony_ci * specific MPT adapter. 9568c2ecf20Sopenharmony_ci */ 9578c2ecf20Sopenharmony_civoid 9588c2ecf20Sopenharmony_cimpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) 9598c2ecf20Sopenharmony_ci{ 9608c2ecf20Sopenharmony_ci u32 mf_dma_addr; 9618c2ecf20Sopenharmony_ci int req_offset; 9628c2ecf20Sopenharmony_ci u16 req_idx; /* Request index */ 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci /* ensure values are reset properly! */ 9658c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */ 9668c2ecf20Sopenharmony_ci req_offset = (u8 *)mf - (u8 *)ioc->req_frames; 9678c2ecf20Sopenharmony_ci /* u16! */ 9688c2ecf20Sopenharmony_ci req_idx = req_offset / ioc->req_sz; 9698c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); 9708c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; 9758c2ecf20Sopenharmony_ci dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d " 9768c2ecf20Sopenharmony_ci "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, 9778c2ecf20Sopenharmony_ci ioc->RequestNB[req_idx])); 9788c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr); 9798c2ecf20Sopenharmony_ci} 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci/** 9828c2ecf20Sopenharmony_ci * mpt_put_msg_frame_hi_pri - Send a hi-pri protocol-specific MPT request frame 9838c2ecf20Sopenharmony_ci * @cb_idx: Handle of registered MPT protocol driver 9848c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 9858c2ecf20Sopenharmony_ci * @mf: Pointer to MPT request frame 9868c2ecf20Sopenharmony_ci * 9878c2ecf20Sopenharmony_ci * Send a protocol-specific MPT request frame to an IOC using 9888c2ecf20Sopenharmony_ci * hi-priority request queue. 9898c2ecf20Sopenharmony_ci * 9908c2ecf20Sopenharmony_ci * This routine posts an MPT request frame to the request post FIFO of a 9918c2ecf20Sopenharmony_ci * specific MPT adapter. 9928c2ecf20Sopenharmony_ci **/ 9938c2ecf20Sopenharmony_civoid 9948c2ecf20Sopenharmony_cimpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) 9958c2ecf20Sopenharmony_ci{ 9968c2ecf20Sopenharmony_ci u32 mf_dma_addr; 9978c2ecf20Sopenharmony_ci int req_offset; 9988c2ecf20Sopenharmony_ci u16 req_idx; /* Request index */ 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci /* ensure values are reset properly! */ 10018c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; 10028c2ecf20Sopenharmony_ci req_offset = (u8 *)mf - (u8 *)ioc->req_frames; 10038c2ecf20Sopenharmony_ci req_idx = req_offset / ioc->req_sz; 10048c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); 10058c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf); 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci mf_dma_addr = (ioc->req_frames_low_dma + req_offset); 10108c2ecf20Sopenharmony_ci dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n", 10118c2ecf20Sopenharmony_ci ioc->name, mf_dma_addr, req_idx)); 10128c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr); 10138c2ecf20Sopenharmony_ci} 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 10168c2ecf20Sopenharmony_ci/** 10178c2ecf20Sopenharmony_ci * mpt_free_msg_frame - Place MPT request frame back on FreeQ. 10188c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 10198c2ecf20Sopenharmony_ci * @mf: Pointer to MPT request frame 10208c2ecf20Sopenharmony_ci * 10218c2ecf20Sopenharmony_ci * This routine places a MPT request frame back on the MPT adapter's 10228c2ecf20Sopenharmony_ci * FreeQ. 10238c2ecf20Sopenharmony_ci */ 10248c2ecf20Sopenharmony_civoid 10258c2ecf20Sopenharmony_cimpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci unsigned long flags; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci /* Put Request back on FreeQ! */ 10308c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->FreeQlock, flags); 10318c2ecf20Sopenharmony_ci if (cpu_to_le32(mf->u.frame.linkage.arg1) == 0xdeadbeaf) 10328c2ecf20Sopenharmony_ci goto out; 10338c2ecf20Sopenharmony_ci /* signature to know if this mf is freed */ 10348c2ecf20Sopenharmony_ci mf->u.frame.linkage.arg1 = cpu_to_le32(0xdeadbeaf); 10358c2ecf20Sopenharmony_ci list_add(&mf->u.frame.linkage.list, &ioc->FreeQ); 10368c2ecf20Sopenharmony_ci#ifdef MFCNT 10378c2ecf20Sopenharmony_ci ioc->mfcnt--; 10388c2ecf20Sopenharmony_ci#endif 10398c2ecf20Sopenharmony_ci out: 10408c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->FreeQlock, flags); 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 10448c2ecf20Sopenharmony_ci/** 10458c2ecf20Sopenharmony_ci * mpt_add_sge - Place a simple 32 bit SGE at address pAddr. 10468c2ecf20Sopenharmony_ci * @pAddr: virtual address for SGE 10478c2ecf20Sopenharmony_ci * @flagslength: SGE flags and data transfer length 10488c2ecf20Sopenharmony_ci * @dma_addr: Physical address 10498c2ecf20Sopenharmony_ci * 10508c2ecf20Sopenharmony_ci * This routine places a MPT request frame back on the MPT adapter's 10518c2ecf20Sopenharmony_ci * FreeQ. 10528c2ecf20Sopenharmony_ci */ 10538c2ecf20Sopenharmony_cistatic void 10548c2ecf20Sopenharmony_cimpt_add_sge(void *pAddr, u32 flagslength, dma_addr_t dma_addr) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci SGESimple32_t *pSge = (SGESimple32_t *) pAddr; 10578c2ecf20Sopenharmony_ci pSge->FlagsLength = cpu_to_le32(flagslength); 10588c2ecf20Sopenharmony_ci pSge->Address = cpu_to_le32(dma_addr); 10598c2ecf20Sopenharmony_ci} 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci/** 10628c2ecf20Sopenharmony_ci * mpt_add_sge_64bit - Place a simple 64 bit SGE at address pAddr. 10638c2ecf20Sopenharmony_ci * @pAddr: virtual address for SGE 10648c2ecf20Sopenharmony_ci * @flagslength: SGE flags and data transfer length 10658c2ecf20Sopenharmony_ci * @dma_addr: Physical address 10668c2ecf20Sopenharmony_ci * 10678c2ecf20Sopenharmony_ci * This routine places a MPT request frame back on the MPT adapter's 10688c2ecf20Sopenharmony_ci * FreeQ. 10698c2ecf20Sopenharmony_ci **/ 10708c2ecf20Sopenharmony_cistatic void 10718c2ecf20Sopenharmony_cimpt_add_sge_64bit(void *pAddr, u32 flagslength, dma_addr_t dma_addr) 10728c2ecf20Sopenharmony_ci{ 10738c2ecf20Sopenharmony_ci SGESimple64_t *pSge = (SGESimple64_t *) pAddr; 10748c2ecf20Sopenharmony_ci pSge->Address.Low = cpu_to_le32 10758c2ecf20Sopenharmony_ci (lower_32_bits(dma_addr)); 10768c2ecf20Sopenharmony_ci pSge->Address.High = cpu_to_le32 10778c2ecf20Sopenharmony_ci (upper_32_bits(dma_addr)); 10788c2ecf20Sopenharmony_ci pSge->FlagsLength = cpu_to_le32 10798c2ecf20Sopenharmony_ci ((flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING)); 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci/** 10838c2ecf20Sopenharmony_ci * mpt_add_sge_64bit_1078 - Place a simple 64 bit SGE at address pAddr (1078 workaround). 10848c2ecf20Sopenharmony_ci * @pAddr: virtual address for SGE 10858c2ecf20Sopenharmony_ci * @flagslength: SGE flags and data transfer length 10868c2ecf20Sopenharmony_ci * @dma_addr: Physical address 10878c2ecf20Sopenharmony_ci * 10888c2ecf20Sopenharmony_ci * This routine places a MPT request frame back on the MPT adapter's 10898c2ecf20Sopenharmony_ci * FreeQ. 10908c2ecf20Sopenharmony_ci **/ 10918c2ecf20Sopenharmony_cistatic void 10928c2ecf20Sopenharmony_cimpt_add_sge_64bit_1078(void *pAddr, u32 flagslength, dma_addr_t dma_addr) 10938c2ecf20Sopenharmony_ci{ 10948c2ecf20Sopenharmony_ci SGESimple64_t *pSge = (SGESimple64_t *) pAddr; 10958c2ecf20Sopenharmony_ci u32 tmp; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci pSge->Address.Low = cpu_to_le32 10988c2ecf20Sopenharmony_ci (lower_32_bits(dma_addr)); 10998c2ecf20Sopenharmony_ci tmp = (u32)(upper_32_bits(dma_addr)); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci /* 11028c2ecf20Sopenharmony_ci * 1078 errata workaround for the 36GB limitation 11038c2ecf20Sopenharmony_ci */ 11048c2ecf20Sopenharmony_ci if ((((u64)dma_addr + MPI_SGE_LENGTH(flagslength)) >> 32) == 9) { 11058c2ecf20Sopenharmony_ci flagslength |= 11068c2ecf20Sopenharmony_ci MPI_SGE_SET_FLAGS(MPI_SGE_FLAGS_LOCAL_ADDRESS); 11078c2ecf20Sopenharmony_ci tmp |= (1<<31); 11088c2ecf20Sopenharmony_ci if (mpt_debug_level & MPT_DEBUG_36GB_MEM) 11098c2ecf20Sopenharmony_ci printk(KERN_DEBUG "1078 P0M2 addressing for " 11108c2ecf20Sopenharmony_ci "addr = 0x%llx len = %d\n", 11118c2ecf20Sopenharmony_ci (unsigned long long)dma_addr, 11128c2ecf20Sopenharmony_ci MPI_SGE_LENGTH(flagslength)); 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci pSge->Address.High = cpu_to_le32(tmp); 11168c2ecf20Sopenharmony_ci pSge->FlagsLength = cpu_to_le32( 11178c2ecf20Sopenharmony_ci (flagslength | MPT_SGE_FLAGS_64_BIT_ADDRESSING)); 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11218c2ecf20Sopenharmony_ci/** 11228c2ecf20Sopenharmony_ci * mpt_add_chain - Place a 32 bit chain SGE at address pAddr. 11238c2ecf20Sopenharmony_ci * @pAddr: virtual address for SGE 11248c2ecf20Sopenharmony_ci * @next: nextChainOffset value (u32's) 11258c2ecf20Sopenharmony_ci * @length: length of next SGL segment 11268c2ecf20Sopenharmony_ci * @dma_addr: Physical address 11278c2ecf20Sopenharmony_ci * 11288c2ecf20Sopenharmony_ci */ 11298c2ecf20Sopenharmony_cistatic void 11308c2ecf20Sopenharmony_cimpt_add_chain(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci SGEChain32_t *pChain = (SGEChain32_t *) pAddr; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci pChain->Length = cpu_to_le16(length); 11358c2ecf20Sopenharmony_ci pChain->Flags = MPI_SGE_FLAGS_CHAIN_ELEMENT; 11368c2ecf20Sopenharmony_ci pChain->NextChainOffset = next; 11378c2ecf20Sopenharmony_ci pChain->Address = cpu_to_le32(dma_addr); 11388c2ecf20Sopenharmony_ci} 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11418c2ecf20Sopenharmony_ci/** 11428c2ecf20Sopenharmony_ci * mpt_add_chain_64bit - Place a 64 bit chain SGE at address pAddr. 11438c2ecf20Sopenharmony_ci * @pAddr: virtual address for SGE 11448c2ecf20Sopenharmony_ci * @next: nextChainOffset value (u32's) 11458c2ecf20Sopenharmony_ci * @length: length of next SGL segment 11468c2ecf20Sopenharmony_ci * @dma_addr: Physical address 11478c2ecf20Sopenharmony_ci * 11488c2ecf20Sopenharmony_ci */ 11498c2ecf20Sopenharmony_cistatic void 11508c2ecf20Sopenharmony_cimpt_add_chain_64bit(void *pAddr, u8 next, u16 length, dma_addr_t dma_addr) 11518c2ecf20Sopenharmony_ci{ 11528c2ecf20Sopenharmony_ci SGEChain64_t *pChain = (SGEChain64_t *) pAddr; 11538c2ecf20Sopenharmony_ci u32 tmp = dma_addr & 0xFFFFFFFF; 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci pChain->Length = cpu_to_le16(length); 11568c2ecf20Sopenharmony_ci pChain->Flags = (MPI_SGE_FLAGS_CHAIN_ELEMENT | 11578c2ecf20Sopenharmony_ci MPI_SGE_FLAGS_64_BIT_ADDRESSING); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci pChain->NextChainOffset = next; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci pChain->Address.Low = cpu_to_le32(tmp); 11628c2ecf20Sopenharmony_ci tmp = (u32)(upper_32_bits(dma_addr)); 11638c2ecf20Sopenharmony_ci pChain->Address.High = cpu_to_le32(tmp); 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 11678c2ecf20Sopenharmony_ci/** 11688c2ecf20Sopenharmony_ci * mpt_send_handshake_request - Send MPT request via doorbell handshake method. 11698c2ecf20Sopenharmony_ci * @cb_idx: Handle of registered MPT protocol driver 11708c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 11718c2ecf20Sopenharmony_ci * @reqBytes: Size of the request in bytes 11728c2ecf20Sopenharmony_ci * @req: Pointer to MPT request frame 11738c2ecf20Sopenharmony_ci * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. 11748c2ecf20Sopenharmony_ci * 11758c2ecf20Sopenharmony_ci * This routine is used exclusively to send MptScsiTaskMgmt 11768c2ecf20Sopenharmony_ci * requests since they are required to be sent via doorbell handshake. 11778c2ecf20Sopenharmony_ci * 11788c2ecf20Sopenharmony_ci * NOTE: It is the callers responsibility to byte-swap fields in the 11798c2ecf20Sopenharmony_ci * request which are greater than 1 byte in size. 11808c2ecf20Sopenharmony_ci * 11818c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 11828c2ecf20Sopenharmony_ci */ 11838c2ecf20Sopenharmony_ciint 11848c2ecf20Sopenharmony_cimpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) 11858c2ecf20Sopenharmony_ci{ 11868c2ecf20Sopenharmony_ci int r = 0; 11878c2ecf20Sopenharmony_ci u8 *req_as_bytes; 11888c2ecf20Sopenharmony_ci int ii; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci /* State is known to be good upon entering 11918c2ecf20Sopenharmony_ci * this function so issue the bus reset 11928c2ecf20Sopenharmony_ci * request. 11938c2ecf20Sopenharmony_ci */ 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci /* 11968c2ecf20Sopenharmony_ci * Emulate what mpt_put_msg_frame() does /wrt to sanity 11978c2ecf20Sopenharmony_ci * setting cb_idx/req_idx. But ONLY if this request 11988c2ecf20Sopenharmony_ci * is in proper (pre-alloc'd) request buffer range... 11998c2ecf20Sopenharmony_ci */ 12008c2ecf20Sopenharmony_ci ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req); 12018c2ecf20Sopenharmony_ci if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) { 12028c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; 12038c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); 12048c2ecf20Sopenharmony_ci mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; 12058c2ecf20Sopenharmony_ci } 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci /* Make sure there are no doorbells */ 12088c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, 12118c2ecf20Sopenharmony_ci ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) | 12128c2ecf20Sopenharmony_ci ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))); 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci /* Wait for IOC doorbell int */ 12158c2ecf20Sopenharmony_ci if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) { 12168c2ecf20Sopenharmony_ci return ii; 12178c2ecf20Sopenharmony_ci } 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci /* Read doorbell and check for active bit */ 12208c2ecf20Sopenharmony_ci if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) 12218c2ecf20Sopenharmony_ci return -5; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n", 12248c2ecf20Sopenharmony_ci ioc->name, ii)); 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { 12298c2ecf20Sopenharmony_ci return -2; 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci /* Send request via doorbell handshake */ 12338c2ecf20Sopenharmony_ci req_as_bytes = (u8 *) req; 12348c2ecf20Sopenharmony_ci for (ii = 0; ii < reqBytes/4; ii++) { 12358c2ecf20Sopenharmony_ci u32 word; 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci word = ((req_as_bytes[(ii*4) + 0] << 0) | 12388c2ecf20Sopenharmony_ci (req_as_bytes[(ii*4) + 1] << 8) | 12398c2ecf20Sopenharmony_ci (req_as_bytes[(ii*4) + 2] << 16) | 12408c2ecf20Sopenharmony_ci (req_as_bytes[(ii*4) + 3] << 24)); 12418c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, word); 12428c2ecf20Sopenharmony_ci if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { 12438c2ecf20Sopenharmony_ci r = -3; 12448c2ecf20Sopenharmony_ci break; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci } 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0) 12498c2ecf20Sopenharmony_ci r = 0; 12508c2ecf20Sopenharmony_ci else 12518c2ecf20Sopenharmony_ci r = -4; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci /* Make sure there are no doorbells */ 12548c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci return r; 12578c2ecf20Sopenharmony_ci} 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 12608c2ecf20Sopenharmony_ci/** 12618c2ecf20Sopenharmony_ci * mpt_host_page_access_control - control the IOC's Host Page Buffer access 12628c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 12638c2ecf20Sopenharmony_ci * @access_control_value: define bits below 12648c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 12658c2ecf20Sopenharmony_ci * 12668c2ecf20Sopenharmony_ci * Provides mechanism for the host driver to control the IOC's 12678c2ecf20Sopenharmony_ci * Host Page Buffer access. 12688c2ecf20Sopenharmony_ci * 12698c2ecf20Sopenharmony_ci * Access Control Value - bits[15:12] 12708c2ecf20Sopenharmony_ci * 0h Reserved 12718c2ecf20Sopenharmony_ci * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } 12728c2ecf20Sopenharmony_ci * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } 12738c2ecf20Sopenharmony_ci * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } 12748c2ecf20Sopenharmony_ci * 12758c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 12768c2ecf20Sopenharmony_ci */ 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_cistatic int 12798c2ecf20Sopenharmony_cimpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) 12808c2ecf20Sopenharmony_ci{ 12818c2ecf20Sopenharmony_ci int r = 0; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci /* return if in use */ 12848c2ecf20Sopenharmony_ci if (CHIPREG_READ32(&ioc->chip->Doorbell) 12858c2ecf20Sopenharmony_ci & MPI_DOORBELL_ACTIVE) 12868c2ecf20Sopenharmony_ci return -1; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, 12918c2ecf20Sopenharmony_ci ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL 12928c2ecf20Sopenharmony_ci <<MPI_DOORBELL_FUNCTION_SHIFT) | 12938c2ecf20Sopenharmony_ci (access_control_value<<12))); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci /* Wait for IOC to clear Doorbell Status bit */ 12968c2ecf20Sopenharmony_ci if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { 12978c2ecf20Sopenharmony_ci return -2; 12988c2ecf20Sopenharmony_ci }else 12998c2ecf20Sopenharmony_ci return 0; 13008c2ecf20Sopenharmony_ci} 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 13038c2ecf20Sopenharmony_ci/** 13048c2ecf20Sopenharmony_ci * mpt_host_page_alloc - allocate system memory for the fw 13058c2ecf20Sopenharmony_ci * @ioc: Pointer to pointer to IOC adapter 13068c2ecf20Sopenharmony_ci * @ioc_init: Pointer to ioc init config page 13078c2ecf20Sopenharmony_ci * 13088c2ecf20Sopenharmony_ci * If we already allocated memory in past, then resend the same pointer. 13098c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 13108c2ecf20Sopenharmony_ci */ 13118c2ecf20Sopenharmony_cistatic int 13128c2ecf20Sopenharmony_cimpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) 13138c2ecf20Sopenharmony_ci{ 13148c2ecf20Sopenharmony_ci char *psge; 13158c2ecf20Sopenharmony_ci int flags_length; 13168c2ecf20Sopenharmony_ci u32 host_page_buffer_sz=0; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci if(!ioc->HostPageBuffer) { 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci host_page_buffer_sz = 13218c2ecf20Sopenharmony_ci le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci if(!host_page_buffer_sz) 13248c2ecf20Sopenharmony_ci return 0; /* fw doesn't need any host buffers */ 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci /* spin till we get enough memory */ 13278c2ecf20Sopenharmony_ci while (host_page_buffer_sz > 0) { 13288c2ecf20Sopenharmony_ci ioc->HostPageBuffer = 13298c2ecf20Sopenharmony_ci dma_alloc_coherent(&ioc->pcidev->dev, 13308c2ecf20Sopenharmony_ci host_page_buffer_sz, 13318c2ecf20Sopenharmony_ci &ioc->HostPageBuffer_dma, 13328c2ecf20Sopenharmony_ci GFP_KERNEL); 13338c2ecf20Sopenharmony_ci if (ioc->HostPageBuffer) { 13348c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 13358c2ecf20Sopenharmony_ci "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n", 13368c2ecf20Sopenharmony_ci ioc->name, ioc->HostPageBuffer, 13378c2ecf20Sopenharmony_ci (u32)ioc->HostPageBuffer_dma, 13388c2ecf20Sopenharmony_ci host_page_buffer_sz)); 13398c2ecf20Sopenharmony_ci ioc->alloc_total += host_page_buffer_sz; 13408c2ecf20Sopenharmony_ci ioc->HostPageBuffer_sz = host_page_buffer_sz; 13418c2ecf20Sopenharmony_ci break; 13428c2ecf20Sopenharmony_ci } 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci host_page_buffer_sz -= (4*1024); 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci if(!ioc->HostPageBuffer) { 13498c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 13508c2ecf20Sopenharmony_ci "Failed to alloc memory for host_page_buffer!\n", 13518c2ecf20Sopenharmony_ci ioc->name); 13528c2ecf20Sopenharmony_ci return -999; 13538c2ecf20Sopenharmony_ci } 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci psge = (char *)&ioc_init->HostPageBufferSGE; 13568c2ecf20Sopenharmony_ci flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT | 13578c2ecf20Sopenharmony_ci MPI_SGE_FLAGS_SYSTEM_ADDRESS | 13588c2ecf20Sopenharmony_ci MPI_SGE_FLAGS_HOST_TO_IOC | 13598c2ecf20Sopenharmony_ci MPI_SGE_FLAGS_END_OF_BUFFER; 13608c2ecf20Sopenharmony_ci flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; 13618c2ecf20Sopenharmony_ci flags_length |= ioc->HostPageBuffer_sz; 13628c2ecf20Sopenharmony_ci ioc->add_sge(psge, flags_length, ioc->HostPageBuffer_dma); 13638c2ecf20Sopenharmony_ci ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci return 0; 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 13698c2ecf20Sopenharmony_ci/** 13708c2ecf20Sopenharmony_ci * mpt_verify_adapter - Given IOC identifier, set pointer to its adapter structure. 13718c2ecf20Sopenharmony_ci * @iocid: IOC unique identifier (integer) 13728c2ecf20Sopenharmony_ci * @iocpp: Pointer to pointer to IOC adapter 13738c2ecf20Sopenharmony_ci * 13748c2ecf20Sopenharmony_ci * Given a unique IOC identifier, set pointer to the associated MPT 13758c2ecf20Sopenharmony_ci * adapter structure. 13768c2ecf20Sopenharmony_ci * 13778c2ecf20Sopenharmony_ci * Returns iocid and sets iocpp if iocid is found. 13788c2ecf20Sopenharmony_ci * Returns -1 if iocid is not found. 13798c2ecf20Sopenharmony_ci */ 13808c2ecf20Sopenharmony_ciint 13818c2ecf20Sopenharmony_cimpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) 13828c2ecf20Sopenharmony_ci{ 13838c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc; 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci list_for_each_entry(ioc,&ioc_list,list) { 13868c2ecf20Sopenharmony_ci if (ioc->id == iocid) { 13878c2ecf20Sopenharmony_ci *iocpp =ioc; 13888c2ecf20Sopenharmony_ci return iocid; 13898c2ecf20Sopenharmony_ci } 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci *iocpp = NULL; 13938c2ecf20Sopenharmony_ci return -1; 13948c2ecf20Sopenharmony_ci} 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci/** 13978c2ecf20Sopenharmony_ci * mpt_get_product_name - returns product string 13988c2ecf20Sopenharmony_ci * @vendor: pci vendor id 13998c2ecf20Sopenharmony_ci * @device: pci device id 14008c2ecf20Sopenharmony_ci * @revision: pci revision id 14018c2ecf20Sopenharmony_ci * 14028c2ecf20Sopenharmony_ci * Returns product string displayed when driver loads, 14038c2ecf20Sopenharmony_ci * in /proc/mpt/summary and /sysfs/class/scsi_host/host<X>/version_product 14048c2ecf20Sopenharmony_ci * 14058c2ecf20Sopenharmony_ci **/ 14068c2ecf20Sopenharmony_cistatic const char* 14078c2ecf20Sopenharmony_cimpt_get_product_name(u16 vendor, u16 device, u8 revision) 14088c2ecf20Sopenharmony_ci{ 14098c2ecf20Sopenharmony_ci char *product_str = NULL; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci if (vendor == PCI_VENDOR_ID_BROCADE) { 14128c2ecf20Sopenharmony_ci switch (device) 14138c2ecf20Sopenharmony_ci { 14148c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC949E: 14158c2ecf20Sopenharmony_ci switch (revision) 14168c2ecf20Sopenharmony_ci { 14178c2ecf20Sopenharmony_ci case 0x00: 14188c2ecf20Sopenharmony_ci product_str = "BRE040 A0"; 14198c2ecf20Sopenharmony_ci break; 14208c2ecf20Sopenharmony_ci case 0x01: 14218c2ecf20Sopenharmony_ci product_str = "BRE040 A1"; 14228c2ecf20Sopenharmony_ci break; 14238c2ecf20Sopenharmony_ci default: 14248c2ecf20Sopenharmony_ci product_str = "BRE040"; 14258c2ecf20Sopenharmony_ci break; 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci break; 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci goto out; 14308c2ecf20Sopenharmony_ci } 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci switch (device) 14338c2ecf20Sopenharmony_ci { 14348c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC909: 14358c2ecf20Sopenharmony_ci product_str = "LSIFC909 B1"; 14368c2ecf20Sopenharmony_ci break; 14378c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC919: 14388c2ecf20Sopenharmony_ci product_str = "LSIFC919 B0"; 14398c2ecf20Sopenharmony_ci break; 14408c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC929: 14418c2ecf20Sopenharmony_ci product_str = "LSIFC929 B0"; 14428c2ecf20Sopenharmony_ci break; 14438c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC919X: 14448c2ecf20Sopenharmony_ci if (revision < 0x80) 14458c2ecf20Sopenharmony_ci product_str = "LSIFC919X A0"; 14468c2ecf20Sopenharmony_ci else 14478c2ecf20Sopenharmony_ci product_str = "LSIFC919XL A1"; 14488c2ecf20Sopenharmony_ci break; 14498c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC929X: 14508c2ecf20Sopenharmony_ci if (revision < 0x80) 14518c2ecf20Sopenharmony_ci product_str = "LSIFC929X A0"; 14528c2ecf20Sopenharmony_ci else 14538c2ecf20Sopenharmony_ci product_str = "LSIFC929XL A1"; 14548c2ecf20Sopenharmony_ci break; 14558c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC939X: 14568c2ecf20Sopenharmony_ci product_str = "LSIFC939X A1"; 14578c2ecf20Sopenharmony_ci break; 14588c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC949X: 14598c2ecf20Sopenharmony_ci product_str = "LSIFC949X A1"; 14608c2ecf20Sopenharmony_ci break; 14618c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC949E: 14628c2ecf20Sopenharmony_ci switch (revision) 14638c2ecf20Sopenharmony_ci { 14648c2ecf20Sopenharmony_ci case 0x00: 14658c2ecf20Sopenharmony_ci product_str = "LSIFC949E A0"; 14668c2ecf20Sopenharmony_ci break; 14678c2ecf20Sopenharmony_ci case 0x01: 14688c2ecf20Sopenharmony_ci product_str = "LSIFC949E A1"; 14698c2ecf20Sopenharmony_ci break; 14708c2ecf20Sopenharmony_ci default: 14718c2ecf20Sopenharmony_ci product_str = "LSIFC949E"; 14728c2ecf20Sopenharmony_ci break; 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci break; 14758c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_53C1030: 14768c2ecf20Sopenharmony_ci switch (revision) 14778c2ecf20Sopenharmony_ci { 14788c2ecf20Sopenharmony_ci case 0x00: 14798c2ecf20Sopenharmony_ci product_str = "LSI53C1030 A0"; 14808c2ecf20Sopenharmony_ci break; 14818c2ecf20Sopenharmony_ci case 0x01: 14828c2ecf20Sopenharmony_ci product_str = "LSI53C1030 B0"; 14838c2ecf20Sopenharmony_ci break; 14848c2ecf20Sopenharmony_ci case 0x03: 14858c2ecf20Sopenharmony_ci product_str = "LSI53C1030 B1"; 14868c2ecf20Sopenharmony_ci break; 14878c2ecf20Sopenharmony_ci case 0x07: 14888c2ecf20Sopenharmony_ci product_str = "LSI53C1030 B2"; 14898c2ecf20Sopenharmony_ci break; 14908c2ecf20Sopenharmony_ci case 0x08: 14918c2ecf20Sopenharmony_ci product_str = "LSI53C1030 C0"; 14928c2ecf20Sopenharmony_ci break; 14938c2ecf20Sopenharmony_ci case 0x80: 14948c2ecf20Sopenharmony_ci product_str = "LSI53C1030T A0"; 14958c2ecf20Sopenharmony_ci break; 14968c2ecf20Sopenharmony_ci case 0x83: 14978c2ecf20Sopenharmony_ci product_str = "LSI53C1030T A2"; 14988c2ecf20Sopenharmony_ci break; 14998c2ecf20Sopenharmony_ci case 0x87: 15008c2ecf20Sopenharmony_ci product_str = "LSI53C1030T A3"; 15018c2ecf20Sopenharmony_ci break; 15028c2ecf20Sopenharmony_ci case 0xc1: 15038c2ecf20Sopenharmony_ci product_str = "LSI53C1020A A1"; 15048c2ecf20Sopenharmony_ci break; 15058c2ecf20Sopenharmony_ci default: 15068c2ecf20Sopenharmony_ci product_str = "LSI53C1030"; 15078c2ecf20Sopenharmony_ci break; 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci break; 15108c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_1030_53C1035: 15118c2ecf20Sopenharmony_ci switch (revision) 15128c2ecf20Sopenharmony_ci { 15138c2ecf20Sopenharmony_ci case 0x03: 15148c2ecf20Sopenharmony_ci product_str = "LSI53C1035 A2"; 15158c2ecf20Sopenharmony_ci break; 15168c2ecf20Sopenharmony_ci case 0x04: 15178c2ecf20Sopenharmony_ci product_str = "LSI53C1035 B0"; 15188c2ecf20Sopenharmony_ci break; 15198c2ecf20Sopenharmony_ci default: 15208c2ecf20Sopenharmony_ci product_str = "LSI53C1035"; 15218c2ecf20Sopenharmony_ci break; 15228c2ecf20Sopenharmony_ci } 15238c2ecf20Sopenharmony_ci break; 15248c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1064: 15258c2ecf20Sopenharmony_ci switch (revision) 15268c2ecf20Sopenharmony_ci { 15278c2ecf20Sopenharmony_ci case 0x00: 15288c2ecf20Sopenharmony_ci product_str = "LSISAS1064 A1"; 15298c2ecf20Sopenharmony_ci break; 15308c2ecf20Sopenharmony_ci case 0x01: 15318c2ecf20Sopenharmony_ci product_str = "LSISAS1064 A2"; 15328c2ecf20Sopenharmony_ci break; 15338c2ecf20Sopenharmony_ci case 0x02: 15348c2ecf20Sopenharmony_ci product_str = "LSISAS1064 A3"; 15358c2ecf20Sopenharmony_ci break; 15368c2ecf20Sopenharmony_ci case 0x03: 15378c2ecf20Sopenharmony_ci product_str = "LSISAS1064 A4"; 15388c2ecf20Sopenharmony_ci break; 15398c2ecf20Sopenharmony_ci default: 15408c2ecf20Sopenharmony_ci product_str = "LSISAS1064"; 15418c2ecf20Sopenharmony_ci break; 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci break; 15448c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1064E: 15458c2ecf20Sopenharmony_ci switch (revision) 15468c2ecf20Sopenharmony_ci { 15478c2ecf20Sopenharmony_ci case 0x00: 15488c2ecf20Sopenharmony_ci product_str = "LSISAS1064E A0"; 15498c2ecf20Sopenharmony_ci break; 15508c2ecf20Sopenharmony_ci case 0x01: 15518c2ecf20Sopenharmony_ci product_str = "LSISAS1064E B0"; 15528c2ecf20Sopenharmony_ci break; 15538c2ecf20Sopenharmony_ci case 0x02: 15548c2ecf20Sopenharmony_ci product_str = "LSISAS1064E B1"; 15558c2ecf20Sopenharmony_ci break; 15568c2ecf20Sopenharmony_ci case 0x04: 15578c2ecf20Sopenharmony_ci product_str = "LSISAS1064E B2"; 15588c2ecf20Sopenharmony_ci break; 15598c2ecf20Sopenharmony_ci case 0x08: 15608c2ecf20Sopenharmony_ci product_str = "LSISAS1064E B3"; 15618c2ecf20Sopenharmony_ci break; 15628c2ecf20Sopenharmony_ci default: 15638c2ecf20Sopenharmony_ci product_str = "LSISAS1064E"; 15648c2ecf20Sopenharmony_ci break; 15658c2ecf20Sopenharmony_ci } 15668c2ecf20Sopenharmony_ci break; 15678c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1068: 15688c2ecf20Sopenharmony_ci switch (revision) 15698c2ecf20Sopenharmony_ci { 15708c2ecf20Sopenharmony_ci case 0x00: 15718c2ecf20Sopenharmony_ci product_str = "LSISAS1068 A0"; 15728c2ecf20Sopenharmony_ci break; 15738c2ecf20Sopenharmony_ci case 0x01: 15748c2ecf20Sopenharmony_ci product_str = "LSISAS1068 B0"; 15758c2ecf20Sopenharmony_ci break; 15768c2ecf20Sopenharmony_ci case 0x02: 15778c2ecf20Sopenharmony_ci product_str = "LSISAS1068 B1"; 15788c2ecf20Sopenharmony_ci break; 15798c2ecf20Sopenharmony_ci default: 15808c2ecf20Sopenharmony_ci product_str = "LSISAS1068"; 15818c2ecf20Sopenharmony_ci break; 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci break; 15848c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1068E: 15858c2ecf20Sopenharmony_ci switch (revision) 15868c2ecf20Sopenharmony_ci { 15878c2ecf20Sopenharmony_ci case 0x00: 15888c2ecf20Sopenharmony_ci product_str = "LSISAS1068E A0"; 15898c2ecf20Sopenharmony_ci break; 15908c2ecf20Sopenharmony_ci case 0x01: 15918c2ecf20Sopenharmony_ci product_str = "LSISAS1068E B0"; 15928c2ecf20Sopenharmony_ci break; 15938c2ecf20Sopenharmony_ci case 0x02: 15948c2ecf20Sopenharmony_ci product_str = "LSISAS1068E B1"; 15958c2ecf20Sopenharmony_ci break; 15968c2ecf20Sopenharmony_ci case 0x04: 15978c2ecf20Sopenharmony_ci product_str = "LSISAS1068E B2"; 15988c2ecf20Sopenharmony_ci break; 15998c2ecf20Sopenharmony_ci case 0x08: 16008c2ecf20Sopenharmony_ci product_str = "LSISAS1068E B3"; 16018c2ecf20Sopenharmony_ci break; 16028c2ecf20Sopenharmony_ci default: 16038c2ecf20Sopenharmony_ci product_str = "LSISAS1068E"; 16048c2ecf20Sopenharmony_ci break; 16058c2ecf20Sopenharmony_ci } 16068c2ecf20Sopenharmony_ci break; 16078c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1078: 16088c2ecf20Sopenharmony_ci switch (revision) 16098c2ecf20Sopenharmony_ci { 16108c2ecf20Sopenharmony_ci case 0x00: 16118c2ecf20Sopenharmony_ci product_str = "LSISAS1078 A0"; 16128c2ecf20Sopenharmony_ci break; 16138c2ecf20Sopenharmony_ci case 0x01: 16148c2ecf20Sopenharmony_ci product_str = "LSISAS1078 B0"; 16158c2ecf20Sopenharmony_ci break; 16168c2ecf20Sopenharmony_ci case 0x02: 16178c2ecf20Sopenharmony_ci product_str = "LSISAS1078 C0"; 16188c2ecf20Sopenharmony_ci break; 16198c2ecf20Sopenharmony_ci case 0x03: 16208c2ecf20Sopenharmony_ci product_str = "LSISAS1078 C1"; 16218c2ecf20Sopenharmony_ci break; 16228c2ecf20Sopenharmony_ci case 0x04: 16238c2ecf20Sopenharmony_ci product_str = "LSISAS1078 C2"; 16248c2ecf20Sopenharmony_ci break; 16258c2ecf20Sopenharmony_ci default: 16268c2ecf20Sopenharmony_ci product_str = "LSISAS1078"; 16278c2ecf20Sopenharmony_ci break; 16288c2ecf20Sopenharmony_ci } 16298c2ecf20Sopenharmony_ci break; 16308c2ecf20Sopenharmony_ci } 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci out: 16338c2ecf20Sopenharmony_ci return product_str; 16348c2ecf20Sopenharmony_ci} 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci/** 16378c2ecf20Sopenharmony_ci * mpt_mapresources - map in memory mapped io 16388c2ecf20Sopenharmony_ci * @ioc: Pointer to pointer to IOC adapter 16398c2ecf20Sopenharmony_ci * 16408c2ecf20Sopenharmony_ci **/ 16418c2ecf20Sopenharmony_cistatic int 16428c2ecf20Sopenharmony_cimpt_mapresources(MPT_ADAPTER *ioc) 16438c2ecf20Sopenharmony_ci{ 16448c2ecf20Sopenharmony_ci u8 __iomem *mem; 16458c2ecf20Sopenharmony_ci int ii; 16468c2ecf20Sopenharmony_ci resource_size_t mem_phys; 16478c2ecf20Sopenharmony_ci unsigned long port; 16488c2ecf20Sopenharmony_ci u32 msize; 16498c2ecf20Sopenharmony_ci u32 psize; 16508c2ecf20Sopenharmony_ci int r = -ENODEV; 16518c2ecf20Sopenharmony_ci struct pci_dev *pdev; 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci pdev = ioc->pcidev; 16548c2ecf20Sopenharmony_ci ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); 16558c2ecf20Sopenharmony_ci if (pci_enable_device_mem(pdev)) { 16568c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() " 16578c2ecf20Sopenharmony_ci "failed\n", ioc->name); 16588c2ecf20Sopenharmony_ci return r; 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) { 16618c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with " 16628c2ecf20Sopenharmony_ci "MEM failed\n", ioc->name); 16638c2ecf20Sopenharmony_ci goto out_pci_disable_device; 16648c2ecf20Sopenharmony_ci } 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci if (sizeof(dma_addr_t) > 4) { 16678c2ecf20Sopenharmony_ci const uint64_t required_mask = dma_get_required_mask 16688c2ecf20Sopenharmony_ci (&pdev->dev); 16698c2ecf20Sopenharmony_ci if (required_mask > DMA_BIT_MASK(32) 16708c2ecf20Sopenharmony_ci && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) 16718c2ecf20Sopenharmony_ci && !pci_set_consistent_dma_mask(pdev, 16728c2ecf20Sopenharmony_ci DMA_BIT_MASK(64))) { 16738c2ecf20Sopenharmony_ci ioc->dma_mask = DMA_BIT_MASK(64); 16748c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 16758c2ecf20Sopenharmony_ci ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", 16768c2ecf20Sopenharmony_ci ioc->name)); 16778c2ecf20Sopenharmony_ci } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) 16788c2ecf20Sopenharmony_ci && !pci_set_consistent_dma_mask(pdev, 16798c2ecf20Sopenharmony_ci DMA_BIT_MASK(32))) { 16808c2ecf20Sopenharmony_ci ioc->dma_mask = DMA_BIT_MASK(32); 16818c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 16828c2ecf20Sopenharmony_ci ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", 16838c2ecf20Sopenharmony_ci ioc->name)); 16848c2ecf20Sopenharmony_ci } else { 16858c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", 16868c2ecf20Sopenharmony_ci ioc->name, pci_name(pdev)); 16878c2ecf20Sopenharmony_ci goto out_pci_release_region; 16888c2ecf20Sopenharmony_ci } 16898c2ecf20Sopenharmony_ci } else { 16908c2ecf20Sopenharmony_ci if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) 16918c2ecf20Sopenharmony_ci && !pci_set_consistent_dma_mask(pdev, 16928c2ecf20Sopenharmony_ci DMA_BIT_MASK(32))) { 16938c2ecf20Sopenharmony_ci ioc->dma_mask = DMA_BIT_MASK(32); 16948c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 16958c2ecf20Sopenharmony_ci ": 32 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", 16968c2ecf20Sopenharmony_ci ioc->name)); 16978c2ecf20Sopenharmony_ci } else { 16988c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", 16998c2ecf20Sopenharmony_ci ioc->name, pci_name(pdev)); 17008c2ecf20Sopenharmony_ci goto out_pci_release_region; 17018c2ecf20Sopenharmony_ci } 17028c2ecf20Sopenharmony_ci } 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci mem_phys = msize = 0; 17058c2ecf20Sopenharmony_ci port = psize = 0; 17068c2ecf20Sopenharmony_ci for (ii = 0; ii < DEVICE_COUNT_RESOURCE; ii++) { 17078c2ecf20Sopenharmony_ci if (pci_resource_flags(pdev, ii) & PCI_BASE_ADDRESS_SPACE_IO) { 17088c2ecf20Sopenharmony_ci if (psize) 17098c2ecf20Sopenharmony_ci continue; 17108c2ecf20Sopenharmony_ci /* Get I/O space! */ 17118c2ecf20Sopenharmony_ci port = pci_resource_start(pdev, ii); 17128c2ecf20Sopenharmony_ci psize = pci_resource_len(pdev, ii); 17138c2ecf20Sopenharmony_ci } else { 17148c2ecf20Sopenharmony_ci if (msize) 17158c2ecf20Sopenharmony_ci continue; 17168c2ecf20Sopenharmony_ci /* Get memmap */ 17178c2ecf20Sopenharmony_ci mem_phys = pci_resource_start(pdev, ii); 17188c2ecf20Sopenharmony_ci msize = pci_resource_len(pdev, ii); 17198c2ecf20Sopenharmony_ci } 17208c2ecf20Sopenharmony_ci } 17218c2ecf20Sopenharmony_ci ioc->mem_size = msize; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci mem = NULL; 17248c2ecf20Sopenharmony_ci /* Get logical ptr for PciMem0 space */ 17258c2ecf20Sopenharmony_ci /*mem = ioremap(mem_phys, msize);*/ 17268c2ecf20Sopenharmony_ci mem = ioremap(mem_phys, msize); 17278c2ecf20Sopenharmony_ci if (mem == NULL) { 17288c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter" 17298c2ecf20Sopenharmony_ci " memory!\n", ioc->name); 17308c2ecf20Sopenharmony_ci r = -EINVAL; 17318c2ecf20Sopenharmony_ci goto out_pci_release_region; 17328c2ecf20Sopenharmony_ci } 17338c2ecf20Sopenharmony_ci ioc->memmap = mem; 17348c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %llx\n", 17358c2ecf20Sopenharmony_ci ioc->name, mem, (unsigned long long)mem_phys)); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci ioc->mem_phys = mem_phys; 17388c2ecf20Sopenharmony_ci ioc->chip = (SYSIF_REGS __iomem *)mem; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci /* Save Port IO values in case we need to do downloadboot */ 17418c2ecf20Sopenharmony_ci ioc->pio_mem_phys = port; 17428c2ecf20Sopenharmony_ci ioc->pio_chip = (SYSIF_REGS __iomem *)port; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci return 0; 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ciout_pci_release_region: 17478c2ecf20Sopenharmony_ci pci_release_selected_regions(pdev, ioc->bars); 17488c2ecf20Sopenharmony_ciout_pci_disable_device: 17498c2ecf20Sopenharmony_ci pci_disable_device(pdev); 17508c2ecf20Sopenharmony_ci return r; 17518c2ecf20Sopenharmony_ci} 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 17548c2ecf20Sopenharmony_ci/** 17558c2ecf20Sopenharmony_ci * mpt_attach - Install a PCI intelligent MPT adapter. 17568c2ecf20Sopenharmony_ci * @pdev: Pointer to pci_dev structure 17578c2ecf20Sopenharmony_ci * @id: PCI device ID information 17588c2ecf20Sopenharmony_ci * 17598c2ecf20Sopenharmony_ci * This routine performs all the steps necessary to bring the IOC of 17608c2ecf20Sopenharmony_ci * a MPT adapter to a OPERATIONAL state. This includes registering 17618c2ecf20Sopenharmony_ci * memory regions, registering the interrupt, and allocating request 17628c2ecf20Sopenharmony_ci * and reply memory pools. 17638c2ecf20Sopenharmony_ci * 17648c2ecf20Sopenharmony_ci * This routine also pre-fetches the LAN MAC address of a Fibre Channel 17658c2ecf20Sopenharmony_ci * MPT adapter. 17668c2ecf20Sopenharmony_ci * 17678c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 17688c2ecf20Sopenharmony_ci * 17698c2ecf20Sopenharmony_ci * TODO: Add support for polled controllers 17708c2ecf20Sopenharmony_ci */ 17718c2ecf20Sopenharmony_ciint 17728c2ecf20Sopenharmony_cimpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) 17738c2ecf20Sopenharmony_ci{ 17748c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc; 17758c2ecf20Sopenharmony_ci u8 cb_idx; 17768c2ecf20Sopenharmony_ci int r = -ENODEV; 17778c2ecf20Sopenharmony_ci u8 pcixcmd; 17788c2ecf20Sopenharmony_ci static int mpt_ids = 0; 17798c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 17808c2ecf20Sopenharmony_ci struct proc_dir_entry *dent; 17818c2ecf20Sopenharmony_ci#endif 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_KERNEL); 17848c2ecf20Sopenharmony_ci if (ioc == NULL) { 17858c2ecf20Sopenharmony_ci printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); 17868c2ecf20Sopenharmony_ci return -ENOMEM; 17878c2ecf20Sopenharmony_ci } 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci ioc->id = mpt_ids++; 17908c2ecf20Sopenharmony_ci sprintf(ioc->name, "ioc%d", ioc->id); 17918c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n")); 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci /* 17948c2ecf20Sopenharmony_ci * set initial debug level 17958c2ecf20Sopenharmony_ci * (refer to mptdebug.h) 17968c2ecf20Sopenharmony_ci * 17978c2ecf20Sopenharmony_ci */ 17988c2ecf20Sopenharmony_ci ioc->debug_level = mpt_debug_level; 17998c2ecf20Sopenharmony_ci if (mpt_debug_level) 18008c2ecf20Sopenharmony_ci printk(KERN_INFO "mpt_debug_level=%xh\n", mpt_debug_level); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name)); 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci ioc->pcidev = pdev; 18058c2ecf20Sopenharmony_ci if (mpt_mapresources(ioc)) { 18068c2ecf20Sopenharmony_ci goto out_free_ioc; 18078c2ecf20Sopenharmony_ci } 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci /* 18108c2ecf20Sopenharmony_ci * Setting up proper handlers for scatter gather handling 18118c2ecf20Sopenharmony_ci */ 18128c2ecf20Sopenharmony_ci if (ioc->dma_mask == DMA_BIT_MASK(64)) { 18138c2ecf20Sopenharmony_ci if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) 18148c2ecf20Sopenharmony_ci ioc->add_sge = &mpt_add_sge_64bit_1078; 18158c2ecf20Sopenharmony_ci else 18168c2ecf20Sopenharmony_ci ioc->add_sge = &mpt_add_sge_64bit; 18178c2ecf20Sopenharmony_ci ioc->add_chain = &mpt_add_chain_64bit; 18188c2ecf20Sopenharmony_ci ioc->sg_addr_size = 8; 18198c2ecf20Sopenharmony_ci } else { 18208c2ecf20Sopenharmony_ci ioc->add_sge = &mpt_add_sge; 18218c2ecf20Sopenharmony_ci ioc->add_chain = &mpt_add_chain; 18228c2ecf20Sopenharmony_ci ioc->sg_addr_size = 4; 18238c2ecf20Sopenharmony_ci } 18248c2ecf20Sopenharmony_ci ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci ioc->alloc_total = sizeof(MPT_ADAPTER); 18278c2ecf20Sopenharmony_ci ioc->req_sz = MPT_DEFAULT_FRAME_SIZE; /* avoid div by zero! */ 18288c2ecf20Sopenharmony_ci ioc->reply_sz = MPT_REPLY_FRAME_SIZE; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci spin_lock_init(&ioc->taskmgmt_lock); 18328c2ecf20Sopenharmony_ci mutex_init(&ioc->internal_cmds.mutex); 18338c2ecf20Sopenharmony_ci init_completion(&ioc->internal_cmds.done); 18348c2ecf20Sopenharmony_ci mutex_init(&ioc->mptbase_cmds.mutex); 18358c2ecf20Sopenharmony_ci init_completion(&ioc->mptbase_cmds.done); 18368c2ecf20Sopenharmony_ci mutex_init(&ioc->taskmgmt_cmds.mutex); 18378c2ecf20Sopenharmony_ci init_completion(&ioc->taskmgmt_cmds.done); 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci /* Initialize the event logging. 18408c2ecf20Sopenharmony_ci */ 18418c2ecf20Sopenharmony_ci ioc->eventTypes = 0; /* None */ 18428c2ecf20Sopenharmony_ci ioc->eventContext = 0; 18438c2ecf20Sopenharmony_ci ioc->eventLogSize = 0; 18448c2ecf20Sopenharmony_ci ioc->events = NULL; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci#ifdef MFCNT 18478c2ecf20Sopenharmony_ci ioc->mfcnt = 0; 18488c2ecf20Sopenharmony_ci#endif 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci ioc->sh = NULL; 18518c2ecf20Sopenharmony_ci ioc->cached_fw = NULL; 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci /* Initialize SCSI Config Data structure 18548c2ecf20Sopenharmony_ci */ 18558c2ecf20Sopenharmony_ci memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci /* Initialize the fc rport list head. 18588c2ecf20Sopenharmony_ci */ 18598c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ioc->fc_rports); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci /* Find lookup slot. */ 18628c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ioc->list); 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci /* Initialize workqueue */ 18668c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work); 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci snprintf(ioc->reset_work_q_name, MPT_KOBJ_NAME_LEN, 18698c2ecf20Sopenharmony_ci "mpt_poll_%d", ioc->id); 18708c2ecf20Sopenharmony_ci ioc->reset_work_q = alloc_workqueue(ioc->reset_work_q_name, 18718c2ecf20Sopenharmony_ci WQ_MEM_RECLAIM, 0); 18728c2ecf20Sopenharmony_ci if (!ioc->reset_work_q) { 18738c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", 18748c2ecf20Sopenharmony_ci ioc->name); 18758c2ecf20Sopenharmony_ci r = -ENOMEM; 18768c2ecf20Sopenharmony_ci goto out_unmap_resources; 18778c2ecf20Sopenharmony_ci } 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", 18808c2ecf20Sopenharmony_ci ioc->name, &ioc->facts, &ioc->pfacts[0])); 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci ioc->prod_name = mpt_get_product_name(pdev->vendor, pdev->device, 18838c2ecf20Sopenharmony_ci pdev->revision); 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci switch (pdev->device) 18868c2ecf20Sopenharmony_ci { 18878c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC939X: 18888c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC949X: 18898c2ecf20Sopenharmony_ci ioc->errata_flag_1064 = 1; 18908c2ecf20Sopenharmony_ci fallthrough; 18918c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC909: 18928c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC929: 18938c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC919: 18948c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC949E: 18958c2ecf20Sopenharmony_ci ioc->bus_type = FC; 18968c2ecf20Sopenharmony_ci break; 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC929X: 18998c2ecf20Sopenharmony_ci if (pdev->revision < XL_929) { 19008c2ecf20Sopenharmony_ci /* 929X Chip Fix. Set Split transactions level 19018c2ecf20Sopenharmony_ci * for PCIX. Set MOST bits to zero. 19028c2ecf20Sopenharmony_ci */ 19038c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, 0x6a, &pcixcmd); 19048c2ecf20Sopenharmony_ci pcixcmd &= 0x8F; 19058c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x6a, pcixcmd); 19068c2ecf20Sopenharmony_ci } else { 19078c2ecf20Sopenharmony_ci /* 929XL Chip Fix. Set MMRBC to 0x08. 19088c2ecf20Sopenharmony_ci */ 19098c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, 0x6a, &pcixcmd); 19108c2ecf20Sopenharmony_ci pcixcmd |= 0x08; 19118c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x6a, pcixcmd); 19128c2ecf20Sopenharmony_ci } 19138c2ecf20Sopenharmony_ci ioc->bus_type = FC; 19148c2ecf20Sopenharmony_ci break; 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVICEID_FC919X: 19178c2ecf20Sopenharmony_ci /* 919X Chip Fix. Set Split transactions level 19188c2ecf20Sopenharmony_ci * for PCIX. Set MOST bits to zero. 19198c2ecf20Sopenharmony_ci */ 19208c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, 0x6a, &pcixcmd); 19218c2ecf20Sopenharmony_ci pcixcmd &= 0x8F; 19228c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x6a, pcixcmd); 19238c2ecf20Sopenharmony_ci ioc->bus_type = FC; 19248c2ecf20Sopenharmony_ci break; 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_53C1030: 19278c2ecf20Sopenharmony_ci /* 1030 Chip Fix. Disable Split transactions 19288c2ecf20Sopenharmony_ci * for PCIX. Set MOST bits to zero if Rev < C0( = 8). 19298c2ecf20Sopenharmony_ci */ 19308c2ecf20Sopenharmony_ci if (pdev->revision < C0_1030) { 19318c2ecf20Sopenharmony_ci pci_read_config_byte(pdev, 0x6a, &pcixcmd); 19328c2ecf20Sopenharmony_ci pcixcmd &= 0x8F; 19338c2ecf20Sopenharmony_ci pci_write_config_byte(pdev, 0x6a, pcixcmd); 19348c2ecf20Sopenharmony_ci } 19358c2ecf20Sopenharmony_ci fallthrough; 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_1030_53C1035: 19388c2ecf20Sopenharmony_ci ioc->bus_type = SPI; 19398c2ecf20Sopenharmony_ci break; 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1064: 19428c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1068: 19438c2ecf20Sopenharmony_ci ioc->errata_flag_1064 = 1; 19448c2ecf20Sopenharmony_ci ioc->bus_type = SAS; 19458c2ecf20Sopenharmony_ci break; 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1064E: 19488c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1068E: 19498c2ecf20Sopenharmony_ci case MPI_MANUFACTPAGE_DEVID_SAS1078: 19508c2ecf20Sopenharmony_ci ioc->bus_type = SAS; 19518c2ecf20Sopenharmony_ci break; 19528c2ecf20Sopenharmony_ci } 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci switch (ioc->bus_type) { 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci case SAS: 19588c2ecf20Sopenharmony_ci ioc->msi_enable = mpt_msi_enable_sas; 19598c2ecf20Sopenharmony_ci break; 19608c2ecf20Sopenharmony_ci 19618c2ecf20Sopenharmony_ci case SPI: 19628c2ecf20Sopenharmony_ci ioc->msi_enable = mpt_msi_enable_spi; 19638c2ecf20Sopenharmony_ci break; 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci case FC: 19668c2ecf20Sopenharmony_ci ioc->msi_enable = mpt_msi_enable_fc; 19678c2ecf20Sopenharmony_ci break; 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci default: 19708c2ecf20Sopenharmony_ci ioc->msi_enable = 0; 19718c2ecf20Sopenharmony_ci break; 19728c2ecf20Sopenharmony_ci } 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci ioc->fw_events_off = 1; 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci if (ioc->errata_flag_1064) 19778c2ecf20Sopenharmony_ci pci_disable_io_access(pdev); 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci spin_lock_init(&ioc->FreeQlock); 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci /* Disable all! */ 19828c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); 19838c2ecf20Sopenharmony_ci ioc->active = 0; 19848c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci /* Set IOC ptr in the pcidev's driver data. */ 19878c2ecf20Sopenharmony_ci pci_set_drvdata(ioc->pcidev, ioc); 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci /* Set lookup ptr. */ 19908c2ecf20Sopenharmony_ci list_add_tail(&ioc->list, &ioc_list); 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_ci /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. 19938c2ecf20Sopenharmony_ci */ 19948c2ecf20Sopenharmony_ci mpt_detect_bound_ports(ioc, pdev); 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ioc->fw_event_list); 19978c2ecf20Sopenharmony_ci spin_lock_init(&ioc->fw_event_lock); 19988c2ecf20Sopenharmony_ci snprintf(ioc->fw_event_q_name, MPT_KOBJ_NAME_LEN, "mpt/%d", ioc->id); 19998c2ecf20Sopenharmony_ci ioc->fw_event_q = alloc_workqueue(ioc->fw_event_q_name, 20008c2ecf20Sopenharmony_ci WQ_MEM_RECLAIM, 0); 20018c2ecf20Sopenharmony_ci if (!ioc->fw_event_q) { 20028c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", 20038c2ecf20Sopenharmony_ci ioc->name); 20048c2ecf20Sopenharmony_ci r = -ENOMEM; 20058c2ecf20Sopenharmony_ci goto out_remove_ioc; 20068c2ecf20Sopenharmony_ci } 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, 20098c2ecf20Sopenharmony_ci CAN_SLEEP)) != 0){ 20108c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", 20118c2ecf20Sopenharmony_ci ioc->name, r); 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci destroy_workqueue(ioc->fw_event_q); 20148c2ecf20Sopenharmony_ci ioc->fw_event_q = NULL; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci list_del(&ioc->list); 20178c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 20188c2ecf20Sopenharmony_ci ioc->alt_ioc->alt_ioc = NULL; 20198c2ecf20Sopenharmony_ci iounmap(ioc->memmap); 20208c2ecf20Sopenharmony_ci if (pci_is_enabled(pdev)) 20218c2ecf20Sopenharmony_ci pci_disable_device(pdev); 20228c2ecf20Sopenharmony_ci if (r != -5) 20238c2ecf20Sopenharmony_ci pci_release_selected_regions(pdev, ioc->bars); 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci destroy_workqueue(ioc->reset_work_q); 20268c2ecf20Sopenharmony_ci ioc->reset_work_q = NULL; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci kfree(ioc); 20298c2ecf20Sopenharmony_ci return r; 20308c2ecf20Sopenharmony_ci } 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci /* call per device driver probe entry point */ 20338c2ecf20Sopenharmony_ci for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) { 20348c2ecf20Sopenharmony_ci if(MptDeviceDriverHandlers[cb_idx] && 20358c2ecf20Sopenharmony_ci MptDeviceDriverHandlers[cb_idx]->probe) { 20368c2ecf20Sopenharmony_ci MptDeviceDriverHandlers[cb_idx]->probe(pdev,id); 20378c2ecf20Sopenharmony_ci } 20388c2ecf20Sopenharmony_ci } 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 20418c2ecf20Sopenharmony_ci /* 20428c2ecf20Sopenharmony_ci * Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter. 20438c2ecf20Sopenharmony_ci */ 20448c2ecf20Sopenharmony_ci dent = proc_mkdir(ioc->name, mpt_proc_root_dir); 20458c2ecf20Sopenharmony_ci if (dent) { 20468c2ecf20Sopenharmony_ci proc_create_single_data("info", S_IRUGO, dent, 20478c2ecf20Sopenharmony_ci mpt_iocinfo_proc_show, ioc); 20488c2ecf20Sopenharmony_ci proc_create_single_data("summary", S_IRUGO, dent, 20498c2ecf20Sopenharmony_ci mpt_summary_proc_show, ioc); 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci#endif 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci if (!ioc->alt_ioc) 20548c2ecf20Sopenharmony_ci queue_delayed_work(ioc->reset_work_q, &ioc->fault_reset_work, 20558c2ecf20Sopenharmony_ci msecs_to_jiffies(MPT_POLLING_INTERVAL)); 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ci return 0; 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ciout_remove_ioc: 20608c2ecf20Sopenharmony_ci list_del(&ioc->list); 20618c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 20628c2ecf20Sopenharmony_ci ioc->alt_ioc->alt_ioc = NULL; 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci destroy_workqueue(ioc->reset_work_q); 20658c2ecf20Sopenharmony_ci ioc->reset_work_q = NULL; 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ciout_unmap_resources: 20688c2ecf20Sopenharmony_ci iounmap(ioc->memmap); 20698c2ecf20Sopenharmony_ci pci_disable_device(pdev); 20708c2ecf20Sopenharmony_ci pci_release_selected_regions(pdev, ioc->bars); 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ciout_free_ioc: 20738c2ecf20Sopenharmony_ci kfree(ioc); 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci return r; 20768c2ecf20Sopenharmony_ci} 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 20798c2ecf20Sopenharmony_ci/** 20808c2ecf20Sopenharmony_ci * mpt_detach - Remove a PCI intelligent MPT adapter. 20818c2ecf20Sopenharmony_ci * @pdev: Pointer to pci_dev structure 20828c2ecf20Sopenharmony_ci */ 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_civoid 20858c2ecf20Sopenharmony_cimpt_detach(struct pci_dev *pdev) 20868c2ecf20Sopenharmony_ci{ 20878c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 20888c2ecf20Sopenharmony_ci char pname[64]; 20898c2ecf20Sopenharmony_ci u8 cb_idx; 20908c2ecf20Sopenharmony_ci unsigned long flags; 20918c2ecf20Sopenharmony_ci struct workqueue_struct *wq; 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci /* 20948c2ecf20Sopenharmony_ci * Stop polling ioc for fault condition 20958c2ecf20Sopenharmony_ci */ 20968c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 20978c2ecf20Sopenharmony_ci wq = ioc->reset_work_q; 20988c2ecf20Sopenharmony_ci ioc->reset_work_q = NULL; 20998c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 21008c2ecf20Sopenharmony_ci cancel_delayed_work(&ioc->fault_reset_work); 21018c2ecf20Sopenharmony_ci destroy_workqueue(wq); 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->fw_event_lock, flags); 21048c2ecf20Sopenharmony_ci wq = ioc->fw_event_q; 21058c2ecf20Sopenharmony_ci ioc->fw_event_q = NULL; 21068c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->fw_event_lock, flags); 21078c2ecf20Sopenharmony_ci destroy_workqueue(wq); 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci snprintf(pname, sizeof(pname), MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); 21108c2ecf20Sopenharmony_ci remove_proc_entry(pname, NULL); 21118c2ecf20Sopenharmony_ci snprintf(pname, sizeof(pname), MPT_PROCFS_MPTBASEDIR "/%s/info", ioc->name); 21128c2ecf20Sopenharmony_ci remove_proc_entry(pname, NULL); 21138c2ecf20Sopenharmony_ci snprintf(pname, sizeof(pname), MPT_PROCFS_MPTBASEDIR "/%s", ioc->name); 21148c2ecf20Sopenharmony_ci remove_proc_entry(pname, NULL); 21158c2ecf20Sopenharmony_ci 21168c2ecf20Sopenharmony_ci /* call per device driver remove entry point */ 21178c2ecf20Sopenharmony_ci for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) { 21188c2ecf20Sopenharmony_ci if(MptDeviceDriverHandlers[cb_idx] && 21198c2ecf20Sopenharmony_ci MptDeviceDriverHandlers[cb_idx]->remove) { 21208c2ecf20Sopenharmony_ci MptDeviceDriverHandlers[cb_idx]->remove(pdev); 21218c2ecf20Sopenharmony_ci } 21228c2ecf20Sopenharmony_ci } 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci /* Disable interrupts! */ 21258c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci ioc->active = 0; 21288c2ecf20Sopenharmony_ci synchronize_irq(pdev->irq); 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci /* Clear any lingering interrupt */ 21318c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci CHIPREG_READ32(&ioc->chip->IntStatus); 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_ci mpt_adapter_dispose(ioc); 21368c2ecf20Sopenharmony_ci 21378c2ecf20Sopenharmony_ci} 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci/************************************************************************** 21408c2ecf20Sopenharmony_ci * Power Management 21418c2ecf20Sopenharmony_ci */ 21428c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 21438c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 21448c2ecf20Sopenharmony_ci/** 21458c2ecf20Sopenharmony_ci * mpt_suspend - Fusion MPT base driver suspend routine. 21468c2ecf20Sopenharmony_ci * @pdev: Pointer to pci_dev structure 21478c2ecf20Sopenharmony_ci * @state: new state to enter 21488c2ecf20Sopenharmony_ci */ 21498c2ecf20Sopenharmony_ciint 21508c2ecf20Sopenharmony_cimpt_suspend(struct pci_dev *pdev, pm_message_t state) 21518c2ecf20Sopenharmony_ci{ 21528c2ecf20Sopenharmony_ci u32 device_state; 21538c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci device_state = pci_choose_state(pdev, state); 21568c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "pci-suspend: pdev=0x%p, slot=%s, Entering " 21578c2ecf20Sopenharmony_ci "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), 21588c2ecf20Sopenharmony_ci device_state); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci /* put ioc into READY_STATE */ 21618c2ecf20Sopenharmony_ci if (SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, CAN_SLEEP)) { 21628c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 21638c2ecf20Sopenharmony_ci "pci-suspend: IOC msg unit reset failed!\n", ioc->name); 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci /* disable interrupts */ 21678c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); 21688c2ecf20Sopenharmony_ci ioc->active = 0; 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci /* Clear any lingering interrupt */ 21718c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci free_irq(ioc->pci_irq, ioc); 21748c2ecf20Sopenharmony_ci if (ioc->msi_enable) 21758c2ecf20Sopenharmony_ci pci_disable_msi(ioc->pcidev); 21768c2ecf20Sopenharmony_ci ioc->pci_irq = -1; 21778c2ecf20Sopenharmony_ci pci_save_state(pdev); 21788c2ecf20Sopenharmony_ci pci_disable_device(pdev); 21798c2ecf20Sopenharmony_ci pci_release_selected_regions(pdev, ioc->bars); 21808c2ecf20Sopenharmony_ci pci_set_power_state(pdev, device_state); 21818c2ecf20Sopenharmony_ci return 0; 21828c2ecf20Sopenharmony_ci} 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 21858c2ecf20Sopenharmony_ci/** 21868c2ecf20Sopenharmony_ci * mpt_resume - Fusion MPT base driver resume routine. 21878c2ecf20Sopenharmony_ci * @pdev: Pointer to pci_dev structure 21888c2ecf20Sopenharmony_ci */ 21898c2ecf20Sopenharmony_ciint 21908c2ecf20Sopenharmony_cimpt_resume(struct pci_dev *pdev) 21918c2ecf20Sopenharmony_ci{ 21928c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = pci_get_drvdata(pdev); 21938c2ecf20Sopenharmony_ci u32 device_state = pdev->current_state; 21948c2ecf20Sopenharmony_ci int recovery_state; 21958c2ecf20Sopenharmony_ci int err; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "pci-resume: pdev=0x%p, slot=%s, Previous " 21988c2ecf20Sopenharmony_ci "operating state [D%d]\n", ioc->name, pdev, pci_name(pdev), 21998c2ecf20Sopenharmony_ci device_state); 22008c2ecf20Sopenharmony_ci 22018c2ecf20Sopenharmony_ci pci_set_power_state(pdev, PCI_D0); 22028c2ecf20Sopenharmony_ci pci_enable_wake(pdev, PCI_D0, 0); 22038c2ecf20Sopenharmony_ci pci_restore_state(pdev); 22048c2ecf20Sopenharmony_ci ioc->pcidev = pdev; 22058c2ecf20Sopenharmony_ci err = mpt_mapresources(ioc); 22068c2ecf20Sopenharmony_ci if (err) 22078c2ecf20Sopenharmony_ci return err; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci if (ioc->dma_mask == DMA_BIT_MASK(64)) { 22108c2ecf20Sopenharmony_ci if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) 22118c2ecf20Sopenharmony_ci ioc->add_sge = &mpt_add_sge_64bit_1078; 22128c2ecf20Sopenharmony_ci else 22138c2ecf20Sopenharmony_ci ioc->add_sge = &mpt_add_sge_64bit; 22148c2ecf20Sopenharmony_ci ioc->add_chain = &mpt_add_chain_64bit; 22158c2ecf20Sopenharmony_ci ioc->sg_addr_size = 8; 22168c2ecf20Sopenharmony_ci } else { 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci ioc->add_sge = &mpt_add_sge; 22198c2ecf20Sopenharmony_ci ioc->add_chain = &mpt_add_chain; 22208c2ecf20Sopenharmony_ci ioc->sg_addr_size = 4; 22218c2ecf20Sopenharmony_ci } 22228c2ecf20Sopenharmony_ci ioc->SGE_size = sizeof(u32) + ioc->sg_addr_size; 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "pci-resume: ioc-state=0x%x,doorbell=0x%x\n", 22258c2ecf20Sopenharmony_ci ioc->name, (mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT), 22268c2ecf20Sopenharmony_ci CHIPREG_READ32(&ioc->chip->Doorbell)); 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci /* 22298c2ecf20Sopenharmony_ci * Errata workaround for SAS pci express: 22308c2ecf20Sopenharmony_ci * Upon returning to the D0 state, the contents of the doorbell will be 22318c2ecf20Sopenharmony_ci * stale data, and this will incorrectly signal to the host driver that 22328c2ecf20Sopenharmony_ci * the firmware is ready to process mpt commands. The workaround is 22338c2ecf20Sopenharmony_ci * to issue a diagnostic reset. 22348c2ecf20Sopenharmony_ci */ 22358c2ecf20Sopenharmony_ci if (ioc->bus_type == SAS && (pdev->device == 22368c2ecf20Sopenharmony_ci MPI_MANUFACTPAGE_DEVID_SAS1068E || pdev->device == 22378c2ecf20Sopenharmony_ci MPI_MANUFACTPAGE_DEVID_SAS1064E)) { 22388c2ecf20Sopenharmony_ci if (KickStart(ioc, 1, CAN_SLEEP) < 0) { 22398c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover\n", 22408c2ecf20Sopenharmony_ci ioc->name); 22418c2ecf20Sopenharmony_ci goto out; 22428c2ecf20Sopenharmony_ci } 22438c2ecf20Sopenharmony_ci } 22448c2ecf20Sopenharmony_ci 22458c2ecf20Sopenharmony_ci /* bring ioc to operational state */ 22468c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "Sending mpt_do_ioc_recovery\n", ioc->name); 22478c2ecf20Sopenharmony_ci recovery_state = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, 22488c2ecf20Sopenharmony_ci CAN_SLEEP); 22498c2ecf20Sopenharmony_ci if (recovery_state != 0) 22508c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "pci-resume: Cannot recover, " 22518c2ecf20Sopenharmony_ci "error:[%x]\n", ioc->name, recovery_state); 22528c2ecf20Sopenharmony_ci else 22538c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT 22548c2ecf20Sopenharmony_ci "pci-resume: success\n", ioc->name); 22558c2ecf20Sopenharmony_ci out: 22568c2ecf20Sopenharmony_ci return 0; 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci} 22598c2ecf20Sopenharmony_ci#endif 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_cistatic int 22628c2ecf20Sopenharmony_cimpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase) 22638c2ecf20Sopenharmony_ci{ 22648c2ecf20Sopenharmony_ci if ((MptDriverClass[index] == MPTSPI_DRIVER && 22658c2ecf20Sopenharmony_ci ioc->bus_type != SPI) || 22668c2ecf20Sopenharmony_ci (MptDriverClass[index] == MPTFC_DRIVER && 22678c2ecf20Sopenharmony_ci ioc->bus_type != FC) || 22688c2ecf20Sopenharmony_ci (MptDriverClass[index] == MPTSAS_DRIVER && 22698c2ecf20Sopenharmony_ci ioc->bus_type != SAS)) 22708c2ecf20Sopenharmony_ci /* make sure we only call the relevant reset handler 22718c2ecf20Sopenharmony_ci * for the bus */ 22728c2ecf20Sopenharmony_ci return 0; 22738c2ecf20Sopenharmony_ci return (MptResetHandlers[index])(ioc, reset_phase); 22748c2ecf20Sopenharmony_ci} 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 22778c2ecf20Sopenharmony_ci/** 22788c2ecf20Sopenharmony_ci * mpt_do_ioc_recovery - Initialize or recover MPT adapter. 22798c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 22808c2ecf20Sopenharmony_ci * @reason: Event word / reason 22818c2ecf20Sopenharmony_ci * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. 22828c2ecf20Sopenharmony_ci * 22838c2ecf20Sopenharmony_ci * This routine performs all the steps necessary to bring the IOC 22848c2ecf20Sopenharmony_ci * to a OPERATIONAL state. 22858c2ecf20Sopenharmony_ci * 22868c2ecf20Sopenharmony_ci * This routine also pre-fetches the LAN MAC address of a Fibre Channel 22878c2ecf20Sopenharmony_ci * MPT adapter. 22888c2ecf20Sopenharmony_ci * 22898c2ecf20Sopenharmony_ci * Returns: 22908c2ecf20Sopenharmony_ci * 0 for success 22918c2ecf20Sopenharmony_ci * -1 if failed to get board READY 22928c2ecf20Sopenharmony_ci * -2 if READY but IOCFacts Failed 22938c2ecf20Sopenharmony_ci * -3 if READY but PrimeIOCFifos Failed 22948c2ecf20Sopenharmony_ci * -4 if READY but IOCInit Failed 22958c2ecf20Sopenharmony_ci * -5 if failed to enable_device and/or request_selected_regions 22968c2ecf20Sopenharmony_ci * -6 if failed to upload firmware 22978c2ecf20Sopenharmony_ci */ 22988c2ecf20Sopenharmony_cistatic int 22998c2ecf20Sopenharmony_cimpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) 23008c2ecf20Sopenharmony_ci{ 23018c2ecf20Sopenharmony_ci int hard_reset_done = 0; 23028c2ecf20Sopenharmony_ci int alt_ioc_ready = 0; 23038c2ecf20Sopenharmony_ci int hard; 23048c2ecf20Sopenharmony_ci int rc=0; 23058c2ecf20Sopenharmony_ci int ii; 23068c2ecf20Sopenharmony_ci int ret = 0; 23078c2ecf20Sopenharmony_ci int reset_alt_ioc_active = 0; 23088c2ecf20Sopenharmony_ci int irq_allocated = 0; 23098c2ecf20Sopenharmony_ci u8 *a; 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name, 23128c2ecf20Sopenharmony_ci reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_ci /* Disable reply interrupts (also blocks FreeQ) */ 23158c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); 23168c2ecf20Sopenharmony_ci ioc->active = 0; 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci if (ioc->alt_ioc) { 23198c2ecf20Sopenharmony_ci if (ioc->alt_ioc->active || 23208c2ecf20Sopenharmony_ci reason == MPT_HOSTEVENT_IOC_RECOVER) { 23218c2ecf20Sopenharmony_ci reset_alt_ioc_active = 1; 23228c2ecf20Sopenharmony_ci /* Disable alt-IOC's reply interrupts 23238c2ecf20Sopenharmony_ci * (and FreeQ) for a bit 23248c2ecf20Sopenharmony_ci **/ 23258c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 23268c2ecf20Sopenharmony_ci 0xFFFFFFFF); 23278c2ecf20Sopenharmony_ci ioc->alt_ioc->active = 0; 23288c2ecf20Sopenharmony_ci } 23298c2ecf20Sopenharmony_ci } 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci hard = 1; 23328c2ecf20Sopenharmony_ci if (reason == MPT_HOSTEVENT_IOC_BRINGUP) 23338c2ecf20Sopenharmony_ci hard = 0; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) { 23368c2ecf20Sopenharmony_ci if (hard_reset_done == -4) { 23378c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n", 23388c2ecf20Sopenharmony_ci ioc->name); 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci if (reset_alt_ioc_active && ioc->alt_ioc) { 23418c2ecf20Sopenharmony_ci /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ 23428c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_INFO_FMT 23438c2ecf20Sopenharmony_ci "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name)); 23448c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); 23458c2ecf20Sopenharmony_ci ioc->alt_ioc->active = 1; 23468c2ecf20Sopenharmony_ci } 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci } else { 23498c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 23508c2ecf20Sopenharmony_ci "NOT READY WARNING!\n", ioc->name); 23518c2ecf20Sopenharmony_ci } 23528c2ecf20Sopenharmony_ci ret = -1; 23538c2ecf20Sopenharmony_ci goto out; 23548c2ecf20Sopenharmony_ci } 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_ci /* hard_reset_done = 0 if a soft reset was performed 23578c2ecf20Sopenharmony_ci * and 1 if a hard reset was performed. 23588c2ecf20Sopenharmony_ci */ 23598c2ecf20Sopenharmony_ci if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) { 23608c2ecf20Sopenharmony_ci if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) 23618c2ecf20Sopenharmony_ci alt_ioc_ready = 1; 23628c2ecf20Sopenharmony_ci else 23638c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 23648c2ecf20Sopenharmony_ci ": alt-ioc Not ready WARNING!\n", 23658c2ecf20Sopenharmony_ci ioc->alt_ioc->name); 23668c2ecf20Sopenharmony_ci } 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci for (ii=0; ii<5; ii++) { 23698c2ecf20Sopenharmony_ci /* Get IOC facts! Allow 5 retries */ 23708c2ecf20Sopenharmony_ci if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0) 23718c2ecf20Sopenharmony_ci break; 23728c2ecf20Sopenharmony_ci } 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci if (ii == 5) { 23768c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23778c2ecf20Sopenharmony_ci "Retry IocFacts failed rc=%x\n", ioc->name, rc)); 23788c2ecf20Sopenharmony_ci ret = -2; 23798c2ecf20Sopenharmony_ci } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { 23808c2ecf20Sopenharmony_ci MptDisplayIocCapabilities(ioc); 23818c2ecf20Sopenharmony_ci } 23828c2ecf20Sopenharmony_ci 23838c2ecf20Sopenharmony_ci if (alt_ioc_ready) { 23848c2ecf20Sopenharmony_ci if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { 23858c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23868c2ecf20Sopenharmony_ci "Initial Alt IocFacts failed rc=%x\n", 23878c2ecf20Sopenharmony_ci ioc->name, rc)); 23888c2ecf20Sopenharmony_ci /* Retry - alt IOC was initialized once 23898c2ecf20Sopenharmony_ci */ 23908c2ecf20Sopenharmony_ci rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); 23918c2ecf20Sopenharmony_ci } 23928c2ecf20Sopenharmony_ci if (rc) { 23938c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 23948c2ecf20Sopenharmony_ci "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); 23958c2ecf20Sopenharmony_ci alt_ioc_ready = 0; 23968c2ecf20Sopenharmony_ci reset_alt_ioc_active = 0; 23978c2ecf20Sopenharmony_ci } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { 23988c2ecf20Sopenharmony_ci MptDisplayIocCapabilities(ioc->alt_ioc); 23998c2ecf20Sopenharmony_ci } 24008c2ecf20Sopenharmony_ci } 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) && 24038c2ecf20Sopenharmony_ci (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) { 24048c2ecf20Sopenharmony_ci pci_release_selected_regions(ioc->pcidev, ioc->bars); 24058c2ecf20Sopenharmony_ci ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM | 24068c2ecf20Sopenharmony_ci IORESOURCE_IO); 24078c2ecf20Sopenharmony_ci if (pci_enable_device(ioc->pcidev)) 24088c2ecf20Sopenharmony_ci return -5; 24098c2ecf20Sopenharmony_ci if (pci_request_selected_regions(ioc->pcidev, ioc->bars, 24108c2ecf20Sopenharmony_ci "mpt")) 24118c2ecf20Sopenharmony_ci return -5; 24128c2ecf20Sopenharmony_ci } 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci /* 24158c2ecf20Sopenharmony_ci * Device is reset now. It must have de-asserted the interrupt line 24168c2ecf20Sopenharmony_ci * (if it was asserted) and it should be safe to register for the 24178c2ecf20Sopenharmony_ci * interrupt now. 24188c2ecf20Sopenharmony_ci */ 24198c2ecf20Sopenharmony_ci if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { 24208c2ecf20Sopenharmony_ci ioc->pci_irq = -1; 24218c2ecf20Sopenharmony_ci if (ioc->pcidev->irq) { 24228c2ecf20Sopenharmony_ci if (ioc->msi_enable && !pci_enable_msi(ioc->pcidev)) 24238c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", 24248c2ecf20Sopenharmony_ci ioc->name); 24258c2ecf20Sopenharmony_ci else 24268c2ecf20Sopenharmony_ci ioc->msi_enable = 0; 24278c2ecf20Sopenharmony_ci rc = request_irq(ioc->pcidev->irq, mpt_interrupt, 24288c2ecf20Sopenharmony_ci IRQF_SHARED, ioc->name, ioc); 24298c2ecf20Sopenharmony_ci if (rc < 0) { 24308c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Unable to allocate " 24318c2ecf20Sopenharmony_ci "interrupt %d!\n", 24328c2ecf20Sopenharmony_ci ioc->name, ioc->pcidev->irq); 24338c2ecf20Sopenharmony_ci if (ioc->msi_enable) 24348c2ecf20Sopenharmony_ci pci_disable_msi(ioc->pcidev); 24358c2ecf20Sopenharmony_ci ret = -EBUSY; 24368c2ecf20Sopenharmony_ci goto out; 24378c2ecf20Sopenharmony_ci } 24388c2ecf20Sopenharmony_ci irq_allocated = 1; 24398c2ecf20Sopenharmony_ci ioc->pci_irq = ioc->pcidev->irq; 24408c2ecf20Sopenharmony_ci pci_set_master(ioc->pcidev); /* ?? */ 24418c2ecf20Sopenharmony_ci pci_set_drvdata(ioc->pcidev, ioc); 24428c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 24438c2ecf20Sopenharmony_ci "installed at interrupt %d\n", ioc->name, 24448c2ecf20Sopenharmony_ci ioc->pcidev->irq)); 24458c2ecf20Sopenharmony_ci } 24468c2ecf20Sopenharmony_ci } 24478c2ecf20Sopenharmony_ci 24488c2ecf20Sopenharmony_ci /* Prime reply & request queues! 24498c2ecf20Sopenharmony_ci * (mucho alloc's) Must be done prior to 24508c2ecf20Sopenharmony_ci * init as upper addresses are needed for init. 24518c2ecf20Sopenharmony_ci * If fails, continue with alt-ioc processing 24528c2ecf20Sopenharmony_ci */ 24538c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "PrimeIocFifos\n", 24548c2ecf20Sopenharmony_ci ioc->name)); 24558c2ecf20Sopenharmony_ci if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0)) 24568c2ecf20Sopenharmony_ci ret = -3; 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci /* May need to check/upload firmware & data here! 24598c2ecf20Sopenharmony_ci * If fails, continue with alt-ioc processing 24608c2ecf20Sopenharmony_ci */ 24618c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "SendIocInit\n", 24628c2ecf20Sopenharmony_ci ioc->name)); 24638c2ecf20Sopenharmony_ci if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0)) 24648c2ecf20Sopenharmony_ci ret = -4; 24658c2ecf20Sopenharmony_ci// NEW! 24668c2ecf20Sopenharmony_ci if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { 24678c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 24688c2ecf20Sopenharmony_ci ": alt-ioc (%d) FIFO mgmt alloc WARNING!\n", 24698c2ecf20Sopenharmony_ci ioc->alt_ioc->name, rc); 24708c2ecf20Sopenharmony_ci alt_ioc_ready = 0; 24718c2ecf20Sopenharmony_ci reset_alt_ioc_active = 0; 24728c2ecf20Sopenharmony_ci } 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci if (alt_ioc_ready) { 24758c2ecf20Sopenharmony_ci if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { 24768c2ecf20Sopenharmony_ci alt_ioc_ready = 0; 24778c2ecf20Sopenharmony_ci reset_alt_ioc_active = 0; 24788c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 24798c2ecf20Sopenharmony_ci ": alt-ioc: (%d) init failure WARNING!\n", 24808c2ecf20Sopenharmony_ci ioc->alt_ioc->name, rc); 24818c2ecf20Sopenharmony_ci } 24828c2ecf20Sopenharmony_ci } 24838c2ecf20Sopenharmony_ci 24848c2ecf20Sopenharmony_ci if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ 24858c2ecf20Sopenharmony_ci if (ioc->upload_fw) { 24868c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 24878c2ecf20Sopenharmony_ci "firmware upload required!\n", ioc->name)); 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_ci /* Controller is not operational, cannot do upload 24908c2ecf20Sopenharmony_ci */ 24918c2ecf20Sopenharmony_ci if (ret == 0) { 24928c2ecf20Sopenharmony_ci rc = mpt_do_upload(ioc, sleepFlag); 24938c2ecf20Sopenharmony_ci if (rc == 0) { 24948c2ecf20Sopenharmony_ci if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { 24958c2ecf20Sopenharmony_ci /* 24968c2ecf20Sopenharmony_ci * Maintain only one pointer to FW memory 24978c2ecf20Sopenharmony_ci * so there will not be two attempt to 24988c2ecf20Sopenharmony_ci * downloadboot onboard dual function 24998c2ecf20Sopenharmony_ci * chips (mpt_adapter_disable, 25008c2ecf20Sopenharmony_ci * mpt_diag_reset) 25018c2ecf20Sopenharmony_ci */ 25028c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 25038c2ecf20Sopenharmony_ci "mpt_upload: alt_%s has cached_fw=%p \n", 25048c2ecf20Sopenharmony_ci ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); 25058c2ecf20Sopenharmony_ci ioc->cached_fw = NULL; 25068c2ecf20Sopenharmony_ci } 25078c2ecf20Sopenharmony_ci } else { 25088c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 25098c2ecf20Sopenharmony_ci "firmware upload failure!\n", ioc->name); 25108c2ecf20Sopenharmony_ci ret = -6; 25118c2ecf20Sopenharmony_ci } 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci } 25148c2ecf20Sopenharmony_ci } 25158c2ecf20Sopenharmony_ci 25168c2ecf20Sopenharmony_ci /* Enable MPT base driver management of EventNotification 25178c2ecf20Sopenharmony_ci * and EventAck handling. 25188c2ecf20Sopenharmony_ci */ 25198c2ecf20Sopenharmony_ci if ((ret == 0) && (!ioc->facts.EventState)) { 25208c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 25218c2ecf20Sopenharmony_ci "SendEventNotification\n", 25228c2ecf20Sopenharmony_ci ioc->name)); 25238c2ecf20Sopenharmony_ci ret = SendEventNotification(ioc, 1, sleepFlag); /* 1=Enable */ 25248c2ecf20Sopenharmony_ci } 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState) 25278c2ecf20Sopenharmony_ci rc = SendEventNotification(ioc->alt_ioc, 1, sleepFlag); 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci if (ret == 0) { 25308c2ecf20Sopenharmony_ci /* Enable! (reply interrupt) */ 25318c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); 25328c2ecf20Sopenharmony_ci ioc->active = 1; 25338c2ecf20Sopenharmony_ci } 25348c2ecf20Sopenharmony_ci if (rc == 0) { /* alt ioc */ 25358c2ecf20Sopenharmony_ci if (reset_alt_ioc_active && ioc->alt_ioc) { 25368c2ecf20Sopenharmony_ci /* (re)Enable alt-IOC! (reply interrupt) */ 25378c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "alt-ioc" 25388c2ecf20Sopenharmony_ci "reply irq re-enabled\n", 25398c2ecf20Sopenharmony_ci ioc->alt_ioc->name)); 25408c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 25418c2ecf20Sopenharmony_ci MPI_HIM_DIM); 25428c2ecf20Sopenharmony_ci ioc->alt_ioc->active = 1; 25438c2ecf20Sopenharmony_ci } 25448c2ecf20Sopenharmony_ci } 25458c2ecf20Sopenharmony_ci 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci /* Add additional "reason" check before call to GetLanConfigPages 25488c2ecf20Sopenharmony_ci * (combined with GetIoUnitPage2 call). This prevents a somewhat 25498c2ecf20Sopenharmony_ci * recursive scenario; GetLanConfigPages times out, timer expired 25508c2ecf20Sopenharmony_ci * routine calls HardResetHandler, which calls into here again, 25518c2ecf20Sopenharmony_ci * and we try GetLanConfigPages again... 25528c2ecf20Sopenharmony_ci */ 25538c2ecf20Sopenharmony_ci if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci /* 25568c2ecf20Sopenharmony_ci * Initialize link list for inactive raid volumes. 25578c2ecf20Sopenharmony_ci */ 25588c2ecf20Sopenharmony_ci mutex_init(&ioc->raid_data.inactive_list_mutex); 25598c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ioc->raid_data.inactive_list); 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_ci switch (ioc->bus_type) { 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci case SAS: 25648c2ecf20Sopenharmony_ci /* clear persistency table */ 25658c2ecf20Sopenharmony_ci if(ioc->facts.IOCExceptions & 25668c2ecf20Sopenharmony_ci MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { 25678c2ecf20Sopenharmony_ci ret = mptbase_sas_persist_operation(ioc, 25688c2ecf20Sopenharmony_ci MPI_SAS_OP_CLEAR_NOT_PRESENT); 25698c2ecf20Sopenharmony_ci if(ret != 0) 25708c2ecf20Sopenharmony_ci goto out; 25718c2ecf20Sopenharmony_ci } 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci /* Find IM volumes 25748c2ecf20Sopenharmony_ci */ 25758c2ecf20Sopenharmony_ci mpt_findImVolumes(ioc); 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci /* Check, and possibly reset, the coalescing value 25788c2ecf20Sopenharmony_ci */ 25798c2ecf20Sopenharmony_ci mpt_read_ioc_pg_1(ioc); 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci break; 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci case FC: 25848c2ecf20Sopenharmony_ci if ((ioc->pfacts[0].ProtocolFlags & 25858c2ecf20Sopenharmony_ci MPI_PORTFACTS_PROTOCOL_LAN) && 25868c2ecf20Sopenharmony_ci (ioc->lan_cnfg_page0.Header.PageLength == 0)) { 25878c2ecf20Sopenharmony_ci /* 25888c2ecf20Sopenharmony_ci * Pre-fetch the ports LAN MAC address! 25898c2ecf20Sopenharmony_ci * (LANPage1_t stuff) 25908c2ecf20Sopenharmony_ci */ 25918c2ecf20Sopenharmony_ci (void) GetLanConfigPages(ioc); 25928c2ecf20Sopenharmony_ci a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; 25938c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 25948c2ecf20Sopenharmony_ci "LanAddr = %pMR\n", ioc->name, a)); 25958c2ecf20Sopenharmony_ci } 25968c2ecf20Sopenharmony_ci break; 25978c2ecf20Sopenharmony_ci 25988c2ecf20Sopenharmony_ci case SPI: 25998c2ecf20Sopenharmony_ci /* Get NVRAM and adapter maximums from SPP 0 and 2 26008c2ecf20Sopenharmony_ci */ 26018c2ecf20Sopenharmony_ci mpt_GetScsiPortSettings(ioc, 0); 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci /* Get version and length of SDP 1 26048c2ecf20Sopenharmony_ci */ 26058c2ecf20Sopenharmony_ci mpt_readScsiDevicePageHeaders(ioc, 0); 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci /* Find IM volumes 26088c2ecf20Sopenharmony_ci */ 26098c2ecf20Sopenharmony_ci if (ioc->facts.MsgVersion >= MPI_VERSION_01_02) 26108c2ecf20Sopenharmony_ci mpt_findImVolumes(ioc); 26118c2ecf20Sopenharmony_ci 26128c2ecf20Sopenharmony_ci /* Check, and possibly reset, the coalescing value 26138c2ecf20Sopenharmony_ci */ 26148c2ecf20Sopenharmony_ci mpt_read_ioc_pg_1(ioc); 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_ci mpt_read_ioc_pg_4(ioc); 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci break; 26198c2ecf20Sopenharmony_ci } 26208c2ecf20Sopenharmony_ci 26218c2ecf20Sopenharmony_ci GetIoUnitPage2(ioc); 26228c2ecf20Sopenharmony_ci mpt_get_manufacturing_pg_0(ioc); 26238c2ecf20Sopenharmony_ci } 26248c2ecf20Sopenharmony_ci 26258c2ecf20Sopenharmony_ci out: 26268c2ecf20Sopenharmony_ci if ((ret != 0) && irq_allocated) { 26278c2ecf20Sopenharmony_ci free_irq(ioc->pci_irq, ioc); 26288c2ecf20Sopenharmony_ci if (ioc->msi_enable) 26298c2ecf20Sopenharmony_ci pci_disable_msi(ioc->pcidev); 26308c2ecf20Sopenharmony_ci } 26318c2ecf20Sopenharmony_ci return ret; 26328c2ecf20Sopenharmony_ci} 26338c2ecf20Sopenharmony_ci 26348c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26358c2ecf20Sopenharmony_ci/** 26368c2ecf20Sopenharmony_ci * mpt_detect_bound_ports - Search for matching PCI bus/dev_function 26378c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 26388c2ecf20Sopenharmony_ci * @pdev: Pointer to (struct pci_dev) structure 26398c2ecf20Sopenharmony_ci * 26408c2ecf20Sopenharmony_ci * Search for PCI bus/dev_function which matches 26418c2ecf20Sopenharmony_ci * PCI bus/dev_function (+/-1) for newly discovered 929, 26428c2ecf20Sopenharmony_ci * 929X, 1030 or 1035. 26438c2ecf20Sopenharmony_ci * 26448c2ecf20Sopenharmony_ci * If match on PCI dev_function +/-1 is found, bind the two MPT adapters 26458c2ecf20Sopenharmony_ci * using alt_ioc pointer fields in their %MPT_ADAPTER structures. 26468c2ecf20Sopenharmony_ci */ 26478c2ecf20Sopenharmony_cistatic void 26488c2ecf20Sopenharmony_cimpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) 26498c2ecf20Sopenharmony_ci{ 26508c2ecf20Sopenharmony_ci struct pci_dev *peer=NULL; 26518c2ecf20Sopenharmony_ci unsigned int slot = PCI_SLOT(pdev->devfn); 26528c2ecf20Sopenharmony_ci unsigned int func = PCI_FUNC(pdev->devfn); 26538c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc_srch; 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x," 26568c2ecf20Sopenharmony_ci " searching for devfn match on %x or %x\n", 26578c2ecf20Sopenharmony_ci ioc->name, pci_name(pdev), pdev->bus->number, 26588c2ecf20Sopenharmony_ci pdev->devfn, func-1, func+1)); 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1)); 26618c2ecf20Sopenharmony_ci if (!peer) { 26628c2ecf20Sopenharmony_ci peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1)); 26638c2ecf20Sopenharmony_ci if (!peer) 26648c2ecf20Sopenharmony_ci return; 26658c2ecf20Sopenharmony_ci } 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci list_for_each_entry(ioc_srch, &ioc_list, list) { 26688c2ecf20Sopenharmony_ci struct pci_dev *_pcidev = ioc_srch->pcidev; 26698c2ecf20Sopenharmony_ci if (_pcidev == peer) { 26708c2ecf20Sopenharmony_ci /* Paranoia checks */ 26718c2ecf20Sopenharmony_ci if (ioc->alt_ioc != NULL) { 26728c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 26738c2ecf20Sopenharmony_ci "Oops, already bound (%s <==> %s)!\n", 26748c2ecf20Sopenharmony_ci ioc->name, ioc->name, ioc->alt_ioc->name); 26758c2ecf20Sopenharmony_ci break; 26768c2ecf20Sopenharmony_ci } else if (ioc_srch->alt_ioc != NULL) { 26778c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 26788c2ecf20Sopenharmony_ci "Oops, already bound (%s <==> %s)!\n", 26798c2ecf20Sopenharmony_ci ioc_srch->name, ioc_srch->name, 26808c2ecf20Sopenharmony_ci ioc_srch->alt_ioc->name); 26818c2ecf20Sopenharmony_ci break; 26828c2ecf20Sopenharmony_ci } 26838c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 26848c2ecf20Sopenharmony_ci "FOUND! binding %s <==> %s\n", 26858c2ecf20Sopenharmony_ci ioc->name, ioc->name, ioc_srch->name)); 26868c2ecf20Sopenharmony_ci ioc_srch->alt_ioc = ioc; 26878c2ecf20Sopenharmony_ci ioc->alt_ioc = ioc_srch; 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci } 26908c2ecf20Sopenharmony_ci pci_dev_put(peer); 26918c2ecf20Sopenharmony_ci} 26928c2ecf20Sopenharmony_ci 26938c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 26948c2ecf20Sopenharmony_ci/** 26958c2ecf20Sopenharmony_ci * mpt_adapter_disable - Disable misbehaving MPT adapter. 26968c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 26978c2ecf20Sopenharmony_ci */ 26988c2ecf20Sopenharmony_cistatic void 26998c2ecf20Sopenharmony_cimpt_adapter_disable(MPT_ADAPTER *ioc) 27008c2ecf20Sopenharmony_ci{ 27018c2ecf20Sopenharmony_ci int sz; 27028c2ecf20Sopenharmony_ci int ret; 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ci if (ioc->cached_fw != NULL) { 27058c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 27068c2ecf20Sopenharmony_ci "%s: Pushing FW onto adapter\n", __func__, ioc->name)); 27078c2ecf20Sopenharmony_ci if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *) 27088c2ecf20Sopenharmony_ci ioc->cached_fw, CAN_SLEEP)) < 0) { 27098c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 27108c2ecf20Sopenharmony_ci ": firmware downloadboot failure (%d)!\n", 27118c2ecf20Sopenharmony_ci ioc->name, ret); 27128c2ecf20Sopenharmony_ci } 27138c2ecf20Sopenharmony_ci } 27148c2ecf20Sopenharmony_ci 27158c2ecf20Sopenharmony_ci /* 27168c2ecf20Sopenharmony_ci * Put the controller into ready state (if its not already) 27178c2ecf20Sopenharmony_ci */ 27188c2ecf20Sopenharmony_ci if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) { 27198c2ecf20Sopenharmony_ci if (!SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, 27208c2ecf20Sopenharmony_ci CAN_SLEEP)) { 27218c2ecf20Sopenharmony_ci if (mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_READY) 27228c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "%s: IOC msg unit " 27238c2ecf20Sopenharmony_ci "reset failed to put ioc in ready state!\n", 27248c2ecf20Sopenharmony_ci ioc->name, __func__); 27258c2ecf20Sopenharmony_ci } else 27268c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "%s: IOC msg unit reset " 27278c2ecf20Sopenharmony_ci "failed!\n", ioc->name, __func__); 27288c2ecf20Sopenharmony_ci } 27298c2ecf20Sopenharmony_ci 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci /* Disable adapter interrupts! */ 27328c2ecf20Sopenharmony_ci synchronize_irq(ioc->pcidev->irq); 27338c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); 27348c2ecf20Sopenharmony_ci ioc->active = 0; 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci /* Clear any lingering interrupt */ 27378c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 27388c2ecf20Sopenharmony_ci CHIPREG_READ32(&ioc->chip->IntStatus); 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci if (ioc->alloc != NULL) { 27418c2ecf20Sopenharmony_ci sz = ioc->alloc_sz; 27428c2ecf20Sopenharmony_ci dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n", 27438c2ecf20Sopenharmony_ci ioc->name, ioc->alloc, ioc->alloc_sz)); 27448c2ecf20Sopenharmony_ci dma_free_coherent(&ioc->pcidev->dev, sz, ioc->alloc, 27458c2ecf20Sopenharmony_ci ioc->alloc_dma); 27468c2ecf20Sopenharmony_ci ioc->reply_frames = NULL; 27478c2ecf20Sopenharmony_ci ioc->req_frames = NULL; 27488c2ecf20Sopenharmony_ci ioc->alloc = NULL; 27498c2ecf20Sopenharmony_ci ioc->alloc_total -= sz; 27508c2ecf20Sopenharmony_ci } 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci if (ioc->sense_buf_pool != NULL) { 27538c2ecf20Sopenharmony_ci sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); 27548c2ecf20Sopenharmony_ci dma_free_coherent(&ioc->pcidev->dev, sz, ioc->sense_buf_pool, 27558c2ecf20Sopenharmony_ci ioc->sense_buf_pool_dma); 27568c2ecf20Sopenharmony_ci ioc->sense_buf_pool = NULL; 27578c2ecf20Sopenharmony_ci ioc->alloc_total -= sz; 27588c2ecf20Sopenharmony_ci } 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ci if (ioc->events != NULL){ 27618c2ecf20Sopenharmony_ci sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); 27628c2ecf20Sopenharmony_ci kfree(ioc->events); 27638c2ecf20Sopenharmony_ci ioc->events = NULL; 27648c2ecf20Sopenharmony_ci ioc->alloc_total -= sz; 27658c2ecf20Sopenharmony_ci } 27668c2ecf20Sopenharmony_ci 27678c2ecf20Sopenharmony_ci mpt_free_fw_memory(ioc); 27688c2ecf20Sopenharmony_ci 27698c2ecf20Sopenharmony_ci kfree(ioc->spi_data.nvram); 27708c2ecf20Sopenharmony_ci mpt_inactive_raid_list_free(ioc); 27718c2ecf20Sopenharmony_ci kfree(ioc->raid_data.pIocPg2); 27728c2ecf20Sopenharmony_ci kfree(ioc->raid_data.pIocPg3); 27738c2ecf20Sopenharmony_ci ioc->spi_data.nvram = NULL; 27748c2ecf20Sopenharmony_ci ioc->raid_data.pIocPg3 = NULL; 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci if (ioc->spi_data.pIocPg4 != NULL) { 27778c2ecf20Sopenharmony_ci sz = ioc->spi_data.IocPg4Sz; 27788c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, sz, 27798c2ecf20Sopenharmony_ci ioc->spi_data.pIocPg4, 27808c2ecf20Sopenharmony_ci ioc->spi_data.IocPg4_dma); 27818c2ecf20Sopenharmony_ci ioc->spi_data.pIocPg4 = NULL; 27828c2ecf20Sopenharmony_ci ioc->alloc_total -= sz; 27838c2ecf20Sopenharmony_ci } 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci if (ioc->ReqToChain != NULL) { 27868c2ecf20Sopenharmony_ci kfree(ioc->ReqToChain); 27878c2ecf20Sopenharmony_ci kfree(ioc->RequestNB); 27888c2ecf20Sopenharmony_ci ioc->ReqToChain = NULL; 27898c2ecf20Sopenharmony_ci } 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci kfree(ioc->ChainToChain); 27928c2ecf20Sopenharmony_ci ioc->ChainToChain = NULL; 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci if (ioc->HostPageBuffer != NULL) { 27958c2ecf20Sopenharmony_ci if((ret = mpt_host_page_access_control(ioc, 27968c2ecf20Sopenharmony_ci MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { 27978c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 27988c2ecf20Sopenharmony_ci ": %s: host page buffers free failed (%d)!\n", 27998c2ecf20Sopenharmony_ci ioc->name, __func__, ret); 28008c2ecf20Sopenharmony_ci } 28018c2ecf20Sopenharmony_ci dexitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 28028c2ecf20Sopenharmony_ci "HostPageBuffer free @ %p, sz=%d bytes\n", 28038c2ecf20Sopenharmony_ci ioc->name, ioc->HostPageBuffer, 28048c2ecf20Sopenharmony_ci ioc->HostPageBuffer_sz)); 28058c2ecf20Sopenharmony_ci dma_free_coherent(&ioc->pcidev->dev, ioc->HostPageBuffer_sz, 28068c2ecf20Sopenharmony_ci ioc->HostPageBuffer, ioc->HostPageBuffer_dma); 28078c2ecf20Sopenharmony_ci ioc->HostPageBuffer = NULL; 28088c2ecf20Sopenharmony_ci ioc->HostPageBuffer_sz = 0; 28098c2ecf20Sopenharmony_ci ioc->alloc_total -= ioc->HostPageBuffer_sz; 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci pci_set_drvdata(ioc->pcidev, NULL); 28138c2ecf20Sopenharmony_ci} 28148c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 28158c2ecf20Sopenharmony_ci/** 28168c2ecf20Sopenharmony_ci * mpt_adapter_dispose - Free all resources associated with an MPT adapter 28178c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 28188c2ecf20Sopenharmony_ci * 28198c2ecf20Sopenharmony_ci * This routine unregisters h/w resources and frees all alloc'd memory 28208c2ecf20Sopenharmony_ci * associated with a MPT adapter structure. 28218c2ecf20Sopenharmony_ci */ 28228c2ecf20Sopenharmony_cistatic void 28238c2ecf20Sopenharmony_cimpt_adapter_dispose(MPT_ADAPTER *ioc) 28248c2ecf20Sopenharmony_ci{ 28258c2ecf20Sopenharmony_ci int sz_first, sz_last; 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_ci if (ioc == NULL) 28288c2ecf20Sopenharmony_ci return; 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci sz_first = ioc->alloc_total; 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci mpt_adapter_disable(ioc); 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci if (ioc->pci_irq != -1) { 28358c2ecf20Sopenharmony_ci free_irq(ioc->pci_irq, ioc); 28368c2ecf20Sopenharmony_ci if (ioc->msi_enable) 28378c2ecf20Sopenharmony_ci pci_disable_msi(ioc->pcidev); 28388c2ecf20Sopenharmony_ci ioc->pci_irq = -1; 28398c2ecf20Sopenharmony_ci } 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci if (ioc->memmap != NULL) { 28428c2ecf20Sopenharmony_ci iounmap(ioc->memmap); 28438c2ecf20Sopenharmony_ci ioc->memmap = NULL; 28448c2ecf20Sopenharmony_ci } 28458c2ecf20Sopenharmony_ci 28468c2ecf20Sopenharmony_ci pci_disable_device(ioc->pcidev); 28478c2ecf20Sopenharmony_ci pci_release_selected_regions(ioc->pcidev, ioc->bars); 28488c2ecf20Sopenharmony_ci 28498c2ecf20Sopenharmony_ci /* Zap the adapter lookup ptr! */ 28508c2ecf20Sopenharmony_ci list_del(&ioc->list); 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci sz_last = ioc->alloc_total; 28538c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n", 28548c2ecf20Sopenharmony_ci ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 28578c2ecf20Sopenharmony_ci ioc->alt_ioc->alt_ioc = NULL; 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_ci kfree(ioc); 28608c2ecf20Sopenharmony_ci} 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 28638c2ecf20Sopenharmony_ci/** 28648c2ecf20Sopenharmony_ci * MptDisplayIocCapabilities - Disply IOC's capabilities. 28658c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT adapter structure 28668c2ecf20Sopenharmony_ci */ 28678c2ecf20Sopenharmony_cistatic void 28688c2ecf20Sopenharmony_ciMptDisplayIocCapabilities(MPT_ADAPTER *ioc) 28698c2ecf20Sopenharmony_ci{ 28708c2ecf20Sopenharmony_ci int i = 0; 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci printk(KERN_INFO "%s: ", ioc->name); 28738c2ecf20Sopenharmony_ci if (ioc->prod_name) 28748c2ecf20Sopenharmony_ci pr_cont("%s: ", ioc->prod_name); 28758c2ecf20Sopenharmony_ci pr_cont("Capabilities={"); 28768c2ecf20Sopenharmony_ci 28778c2ecf20Sopenharmony_ci if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) { 28788c2ecf20Sopenharmony_ci pr_cont("Initiator"); 28798c2ecf20Sopenharmony_ci i++; 28808c2ecf20Sopenharmony_ci } 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { 28838c2ecf20Sopenharmony_ci pr_cont("%sTarget", i ? "," : ""); 28848c2ecf20Sopenharmony_ci i++; 28858c2ecf20Sopenharmony_ci } 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { 28888c2ecf20Sopenharmony_ci pr_cont("%sLAN", i ? "," : ""); 28898c2ecf20Sopenharmony_ci i++; 28908c2ecf20Sopenharmony_ci } 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_ci#if 0 28938c2ecf20Sopenharmony_ci /* 28948c2ecf20Sopenharmony_ci * This would probably evoke more questions than it's worth 28958c2ecf20Sopenharmony_ci */ 28968c2ecf20Sopenharmony_ci if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) { 28978c2ecf20Sopenharmony_ci pr_cont("%sLogBusAddr", i ? "," : ""); 28988c2ecf20Sopenharmony_ci i++; 28998c2ecf20Sopenharmony_ci } 29008c2ecf20Sopenharmony_ci#endif 29018c2ecf20Sopenharmony_ci 29028c2ecf20Sopenharmony_ci pr_cont("}\n"); 29038c2ecf20Sopenharmony_ci} 29048c2ecf20Sopenharmony_ci 29058c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 29068c2ecf20Sopenharmony_ci/** 29078c2ecf20Sopenharmony_ci * MakeIocReady - Get IOC to a READY state, using KickStart if needed. 29088c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 29098c2ecf20Sopenharmony_ci * @force: Force hard KickStart of IOC 29108c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 29118c2ecf20Sopenharmony_ci * 29128c2ecf20Sopenharmony_ci * Returns: 29138c2ecf20Sopenharmony_ci * 1 - DIAG reset and READY 29148c2ecf20Sopenharmony_ci * 0 - READY initially OR soft reset and READY 29158c2ecf20Sopenharmony_ci * -1 - Any failure on KickStart 29168c2ecf20Sopenharmony_ci * -2 - Msg Unit Reset Failed 29178c2ecf20Sopenharmony_ci * -3 - IO Unit Reset Failed 29188c2ecf20Sopenharmony_ci * -4 - IOC owned by a PEER 29198c2ecf20Sopenharmony_ci */ 29208c2ecf20Sopenharmony_cistatic int 29218c2ecf20Sopenharmony_ciMakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) 29228c2ecf20Sopenharmony_ci{ 29238c2ecf20Sopenharmony_ci u32 ioc_state; 29248c2ecf20Sopenharmony_ci int statefault = 0; 29258c2ecf20Sopenharmony_ci int cntdn; 29268c2ecf20Sopenharmony_ci int hard_reset_done = 0; 29278c2ecf20Sopenharmony_ci int r; 29288c2ecf20Sopenharmony_ci int ii; 29298c2ecf20Sopenharmony_ci int whoinit; 29308c2ecf20Sopenharmony_ci 29318c2ecf20Sopenharmony_ci /* Get current [raw] IOC state */ 29328c2ecf20Sopenharmony_ci ioc_state = mpt_GetIocState(ioc, 0); 29338c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state)); 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci /* 29368c2ecf20Sopenharmony_ci * Check to see if IOC got left/stuck in doorbell handshake 29378c2ecf20Sopenharmony_ci * grip of death. If so, hard reset the IOC. 29388c2ecf20Sopenharmony_ci */ 29398c2ecf20Sopenharmony_ci if (ioc_state & MPI_DOORBELL_ACTIVE) { 29408c2ecf20Sopenharmony_ci statefault = 1; 29418c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "Unexpected doorbell active!\n", 29428c2ecf20Sopenharmony_ci ioc->name); 29438c2ecf20Sopenharmony_ci } 29448c2ecf20Sopenharmony_ci 29458c2ecf20Sopenharmony_ci /* Is it already READY? */ 29468c2ecf20Sopenharmony_ci if (!statefault && 29478c2ecf20Sopenharmony_ci ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_READY)) { 29488c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 29498c2ecf20Sopenharmony_ci "IOC is in READY state\n", ioc->name)); 29508c2ecf20Sopenharmony_ci return 0; 29518c2ecf20Sopenharmony_ci } 29528c2ecf20Sopenharmony_ci 29538c2ecf20Sopenharmony_ci /* 29548c2ecf20Sopenharmony_ci * Check to see if IOC is in FAULT state. 29558c2ecf20Sopenharmony_ci */ 29568c2ecf20Sopenharmony_ci if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { 29578c2ecf20Sopenharmony_ci statefault = 2; 29588c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n", 29598c2ecf20Sopenharmony_ci ioc->name); 29608c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n", 29618c2ecf20Sopenharmony_ci ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK); 29628c2ecf20Sopenharmony_ci } 29638c2ecf20Sopenharmony_ci 29648c2ecf20Sopenharmony_ci /* 29658c2ecf20Sopenharmony_ci * Hmmm... Did it get left operational? 29668c2ecf20Sopenharmony_ci */ 29678c2ecf20Sopenharmony_ci if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) { 29688c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC operational unexpected\n", 29698c2ecf20Sopenharmony_ci ioc->name)); 29708c2ecf20Sopenharmony_ci 29718c2ecf20Sopenharmony_ci /* Check WhoInit. 29728c2ecf20Sopenharmony_ci * If PCI Peer, exit. 29738c2ecf20Sopenharmony_ci * Else, if no fault conditions are present, issue a MessageUnitReset 29748c2ecf20Sopenharmony_ci * Else, fall through to KickStart case 29758c2ecf20Sopenharmony_ci */ 29768c2ecf20Sopenharmony_ci whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT; 29778c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT 29788c2ecf20Sopenharmony_ci "whoinit 0x%x statefault %d force %d\n", 29798c2ecf20Sopenharmony_ci ioc->name, whoinit, statefault, force)); 29808c2ecf20Sopenharmony_ci if (whoinit == MPI_WHOINIT_PCI_PEER) 29818c2ecf20Sopenharmony_ci return -4; 29828c2ecf20Sopenharmony_ci else { 29838c2ecf20Sopenharmony_ci if ((statefault == 0 ) && (force == 0)) { 29848c2ecf20Sopenharmony_ci if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0) 29858c2ecf20Sopenharmony_ci return 0; 29868c2ecf20Sopenharmony_ci } 29878c2ecf20Sopenharmony_ci statefault = 3; 29888c2ecf20Sopenharmony_ci } 29898c2ecf20Sopenharmony_ci } 29908c2ecf20Sopenharmony_ci 29918c2ecf20Sopenharmony_ci hard_reset_done = KickStart(ioc, statefault||force, sleepFlag); 29928c2ecf20Sopenharmony_ci if (hard_reset_done < 0) 29938c2ecf20Sopenharmony_ci return -1; 29948c2ecf20Sopenharmony_ci 29958c2ecf20Sopenharmony_ci /* 29968c2ecf20Sopenharmony_ci * Loop here waiting for IOC to come READY. 29978c2ecf20Sopenharmony_ci */ 29988c2ecf20Sopenharmony_ci ii = 0; 29998c2ecf20Sopenharmony_ci cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */ 30008c2ecf20Sopenharmony_ci 30018c2ecf20Sopenharmony_ci while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { 30028c2ecf20Sopenharmony_ci if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { 30038c2ecf20Sopenharmony_ci /* 30048c2ecf20Sopenharmony_ci * BIOS or previous driver load left IOC in OP state. 30058c2ecf20Sopenharmony_ci * Reset messaging FIFOs. 30068c2ecf20Sopenharmony_ci */ 30078c2ecf20Sopenharmony_ci if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) != 0) { 30088c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "IOC msg unit reset failed!\n", ioc->name); 30098c2ecf20Sopenharmony_ci return -2; 30108c2ecf20Sopenharmony_ci } 30118c2ecf20Sopenharmony_ci } else if (ioc_state == MPI_IOC_STATE_RESET) { 30128c2ecf20Sopenharmony_ci /* 30138c2ecf20Sopenharmony_ci * Something is wrong. Try to get IOC back 30148c2ecf20Sopenharmony_ci * to a known state. 30158c2ecf20Sopenharmony_ci */ 30168c2ecf20Sopenharmony_ci if ((r = SendIocReset(ioc, MPI_FUNCTION_IO_UNIT_RESET, sleepFlag)) != 0) { 30178c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "IO unit reset failed!\n", ioc->name); 30188c2ecf20Sopenharmony_ci return -3; 30198c2ecf20Sopenharmony_ci } 30208c2ecf20Sopenharmony_ci } 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_ci ii++; cntdn--; 30238c2ecf20Sopenharmony_ci if (!cntdn) { 30248c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 30258c2ecf20Sopenharmony_ci "Wait IOC_READY state (0x%x) timeout(%d)!\n", 30268c2ecf20Sopenharmony_ci ioc->name, ioc_state, (int)((ii+5)/HZ)); 30278c2ecf20Sopenharmony_ci return -ETIME; 30288c2ecf20Sopenharmony_ci } 30298c2ecf20Sopenharmony_ci 30308c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 30318c2ecf20Sopenharmony_ci msleep(1); 30328c2ecf20Sopenharmony_ci } else { 30338c2ecf20Sopenharmony_ci mdelay (1); /* 1 msec delay */ 30348c2ecf20Sopenharmony_ci } 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci } 30378c2ecf20Sopenharmony_ci 30388c2ecf20Sopenharmony_ci if (statefault < 3) { 30398c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "Recovered from %s\n", ioc->name, 30408c2ecf20Sopenharmony_ci statefault == 1 ? "stuck handshake" : "IOC FAULT"); 30418c2ecf20Sopenharmony_ci } 30428c2ecf20Sopenharmony_ci 30438c2ecf20Sopenharmony_ci return hard_reset_done; 30448c2ecf20Sopenharmony_ci} 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 30478c2ecf20Sopenharmony_ci/** 30488c2ecf20Sopenharmony_ci * mpt_GetIocState - Get the current state of a MPT adapter. 30498c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 30508c2ecf20Sopenharmony_ci * @cooked: Request raw or cooked IOC state 30518c2ecf20Sopenharmony_ci * 30528c2ecf20Sopenharmony_ci * Returns all IOC Doorbell register bits if cooked==0, else just the 30538c2ecf20Sopenharmony_ci * Doorbell bits in MPI_IOC_STATE_MASK. 30548c2ecf20Sopenharmony_ci */ 30558c2ecf20Sopenharmony_ciu32 30568c2ecf20Sopenharmony_cimpt_GetIocState(MPT_ADAPTER *ioc, int cooked) 30578c2ecf20Sopenharmony_ci{ 30588c2ecf20Sopenharmony_ci u32 s, sc; 30598c2ecf20Sopenharmony_ci 30608c2ecf20Sopenharmony_ci /* Get! */ 30618c2ecf20Sopenharmony_ci s = CHIPREG_READ32(&ioc->chip->Doorbell); 30628c2ecf20Sopenharmony_ci sc = s & MPI_IOC_STATE_MASK; 30638c2ecf20Sopenharmony_ci 30648c2ecf20Sopenharmony_ci /* Save! */ 30658c2ecf20Sopenharmony_ci ioc->last_state = sc; 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci return cooked ? sc : s; 30688c2ecf20Sopenharmony_ci} 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 30718c2ecf20Sopenharmony_ci/** 30728c2ecf20Sopenharmony_ci * GetIocFacts - Send IOCFacts request to MPT adapter. 30738c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 30748c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 30758c2ecf20Sopenharmony_ci * @reason: If recovery, only update facts. 30768c2ecf20Sopenharmony_ci * 30778c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 30788c2ecf20Sopenharmony_ci */ 30798c2ecf20Sopenharmony_cistatic int 30808c2ecf20Sopenharmony_ciGetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) 30818c2ecf20Sopenharmony_ci{ 30828c2ecf20Sopenharmony_ci IOCFacts_t get_facts; 30838c2ecf20Sopenharmony_ci IOCFactsReply_t *facts; 30848c2ecf20Sopenharmony_ci int r; 30858c2ecf20Sopenharmony_ci int req_sz; 30868c2ecf20Sopenharmony_ci int reply_sz; 30878c2ecf20Sopenharmony_ci int sz; 30888c2ecf20Sopenharmony_ci u32 status, vv; 30898c2ecf20Sopenharmony_ci u8 shiftFactor=1; 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci /* IOC *must* NOT be in RESET state! */ 30928c2ecf20Sopenharmony_ci if (ioc->last_state == MPI_IOC_STATE_RESET) { 30938c2ecf20Sopenharmony_ci printk(KERN_ERR MYNAM 30948c2ecf20Sopenharmony_ci ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", 30958c2ecf20Sopenharmony_ci ioc->name, ioc->last_state); 30968c2ecf20Sopenharmony_ci return -44; 30978c2ecf20Sopenharmony_ci } 30988c2ecf20Sopenharmony_ci 30998c2ecf20Sopenharmony_ci facts = &ioc->facts; 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci /* Destination (reply area)... */ 31028c2ecf20Sopenharmony_ci reply_sz = sizeof(*facts); 31038c2ecf20Sopenharmony_ci memset(facts, 0, reply_sz); 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci /* Request area (get_facts on the stack right now!) */ 31068c2ecf20Sopenharmony_ci req_sz = sizeof(get_facts); 31078c2ecf20Sopenharmony_ci memset(&get_facts, 0, req_sz); 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci get_facts.Function = MPI_FUNCTION_IOC_FACTS; 31108c2ecf20Sopenharmony_ci /* Assert: All other get_facts fields are zero! */ 31118c2ecf20Sopenharmony_ci 31128c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 31138c2ecf20Sopenharmony_ci "Sending get IocFacts request req_sz=%d reply_sz=%d\n", 31148c2ecf20Sopenharmony_ci ioc->name, req_sz, reply_sz)); 31158c2ecf20Sopenharmony_ci 31168c2ecf20Sopenharmony_ci /* No non-zero fields in the get_facts request are greater than 31178c2ecf20Sopenharmony_ci * 1 byte in size, so we can just fire it off as is. 31188c2ecf20Sopenharmony_ci */ 31198c2ecf20Sopenharmony_ci r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts, 31208c2ecf20Sopenharmony_ci reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag); 31218c2ecf20Sopenharmony_ci if (r != 0) 31228c2ecf20Sopenharmony_ci return r; 31238c2ecf20Sopenharmony_ci 31248c2ecf20Sopenharmony_ci /* 31258c2ecf20Sopenharmony_ci * Now byte swap (GRRR) the necessary fields before any further 31268c2ecf20Sopenharmony_ci * inspection of reply contents. 31278c2ecf20Sopenharmony_ci * 31288c2ecf20Sopenharmony_ci * But need to do some sanity checks on MsgLength (byte) field 31298c2ecf20Sopenharmony_ci * to make sure we don't zero IOC's req_sz! 31308c2ecf20Sopenharmony_ci */ 31318c2ecf20Sopenharmony_ci /* Did we get a valid reply? */ 31328c2ecf20Sopenharmony_ci if (facts->MsgLength > offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)) { 31338c2ecf20Sopenharmony_ci if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { 31348c2ecf20Sopenharmony_ci /* 31358c2ecf20Sopenharmony_ci * If not been here, done that, save off first WhoInit value 31368c2ecf20Sopenharmony_ci */ 31378c2ecf20Sopenharmony_ci if (ioc->FirstWhoInit == WHOINIT_UNKNOWN) 31388c2ecf20Sopenharmony_ci ioc->FirstWhoInit = facts->WhoInit; 31398c2ecf20Sopenharmony_ci } 31408c2ecf20Sopenharmony_ci 31418c2ecf20Sopenharmony_ci facts->MsgVersion = le16_to_cpu(facts->MsgVersion); 31428c2ecf20Sopenharmony_ci facts->MsgContext = le32_to_cpu(facts->MsgContext); 31438c2ecf20Sopenharmony_ci facts->IOCExceptions = le16_to_cpu(facts->IOCExceptions); 31448c2ecf20Sopenharmony_ci facts->IOCStatus = le16_to_cpu(facts->IOCStatus); 31458c2ecf20Sopenharmony_ci facts->IOCLogInfo = le32_to_cpu(facts->IOCLogInfo); 31468c2ecf20Sopenharmony_ci status = le16_to_cpu(facts->IOCStatus) & MPI_IOCSTATUS_MASK; 31478c2ecf20Sopenharmony_ci /* CHECKME! IOCStatus, IOCLogInfo */ 31488c2ecf20Sopenharmony_ci 31498c2ecf20Sopenharmony_ci facts->ReplyQueueDepth = le16_to_cpu(facts->ReplyQueueDepth); 31508c2ecf20Sopenharmony_ci facts->RequestFrameSize = le16_to_cpu(facts->RequestFrameSize); 31518c2ecf20Sopenharmony_ci 31528c2ecf20Sopenharmony_ci /* 31538c2ecf20Sopenharmony_ci * FC f/w version changed between 1.1 and 1.2 31548c2ecf20Sopenharmony_ci * Old: u16{Major(4),Minor(4),SubMinor(8)} 31558c2ecf20Sopenharmony_ci * New: u32{Major(8),Minor(8),Unit(8),Dev(8)} 31568c2ecf20Sopenharmony_ci */ 31578c2ecf20Sopenharmony_ci if (facts->MsgVersion < MPI_VERSION_01_02) { 31588c2ecf20Sopenharmony_ci /* 31598c2ecf20Sopenharmony_ci * Handle old FC f/w style, convert to new... 31608c2ecf20Sopenharmony_ci */ 31618c2ecf20Sopenharmony_ci u16 oldv = le16_to_cpu(facts->Reserved_0101_FWVersion); 31628c2ecf20Sopenharmony_ci facts->FWVersion.Word = 31638c2ecf20Sopenharmony_ci ((oldv<<12) & 0xFF000000) | 31648c2ecf20Sopenharmony_ci ((oldv<<8) & 0x000FFF00); 31658c2ecf20Sopenharmony_ci } else 31668c2ecf20Sopenharmony_ci facts->FWVersion.Word = le32_to_cpu(facts->FWVersion.Word); 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ci facts->ProductID = le16_to_cpu(facts->ProductID); 31698c2ecf20Sopenharmony_ci 31708c2ecf20Sopenharmony_ci if ((ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) 31718c2ecf20Sopenharmony_ci > MPI_FW_HEADER_PID_PROD_TARGET_SCSI) 31728c2ecf20Sopenharmony_ci ioc->ir_firmware = 1; 31738c2ecf20Sopenharmony_ci 31748c2ecf20Sopenharmony_ci facts->CurrentHostMfaHighAddr = 31758c2ecf20Sopenharmony_ci le32_to_cpu(facts->CurrentHostMfaHighAddr); 31768c2ecf20Sopenharmony_ci facts->GlobalCredits = le16_to_cpu(facts->GlobalCredits); 31778c2ecf20Sopenharmony_ci facts->CurrentSenseBufferHighAddr = 31788c2ecf20Sopenharmony_ci le32_to_cpu(facts->CurrentSenseBufferHighAddr); 31798c2ecf20Sopenharmony_ci facts->CurReplyFrameSize = 31808c2ecf20Sopenharmony_ci le16_to_cpu(facts->CurReplyFrameSize); 31818c2ecf20Sopenharmony_ci facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities); 31828c2ecf20Sopenharmony_ci 31838c2ecf20Sopenharmony_ci /* 31848c2ecf20Sopenharmony_ci * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx 31858c2ecf20Sopenharmony_ci * Older MPI-1.00.xx struct had 13 dwords, and enlarged 31868c2ecf20Sopenharmony_ci * to 14 in MPI-1.01.0x. 31878c2ecf20Sopenharmony_ci */ 31888c2ecf20Sopenharmony_ci if (facts->MsgLength >= (offsetof(IOCFactsReply_t,FWImageSize) + 7)/4 && 31898c2ecf20Sopenharmony_ci facts->MsgVersion > MPI_VERSION_01_00) { 31908c2ecf20Sopenharmony_ci facts->FWImageSize = le32_to_cpu(facts->FWImageSize); 31918c2ecf20Sopenharmony_ci } 31928c2ecf20Sopenharmony_ci 31938c2ecf20Sopenharmony_ci facts->FWImageSize = ALIGN(facts->FWImageSize, 4); 31948c2ecf20Sopenharmony_ci 31958c2ecf20Sopenharmony_ci if (!facts->RequestFrameSize) { 31968c2ecf20Sopenharmony_ci /* Something is wrong! */ 31978c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n", 31988c2ecf20Sopenharmony_ci ioc->name); 31998c2ecf20Sopenharmony_ci return -55; 32008c2ecf20Sopenharmony_ci } 32018c2ecf20Sopenharmony_ci 32028c2ecf20Sopenharmony_ci r = sz = facts->BlockSize; 32038c2ecf20Sopenharmony_ci vv = ((63 / (sz * 4)) + 1) & 0x03; 32048c2ecf20Sopenharmony_ci ioc->NB_for_64_byte_frame = vv; 32058c2ecf20Sopenharmony_ci while ( sz ) 32068c2ecf20Sopenharmony_ci { 32078c2ecf20Sopenharmony_ci shiftFactor++; 32088c2ecf20Sopenharmony_ci sz = sz >> 1; 32098c2ecf20Sopenharmony_ci } 32108c2ecf20Sopenharmony_ci ioc->NBShiftFactor = shiftFactor; 32118c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT 32128c2ecf20Sopenharmony_ci "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", 32138c2ecf20Sopenharmony_ci ioc->name, vv, shiftFactor, r)); 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ci if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { 32168c2ecf20Sopenharmony_ci /* 32178c2ecf20Sopenharmony_ci * Set values for this IOC's request & reply frame sizes, 32188c2ecf20Sopenharmony_ci * and request & reply queue depths... 32198c2ecf20Sopenharmony_ci */ 32208c2ecf20Sopenharmony_ci ioc->req_sz = min(MPT_DEFAULT_FRAME_SIZE, facts->RequestFrameSize * 4); 32218c2ecf20Sopenharmony_ci ioc->req_depth = min_t(int, MPT_MAX_REQ_DEPTH, facts->GlobalCredits); 32228c2ecf20Sopenharmony_ci ioc->reply_sz = MPT_REPLY_FRAME_SIZE; 32238c2ecf20Sopenharmony_ci ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "reply_sz=%3d, reply_depth=%4d\n", 32268c2ecf20Sopenharmony_ci ioc->name, ioc->reply_sz, ioc->reply_depth)); 32278c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "req_sz =%3d, req_depth =%4d\n", 32288c2ecf20Sopenharmony_ci ioc->name, ioc->req_sz, ioc->req_depth)); 32298c2ecf20Sopenharmony_ci 32308c2ecf20Sopenharmony_ci /* Get port facts! */ 32318c2ecf20Sopenharmony_ci if ( (r = GetPortFacts(ioc, 0, sleepFlag)) != 0 ) 32328c2ecf20Sopenharmony_ci return r; 32338c2ecf20Sopenharmony_ci } 32348c2ecf20Sopenharmony_ci } else { 32358c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 32368c2ecf20Sopenharmony_ci "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n", 32378c2ecf20Sopenharmony_ci ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t, 32388c2ecf20Sopenharmony_ci RequestFrameSize)/sizeof(u32))); 32398c2ecf20Sopenharmony_ci return -66; 32408c2ecf20Sopenharmony_ci } 32418c2ecf20Sopenharmony_ci 32428c2ecf20Sopenharmony_ci return 0; 32438c2ecf20Sopenharmony_ci} 32448c2ecf20Sopenharmony_ci 32458c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 32468c2ecf20Sopenharmony_ci/** 32478c2ecf20Sopenharmony_ci * GetPortFacts - Send PortFacts request to MPT adapter. 32488c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 32498c2ecf20Sopenharmony_ci * @portnum: Port number 32508c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 32518c2ecf20Sopenharmony_ci * 32528c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 32538c2ecf20Sopenharmony_ci */ 32548c2ecf20Sopenharmony_cistatic int 32558c2ecf20Sopenharmony_ciGetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) 32568c2ecf20Sopenharmony_ci{ 32578c2ecf20Sopenharmony_ci PortFacts_t get_pfacts; 32588c2ecf20Sopenharmony_ci PortFactsReply_t *pfacts; 32598c2ecf20Sopenharmony_ci int ii; 32608c2ecf20Sopenharmony_ci int req_sz; 32618c2ecf20Sopenharmony_ci int reply_sz; 32628c2ecf20Sopenharmony_ci int max_id; 32638c2ecf20Sopenharmony_ci 32648c2ecf20Sopenharmony_ci /* IOC *must* NOT be in RESET state! */ 32658c2ecf20Sopenharmony_ci if (ioc->last_state == MPI_IOC_STATE_RESET) { 32668c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n", 32678c2ecf20Sopenharmony_ci ioc->name, ioc->last_state ); 32688c2ecf20Sopenharmony_ci return -4; 32698c2ecf20Sopenharmony_ci } 32708c2ecf20Sopenharmony_ci 32718c2ecf20Sopenharmony_ci pfacts = &ioc->pfacts[portnum]; 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci /* Destination (reply area)... */ 32748c2ecf20Sopenharmony_ci reply_sz = sizeof(*pfacts); 32758c2ecf20Sopenharmony_ci memset(pfacts, 0, reply_sz); 32768c2ecf20Sopenharmony_ci 32778c2ecf20Sopenharmony_ci /* Request area (get_pfacts on the stack right now!) */ 32788c2ecf20Sopenharmony_ci req_sz = sizeof(get_pfacts); 32798c2ecf20Sopenharmony_ci memset(&get_pfacts, 0, req_sz); 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ci get_pfacts.Function = MPI_FUNCTION_PORT_FACTS; 32828c2ecf20Sopenharmony_ci get_pfacts.PortNumber = portnum; 32838c2ecf20Sopenharmony_ci /* Assert: All other get_pfacts fields are zero! */ 32848c2ecf20Sopenharmony_ci 32858c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending get PortFacts(%d) request\n", 32868c2ecf20Sopenharmony_ci ioc->name, portnum)); 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci /* No non-zero fields in the get_pfacts request are greater than 32898c2ecf20Sopenharmony_ci * 1 byte in size, so we can just fire it off as is. 32908c2ecf20Sopenharmony_ci */ 32918c2ecf20Sopenharmony_ci ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts, 32928c2ecf20Sopenharmony_ci reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag); 32938c2ecf20Sopenharmony_ci if (ii != 0) 32948c2ecf20Sopenharmony_ci return ii; 32958c2ecf20Sopenharmony_ci 32968c2ecf20Sopenharmony_ci /* Did we get a valid reply? */ 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci /* Now byte swap the necessary fields in the response. */ 32998c2ecf20Sopenharmony_ci pfacts->MsgContext = le32_to_cpu(pfacts->MsgContext); 33008c2ecf20Sopenharmony_ci pfacts->IOCStatus = le16_to_cpu(pfacts->IOCStatus); 33018c2ecf20Sopenharmony_ci pfacts->IOCLogInfo = le32_to_cpu(pfacts->IOCLogInfo); 33028c2ecf20Sopenharmony_ci pfacts->MaxDevices = le16_to_cpu(pfacts->MaxDevices); 33038c2ecf20Sopenharmony_ci pfacts->PortSCSIID = le16_to_cpu(pfacts->PortSCSIID); 33048c2ecf20Sopenharmony_ci pfacts->ProtocolFlags = le16_to_cpu(pfacts->ProtocolFlags); 33058c2ecf20Sopenharmony_ci pfacts->MaxPostedCmdBuffers = le16_to_cpu(pfacts->MaxPostedCmdBuffers); 33068c2ecf20Sopenharmony_ci pfacts->MaxPersistentIDs = le16_to_cpu(pfacts->MaxPersistentIDs); 33078c2ecf20Sopenharmony_ci pfacts->MaxLanBuckets = le16_to_cpu(pfacts->MaxLanBuckets); 33088c2ecf20Sopenharmony_ci 33098c2ecf20Sopenharmony_ci max_id = (ioc->bus_type == SAS) ? pfacts->PortSCSIID : 33108c2ecf20Sopenharmony_ci pfacts->MaxDevices; 33118c2ecf20Sopenharmony_ci ioc->devices_per_bus = (max_id > 255) ? 256 : max_id; 33128c2ecf20Sopenharmony_ci ioc->number_of_buses = (ioc->devices_per_bus < 256) ? 1 : max_id/256; 33138c2ecf20Sopenharmony_ci 33148c2ecf20Sopenharmony_ci /* 33158c2ecf20Sopenharmony_ci * Place all the devices on channels 33168c2ecf20Sopenharmony_ci * 33178c2ecf20Sopenharmony_ci * (for debuging) 33188c2ecf20Sopenharmony_ci */ 33198c2ecf20Sopenharmony_ci if (mpt_channel_mapping) { 33208c2ecf20Sopenharmony_ci ioc->devices_per_bus = 1; 33218c2ecf20Sopenharmony_ci ioc->number_of_buses = (max_id > 255) ? 255 : max_id; 33228c2ecf20Sopenharmony_ci } 33238c2ecf20Sopenharmony_ci 33248c2ecf20Sopenharmony_ci return 0; 33258c2ecf20Sopenharmony_ci} 33268c2ecf20Sopenharmony_ci 33278c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 33288c2ecf20Sopenharmony_ci/** 33298c2ecf20Sopenharmony_ci * SendIocInit - Send IOCInit request to MPT adapter. 33308c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 33318c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 33328c2ecf20Sopenharmony_ci * 33338c2ecf20Sopenharmony_ci * Send IOCInit followed by PortEnable to bring IOC to OPERATIONAL state. 33348c2ecf20Sopenharmony_ci * 33358c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 33368c2ecf20Sopenharmony_ci */ 33378c2ecf20Sopenharmony_cistatic int 33388c2ecf20Sopenharmony_ciSendIocInit(MPT_ADAPTER *ioc, int sleepFlag) 33398c2ecf20Sopenharmony_ci{ 33408c2ecf20Sopenharmony_ci IOCInit_t ioc_init; 33418c2ecf20Sopenharmony_ci MPIDefaultReply_t init_reply; 33428c2ecf20Sopenharmony_ci u32 state; 33438c2ecf20Sopenharmony_ci int r; 33448c2ecf20Sopenharmony_ci int count; 33458c2ecf20Sopenharmony_ci int cntdn; 33468c2ecf20Sopenharmony_ci 33478c2ecf20Sopenharmony_ci memset(&ioc_init, 0, sizeof(ioc_init)); 33488c2ecf20Sopenharmony_ci memset(&init_reply, 0, sizeof(init_reply)); 33498c2ecf20Sopenharmony_ci 33508c2ecf20Sopenharmony_ci ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER; 33518c2ecf20Sopenharmony_ci ioc_init.Function = MPI_FUNCTION_IOC_INIT; 33528c2ecf20Sopenharmony_ci 33538c2ecf20Sopenharmony_ci /* If we are in a recovery mode and we uploaded the FW image, 33548c2ecf20Sopenharmony_ci * then this pointer is not NULL. Skip the upload a second time. 33558c2ecf20Sopenharmony_ci * Set this flag if cached_fw set for either IOC. 33568c2ecf20Sopenharmony_ci */ 33578c2ecf20Sopenharmony_ci if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) 33588c2ecf20Sopenharmony_ci ioc->upload_fw = 1; 33598c2ecf20Sopenharmony_ci else 33608c2ecf20Sopenharmony_ci ioc->upload_fw = 0; 33618c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "upload_fw %d facts.Flags=%x\n", 33628c2ecf20Sopenharmony_ci ioc->name, ioc->upload_fw, ioc->facts.Flags)); 33638c2ecf20Sopenharmony_ci 33648c2ecf20Sopenharmony_ci ioc_init.MaxDevices = (U8)ioc->devices_per_bus; 33658c2ecf20Sopenharmony_ci ioc_init.MaxBuses = (U8)ioc->number_of_buses; 33668c2ecf20Sopenharmony_ci 33678c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "facts.MsgVersion=%x\n", 33688c2ecf20Sopenharmony_ci ioc->name, ioc->facts.MsgVersion)); 33698c2ecf20Sopenharmony_ci if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { 33708c2ecf20Sopenharmony_ci // set MsgVersion and HeaderVersion host driver was built with 33718c2ecf20Sopenharmony_ci ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION); 33728c2ecf20Sopenharmony_ci ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION); 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ci if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) { 33758c2ecf20Sopenharmony_ci ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE; 33768c2ecf20Sopenharmony_ci } else if(mpt_host_page_alloc(ioc, &ioc_init)) 33778c2ecf20Sopenharmony_ci return -99; 33788c2ecf20Sopenharmony_ci } 33798c2ecf20Sopenharmony_ci ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ 33808c2ecf20Sopenharmony_ci 33818c2ecf20Sopenharmony_ci if (ioc->sg_addr_size == sizeof(u64)) { 33828c2ecf20Sopenharmony_ci /* Save the upper 32-bits of the request 33838c2ecf20Sopenharmony_ci * (reply) and sense buffers. 33848c2ecf20Sopenharmony_ci */ 33858c2ecf20Sopenharmony_ci ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32)); 33868c2ecf20Sopenharmony_ci ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); 33878c2ecf20Sopenharmony_ci } else { 33888c2ecf20Sopenharmony_ci /* Force 32-bit addressing */ 33898c2ecf20Sopenharmony_ci ioc_init.HostMfaHighAddr = cpu_to_le32(0); 33908c2ecf20Sopenharmony_ci ioc_init.SenseBufferHighAddr = cpu_to_le32(0); 33918c2ecf20Sopenharmony_ci } 33928c2ecf20Sopenharmony_ci 33938c2ecf20Sopenharmony_ci ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; 33948c2ecf20Sopenharmony_ci ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; 33958c2ecf20Sopenharmony_ci ioc->facts.MaxDevices = ioc_init.MaxDevices; 33968c2ecf20Sopenharmony_ci ioc->facts.MaxBuses = ioc_init.MaxBuses; 33978c2ecf20Sopenharmony_ci 33988c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOCInit (req @ %p)\n", 33998c2ecf20Sopenharmony_ci ioc->name, &ioc_init)); 34008c2ecf20Sopenharmony_ci 34018c2ecf20Sopenharmony_ci r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, 34028c2ecf20Sopenharmony_ci sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag); 34038c2ecf20Sopenharmony_ci if (r != 0) { 34048c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r); 34058c2ecf20Sopenharmony_ci return r; 34068c2ecf20Sopenharmony_ci } 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_ci /* No need to byte swap the multibyte fields in the reply 34098c2ecf20Sopenharmony_ci * since we don't even look at its contents. 34108c2ecf20Sopenharmony_ci */ 34118c2ecf20Sopenharmony_ci 34128c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending PortEnable (req @ %p)\n", 34138c2ecf20Sopenharmony_ci ioc->name, &ioc_init)); 34148c2ecf20Sopenharmony_ci 34158c2ecf20Sopenharmony_ci if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0) { 34168c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Sending PortEnable failed(%d)!\n",ioc->name, r); 34178c2ecf20Sopenharmony_ci return r; 34188c2ecf20Sopenharmony_ci } 34198c2ecf20Sopenharmony_ci 34208c2ecf20Sopenharmony_ci /* YIKES! SUPER IMPORTANT!!! 34218c2ecf20Sopenharmony_ci * Poll IocState until _OPERATIONAL while IOC is doing 34228c2ecf20Sopenharmony_ci * LoopInit and TargetDiscovery! 34238c2ecf20Sopenharmony_ci */ 34248c2ecf20Sopenharmony_ci count = 0; 34258c2ecf20Sopenharmony_ci cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 60; /* 60 seconds */ 34268c2ecf20Sopenharmony_ci state = mpt_GetIocState(ioc, 1); 34278c2ecf20Sopenharmony_ci while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) { 34288c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 34298c2ecf20Sopenharmony_ci msleep(1); 34308c2ecf20Sopenharmony_ci } else { 34318c2ecf20Sopenharmony_ci mdelay(1); 34328c2ecf20Sopenharmony_ci } 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci if (!cntdn) { 34358c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n", 34368c2ecf20Sopenharmony_ci ioc->name, (int)((count+5)/HZ)); 34378c2ecf20Sopenharmony_ci return -9; 34388c2ecf20Sopenharmony_ci } 34398c2ecf20Sopenharmony_ci 34408c2ecf20Sopenharmony_ci state = mpt_GetIocState(ioc, 1); 34418c2ecf20Sopenharmony_ci count++; 34428c2ecf20Sopenharmony_ci } 34438c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n", 34448c2ecf20Sopenharmony_ci ioc->name, count)); 34458c2ecf20Sopenharmony_ci 34468c2ecf20Sopenharmony_ci ioc->aen_event_read_flag=0; 34478c2ecf20Sopenharmony_ci return r; 34488c2ecf20Sopenharmony_ci} 34498c2ecf20Sopenharmony_ci 34508c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 34518c2ecf20Sopenharmony_ci/** 34528c2ecf20Sopenharmony_ci * SendPortEnable - Send PortEnable request to MPT adapter port. 34538c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 34548c2ecf20Sopenharmony_ci * @portnum: Port number to enable 34558c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 34568c2ecf20Sopenharmony_ci * 34578c2ecf20Sopenharmony_ci * Send PortEnable to bring IOC to OPERATIONAL state. 34588c2ecf20Sopenharmony_ci * 34598c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 34608c2ecf20Sopenharmony_ci */ 34618c2ecf20Sopenharmony_cistatic int 34628c2ecf20Sopenharmony_ciSendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) 34638c2ecf20Sopenharmony_ci{ 34648c2ecf20Sopenharmony_ci PortEnable_t port_enable; 34658c2ecf20Sopenharmony_ci MPIDefaultReply_t reply_buf; 34668c2ecf20Sopenharmony_ci int rc; 34678c2ecf20Sopenharmony_ci int req_sz; 34688c2ecf20Sopenharmony_ci int reply_sz; 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci /* Destination... */ 34718c2ecf20Sopenharmony_ci reply_sz = sizeof(MPIDefaultReply_t); 34728c2ecf20Sopenharmony_ci memset(&reply_buf, 0, reply_sz); 34738c2ecf20Sopenharmony_ci 34748c2ecf20Sopenharmony_ci req_sz = sizeof(PortEnable_t); 34758c2ecf20Sopenharmony_ci memset(&port_enable, 0, req_sz); 34768c2ecf20Sopenharmony_ci 34778c2ecf20Sopenharmony_ci port_enable.Function = MPI_FUNCTION_PORT_ENABLE; 34788c2ecf20Sopenharmony_ci port_enable.PortNumber = portnum; 34798c2ecf20Sopenharmony_ci/* port_enable.ChainOffset = 0; */ 34808c2ecf20Sopenharmony_ci/* port_enable.MsgFlags = 0; */ 34818c2ecf20Sopenharmony_ci/* port_enable.MsgContext = 0; */ 34828c2ecf20Sopenharmony_ci 34838c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Port(%d)Enable (req @ %p)\n", 34848c2ecf20Sopenharmony_ci ioc->name, portnum, &port_enable)); 34858c2ecf20Sopenharmony_ci 34868c2ecf20Sopenharmony_ci /* RAID FW may take a long time to enable 34878c2ecf20Sopenharmony_ci */ 34888c2ecf20Sopenharmony_ci if (ioc->ir_firmware || ioc->bus_type == SAS) { 34898c2ecf20Sopenharmony_ci rc = mpt_handshake_req_reply_wait(ioc, req_sz, 34908c2ecf20Sopenharmony_ci (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 34918c2ecf20Sopenharmony_ci 300 /*seconds*/, sleepFlag); 34928c2ecf20Sopenharmony_ci } else { 34938c2ecf20Sopenharmony_ci rc = mpt_handshake_req_reply_wait(ioc, req_sz, 34948c2ecf20Sopenharmony_ci (u32*)&port_enable, reply_sz, (u16*)&reply_buf, 34958c2ecf20Sopenharmony_ci 30 /*seconds*/, sleepFlag); 34968c2ecf20Sopenharmony_ci } 34978c2ecf20Sopenharmony_ci return rc; 34988c2ecf20Sopenharmony_ci} 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci/** 35018c2ecf20Sopenharmony_ci * mpt_alloc_fw_memory - allocate firmware memory 35028c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 35038c2ecf20Sopenharmony_ci * @size: total FW bytes 35048c2ecf20Sopenharmony_ci * 35058c2ecf20Sopenharmony_ci * If memory has already been allocated, the same (cached) value 35068c2ecf20Sopenharmony_ci * is returned. 35078c2ecf20Sopenharmony_ci * 35088c2ecf20Sopenharmony_ci * Return 0 if successful, or non-zero for failure 35098c2ecf20Sopenharmony_ci **/ 35108c2ecf20Sopenharmony_ciint 35118c2ecf20Sopenharmony_cimpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size) 35128c2ecf20Sopenharmony_ci{ 35138c2ecf20Sopenharmony_ci int rc; 35148c2ecf20Sopenharmony_ci 35158c2ecf20Sopenharmony_ci if (ioc->cached_fw) { 35168c2ecf20Sopenharmony_ci rc = 0; /* use already allocated memory */ 35178c2ecf20Sopenharmony_ci goto out; 35188c2ecf20Sopenharmony_ci } 35198c2ecf20Sopenharmony_ci else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { 35208c2ecf20Sopenharmony_ci ioc->cached_fw = ioc->alt_ioc->cached_fw; /* use alt_ioc's memory */ 35218c2ecf20Sopenharmony_ci ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma; 35228c2ecf20Sopenharmony_ci rc = 0; 35238c2ecf20Sopenharmony_ci goto out; 35248c2ecf20Sopenharmony_ci } 35258c2ecf20Sopenharmony_ci ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma); 35268c2ecf20Sopenharmony_ci if (!ioc->cached_fw) { 35278c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Unable to allocate memory for the cached firmware image!\n", 35288c2ecf20Sopenharmony_ci ioc->name); 35298c2ecf20Sopenharmony_ci rc = -1; 35308c2ecf20Sopenharmony_ci } else { 35318c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Image @ %p[%p], sz=%d[%x] bytes\n", 35328c2ecf20Sopenharmony_ci ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, size, size)); 35338c2ecf20Sopenharmony_ci ioc->alloc_total += size; 35348c2ecf20Sopenharmony_ci rc = 0; 35358c2ecf20Sopenharmony_ci } 35368c2ecf20Sopenharmony_ci out: 35378c2ecf20Sopenharmony_ci return rc; 35388c2ecf20Sopenharmony_ci} 35398c2ecf20Sopenharmony_ci 35408c2ecf20Sopenharmony_ci/** 35418c2ecf20Sopenharmony_ci * mpt_free_fw_memory - free firmware memory 35428c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 35438c2ecf20Sopenharmony_ci * 35448c2ecf20Sopenharmony_ci * If alt_img is NULL, delete from ioc structure. 35458c2ecf20Sopenharmony_ci * Else, delete a secondary image in same format. 35468c2ecf20Sopenharmony_ci **/ 35478c2ecf20Sopenharmony_civoid 35488c2ecf20Sopenharmony_cimpt_free_fw_memory(MPT_ADAPTER *ioc) 35498c2ecf20Sopenharmony_ci{ 35508c2ecf20Sopenharmony_ci int sz; 35518c2ecf20Sopenharmony_ci 35528c2ecf20Sopenharmony_ci if (!ioc->cached_fw) 35538c2ecf20Sopenharmony_ci return; 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_ci sz = ioc->facts.FWImageSize; 35568c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", 35578c2ecf20Sopenharmony_ci ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); 35588c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); 35598c2ecf20Sopenharmony_ci ioc->alloc_total -= sz; 35608c2ecf20Sopenharmony_ci ioc->cached_fw = NULL; 35618c2ecf20Sopenharmony_ci} 35628c2ecf20Sopenharmony_ci 35638c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 35648c2ecf20Sopenharmony_ci/** 35658c2ecf20Sopenharmony_ci * mpt_do_upload - Construct and Send FWUpload request to MPT adapter port. 35668c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 35678c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 35688c2ecf20Sopenharmony_ci * 35698c2ecf20Sopenharmony_ci * Returns 0 for success, >0 for handshake failure 35708c2ecf20Sopenharmony_ci * <0 for fw upload failure. 35718c2ecf20Sopenharmony_ci * 35728c2ecf20Sopenharmony_ci * Remark: If bound IOC and a successful FWUpload was performed 35738c2ecf20Sopenharmony_ci * on the bound IOC, the second image is discarded 35748c2ecf20Sopenharmony_ci * and memory is free'd. Both channels must upload to prevent 35758c2ecf20Sopenharmony_ci * IOC from running in degraded mode. 35768c2ecf20Sopenharmony_ci */ 35778c2ecf20Sopenharmony_cistatic int 35788c2ecf20Sopenharmony_cimpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) 35798c2ecf20Sopenharmony_ci{ 35808c2ecf20Sopenharmony_ci u8 reply[sizeof(FWUploadReply_t)]; 35818c2ecf20Sopenharmony_ci FWUpload_t *prequest; 35828c2ecf20Sopenharmony_ci FWUploadReply_t *preply; 35838c2ecf20Sopenharmony_ci FWUploadTCSGE_t *ptcsge; 35848c2ecf20Sopenharmony_ci u32 flagsLength; 35858c2ecf20Sopenharmony_ci int ii, sz, reply_sz; 35868c2ecf20Sopenharmony_ci int cmdStatus; 35878c2ecf20Sopenharmony_ci int request_size; 35888c2ecf20Sopenharmony_ci /* If the image size is 0, we are done. 35898c2ecf20Sopenharmony_ci */ 35908c2ecf20Sopenharmony_ci if ((sz = ioc->facts.FWImageSize) == 0) 35918c2ecf20Sopenharmony_ci return 0; 35928c2ecf20Sopenharmony_ci 35938c2ecf20Sopenharmony_ci if (mpt_alloc_fw_memory(ioc, ioc->facts.FWImageSize) != 0) 35948c2ecf20Sopenharmony_ci return -ENOMEM; 35958c2ecf20Sopenharmony_ci 35968c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n", 35978c2ecf20Sopenharmony_ci ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); 35988c2ecf20Sopenharmony_ci 35998c2ecf20Sopenharmony_ci prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) : 36008c2ecf20Sopenharmony_ci kzalloc(ioc->req_sz, GFP_KERNEL); 36018c2ecf20Sopenharmony_ci if (!prequest) { 36028c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed " 36038c2ecf20Sopenharmony_ci "while allocating memory \n", ioc->name)); 36048c2ecf20Sopenharmony_ci mpt_free_fw_memory(ioc); 36058c2ecf20Sopenharmony_ci return -ENOMEM; 36068c2ecf20Sopenharmony_ci } 36078c2ecf20Sopenharmony_ci 36088c2ecf20Sopenharmony_ci preply = (FWUploadReply_t *)&reply; 36098c2ecf20Sopenharmony_ci 36108c2ecf20Sopenharmony_ci reply_sz = sizeof(reply); 36118c2ecf20Sopenharmony_ci memset(preply, 0, reply_sz); 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM; 36148c2ecf20Sopenharmony_ci prequest->Function = MPI_FUNCTION_FW_UPLOAD; 36158c2ecf20Sopenharmony_ci 36168c2ecf20Sopenharmony_ci ptcsge = (FWUploadTCSGE_t *) &prequest->SGL; 36178c2ecf20Sopenharmony_ci ptcsge->DetailsLength = 12; 36188c2ecf20Sopenharmony_ci ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; 36198c2ecf20Sopenharmony_ci ptcsge->ImageSize = cpu_to_le32(sz); 36208c2ecf20Sopenharmony_ci ptcsge++; 36218c2ecf20Sopenharmony_ci 36228c2ecf20Sopenharmony_ci flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; 36238c2ecf20Sopenharmony_ci ioc->add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma); 36248c2ecf20Sopenharmony_ci request_size = offsetof(FWUpload_t, SGL) + sizeof(FWUploadTCSGE_t) + 36258c2ecf20Sopenharmony_ci ioc->SGE_size; 36268c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending FW Upload " 36278c2ecf20Sopenharmony_ci " (req @ %p) fw_size=%d mf_request_size=%d\n", ioc->name, prequest, 36288c2ecf20Sopenharmony_ci ioc->facts.FWImageSize, request_size)); 36298c2ecf20Sopenharmony_ci DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest); 36308c2ecf20Sopenharmony_ci 36318c2ecf20Sopenharmony_ci ii = mpt_handshake_req_reply_wait(ioc, request_size, (u32 *)prequest, 36328c2ecf20Sopenharmony_ci reply_sz, (u16 *)preply, 65 /*seconds*/, sleepFlag); 36338c2ecf20Sopenharmony_ci 36348c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "FW Upload completed " 36358c2ecf20Sopenharmony_ci "rc=%x \n", ioc->name, ii)); 36368c2ecf20Sopenharmony_ci 36378c2ecf20Sopenharmony_ci cmdStatus = -EFAULT; 36388c2ecf20Sopenharmony_ci if (ii == 0) { 36398c2ecf20Sopenharmony_ci /* Handshake transfer was complete and successful. 36408c2ecf20Sopenharmony_ci * Check the Reply Frame. 36418c2ecf20Sopenharmony_ci */ 36428c2ecf20Sopenharmony_ci int status; 36438c2ecf20Sopenharmony_ci status = le16_to_cpu(preply->IOCStatus) & 36448c2ecf20Sopenharmony_ci MPI_IOCSTATUS_MASK; 36458c2ecf20Sopenharmony_ci if (status == MPI_IOCSTATUS_SUCCESS && 36468c2ecf20Sopenharmony_ci ioc->facts.FWImageSize == 36478c2ecf20Sopenharmony_ci le32_to_cpu(preply->ActualImageSize)) 36488c2ecf20Sopenharmony_ci cmdStatus = 0; 36498c2ecf20Sopenharmony_ci } 36508c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": do_upload cmdStatus=%d \n", 36518c2ecf20Sopenharmony_ci ioc->name, cmdStatus)); 36528c2ecf20Sopenharmony_ci 36538c2ecf20Sopenharmony_ci 36548c2ecf20Sopenharmony_ci if (cmdStatus) { 36558c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed, " 36568c2ecf20Sopenharmony_ci "freeing image \n", ioc->name)); 36578c2ecf20Sopenharmony_ci mpt_free_fw_memory(ioc); 36588c2ecf20Sopenharmony_ci } 36598c2ecf20Sopenharmony_ci kfree(prequest); 36608c2ecf20Sopenharmony_ci 36618c2ecf20Sopenharmony_ci return cmdStatus; 36628c2ecf20Sopenharmony_ci} 36638c2ecf20Sopenharmony_ci 36648c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 36658c2ecf20Sopenharmony_ci/** 36668c2ecf20Sopenharmony_ci * mpt_downloadboot - DownloadBoot code 36678c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 36688c2ecf20Sopenharmony_ci * @pFwHeader: Pointer to firmware header info 36698c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 36708c2ecf20Sopenharmony_ci * 36718c2ecf20Sopenharmony_ci * FwDownloadBoot requires Programmed IO access. 36728c2ecf20Sopenharmony_ci * 36738c2ecf20Sopenharmony_ci * Returns 0 for success 36748c2ecf20Sopenharmony_ci * -1 FW Image size is 0 36758c2ecf20Sopenharmony_ci * -2 No valid cached_fw Pointer 36768c2ecf20Sopenharmony_ci * <0 for fw upload failure. 36778c2ecf20Sopenharmony_ci */ 36788c2ecf20Sopenharmony_cistatic int 36798c2ecf20Sopenharmony_cimpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) 36808c2ecf20Sopenharmony_ci{ 36818c2ecf20Sopenharmony_ci MpiExtImageHeader_t *pExtImage; 36828c2ecf20Sopenharmony_ci u32 fwSize; 36838c2ecf20Sopenharmony_ci u32 diag0val; 36848c2ecf20Sopenharmony_ci int count; 36858c2ecf20Sopenharmony_ci u32 *ptrFw; 36868c2ecf20Sopenharmony_ci u32 diagRwData; 36878c2ecf20Sopenharmony_ci u32 nextImage; 36888c2ecf20Sopenharmony_ci u32 load_addr; 36898c2ecf20Sopenharmony_ci u32 ioc_state=0; 36908c2ecf20Sopenharmony_ci 36918c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", 36928c2ecf20Sopenharmony_ci ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); 36938c2ecf20Sopenharmony_ci 36948c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); 36958c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); 36968c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); 36978c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); 36988c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); 36998c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); 37008c2ecf20Sopenharmony_ci 37018c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM)); 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci /* wait 1 msec */ 37048c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 37058c2ecf20Sopenharmony_ci msleep(1); 37068c2ecf20Sopenharmony_ci } else { 37078c2ecf20Sopenharmony_ci mdelay (1); 37088c2ecf20Sopenharmony_ci } 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 37118c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER); 37128c2ecf20Sopenharmony_ci 37138c2ecf20Sopenharmony_ci for (count = 0; count < 30; count ++) { 37148c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 37158c2ecf20Sopenharmony_ci if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { 37168c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESET_ADAPTER cleared, count=%d\n", 37178c2ecf20Sopenharmony_ci ioc->name, count)); 37188c2ecf20Sopenharmony_ci break; 37198c2ecf20Sopenharmony_ci } 37208c2ecf20Sopenharmony_ci /* wait .1 sec */ 37218c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 37228c2ecf20Sopenharmony_ci msleep (100); 37238c2ecf20Sopenharmony_ci } else { 37248c2ecf20Sopenharmony_ci mdelay (100); 37258c2ecf20Sopenharmony_ci } 37268c2ecf20Sopenharmony_ci } 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci if ( count == 30 ) { 37298c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot failed! " 37308c2ecf20Sopenharmony_ci "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", 37318c2ecf20Sopenharmony_ci ioc->name, diag0val)); 37328c2ecf20Sopenharmony_ci return -3; 37338c2ecf20Sopenharmony_ci } 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); 37368c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); 37378c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); 37388c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); 37398c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); 37408c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); 37418c2ecf20Sopenharmony_ci 37428c2ecf20Sopenharmony_ci /* Set the DiagRwEn and Disable ARM bits */ 37438c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); 37448c2ecf20Sopenharmony_ci 37458c2ecf20Sopenharmony_ci fwSize = (pFwHeader->ImageSize + 3)/4; 37468c2ecf20Sopenharmony_ci ptrFw = (u32 *) pFwHeader; 37478c2ecf20Sopenharmony_ci 37488c2ecf20Sopenharmony_ci /* Write the LoadStartAddress to the DiagRw Address Register 37498c2ecf20Sopenharmony_ci * using Programmed IO 37508c2ecf20Sopenharmony_ci */ 37518c2ecf20Sopenharmony_ci if (ioc->errata_flag_1064) 37528c2ecf20Sopenharmony_ci pci_enable_io_access(ioc->pcidev); 37538c2ecf20Sopenharmony_ci 37548c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress); 37558c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "LoadStart addr written 0x%x \n", 37568c2ecf20Sopenharmony_ci ioc->name, pFwHeader->LoadStartAddress)); 37578c2ecf20Sopenharmony_ci 37588c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write FW Image: 0x%x bytes @ %p\n", 37598c2ecf20Sopenharmony_ci ioc->name, fwSize*4, ptrFw)); 37608c2ecf20Sopenharmony_ci while (fwSize--) { 37618c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++); 37628c2ecf20Sopenharmony_ci } 37638c2ecf20Sopenharmony_ci 37648c2ecf20Sopenharmony_ci nextImage = pFwHeader->NextImageHeaderOffset; 37658c2ecf20Sopenharmony_ci while (nextImage) { 37668c2ecf20Sopenharmony_ci pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage); 37678c2ecf20Sopenharmony_ci 37688c2ecf20Sopenharmony_ci load_addr = pExtImage->LoadStartAddress; 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci fwSize = (pExtImage->ImageSize + 3) >> 2; 37718c2ecf20Sopenharmony_ci ptrFw = (u32 *)pExtImage; 37728c2ecf20Sopenharmony_ci 37738c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write Ext Image: 0x%x (%d) bytes @ %p load_addr=%x\n", 37748c2ecf20Sopenharmony_ci ioc->name, fwSize*4, fwSize*4, ptrFw, load_addr)); 37758c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr); 37768c2ecf20Sopenharmony_ci 37778c2ecf20Sopenharmony_ci while (fwSize--) { 37788c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++); 37798c2ecf20Sopenharmony_ci } 37808c2ecf20Sopenharmony_ci nextImage = pExtImage->NextImageHeaderOffset; 37818c2ecf20Sopenharmony_ci } 37828c2ecf20Sopenharmony_ci 37838c2ecf20Sopenharmony_ci /* Write the IopResetVectorRegAddr */ 37848c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Addr=%x! \n", ioc->name, pFwHeader->IopResetRegAddr)); 37858c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr); 37868c2ecf20Sopenharmony_ci 37878c2ecf20Sopenharmony_ci /* Write the IopResetVectorValue */ 37888c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue)); 37898c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue); 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci /* Clear the internal flash bad bit - autoincrementing register, 37928c2ecf20Sopenharmony_ci * so must do two writes. 37938c2ecf20Sopenharmony_ci */ 37948c2ecf20Sopenharmony_ci if (ioc->bus_type == SPI) { 37958c2ecf20Sopenharmony_ci /* 37968c2ecf20Sopenharmony_ci * 1030 and 1035 H/W errata, workaround to access 37978c2ecf20Sopenharmony_ci * the ClearFlashBadSignatureBit 37988c2ecf20Sopenharmony_ci */ 37998c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); 38008c2ecf20Sopenharmony_ci diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); 38018c2ecf20Sopenharmony_ci diagRwData |= 0x40000000; 38028c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); 38038c2ecf20Sopenharmony_ci CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); 38048c2ecf20Sopenharmony_ci 38058c2ecf20Sopenharmony_ci } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ { 38068c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 38078c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | 38088c2ecf20Sopenharmony_ci MPI_DIAG_CLEAR_FLASH_BAD_SIG); 38098c2ecf20Sopenharmony_ci 38108c2ecf20Sopenharmony_ci /* wait 1 msec */ 38118c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 38128c2ecf20Sopenharmony_ci msleep (1); 38138c2ecf20Sopenharmony_ci } else { 38148c2ecf20Sopenharmony_ci mdelay (1); 38158c2ecf20Sopenharmony_ci } 38168c2ecf20Sopenharmony_ci } 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci if (ioc->errata_flag_1064) 38198c2ecf20Sopenharmony_ci pci_disable_io_access(ioc->pcidev); 38208c2ecf20Sopenharmony_ci 38218c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 38228c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot diag0val=%x, " 38238c2ecf20Sopenharmony_ci "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", 38248c2ecf20Sopenharmony_ci ioc->name, diag0val)); 38258c2ecf20Sopenharmony_ci diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE); 38268c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "downloadboot now diag0val=%x\n", 38278c2ecf20Sopenharmony_ci ioc->name, diag0val)); 38288c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); 38298c2ecf20Sopenharmony_ci 38308c2ecf20Sopenharmony_ci /* Write 0xFF to reset the sequencer */ 38318c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); 38328c2ecf20Sopenharmony_ci 38338c2ecf20Sopenharmony_ci if (ioc->bus_type == SAS) { 38348c2ecf20Sopenharmony_ci ioc_state = mpt_GetIocState(ioc, 0); 38358c2ecf20Sopenharmony_ci if ( (GetIocFacts(ioc, sleepFlag, 38368c2ecf20Sopenharmony_ci MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) { 38378c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "GetIocFacts failed: IocState=%x\n", 38388c2ecf20Sopenharmony_ci ioc->name, ioc_state)); 38398c2ecf20Sopenharmony_ci return -EFAULT; 38408c2ecf20Sopenharmony_ci } 38418c2ecf20Sopenharmony_ci } 38428c2ecf20Sopenharmony_ci 38438c2ecf20Sopenharmony_ci for (count=0; count<HZ*20; count++) { 38448c2ecf20Sopenharmony_ci if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { 38458c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 38468c2ecf20Sopenharmony_ci "downloadboot successful! (count=%d) IocState=%x\n", 38478c2ecf20Sopenharmony_ci ioc->name, count, ioc_state)); 38488c2ecf20Sopenharmony_ci if (ioc->bus_type == SAS) { 38498c2ecf20Sopenharmony_ci return 0; 38508c2ecf20Sopenharmony_ci } 38518c2ecf20Sopenharmony_ci if ((SendIocInit(ioc, sleepFlag)) != 0) { 38528c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 38538c2ecf20Sopenharmony_ci "downloadboot: SendIocInit failed\n", 38548c2ecf20Sopenharmony_ci ioc->name)); 38558c2ecf20Sopenharmony_ci return -EFAULT; 38568c2ecf20Sopenharmony_ci } 38578c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 38588c2ecf20Sopenharmony_ci "downloadboot: SendIocInit successful\n", 38598c2ecf20Sopenharmony_ci ioc->name)); 38608c2ecf20Sopenharmony_ci return 0; 38618c2ecf20Sopenharmony_ci } 38628c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 38638c2ecf20Sopenharmony_ci msleep (10); 38648c2ecf20Sopenharmony_ci } else { 38658c2ecf20Sopenharmony_ci mdelay (10); 38668c2ecf20Sopenharmony_ci } 38678c2ecf20Sopenharmony_ci } 38688c2ecf20Sopenharmony_ci ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT 38698c2ecf20Sopenharmony_ci "downloadboot failed! IocState=%x\n",ioc->name, ioc_state)); 38708c2ecf20Sopenharmony_ci return -EFAULT; 38718c2ecf20Sopenharmony_ci} 38728c2ecf20Sopenharmony_ci 38738c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 38748c2ecf20Sopenharmony_ci/** 38758c2ecf20Sopenharmony_ci * KickStart - Perform hard reset of MPT adapter. 38768c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 38778c2ecf20Sopenharmony_ci * @force: Force hard reset 38788c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 38798c2ecf20Sopenharmony_ci * 38808c2ecf20Sopenharmony_ci * This routine places MPT adapter in diagnostic mode via the 38818c2ecf20Sopenharmony_ci * WriteSequence register, and then performs a hard reset of adapter 38828c2ecf20Sopenharmony_ci * via the Diagnostic register. 38838c2ecf20Sopenharmony_ci * 38848c2ecf20Sopenharmony_ci * Inputs: sleepflag - CAN_SLEEP (non-interrupt thread) 38858c2ecf20Sopenharmony_ci * or NO_SLEEP (interrupt thread, use mdelay) 38868c2ecf20Sopenharmony_ci * force - 1 if doorbell active, board fault state 38878c2ecf20Sopenharmony_ci * board operational, IOC_RECOVERY or 38888c2ecf20Sopenharmony_ci * IOC_BRINGUP and there is an alt_ioc. 38898c2ecf20Sopenharmony_ci * 0 else 38908c2ecf20Sopenharmony_ci * 38918c2ecf20Sopenharmony_ci * Returns: 38928c2ecf20Sopenharmony_ci * 1 - hard reset, READY 38938c2ecf20Sopenharmony_ci * 0 - no reset due to History bit, READY 38948c2ecf20Sopenharmony_ci * -1 - no reset due to History bit but not READY 38958c2ecf20Sopenharmony_ci * OR reset but failed to come READY 38968c2ecf20Sopenharmony_ci * -2 - no reset, could not enter DIAG mode 38978c2ecf20Sopenharmony_ci * -3 - reset but bad FW bit 38988c2ecf20Sopenharmony_ci */ 38998c2ecf20Sopenharmony_cistatic int 39008c2ecf20Sopenharmony_ciKickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) 39018c2ecf20Sopenharmony_ci{ 39028c2ecf20Sopenharmony_ci int hard_reset_done = 0; 39038c2ecf20Sopenharmony_ci u32 ioc_state=0; 39048c2ecf20Sopenharmony_ci int cnt,cntdn; 39058c2ecf20Sopenharmony_ci 39068c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name)); 39078c2ecf20Sopenharmony_ci if (ioc->bus_type == SPI) { 39088c2ecf20Sopenharmony_ci /* Always issue a Msg Unit Reset first. This will clear some 39098c2ecf20Sopenharmony_ci * SCSI bus hang conditions. 39108c2ecf20Sopenharmony_ci */ 39118c2ecf20Sopenharmony_ci SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); 39128c2ecf20Sopenharmony_ci 39138c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 39148c2ecf20Sopenharmony_ci msleep (1000); 39158c2ecf20Sopenharmony_ci } else { 39168c2ecf20Sopenharmony_ci mdelay (1000); 39178c2ecf20Sopenharmony_ci } 39188c2ecf20Sopenharmony_ci } 39198c2ecf20Sopenharmony_ci 39208c2ecf20Sopenharmony_ci hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag); 39218c2ecf20Sopenharmony_ci if (hard_reset_done < 0) 39228c2ecf20Sopenharmony_ci return hard_reset_done; 39238c2ecf20Sopenharmony_ci 39248c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n", 39258c2ecf20Sopenharmony_ci ioc->name)); 39268c2ecf20Sopenharmony_ci 39278c2ecf20Sopenharmony_ci cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */ 39288c2ecf20Sopenharmony_ci for (cnt=0; cnt<cntdn; cnt++) { 39298c2ecf20Sopenharmony_ci ioc_state = mpt_GetIocState(ioc, 1); 39308c2ecf20Sopenharmony_ci if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) { 39318c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStart successful! (cnt=%d)\n", 39328c2ecf20Sopenharmony_ci ioc->name, cnt)); 39338c2ecf20Sopenharmony_ci return hard_reset_done; 39348c2ecf20Sopenharmony_ci } 39358c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 39368c2ecf20Sopenharmony_ci msleep (10); 39378c2ecf20Sopenharmony_ci } else { 39388c2ecf20Sopenharmony_ci mdelay (10); 39398c2ecf20Sopenharmony_ci } 39408c2ecf20Sopenharmony_ci } 39418c2ecf20Sopenharmony_ci 39428c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n", 39438c2ecf20Sopenharmony_ci ioc->name, mpt_GetIocState(ioc, 0))); 39448c2ecf20Sopenharmony_ci return -1; 39458c2ecf20Sopenharmony_ci} 39468c2ecf20Sopenharmony_ci 39478c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 39488c2ecf20Sopenharmony_ci/** 39498c2ecf20Sopenharmony_ci * mpt_diag_reset - Perform hard reset of the adapter. 39508c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 39518c2ecf20Sopenharmony_ci * @ignore: Set if to honor and clear to ignore 39528c2ecf20Sopenharmony_ci * the reset history bit 39538c2ecf20Sopenharmony_ci * @sleepFlag: CAN_SLEEP if called in a non-interrupt thread, 39548c2ecf20Sopenharmony_ci * else set to NO_SLEEP (use mdelay instead) 39558c2ecf20Sopenharmony_ci * 39568c2ecf20Sopenharmony_ci * This routine places the adapter in diagnostic mode via the 39578c2ecf20Sopenharmony_ci * WriteSequence register and then performs a hard reset of adapter 39588c2ecf20Sopenharmony_ci * via the Diagnostic register. Adapter should be in ready state 39598c2ecf20Sopenharmony_ci * upon successful completion. 39608c2ecf20Sopenharmony_ci * 39618c2ecf20Sopenharmony_ci * Returns: 1 hard reset successful 39628c2ecf20Sopenharmony_ci * 0 no reset performed because reset history bit set 39638c2ecf20Sopenharmony_ci * -2 enabling diagnostic mode failed 39648c2ecf20Sopenharmony_ci * -3 diagnostic reset failed 39658c2ecf20Sopenharmony_ci */ 39668c2ecf20Sopenharmony_cistatic int 39678c2ecf20Sopenharmony_cimpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) 39688c2ecf20Sopenharmony_ci{ 39698c2ecf20Sopenharmony_ci u32 diag0val; 39708c2ecf20Sopenharmony_ci u32 doorbell; 39718c2ecf20Sopenharmony_ci int hard_reset_done = 0; 39728c2ecf20Sopenharmony_ci int count = 0; 39738c2ecf20Sopenharmony_ci u32 diag1val = 0; 39748c2ecf20Sopenharmony_ci MpiFwHeader_t *cached_fw; /* Pointer to FW */ 39758c2ecf20Sopenharmony_ci u8 cb_idx; 39768c2ecf20Sopenharmony_ci 39778c2ecf20Sopenharmony_ci /* Clear any existing interrupts */ 39788c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 39798c2ecf20Sopenharmony_ci 39808c2ecf20Sopenharmony_ci if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci if (!ignore) 39838c2ecf20Sopenharmony_ci return 0; 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_ci drsprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " 39868c2ecf20Sopenharmony_ci "address=%p\n", ioc->name, __func__, 39878c2ecf20Sopenharmony_ci &ioc->chip->Doorbell, &ioc->chip->Reset_1078)); 39888c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Reset_1078, 0x07); 39898c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) 39908c2ecf20Sopenharmony_ci msleep(1); 39918c2ecf20Sopenharmony_ci else 39928c2ecf20Sopenharmony_ci mdelay(1); 39938c2ecf20Sopenharmony_ci 39948c2ecf20Sopenharmony_ci /* 39958c2ecf20Sopenharmony_ci * Call each currently registered protocol IOC reset handler 39968c2ecf20Sopenharmony_ci * with pre-reset indication. 39978c2ecf20Sopenharmony_ci * NOTE: If we're doing _IOC_BRINGUP, there can be no 39988c2ecf20Sopenharmony_ci * MptResetHandlers[] registered yet. 39998c2ecf20Sopenharmony_ci */ 40008c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 40018c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) 40028c2ecf20Sopenharmony_ci (*(MptResetHandlers[cb_idx]))(ioc, 40038c2ecf20Sopenharmony_ci MPT_IOC_PRE_RESET); 40048c2ecf20Sopenharmony_ci } 40058c2ecf20Sopenharmony_ci 40068c2ecf20Sopenharmony_ci for (count = 0; count < 60; count ++) { 40078c2ecf20Sopenharmony_ci doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); 40088c2ecf20Sopenharmony_ci doorbell &= MPI_IOC_STATE_MASK; 40098c2ecf20Sopenharmony_ci 40108c2ecf20Sopenharmony_ci drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 40118c2ecf20Sopenharmony_ci "looking for READY STATE: doorbell=%x" 40128c2ecf20Sopenharmony_ci " count=%d\n", 40138c2ecf20Sopenharmony_ci ioc->name, doorbell, count)); 40148c2ecf20Sopenharmony_ci 40158c2ecf20Sopenharmony_ci if (doorbell == MPI_IOC_STATE_READY) { 40168c2ecf20Sopenharmony_ci return 1; 40178c2ecf20Sopenharmony_ci } 40188c2ecf20Sopenharmony_ci 40198c2ecf20Sopenharmony_ci /* wait 1 sec */ 40208c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) 40218c2ecf20Sopenharmony_ci msleep(1000); 40228c2ecf20Sopenharmony_ci else 40238c2ecf20Sopenharmony_ci mdelay(1000); 40248c2ecf20Sopenharmony_ci } 40258c2ecf20Sopenharmony_ci return -1; 40268c2ecf20Sopenharmony_ci } 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_ci /* Use "Diagnostic reset" method! (only thing available!) */ 40298c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 40308c2ecf20Sopenharmony_ci 40318c2ecf20Sopenharmony_ci if (ioc->debug_level & MPT_DEBUG) { 40328c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 40338c2ecf20Sopenharmony_ci diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); 40348c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG1: diag0=%08x, diag1=%08x\n", 40358c2ecf20Sopenharmony_ci ioc->name, diag0val, diag1val)); 40368c2ecf20Sopenharmony_ci } 40378c2ecf20Sopenharmony_ci 40388c2ecf20Sopenharmony_ci /* Do the reset if we are told to ignore the reset history 40398c2ecf20Sopenharmony_ci * or if the reset history is 0 40408c2ecf20Sopenharmony_ci */ 40418c2ecf20Sopenharmony_ci if (ignore || !(diag0val & MPI_DIAG_RESET_HISTORY)) { 40428c2ecf20Sopenharmony_ci while ((diag0val & MPI_DIAG_DRWE) == 0) { 40438c2ecf20Sopenharmony_ci /* Write magic sequence to WriteSequence register 40448c2ecf20Sopenharmony_ci * Loop until in diagnostic mode 40458c2ecf20Sopenharmony_ci */ 40468c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); 40478c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); 40488c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); 40498c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); 40508c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); 40518c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); 40528c2ecf20Sopenharmony_ci 40538c2ecf20Sopenharmony_ci /* wait 100 msec */ 40548c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 40558c2ecf20Sopenharmony_ci msleep (100); 40568c2ecf20Sopenharmony_ci } else { 40578c2ecf20Sopenharmony_ci mdelay (100); 40588c2ecf20Sopenharmony_ci } 40598c2ecf20Sopenharmony_ci 40608c2ecf20Sopenharmony_ci count++; 40618c2ecf20Sopenharmony_ci if (count > 20) { 40628c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n", 40638c2ecf20Sopenharmony_ci ioc->name, diag0val); 40648c2ecf20Sopenharmony_ci return -2; 40658c2ecf20Sopenharmony_ci 40668c2ecf20Sopenharmony_ci } 40678c2ecf20Sopenharmony_ci 40688c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 40698c2ecf20Sopenharmony_ci 40708c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wrote magic DiagWriteEn sequence (%x)\n", 40718c2ecf20Sopenharmony_ci ioc->name, diag0val)); 40728c2ecf20Sopenharmony_ci } 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci if (ioc->debug_level & MPT_DEBUG) { 40758c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 40768c2ecf20Sopenharmony_ci diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); 40778c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG2: diag0=%08x, diag1=%08x\n", 40788c2ecf20Sopenharmony_ci ioc->name, diag0val, diag1val)); 40798c2ecf20Sopenharmony_ci } 40808c2ecf20Sopenharmony_ci /* 40818c2ecf20Sopenharmony_ci * Disable the ARM (Bug fix) 40828c2ecf20Sopenharmony_ci * 40838c2ecf20Sopenharmony_ci */ 40848c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM); 40858c2ecf20Sopenharmony_ci mdelay(1); 40868c2ecf20Sopenharmony_ci 40878c2ecf20Sopenharmony_ci /* 40888c2ecf20Sopenharmony_ci * Now hit the reset bit in the Diagnostic register 40898c2ecf20Sopenharmony_ci * (THE BIG HAMMER!) (Clears DRWE bit). 40908c2ecf20Sopenharmony_ci */ 40918c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER); 40928c2ecf20Sopenharmony_ci hard_reset_done = 1; 40938c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset performed\n", 40948c2ecf20Sopenharmony_ci ioc->name)); 40958c2ecf20Sopenharmony_ci 40968c2ecf20Sopenharmony_ci /* 40978c2ecf20Sopenharmony_ci * Call each currently registered protocol IOC reset handler 40988c2ecf20Sopenharmony_ci * with pre-reset indication. 40998c2ecf20Sopenharmony_ci * NOTE: If we're doing _IOC_BRINGUP, there can be no 41008c2ecf20Sopenharmony_ci * MptResetHandlers[] registered yet. 41018c2ecf20Sopenharmony_ci */ 41028c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 41038c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) { 41048c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, 41058c2ecf20Sopenharmony_ci ioc, MPT_IOC_PRE_RESET); 41068c2ecf20Sopenharmony_ci if (ioc->alt_ioc) { 41078c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, 41088c2ecf20Sopenharmony_ci ioc->alt_ioc, MPT_IOC_PRE_RESET); 41098c2ecf20Sopenharmony_ci } 41108c2ecf20Sopenharmony_ci } 41118c2ecf20Sopenharmony_ci } 41128c2ecf20Sopenharmony_ci 41138c2ecf20Sopenharmony_ci if (ioc->cached_fw) 41148c2ecf20Sopenharmony_ci cached_fw = (MpiFwHeader_t *)ioc->cached_fw; 41158c2ecf20Sopenharmony_ci else if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) 41168c2ecf20Sopenharmony_ci cached_fw = (MpiFwHeader_t *)ioc->alt_ioc->cached_fw; 41178c2ecf20Sopenharmony_ci else 41188c2ecf20Sopenharmony_ci cached_fw = NULL; 41198c2ecf20Sopenharmony_ci if (cached_fw) { 41208c2ecf20Sopenharmony_ci /* If the DownloadBoot operation fails, the 41218c2ecf20Sopenharmony_ci * IOC will be left unusable. This is a fatal error 41228c2ecf20Sopenharmony_ci * case. _diag_reset will return < 0 41238c2ecf20Sopenharmony_ci */ 41248c2ecf20Sopenharmony_ci for (count = 0; count < 30; count ++) { 41258c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 41268c2ecf20Sopenharmony_ci if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) { 41278c2ecf20Sopenharmony_ci break; 41288c2ecf20Sopenharmony_ci } 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "cached_fw: diag0val=%x count=%d\n", 41318c2ecf20Sopenharmony_ci ioc->name, diag0val, count)); 41328c2ecf20Sopenharmony_ci /* wait 1 sec */ 41338c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 41348c2ecf20Sopenharmony_ci msleep (1000); 41358c2ecf20Sopenharmony_ci } else { 41368c2ecf20Sopenharmony_ci mdelay (1000); 41378c2ecf20Sopenharmony_ci } 41388c2ecf20Sopenharmony_ci } 41398c2ecf20Sopenharmony_ci if ((count = mpt_downloadboot(ioc, cached_fw, sleepFlag)) < 0) { 41408c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 41418c2ecf20Sopenharmony_ci "firmware downloadboot failure (%d)!\n", ioc->name, count); 41428c2ecf20Sopenharmony_ci } 41438c2ecf20Sopenharmony_ci 41448c2ecf20Sopenharmony_ci } else { 41458c2ecf20Sopenharmony_ci /* Wait for FW to reload and for board 41468c2ecf20Sopenharmony_ci * to go to the READY state. 41478c2ecf20Sopenharmony_ci * Maximum wait is 60 seconds. 41488c2ecf20Sopenharmony_ci * If fail, no error will check again 41498c2ecf20Sopenharmony_ci * with calling program. 41508c2ecf20Sopenharmony_ci */ 41518c2ecf20Sopenharmony_ci for (count = 0; count < 60; count ++) { 41528c2ecf20Sopenharmony_ci doorbell = CHIPREG_READ32(&ioc->chip->Doorbell); 41538c2ecf20Sopenharmony_ci doorbell &= MPI_IOC_STATE_MASK; 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ci drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT 41568c2ecf20Sopenharmony_ci "looking for READY STATE: doorbell=%x" 41578c2ecf20Sopenharmony_ci " count=%d\n", ioc->name, doorbell, count)); 41588c2ecf20Sopenharmony_ci 41598c2ecf20Sopenharmony_ci if (doorbell == MPI_IOC_STATE_READY) { 41608c2ecf20Sopenharmony_ci break; 41618c2ecf20Sopenharmony_ci } 41628c2ecf20Sopenharmony_ci 41638c2ecf20Sopenharmony_ci /* wait 1 sec */ 41648c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 41658c2ecf20Sopenharmony_ci msleep (1000); 41668c2ecf20Sopenharmony_ci } else { 41678c2ecf20Sopenharmony_ci mdelay (1000); 41688c2ecf20Sopenharmony_ci } 41698c2ecf20Sopenharmony_ci } 41708c2ecf20Sopenharmony_ci 41718c2ecf20Sopenharmony_ci if (doorbell != MPI_IOC_STATE_READY) 41728c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Failed to come READY " 41738c2ecf20Sopenharmony_ci "after reset! IocState=%x", ioc->name, 41748c2ecf20Sopenharmony_ci doorbell); 41758c2ecf20Sopenharmony_ci } 41768c2ecf20Sopenharmony_ci } 41778c2ecf20Sopenharmony_ci 41788c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 41798c2ecf20Sopenharmony_ci if (ioc->debug_level & MPT_DEBUG) { 41808c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 41818c2ecf20Sopenharmony_ci diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); 41828c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG3: diag0=%08x, diag1=%08x\n", 41838c2ecf20Sopenharmony_ci ioc->name, diag0val, diag1val)); 41848c2ecf20Sopenharmony_ci } 41858c2ecf20Sopenharmony_ci 41868c2ecf20Sopenharmony_ci /* Clear RESET_HISTORY bit! Place board in the 41878c2ecf20Sopenharmony_ci * diagnostic mode to update the diag register. 41888c2ecf20Sopenharmony_ci */ 41898c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 41908c2ecf20Sopenharmony_ci count = 0; 41918c2ecf20Sopenharmony_ci while ((diag0val & MPI_DIAG_DRWE) == 0) { 41928c2ecf20Sopenharmony_ci /* Write magic sequence to WriteSequence register 41938c2ecf20Sopenharmony_ci * Loop until in diagnostic mode 41948c2ecf20Sopenharmony_ci */ 41958c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); 41968c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); 41978c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); 41988c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); 41998c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE); 42008c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE); 42018c2ecf20Sopenharmony_ci 42028c2ecf20Sopenharmony_ci /* wait 100 msec */ 42038c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 42048c2ecf20Sopenharmony_ci msleep (100); 42058c2ecf20Sopenharmony_ci } else { 42068c2ecf20Sopenharmony_ci mdelay (100); 42078c2ecf20Sopenharmony_ci } 42088c2ecf20Sopenharmony_ci 42098c2ecf20Sopenharmony_ci count++; 42108c2ecf20Sopenharmony_ci if (count > 20) { 42118c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n", 42128c2ecf20Sopenharmony_ci ioc->name, diag0val); 42138c2ecf20Sopenharmony_ci break; 42148c2ecf20Sopenharmony_ci } 42158c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 42168c2ecf20Sopenharmony_ci } 42178c2ecf20Sopenharmony_ci diag0val &= ~MPI_DIAG_RESET_HISTORY; 42188c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); 42198c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 42208c2ecf20Sopenharmony_ci if (diag0val & MPI_DIAG_RESET_HISTORY) { 42218c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n", 42228c2ecf20Sopenharmony_ci ioc->name); 42238c2ecf20Sopenharmony_ci } 42248c2ecf20Sopenharmony_ci 42258c2ecf20Sopenharmony_ci /* Disable Diagnostic Mode 42268c2ecf20Sopenharmony_ci */ 42278c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF); 42288c2ecf20Sopenharmony_ci 42298c2ecf20Sopenharmony_ci /* Check FW reload status flags. 42308c2ecf20Sopenharmony_ci */ 42318c2ecf20Sopenharmony_ci diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); 42328c2ecf20Sopenharmony_ci if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) { 42338c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n", 42348c2ecf20Sopenharmony_ci ioc->name, diag0val); 42358c2ecf20Sopenharmony_ci return -3; 42368c2ecf20Sopenharmony_ci } 42378c2ecf20Sopenharmony_ci 42388c2ecf20Sopenharmony_ci if (ioc->debug_level & MPT_DEBUG) { 42398c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 42408c2ecf20Sopenharmony_ci diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic); 42418c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DbG4: diag0=%08x, diag1=%08x\n", 42428c2ecf20Sopenharmony_ci ioc->name, diag0val, diag1val)); 42438c2ecf20Sopenharmony_ci } 42448c2ecf20Sopenharmony_ci 42458c2ecf20Sopenharmony_ci /* 42468c2ecf20Sopenharmony_ci * Reset flag that says we've enabled event notification 42478c2ecf20Sopenharmony_ci */ 42488c2ecf20Sopenharmony_ci ioc->facts.EventState = 0; 42498c2ecf20Sopenharmony_ci 42508c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 42518c2ecf20Sopenharmony_ci ioc->alt_ioc->facts.EventState = 0; 42528c2ecf20Sopenharmony_ci 42538c2ecf20Sopenharmony_ci return hard_reset_done; 42548c2ecf20Sopenharmony_ci} 42558c2ecf20Sopenharmony_ci 42568c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 42578c2ecf20Sopenharmony_ci/** 42588c2ecf20Sopenharmony_ci * SendIocReset - Send IOCReset request to MPT adapter. 42598c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 42608c2ecf20Sopenharmony_ci * @reset_type: reset type, expected values are 42618c2ecf20Sopenharmony_ci * %MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET or %MPI_FUNCTION_IO_UNIT_RESET 42628c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 42638c2ecf20Sopenharmony_ci * 42648c2ecf20Sopenharmony_ci * Send IOCReset request to the MPT adapter. 42658c2ecf20Sopenharmony_ci * 42668c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 42678c2ecf20Sopenharmony_ci */ 42688c2ecf20Sopenharmony_cistatic int 42698c2ecf20Sopenharmony_ciSendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) 42708c2ecf20Sopenharmony_ci{ 42718c2ecf20Sopenharmony_ci int r; 42728c2ecf20Sopenharmony_ci u32 state; 42738c2ecf20Sopenharmony_ci int cntdn, count; 42748c2ecf20Sopenharmony_ci 42758c2ecf20Sopenharmony_ci drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending IOC reset(0x%02x)!\n", 42768c2ecf20Sopenharmony_ci ioc->name, reset_type)); 42778c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT); 42788c2ecf20Sopenharmony_ci if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) 42798c2ecf20Sopenharmony_ci return r; 42808c2ecf20Sopenharmony_ci 42818c2ecf20Sopenharmony_ci /* FW ACK'd request, wait for READY state 42828c2ecf20Sopenharmony_ci */ 42838c2ecf20Sopenharmony_ci count = 0; 42848c2ecf20Sopenharmony_ci cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */ 42858c2ecf20Sopenharmony_ci 42868c2ecf20Sopenharmony_ci while ((state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { 42878c2ecf20Sopenharmony_ci cntdn--; 42888c2ecf20Sopenharmony_ci count++; 42898c2ecf20Sopenharmony_ci if (!cntdn) { 42908c2ecf20Sopenharmony_ci if (sleepFlag != CAN_SLEEP) 42918c2ecf20Sopenharmony_ci count *= 10; 42928c2ecf20Sopenharmony_ci 42938c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 42948c2ecf20Sopenharmony_ci "Wait IOC_READY state (0x%x) timeout(%d)!\n", 42958c2ecf20Sopenharmony_ci ioc->name, state, (int)((count+5)/HZ)); 42968c2ecf20Sopenharmony_ci return -ETIME; 42978c2ecf20Sopenharmony_ci } 42988c2ecf20Sopenharmony_ci 42998c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 43008c2ecf20Sopenharmony_ci msleep(1); 43018c2ecf20Sopenharmony_ci } else { 43028c2ecf20Sopenharmony_ci mdelay (1); /* 1 msec delay */ 43038c2ecf20Sopenharmony_ci } 43048c2ecf20Sopenharmony_ci } 43058c2ecf20Sopenharmony_ci 43068c2ecf20Sopenharmony_ci /* TODO! 43078c2ecf20Sopenharmony_ci * Cleanup all event stuff for this IOC; re-issue EventNotification 43088c2ecf20Sopenharmony_ci * request if needed. 43098c2ecf20Sopenharmony_ci */ 43108c2ecf20Sopenharmony_ci if (ioc->facts.Function) 43118c2ecf20Sopenharmony_ci ioc->facts.EventState = 0; 43128c2ecf20Sopenharmony_ci 43138c2ecf20Sopenharmony_ci return 0; 43148c2ecf20Sopenharmony_ci} 43158c2ecf20Sopenharmony_ci 43168c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 43178c2ecf20Sopenharmony_ci/** 43188c2ecf20Sopenharmony_ci * initChainBuffers - Allocate memory for and initialize chain buffers 43198c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 43208c2ecf20Sopenharmony_ci * 43218c2ecf20Sopenharmony_ci * Allocates memory for and initializes chain buffers, 43228c2ecf20Sopenharmony_ci * chain buffer control arrays and spinlock. 43238c2ecf20Sopenharmony_ci */ 43248c2ecf20Sopenharmony_cistatic int 43258c2ecf20Sopenharmony_ciinitChainBuffers(MPT_ADAPTER *ioc) 43268c2ecf20Sopenharmony_ci{ 43278c2ecf20Sopenharmony_ci u8 *mem; 43288c2ecf20Sopenharmony_ci int sz, ii, num_chain; 43298c2ecf20Sopenharmony_ci int scale, num_sge, numSGE; 43308c2ecf20Sopenharmony_ci 43318c2ecf20Sopenharmony_ci /* ReqToChain size must equal the req_depth 43328c2ecf20Sopenharmony_ci * index = req_idx 43338c2ecf20Sopenharmony_ci */ 43348c2ecf20Sopenharmony_ci if (ioc->ReqToChain == NULL) { 43358c2ecf20Sopenharmony_ci sz = ioc->req_depth * sizeof(int); 43368c2ecf20Sopenharmony_ci mem = kmalloc(sz, GFP_ATOMIC); 43378c2ecf20Sopenharmony_ci if (mem == NULL) 43388c2ecf20Sopenharmony_ci return -1; 43398c2ecf20Sopenharmony_ci 43408c2ecf20Sopenharmony_ci ioc->ReqToChain = (int *) mem; 43418c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReqToChain alloc @ %p, sz=%d bytes\n", 43428c2ecf20Sopenharmony_ci ioc->name, mem, sz)); 43438c2ecf20Sopenharmony_ci mem = kmalloc(sz, GFP_ATOMIC); 43448c2ecf20Sopenharmony_ci if (mem == NULL) 43458c2ecf20Sopenharmony_ci return -1; 43468c2ecf20Sopenharmony_ci 43478c2ecf20Sopenharmony_ci ioc->RequestNB = (int *) mem; 43488c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestNB alloc @ %p, sz=%d bytes\n", 43498c2ecf20Sopenharmony_ci ioc->name, mem, sz)); 43508c2ecf20Sopenharmony_ci } 43518c2ecf20Sopenharmony_ci for (ii = 0; ii < ioc->req_depth; ii++) { 43528c2ecf20Sopenharmony_ci ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN; 43538c2ecf20Sopenharmony_ci } 43548c2ecf20Sopenharmony_ci 43558c2ecf20Sopenharmony_ci /* ChainToChain size must equal the total number 43568c2ecf20Sopenharmony_ci * of chain buffers to be allocated. 43578c2ecf20Sopenharmony_ci * index = chain_idx 43588c2ecf20Sopenharmony_ci * 43598c2ecf20Sopenharmony_ci * Calculate the number of chain buffers needed(plus 1) per I/O 43608c2ecf20Sopenharmony_ci * then multiply the maximum number of simultaneous cmds 43618c2ecf20Sopenharmony_ci * 43628c2ecf20Sopenharmony_ci * num_sge = num sge in request frame + last chain buffer 43638c2ecf20Sopenharmony_ci * scale = num sge per chain buffer if no chain element 43648c2ecf20Sopenharmony_ci */ 43658c2ecf20Sopenharmony_ci scale = ioc->req_sz / ioc->SGE_size; 43668c2ecf20Sopenharmony_ci if (ioc->sg_addr_size == sizeof(u64)) 43678c2ecf20Sopenharmony_ci num_sge = scale + (ioc->req_sz - 60) / ioc->SGE_size; 43688c2ecf20Sopenharmony_ci else 43698c2ecf20Sopenharmony_ci num_sge = 1 + scale + (ioc->req_sz - 64) / ioc->SGE_size; 43708c2ecf20Sopenharmony_ci 43718c2ecf20Sopenharmony_ci if (ioc->sg_addr_size == sizeof(u64)) { 43728c2ecf20Sopenharmony_ci numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale + 43738c2ecf20Sopenharmony_ci (ioc->req_sz - 60) / ioc->SGE_size; 43748c2ecf20Sopenharmony_ci } else { 43758c2ecf20Sopenharmony_ci numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + 43768c2ecf20Sopenharmony_ci scale + (ioc->req_sz - 64) / ioc->SGE_size; 43778c2ecf20Sopenharmony_ci } 43788c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "num_sge=%d numSGE=%d\n", 43798c2ecf20Sopenharmony_ci ioc->name, num_sge, numSGE)); 43808c2ecf20Sopenharmony_ci 43818c2ecf20Sopenharmony_ci if (ioc->bus_type == FC) { 43828c2ecf20Sopenharmony_ci if (numSGE > MPT_SCSI_FC_SG_DEPTH) 43838c2ecf20Sopenharmony_ci numSGE = MPT_SCSI_FC_SG_DEPTH; 43848c2ecf20Sopenharmony_ci } else { 43858c2ecf20Sopenharmony_ci if (numSGE > MPT_SCSI_SG_DEPTH) 43868c2ecf20Sopenharmony_ci numSGE = MPT_SCSI_SG_DEPTH; 43878c2ecf20Sopenharmony_ci } 43888c2ecf20Sopenharmony_ci 43898c2ecf20Sopenharmony_ci num_chain = 1; 43908c2ecf20Sopenharmony_ci while (numSGE - num_sge > 0) { 43918c2ecf20Sopenharmony_ci num_chain++; 43928c2ecf20Sopenharmony_ci num_sge += (scale - 1); 43938c2ecf20Sopenharmony_ci } 43948c2ecf20Sopenharmony_ci num_chain++; 43958c2ecf20Sopenharmony_ci 43968c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Now numSGE=%d num_sge=%d num_chain=%d\n", 43978c2ecf20Sopenharmony_ci ioc->name, numSGE, num_sge, num_chain)); 43988c2ecf20Sopenharmony_ci 43998c2ecf20Sopenharmony_ci if (ioc->bus_type == SPI) 44008c2ecf20Sopenharmony_ci num_chain *= MPT_SCSI_CAN_QUEUE; 44018c2ecf20Sopenharmony_ci else if (ioc->bus_type == SAS) 44028c2ecf20Sopenharmony_ci num_chain *= MPT_SAS_CAN_QUEUE; 44038c2ecf20Sopenharmony_ci else 44048c2ecf20Sopenharmony_ci num_chain *= MPT_FC_CAN_QUEUE; 44058c2ecf20Sopenharmony_ci 44068c2ecf20Sopenharmony_ci ioc->num_chain = num_chain; 44078c2ecf20Sopenharmony_ci 44088c2ecf20Sopenharmony_ci sz = num_chain * sizeof(int); 44098c2ecf20Sopenharmony_ci if (ioc->ChainToChain == NULL) { 44108c2ecf20Sopenharmony_ci mem = kmalloc(sz, GFP_ATOMIC); 44118c2ecf20Sopenharmony_ci if (mem == NULL) 44128c2ecf20Sopenharmony_ci return -1; 44138c2ecf20Sopenharmony_ci 44148c2ecf20Sopenharmony_ci ioc->ChainToChain = (int *) mem; 44158c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainToChain alloc @ %p, sz=%d bytes\n", 44168c2ecf20Sopenharmony_ci ioc->name, mem, sz)); 44178c2ecf20Sopenharmony_ci } else { 44188c2ecf20Sopenharmony_ci mem = (u8 *) ioc->ChainToChain; 44198c2ecf20Sopenharmony_ci } 44208c2ecf20Sopenharmony_ci memset(mem, 0xFF, sz); 44218c2ecf20Sopenharmony_ci return num_chain; 44228c2ecf20Sopenharmony_ci} 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 44258c2ecf20Sopenharmony_ci/** 44268c2ecf20Sopenharmony_ci * PrimeIocFifos - Initialize IOC request and reply FIFOs. 44278c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 44288c2ecf20Sopenharmony_ci * 44298c2ecf20Sopenharmony_ci * This routine allocates memory for the MPT reply and request frame 44308c2ecf20Sopenharmony_ci * pools (if necessary), and primes the IOC reply FIFO with 44318c2ecf20Sopenharmony_ci * reply frames. 44328c2ecf20Sopenharmony_ci * 44338c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 44348c2ecf20Sopenharmony_ci */ 44358c2ecf20Sopenharmony_cistatic int 44368c2ecf20Sopenharmony_ciPrimeIocFifos(MPT_ADAPTER *ioc) 44378c2ecf20Sopenharmony_ci{ 44388c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf; 44398c2ecf20Sopenharmony_ci unsigned long flags; 44408c2ecf20Sopenharmony_ci dma_addr_t alloc_dma; 44418c2ecf20Sopenharmony_ci u8 *mem; 44428c2ecf20Sopenharmony_ci int i, reply_sz, sz, total_size, num_chain; 44438c2ecf20Sopenharmony_ci u64 dma_mask; 44448c2ecf20Sopenharmony_ci 44458c2ecf20Sopenharmony_ci dma_mask = 0; 44468c2ecf20Sopenharmony_ci 44478c2ecf20Sopenharmony_ci /* Prime reply FIFO... */ 44488c2ecf20Sopenharmony_ci 44498c2ecf20Sopenharmony_ci if (ioc->reply_frames == NULL) { 44508c2ecf20Sopenharmony_ci if ( (num_chain = initChainBuffers(ioc)) < 0) 44518c2ecf20Sopenharmony_ci return -1; 44528c2ecf20Sopenharmony_ci /* 44538c2ecf20Sopenharmony_ci * 1078 errata workaround for the 36GB limitation 44548c2ecf20Sopenharmony_ci */ 44558c2ecf20Sopenharmony_ci if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078 && 44568c2ecf20Sopenharmony_ci ioc->dma_mask > DMA_BIT_MASK(35)) { 44578c2ecf20Sopenharmony_ci if (!pci_set_dma_mask(ioc->pcidev, DMA_BIT_MASK(32)) 44588c2ecf20Sopenharmony_ci && !pci_set_consistent_dma_mask(ioc->pcidev, 44598c2ecf20Sopenharmony_ci DMA_BIT_MASK(32))) { 44608c2ecf20Sopenharmony_ci dma_mask = DMA_BIT_MASK(35); 44618c2ecf20Sopenharmony_ci d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT 44628c2ecf20Sopenharmony_ci "setting 35 bit addressing for " 44638c2ecf20Sopenharmony_ci "Request/Reply/Chain and Sense Buffers\n", 44648c2ecf20Sopenharmony_ci ioc->name)); 44658c2ecf20Sopenharmony_ci } else { 44668c2ecf20Sopenharmony_ci /*Reseting DMA mask to 64 bit*/ 44678c2ecf20Sopenharmony_ci pci_set_dma_mask(ioc->pcidev, 44688c2ecf20Sopenharmony_ci DMA_BIT_MASK(64)); 44698c2ecf20Sopenharmony_ci pci_set_consistent_dma_mask(ioc->pcidev, 44708c2ecf20Sopenharmony_ci DMA_BIT_MASK(64)); 44718c2ecf20Sopenharmony_ci 44728c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT 44738c2ecf20Sopenharmony_ci "failed setting 35 bit addressing for " 44748c2ecf20Sopenharmony_ci "Request/Reply/Chain and Sense Buffers\n", 44758c2ecf20Sopenharmony_ci ioc->name); 44768c2ecf20Sopenharmony_ci return -1; 44778c2ecf20Sopenharmony_ci } 44788c2ecf20Sopenharmony_ci } 44798c2ecf20Sopenharmony_ci 44808c2ecf20Sopenharmony_ci total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth); 44818c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d bytes, ReplyDepth=%d\n", 44828c2ecf20Sopenharmony_ci ioc->name, ioc->reply_sz, ioc->reply_depth)); 44838c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffer sz=%d[%x] bytes\n", 44848c2ecf20Sopenharmony_ci ioc->name, reply_sz, reply_sz)); 44858c2ecf20Sopenharmony_ci 44868c2ecf20Sopenharmony_ci sz = (ioc->req_sz * ioc->req_depth); 44878c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d bytes, RequestDepth=%d\n", 44888c2ecf20Sopenharmony_ci ioc->name, ioc->req_sz, ioc->req_depth)); 44898c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffer sz=%d[%x] bytes\n", 44908c2ecf20Sopenharmony_ci ioc->name, sz, sz)); 44918c2ecf20Sopenharmony_ci total_size += sz; 44928c2ecf20Sopenharmony_ci 44938c2ecf20Sopenharmony_ci sz = num_chain * ioc->req_sz; /* chain buffer pool size */ 44948c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d bytes, ChainDepth=%d\n", 44958c2ecf20Sopenharmony_ci ioc->name, ioc->req_sz, num_chain)); 44968c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffer sz=%d[%x] bytes num_chain=%d\n", 44978c2ecf20Sopenharmony_ci ioc->name, sz, sz, num_chain)); 44988c2ecf20Sopenharmony_ci 44998c2ecf20Sopenharmony_ci total_size += sz; 45008c2ecf20Sopenharmony_ci mem = dma_alloc_coherent(&ioc->pcidev->dev, total_size, 45018c2ecf20Sopenharmony_ci &alloc_dma, GFP_KERNEL); 45028c2ecf20Sopenharmony_ci if (mem == NULL) { 45038c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n", 45048c2ecf20Sopenharmony_ci ioc->name); 45058c2ecf20Sopenharmony_ci goto out_fail; 45068c2ecf20Sopenharmony_ci } 45078c2ecf20Sopenharmony_ci 45088c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Total alloc @ %p[%p], sz=%d[%x] bytes\n", 45098c2ecf20Sopenharmony_ci ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size)); 45108c2ecf20Sopenharmony_ci 45118c2ecf20Sopenharmony_ci memset(mem, 0, total_size); 45128c2ecf20Sopenharmony_ci ioc->alloc_total += total_size; 45138c2ecf20Sopenharmony_ci ioc->alloc = mem; 45148c2ecf20Sopenharmony_ci ioc->alloc_dma = alloc_dma; 45158c2ecf20Sopenharmony_ci ioc->alloc_sz = total_size; 45168c2ecf20Sopenharmony_ci ioc->reply_frames = (MPT_FRAME_HDR *) mem; 45178c2ecf20Sopenharmony_ci ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); 45188c2ecf20Sopenharmony_ci 45198c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n", 45208c2ecf20Sopenharmony_ci ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); 45218c2ecf20Sopenharmony_ci 45228c2ecf20Sopenharmony_ci alloc_dma += reply_sz; 45238c2ecf20Sopenharmony_ci mem += reply_sz; 45248c2ecf20Sopenharmony_ci 45258c2ecf20Sopenharmony_ci /* Request FIFO - WE manage this! */ 45268c2ecf20Sopenharmony_ci 45278c2ecf20Sopenharmony_ci ioc->req_frames = (MPT_FRAME_HDR *) mem; 45288c2ecf20Sopenharmony_ci ioc->req_frames_dma = alloc_dma; 45298c2ecf20Sopenharmony_ci 45308c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RequestBuffers @ %p[%p]\n", 45318c2ecf20Sopenharmony_ci ioc->name, mem, (void *)(ulong)alloc_dma)); 45328c2ecf20Sopenharmony_ci 45338c2ecf20Sopenharmony_ci ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF); 45348c2ecf20Sopenharmony_ci 45358c2ecf20Sopenharmony_ci for (i = 0; i < ioc->req_depth; i++) { 45368c2ecf20Sopenharmony_ci alloc_dma += ioc->req_sz; 45378c2ecf20Sopenharmony_ci mem += ioc->req_sz; 45388c2ecf20Sopenharmony_ci } 45398c2ecf20Sopenharmony_ci 45408c2ecf20Sopenharmony_ci ioc->ChainBuffer = mem; 45418c2ecf20Sopenharmony_ci ioc->ChainBufferDMA = alloc_dma; 45428c2ecf20Sopenharmony_ci 45438c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ChainBuffers @ %p(%p)\n", 45448c2ecf20Sopenharmony_ci ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA)); 45458c2ecf20Sopenharmony_ci 45468c2ecf20Sopenharmony_ci /* Initialize the free chain Q. 45478c2ecf20Sopenharmony_ci */ 45488c2ecf20Sopenharmony_ci 45498c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ioc->FreeChainQ); 45508c2ecf20Sopenharmony_ci 45518c2ecf20Sopenharmony_ci /* Post the chain buffers to the FreeChainQ. 45528c2ecf20Sopenharmony_ci */ 45538c2ecf20Sopenharmony_ci mem = (u8 *)ioc->ChainBuffer; 45548c2ecf20Sopenharmony_ci for (i=0; i < num_chain; i++) { 45558c2ecf20Sopenharmony_ci mf = (MPT_FRAME_HDR *) mem; 45568c2ecf20Sopenharmony_ci list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeChainQ); 45578c2ecf20Sopenharmony_ci mem += ioc->req_sz; 45588c2ecf20Sopenharmony_ci } 45598c2ecf20Sopenharmony_ci 45608c2ecf20Sopenharmony_ci /* Initialize Request frames linked list 45618c2ecf20Sopenharmony_ci */ 45628c2ecf20Sopenharmony_ci alloc_dma = ioc->req_frames_dma; 45638c2ecf20Sopenharmony_ci mem = (u8 *) ioc->req_frames; 45648c2ecf20Sopenharmony_ci 45658c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->FreeQlock, flags); 45668c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ioc->FreeQ); 45678c2ecf20Sopenharmony_ci for (i = 0; i < ioc->req_depth; i++) { 45688c2ecf20Sopenharmony_ci mf = (MPT_FRAME_HDR *) mem; 45698c2ecf20Sopenharmony_ci 45708c2ecf20Sopenharmony_ci /* Queue REQUESTs *internally*! */ 45718c2ecf20Sopenharmony_ci list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); 45728c2ecf20Sopenharmony_ci 45738c2ecf20Sopenharmony_ci mem += ioc->req_sz; 45748c2ecf20Sopenharmony_ci } 45758c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->FreeQlock, flags); 45768c2ecf20Sopenharmony_ci 45778c2ecf20Sopenharmony_ci sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); 45788c2ecf20Sopenharmony_ci ioc->sense_buf_pool = dma_alloc_coherent(&ioc->pcidev->dev, sz, 45798c2ecf20Sopenharmony_ci &ioc->sense_buf_pool_dma, GFP_KERNEL); 45808c2ecf20Sopenharmony_ci if (ioc->sense_buf_pool == NULL) { 45818c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n", 45828c2ecf20Sopenharmony_ci ioc->name); 45838c2ecf20Sopenharmony_ci goto out_fail; 45848c2ecf20Sopenharmony_ci } 45858c2ecf20Sopenharmony_ci 45868c2ecf20Sopenharmony_ci ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF); 45878c2ecf20Sopenharmony_ci ioc->alloc_total += sz; 45888c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SenseBuffers @ %p[%p]\n", 45898c2ecf20Sopenharmony_ci ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma)); 45908c2ecf20Sopenharmony_ci 45918c2ecf20Sopenharmony_ci } 45928c2ecf20Sopenharmony_ci 45938c2ecf20Sopenharmony_ci /* Post Reply frames to FIFO 45948c2ecf20Sopenharmony_ci */ 45958c2ecf20Sopenharmony_ci alloc_dma = ioc->alloc_dma; 45968c2ecf20Sopenharmony_ci dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ReplyBuffers @ %p[%p]\n", 45978c2ecf20Sopenharmony_ci ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma)); 45988c2ecf20Sopenharmony_ci 45998c2ecf20Sopenharmony_ci for (i = 0; i < ioc->reply_depth; i++) { 46008c2ecf20Sopenharmony_ci /* Write each address to the IOC! */ 46018c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma); 46028c2ecf20Sopenharmony_ci alloc_dma += ioc->reply_sz; 46038c2ecf20Sopenharmony_ci } 46048c2ecf20Sopenharmony_ci 46058c2ecf20Sopenharmony_ci if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev, 46068c2ecf20Sopenharmony_ci ioc->dma_mask) && !pci_set_consistent_dma_mask(ioc->pcidev, 46078c2ecf20Sopenharmony_ci ioc->dma_mask)) 46088c2ecf20Sopenharmony_ci d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT 46098c2ecf20Sopenharmony_ci "restoring 64 bit addressing\n", ioc->name)); 46108c2ecf20Sopenharmony_ci 46118c2ecf20Sopenharmony_ci return 0; 46128c2ecf20Sopenharmony_ci 46138c2ecf20Sopenharmony_ciout_fail: 46148c2ecf20Sopenharmony_ci 46158c2ecf20Sopenharmony_ci if (ioc->alloc != NULL) { 46168c2ecf20Sopenharmony_ci sz = ioc->alloc_sz; 46178c2ecf20Sopenharmony_ci dma_free_coherent(&ioc->pcidev->dev, sz, ioc->alloc, 46188c2ecf20Sopenharmony_ci ioc->alloc_dma); 46198c2ecf20Sopenharmony_ci ioc->reply_frames = NULL; 46208c2ecf20Sopenharmony_ci ioc->req_frames = NULL; 46218c2ecf20Sopenharmony_ci ioc->alloc_total -= sz; 46228c2ecf20Sopenharmony_ci } 46238c2ecf20Sopenharmony_ci if (ioc->sense_buf_pool != NULL) { 46248c2ecf20Sopenharmony_ci sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC); 46258c2ecf20Sopenharmony_ci dma_free_coherent(&ioc->pcidev->dev, sz, ioc->sense_buf_pool, 46268c2ecf20Sopenharmony_ci ioc->sense_buf_pool_dma); 46278c2ecf20Sopenharmony_ci ioc->sense_buf_pool = NULL; 46288c2ecf20Sopenharmony_ci } 46298c2ecf20Sopenharmony_ci 46308c2ecf20Sopenharmony_ci if (dma_mask == DMA_BIT_MASK(35) && !pci_set_dma_mask(ioc->pcidev, 46318c2ecf20Sopenharmony_ci DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(ioc->pcidev, 46328c2ecf20Sopenharmony_ci DMA_BIT_MASK(64))) 46338c2ecf20Sopenharmony_ci d36memprintk(ioc, printk(MYIOC_s_DEBUG_FMT 46348c2ecf20Sopenharmony_ci "restoring 64 bit addressing\n", ioc->name)); 46358c2ecf20Sopenharmony_ci 46368c2ecf20Sopenharmony_ci return -1; 46378c2ecf20Sopenharmony_ci} 46388c2ecf20Sopenharmony_ci 46398c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 46408c2ecf20Sopenharmony_ci/** 46418c2ecf20Sopenharmony_ci * mpt_handshake_req_reply_wait - Send MPT request to and receive reply 46428c2ecf20Sopenharmony_ci * from IOC via doorbell handshake method. 46438c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 46448c2ecf20Sopenharmony_ci * @reqBytes: Size of the request in bytes 46458c2ecf20Sopenharmony_ci * @req: Pointer to MPT request frame 46468c2ecf20Sopenharmony_ci * @replyBytes: Expected size of the reply in bytes 46478c2ecf20Sopenharmony_ci * @u16reply: Pointer to area where reply should be written 46488c2ecf20Sopenharmony_ci * @maxwait: Max wait time for a reply (in seconds) 46498c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 46508c2ecf20Sopenharmony_ci * 46518c2ecf20Sopenharmony_ci * NOTES: It is the callers responsibility to byte-swap fields in the 46528c2ecf20Sopenharmony_ci * request which are greater than 1 byte in size. It is also the 46538c2ecf20Sopenharmony_ci * callers responsibility to byte-swap response fields which are 46548c2ecf20Sopenharmony_ci * greater than 1 byte in size. 46558c2ecf20Sopenharmony_ci * 46568c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 46578c2ecf20Sopenharmony_ci */ 46588c2ecf20Sopenharmony_cistatic int 46598c2ecf20Sopenharmony_cimpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, 46608c2ecf20Sopenharmony_ci int replyBytes, u16 *u16reply, int maxwait, int sleepFlag) 46618c2ecf20Sopenharmony_ci{ 46628c2ecf20Sopenharmony_ci MPIDefaultReply_t *mptReply; 46638c2ecf20Sopenharmony_ci int failcnt = 0; 46648c2ecf20Sopenharmony_ci int t; 46658c2ecf20Sopenharmony_ci 46668c2ecf20Sopenharmony_ci /* 46678c2ecf20Sopenharmony_ci * Get ready to cache a handshake reply 46688c2ecf20Sopenharmony_ci */ 46698c2ecf20Sopenharmony_ci ioc->hs_reply_idx = 0; 46708c2ecf20Sopenharmony_ci mptReply = (MPIDefaultReply_t *) ioc->hs_reply; 46718c2ecf20Sopenharmony_ci mptReply->MsgLength = 0; 46728c2ecf20Sopenharmony_ci 46738c2ecf20Sopenharmony_ci /* 46748c2ecf20Sopenharmony_ci * Make sure there are no doorbells (WRITE 0 to IntStatus reg), 46758c2ecf20Sopenharmony_ci * then tell IOC that we want to handshake a request of N words. 46768c2ecf20Sopenharmony_ci * (WRITE u32val to Doorbell reg). 46778c2ecf20Sopenharmony_ci */ 46788c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 46798c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, 46808c2ecf20Sopenharmony_ci ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) | 46818c2ecf20Sopenharmony_ci ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))); 46828c2ecf20Sopenharmony_ci 46838c2ecf20Sopenharmony_ci /* 46848c2ecf20Sopenharmony_ci * Wait for IOC's doorbell handshake int 46858c2ecf20Sopenharmony_ci */ 46868c2ecf20Sopenharmony_ci if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) 46878c2ecf20Sopenharmony_ci failcnt++; 46888c2ecf20Sopenharmony_ci 46898c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n", 46908c2ecf20Sopenharmony_ci ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); 46918c2ecf20Sopenharmony_ci 46928c2ecf20Sopenharmony_ci /* Read doorbell and check for active bit */ 46938c2ecf20Sopenharmony_ci if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) 46948c2ecf20Sopenharmony_ci return -1; 46958c2ecf20Sopenharmony_ci 46968c2ecf20Sopenharmony_ci /* 46978c2ecf20Sopenharmony_ci * Clear doorbell int (WRITE 0 to IntStatus reg), 46988c2ecf20Sopenharmony_ci * then wait for IOC to ACKnowledge that it's ready for 46998c2ecf20Sopenharmony_ci * our handshake request. 47008c2ecf20Sopenharmony_ci */ 47018c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 47028c2ecf20Sopenharmony_ci if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) 47038c2ecf20Sopenharmony_ci failcnt++; 47048c2ecf20Sopenharmony_ci 47058c2ecf20Sopenharmony_ci if (!failcnt) { 47068c2ecf20Sopenharmony_ci int ii; 47078c2ecf20Sopenharmony_ci u8 *req_as_bytes = (u8 *) req; 47088c2ecf20Sopenharmony_ci 47098c2ecf20Sopenharmony_ci /* 47108c2ecf20Sopenharmony_ci * Stuff request words via doorbell handshake, 47118c2ecf20Sopenharmony_ci * with ACK from IOC for each. 47128c2ecf20Sopenharmony_ci */ 47138c2ecf20Sopenharmony_ci for (ii = 0; !failcnt && ii < reqBytes/4; ii++) { 47148c2ecf20Sopenharmony_ci u32 word = ((req_as_bytes[(ii*4) + 0] << 0) | 47158c2ecf20Sopenharmony_ci (req_as_bytes[(ii*4) + 1] << 8) | 47168c2ecf20Sopenharmony_ci (req_as_bytes[(ii*4) + 2] << 16) | 47178c2ecf20Sopenharmony_ci (req_as_bytes[(ii*4) + 3] << 24)); 47188c2ecf20Sopenharmony_ci 47198c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, word); 47208c2ecf20Sopenharmony_ci if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) 47218c2ecf20Sopenharmony_ci failcnt++; 47228c2ecf20Sopenharmony_ci } 47238c2ecf20Sopenharmony_ci 47248c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req)); 47258c2ecf20Sopenharmony_ci DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req); 47268c2ecf20Sopenharmony_ci 47278c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n", 47288c2ecf20Sopenharmony_ci ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : "")); 47298c2ecf20Sopenharmony_ci 47308c2ecf20Sopenharmony_ci /* 47318c2ecf20Sopenharmony_ci * Wait for completion of doorbell handshake reply from the IOC 47328c2ecf20Sopenharmony_ci */ 47338c2ecf20Sopenharmony_ci if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0) 47348c2ecf20Sopenharmony_ci failcnt++; 47358c2ecf20Sopenharmony_ci 47368c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake reply count=%d%s\n", 47378c2ecf20Sopenharmony_ci ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : "")); 47388c2ecf20Sopenharmony_ci 47398c2ecf20Sopenharmony_ci /* 47408c2ecf20Sopenharmony_ci * Copy out the cached reply... 47418c2ecf20Sopenharmony_ci */ 47428c2ecf20Sopenharmony_ci for (ii=0; ii < min(replyBytes/2,mptReply->MsgLength*2); ii++) 47438c2ecf20Sopenharmony_ci u16reply[ii] = ioc->hs_reply[ii]; 47448c2ecf20Sopenharmony_ci } else { 47458c2ecf20Sopenharmony_ci return -99; 47468c2ecf20Sopenharmony_ci } 47478c2ecf20Sopenharmony_ci 47488c2ecf20Sopenharmony_ci return -failcnt; 47498c2ecf20Sopenharmony_ci} 47508c2ecf20Sopenharmony_ci 47518c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 47528c2ecf20Sopenharmony_ci/** 47538c2ecf20Sopenharmony_ci * WaitForDoorbellAck - Wait for IOC doorbell handshake acknowledge 47548c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 47558c2ecf20Sopenharmony_ci * @howlong: How long to wait (in seconds) 47568c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 47578c2ecf20Sopenharmony_ci * 47588c2ecf20Sopenharmony_ci * This routine waits (up to ~2 seconds max) for IOC doorbell 47598c2ecf20Sopenharmony_ci * handshake ACKnowledge, indicated by the IOP_DOORBELL_STATUS 47608c2ecf20Sopenharmony_ci * bit in its IntStatus register being clear. 47618c2ecf20Sopenharmony_ci * 47628c2ecf20Sopenharmony_ci * Returns a negative value on failure, else wait loop count. 47638c2ecf20Sopenharmony_ci */ 47648c2ecf20Sopenharmony_cistatic int 47658c2ecf20Sopenharmony_ciWaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) 47668c2ecf20Sopenharmony_ci{ 47678c2ecf20Sopenharmony_ci int cntdn; 47688c2ecf20Sopenharmony_ci int count = 0; 47698c2ecf20Sopenharmony_ci u32 intstat=0; 47708c2ecf20Sopenharmony_ci 47718c2ecf20Sopenharmony_ci cntdn = 1000 * howlong; 47728c2ecf20Sopenharmony_ci 47738c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 47748c2ecf20Sopenharmony_ci while (--cntdn) { 47758c2ecf20Sopenharmony_ci msleep (1); 47768c2ecf20Sopenharmony_ci intstat = CHIPREG_READ32(&ioc->chip->IntStatus); 47778c2ecf20Sopenharmony_ci if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) 47788c2ecf20Sopenharmony_ci break; 47798c2ecf20Sopenharmony_ci count++; 47808c2ecf20Sopenharmony_ci } 47818c2ecf20Sopenharmony_ci } else { 47828c2ecf20Sopenharmony_ci while (--cntdn) { 47838c2ecf20Sopenharmony_ci udelay (1000); 47848c2ecf20Sopenharmony_ci intstat = CHIPREG_READ32(&ioc->chip->IntStatus); 47858c2ecf20Sopenharmony_ci if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) 47868c2ecf20Sopenharmony_ci break; 47878c2ecf20Sopenharmony_ci count++; 47888c2ecf20Sopenharmony_ci } 47898c2ecf20Sopenharmony_ci } 47908c2ecf20Sopenharmony_ci 47918c2ecf20Sopenharmony_ci if (cntdn) { 47928c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell ACK (count=%d)\n", 47938c2ecf20Sopenharmony_ci ioc->name, count)); 47948c2ecf20Sopenharmony_ci return count; 47958c2ecf20Sopenharmony_ci } 47968c2ecf20Sopenharmony_ci 47978c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n", 47988c2ecf20Sopenharmony_ci ioc->name, count, intstat); 47998c2ecf20Sopenharmony_ci return -1; 48008c2ecf20Sopenharmony_ci} 48018c2ecf20Sopenharmony_ci 48028c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 48038c2ecf20Sopenharmony_ci/** 48048c2ecf20Sopenharmony_ci * WaitForDoorbellInt - Wait for IOC to set its doorbell interrupt bit 48058c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 48068c2ecf20Sopenharmony_ci * @howlong: How long to wait (in seconds) 48078c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 48088c2ecf20Sopenharmony_ci * 48098c2ecf20Sopenharmony_ci * This routine waits (up to ~2 seconds max) for IOC doorbell interrupt 48108c2ecf20Sopenharmony_ci * (MPI_HIS_DOORBELL_INTERRUPT) to be set in the IntStatus register. 48118c2ecf20Sopenharmony_ci * 48128c2ecf20Sopenharmony_ci * Returns a negative value on failure, else wait loop count. 48138c2ecf20Sopenharmony_ci */ 48148c2ecf20Sopenharmony_cistatic int 48158c2ecf20Sopenharmony_ciWaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) 48168c2ecf20Sopenharmony_ci{ 48178c2ecf20Sopenharmony_ci int cntdn; 48188c2ecf20Sopenharmony_ci int count = 0; 48198c2ecf20Sopenharmony_ci u32 intstat=0; 48208c2ecf20Sopenharmony_ci 48218c2ecf20Sopenharmony_ci cntdn = 1000 * howlong; 48228c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) { 48238c2ecf20Sopenharmony_ci while (--cntdn) { 48248c2ecf20Sopenharmony_ci intstat = CHIPREG_READ32(&ioc->chip->IntStatus); 48258c2ecf20Sopenharmony_ci if (intstat & MPI_HIS_DOORBELL_INTERRUPT) 48268c2ecf20Sopenharmony_ci break; 48278c2ecf20Sopenharmony_ci msleep(1); 48288c2ecf20Sopenharmony_ci count++; 48298c2ecf20Sopenharmony_ci } 48308c2ecf20Sopenharmony_ci } else { 48318c2ecf20Sopenharmony_ci while (--cntdn) { 48328c2ecf20Sopenharmony_ci intstat = CHIPREG_READ32(&ioc->chip->IntStatus); 48338c2ecf20Sopenharmony_ci if (intstat & MPI_HIS_DOORBELL_INTERRUPT) 48348c2ecf20Sopenharmony_ci break; 48358c2ecf20Sopenharmony_ci udelay (1000); 48368c2ecf20Sopenharmony_ci count++; 48378c2ecf20Sopenharmony_ci } 48388c2ecf20Sopenharmony_ci } 48398c2ecf20Sopenharmony_ci 48408c2ecf20Sopenharmony_ci if (cntdn) { 48418c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n", 48428c2ecf20Sopenharmony_ci ioc->name, count, howlong)); 48438c2ecf20Sopenharmony_ci return count; 48448c2ecf20Sopenharmony_ci } 48458c2ecf20Sopenharmony_ci 48468c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n", 48478c2ecf20Sopenharmony_ci ioc->name, count, intstat); 48488c2ecf20Sopenharmony_ci return -1; 48498c2ecf20Sopenharmony_ci} 48508c2ecf20Sopenharmony_ci 48518c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 48528c2ecf20Sopenharmony_ci/** 48538c2ecf20Sopenharmony_ci * WaitForDoorbellReply - Wait for and capture an IOC handshake reply. 48548c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 48558c2ecf20Sopenharmony_ci * @howlong: How long to wait (in seconds) 48568c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 48578c2ecf20Sopenharmony_ci * 48588c2ecf20Sopenharmony_ci * This routine polls the IOC for a handshake reply, 16 bits at a time. 48598c2ecf20Sopenharmony_ci * Reply is cached to IOC private area large enough to hold a maximum 48608c2ecf20Sopenharmony_ci * of 128 bytes of reply data. 48618c2ecf20Sopenharmony_ci * 48628c2ecf20Sopenharmony_ci * Returns a negative value on failure, else size of reply in WORDS. 48638c2ecf20Sopenharmony_ci */ 48648c2ecf20Sopenharmony_cistatic int 48658c2ecf20Sopenharmony_ciWaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) 48668c2ecf20Sopenharmony_ci{ 48678c2ecf20Sopenharmony_ci int u16cnt = 0; 48688c2ecf20Sopenharmony_ci int failcnt = 0; 48698c2ecf20Sopenharmony_ci int t; 48708c2ecf20Sopenharmony_ci u16 *hs_reply = ioc->hs_reply; 48718c2ecf20Sopenharmony_ci volatile MPIDefaultReply_t *mptReply = (MPIDefaultReply_t *) ioc->hs_reply; 48728c2ecf20Sopenharmony_ci u16 hword; 48738c2ecf20Sopenharmony_ci 48748c2ecf20Sopenharmony_ci hs_reply[0] = hs_reply[1] = hs_reply[7] = 0; 48758c2ecf20Sopenharmony_ci 48768c2ecf20Sopenharmony_ci /* 48778c2ecf20Sopenharmony_ci * Get first two u16's so we can look at IOC's intended reply MsgLength 48788c2ecf20Sopenharmony_ci */ 48798c2ecf20Sopenharmony_ci u16cnt=0; 48808c2ecf20Sopenharmony_ci if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) { 48818c2ecf20Sopenharmony_ci failcnt++; 48828c2ecf20Sopenharmony_ci } else { 48838c2ecf20Sopenharmony_ci hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); 48848c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 48858c2ecf20Sopenharmony_ci if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) 48868c2ecf20Sopenharmony_ci failcnt++; 48878c2ecf20Sopenharmony_ci else { 48888c2ecf20Sopenharmony_ci hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); 48898c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 48908c2ecf20Sopenharmony_ci } 48918c2ecf20Sopenharmony_ci } 48928c2ecf20Sopenharmony_ci 48938c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitCnt=%d First handshake reply word=%08x%s\n", 48948c2ecf20Sopenharmony_ci ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), 48958c2ecf20Sopenharmony_ci failcnt ? " - MISSING DOORBELL HANDSHAKE!" : "")); 48968c2ecf20Sopenharmony_ci 48978c2ecf20Sopenharmony_ci /* 48988c2ecf20Sopenharmony_ci * If no error (and IOC said MsgLength is > 0), piece together 48998c2ecf20Sopenharmony_ci * reply 16 bits at a time. 49008c2ecf20Sopenharmony_ci */ 49018c2ecf20Sopenharmony_ci for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) { 49028c2ecf20Sopenharmony_ci if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) 49038c2ecf20Sopenharmony_ci failcnt++; 49048c2ecf20Sopenharmony_ci hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF); 49058c2ecf20Sopenharmony_ci /* don't overflow our IOC hs_reply[] buffer! */ 49068c2ecf20Sopenharmony_ci if (u16cnt < ARRAY_SIZE(ioc->hs_reply)) 49078c2ecf20Sopenharmony_ci hs_reply[u16cnt] = hword; 49088c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 49098c2ecf20Sopenharmony_ci } 49108c2ecf20Sopenharmony_ci 49118c2ecf20Sopenharmony_ci if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) 49128c2ecf20Sopenharmony_ci failcnt++; 49138c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); 49148c2ecf20Sopenharmony_ci 49158c2ecf20Sopenharmony_ci if (failcnt) { 49168c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n", 49178c2ecf20Sopenharmony_ci ioc->name); 49188c2ecf20Sopenharmony_ci return -failcnt; 49198c2ecf20Sopenharmony_ci } 49208c2ecf20Sopenharmony_ci#if 0 49218c2ecf20Sopenharmony_ci else if (u16cnt != (2 * mptReply->MsgLength)) { 49228c2ecf20Sopenharmony_ci return -101; 49238c2ecf20Sopenharmony_ci } 49248c2ecf20Sopenharmony_ci else if ((mptReply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 49258c2ecf20Sopenharmony_ci return -102; 49268c2ecf20Sopenharmony_ci } 49278c2ecf20Sopenharmony_ci#endif 49288c2ecf20Sopenharmony_ci 49298c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name)); 49308c2ecf20Sopenharmony_ci DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply); 49318c2ecf20Sopenharmony_ci 49328c2ecf20Sopenharmony_ci dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n", 49338c2ecf20Sopenharmony_ci ioc->name, t, u16cnt/2)); 49348c2ecf20Sopenharmony_ci return u16cnt/2; 49358c2ecf20Sopenharmony_ci} 49368c2ecf20Sopenharmony_ci 49378c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 49388c2ecf20Sopenharmony_ci/** 49398c2ecf20Sopenharmony_ci * GetLanConfigPages - Fetch LANConfig pages. 49408c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 49418c2ecf20Sopenharmony_ci * 49428c2ecf20Sopenharmony_ci * Return: 0 for success 49438c2ecf20Sopenharmony_ci * -ENOMEM if no memory available 49448c2ecf20Sopenharmony_ci * -EPERM if not allowed due to ISR context 49458c2ecf20Sopenharmony_ci * -EAGAIN if no msg frames currently available 49468c2ecf20Sopenharmony_ci * -EFAULT for non-successful reply or no reply (timeout) 49478c2ecf20Sopenharmony_ci */ 49488c2ecf20Sopenharmony_cistatic int 49498c2ecf20Sopenharmony_ciGetLanConfigPages(MPT_ADAPTER *ioc) 49508c2ecf20Sopenharmony_ci{ 49518c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 49528c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 49538c2ecf20Sopenharmony_ci LANPage0_t *ppage0_alloc; 49548c2ecf20Sopenharmony_ci dma_addr_t page0_dma; 49558c2ecf20Sopenharmony_ci LANPage1_t *ppage1_alloc; 49568c2ecf20Sopenharmony_ci dma_addr_t page1_dma; 49578c2ecf20Sopenharmony_ci int rc = 0; 49588c2ecf20Sopenharmony_ci int data_sz; 49598c2ecf20Sopenharmony_ci int copy_sz; 49608c2ecf20Sopenharmony_ci 49618c2ecf20Sopenharmony_ci /* Get LAN Page 0 header */ 49628c2ecf20Sopenharmony_ci hdr.PageVersion = 0; 49638c2ecf20Sopenharmony_ci hdr.PageLength = 0; 49648c2ecf20Sopenharmony_ci hdr.PageNumber = 0; 49658c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_LAN; 49668c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 49678c2ecf20Sopenharmony_ci cfg.physAddr = -1; 49688c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 49698c2ecf20Sopenharmony_ci cfg.dir = 0; 49708c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 49718c2ecf20Sopenharmony_ci cfg.timeout = 0; 49728c2ecf20Sopenharmony_ci 49738c2ecf20Sopenharmony_ci if ((rc = mpt_config(ioc, &cfg)) != 0) 49748c2ecf20Sopenharmony_ci return rc; 49758c2ecf20Sopenharmony_ci 49768c2ecf20Sopenharmony_ci if (hdr.PageLength > 0) { 49778c2ecf20Sopenharmony_ci data_sz = hdr.PageLength * 4; 49788c2ecf20Sopenharmony_ci ppage0_alloc = (LANPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); 49798c2ecf20Sopenharmony_ci rc = -ENOMEM; 49808c2ecf20Sopenharmony_ci if (ppage0_alloc) { 49818c2ecf20Sopenharmony_ci memset((u8 *)ppage0_alloc, 0, data_sz); 49828c2ecf20Sopenharmony_ci cfg.physAddr = page0_dma; 49838c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 49848c2ecf20Sopenharmony_ci 49858c2ecf20Sopenharmony_ci if ((rc = mpt_config(ioc, &cfg)) == 0) { 49868c2ecf20Sopenharmony_ci /* save the data */ 49878c2ecf20Sopenharmony_ci copy_sz = min_t(int, sizeof(LANPage0_t), data_sz); 49888c2ecf20Sopenharmony_ci memcpy(&ioc->lan_cnfg_page0, ppage0_alloc, copy_sz); 49898c2ecf20Sopenharmony_ci 49908c2ecf20Sopenharmony_ci } 49918c2ecf20Sopenharmony_ci 49928c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); 49938c2ecf20Sopenharmony_ci 49948c2ecf20Sopenharmony_ci /* FIXME! 49958c2ecf20Sopenharmony_ci * Normalize endianness of structure data, 49968c2ecf20Sopenharmony_ci * by byte-swapping all > 1 byte fields! 49978c2ecf20Sopenharmony_ci */ 49988c2ecf20Sopenharmony_ci 49998c2ecf20Sopenharmony_ci } 50008c2ecf20Sopenharmony_ci 50018c2ecf20Sopenharmony_ci if (rc) 50028c2ecf20Sopenharmony_ci return rc; 50038c2ecf20Sopenharmony_ci } 50048c2ecf20Sopenharmony_ci 50058c2ecf20Sopenharmony_ci /* Get LAN Page 1 header */ 50068c2ecf20Sopenharmony_ci hdr.PageVersion = 0; 50078c2ecf20Sopenharmony_ci hdr.PageLength = 0; 50088c2ecf20Sopenharmony_ci hdr.PageNumber = 1; 50098c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_LAN; 50108c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 50118c2ecf20Sopenharmony_ci cfg.physAddr = -1; 50128c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 50138c2ecf20Sopenharmony_ci cfg.dir = 0; 50148c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 50158c2ecf20Sopenharmony_ci 50168c2ecf20Sopenharmony_ci if ((rc = mpt_config(ioc, &cfg)) != 0) 50178c2ecf20Sopenharmony_ci return rc; 50188c2ecf20Sopenharmony_ci 50198c2ecf20Sopenharmony_ci if (hdr.PageLength == 0) 50208c2ecf20Sopenharmony_ci return 0; 50218c2ecf20Sopenharmony_ci 50228c2ecf20Sopenharmony_ci data_sz = hdr.PageLength * 4; 50238c2ecf20Sopenharmony_ci rc = -ENOMEM; 50248c2ecf20Sopenharmony_ci ppage1_alloc = (LANPage1_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page1_dma); 50258c2ecf20Sopenharmony_ci if (ppage1_alloc) { 50268c2ecf20Sopenharmony_ci memset((u8 *)ppage1_alloc, 0, data_sz); 50278c2ecf20Sopenharmony_ci cfg.physAddr = page1_dma; 50288c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 50298c2ecf20Sopenharmony_ci 50308c2ecf20Sopenharmony_ci if ((rc = mpt_config(ioc, &cfg)) == 0) { 50318c2ecf20Sopenharmony_ci /* save the data */ 50328c2ecf20Sopenharmony_ci copy_sz = min_t(int, sizeof(LANPage1_t), data_sz); 50338c2ecf20Sopenharmony_ci memcpy(&ioc->lan_cnfg_page1, ppage1_alloc, copy_sz); 50348c2ecf20Sopenharmony_ci } 50358c2ecf20Sopenharmony_ci 50368c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage1_alloc, page1_dma); 50378c2ecf20Sopenharmony_ci 50388c2ecf20Sopenharmony_ci /* FIXME! 50398c2ecf20Sopenharmony_ci * Normalize endianness of structure data, 50408c2ecf20Sopenharmony_ci * by byte-swapping all > 1 byte fields! 50418c2ecf20Sopenharmony_ci */ 50428c2ecf20Sopenharmony_ci 50438c2ecf20Sopenharmony_ci } 50448c2ecf20Sopenharmony_ci 50458c2ecf20Sopenharmony_ci return rc; 50468c2ecf20Sopenharmony_ci} 50478c2ecf20Sopenharmony_ci 50488c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 50498c2ecf20Sopenharmony_ci/** 50508c2ecf20Sopenharmony_ci * mptbase_sas_persist_operation - Perform operation on SAS Persistent Table 50518c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 50528c2ecf20Sopenharmony_ci * @persist_opcode: see below 50538c2ecf20Sopenharmony_ci * 50548c2ecf20Sopenharmony_ci * =============================== ====================================== 50558c2ecf20Sopenharmony_ci * MPI_SAS_OP_CLEAR_NOT_PRESENT Free all persist TargetID mappings for 50568c2ecf20Sopenharmony_ci * devices not currently present. 50578c2ecf20Sopenharmony_ci * MPI_SAS_OP_CLEAR_ALL_PERSISTENT Clear al persist TargetID mappings 50588c2ecf20Sopenharmony_ci * =============================== ====================================== 50598c2ecf20Sopenharmony_ci * 50608c2ecf20Sopenharmony_ci * NOTE: Don't use not this function during interrupt time. 50618c2ecf20Sopenharmony_ci * 50628c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero error 50638c2ecf20Sopenharmony_ci */ 50648c2ecf20Sopenharmony_ci 50658c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 50668c2ecf20Sopenharmony_ciint 50678c2ecf20Sopenharmony_cimptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) 50688c2ecf20Sopenharmony_ci{ 50698c2ecf20Sopenharmony_ci SasIoUnitControlRequest_t *sasIoUnitCntrReq; 50708c2ecf20Sopenharmony_ci SasIoUnitControlReply_t *sasIoUnitCntrReply; 50718c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf = NULL; 50728c2ecf20Sopenharmony_ci MPIHeader_t *mpi_hdr; 50738c2ecf20Sopenharmony_ci int ret = 0; 50748c2ecf20Sopenharmony_ci unsigned long timeleft; 50758c2ecf20Sopenharmony_ci 50768c2ecf20Sopenharmony_ci mutex_lock(&ioc->mptbase_cmds.mutex); 50778c2ecf20Sopenharmony_ci 50788c2ecf20Sopenharmony_ci /* init the internal cmd struct */ 50798c2ecf20Sopenharmony_ci memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); 50808c2ecf20Sopenharmony_ci INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) 50818c2ecf20Sopenharmony_ci 50828c2ecf20Sopenharmony_ci /* insure garbage is not sent to fw */ 50838c2ecf20Sopenharmony_ci switch(persist_opcode) { 50848c2ecf20Sopenharmony_ci 50858c2ecf20Sopenharmony_ci case MPI_SAS_OP_CLEAR_NOT_PRESENT: 50868c2ecf20Sopenharmony_ci case MPI_SAS_OP_CLEAR_ALL_PERSISTENT: 50878c2ecf20Sopenharmony_ci break; 50888c2ecf20Sopenharmony_ci 50898c2ecf20Sopenharmony_ci default: 50908c2ecf20Sopenharmony_ci ret = -1; 50918c2ecf20Sopenharmony_ci goto out; 50928c2ecf20Sopenharmony_ci } 50938c2ecf20Sopenharmony_ci 50948c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: persist_opcode=%x\n", 50958c2ecf20Sopenharmony_ci __func__, persist_opcode); 50968c2ecf20Sopenharmony_ci 50978c2ecf20Sopenharmony_ci /* Get a MF for this command. 50988c2ecf20Sopenharmony_ci */ 50998c2ecf20Sopenharmony_ci if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { 51008c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: no msg frames!\n", __func__); 51018c2ecf20Sopenharmony_ci ret = -1; 51028c2ecf20Sopenharmony_ci goto out; 51038c2ecf20Sopenharmony_ci } 51048c2ecf20Sopenharmony_ci 51058c2ecf20Sopenharmony_ci mpi_hdr = (MPIHeader_t *) mf; 51068c2ecf20Sopenharmony_ci sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; 51078c2ecf20Sopenharmony_ci memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); 51088c2ecf20Sopenharmony_ci sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; 51098c2ecf20Sopenharmony_ci sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; 51108c2ecf20Sopenharmony_ci sasIoUnitCntrReq->Operation = persist_opcode; 51118c2ecf20Sopenharmony_ci 51128c2ecf20Sopenharmony_ci mpt_put_msg_frame(mpt_base_index, ioc, mf); 51138c2ecf20Sopenharmony_ci timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 10*HZ); 51148c2ecf20Sopenharmony_ci if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { 51158c2ecf20Sopenharmony_ci ret = -ETIME; 51168c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: failed\n", __func__); 51178c2ecf20Sopenharmony_ci if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) 51188c2ecf20Sopenharmony_ci goto out; 51198c2ecf20Sopenharmony_ci if (!timeleft) { 51208c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 51218c2ecf20Sopenharmony_ci "Issuing Reset from %s!!, doorbell=0x%08x\n", 51228c2ecf20Sopenharmony_ci ioc->name, __func__, mpt_GetIocState(ioc, 0)); 51238c2ecf20Sopenharmony_ci mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP); 51248c2ecf20Sopenharmony_ci mpt_free_msg_frame(ioc, mf); 51258c2ecf20Sopenharmony_ci } 51268c2ecf20Sopenharmony_ci goto out; 51278c2ecf20Sopenharmony_ci } 51288c2ecf20Sopenharmony_ci 51298c2ecf20Sopenharmony_ci if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { 51308c2ecf20Sopenharmony_ci ret = -1; 51318c2ecf20Sopenharmony_ci goto out; 51328c2ecf20Sopenharmony_ci } 51338c2ecf20Sopenharmony_ci 51348c2ecf20Sopenharmony_ci sasIoUnitCntrReply = 51358c2ecf20Sopenharmony_ci (SasIoUnitControlReply_t *)ioc->mptbase_cmds.reply; 51368c2ecf20Sopenharmony_ci if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { 51378c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", 51388c2ecf20Sopenharmony_ci __func__, sasIoUnitCntrReply->IOCStatus, 51398c2ecf20Sopenharmony_ci sasIoUnitCntrReply->IOCLogInfo); 51408c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: failed\n", __func__); 51418c2ecf20Sopenharmony_ci ret = -1; 51428c2ecf20Sopenharmony_ci } else 51438c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s: success\n", __func__); 51448c2ecf20Sopenharmony_ci out: 51458c2ecf20Sopenharmony_ci 51468c2ecf20Sopenharmony_ci CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) 51478c2ecf20Sopenharmony_ci mutex_unlock(&ioc->mptbase_cmds.mutex); 51488c2ecf20Sopenharmony_ci return ret; 51498c2ecf20Sopenharmony_ci} 51508c2ecf20Sopenharmony_ci 51518c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 51528c2ecf20Sopenharmony_ci 51538c2ecf20Sopenharmony_cistatic void 51548c2ecf20Sopenharmony_cimptbase_raid_process_event_data(MPT_ADAPTER *ioc, 51558c2ecf20Sopenharmony_ci MpiEventDataRaid_t * pRaidEventData) 51568c2ecf20Sopenharmony_ci{ 51578c2ecf20Sopenharmony_ci int volume; 51588c2ecf20Sopenharmony_ci int reason; 51598c2ecf20Sopenharmony_ci int disk; 51608c2ecf20Sopenharmony_ci int status; 51618c2ecf20Sopenharmony_ci int flags; 51628c2ecf20Sopenharmony_ci int state; 51638c2ecf20Sopenharmony_ci 51648c2ecf20Sopenharmony_ci volume = pRaidEventData->VolumeID; 51658c2ecf20Sopenharmony_ci reason = pRaidEventData->ReasonCode; 51668c2ecf20Sopenharmony_ci disk = pRaidEventData->PhysDiskNum; 51678c2ecf20Sopenharmony_ci status = le32_to_cpu(pRaidEventData->SettingsStatus); 51688c2ecf20Sopenharmony_ci flags = (status >> 0) & 0xff; 51698c2ecf20Sopenharmony_ci state = (status >> 8) & 0xff; 51708c2ecf20Sopenharmony_ci 51718c2ecf20Sopenharmony_ci if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { 51728c2ecf20Sopenharmony_ci return; 51738c2ecf20Sopenharmony_ci } 51748c2ecf20Sopenharmony_ci 51758c2ecf20Sopenharmony_ci if ((reason >= MPI_EVENT_RAID_RC_PHYSDISK_CREATED && 51768c2ecf20Sopenharmony_ci reason <= MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED) || 51778c2ecf20Sopenharmony_ci (reason == MPI_EVENT_RAID_RC_SMART_DATA)) { 51788c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for PhysDisk %d id=%d\n", 51798c2ecf20Sopenharmony_ci ioc->name, disk, volume); 51808c2ecf20Sopenharmony_ci } else { 51818c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "RAID STATUS CHANGE for VolumeID %d\n", 51828c2ecf20Sopenharmony_ci ioc->name, volume); 51838c2ecf20Sopenharmony_ci } 51848c2ecf20Sopenharmony_ci 51858c2ecf20Sopenharmony_ci switch(reason) { 51868c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_CREATED: 51878c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " volume has been created\n", 51888c2ecf20Sopenharmony_ci ioc->name); 51898c2ecf20Sopenharmony_ci break; 51908c2ecf20Sopenharmony_ci 51918c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_DELETED: 51928c2ecf20Sopenharmony_ci 51938c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " volume has been deleted\n", 51948c2ecf20Sopenharmony_ci ioc->name); 51958c2ecf20Sopenharmony_ci break; 51968c2ecf20Sopenharmony_ci 51978c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED: 51988c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " volume settings have been changed\n", 51998c2ecf20Sopenharmony_ci ioc->name); 52008c2ecf20Sopenharmony_ci break; 52018c2ecf20Sopenharmony_ci 52028c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED: 52038c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " volume is now %s%s%s%s\n", 52048c2ecf20Sopenharmony_ci ioc->name, 52058c2ecf20Sopenharmony_ci state == MPI_RAIDVOL0_STATUS_STATE_OPTIMAL 52068c2ecf20Sopenharmony_ci ? "optimal" 52078c2ecf20Sopenharmony_ci : state == MPI_RAIDVOL0_STATUS_STATE_DEGRADED 52088c2ecf20Sopenharmony_ci ? "degraded" 52098c2ecf20Sopenharmony_ci : state == MPI_RAIDVOL0_STATUS_STATE_FAILED 52108c2ecf20Sopenharmony_ci ? "failed" 52118c2ecf20Sopenharmony_ci : "state unknown", 52128c2ecf20Sopenharmony_ci flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED 52138c2ecf20Sopenharmony_ci ? ", enabled" : "", 52148c2ecf20Sopenharmony_ci flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED 52158c2ecf20Sopenharmony_ci ? ", quiesced" : "", 52168c2ecf20Sopenharmony_ci flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS 52178c2ecf20Sopenharmony_ci ? ", resync in progress" : "" ); 52188c2ecf20Sopenharmony_ci break; 52198c2ecf20Sopenharmony_ci 52208c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED: 52218c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " volume membership of PhysDisk %d has changed\n", 52228c2ecf20Sopenharmony_ci ioc->name, disk); 52238c2ecf20Sopenharmony_ci break; 52248c2ecf20Sopenharmony_ci 52258c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_CREATED: 52268c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " PhysDisk has been created\n", 52278c2ecf20Sopenharmony_ci ioc->name); 52288c2ecf20Sopenharmony_ci break; 52298c2ecf20Sopenharmony_ci 52308c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_DELETED: 52318c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " PhysDisk has been deleted\n", 52328c2ecf20Sopenharmony_ci ioc->name); 52338c2ecf20Sopenharmony_ci break; 52348c2ecf20Sopenharmony_ci 52358c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED: 52368c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " PhysDisk settings have been changed\n", 52378c2ecf20Sopenharmony_ci ioc->name); 52388c2ecf20Sopenharmony_ci break; 52398c2ecf20Sopenharmony_ci 52408c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED: 52418c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " PhysDisk is now %s%s%s\n", 52428c2ecf20Sopenharmony_ci ioc->name, 52438c2ecf20Sopenharmony_ci state == MPI_PHYSDISK0_STATUS_ONLINE 52448c2ecf20Sopenharmony_ci ? "online" 52458c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_MISSING 52468c2ecf20Sopenharmony_ci ? "missing" 52478c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE 52488c2ecf20Sopenharmony_ci ? "not compatible" 52498c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_FAILED 52508c2ecf20Sopenharmony_ci ? "failed" 52518c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_INITIALIZING 52528c2ecf20Sopenharmony_ci ? "initializing" 52538c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED 52548c2ecf20Sopenharmony_ci ? "offline requested" 52558c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_FAILED_REQUESTED 52568c2ecf20Sopenharmony_ci ? "failed requested" 52578c2ecf20Sopenharmony_ci : state == MPI_PHYSDISK0_STATUS_OTHER_OFFLINE 52588c2ecf20Sopenharmony_ci ? "offline" 52598c2ecf20Sopenharmony_ci : "state unknown", 52608c2ecf20Sopenharmony_ci flags & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC 52618c2ecf20Sopenharmony_ci ? ", out of sync" : "", 52628c2ecf20Sopenharmony_ci flags & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED 52638c2ecf20Sopenharmony_ci ? ", quiesced" : "" ); 52648c2ecf20Sopenharmony_ci break; 52658c2ecf20Sopenharmony_ci 52668c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED: 52678c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " Domain Validation needed for PhysDisk %d\n", 52688c2ecf20Sopenharmony_ci ioc->name, disk); 52698c2ecf20Sopenharmony_ci break; 52708c2ecf20Sopenharmony_ci 52718c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_SMART_DATA: 52728c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " SMART data received, ASC/ASCQ = %02xh/%02xh\n", 52738c2ecf20Sopenharmony_ci ioc->name, pRaidEventData->ASC, pRaidEventData->ASCQ); 52748c2ecf20Sopenharmony_ci break; 52758c2ecf20Sopenharmony_ci 52768c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED: 52778c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT " replacement of PhysDisk %d has started\n", 52788c2ecf20Sopenharmony_ci ioc->name, disk); 52798c2ecf20Sopenharmony_ci break; 52808c2ecf20Sopenharmony_ci } 52818c2ecf20Sopenharmony_ci} 52828c2ecf20Sopenharmony_ci 52838c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 52848c2ecf20Sopenharmony_ci/** 52858c2ecf20Sopenharmony_ci * GetIoUnitPage2 - Retrieve BIOS version and boot order information. 52868c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 52878c2ecf20Sopenharmony_ci * 52888c2ecf20Sopenharmony_ci * Returns: 0 for success 52898c2ecf20Sopenharmony_ci * -ENOMEM if no memory available 52908c2ecf20Sopenharmony_ci * -EPERM if not allowed due to ISR context 52918c2ecf20Sopenharmony_ci * -EAGAIN if no msg frames currently available 52928c2ecf20Sopenharmony_ci * -EFAULT for non-successful reply or no reply (timeout) 52938c2ecf20Sopenharmony_ci */ 52948c2ecf20Sopenharmony_cistatic int 52958c2ecf20Sopenharmony_ciGetIoUnitPage2(MPT_ADAPTER *ioc) 52968c2ecf20Sopenharmony_ci{ 52978c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 52988c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 52998c2ecf20Sopenharmony_ci IOUnitPage2_t *ppage_alloc; 53008c2ecf20Sopenharmony_ci dma_addr_t page_dma; 53018c2ecf20Sopenharmony_ci int data_sz; 53028c2ecf20Sopenharmony_ci int rc; 53038c2ecf20Sopenharmony_ci 53048c2ecf20Sopenharmony_ci /* Get the page header */ 53058c2ecf20Sopenharmony_ci hdr.PageVersion = 0; 53068c2ecf20Sopenharmony_ci hdr.PageLength = 0; 53078c2ecf20Sopenharmony_ci hdr.PageNumber = 2; 53088c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_IO_UNIT; 53098c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 53108c2ecf20Sopenharmony_ci cfg.physAddr = -1; 53118c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 53128c2ecf20Sopenharmony_ci cfg.dir = 0; 53138c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 53148c2ecf20Sopenharmony_ci cfg.timeout = 0; 53158c2ecf20Sopenharmony_ci 53168c2ecf20Sopenharmony_ci if ((rc = mpt_config(ioc, &cfg)) != 0) 53178c2ecf20Sopenharmony_ci return rc; 53188c2ecf20Sopenharmony_ci 53198c2ecf20Sopenharmony_ci if (hdr.PageLength == 0) 53208c2ecf20Sopenharmony_ci return 0; 53218c2ecf20Sopenharmony_ci 53228c2ecf20Sopenharmony_ci /* Read the config page */ 53238c2ecf20Sopenharmony_ci data_sz = hdr.PageLength * 4; 53248c2ecf20Sopenharmony_ci rc = -ENOMEM; 53258c2ecf20Sopenharmony_ci ppage_alloc = (IOUnitPage2_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma); 53268c2ecf20Sopenharmony_ci if (ppage_alloc) { 53278c2ecf20Sopenharmony_ci memset((u8 *)ppage_alloc, 0, data_sz); 53288c2ecf20Sopenharmony_ci cfg.physAddr = page_dma; 53298c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 53308c2ecf20Sopenharmony_ci 53318c2ecf20Sopenharmony_ci /* If Good, save data */ 53328c2ecf20Sopenharmony_ci if ((rc = mpt_config(ioc, &cfg)) == 0) 53338c2ecf20Sopenharmony_ci ioc->biosVersion = le32_to_cpu(ppage_alloc->BiosVersion); 53348c2ecf20Sopenharmony_ci 53358c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage_alloc, page_dma); 53368c2ecf20Sopenharmony_ci } 53378c2ecf20Sopenharmony_ci 53388c2ecf20Sopenharmony_ci return rc; 53398c2ecf20Sopenharmony_ci} 53408c2ecf20Sopenharmony_ci 53418c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 53428c2ecf20Sopenharmony_ci/** 53438c2ecf20Sopenharmony_ci * mpt_GetScsiPortSettings - read SCSI Port Page 0 and 2 53448c2ecf20Sopenharmony_ci * @ioc: Pointer to a Adapter Strucutre 53458c2ecf20Sopenharmony_ci * @portnum: IOC port number 53468c2ecf20Sopenharmony_ci * 53478c2ecf20Sopenharmony_ci * Return: -EFAULT if read of config page header fails 53488c2ecf20Sopenharmony_ci * or if no nvram 53498c2ecf20Sopenharmony_ci * If read of SCSI Port Page 0 fails, 53508c2ecf20Sopenharmony_ci * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF) 53518c2ecf20Sopenharmony_ci * Adapter settings: async, narrow 53528c2ecf20Sopenharmony_ci * Return 1 53538c2ecf20Sopenharmony_ci * If read of SCSI Port Page 2 fails, 53548c2ecf20Sopenharmony_ci * Adapter settings valid 53558c2ecf20Sopenharmony_ci * NVRAM = MPT_HOST_NVRAM_INVALID (0xFFFFFFFF) 53568c2ecf20Sopenharmony_ci * Return 1 53578c2ecf20Sopenharmony_ci * Else 53588c2ecf20Sopenharmony_ci * Both valid 53598c2ecf20Sopenharmony_ci * Return 0 53608c2ecf20Sopenharmony_ci * CHECK - what type of locking mechanisms should be used???? 53618c2ecf20Sopenharmony_ci */ 53628c2ecf20Sopenharmony_cistatic int 53638c2ecf20Sopenharmony_cimpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) 53648c2ecf20Sopenharmony_ci{ 53658c2ecf20Sopenharmony_ci u8 *pbuf; 53668c2ecf20Sopenharmony_ci dma_addr_t buf_dma; 53678c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 53688c2ecf20Sopenharmony_ci ConfigPageHeader_t header; 53698c2ecf20Sopenharmony_ci int ii; 53708c2ecf20Sopenharmony_ci int data, rc = 0; 53718c2ecf20Sopenharmony_ci 53728c2ecf20Sopenharmony_ci /* Allocate memory 53738c2ecf20Sopenharmony_ci */ 53748c2ecf20Sopenharmony_ci if (!ioc->spi_data.nvram) { 53758c2ecf20Sopenharmony_ci int sz; 53768c2ecf20Sopenharmony_ci u8 *mem; 53778c2ecf20Sopenharmony_ci sz = MPT_MAX_SCSI_DEVICES * sizeof(int); 53788c2ecf20Sopenharmony_ci mem = kmalloc(sz, GFP_ATOMIC); 53798c2ecf20Sopenharmony_ci if (mem == NULL) 53808c2ecf20Sopenharmony_ci return -EFAULT; 53818c2ecf20Sopenharmony_ci 53828c2ecf20Sopenharmony_ci ioc->spi_data.nvram = (int *) mem; 53838c2ecf20Sopenharmony_ci 53848c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SCSI device NVRAM settings @ %p, sz=%d\n", 53858c2ecf20Sopenharmony_ci ioc->name, ioc->spi_data.nvram, sz)); 53868c2ecf20Sopenharmony_ci } 53878c2ecf20Sopenharmony_ci 53888c2ecf20Sopenharmony_ci /* Invalidate NVRAM information 53898c2ecf20Sopenharmony_ci */ 53908c2ecf20Sopenharmony_ci for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { 53918c2ecf20Sopenharmony_ci ioc->spi_data.nvram[ii] = MPT_HOST_NVRAM_INVALID; 53928c2ecf20Sopenharmony_ci } 53938c2ecf20Sopenharmony_ci 53948c2ecf20Sopenharmony_ci /* Read SPP0 header, allocate memory, then read page. 53958c2ecf20Sopenharmony_ci */ 53968c2ecf20Sopenharmony_ci header.PageVersion = 0; 53978c2ecf20Sopenharmony_ci header.PageLength = 0; 53988c2ecf20Sopenharmony_ci header.PageNumber = 0; 53998c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT; 54008c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 54018c2ecf20Sopenharmony_ci cfg.physAddr = -1; 54028c2ecf20Sopenharmony_ci cfg.pageAddr = portnum; 54038c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 54048c2ecf20Sopenharmony_ci cfg.dir = 0; 54058c2ecf20Sopenharmony_ci cfg.timeout = 0; /* use default */ 54068c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 54078c2ecf20Sopenharmony_ci return -EFAULT; 54088c2ecf20Sopenharmony_ci 54098c2ecf20Sopenharmony_ci if (header.PageLength > 0) { 54108c2ecf20Sopenharmony_ci pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma); 54118c2ecf20Sopenharmony_ci if (pbuf) { 54128c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 54138c2ecf20Sopenharmony_ci cfg.physAddr = buf_dma; 54148c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 54158c2ecf20Sopenharmony_ci ioc->spi_data.maxBusWidth = MPT_NARROW; 54168c2ecf20Sopenharmony_ci ioc->spi_data.maxSyncOffset = 0; 54178c2ecf20Sopenharmony_ci ioc->spi_data.minSyncFactor = MPT_ASYNC; 54188c2ecf20Sopenharmony_ci ioc->spi_data.busType = MPT_HOST_BUS_UNKNOWN; 54198c2ecf20Sopenharmony_ci rc = 1; 54208c2ecf20Sopenharmony_ci ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT 54218c2ecf20Sopenharmony_ci "Unable to read PortPage0 minSyncFactor=%x\n", 54228c2ecf20Sopenharmony_ci ioc->name, ioc->spi_data.minSyncFactor)); 54238c2ecf20Sopenharmony_ci } else { 54248c2ecf20Sopenharmony_ci /* Save the Port Page 0 data 54258c2ecf20Sopenharmony_ci */ 54268c2ecf20Sopenharmony_ci SCSIPortPage0_t *pPP0 = (SCSIPortPage0_t *) pbuf; 54278c2ecf20Sopenharmony_ci pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities); 54288c2ecf20Sopenharmony_ci pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface); 54298c2ecf20Sopenharmony_ci 54308c2ecf20Sopenharmony_ci if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { 54318c2ecf20Sopenharmony_ci ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; 54328c2ecf20Sopenharmony_ci ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT 54338c2ecf20Sopenharmony_ci "noQas due to Capabilities=%x\n", 54348c2ecf20Sopenharmony_ci ioc->name, pPP0->Capabilities)); 54358c2ecf20Sopenharmony_ci } 54368c2ecf20Sopenharmony_ci ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; 54378c2ecf20Sopenharmony_ci data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK; 54388c2ecf20Sopenharmony_ci if (data) { 54398c2ecf20Sopenharmony_ci ioc->spi_data.maxSyncOffset = (u8) (data >> 16); 54408c2ecf20Sopenharmony_ci data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK; 54418c2ecf20Sopenharmony_ci ioc->spi_data.minSyncFactor = (u8) (data >> 8); 54428c2ecf20Sopenharmony_ci ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT 54438c2ecf20Sopenharmony_ci "PortPage0 minSyncFactor=%x\n", 54448c2ecf20Sopenharmony_ci ioc->name, ioc->spi_data.minSyncFactor)); 54458c2ecf20Sopenharmony_ci } else { 54468c2ecf20Sopenharmony_ci ioc->spi_data.maxSyncOffset = 0; 54478c2ecf20Sopenharmony_ci ioc->spi_data.minSyncFactor = MPT_ASYNC; 54488c2ecf20Sopenharmony_ci } 54498c2ecf20Sopenharmony_ci 54508c2ecf20Sopenharmony_ci ioc->spi_data.busType = pPP0->PhysicalInterface & MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK; 54518c2ecf20Sopenharmony_ci 54528c2ecf20Sopenharmony_ci /* Update the minSyncFactor based on bus type. 54538c2ecf20Sopenharmony_ci */ 54548c2ecf20Sopenharmony_ci if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) || 54558c2ecf20Sopenharmony_ci (ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) { 54568c2ecf20Sopenharmony_ci 54578c2ecf20Sopenharmony_ci if (ioc->spi_data.minSyncFactor < MPT_ULTRA) { 54588c2ecf20Sopenharmony_ci ioc->spi_data.minSyncFactor = MPT_ULTRA; 54598c2ecf20Sopenharmony_ci ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT 54608c2ecf20Sopenharmony_ci "HVD or SE detected, minSyncFactor=%x\n", 54618c2ecf20Sopenharmony_ci ioc->name, ioc->spi_data.minSyncFactor)); 54628c2ecf20Sopenharmony_ci } 54638c2ecf20Sopenharmony_ci } 54648c2ecf20Sopenharmony_ci } 54658c2ecf20Sopenharmony_ci if (pbuf) { 54668c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma); 54678c2ecf20Sopenharmony_ci } 54688c2ecf20Sopenharmony_ci } 54698c2ecf20Sopenharmony_ci } 54708c2ecf20Sopenharmony_ci 54718c2ecf20Sopenharmony_ci /* SCSI Port Page 2 - Read the header then the page. 54728c2ecf20Sopenharmony_ci */ 54738c2ecf20Sopenharmony_ci header.PageVersion = 0; 54748c2ecf20Sopenharmony_ci header.PageLength = 0; 54758c2ecf20Sopenharmony_ci header.PageNumber = 2; 54768c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_SCSI_PORT; 54778c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 54788c2ecf20Sopenharmony_ci cfg.physAddr = -1; 54798c2ecf20Sopenharmony_ci cfg.pageAddr = portnum; 54808c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 54818c2ecf20Sopenharmony_ci cfg.dir = 0; 54828c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 54838c2ecf20Sopenharmony_ci return -EFAULT; 54848c2ecf20Sopenharmony_ci 54858c2ecf20Sopenharmony_ci if (header.PageLength > 0) { 54868c2ecf20Sopenharmony_ci /* Allocate memory and read SCSI Port Page 2 54878c2ecf20Sopenharmony_ci */ 54888c2ecf20Sopenharmony_ci pbuf = pci_alloc_consistent(ioc->pcidev, header.PageLength * 4, &buf_dma); 54898c2ecf20Sopenharmony_ci if (pbuf) { 54908c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_NVRAM; 54918c2ecf20Sopenharmony_ci cfg.physAddr = buf_dma; 54928c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 54938c2ecf20Sopenharmony_ci /* Nvram data is left with INVALID mark 54948c2ecf20Sopenharmony_ci */ 54958c2ecf20Sopenharmony_ci rc = 1; 54968c2ecf20Sopenharmony_ci } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) { 54978c2ecf20Sopenharmony_ci 54988c2ecf20Sopenharmony_ci /* This is an ATTO adapter, read Page2 accordingly 54998c2ecf20Sopenharmony_ci */ 55008c2ecf20Sopenharmony_ci ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf; 55018c2ecf20Sopenharmony_ci ATTODeviceInfo_t *pdevice = NULL; 55028c2ecf20Sopenharmony_ci u16 ATTOFlags; 55038c2ecf20Sopenharmony_ci 55048c2ecf20Sopenharmony_ci /* Save the Port Page 2 data 55058c2ecf20Sopenharmony_ci * (reformat into a 32bit quantity) 55068c2ecf20Sopenharmony_ci */ 55078c2ecf20Sopenharmony_ci for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { 55088c2ecf20Sopenharmony_ci pdevice = &pPP2->DeviceSettings[ii]; 55098c2ecf20Sopenharmony_ci ATTOFlags = le16_to_cpu(pdevice->ATTOFlags); 55108c2ecf20Sopenharmony_ci data = 0; 55118c2ecf20Sopenharmony_ci 55128c2ecf20Sopenharmony_ci /* Translate ATTO device flags to LSI format 55138c2ecf20Sopenharmony_ci */ 55148c2ecf20Sopenharmony_ci if (ATTOFlags & ATTOFLAG_DISC) 55158c2ecf20Sopenharmony_ci data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE); 55168c2ecf20Sopenharmony_ci if (ATTOFlags & ATTOFLAG_ID_ENB) 55178c2ecf20Sopenharmony_ci data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE); 55188c2ecf20Sopenharmony_ci if (ATTOFlags & ATTOFLAG_LUN_ENB) 55198c2ecf20Sopenharmony_ci data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE); 55208c2ecf20Sopenharmony_ci if (ATTOFlags & ATTOFLAG_TAGGED) 55218c2ecf20Sopenharmony_ci data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE); 55228c2ecf20Sopenharmony_ci if (!(ATTOFlags & ATTOFLAG_WIDE_ENB)) 55238c2ecf20Sopenharmony_ci data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE); 55248c2ecf20Sopenharmony_ci 55258c2ecf20Sopenharmony_ci data = (data << 16) | (pdevice->Period << 8) | 10; 55268c2ecf20Sopenharmony_ci ioc->spi_data.nvram[ii] = data; 55278c2ecf20Sopenharmony_ci } 55288c2ecf20Sopenharmony_ci } else { 55298c2ecf20Sopenharmony_ci SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf; 55308c2ecf20Sopenharmony_ci MpiDeviceInfo_t *pdevice = NULL; 55318c2ecf20Sopenharmony_ci 55328c2ecf20Sopenharmony_ci /* 55338c2ecf20Sopenharmony_ci * Save "Set to Avoid SCSI Bus Resets" flag 55348c2ecf20Sopenharmony_ci */ 55358c2ecf20Sopenharmony_ci ioc->spi_data.bus_reset = 55368c2ecf20Sopenharmony_ci (le32_to_cpu(pPP2->PortFlags) & 55378c2ecf20Sopenharmony_ci MPI_SCSIPORTPAGE2_PORT_FLAGS_AVOID_SCSI_RESET) ? 55388c2ecf20Sopenharmony_ci 0 : 1 ; 55398c2ecf20Sopenharmony_ci 55408c2ecf20Sopenharmony_ci /* Save the Port Page 2 data 55418c2ecf20Sopenharmony_ci * (reformat into a 32bit quantity) 55428c2ecf20Sopenharmony_ci */ 55438c2ecf20Sopenharmony_ci data = le32_to_cpu(pPP2->PortFlags) & MPI_SCSIPORTPAGE2_PORT_FLAGS_DV_MASK; 55448c2ecf20Sopenharmony_ci ioc->spi_data.PortFlags = data; 55458c2ecf20Sopenharmony_ci for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { 55468c2ecf20Sopenharmony_ci pdevice = &pPP2->DeviceSettings[ii]; 55478c2ecf20Sopenharmony_ci data = (le16_to_cpu(pdevice->DeviceFlags) << 16) | 55488c2ecf20Sopenharmony_ci (pdevice->SyncFactor << 8) | pdevice->Timeout; 55498c2ecf20Sopenharmony_ci ioc->spi_data.nvram[ii] = data; 55508c2ecf20Sopenharmony_ci } 55518c2ecf20Sopenharmony_ci } 55528c2ecf20Sopenharmony_ci 55538c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, header.PageLength * 4, pbuf, buf_dma); 55548c2ecf20Sopenharmony_ci } 55558c2ecf20Sopenharmony_ci } 55568c2ecf20Sopenharmony_ci 55578c2ecf20Sopenharmony_ci /* Update Adapter limits with those from NVRAM 55588c2ecf20Sopenharmony_ci * Comment: Don't need to do this. Target performance 55598c2ecf20Sopenharmony_ci * parameters will never exceed the adapters limits. 55608c2ecf20Sopenharmony_ci */ 55618c2ecf20Sopenharmony_ci 55628c2ecf20Sopenharmony_ci return rc; 55638c2ecf20Sopenharmony_ci} 55648c2ecf20Sopenharmony_ci 55658c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 55668c2ecf20Sopenharmony_ci/** 55678c2ecf20Sopenharmony_ci * mpt_readScsiDevicePageHeaders - save version and length of SDP1 55688c2ecf20Sopenharmony_ci * @ioc: Pointer to a Adapter Strucutre 55698c2ecf20Sopenharmony_ci * @portnum: IOC port number 55708c2ecf20Sopenharmony_ci * 55718c2ecf20Sopenharmony_ci * Return: -EFAULT if read of config page header fails 55728c2ecf20Sopenharmony_ci * or 0 if success. 55738c2ecf20Sopenharmony_ci */ 55748c2ecf20Sopenharmony_cistatic int 55758c2ecf20Sopenharmony_cimpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum) 55768c2ecf20Sopenharmony_ci{ 55778c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 55788c2ecf20Sopenharmony_ci ConfigPageHeader_t header; 55798c2ecf20Sopenharmony_ci 55808c2ecf20Sopenharmony_ci /* Read the SCSI Device Page 1 header 55818c2ecf20Sopenharmony_ci */ 55828c2ecf20Sopenharmony_ci header.PageVersion = 0; 55838c2ecf20Sopenharmony_ci header.PageLength = 0; 55848c2ecf20Sopenharmony_ci header.PageNumber = 1; 55858c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; 55868c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 55878c2ecf20Sopenharmony_ci cfg.physAddr = -1; 55888c2ecf20Sopenharmony_ci cfg.pageAddr = portnum; 55898c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 55908c2ecf20Sopenharmony_ci cfg.dir = 0; 55918c2ecf20Sopenharmony_ci cfg.timeout = 0; 55928c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 55938c2ecf20Sopenharmony_ci return -EFAULT; 55948c2ecf20Sopenharmony_ci 55958c2ecf20Sopenharmony_ci ioc->spi_data.sdp1version = cfg.cfghdr.hdr->PageVersion; 55968c2ecf20Sopenharmony_ci ioc->spi_data.sdp1length = cfg.cfghdr.hdr->PageLength; 55978c2ecf20Sopenharmony_ci 55988c2ecf20Sopenharmony_ci header.PageVersion = 0; 55998c2ecf20Sopenharmony_ci header.PageLength = 0; 56008c2ecf20Sopenharmony_ci header.PageNumber = 0; 56018c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; 56028c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 56038c2ecf20Sopenharmony_ci return -EFAULT; 56048c2ecf20Sopenharmony_ci 56058c2ecf20Sopenharmony_ci ioc->spi_data.sdp0version = cfg.cfghdr.hdr->PageVersion; 56068c2ecf20Sopenharmony_ci ioc->spi_data.sdp0length = cfg.cfghdr.hdr->PageLength; 56078c2ecf20Sopenharmony_ci 56088c2ecf20Sopenharmony_ci dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 0: version %d length %d\n", 56098c2ecf20Sopenharmony_ci ioc->name, ioc->spi_data.sdp0version, ioc->spi_data.sdp0length)); 56108c2ecf20Sopenharmony_ci 56118c2ecf20Sopenharmony_ci dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Headers: 1: version %d length %d\n", 56128c2ecf20Sopenharmony_ci ioc->name, ioc->spi_data.sdp1version, ioc->spi_data.sdp1length)); 56138c2ecf20Sopenharmony_ci return 0; 56148c2ecf20Sopenharmony_ci} 56158c2ecf20Sopenharmony_ci 56168c2ecf20Sopenharmony_ci/** 56178c2ecf20Sopenharmony_ci * mpt_inactive_raid_list_free - This clears this link list. 56188c2ecf20Sopenharmony_ci * @ioc : pointer to per adapter structure 56198c2ecf20Sopenharmony_ci **/ 56208c2ecf20Sopenharmony_cistatic void 56218c2ecf20Sopenharmony_cimpt_inactive_raid_list_free(MPT_ADAPTER *ioc) 56228c2ecf20Sopenharmony_ci{ 56238c2ecf20Sopenharmony_ci struct inactive_raid_component_info *component_info, *pNext; 56248c2ecf20Sopenharmony_ci 56258c2ecf20Sopenharmony_ci if (list_empty(&ioc->raid_data.inactive_list)) 56268c2ecf20Sopenharmony_ci return; 56278c2ecf20Sopenharmony_ci 56288c2ecf20Sopenharmony_ci mutex_lock(&ioc->raid_data.inactive_list_mutex); 56298c2ecf20Sopenharmony_ci list_for_each_entry_safe(component_info, pNext, 56308c2ecf20Sopenharmony_ci &ioc->raid_data.inactive_list, list) { 56318c2ecf20Sopenharmony_ci list_del(&component_info->list); 56328c2ecf20Sopenharmony_ci kfree(component_info); 56338c2ecf20Sopenharmony_ci } 56348c2ecf20Sopenharmony_ci mutex_unlock(&ioc->raid_data.inactive_list_mutex); 56358c2ecf20Sopenharmony_ci} 56368c2ecf20Sopenharmony_ci 56378c2ecf20Sopenharmony_ci/** 56388c2ecf20Sopenharmony_ci * mpt_inactive_raid_volumes - sets up link list of phy_disk_nums for devices belonging in an inactive volume 56398c2ecf20Sopenharmony_ci * 56408c2ecf20Sopenharmony_ci * @ioc : pointer to per adapter structure 56418c2ecf20Sopenharmony_ci * @channel : volume channel 56428c2ecf20Sopenharmony_ci * @id : volume target id 56438c2ecf20Sopenharmony_ci **/ 56448c2ecf20Sopenharmony_cistatic void 56458c2ecf20Sopenharmony_cimpt_inactive_raid_volumes(MPT_ADAPTER *ioc, u8 channel, u8 id) 56468c2ecf20Sopenharmony_ci{ 56478c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 56488c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 56498c2ecf20Sopenharmony_ci dma_addr_t dma_handle; 56508c2ecf20Sopenharmony_ci pRaidVolumePage0_t buffer = NULL; 56518c2ecf20Sopenharmony_ci int i; 56528c2ecf20Sopenharmony_ci RaidPhysDiskPage0_t phys_disk; 56538c2ecf20Sopenharmony_ci struct inactive_raid_component_info *component_info; 56548c2ecf20Sopenharmony_ci int handle_inactive_volumes; 56558c2ecf20Sopenharmony_ci 56568c2ecf20Sopenharmony_ci memset(&cfg, 0 , sizeof(CONFIGPARMS)); 56578c2ecf20Sopenharmony_ci memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 56588c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME; 56598c2ecf20Sopenharmony_ci cfg.pageAddr = (channel << 8) + id; 56608c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 56618c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 56628c2ecf20Sopenharmony_ci 56638c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 56648c2ecf20Sopenharmony_ci goto out; 56658c2ecf20Sopenharmony_ci 56668c2ecf20Sopenharmony_ci if (!hdr.PageLength) 56678c2ecf20Sopenharmony_ci goto out; 56688c2ecf20Sopenharmony_ci 56698c2ecf20Sopenharmony_ci buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, 56708c2ecf20Sopenharmony_ci &dma_handle); 56718c2ecf20Sopenharmony_ci 56728c2ecf20Sopenharmony_ci if (!buffer) 56738c2ecf20Sopenharmony_ci goto out; 56748c2ecf20Sopenharmony_ci 56758c2ecf20Sopenharmony_ci cfg.physAddr = dma_handle; 56768c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 56778c2ecf20Sopenharmony_ci 56788c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 56798c2ecf20Sopenharmony_ci goto out; 56808c2ecf20Sopenharmony_ci 56818c2ecf20Sopenharmony_ci if (!buffer->NumPhysDisks) 56828c2ecf20Sopenharmony_ci goto out; 56838c2ecf20Sopenharmony_ci 56848c2ecf20Sopenharmony_ci handle_inactive_volumes = 56858c2ecf20Sopenharmony_ci (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE || 56868c2ecf20Sopenharmony_ci (buffer->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) == 0 || 56878c2ecf20Sopenharmony_ci buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_FAILED || 56888c2ecf20Sopenharmony_ci buffer->VolumeStatus.State == MPI_RAIDVOL0_STATUS_STATE_MISSING) ? 1 : 0; 56898c2ecf20Sopenharmony_ci 56908c2ecf20Sopenharmony_ci if (!handle_inactive_volumes) 56918c2ecf20Sopenharmony_ci goto out; 56928c2ecf20Sopenharmony_ci 56938c2ecf20Sopenharmony_ci mutex_lock(&ioc->raid_data.inactive_list_mutex); 56948c2ecf20Sopenharmony_ci for (i = 0; i < buffer->NumPhysDisks; i++) { 56958c2ecf20Sopenharmony_ci if(mpt_raid_phys_disk_pg0(ioc, 56968c2ecf20Sopenharmony_ci buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0) 56978c2ecf20Sopenharmony_ci continue; 56988c2ecf20Sopenharmony_ci 56998c2ecf20Sopenharmony_ci if ((component_info = kmalloc(sizeof (*component_info), 57008c2ecf20Sopenharmony_ci GFP_KERNEL)) == NULL) 57018c2ecf20Sopenharmony_ci continue; 57028c2ecf20Sopenharmony_ci 57038c2ecf20Sopenharmony_ci component_info->volumeID = id; 57048c2ecf20Sopenharmony_ci component_info->volumeBus = channel; 57058c2ecf20Sopenharmony_ci component_info->d.PhysDiskNum = phys_disk.PhysDiskNum; 57068c2ecf20Sopenharmony_ci component_info->d.PhysDiskBus = phys_disk.PhysDiskBus; 57078c2ecf20Sopenharmony_ci component_info->d.PhysDiskID = phys_disk.PhysDiskID; 57088c2ecf20Sopenharmony_ci component_info->d.PhysDiskIOC = phys_disk.PhysDiskIOC; 57098c2ecf20Sopenharmony_ci 57108c2ecf20Sopenharmony_ci list_add_tail(&component_info->list, 57118c2ecf20Sopenharmony_ci &ioc->raid_data.inactive_list); 57128c2ecf20Sopenharmony_ci } 57138c2ecf20Sopenharmony_ci mutex_unlock(&ioc->raid_data.inactive_list_mutex); 57148c2ecf20Sopenharmony_ci 57158c2ecf20Sopenharmony_ci out: 57168c2ecf20Sopenharmony_ci if (buffer) 57178c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, 57188c2ecf20Sopenharmony_ci dma_handle); 57198c2ecf20Sopenharmony_ci} 57208c2ecf20Sopenharmony_ci 57218c2ecf20Sopenharmony_ci/** 57228c2ecf20Sopenharmony_ci * mpt_raid_phys_disk_pg0 - returns phys disk page zero 57238c2ecf20Sopenharmony_ci * @ioc: Pointer to a Adapter Structure 57248c2ecf20Sopenharmony_ci * @phys_disk_num: io unit unique phys disk num generated by the ioc 57258c2ecf20Sopenharmony_ci * @phys_disk: requested payload data returned 57268c2ecf20Sopenharmony_ci * 57278c2ecf20Sopenharmony_ci * Return: 57288c2ecf20Sopenharmony_ci * 0 on success 57298c2ecf20Sopenharmony_ci * -EFAULT if read of config page header fails or data pointer not NULL 57308c2ecf20Sopenharmony_ci * -ENOMEM if pci_alloc failed 57318c2ecf20Sopenharmony_ci **/ 57328c2ecf20Sopenharmony_ciint 57338c2ecf20Sopenharmony_cimpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, 57348c2ecf20Sopenharmony_ci RaidPhysDiskPage0_t *phys_disk) 57358c2ecf20Sopenharmony_ci{ 57368c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 57378c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 57388c2ecf20Sopenharmony_ci dma_addr_t dma_handle; 57398c2ecf20Sopenharmony_ci pRaidPhysDiskPage0_t buffer = NULL; 57408c2ecf20Sopenharmony_ci int rc; 57418c2ecf20Sopenharmony_ci 57428c2ecf20Sopenharmony_ci memset(&cfg, 0 , sizeof(CONFIGPARMS)); 57438c2ecf20Sopenharmony_ci memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 57448c2ecf20Sopenharmony_ci memset(phys_disk, 0, sizeof(RaidPhysDiskPage0_t)); 57458c2ecf20Sopenharmony_ci 57468c2ecf20Sopenharmony_ci hdr.PageVersion = MPI_RAIDPHYSDISKPAGE0_PAGEVERSION; 57478c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; 57488c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 57498c2ecf20Sopenharmony_ci cfg.physAddr = -1; 57508c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 57518c2ecf20Sopenharmony_ci 57528c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 57538c2ecf20Sopenharmony_ci rc = -EFAULT; 57548c2ecf20Sopenharmony_ci goto out; 57558c2ecf20Sopenharmony_ci } 57568c2ecf20Sopenharmony_ci 57578c2ecf20Sopenharmony_ci if (!hdr.PageLength) { 57588c2ecf20Sopenharmony_ci rc = -EFAULT; 57598c2ecf20Sopenharmony_ci goto out; 57608c2ecf20Sopenharmony_ci } 57618c2ecf20Sopenharmony_ci 57628c2ecf20Sopenharmony_ci buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, 57638c2ecf20Sopenharmony_ci &dma_handle); 57648c2ecf20Sopenharmony_ci 57658c2ecf20Sopenharmony_ci if (!buffer) { 57668c2ecf20Sopenharmony_ci rc = -ENOMEM; 57678c2ecf20Sopenharmony_ci goto out; 57688c2ecf20Sopenharmony_ci } 57698c2ecf20Sopenharmony_ci 57708c2ecf20Sopenharmony_ci cfg.physAddr = dma_handle; 57718c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 57728c2ecf20Sopenharmony_ci cfg.pageAddr = phys_disk_num; 57738c2ecf20Sopenharmony_ci 57748c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 57758c2ecf20Sopenharmony_ci rc = -EFAULT; 57768c2ecf20Sopenharmony_ci goto out; 57778c2ecf20Sopenharmony_ci } 57788c2ecf20Sopenharmony_ci 57798c2ecf20Sopenharmony_ci rc = 0; 57808c2ecf20Sopenharmony_ci memcpy(phys_disk, buffer, sizeof(*buffer)); 57818c2ecf20Sopenharmony_ci phys_disk->MaxLBA = le32_to_cpu(buffer->MaxLBA); 57828c2ecf20Sopenharmony_ci 57838c2ecf20Sopenharmony_ci out: 57848c2ecf20Sopenharmony_ci 57858c2ecf20Sopenharmony_ci if (buffer) 57868c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, 57878c2ecf20Sopenharmony_ci dma_handle); 57888c2ecf20Sopenharmony_ci 57898c2ecf20Sopenharmony_ci return rc; 57908c2ecf20Sopenharmony_ci} 57918c2ecf20Sopenharmony_ci 57928c2ecf20Sopenharmony_ci/** 57938c2ecf20Sopenharmony_ci * mpt_raid_phys_disk_get_num_paths - returns number paths associated to this phys_num 57948c2ecf20Sopenharmony_ci * @ioc: Pointer to a Adapter Structure 57958c2ecf20Sopenharmony_ci * @phys_disk_num: io unit unique phys disk num generated by the ioc 57968c2ecf20Sopenharmony_ci * 57978c2ecf20Sopenharmony_ci * Return: 57988c2ecf20Sopenharmony_ci * returns number paths 57998c2ecf20Sopenharmony_ci **/ 58008c2ecf20Sopenharmony_ciint 58018c2ecf20Sopenharmony_cimpt_raid_phys_disk_get_num_paths(MPT_ADAPTER *ioc, u8 phys_disk_num) 58028c2ecf20Sopenharmony_ci{ 58038c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 58048c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 58058c2ecf20Sopenharmony_ci dma_addr_t dma_handle; 58068c2ecf20Sopenharmony_ci pRaidPhysDiskPage1_t buffer = NULL; 58078c2ecf20Sopenharmony_ci int rc; 58088c2ecf20Sopenharmony_ci 58098c2ecf20Sopenharmony_ci memset(&cfg, 0 , sizeof(CONFIGPARMS)); 58108c2ecf20Sopenharmony_ci memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 58118c2ecf20Sopenharmony_ci 58128c2ecf20Sopenharmony_ci hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; 58138c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; 58148c2ecf20Sopenharmony_ci hdr.PageNumber = 1; 58158c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 58168c2ecf20Sopenharmony_ci cfg.physAddr = -1; 58178c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 58188c2ecf20Sopenharmony_ci 58198c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 58208c2ecf20Sopenharmony_ci rc = 0; 58218c2ecf20Sopenharmony_ci goto out; 58228c2ecf20Sopenharmony_ci } 58238c2ecf20Sopenharmony_ci 58248c2ecf20Sopenharmony_ci if (!hdr.PageLength) { 58258c2ecf20Sopenharmony_ci rc = 0; 58268c2ecf20Sopenharmony_ci goto out; 58278c2ecf20Sopenharmony_ci } 58288c2ecf20Sopenharmony_ci 58298c2ecf20Sopenharmony_ci buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, 58308c2ecf20Sopenharmony_ci &dma_handle); 58318c2ecf20Sopenharmony_ci 58328c2ecf20Sopenharmony_ci if (!buffer) { 58338c2ecf20Sopenharmony_ci rc = 0; 58348c2ecf20Sopenharmony_ci goto out; 58358c2ecf20Sopenharmony_ci } 58368c2ecf20Sopenharmony_ci 58378c2ecf20Sopenharmony_ci cfg.physAddr = dma_handle; 58388c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 58398c2ecf20Sopenharmony_ci cfg.pageAddr = phys_disk_num; 58408c2ecf20Sopenharmony_ci 58418c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 58428c2ecf20Sopenharmony_ci rc = 0; 58438c2ecf20Sopenharmony_ci goto out; 58448c2ecf20Sopenharmony_ci } 58458c2ecf20Sopenharmony_ci 58468c2ecf20Sopenharmony_ci rc = buffer->NumPhysDiskPaths; 58478c2ecf20Sopenharmony_ci out: 58488c2ecf20Sopenharmony_ci 58498c2ecf20Sopenharmony_ci if (buffer) 58508c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, 58518c2ecf20Sopenharmony_ci dma_handle); 58528c2ecf20Sopenharmony_ci 58538c2ecf20Sopenharmony_ci return rc; 58548c2ecf20Sopenharmony_ci} 58558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_raid_phys_disk_get_num_paths); 58568c2ecf20Sopenharmony_ci 58578c2ecf20Sopenharmony_ci/** 58588c2ecf20Sopenharmony_ci * mpt_raid_phys_disk_pg1 - returns phys disk page 1 58598c2ecf20Sopenharmony_ci * @ioc: Pointer to a Adapter Structure 58608c2ecf20Sopenharmony_ci * @phys_disk_num: io unit unique phys disk num generated by the ioc 58618c2ecf20Sopenharmony_ci * @phys_disk: requested payload data returned 58628c2ecf20Sopenharmony_ci * 58638c2ecf20Sopenharmony_ci * Return: 58648c2ecf20Sopenharmony_ci * 0 on success 58658c2ecf20Sopenharmony_ci * -EFAULT if read of config page header fails or data pointer not NULL 58668c2ecf20Sopenharmony_ci * -ENOMEM if pci_alloc failed 58678c2ecf20Sopenharmony_ci **/ 58688c2ecf20Sopenharmony_ciint 58698c2ecf20Sopenharmony_cimpt_raid_phys_disk_pg1(MPT_ADAPTER *ioc, u8 phys_disk_num, 58708c2ecf20Sopenharmony_ci RaidPhysDiskPage1_t *phys_disk) 58718c2ecf20Sopenharmony_ci{ 58728c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 58738c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 58748c2ecf20Sopenharmony_ci dma_addr_t dma_handle; 58758c2ecf20Sopenharmony_ci pRaidPhysDiskPage1_t buffer = NULL; 58768c2ecf20Sopenharmony_ci int rc; 58778c2ecf20Sopenharmony_ci int i; 58788c2ecf20Sopenharmony_ci __le64 sas_address; 58798c2ecf20Sopenharmony_ci 58808c2ecf20Sopenharmony_ci memset(&cfg, 0 , sizeof(CONFIGPARMS)); 58818c2ecf20Sopenharmony_ci memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 58828c2ecf20Sopenharmony_ci rc = 0; 58838c2ecf20Sopenharmony_ci 58848c2ecf20Sopenharmony_ci hdr.PageVersion = MPI_RAIDPHYSDISKPAGE1_PAGEVERSION; 58858c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_PHYSDISK; 58868c2ecf20Sopenharmony_ci hdr.PageNumber = 1; 58878c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 58888c2ecf20Sopenharmony_ci cfg.physAddr = -1; 58898c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 58908c2ecf20Sopenharmony_ci 58918c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 58928c2ecf20Sopenharmony_ci rc = -EFAULT; 58938c2ecf20Sopenharmony_ci goto out; 58948c2ecf20Sopenharmony_ci } 58958c2ecf20Sopenharmony_ci 58968c2ecf20Sopenharmony_ci if (!hdr.PageLength) { 58978c2ecf20Sopenharmony_ci rc = -EFAULT; 58988c2ecf20Sopenharmony_ci goto out; 58998c2ecf20Sopenharmony_ci } 59008c2ecf20Sopenharmony_ci 59018c2ecf20Sopenharmony_ci buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, 59028c2ecf20Sopenharmony_ci &dma_handle); 59038c2ecf20Sopenharmony_ci 59048c2ecf20Sopenharmony_ci if (!buffer) { 59058c2ecf20Sopenharmony_ci rc = -ENOMEM; 59068c2ecf20Sopenharmony_ci goto out; 59078c2ecf20Sopenharmony_ci } 59088c2ecf20Sopenharmony_ci 59098c2ecf20Sopenharmony_ci cfg.physAddr = dma_handle; 59108c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 59118c2ecf20Sopenharmony_ci cfg.pageAddr = phys_disk_num; 59128c2ecf20Sopenharmony_ci 59138c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) { 59148c2ecf20Sopenharmony_ci rc = -EFAULT; 59158c2ecf20Sopenharmony_ci goto out; 59168c2ecf20Sopenharmony_ci } 59178c2ecf20Sopenharmony_ci 59188c2ecf20Sopenharmony_ci phys_disk->NumPhysDiskPaths = buffer->NumPhysDiskPaths; 59198c2ecf20Sopenharmony_ci phys_disk->PhysDiskNum = phys_disk_num; 59208c2ecf20Sopenharmony_ci for (i = 0; i < phys_disk->NumPhysDiskPaths; i++) { 59218c2ecf20Sopenharmony_ci phys_disk->Path[i].PhysDiskID = buffer->Path[i].PhysDiskID; 59228c2ecf20Sopenharmony_ci phys_disk->Path[i].PhysDiskBus = buffer->Path[i].PhysDiskBus; 59238c2ecf20Sopenharmony_ci phys_disk->Path[i].OwnerIdentifier = 59248c2ecf20Sopenharmony_ci buffer->Path[i].OwnerIdentifier; 59258c2ecf20Sopenharmony_ci phys_disk->Path[i].Flags = le16_to_cpu(buffer->Path[i].Flags); 59268c2ecf20Sopenharmony_ci memcpy(&sas_address, &buffer->Path[i].WWID, sizeof(__le64)); 59278c2ecf20Sopenharmony_ci sas_address = le64_to_cpu(sas_address); 59288c2ecf20Sopenharmony_ci memcpy(&phys_disk->Path[i].WWID, &sas_address, sizeof(__le64)); 59298c2ecf20Sopenharmony_ci memcpy(&sas_address, 59308c2ecf20Sopenharmony_ci &buffer->Path[i].OwnerWWID, sizeof(__le64)); 59318c2ecf20Sopenharmony_ci sas_address = le64_to_cpu(sas_address); 59328c2ecf20Sopenharmony_ci memcpy(&phys_disk->Path[i].OwnerWWID, 59338c2ecf20Sopenharmony_ci &sas_address, sizeof(__le64)); 59348c2ecf20Sopenharmony_ci } 59358c2ecf20Sopenharmony_ci 59368c2ecf20Sopenharmony_ci out: 59378c2ecf20Sopenharmony_ci 59388c2ecf20Sopenharmony_ci if (buffer) 59398c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer, 59408c2ecf20Sopenharmony_ci dma_handle); 59418c2ecf20Sopenharmony_ci 59428c2ecf20Sopenharmony_ci return rc; 59438c2ecf20Sopenharmony_ci} 59448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_raid_phys_disk_pg1); 59458c2ecf20Sopenharmony_ci 59468c2ecf20Sopenharmony_ci 59478c2ecf20Sopenharmony_ci/** 59488c2ecf20Sopenharmony_ci * mpt_findImVolumes - Identify IDs of hidden disks and RAID Volumes 59498c2ecf20Sopenharmony_ci * @ioc: Pointer to a Adapter Strucutre 59508c2ecf20Sopenharmony_ci * 59518c2ecf20Sopenharmony_ci * Return: 59528c2ecf20Sopenharmony_ci * 0 on success 59538c2ecf20Sopenharmony_ci * -EFAULT if read of config page header fails or data pointer not NULL 59548c2ecf20Sopenharmony_ci * -ENOMEM if pci_alloc failed 59558c2ecf20Sopenharmony_ci **/ 59568c2ecf20Sopenharmony_ciint 59578c2ecf20Sopenharmony_cimpt_findImVolumes(MPT_ADAPTER *ioc) 59588c2ecf20Sopenharmony_ci{ 59598c2ecf20Sopenharmony_ci IOCPage2_t *pIoc2; 59608c2ecf20Sopenharmony_ci u8 *mem; 59618c2ecf20Sopenharmony_ci dma_addr_t ioc2_dma; 59628c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 59638c2ecf20Sopenharmony_ci ConfigPageHeader_t header; 59648c2ecf20Sopenharmony_ci int rc = 0; 59658c2ecf20Sopenharmony_ci int iocpage2sz; 59668c2ecf20Sopenharmony_ci int i; 59678c2ecf20Sopenharmony_ci 59688c2ecf20Sopenharmony_ci if (!ioc->ir_firmware) 59698c2ecf20Sopenharmony_ci return 0; 59708c2ecf20Sopenharmony_ci 59718c2ecf20Sopenharmony_ci /* Free the old page 59728c2ecf20Sopenharmony_ci */ 59738c2ecf20Sopenharmony_ci kfree(ioc->raid_data.pIocPg2); 59748c2ecf20Sopenharmony_ci ioc->raid_data.pIocPg2 = NULL; 59758c2ecf20Sopenharmony_ci mpt_inactive_raid_list_free(ioc); 59768c2ecf20Sopenharmony_ci 59778c2ecf20Sopenharmony_ci /* Read IOCP2 header then the page. 59788c2ecf20Sopenharmony_ci */ 59798c2ecf20Sopenharmony_ci header.PageVersion = 0; 59808c2ecf20Sopenharmony_ci header.PageLength = 0; 59818c2ecf20Sopenharmony_ci header.PageNumber = 2; 59828c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_IOC; 59838c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 59848c2ecf20Sopenharmony_ci cfg.physAddr = -1; 59858c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 59868c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 59878c2ecf20Sopenharmony_ci cfg.dir = 0; 59888c2ecf20Sopenharmony_ci cfg.timeout = 0; 59898c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 59908c2ecf20Sopenharmony_ci return -EFAULT; 59918c2ecf20Sopenharmony_ci 59928c2ecf20Sopenharmony_ci if (header.PageLength == 0) 59938c2ecf20Sopenharmony_ci return -EFAULT; 59948c2ecf20Sopenharmony_ci 59958c2ecf20Sopenharmony_ci iocpage2sz = header.PageLength * 4; 59968c2ecf20Sopenharmony_ci pIoc2 = pci_alloc_consistent(ioc->pcidev, iocpage2sz, &ioc2_dma); 59978c2ecf20Sopenharmony_ci if (!pIoc2) 59988c2ecf20Sopenharmony_ci return -ENOMEM; 59998c2ecf20Sopenharmony_ci 60008c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 60018c2ecf20Sopenharmony_ci cfg.physAddr = ioc2_dma; 60028c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 60038c2ecf20Sopenharmony_ci goto out; 60048c2ecf20Sopenharmony_ci 60058c2ecf20Sopenharmony_ci mem = kmemdup(pIoc2, iocpage2sz, GFP_KERNEL); 60068c2ecf20Sopenharmony_ci if (!mem) { 60078c2ecf20Sopenharmony_ci rc = -ENOMEM; 60088c2ecf20Sopenharmony_ci goto out; 60098c2ecf20Sopenharmony_ci } 60108c2ecf20Sopenharmony_ci 60118c2ecf20Sopenharmony_ci ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; 60128c2ecf20Sopenharmony_ci 60138c2ecf20Sopenharmony_ci mpt_read_ioc_pg_3(ioc); 60148c2ecf20Sopenharmony_ci 60158c2ecf20Sopenharmony_ci for (i = 0; i < pIoc2->NumActiveVolumes ; i++) 60168c2ecf20Sopenharmony_ci mpt_inactive_raid_volumes(ioc, 60178c2ecf20Sopenharmony_ci pIoc2->RaidVolume[i].VolumeBus, 60188c2ecf20Sopenharmony_ci pIoc2->RaidVolume[i].VolumeID); 60198c2ecf20Sopenharmony_ci 60208c2ecf20Sopenharmony_ci out: 60218c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, iocpage2sz, pIoc2, ioc2_dma); 60228c2ecf20Sopenharmony_ci 60238c2ecf20Sopenharmony_ci return rc; 60248c2ecf20Sopenharmony_ci} 60258c2ecf20Sopenharmony_ci 60268c2ecf20Sopenharmony_cistatic int 60278c2ecf20Sopenharmony_cimpt_read_ioc_pg_3(MPT_ADAPTER *ioc) 60288c2ecf20Sopenharmony_ci{ 60298c2ecf20Sopenharmony_ci IOCPage3_t *pIoc3; 60308c2ecf20Sopenharmony_ci u8 *mem; 60318c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 60328c2ecf20Sopenharmony_ci ConfigPageHeader_t header; 60338c2ecf20Sopenharmony_ci dma_addr_t ioc3_dma; 60348c2ecf20Sopenharmony_ci int iocpage3sz = 0; 60358c2ecf20Sopenharmony_ci 60368c2ecf20Sopenharmony_ci /* Free the old page 60378c2ecf20Sopenharmony_ci */ 60388c2ecf20Sopenharmony_ci kfree(ioc->raid_data.pIocPg3); 60398c2ecf20Sopenharmony_ci ioc->raid_data.pIocPg3 = NULL; 60408c2ecf20Sopenharmony_ci 60418c2ecf20Sopenharmony_ci /* There is at least one physical disk. 60428c2ecf20Sopenharmony_ci * Read and save IOC Page 3 60438c2ecf20Sopenharmony_ci */ 60448c2ecf20Sopenharmony_ci header.PageVersion = 0; 60458c2ecf20Sopenharmony_ci header.PageLength = 0; 60468c2ecf20Sopenharmony_ci header.PageNumber = 3; 60478c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_IOC; 60488c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 60498c2ecf20Sopenharmony_ci cfg.physAddr = -1; 60508c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 60518c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 60528c2ecf20Sopenharmony_ci cfg.dir = 0; 60538c2ecf20Sopenharmony_ci cfg.timeout = 0; 60548c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 60558c2ecf20Sopenharmony_ci return 0; 60568c2ecf20Sopenharmony_ci 60578c2ecf20Sopenharmony_ci if (header.PageLength == 0) 60588c2ecf20Sopenharmony_ci return 0; 60598c2ecf20Sopenharmony_ci 60608c2ecf20Sopenharmony_ci /* Read Header good, alloc memory 60618c2ecf20Sopenharmony_ci */ 60628c2ecf20Sopenharmony_ci iocpage3sz = header.PageLength * 4; 60638c2ecf20Sopenharmony_ci pIoc3 = pci_alloc_consistent(ioc->pcidev, iocpage3sz, &ioc3_dma); 60648c2ecf20Sopenharmony_ci if (!pIoc3) 60658c2ecf20Sopenharmony_ci return 0; 60668c2ecf20Sopenharmony_ci 60678c2ecf20Sopenharmony_ci /* Read the Page and save the data 60688c2ecf20Sopenharmony_ci * into malloc'd memory. 60698c2ecf20Sopenharmony_ci */ 60708c2ecf20Sopenharmony_ci cfg.physAddr = ioc3_dma; 60718c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 60728c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) == 0) { 60738c2ecf20Sopenharmony_ci mem = kmalloc(iocpage3sz, GFP_KERNEL); 60748c2ecf20Sopenharmony_ci if (mem) { 60758c2ecf20Sopenharmony_ci memcpy(mem, (u8 *)pIoc3, iocpage3sz); 60768c2ecf20Sopenharmony_ci ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; 60778c2ecf20Sopenharmony_ci } 60788c2ecf20Sopenharmony_ci } 60798c2ecf20Sopenharmony_ci 60808c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, iocpage3sz, pIoc3, ioc3_dma); 60818c2ecf20Sopenharmony_ci 60828c2ecf20Sopenharmony_ci return 0; 60838c2ecf20Sopenharmony_ci} 60848c2ecf20Sopenharmony_ci 60858c2ecf20Sopenharmony_cistatic void 60868c2ecf20Sopenharmony_cimpt_read_ioc_pg_4(MPT_ADAPTER *ioc) 60878c2ecf20Sopenharmony_ci{ 60888c2ecf20Sopenharmony_ci IOCPage4_t *pIoc4; 60898c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 60908c2ecf20Sopenharmony_ci ConfigPageHeader_t header; 60918c2ecf20Sopenharmony_ci dma_addr_t ioc4_dma; 60928c2ecf20Sopenharmony_ci int iocpage4sz; 60938c2ecf20Sopenharmony_ci 60948c2ecf20Sopenharmony_ci /* Read and save IOC Page 4 60958c2ecf20Sopenharmony_ci */ 60968c2ecf20Sopenharmony_ci header.PageVersion = 0; 60978c2ecf20Sopenharmony_ci header.PageLength = 0; 60988c2ecf20Sopenharmony_ci header.PageNumber = 4; 60998c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_IOC; 61008c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 61018c2ecf20Sopenharmony_ci cfg.physAddr = -1; 61028c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 61038c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 61048c2ecf20Sopenharmony_ci cfg.dir = 0; 61058c2ecf20Sopenharmony_ci cfg.timeout = 0; 61068c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 61078c2ecf20Sopenharmony_ci return; 61088c2ecf20Sopenharmony_ci 61098c2ecf20Sopenharmony_ci if (header.PageLength == 0) 61108c2ecf20Sopenharmony_ci return; 61118c2ecf20Sopenharmony_ci 61128c2ecf20Sopenharmony_ci if ( (pIoc4 = ioc->spi_data.pIocPg4) == NULL ) { 61138c2ecf20Sopenharmony_ci iocpage4sz = (header.PageLength + 4) * 4; /* Allow 4 additional SEP's */ 61148c2ecf20Sopenharmony_ci pIoc4 = pci_alloc_consistent(ioc->pcidev, iocpage4sz, &ioc4_dma); 61158c2ecf20Sopenharmony_ci if (!pIoc4) 61168c2ecf20Sopenharmony_ci return; 61178c2ecf20Sopenharmony_ci ioc->alloc_total += iocpage4sz; 61188c2ecf20Sopenharmony_ci } else { 61198c2ecf20Sopenharmony_ci ioc4_dma = ioc->spi_data.IocPg4_dma; 61208c2ecf20Sopenharmony_ci iocpage4sz = ioc->spi_data.IocPg4Sz; 61218c2ecf20Sopenharmony_ci } 61228c2ecf20Sopenharmony_ci 61238c2ecf20Sopenharmony_ci /* Read the Page into dma memory. 61248c2ecf20Sopenharmony_ci */ 61258c2ecf20Sopenharmony_ci cfg.physAddr = ioc4_dma; 61268c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 61278c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) == 0) { 61288c2ecf20Sopenharmony_ci ioc->spi_data.pIocPg4 = (IOCPage4_t *) pIoc4; 61298c2ecf20Sopenharmony_ci ioc->spi_data.IocPg4_dma = ioc4_dma; 61308c2ecf20Sopenharmony_ci ioc->spi_data.IocPg4Sz = iocpage4sz; 61318c2ecf20Sopenharmony_ci } else { 61328c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, iocpage4sz, pIoc4, ioc4_dma); 61338c2ecf20Sopenharmony_ci ioc->spi_data.pIocPg4 = NULL; 61348c2ecf20Sopenharmony_ci ioc->alloc_total -= iocpage4sz; 61358c2ecf20Sopenharmony_ci } 61368c2ecf20Sopenharmony_ci} 61378c2ecf20Sopenharmony_ci 61388c2ecf20Sopenharmony_cistatic void 61398c2ecf20Sopenharmony_cimpt_read_ioc_pg_1(MPT_ADAPTER *ioc) 61408c2ecf20Sopenharmony_ci{ 61418c2ecf20Sopenharmony_ci IOCPage1_t *pIoc1; 61428c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 61438c2ecf20Sopenharmony_ci ConfigPageHeader_t header; 61448c2ecf20Sopenharmony_ci dma_addr_t ioc1_dma; 61458c2ecf20Sopenharmony_ci int iocpage1sz = 0; 61468c2ecf20Sopenharmony_ci u32 tmp; 61478c2ecf20Sopenharmony_ci 61488c2ecf20Sopenharmony_ci /* Check the Coalescing Timeout in IOC Page 1 61498c2ecf20Sopenharmony_ci */ 61508c2ecf20Sopenharmony_ci header.PageVersion = 0; 61518c2ecf20Sopenharmony_ci header.PageLength = 0; 61528c2ecf20Sopenharmony_ci header.PageNumber = 1; 61538c2ecf20Sopenharmony_ci header.PageType = MPI_CONFIG_PAGETYPE_IOC; 61548c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &header; 61558c2ecf20Sopenharmony_ci cfg.physAddr = -1; 61568c2ecf20Sopenharmony_ci cfg.pageAddr = 0; 61578c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 61588c2ecf20Sopenharmony_ci cfg.dir = 0; 61598c2ecf20Sopenharmony_ci cfg.timeout = 0; 61608c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 61618c2ecf20Sopenharmony_ci return; 61628c2ecf20Sopenharmony_ci 61638c2ecf20Sopenharmony_ci if (header.PageLength == 0) 61648c2ecf20Sopenharmony_ci return; 61658c2ecf20Sopenharmony_ci 61668c2ecf20Sopenharmony_ci /* Read Header good, alloc memory 61678c2ecf20Sopenharmony_ci */ 61688c2ecf20Sopenharmony_ci iocpage1sz = header.PageLength * 4; 61698c2ecf20Sopenharmony_ci pIoc1 = pci_alloc_consistent(ioc->pcidev, iocpage1sz, &ioc1_dma); 61708c2ecf20Sopenharmony_ci if (!pIoc1) 61718c2ecf20Sopenharmony_ci return; 61728c2ecf20Sopenharmony_ci 61738c2ecf20Sopenharmony_ci /* Read the Page and check coalescing timeout 61748c2ecf20Sopenharmony_ci */ 61758c2ecf20Sopenharmony_ci cfg.physAddr = ioc1_dma; 61768c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 61778c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) == 0) { 61788c2ecf20Sopenharmony_ci 61798c2ecf20Sopenharmony_ci tmp = le32_to_cpu(pIoc1->Flags) & MPI_IOCPAGE1_REPLY_COALESCING; 61808c2ecf20Sopenharmony_ci if (tmp == MPI_IOCPAGE1_REPLY_COALESCING) { 61818c2ecf20Sopenharmony_ci tmp = le32_to_cpu(pIoc1->CoalescingTimeout); 61828c2ecf20Sopenharmony_ci 61838c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Coalescing Enabled Timeout = %d\n", 61848c2ecf20Sopenharmony_ci ioc->name, tmp)); 61858c2ecf20Sopenharmony_ci 61868c2ecf20Sopenharmony_ci if (tmp > MPT_COALESCING_TIMEOUT) { 61878c2ecf20Sopenharmony_ci pIoc1->CoalescingTimeout = cpu_to_le32(MPT_COALESCING_TIMEOUT); 61888c2ecf20Sopenharmony_ci 61898c2ecf20Sopenharmony_ci /* Write NVRAM and current 61908c2ecf20Sopenharmony_ci */ 61918c2ecf20Sopenharmony_ci cfg.dir = 1; 61928c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; 61938c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) == 0) { 61948c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Reset Current Coalescing Timeout to = %d\n", 61958c2ecf20Sopenharmony_ci ioc->name, MPT_COALESCING_TIMEOUT)); 61968c2ecf20Sopenharmony_ci 61978c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM; 61988c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) == 0) { 61998c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 62008c2ecf20Sopenharmony_ci "Reset NVRAM Coalescing Timeout to = %d\n", 62018c2ecf20Sopenharmony_ci ioc->name, MPT_COALESCING_TIMEOUT)); 62028c2ecf20Sopenharmony_ci } else { 62038c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_DEBUG_FMT 62048c2ecf20Sopenharmony_ci "Reset NVRAM Coalescing Timeout Failed\n", 62058c2ecf20Sopenharmony_ci ioc->name)); 62068c2ecf20Sopenharmony_ci } 62078c2ecf20Sopenharmony_ci 62088c2ecf20Sopenharmony_ci } else { 62098c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_WARN_FMT 62108c2ecf20Sopenharmony_ci "Reset of Current Coalescing Timeout Failed!\n", 62118c2ecf20Sopenharmony_ci ioc->name)); 62128c2ecf20Sopenharmony_ci } 62138c2ecf20Sopenharmony_ci } 62148c2ecf20Sopenharmony_ci 62158c2ecf20Sopenharmony_ci } else { 62168c2ecf20Sopenharmony_ci dprintk(ioc, printk(MYIOC_s_WARN_FMT "Coalescing Disabled\n", ioc->name)); 62178c2ecf20Sopenharmony_ci } 62188c2ecf20Sopenharmony_ci } 62198c2ecf20Sopenharmony_ci 62208c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, iocpage1sz, pIoc1, ioc1_dma); 62218c2ecf20Sopenharmony_ci 62228c2ecf20Sopenharmony_ci return; 62238c2ecf20Sopenharmony_ci} 62248c2ecf20Sopenharmony_ci 62258c2ecf20Sopenharmony_cistatic void 62268c2ecf20Sopenharmony_cimpt_get_manufacturing_pg_0(MPT_ADAPTER *ioc) 62278c2ecf20Sopenharmony_ci{ 62288c2ecf20Sopenharmony_ci CONFIGPARMS cfg; 62298c2ecf20Sopenharmony_ci ConfigPageHeader_t hdr; 62308c2ecf20Sopenharmony_ci dma_addr_t buf_dma; 62318c2ecf20Sopenharmony_ci ManufacturingPage0_t *pbuf = NULL; 62328c2ecf20Sopenharmony_ci 62338c2ecf20Sopenharmony_ci memset(&cfg, 0 , sizeof(CONFIGPARMS)); 62348c2ecf20Sopenharmony_ci memset(&hdr, 0 , sizeof(ConfigPageHeader_t)); 62358c2ecf20Sopenharmony_ci 62368c2ecf20Sopenharmony_ci hdr.PageType = MPI_CONFIG_PAGETYPE_MANUFACTURING; 62378c2ecf20Sopenharmony_ci cfg.cfghdr.hdr = &hdr; 62388c2ecf20Sopenharmony_ci cfg.physAddr = -1; 62398c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; 62408c2ecf20Sopenharmony_ci cfg.timeout = 10; 62418c2ecf20Sopenharmony_ci 62428c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 62438c2ecf20Sopenharmony_ci goto out; 62448c2ecf20Sopenharmony_ci 62458c2ecf20Sopenharmony_ci if (!cfg.cfghdr.hdr->PageLength) 62468c2ecf20Sopenharmony_ci goto out; 62478c2ecf20Sopenharmony_ci 62488c2ecf20Sopenharmony_ci cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 62498c2ecf20Sopenharmony_ci pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma); 62508c2ecf20Sopenharmony_ci if (!pbuf) 62518c2ecf20Sopenharmony_ci goto out; 62528c2ecf20Sopenharmony_ci 62538c2ecf20Sopenharmony_ci cfg.physAddr = buf_dma; 62548c2ecf20Sopenharmony_ci 62558c2ecf20Sopenharmony_ci if (mpt_config(ioc, &cfg) != 0) 62568c2ecf20Sopenharmony_ci goto out; 62578c2ecf20Sopenharmony_ci 62588c2ecf20Sopenharmony_ci memcpy(ioc->board_name, pbuf->BoardName, sizeof(ioc->board_name)); 62598c2ecf20Sopenharmony_ci memcpy(ioc->board_assembly, pbuf->BoardAssembly, sizeof(ioc->board_assembly)); 62608c2ecf20Sopenharmony_ci memcpy(ioc->board_tracer, pbuf->BoardTracerNumber, sizeof(ioc->board_tracer)); 62618c2ecf20Sopenharmony_ci 62628c2ecf20Sopenharmony_ciout: 62638c2ecf20Sopenharmony_ci 62648c2ecf20Sopenharmony_ci if (pbuf) 62658c2ecf20Sopenharmony_ci pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); 62668c2ecf20Sopenharmony_ci} 62678c2ecf20Sopenharmony_ci 62688c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 62698c2ecf20Sopenharmony_ci/** 62708c2ecf20Sopenharmony_ci * SendEventNotification - Send EventNotification (on or off) request to adapter 62718c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 62728c2ecf20Sopenharmony_ci * @EvSwitch: Event switch flags 62738c2ecf20Sopenharmony_ci * @sleepFlag: Specifies whether the process can sleep 62748c2ecf20Sopenharmony_ci */ 62758c2ecf20Sopenharmony_cistatic int 62768c2ecf20Sopenharmony_ciSendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch, int sleepFlag) 62778c2ecf20Sopenharmony_ci{ 62788c2ecf20Sopenharmony_ci EventNotification_t evn; 62798c2ecf20Sopenharmony_ci MPIDefaultReply_t reply_buf; 62808c2ecf20Sopenharmony_ci 62818c2ecf20Sopenharmony_ci memset(&evn, 0, sizeof(EventNotification_t)); 62828c2ecf20Sopenharmony_ci memset(&reply_buf, 0, sizeof(MPIDefaultReply_t)); 62838c2ecf20Sopenharmony_ci 62848c2ecf20Sopenharmony_ci evn.Function = MPI_FUNCTION_EVENT_NOTIFICATION; 62858c2ecf20Sopenharmony_ci evn.Switch = EvSwitch; 62868c2ecf20Sopenharmony_ci evn.MsgContext = cpu_to_le32(mpt_base_index << 16); 62878c2ecf20Sopenharmony_ci 62888c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 62898c2ecf20Sopenharmony_ci "Sending EventNotification (%d) request %p\n", 62908c2ecf20Sopenharmony_ci ioc->name, EvSwitch, &evn)); 62918c2ecf20Sopenharmony_ci 62928c2ecf20Sopenharmony_ci return mpt_handshake_req_reply_wait(ioc, sizeof(EventNotification_t), 62938c2ecf20Sopenharmony_ci (u32 *)&evn, sizeof(MPIDefaultReply_t), (u16 *)&reply_buf, 30, 62948c2ecf20Sopenharmony_ci sleepFlag); 62958c2ecf20Sopenharmony_ci} 62968c2ecf20Sopenharmony_ci 62978c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 62988c2ecf20Sopenharmony_ci/** 62998c2ecf20Sopenharmony_ci * SendEventAck - Send EventAck request to MPT adapter. 63008c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 63018c2ecf20Sopenharmony_ci * @evnp: Pointer to original EventNotification request 63028c2ecf20Sopenharmony_ci */ 63038c2ecf20Sopenharmony_cistatic int 63048c2ecf20Sopenharmony_ciSendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) 63058c2ecf20Sopenharmony_ci{ 63068c2ecf20Sopenharmony_ci EventAck_t *pAck; 63078c2ecf20Sopenharmony_ci 63088c2ecf20Sopenharmony_ci if ((pAck = (EventAck_t *) mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { 63098c2ecf20Sopenharmony_ci dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames!!\n", 63108c2ecf20Sopenharmony_ci ioc->name, __func__)); 63118c2ecf20Sopenharmony_ci return -1; 63128c2ecf20Sopenharmony_ci } 63138c2ecf20Sopenharmony_ci 63148c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending EventAck\n", ioc->name)); 63158c2ecf20Sopenharmony_ci 63168c2ecf20Sopenharmony_ci pAck->Function = MPI_FUNCTION_EVENT_ACK; 63178c2ecf20Sopenharmony_ci pAck->ChainOffset = 0; 63188c2ecf20Sopenharmony_ci pAck->Reserved[0] = pAck->Reserved[1] = 0; 63198c2ecf20Sopenharmony_ci pAck->MsgFlags = 0; 63208c2ecf20Sopenharmony_ci pAck->Reserved1[0] = pAck->Reserved1[1] = pAck->Reserved1[2] = 0; 63218c2ecf20Sopenharmony_ci pAck->Event = evnp->Event; 63228c2ecf20Sopenharmony_ci pAck->EventContext = evnp->EventContext; 63238c2ecf20Sopenharmony_ci 63248c2ecf20Sopenharmony_ci mpt_put_msg_frame(mpt_base_index, ioc, (MPT_FRAME_HDR *)pAck); 63258c2ecf20Sopenharmony_ci 63268c2ecf20Sopenharmony_ci return 0; 63278c2ecf20Sopenharmony_ci} 63288c2ecf20Sopenharmony_ci 63298c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 63308c2ecf20Sopenharmony_ci/** 63318c2ecf20Sopenharmony_ci * mpt_config - Generic function to issue config message 63328c2ecf20Sopenharmony_ci * @ioc: Pointer to an adapter structure 63338c2ecf20Sopenharmony_ci * @pCfg: Pointer to a configuration structure. Struct contains 63348c2ecf20Sopenharmony_ci * action, page address, direction, physical address 63358c2ecf20Sopenharmony_ci * and pointer to a configuration page header 63368c2ecf20Sopenharmony_ci * Page header is updated. 63378c2ecf20Sopenharmony_ci * 63388c2ecf20Sopenharmony_ci * Returns 0 for success 63398c2ecf20Sopenharmony_ci * -EPERM if not allowed due to ISR context 63408c2ecf20Sopenharmony_ci * -EAGAIN if no msg frames currently available 63418c2ecf20Sopenharmony_ci * -EFAULT for non-successful reply or no reply (timeout) 63428c2ecf20Sopenharmony_ci */ 63438c2ecf20Sopenharmony_ciint 63448c2ecf20Sopenharmony_cimpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) 63458c2ecf20Sopenharmony_ci{ 63468c2ecf20Sopenharmony_ci Config_t *pReq; 63478c2ecf20Sopenharmony_ci ConfigReply_t *pReply; 63488c2ecf20Sopenharmony_ci ConfigExtendedPageHeader_t *pExtHdr = NULL; 63498c2ecf20Sopenharmony_ci MPT_FRAME_HDR *mf; 63508c2ecf20Sopenharmony_ci int ii; 63518c2ecf20Sopenharmony_ci int flagsLength; 63528c2ecf20Sopenharmony_ci long timeout; 63538c2ecf20Sopenharmony_ci int ret; 63548c2ecf20Sopenharmony_ci u8 page_type = 0, extend_page; 63558c2ecf20Sopenharmony_ci unsigned long timeleft; 63568c2ecf20Sopenharmony_ci unsigned long flags; 63578c2ecf20Sopenharmony_ci int in_isr; 63588c2ecf20Sopenharmony_ci u8 issue_hard_reset = 0; 63598c2ecf20Sopenharmony_ci u8 retry_count = 0; 63608c2ecf20Sopenharmony_ci 63618c2ecf20Sopenharmony_ci /* Prevent calling wait_event() (below), if caller happens 63628c2ecf20Sopenharmony_ci * to be in ISR context, because that is fatal! 63638c2ecf20Sopenharmony_ci */ 63648c2ecf20Sopenharmony_ci in_isr = in_interrupt(); 63658c2ecf20Sopenharmony_ci if (in_isr) { 63668c2ecf20Sopenharmony_ci dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", 63678c2ecf20Sopenharmony_ci ioc->name)); 63688c2ecf20Sopenharmony_ci return -EPERM; 63698c2ecf20Sopenharmony_ci } 63708c2ecf20Sopenharmony_ci 63718c2ecf20Sopenharmony_ci /* don't send a config page during diag reset */ 63728c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 63738c2ecf20Sopenharmony_ci if (ioc->ioc_reset_in_progress) { 63748c2ecf20Sopenharmony_ci dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 63758c2ecf20Sopenharmony_ci "%s: busy with host reset\n", ioc->name, __func__)); 63768c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 63778c2ecf20Sopenharmony_ci return -EBUSY; 63788c2ecf20Sopenharmony_ci } 63798c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 63808c2ecf20Sopenharmony_ci 63818c2ecf20Sopenharmony_ci /* don't send if no chance of success */ 63828c2ecf20Sopenharmony_ci if (!ioc->active || 63838c2ecf20Sopenharmony_ci mpt_GetIocState(ioc, 1) != MPI_IOC_STATE_OPERATIONAL) { 63848c2ecf20Sopenharmony_ci dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 63858c2ecf20Sopenharmony_ci "%s: ioc not operational, %d, %xh\n", 63868c2ecf20Sopenharmony_ci ioc->name, __func__, ioc->active, 63878c2ecf20Sopenharmony_ci mpt_GetIocState(ioc, 0))); 63888c2ecf20Sopenharmony_ci return -EFAULT; 63898c2ecf20Sopenharmony_ci } 63908c2ecf20Sopenharmony_ci 63918c2ecf20Sopenharmony_ci retry_config: 63928c2ecf20Sopenharmony_ci mutex_lock(&ioc->mptbase_cmds.mutex); 63938c2ecf20Sopenharmony_ci /* init the internal cmd struct */ 63948c2ecf20Sopenharmony_ci memset(ioc->mptbase_cmds.reply, 0 , MPT_DEFAULT_FRAME_SIZE); 63958c2ecf20Sopenharmony_ci INITIALIZE_MGMT_STATUS(ioc->mptbase_cmds.status) 63968c2ecf20Sopenharmony_ci 63978c2ecf20Sopenharmony_ci /* Get and Populate a free Frame 63988c2ecf20Sopenharmony_ci */ 63998c2ecf20Sopenharmony_ci if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { 64008c2ecf20Sopenharmony_ci dcprintk(ioc, printk(MYIOC_s_WARN_FMT 64018c2ecf20Sopenharmony_ci "mpt_config: no msg frames!\n", ioc->name)); 64028c2ecf20Sopenharmony_ci ret = -EAGAIN; 64038c2ecf20Sopenharmony_ci goto out; 64048c2ecf20Sopenharmony_ci } 64058c2ecf20Sopenharmony_ci 64068c2ecf20Sopenharmony_ci pReq = (Config_t *)mf; 64078c2ecf20Sopenharmony_ci pReq->Action = pCfg->action; 64088c2ecf20Sopenharmony_ci pReq->Reserved = 0; 64098c2ecf20Sopenharmony_ci pReq->ChainOffset = 0; 64108c2ecf20Sopenharmony_ci pReq->Function = MPI_FUNCTION_CONFIG; 64118c2ecf20Sopenharmony_ci 64128c2ecf20Sopenharmony_ci /* Assume page type is not extended and clear "reserved" fields. */ 64138c2ecf20Sopenharmony_ci pReq->ExtPageLength = 0; 64148c2ecf20Sopenharmony_ci pReq->ExtPageType = 0; 64158c2ecf20Sopenharmony_ci pReq->MsgFlags = 0; 64168c2ecf20Sopenharmony_ci 64178c2ecf20Sopenharmony_ci for (ii=0; ii < 8; ii++) 64188c2ecf20Sopenharmony_ci pReq->Reserved2[ii] = 0; 64198c2ecf20Sopenharmony_ci 64208c2ecf20Sopenharmony_ci pReq->Header.PageVersion = pCfg->cfghdr.hdr->PageVersion; 64218c2ecf20Sopenharmony_ci pReq->Header.PageLength = pCfg->cfghdr.hdr->PageLength; 64228c2ecf20Sopenharmony_ci pReq->Header.PageNumber = pCfg->cfghdr.hdr->PageNumber; 64238c2ecf20Sopenharmony_ci pReq->Header.PageType = (pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); 64248c2ecf20Sopenharmony_ci 64258c2ecf20Sopenharmony_ci if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == MPI_CONFIG_PAGETYPE_EXTENDED) { 64268c2ecf20Sopenharmony_ci pExtHdr = (ConfigExtendedPageHeader_t *)pCfg->cfghdr.ehdr; 64278c2ecf20Sopenharmony_ci pReq->ExtPageLength = cpu_to_le16(pExtHdr->ExtPageLength); 64288c2ecf20Sopenharmony_ci pReq->ExtPageType = pExtHdr->ExtPageType; 64298c2ecf20Sopenharmony_ci pReq->Header.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; 64308c2ecf20Sopenharmony_ci 64318c2ecf20Sopenharmony_ci /* Page Length must be treated as a reserved field for the 64328c2ecf20Sopenharmony_ci * extended header. 64338c2ecf20Sopenharmony_ci */ 64348c2ecf20Sopenharmony_ci pReq->Header.PageLength = 0; 64358c2ecf20Sopenharmony_ci } 64368c2ecf20Sopenharmony_ci 64378c2ecf20Sopenharmony_ci pReq->PageAddress = cpu_to_le32(pCfg->pageAddr); 64388c2ecf20Sopenharmony_ci 64398c2ecf20Sopenharmony_ci /* Add a SGE to the config request. 64408c2ecf20Sopenharmony_ci */ 64418c2ecf20Sopenharmony_ci if (pCfg->dir) 64428c2ecf20Sopenharmony_ci flagsLength = MPT_SGE_FLAGS_SSIMPLE_WRITE; 64438c2ecf20Sopenharmony_ci else 64448c2ecf20Sopenharmony_ci flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; 64458c2ecf20Sopenharmony_ci 64468c2ecf20Sopenharmony_ci if ((pCfg->cfghdr.hdr->PageType & MPI_CONFIG_PAGETYPE_MASK) == 64478c2ecf20Sopenharmony_ci MPI_CONFIG_PAGETYPE_EXTENDED) { 64488c2ecf20Sopenharmony_ci flagsLength |= pExtHdr->ExtPageLength * 4; 64498c2ecf20Sopenharmony_ci page_type = pReq->ExtPageType; 64508c2ecf20Sopenharmony_ci extend_page = 1; 64518c2ecf20Sopenharmony_ci } else { 64528c2ecf20Sopenharmony_ci flagsLength |= pCfg->cfghdr.hdr->PageLength * 4; 64538c2ecf20Sopenharmony_ci page_type = pReq->Header.PageType; 64548c2ecf20Sopenharmony_ci extend_page = 0; 64558c2ecf20Sopenharmony_ci } 64568c2ecf20Sopenharmony_ci 64578c2ecf20Sopenharmony_ci dcprintk(ioc, printk(MYIOC_s_DEBUG_FMT 64588c2ecf20Sopenharmony_ci "Sending Config request type 0x%x, page 0x%x and action %d\n", 64598c2ecf20Sopenharmony_ci ioc->name, page_type, pReq->Header.PageNumber, pReq->Action)); 64608c2ecf20Sopenharmony_ci 64618c2ecf20Sopenharmony_ci ioc->add_sge((char *)&pReq->PageBufferSGE, flagsLength, pCfg->physAddr); 64628c2ecf20Sopenharmony_ci timeout = (pCfg->timeout < 15) ? HZ*15 : HZ*pCfg->timeout; 64638c2ecf20Sopenharmony_ci mpt_put_msg_frame(mpt_base_index, ioc, mf); 64648c2ecf20Sopenharmony_ci timeleft = wait_for_completion_timeout(&ioc->mptbase_cmds.done, 64658c2ecf20Sopenharmony_ci timeout); 64668c2ecf20Sopenharmony_ci if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { 64678c2ecf20Sopenharmony_ci ret = -ETIME; 64688c2ecf20Sopenharmony_ci dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT 64698c2ecf20Sopenharmony_ci "Failed Sending Config request type 0x%x, page 0x%x," 64708c2ecf20Sopenharmony_ci " action %d, status %xh, time left %ld\n\n", 64718c2ecf20Sopenharmony_ci ioc->name, page_type, pReq->Header.PageNumber, 64728c2ecf20Sopenharmony_ci pReq->Action, ioc->mptbase_cmds.status, timeleft)); 64738c2ecf20Sopenharmony_ci if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) 64748c2ecf20Sopenharmony_ci goto out; 64758c2ecf20Sopenharmony_ci if (!timeleft) { 64768c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 64778c2ecf20Sopenharmony_ci if (ioc->ioc_reset_in_progress) { 64788c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, 64798c2ecf20Sopenharmony_ci flags); 64808c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "%s: host reset in" 64818c2ecf20Sopenharmony_ci " progress mpt_config timed out.!!\n", 64828c2ecf20Sopenharmony_ci __func__, ioc->name); 64838c2ecf20Sopenharmony_ci mutex_unlock(&ioc->mptbase_cmds.mutex); 64848c2ecf20Sopenharmony_ci return -EFAULT; 64858c2ecf20Sopenharmony_ci } 64868c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 64878c2ecf20Sopenharmony_ci issue_hard_reset = 1; 64888c2ecf20Sopenharmony_ci } 64898c2ecf20Sopenharmony_ci goto out; 64908c2ecf20Sopenharmony_ci } 64918c2ecf20Sopenharmony_ci 64928c2ecf20Sopenharmony_ci if (!(ioc->mptbase_cmds.status & MPT_MGMT_STATUS_RF_VALID)) { 64938c2ecf20Sopenharmony_ci ret = -1; 64948c2ecf20Sopenharmony_ci goto out; 64958c2ecf20Sopenharmony_ci } 64968c2ecf20Sopenharmony_ci pReply = (ConfigReply_t *)ioc->mptbase_cmds.reply; 64978c2ecf20Sopenharmony_ci ret = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; 64988c2ecf20Sopenharmony_ci if (ret == MPI_IOCSTATUS_SUCCESS) { 64998c2ecf20Sopenharmony_ci if (extend_page) { 65008c2ecf20Sopenharmony_ci pCfg->cfghdr.ehdr->ExtPageLength = 65018c2ecf20Sopenharmony_ci le16_to_cpu(pReply->ExtPageLength); 65028c2ecf20Sopenharmony_ci pCfg->cfghdr.ehdr->ExtPageType = 65038c2ecf20Sopenharmony_ci pReply->ExtPageType; 65048c2ecf20Sopenharmony_ci } 65058c2ecf20Sopenharmony_ci pCfg->cfghdr.hdr->PageVersion = pReply->Header.PageVersion; 65068c2ecf20Sopenharmony_ci pCfg->cfghdr.hdr->PageLength = pReply->Header.PageLength; 65078c2ecf20Sopenharmony_ci pCfg->cfghdr.hdr->PageNumber = pReply->Header.PageNumber; 65088c2ecf20Sopenharmony_ci pCfg->cfghdr.hdr->PageType = pReply->Header.PageType; 65098c2ecf20Sopenharmony_ci 65108c2ecf20Sopenharmony_ci } 65118c2ecf20Sopenharmony_ci 65128c2ecf20Sopenharmony_ci if (retry_count) 65138c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "Retry completed " 65148c2ecf20Sopenharmony_ci "ret=0x%x timeleft=%ld\n", 65158c2ecf20Sopenharmony_ci ioc->name, ret, timeleft); 65168c2ecf20Sopenharmony_ci 65178c2ecf20Sopenharmony_ci dcprintk(ioc, printk(KERN_DEBUG "IOCStatus=%04xh, IOCLogInfo=%08xh\n", 65188c2ecf20Sopenharmony_ci ret, le32_to_cpu(pReply->IOCLogInfo))); 65198c2ecf20Sopenharmony_ci 65208c2ecf20Sopenharmony_ciout: 65218c2ecf20Sopenharmony_ci 65228c2ecf20Sopenharmony_ci CLEAR_MGMT_STATUS(ioc->mptbase_cmds.status) 65238c2ecf20Sopenharmony_ci mutex_unlock(&ioc->mptbase_cmds.mutex); 65248c2ecf20Sopenharmony_ci if (issue_hard_reset) { 65258c2ecf20Sopenharmony_ci issue_hard_reset = 0; 65268c2ecf20Sopenharmony_ci printk(MYIOC_s_WARN_FMT 65278c2ecf20Sopenharmony_ci "Issuing Reset from %s!!, doorbell=0x%08x\n", 65288c2ecf20Sopenharmony_ci ioc->name, __func__, mpt_GetIocState(ioc, 0)); 65298c2ecf20Sopenharmony_ci if (retry_count == 0) { 65308c2ecf20Sopenharmony_ci if (mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP) != 0) 65318c2ecf20Sopenharmony_ci retry_count++; 65328c2ecf20Sopenharmony_ci } else 65338c2ecf20Sopenharmony_ci mpt_HardResetHandler(ioc, CAN_SLEEP); 65348c2ecf20Sopenharmony_ci 65358c2ecf20Sopenharmony_ci mpt_free_msg_frame(ioc, mf); 65368c2ecf20Sopenharmony_ci /* attempt one retry for a timed out command */ 65378c2ecf20Sopenharmony_ci if (retry_count < 2) { 65388c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT 65398c2ecf20Sopenharmony_ci "Attempting Retry Config request" 65408c2ecf20Sopenharmony_ci " type 0x%x, page 0x%x," 65418c2ecf20Sopenharmony_ci " action %d\n", ioc->name, page_type, 65428c2ecf20Sopenharmony_ci pCfg->cfghdr.hdr->PageNumber, pCfg->action); 65438c2ecf20Sopenharmony_ci retry_count++; 65448c2ecf20Sopenharmony_ci goto retry_config; 65458c2ecf20Sopenharmony_ci } 65468c2ecf20Sopenharmony_ci } 65478c2ecf20Sopenharmony_ci return ret; 65488c2ecf20Sopenharmony_ci 65498c2ecf20Sopenharmony_ci} 65508c2ecf20Sopenharmony_ci 65518c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 65528c2ecf20Sopenharmony_ci/** 65538c2ecf20Sopenharmony_ci * mpt_ioc_reset - Base cleanup for hard reset 65548c2ecf20Sopenharmony_ci * @ioc: Pointer to the adapter structure 65558c2ecf20Sopenharmony_ci * @reset_phase: Indicates pre- or post-reset functionality 65568c2ecf20Sopenharmony_ci * 65578c2ecf20Sopenharmony_ci * Remark: Frees resources with internally generated commands. 65588c2ecf20Sopenharmony_ci */ 65598c2ecf20Sopenharmony_cistatic int 65608c2ecf20Sopenharmony_cimpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) 65618c2ecf20Sopenharmony_ci{ 65628c2ecf20Sopenharmony_ci switch (reset_phase) { 65638c2ecf20Sopenharmony_ci case MPT_IOC_SETUP_RESET: 65648c2ecf20Sopenharmony_ci ioc->taskmgmt_quiesce_io = 1; 65658c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 65668c2ecf20Sopenharmony_ci "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); 65678c2ecf20Sopenharmony_ci break; 65688c2ecf20Sopenharmony_ci case MPT_IOC_PRE_RESET: 65698c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 65708c2ecf20Sopenharmony_ci "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); 65718c2ecf20Sopenharmony_ci break; 65728c2ecf20Sopenharmony_ci case MPT_IOC_POST_RESET: 65738c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 65748c2ecf20Sopenharmony_ci "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); 65758c2ecf20Sopenharmony_ci/* wake up mptbase_cmds */ 65768c2ecf20Sopenharmony_ci if (ioc->mptbase_cmds.status & MPT_MGMT_STATUS_PENDING) { 65778c2ecf20Sopenharmony_ci ioc->mptbase_cmds.status |= 65788c2ecf20Sopenharmony_ci MPT_MGMT_STATUS_DID_IOCRESET; 65798c2ecf20Sopenharmony_ci complete(&ioc->mptbase_cmds.done); 65808c2ecf20Sopenharmony_ci } 65818c2ecf20Sopenharmony_ci/* wake up taskmgmt_cmds */ 65828c2ecf20Sopenharmony_ci if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) { 65838c2ecf20Sopenharmony_ci ioc->taskmgmt_cmds.status |= 65848c2ecf20Sopenharmony_ci MPT_MGMT_STATUS_DID_IOCRESET; 65858c2ecf20Sopenharmony_ci complete(&ioc->taskmgmt_cmds.done); 65868c2ecf20Sopenharmony_ci } 65878c2ecf20Sopenharmony_ci break; 65888c2ecf20Sopenharmony_ci default: 65898c2ecf20Sopenharmony_ci break; 65908c2ecf20Sopenharmony_ci } 65918c2ecf20Sopenharmony_ci 65928c2ecf20Sopenharmony_ci return 1; /* currently means nothing really */ 65938c2ecf20Sopenharmony_ci} 65948c2ecf20Sopenharmony_ci 65958c2ecf20Sopenharmony_ci 65968c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS /* { */ 65978c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 65988c2ecf20Sopenharmony_ci/* 65998c2ecf20Sopenharmony_ci * procfs (%MPT_PROCFS_MPTBASEDIR/...) support stuff... 66008c2ecf20Sopenharmony_ci */ 66018c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 66028c2ecf20Sopenharmony_ci/** 66038c2ecf20Sopenharmony_ci * procmpt_create - Create %MPT_PROCFS_MPTBASEDIR entries. 66048c2ecf20Sopenharmony_ci * 66058c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 66068c2ecf20Sopenharmony_ci */ 66078c2ecf20Sopenharmony_cistatic int 66088c2ecf20Sopenharmony_ciprocmpt_create(void) 66098c2ecf20Sopenharmony_ci{ 66108c2ecf20Sopenharmony_ci mpt_proc_root_dir = proc_mkdir(MPT_PROCFS_MPTBASEDIR, NULL); 66118c2ecf20Sopenharmony_ci if (mpt_proc_root_dir == NULL) 66128c2ecf20Sopenharmony_ci return -ENOTDIR; 66138c2ecf20Sopenharmony_ci 66148c2ecf20Sopenharmony_ci proc_create_single("summary", S_IRUGO, mpt_proc_root_dir, 66158c2ecf20Sopenharmony_ci mpt_summary_proc_show); 66168c2ecf20Sopenharmony_ci proc_create_single("version", S_IRUGO, mpt_proc_root_dir, 66178c2ecf20Sopenharmony_ci mpt_version_proc_show); 66188c2ecf20Sopenharmony_ci return 0; 66198c2ecf20Sopenharmony_ci} 66208c2ecf20Sopenharmony_ci 66218c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 66228c2ecf20Sopenharmony_ci/** 66238c2ecf20Sopenharmony_ci * procmpt_destroy - Tear down %MPT_PROCFS_MPTBASEDIR entries. 66248c2ecf20Sopenharmony_ci * 66258c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 66268c2ecf20Sopenharmony_ci */ 66278c2ecf20Sopenharmony_cistatic void 66288c2ecf20Sopenharmony_ciprocmpt_destroy(void) 66298c2ecf20Sopenharmony_ci{ 66308c2ecf20Sopenharmony_ci remove_proc_entry("version", mpt_proc_root_dir); 66318c2ecf20Sopenharmony_ci remove_proc_entry("summary", mpt_proc_root_dir); 66328c2ecf20Sopenharmony_ci remove_proc_entry(MPT_PROCFS_MPTBASEDIR, NULL); 66338c2ecf20Sopenharmony_ci} 66348c2ecf20Sopenharmony_ci 66358c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 66368c2ecf20Sopenharmony_ci/* 66378c2ecf20Sopenharmony_ci * Handles read request from /proc/mpt/summary or /proc/mpt/iocN/summary. 66388c2ecf20Sopenharmony_ci */ 66398c2ecf20Sopenharmony_cistatic void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan); 66408c2ecf20Sopenharmony_ci 66418c2ecf20Sopenharmony_cistatic int mpt_summary_proc_show(struct seq_file *m, void *v) 66428c2ecf20Sopenharmony_ci{ 66438c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = m->private; 66448c2ecf20Sopenharmony_ci 66458c2ecf20Sopenharmony_ci if (ioc) { 66468c2ecf20Sopenharmony_ci seq_mpt_print_ioc_summary(ioc, m, 1); 66478c2ecf20Sopenharmony_ci } else { 66488c2ecf20Sopenharmony_ci list_for_each_entry(ioc, &ioc_list, list) { 66498c2ecf20Sopenharmony_ci seq_mpt_print_ioc_summary(ioc, m, 1); 66508c2ecf20Sopenharmony_ci } 66518c2ecf20Sopenharmony_ci } 66528c2ecf20Sopenharmony_ci 66538c2ecf20Sopenharmony_ci return 0; 66548c2ecf20Sopenharmony_ci} 66558c2ecf20Sopenharmony_ci 66568c2ecf20Sopenharmony_cistatic int mpt_version_proc_show(struct seq_file *m, void *v) 66578c2ecf20Sopenharmony_ci{ 66588c2ecf20Sopenharmony_ci u8 cb_idx; 66598c2ecf20Sopenharmony_ci int scsi, fc, sas, lan, ctl, targ, dmp; 66608c2ecf20Sopenharmony_ci char *drvname; 66618c2ecf20Sopenharmony_ci 66628c2ecf20Sopenharmony_ci seq_printf(m, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON); 66638c2ecf20Sopenharmony_ci seq_printf(m, " Fusion MPT base driver\n"); 66648c2ecf20Sopenharmony_ci 66658c2ecf20Sopenharmony_ci scsi = fc = sas = lan = ctl = targ = dmp = 0; 66668c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 66678c2ecf20Sopenharmony_ci drvname = NULL; 66688c2ecf20Sopenharmony_ci if (MptCallbacks[cb_idx]) { 66698c2ecf20Sopenharmony_ci switch (MptDriverClass[cb_idx]) { 66708c2ecf20Sopenharmony_ci case MPTSPI_DRIVER: 66718c2ecf20Sopenharmony_ci if (!scsi++) drvname = "SPI host"; 66728c2ecf20Sopenharmony_ci break; 66738c2ecf20Sopenharmony_ci case MPTFC_DRIVER: 66748c2ecf20Sopenharmony_ci if (!fc++) drvname = "FC host"; 66758c2ecf20Sopenharmony_ci break; 66768c2ecf20Sopenharmony_ci case MPTSAS_DRIVER: 66778c2ecf20Sopenharmony_ci if (!sas++) drvname = "SAS host"; 66788c2ecf20Sopenharmony_ci break; 66798c2ecf20Sopenharmony_ci case MPTLAN_DRIVER: 66808c2ecf20Sopenharmony_ci if (!lan++) drvname = "LAN"; 66818c2ecf20Sopenharmony_ci break; 66828c2ecf20Sopenharmony_ci case MPTSTM_DRIVER: 66838c2ecf20Sopenharmony_ci if (!targ++) drvname = "SCSI target"; 66848c2ecf20Sopenharmony_ci break; 66858c2ecf20Sopenharmony_ci case MPTCTL_DRIVER: 66868c2ecf20Sopenharmony_ci if (!ctl++) drvname = "ioctl"; 66878c2ecf20Sopenharmony_ci break; 66888c2ecf20Sopenharmony_ci } 66898c2ecf20Sopenharmony_ci 66908c2ecf20Sopenharmony_ci if (drvname) 66918c2ecf20Sopenharmony_ci seq_printf(m, " Fusion MPT %s driver\n", drvname); 66928c2ecf20Sopenharmony_ci } 66938c2ecf20Sopenharmony_ci } 66948c2ecf20Sopenharmony_ci 66958c2ecf20Sopenharmony_ci return 0; 66968c2ecf20Sopenharmony_ci} 66978c2ecf20Sopenharmony_ci 66988c2ecf20Sopenharmony_cistatic int mpt_iocinfo_proc_show(struct seq_file *m, void *v) 66998c2ecf20Sopenharmony_ci{ 67008c2ecf20Sopenharmony_ci MPT_ADAPTER *ioc = m->private; 67018c2ecf20Sopenharmony_ci char expVer[32]; 67028c2ecf20Sopenharmony_ci int sz; 67038c2ecf20Sopenharmony_ci int p; 67048c2ecf20Sopenharmony_ci 67058c2ecf20Sopenharmony_ci mpt_get_fw_exp_ver(expVer, ioc); 67068c2ecf20Sopenharmony_ci 67078c2ecf20Sopenharmony_ci seq_printf(m, "%s:", ioc->name); 67088c2ecf20Sopenharmony_ci if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) 67098c2ecf20Sopenharmony_ci seq_printf(m, " (f/w download boot flag set)"); 67108c2ecf20Sopenharmony_ci// if (ioc->facts.IOCExceptions & MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL) 67118c2ecf20Sopenharmony_ci// seq_printf(m, " CONFIG_CHECKSUM_FAIL!"); 67128c2ecf20Sopenharmony_ci 67138c2ecf20Sopenharmony_ci seq_printf(m, "\n ProductID = 0x%04x (%s)\n", 67148c2ecf20Sopenharmony_ci ioc->facts.ProductID, 67158c2ecf20Sopenharmony_ci ioc->prod_name); 67168c2ecf20Sopenharmony_ci seq_printf(m, " FWVersion = 0x%08x%s", ioc->facts.FWVersion.Word, expVer); 67178c2ecf20Sopenharmony_ci if (ioc->facts.FWImageSize) 67188c2ecf20Sopenharmony_ci seq_printf(m, " (fw_size=%d)", ioc->facts.FWImageSize); 67198c2ecf20Sopenharmony_ci seq_printf(m, "\n MsgVersion = 0x%04x\n", ioc->facts.MsgVersion); 67208c2ecf20Sopenharmony_ci seq_printf(m, " FirstWhoInit = 0x%02x\n", ioc->FirstWhoInit); 67218c2ecf20Sopenharmony_ci seq_printf(m, " EventState = 0x%02x\n", ioc->facts.EventState); 67228c2ecf20Sopenharmony_ci 67238c2ecf20Sopenharmony_ci seq_printf(m, " CurrentHostMfaHighAddr = 0x%08x\n", 67248c2ecf20Sopenharmony_ci ioc->facts.CurrentHostMfaHighAddr); 67258c2ecf20Sopenharmony_ci seq_printf(m, " CurrentSenseBufferHighAddr = 0x%08x\n", 67268c2ecf20Sopenharmony_ci ioc->facts.CurrentSenseBufferHighAddr); 67278c2ecf20Sopenharmony_ci 67288c2ecf20Sopenharmony_ci seq_printf(m, " MaxChainDepth = 0x%02x frames\n", ioc->facts.MaxChainDepth); 67298c2ecf20Sopenharmony_ci seq_printf(m, " MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize); 67308c2ecf20Sopenharmony_ci 67318c2ecf20Sopenharmony_ci seq_printf(m, " RequestFrames @ 0x%p (Dma @ 0x%p)\n", 67328c2ecf20Sopenharmony_ci (void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma); 67338c2ecf20Sopenharmony_ci /* 67348c2ecf20Sopenharmony_ci * Rounding UP to nearest 4-kB boundary here... 67358c2ecf20Sopenharmony_ci */ 67368c2ecf20Sopenharmony_ci sz = (ioc->req_sz * ioc->req_depth) + 128; 67378c2ecf20Sopenharmony_ci sz = ((sz + 0x1000UL - 1UL) / 0x1000) * 0x1000; 67388c2ecf20Sopenharmony_ci seq_printf(m, " {CurReqSz=%d} x {CurReqDepth=%d} = %d bytes ^= 0x%x\n", 67398c2ecf20Sopenharmony_ci ioc->req_sz, ioc->req_depth, ioc->req_sz*ioc->req_depth, sz); 67408c2ecf20Sopenharmony_ci seq_printf(m, " {MaxReqSz=%d} {MaxReqDepth=%d}\n", 67418c2ecf20Sopenharmony_ci 4*ioc->facts.RequestFrameSize, 67428c2ecf20Sopenharmony_ci ioc->facts.GlobalCredits); 67438c2ecf20Sopenharmony_ci 67448c2ecf20Sopenharmony_ci seq_printf(m, " Frames @ 0x%p (Dma @ 0x%p)\n", 67458c2ecf20Sopenharmony_ci (void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma); 67468c2ecf20Sopenharmony_ci sz = (ioc->reply_sz * ioc->reply_depth) + 128; 67478c2ecf20Sopenharmony_ci seq_printf(m, " {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n", 67488c2ecf20Sopenharmony_ci ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz); 67498c2ecf20Sopenharmony_ci seq_printf(m, " {MaxRepSz=%d} {MaxRepDepth=%d}\n", 67508c2ecf20Sopenharmony_ci ioc->facts.CurReplyFrameSize, 67518c2ecf20Sopenharmony_ci ioc->facts.ReplyQueueDepth); 67528c2ecf20Sopenharmony_ci 67538c2ecf20Sopenharmony_ci seq_printf(m, " MaxDevices = %d\n", 67548c2ecf20Sopenharmony_ci (ioc->facts.MaxDevices==0) ? 255 : ioc->facts.MaxDevices); 67558c2ecf20Sopenharmony_ci seq_printf(m, " MaxBuses = %d\n", ioc->facts.MaxBuses); 67568c2ecf20Sopenharmony_ci 67578c2ecf20Sopenharmony_ci /* per-port info */ 67588c2ecf20Sopenharmony_ci for (p=0; p < ioc->facts.NumberOfPorts; p++) { 67598c2ecf20Sopenharmony_ci seq_printf(m, " PortNumber = %d (of %d)\n", 67608c2ecf20Sopenharmony_ci p+1, 67618c2ecf20Sopenharmony_ci ioc->facts.NumberOfPorts); 67628c2ecf20Sopenharmony_ci if (ioc->bus_type == FC) { 67638c2ecf20Sopenharmony_ci if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { 67648c2ecf20Sopenharmony_ci u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; 67658c2ecf20Sopenharmony_ci seq_printf(m, " LanAddr = %pMR\n", a); 67668c2ecf20Sopenharmony_ci } 67678c2ecf20Sopenharmony_ci seq_printf(m, " WWN = %08X%08X:%08X%08X\n", 67688c2ecf20Sopenharmony_ci ioc->fc_port_page0[p].WWNN.High, 67698c2ecf20Sopenharmony_ci ioc->fc_port_page0[p].WWNN.Low, 67708c2ecf20Sopenharmony_ci ioc->fc_port_page0[p].WWPN.High, 67718c2ecf20Sopenharmony_ci ioc->fc_port_page0[p].WWPN.Low); 67728c2ecf20Sopenharmony_ci } 67738c2ecf20Sopenharmony_ci } 67748c2ecf20Sopenharmony_ci 67758c2ecf20Sopenharmony_ci return 0; 67768c2ecf20Sopenharmony_ci} 67778c2ecf20Sopenharmony_ci#endif /* CONFIG_PROC_FS } */ 67788c2ecf20Sopenharmony_ci 67798c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 67808c2ecf20Sopenharmony_cistatic void 67818c2ecf20Sopenharmony_cimpt_get_fw_exp_ver(char *buf, MPT_ADAPTER *ioc) 67828c2ecf20Sopenharmony_ci{ 67838c2ecf20Sopenharmony_ci buf[0] ='\0'; 67848c2ecf20Sopenharmony_ci if ((ioc->facts.FWVersion.Word >> 24) == 0x0E) { 67858c2ecf20Sopenharmony_ci sprintf(buf, " (Exp %02d%02d)", 67868c2ecf20Sopenharmony_ci (ioc->facts.FWVersion.Word >> 16) & 0x00FF, /* Month */ 67878c2ecf20Sopenharmony_ci (ioc->facts.FWVersion.Word >> 8) & 0x1F); /* Day */ 67888c2ecf20Sopenharmony_ci 67898c2ecf20Sopenharmony_ci /* insider hack! */ 67908c2ecf20Sopenharmony_ci if ((ioc->facts.FWVersion.Word >> 8) & 0x80) 67918c2ecf20Sopenharmony_ci strcat(buf, " [MDBG]"); 67928c2ecf20Sopenharmony_ci } 67938c2ecf20Sopenharmony_ci} 67948c2ecf20Sopenharmony_ci 67958c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 67968c2ecf20Sopenharmony_ci/** 67978c2ecf20Sopenharmony_ci * mpt_print_ioc_summary - Write ASCII summary of IOC to a buffer. 67988c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 67998c2ecf20Sopenharmony_ci * @buffer: Pointer to buffer where IOC summary info should be written 68008c2ecf20Sopenharmony_ci * @size: Pointer to number of bytes we wrote (set by this routine) 68018c2ecf20Sopenharmony_ci * @len: Offset at which to start writing in buffer 68028c2ecf20Sopenharmony_ci * @showlan: Display LAN stuff? 68038c2ecf20Sopenharmony_ci * 68048c2ecf20Sopenharmony_ci * This routine writes (english readable) ASCII text, which represents 68058c2ecf20Sopenharmony_ci * a summary of IOC information, to a buffer. 68068c2ecf20Sopenharmony_ci */ 68078c2ecf20Sopenharmony_civoid 68088c2ecf20Sopenharmony_cimpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buffer, int *size, int len, int showlan) 68098c2ecf20Sopenharmony_ci{ 68108c2ecf20Sopenharmony_ci char expVer[32]; 68118c2ecf20Sopenharmony_ci int y; 68128c2ecf20Sopenharmony_ci 68138c2ecf20Sopenharmony_ci mpt_get_fw_exp_ver(expVer, ioc); 68148c2ecf20Sopenharmony_ci 68158c2ecf20Sopenharmony_ci /* 68168c2ecf20Sopenharmony_ci * Shorter summary of attached ioc's... 68178c2ecf20Sopenharmony_ci */ 68188c2ecf20Sopenharmony_ci y = sprintf(buffer+len, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d", 68198c2ecf20Sopenharmony_ci ioc->name, 68208c2ecf20Sopenharmony_ci ioc->prod_name, 68218c2ecf20Sopenharmony_ci MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */ 68228c2ecf20Sopenharmony_ci ioc->facts.FWVersion.Word, 68238c2ecf20Sopenharmony_ci expVer, 68248c2ecf20Sopenharmony_ci ioc->facts.NumberOfPorts, 68258c2ecf20Sopenharmony_ci ioc->req_depth); 68268c2ecf20Sopenharmony_ci 68278c2ecf20Sopenharmony_ci if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { 68288c2ecf20Sopenharmony_ci u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; 68298c2ecf20Sopenharmony_ci y += sprintf(buffer+len+y, ", LanAddr=%pMR", a); 68308c2ecf20Sopenharmony_ci } 68318c2ecf20Sopenharmony_ci 68328c2ecf20Sopenharmony_ci y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq); 68338c2ecf20Sopenharmony_ci 68348c2ecf20Sopenharmony_ci if (!ioc->active) 68358c2ecf20Sopenharmony_ci y += sprintf(buffer+len+y, " (disabled)"); 68368c2ecf20Sopenharmony_ci 68378c2ecf20Sopenharmony_ci y += sprintf(buffer+len+y, "\n"); 68388c2ecf20Sopenharmony_ci 68398c2ecf20Sopenharmony_ci *size = y; 68408c2ecf20Sopenharmony_ci} 68418c2ecf20Sopenharmony_ci 68428c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 68438c2ecf20Sopenharmony_cistatic void seq_mpt_print_ioc_summary(MPT_ADAPTER *ioc, struct seq_file *m, int showlan) 68448c2ecf20Sopenharmony_ci{ 68458c2ecf20Sopenharmony_ci char expVer[32]; 68468c2ecf20Sopenharmony_ci 68478c2ecf20Sopenharmony_ci mpt_get_fw_exp_ver(expVer, ioc); 68488c2ecf20Sopenharmony_ci 68498c2ecf20Sopenharmony_ci /* 68508c2ecf20Sopenharmony_ci * Shorter summary of attached ioc's... 68518c2ecf20Sopenharmony_ci */ 68528c2ecf20Sopenharmony_ci seq_printf(m, "%s: %s, %s%08xh%s, Ports=%d, MaxQ=%d", 68538c2ecf20Sopenharmony_ci ioc->name, 68548c2ecf20Sopenharmony_ci ioc->prod_name, 68558c2ecf20Sopenharmony_ci MPT_FW_REV_MAGIC_ID_STRING, /* "FwRev=" or somesuch */ 68568c2ecf20Sopenharmony_ci ioc->facts.FWVersion.Word, 68578c2ecf20Sopenharmony_ci expVer, 68588c2ecf20Sopenharmony_ci ioc->facts.NumberOfPorts, 68598c2ecf20Sopenharmony_ci ioc->req_depth); 68608c2ecf20Sopenharmony_ci 68618c2ecf20Sopenharmony_ci if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { 68628c2ecf20Sopenharmony_ci u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; 68638c2ecf20Sopenharmony_ci seq_printf(m, ", LanAddr=%pMR", a); 68648c2ecf20Sopenharmony_ci } 68658c2ecf20Sopenharmony_ci 68668c2ecf20Sopenharmony_ci seq_printf(m, ", IRQ=%d", ioc->pci_irq); 68678c2ecf20Sopenharmony_ci 68688c2ecf20Sopenharmony_ci if (!ioc->active) 68698c2ecf20Sopenharmony_ci seq_printf(m, " (disabled)"); 68708c2ecf20Sopenharmony_ci 68718c2ecf20Sopenharmony_ci seq_putc(m, '\n'); 68728c2ecf20Sopenharmony_ci} 68738c2ecf20Sopenharmony_ci#endif 68748c2ecf20Sopenharmony_ci 68758c2ecf20Sopenharmony_ci/** 68768c2ecf20Sopenharmony_ci * mpt_set_taskmgmt_in_progress_flag - set flags associated with task management 68778c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 68788c2ecf20Sopenharmony_ci * 68798c2ecf20Sopenharmony_ci * Returns 0 for SUCCESS or -1 if FAILED. 68808c2ecf20Sopenharmony_ci * 68818c2ecf20Sopenharmony_ci * If -1 is return, then it was not possible to set the flags 68828c2ecf20Sopenharmony_ci **/ 68838c2ecf20Sopenharmony_ciint 68848c2ecf20Sopenharmony_cimpt_set_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) 68858c2ecf20Sopenharmony_ci{ 68868c2ecf20Sopenharmony_ci unsigned long flags; 68878c2ecf20Sopenharmony_ci int retval; 68888c2ecf20Sopenharmony_ci 68898c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 68908c2ecf20Sopenharmony_ci if (ioc->ioc_reset_in_progress || ioc->taskmgmt_in_progress || 68918c2ecf20Sopenharmony_ci (ioc->alt_ioc && ioc->alt_ioc->taskmgmt_in_progress)) { 68928c2ecf20Sopenharmony_ci retval = -1; 68938c2ecf20Sopenharmony_ci goto out; 68948c2ecf20Sopenharmony_ci } 68958c2ecf20Sopenharmony_ci retval = 0; 68968c2ecf20Sopenharmony_ci ioc->taskmgmt_in_progress = 1; 68978c2ecf20Sopenharmony_ci ioc->taskmgmt_quiesce_io = 1; 68988c2ecf20Sopenharmony_ci if (ioc->alt_ioc) { 68998c2ecf20Sopenharmony_ci ioc->alt_ioc->taskmgmt_in_progress = 1; 69008c2ecf20Sopenharmony_ci ioc->alt_ioc->taskmgmt_quiesce_io = 1; 69018c2ecf20Sopenharmony_ci } 69028c2ecf20Sopenharmony_ci out: 69038c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 69048c2ecf20Sopenharmony_ci return retval; 69058c2ecf20Sopenharmony_ci} 69068c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_set_taskmgmt_in_progress_flag); 69078c2ecf20Sopenharmony_ci 69088c2ecf20Sopenharmony_ci/** 69098c2ecf20Sopenharmony_ci * mpt_clear_taskmgmt_in_progress_flag - clear flags associated with task management 69108c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 69118c2ecf20Sopenharmony_ci * 69128c2ecf20Sopenharmony_ci **/ 69138c2ecf20Sopenharmony_civoid 69148c2ecf20Sopenharmony_cimpt_clear_taskmgmt_in_progress_flag(MPT_ADAPTER *ioc) 69158c2ecf20Sopenharmony_ci{ 69168c2ecf20Sopenharmony_ci unsigned long flags; 69178c2ecf20Sopenharmony_ci 69188c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 69198c2ecf20Sopenharmony_ci ioc->taskmgmt_in_progress = 0; 69208c2ecf20Sopenharmony_ci ioc->taskmgmt_quiesce_io = 0; 69218c2ecf20Sopenharmony_ci if (ioc->alt_ioc) { 69228c2ecf20Sopenharmony_ci ioc->alt_ioc->taskmgmt_in_progress = 0; 69238c2ecf20Sopenharmony_ci ioc->alt_ioc->taskmgmt_quiesce_io = 0; 69248c2ecf20Sopenharmony_ci } 69258c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 69268c2ecf20Sopenharmony_ci} 69278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_clear_taskmgmt_in_progress_flag); 69288c2ecf20Sopenharmony_ci 69298c2ecf20Sopenharmony_ci 69308c2ecf20Sopenharmony_ci/** 69318c2ecf20Sopenharmony_ci * mpt_halt_firmware - Halts the firmware if it is operational and panic 69328c2ecf20Sopenharmony_ci * the kernel 69338c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 69348c2ecf20Sopenharmony_ci * 69358c2ecf20Sopenharmony_ci **/ 69368c2ecf20Sopenharmony_civoid 69378c2ecf20Sopenharmony_cimpt_halt_firmware(MPT_ADAPTER *ioc) 69388c2ecf20Sopenharmony_ci{ 69398c2ecf20Sopenharmony_ci u32 ioc_raw_state; 69408c2ecf20Sopenharmony_ci 69418c2ecf20Sopenharmony_ci ioc_raw_state = mpt_GetIocState(ioc, 0); 69428c2ecf20Sopenharmony_ci 69438c2ecf20Sopenharmony_ci if ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { 69448c2ecf20Sopenharmony_ci printk(MYIOC_s_ERR_FMT "IOC is in FAULT state (%04xh)!!!\n", 69458c2ecf20Sopenharmony_ci ioc->name, ioc_raw_state & MPI_DOORBELL_DATA_MASK); 69468c2ecf20Sopenharmony_ci panic("%s: IOC Fault (%04xh)!!!\n", ioc->name, 69478c2ecf20Sopenharmony_ci ioc_raw_state & MPI_DOORBELL_DATA_MASK); 69488c2ecf20Sopenharmony_ci } else { 69498c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->Doorbell, 0xC0FFEE00); 69508c2ecf20Sopenharmony_ci panic("%s: Firmware is halted due to command timeout\n", 69518c2ecf20Sopenharmony_ci ioc->name); 69528c2ecf20Sopenharmony_ci } 69538c2ecf20Sopenharmony_ci} 69548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_halt_firmware); 69558c2ecf20Sopenharmony_ci 69568c2ecf20Sopenharmony_ci/** 69578c2ecf20Sopenharmony_ci * mpt_SoftResetHandler - Issues a less expensive reset 69588c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 69598c2ecf20Sopenharmony_ci * @sleepFlag: Indicates if sleep or schedule must be called. 69608c2ecf20Sopenharmony_ci * 69618c2ecf20Sopenharmony_ci * Returns 0 for SUCCESS or -1 if FAILED. 69628c2ecf20Sopenharmony_ci * 69638c2ecf20Sopenharmony_ci * Message Unit Reset - instructs the IOC to reset the Reply Post and 69648c2ecf20Sopenharmony_ci * Free FIFO's. All the Message Frames on Reply Free FIFO are discarded. 69658c2ecf20Sopenharmony_ci * All posted buffers are freed, and event notification is turned off. 69668c2ecf20Sopenharmony_ci * IOC doesn't reply to any outstanding request. This will transfer IOC 69678c2ecf20Sopenharmony_ci * to READY state. 69688c2ecf20Sopenharmony_ci **/ 69698c2ecf20Sopenharmony_cistatic int 69708c2ecf20Sopenharmony_cimpt_SoftResetHandler(MPT_ADAPTER *ioc, int sleepFlag) 69718c2ecf20Sopenharmony_ci{ 69728c2ecf20Sopenharmony_ci int rc; 69738c2ecf20Sopenharmony_ci int ii; 69748c2ecf20Sopenharmony_ci u8 cb_idx; 69758c2ecf20Sopenharmony_ci unsigned long flags; 69768c2ecf20Sopenharmony_ci u32 ioc_state; 69778c2ecf20Sopenharmony_ci unsigned long time_count; 69788c2ecf20Sopenharmony_ci 69798c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SoftResetHandler Entered!\n", 69808c2ecf20Sopenharmony_ci ioc->name)); 69818c2ecf20Sopenharmony_ci 69828c2ecf20Sopenharmony_ci ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK; 69838c2ecf20Sopenharmony_ci 69848c2ecf20Sopenharmony_ci if (mpt_fwfault_debug) 69858c2ecf20Sopenharmony_ci mpt_halt_firmware(ioc); 69868c2ecf20Sopenharmony_ci 69878c2ecf20Sopenharmony_ci if (ioc_state == MPI_IOC_STATE_FAULT || 69888c2ecf20Sopenharmony_ci ioc_state == MPI_IOC_STATE_RESET) { 69898c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 69908c2ecf20Sopenharmony_ci "skipping, either in FAULT or RESET state!\n", ioc->name)); 69918c2ecf20Sopenharmony_ci return -1; 69928c2ecf20Sopenharmony_ci } 69938c2ecf20Sopenharmony_ci 69948c2ecf20Sopenharmony_ci if (ioc->bus_type == FC) { 69958c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 69968c2ecf20Sopenharmony_ci "skipping, because the bus type is FC!\n", ioc->name)); 69978c2ecf20Sopenharmony_ci return -1; 69988c2ecf20Sopenharmony_ci } 69998c2ecf20Sopenharmony_ci 70008c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 70018c2ecf20Sopenharmony_ci if (ioc->ioc_reset_in_progress) { 70028c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 70038c2ecf20Sopenharmony_ci return -1; 70048c2ecf20Sopenharmony_ci } 70058c2ecf20Sopenharmony_ci ioc->ioc_reset_in_progress = 1; 70068c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 70078c2ecf20Sopenharmony_ci 70088c2ecf20Sopenharmony_ci rc = -1; 70098c2ecf20Sopenharmony_ci 70108c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 70118c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) 70128c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); 70138c2ecf20Sopenharmony_ci } 70148c2ecf20Sopenharmony_ci 70158c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 70168c2ecf20Sopenharmony_ci if (ioc->taskmgmt_in_progress) { 70178c2ecf20Sopenharmony_ci ioc->ioc_reset_in_progress = 0; 70188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 70198c2ecf20Sopenharmony_ci return -1; 70208c2ecf20Sopenharmony_ci } 70218c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 70228c2ecf20Sopenharmony_ci /* Disable reply interrupts (also blocks FreeQ) */ 70238c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); 70248c2ecf20Sopenharmony_ci ioc->active = 0; 70258c2ecf20Sopenharmony_ci time_count = jiffies; 70268c2ecf20Sopenharmony_ci 70278c2ecf20Sopenharmony_ci rc = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); 70288c2ecf20Sopenharmony_ci 70298c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 70308c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) 70318c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET); 70328c2ecf20Sopenharmony_ci } 70338c2ecf20Sopenharmony_ci 70348c2ecf20Sopenharmony_ci if (rc) 70358c2ecf20Sopenharmony_ci goto out; 70368c2ecf20Sopenharmony_ci 70378c2ecf20Sopenharmony_ci ioc_state = mpt_GetIocState(ioc, 0) & MPI_IOC_STATE_MASK; 70388c2ecf20Sopenharmony_ci if (ioc_state != MPI_IOC_STATE_READY) 70398c2ecf20Sopenharmony_ci goto out; 70408c2ecf20Sopenharmony_ci 70418c2ecf20Sopenharmony_ci for (ii = 0; ii < 5; ii++) { 70428c2ecf20Sopenharmony_ci /* Get IOC facts! Allow 5 retries */ 70438c2ecf20Sopenharmony_ci rc = GetIocFacts(ioc, sleepFlag, 70448c2ecf20Sopenharmony_ci MPT_HOSTEVENT_IOC_RECOVER); 70458c2ecf20Sopenharmony_ci if (rc == 0) 70468c2ecf20Sopenharmony_ci break; 70478c2ecf20Sopenharmony_ci if (sleepFlag == CAN_SLEEP) 70488c2ecf20Sopenharmony_ci msleep(100); 70498c2ecf20Sopenharmony_ci else 70508c2ecf20Sopenharmony_ci mdelay(100); 70518c2ecf20Sopenharmony_ci } 70528c2ecf20Sopenharmony_ci if (ii == 5) 70538c2ecf20Sopenharmony_ci goto out; 70548c2ecf20Sopenharmony_ci 70558c2ecf20Sopenharmony_ci rc = PrimeIocFifos(ioc); 70568c2ecf20Sopenharmony_ci if (rc != 0) 70578c2ecf20Sopenharmony_ci goto out; 70588c2ecf20Sopenharmony_ci 70598c2ecf20Sopenharmony_ci rc = SendIocInit(ioc, sleepFlag); 70608c2ecf20Sopenharmony_ci if (rc != 0) 70618c2ecf20Sopenharmony_ci goto out; 70628c2ecf20Sopenharmony_ci 70638c2ecf20Sopenharmony_ci rc = SendEventNotification(ioc, 1, sleepFlag); 70648c2ecf20Sopenharmony_ci if (rc != 0) 70658c2ecf20Sopenharmony_ci goto out; 70668c2ecf20Sopenharmony_ci 70678c2ecf20Sopenharmony_ci if (ioc->hard_resets < -1) 70688c2ecf20Sopenharmony_ci ioc->hard_resets++; 70698c2ecf20Sopenharmony_ci 70708c2ecf20Sopenharmony_ci /* 70718c2ecf20Sopenharmony_ci * At this point, we know soft reset succeeded. 70728c2ecf20Sopenharmony_ci */ 70738c2ecf20Sopenharmony_ci 70748c2ecf20Sopenharmony_ci ioc->active = 1; 70758c2ecf20Sopenharmony_ci CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM); 70768c2ecf20Sopenharmony_ci 70778c2ecf20Sopenharmony_ci out: 70788c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 70798c2ecf20Sopenharmony_ci ioc->ioc_reset_in_progress = 0; 70808c2ecf20Sopenharmony_ci ioc->taskmgmt_quiesce_io = 0; 70818c2ecf20Sopenharmony_ci ioc->taskmgmt_in_progress = 0; 70828c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 70838c2ecf20Sopenharmony_ci 70848c2ecf20Sopenharmony_ci if (ioc->active) { /* otherwise, hard reset coming */ 70858c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 70868c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) 70878c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, ioc, 70888c2ecf20Sopenharmony_ci MPT_IOC_POST_RESET); 70898c2ecf20Sopenharmony_ci } 70908c2ecf20Sopenharmony_ci } 70918c2ecf20Sopenharmony_ci 70928c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT 70938c2ecf20Sopenharmony_ci "SoftResetHandler: completed (%d seconds): %s\n", 70948c2ecf20Sopenharmony_ci ioc->name, jiffies_to_msecs(jiffies - time_count)/1000, 70958c2ecf20Sopenharmony_ci ((rc == 0) ? "SUCCESS" : "FAILED"))); 70968c2ecf20Sopenharmony_ci 70978c2ecf20Sopenharmony_ci return rc; 70988c2ecf20Sopenharmony_ci} 70998c2ecf20Sopenharmony_ci 71008c2ecf20Sopenharmony_ci/** 71018c2ecf20Sopenharmony_ci * mpt_Soft_Hard_ResetHandler - Try less expensive reset 71028c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 71038c2ecf20Sopenharmony_ci * @sleepFlag: Indicates if sleep or schedule must be called. 71048c2ecf20Sopenharmony_ci * 71058c2ecf20Sopenharmony_ci * Returns 0 for SUCCESS or -1 if FAILED. 71068c2ecf20Sopenharmony_ci * Try for softreset first, only if it fails go for expensive 71078c2ecf20Sopenharmony_ci * HardReset. 71088c2ecf20Sopenharmony_ci **/ 71098c2ecf20Sopenharmony_ciint 71108c2ecf20Sopenharmony_cimpt_Soft_Hard_ResetHandler(MPT_ADAPTER *ioc, int sleepFlag) { 71118c2ecf20Sopenharmony_ci int ret = -1; 71128c2ecf20Sopenharmony_ci 71138c2ecf20Sopenharmony_ci ret = mpt_SoftResetHandler(ioc, sleepFlag); 71148c2ecf20Sopenharmony_ci if (ret == 0) 71158c2ecf20Sopenharmony_ci return ret; 71168c2ecf20Sopenharmony_ci ret = mpt_HardResetHandler(ioc, sleepFlag); 71178c2ecf20Sopenharmony_ci return ret; 71188c2ecf20Sopenharmony_ci} 71198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_Soft_Hard_ResetHandler); 71208c2ecf20Sopenharmony_ci 71218c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 71228c2ecf20Sopenharmony_ci/* 71238c2ecf20Sopenharmony_ci * Reset Handling 71248c2ecf20Sopenharmony_ci */ 71258c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 71268c2ecf20Sopenharmony_ci/** 71278c2ecf20Sopenharmony_ci * mpt_HardResetHandler - Generic reset handler 71288c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 71298c2ecf20Sopenharmony_ci * @sleepFlag: Indicates if sleep or schedule must be called. 71308c2ecf20Sopenharmony_ci * 71318c2ecf20Sopenharmony_ci * Issues SCSI Task Management call based on input arg values. 71328c2ecf20Sopenharmony_ci * If TaskMgmt fails, returns associated SCSI request. 71338c2ecf20Sopenharmony_ci * 71348c2ecf20Sopenharmony_ci * Remark: _HardResetHandler can be invoked from an interrupt thread (timer) 71358c2ecf20Sopenharmony_ci * or a non-interrupt thread. In the former, must not call schedule(). 71368c2ecf20Sopenharmony_ci * 71378c2ecf20Sopenharmony_ci * Note: A return of -1 is a FATAL error case, as it means a 71388c2ecf20Sopenharmony_ci * FW reload/initialization failed. 71398c2ecf20Sopenharmony_ci * 71408c2ecf20Sopenharmony_ci * Returns 0 for SUCCESS or -1 if FAILED. 71418c2ecf20Sopenharmony_ci */ 71428c2ecf20Sopenharmony_ciint 71438c2ecf20Sopenharmony_cimpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) 71448c2ecf20Sopenharmony_ci{ 71458c2ecf20Sopenharmony_ci int rc; 71468c2ecf20Sopenharmony_ci u8 cb_idx; 71478c2ecf20Sopenharmony_ci unsigned long flags; 71488c2ecf20Sopenharmony_ci unsigned long time_count; 71498c2ecf20Sopenharmony_ci 71508c2ecf20Sopenharmony_ci dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HardResetHandler Entered!\n", ioc->name)); 71518c2ecf20Sopenharmony_ci#ifdef MFCNT 71528c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "HardResetHandler Entered!\n", ioc->name); 71538c2ecf20Sopenharmony_ci printk("MF count 0x%x !\n", ioc->mfcnt); 71548c2ecf20Sopenharmony_ci#endif 71558c2ecf20Sopenharmony_ci if (mpt_fwfault_debug) 71568c2ecf20Sopenharmony_ci mpt_halt_firmware(ioc); 71578c2ecf20Sopenharmony_ci 71588c2ecf20Sopenharmony_ci /* Reset the adapter. Prevent more than 1 call to 71598c2ecf20Sopenharmony_ci * mpt_do_ioc_recovery at any instant in time. 71608c2ecf20Sopenharmony_ci */ 71618c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 71628c2ecf20Sopenharmony_ci if (ioc->ioc_reset_in_progress) { 71638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 71648c2ecf20Sopenharmony_ci ioc->wait_on_reset_completion = 1; 71658c2ecf20Sopenharmony_ci do { 71668c2ecf20Sopenharmony_ci ssleep(1); 71678c2ecf20Sopenharmony_ci } while (ioc->ioc_reset_in_progress == 1); 71688c2ecf20Sopenharmony_ci ioc->wait_on_reset_completion = 0; 71698c2ecf20Sopenharmony_ci return ioc->reset_status; 71708c2ecf20Sopenharmony_ci } 71718c2ecf20Sopenharmony_ci if (ioc->wait_on_reset_completion) { 71728c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 71738c2ecf20Sopenharmony_ci rc = 0; 71748c2ecf20Sopenharmony_ci time_count = jiffies; 71758c2ecf20Sopenharmony_ci goto exit; 71768c2ecf20Sopenharmony_ci } 71778c2ecf20Sopenharmony_ci ioc->ioc_reset_in_progress = 1; 71788c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 71798c2ecf20Sopenharmony_ci ioc->alt_ioc->ioc_reset_in_progress = 1; 71808c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 71818c2ecf20Sopenharmony_ci 71828c2ecf20Sopenharmony_ci 71838c2ecf20Sopenharmony_ci /* The SCSI driver needs to adjust timeouts on all current 71848c2ecf20Sopenharmony_ci * commands prior to the diagnostic reset being issued. 71858c2ecf20Sopenharmony_ci * Prevents timeouts occurring during a diagnostic reset...very bad. 71868c2ecf20Sopenharmony_ci * For all other protocol drivers, this is a no-op. 71878c2ecf20Sopenharmony_ci */ 71888c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 71898c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) { 71908c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); 71918c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 71928c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, ioc->alt_ioc, 71938c2ecf20Sopenharmony_ci MPT_IOC_SETUP_RESET); 71948c2ecf20Sopenharmony_ci } 71958c2ecf20Sopenharmony_ci } 71968c2ecf20Sopenharmony_ci 71978c2ecf20Sopenharmony_ci time_count = jiffies; 71988c2ecf20Sopenharmony_ci rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag); 71998c2ecf20Sopenharmony_ci if (rc != 0) { 72008c2ecf20Sopenharmony_ci printk(KERN_WARNING MYNAM 72018c2ecf20Sopenharmony_ci ": WARNING - (%d) Cannot recover %s, doorbell=0x%08x\n", 72028c2ecf20Sopenharmony_ci rc, ioc->name, mpt_GetIocState(ioc, 0)); 72038c2ecf20Sopenharmony_ci } else { 72048c2ecf20Sopenharmony_ci if (ioc->hard_resets < -1) 72058c2ecf20Sopenharmony_ci ioc->hard_resets++; 72068c2ecf20Sopenharmony_ci } 72078c2ecf20Sopenharmony_ci 72088c2ecf20Sopenharmony_ci spin_lock_irqsave(&ioc->taskmgmt_lock, flags); 72098c2ecf20Sopenharmony_ci ioc->ioc_reset_in_progress = 0; 72108c2ecf20Sopenharmony_ci ioc->taskmgmt_quiesce_io = 0; 72118c2ecf20Sopenharmony_ci ioc->taskmgmt_in_progress = 0; 72128c2ecf20Sopenharmony_ci ioc->reset_status = rc; 72138c2ecf20Sopenharmony_ci if (ioc->alt_ioc) { 72148c2ecf20Sopenharmony_ci ioc->alt_ioc->ioc_reset_in_progress = 0; 72158c2ecf20Sopenharmony_ci ioc->alt_ioc->taskmgmt_quiesce_io = 0; 72168c2ecf20Sopenharmony_ci ioc->alt_ioc->taskmgmt_in_progress = 0; 72178c2ecf20Sopenharmony_ci } 72188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags); 72198c2ecf20Sopenharmony_ci 72208c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 72218c2ecf20Sopenharmony_ci if (MptResetHandlers[cb_idx]) { 72228c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET); 72238c2ecf20Sopenharmony_ci if (ioc->alt_ioc) 72248c2ecf20Sopenharmony_ci mpt_signal_reset(cb_idx, 72258c2ecf20Sopenharmony_ci ioc->alt_ioc, MPT_IOC_POST_RESET); 72268c2ecf20Sopenharmony_ci } 72278c2ecf20Sopenharmony_ci } 72288c2ecf20Sopenharmony_ciexit: 72298c2ecf20Sopenharmony_ci dtmprintk(ioc, 72308c2ecf20Sopenharmony_ci printk(MYIOC_s_DEBUG_FMT 72318c2ecf20Sopenharmony_ci "HardResetHandler: completed (%d seconds): %s\n", ioc->name, 72328c2ecf20Sopenharmony_ci jiffies_to_msecs(jiffies - time_count)/1000, ((rc == 0) ? 72338c2ecf20Sopenharmony_ci "SUCCESS" : "FAILED"))); 72348c2ecf20Sopenharmony_ci 72358c2ecf20Sopenharmony_ci return rc; 72368c2ecf20Sopenharmony_ci} 72378c2ecf20Sopenharmony_ci 72388c2ecf20Sopenharmony_ci#ifdef CONFIG_FUSION_LOGGING 72398c2ecf20Sopenharmony_cistatic void 72408c2ecf20Sopenharmony_cimpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply) 72418c2ecf20Sopenharmony_ci{ 72428c2ecf20Sopenharmony_ci char *ds = NULL; 72438c2ecf20Sopenharmony_ci u32 evData0; 72448c2ecf20Sopenharmony_ci int ii; 72458c2ecf20Sopenharmony_ci u8 event; 72468c2ecf20Sopenharmony_ci char *evStr = ioc->evStr; 72478c2ecf20Sopenharmony_ci 72488c2ecf20Sopenharmony_ci event = le32_to_cpu(pEventReply->Event) & 0xFF; 72498c2ecf20Sopenharmony_ci evData0 = le32_to_cpu(pEventReply->Data[0]); 72508c2ecf20Sopenharmony_ci 72518c2ecf20Sopenharmony_ci switch(event) { 72528c2ecf20Sopenharmony_ci case MPI_EVENT_NONE: 72538c2ecf20Sopenharmony_ci ds = "None"; 72548c2ecf20Sopenharmony_ci break; 72558c2ecf20Sopenharmony_ci case MPI_EVENT_LOG_DATA: 72568c2ecf20Sopenharmony_ci ds = "Log Data"; 72578c2ecf20Sopenharmony_ci break; 72588c2ecf20Sopenharmony_ci case MPI_EVENT_STATE_CHANGE: 72598c2ecf20Sopenharmony_ci ds = "State Change"; 72608c2ecf20Sopenharmony_ci break; 72618c2ecf20Sopenharmony_ci case MPI_EVENT_UNIT_ATTENTION: 72628c2ecf20Sopenharmony_ci ds = "Unit Attention"; 72638c2ecf20Sopenharmony_ci break; 72648c2ecf20Sopenharmony_ci case MPI_EVENT_IOC_BUS_RESET: 72658c2ecf20Sopenharmony_ci ds = "IOC Bus Reset"; 72668c2ecf20Sopenharmony_ci break; 72678c2ecf20Sopenharmony_ci case MPI_EVENT_EXT_BUS_RESET: 72688c2ecf20Sopenharmony_ci ds = "External Bus Reset"; 72698c2ecf20Sopenharmony_ci break; 72708c2ecf20Sopenharmony_ci case MPI_EVENT_RESCAN: 72718c2ecf20Sopenharmony_ci ds = "Bus Rescan Event"; 72728c2ecf20Sopenharmony_ci break; 72738c2ecf20Sopenharmony_ci case MPI_EVENT_LINK_STATUS_CHANGE: 72748c2ecf20Sopenharmony_ci if (evData0 == MPI_EVENT_LINK_STATUS_FAILURE) 72758c2ecf20Sopenharmony_ci ds = "Link Status(FAILURE) Change"; 72768c2ecf20Sopenharmony_ci else 72778c2ecf20Sopenharmony_ci ds = "Link Status(ACTIVE) Change"; 72788c2ecf20Sopenharmony_ci break; 72798c2ecf20Sopenharmony_ci case MPI_EVENT_LOOP_STATE_CHANGE: 72808c2ecf20Sopenharmony_ci if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LIP) 72818c2ecf20Sopenharmony_ci ds = "Loop State(LIP) Change"; 72828c2ecf20Sopenharmony_ci else if (evData0 == MPI_EVENT_LOOP_STATE_CHANGE_LPE) 72838c2ecf20Sopenharmony_ci ds = "Loop State(LPE) Change"; 72848c2ecf20Sopenharmony_ci else 72858c2ecf20Sopenharmony_ci ds = "Loop State(LPB) Change"; 72868c2ecf20Sopenharmony_ci break; 72878c2ecf20Sopenharmony_ci case MPI_EVENT_LOGOUT: 72888c2ecf20Sopenharmony_ci ds = "Logout"; 72898c2ecf20Sopenharmony_ci break; 72908c2ecf20Sopenharmony_ci case MPI_EVENT_EVENT_CHANGE: 72918c2ecf20Sopenharmony_ci if (evData0) 72928c2ecf20Sopenharmony_ci ds = "Events ON"; 72938c2ecf20Sopenharmony_ci else 72948c2ecf20Sopenharmony_ci ds = "Events OFF"; 72958c2ecf20Sopenharmony_ci break; 72968c2ecf20Sopenharmony_ci case MPI_EVENT_INTEGRATED_RAID: 72978c2ecf20Sopenharmony_ci { 72988c2ecf20Sopenharmony_ci u8 ReasonCode = (u8)(evData0 >> 16); 72998c2ecf20Sopenharmony_ci switch (ReasonCode) { 73008c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_CREATED : 73018c2ecf20Sopenharmony_ci ds = "Integrated Raid: Volume Created"; 73028c2ecf20Sopenharmony_ci break; 73038c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_DELETED : 73048c2ecf20Sopenharmony_ci ds = "Integrated Raid: Volume Deleted"; 73058c2ecf20Sopenharmony_ci break; 73068c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED : 73078c2ecf20Sopenharmony_ci ds = "Integrated Raid: Volume Settings Changed"; 73088c2ecf20Sopenharmony_ci break; 73098c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED : 73108c2ecf20Sopenharmony_ci ds = "Integrated Raid: Volume Status Changed"; 73118c2ecf20Sopenharmony_ci break; 73128c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED : 73138c2ecf20Sopenharmony_ci ds = "Integrated Raid: Volume Physdisk Changed"; 73148c2ecf20Sopenharmony_ci break; 73158c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_CREATED : 73168c2ecf20Sopenharmony_ci ds = "Integrated Raid: Physdisk Created"; 73178c2ecf20Sopenharmony_ci break; 73188c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_DELETED : 73198c2ecf20Sopenharmony_ci ds = "Integrated Raid: Physdisk Deleted"; 73208c2ecf20Sopenharmony_ci break; 73218c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED : 73228c2ecf20Sopenharmony_ci ds = "Integrated Raid: Physdisk Settings Changed"; 73238c2ecf20Sopenharmony_ci break; 73248c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED : 73258c2ecf20Sopenharmony_ci ds = "Integrated Raid: Physdisk Status Changed"; 73268c2ecf20Sopenharmony_ci break; 73278c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED : 73288c2ecf20Sopenharmony_ci ds = "Integrated Raid: Domain Validation Needed"; 73298c2ecf20Sopenharmony_ci break; 73308c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_SMART_DATA : 73318c2ecf20Sopenharmony_ci ds = "Integrated Raid; Smart Data"; 73328c2ecf20Sopenharmony_ci break; 73338c2ecf20Sopenharmony_ci case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED : 73348c2ecf20Sopenharmony_ci ds = "Integrated Raid: Replace Action Started"; 73358c2ecf20Sopenharmony_ci break; 73368c2ecf20Sopenharmony_ci default: 73378c2ecf20Sopenharmony_ci ds = "Integrated Raid"; 73388c2ecf20Sopenharmony_ci break; 73398c2ecf20Sopenharmony_ci } 73408c2ecf20Sopenharmony_ci break; 73418c2ecf20Sopenharmony_ci } 73428c2ecf20Sopenharmony_ci case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: 73438c2ecf20Sopenharmony_ci ds = "SCSI Device Status Change"; 73448c2ecf20Sopenharmony_ci break; 73458c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: 73468c2ecf20Sopenharmony_ci { 73478c2ecf20Sopenharmony_ci u8 id = (u8)(evData0); 73488c2ecf20Sopenharmony_ci u8 channel = (u8)(evData0 >> 8); 73498c2ecf20Sopenharmony_ci u8 ReasonCode = (u8)(evData0 >> 16); 73508c2ecf20Sopenharmony_ci switch (ReasonCode) { 73518c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: 73528c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73538c2ecf20Sopenharmony_ci "SAS Device Status Change: Added: " 73548c2ecf20Sopenharmony_ci "id=%d channel=%d", id, channel); 73558c2ecf20Sopenharmony_ci break; 73568c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: 73578c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73588c2ecf20Sopenharmony_ci "SAS Device Status Change: Deleted: " 73598c2ecf20Sopenharmony_ci "id=%d channel=%d", id, channel); 73608c2ecf20Sopenharmony_ci break; 73618c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: 73628c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73638c2ecf20Sopenharmony_ci "SAS Device Status Change: SMART Data: " 73648c2ecf20Sopenharmony_ci "id=%d channel=%d", id, channel); 73658c2ecf20Sopenharmony_ci break; 73668c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: 73678c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73688c2ecf20Sopenharmony_ci "SAS Device Status Change: No Persistency: " 73698c2ecf20Sopenharmony_ci "id=%d channel=%d", id, channel); 73708c2ecf20Sopenharmony_ci break; 73718c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: 73728c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73738c2ecf20Sopenharmony_ci "SAS Device Status Change: Unsupported Device " 73748c2ecf20Sopenharmony_ci "Discovered : id=%d channel=%d", id, channel); 73758c2ecf20Sopenharmony_ci break; 73768c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: 73778c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73788c2ecf20Sopenharmony_ci "SAS Device Status Change: Internal Device " 73798c2ecf20Sopenharmony_ci "Reset : id=%d channel=%d", id, channel); 73808c2ecf20Sopenharmony_ci break; 73818c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: 73828c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73838c2ecf20Sopenharmony_ci "SAS Device Status Change: Internal Task " 73848c2ecf20Sopenharmony_ci "Abort : id=%d channel=%d", id, channel); 73858c2ecf20Sopenharmony_ci break; 73868c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: 73878c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73888c2ecf20Sopenharmony_ci "SAS Device Status Change: Internal Abort " 73898c2ecf20Sopenharmony_ci "Task Set : id=%d channel=%d", id, channel); 73908c2ecf20Sopenharmony_ci break; 73918c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: 73928c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73938c2ecf20Sopenharmony_ci "SAS Device Status Change: Internal Clear " 73948c2ecf20Sopenharmony_ci "Task Set : id=%d channel=%d", id, channel); 73958c2ecf20Sopenharmony_ci break; 73968c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: 73978c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 73988c2ecf20Sopenharmony_ci "SAS Device Status Change: Internal Query " 73998c2ecf20Sopenharmony_ci "Task : id=%d channel=%d", id, channel); 74008c2ecf20Sopenharmony_ci break; 74018c2ecf20Sopenharmony_ci default: 74028c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74038c2ecf20Sopenharmony_ci "SAS Device Status Change: Unknown: " 74048c2ecf20Sopenharmony_ci "id=%d channel=%d", id, channel); 74058c2ecf20Sopenharmony_ci break; 74068c2ecf20Sopenharmony_ci } 74078c2ecf20Sopenharmony_ci break; 74088c2ecf20Sopenharmony_ci } 74098c2ecf20Sopenharmony_ci case MPI_EVENT_ON_BUS_TIMER_EXPIRED: 74108c2ecf20Sopenharmony_ci ds = "Bus Timer Expired"; 74118c2ecf20Sopenharmony_ci break; 74128c2ecf20Sopenharmony_ci case MPI_EVENT_QUEUE_FULL: 74138c2ecf20Sopenharmony_ci { 74148c2ecf20Sopenharmony_ci u16 curr_depth = (u16)(evData0 >> 16); 74158c2ecf20Sopenharmony_ci u8 channel = (u8)(evData0 >> 8); 74168c2ecf20Sopenharmony_ci u8 id = (u8)(evData0); 74178c2ecf20Sopenharmony_ci 74188c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74198c2ecf20Sopenharmony_ci "Queue Full: channel=%d id=%d depth=%d", 74208c2ecf20Sopenharmony_ci channel, id, curr_depth); 74218c2ecf20Sopenharmony_ci break; 74228c2ecf20Sopenharmony_ci } 74238c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_SES: 74248c2ecf20Sopenharmony_ci ds = "SAS SES Event"; 74258c2ecf20Sopenharmony_ci break; 74268c2ecf20Sopenharmony_ci case MPI_EVENT_PERSISTENT_TABLE_FULL: 74278c2ecf20Sopenharmony_ci ds = "Persistent Table Full"; 74288c2ecf20Sopenharmony_ci break; 74298c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PHY_LINK_STATUS: 74308c2ecf20Sopenharmony_ci { 74318c2ecf20Sopenharmony_ci u8 LinkRates = (u8)(evData0 >> 8); 74328c2ecf20Sopenharmony_ci u8 PhyNumber = (u8)(evData0); 74338c2ecf20Sopenharmony_ci LinkRates = (LinkRates & MPI_EVENT_SAS_PLS_LR_CURRENT_MASK) >> 74348c2ecf20Sopenharmony_ci MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT; 74358c2ecf20Sopenharmony_ci switch (LinkRates) { 74368c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN: 74378c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74388c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74398c2ecf20Sopenharmony_ci " Rate Unknown",PhyNumber); 74408c2ecf20Sopenharmony_ci break; 74418c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED: 74428c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74438c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74448c2ecf20Sopenharmony_ci " Phy Disabled",PhyNumber); 74458c2ecf20Sopenharmony_ci break; 74468c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION: 74478c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74488c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74498c2ecf20Sopenharmony_ci " Failed Speed Nego",PhyNumber); 74508c2ecf20Sopenharmony_ci break; 74518c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE: 74528c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74538c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74548c2ecf20Sopenharmony_ci " Sata OOB Completed",PhyNumber); 74558c2ecf20Sopenharmony_ci break; 74568c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_1_5: 74578c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74588c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74598c2ecf20Sopenharmony_ci " Rate 1.5 Gbps",PhyNumber); 74608c2ecf20Sopenharmony_ci break; 74618c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_3_0: 74628c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74638c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74648c2ecf20Sopenharmony_ci " Rate 3.0 Gbps", PhyNumber); 74658c2ecf20Sopenharmony_ci break; 74668c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_PLS_LR_RATE_6_0: 74678c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74688c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d:" 74698c2ecf20Sopenharmony_ci " Rate 6.0 Gbps", PhyNumber); 74708c2ecf20Sopenharmony_ci break; 74718c2ecf20Sopenharmony_ci default: 74728c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74738c2ecf20Sopenharmony_ci "SAS PHY Link Status: Phy=%d", PhyNumber); 74748c2ecf20Sopenharmony_ci break; 74758c2ecf20Sopenharmony_ci } 74768c2ecf20Sopenharmony_ci break; 74778c2ecf20Sopenharmony_ci } 74788c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DISCOVERY_ERROR: 74798c2ecf20Sopenharmony_ci ds = "SAS Discovery Error"; 74808c2ecf20Sopenharmony_ci break; 74818c2ecf20Sopenharmony_ci case MPI_EVENT_IR_RESYNC_UPDATE: 74828c2ecf20Sopenharmony_ci { 74838c2ecf20Sopenharmony_ci u8 resync_complete = (u8)(evData0 >> 16); 74848c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74858c2ecf20Sopenharmony_ci "IR Resync Update: Complete = %d:",resync_complete); 74868c2ecf20Sopenharmony_ci break; 74878c2ecf20Sopenharmony_ci } 74888c2ecf20Sopenharmony_ci case MPI_EVENT_IR2: 74898c2ecf20Sopenharmony_ci { 74908c2ecf20Sopenharmony_ci u8 id = (u8)(evData0); 74918c2ecf20Sopenharmony_ci u8 channel = (u8)(evData0 >> 8); 74928c2ecf20Sopenharmony_ci u8 phys_num = (u8)(evData0 >> 24); 74938c2ecf20Sopenharmony_ci u8 ReasonCode = (u8)(evData0 >> 16); 74948c2ecf20Sopenharmony_ci 74958c2ecf20Sopenharmony_ci switch (ReasonCode) { 74968c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_LD_STATE_CHANGED: 74978c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 74988c2ecf20Sopenharmony_ci "IR2: LD State Changed: " 74998c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75008c2ecf20Sopenharmony_ci id, channel, phys_num); 75018c2ecf20Sopenharmony_ci break; 75028c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_PD_STATE_CHANGED: 75038c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75048c2ecf20Sopenharmony_ci "IR2: PD State Changed " 75058c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75068c2ecf20Sopenharmony_ci id, channel, phys_num); 75078c2ecf20Sopenharmony_ci break; 75088c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL: 75098c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75108c2ecf20Sopenharmony_ci "IR2: Bad Block Table Full: " 75118c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75128c2ecf20Sopenharmony_ci id, channel, phys_num); 75138c2ecf20Sopenharmony_ci break; 75148c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_PD_INSERTED: 75158c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75168c2ecf20Sopenharmony_ci "IR2: PD Inserted: " 75178c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75188c2ecf20Sopenharmony_ci id, channel, phys_num); 75198c2ecf20Sopenharmony_ci break; 75208c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_PD_REMOVED: 75218c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75228c2ecf20Sopenharmony_ci "IR2: PD Removed: " 75238c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75248c2ecf20Sopenharmony_ci id, channel, phys_num); 75258c2ecf20Sopenharmony_ci break; 75268c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED: 75278c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75288c2ecf20Sopenharmony_ci "IR2: Foreign CFG Detected: " 75298c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75308c2ecf20Sopenharmony_ci id, channel, phys_num); 75318c2ecf20Sopenharmony_ci break; 75328c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR: 75338c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75348c2ecf20Sopenharmony_ci "IR2: Rebuild Medium Error: " 75358c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75368c2ecf20Sopenharmony_ci id, channel, phys_num); 75378c2ecf20Sopenharmony_ci break; 75388c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED: 75398c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75408c2ecf20Sopenharmony_ci "IR2: Dual Port Added: " 75418c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75428c2ecf20Sopenharmony_ci id, channel, phys_num); 75438c2ecf20Sopenharmony_ci break; 75448c2ecf20Sopenharmony_ci case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED: 75458c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75468c2ecf20Sopenharmony_ci "IR2: Dual Port Removed: " 75478c2ecf20Sopenharmony_ci "id=%d channel=%d phys_num=%d", 75488c2ecf20Sopenharmony_ci id, channel, phys_num); 75498c2ecf20Sopenharmony_ci break; 75508c2ecf20Sopenharmony_ci default: 75518c2ecf20Sopenharmony_ci ds = "IR2"; 75528c2ecf20Sopenharmony_ci break; 75538c2ecf20Sopenharmony_ci } 75548c2ecf20Sopenharmony_ci break; 75558c2ecf20Sopenharmony_ci } 75568c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_DISCOVERY: 75578c2ecf20Sopenharmony_ci { 75588c2ecf20Sopenharmony_ci if (evData0) 75598c2ecf20Sopenharmony_ci ds = "SAS Discovery: Start"; 75608c2ecf20Sopenharmony_ci else 75618c2ecf20Sopenharmony_ci ds = "SAS Discovery: Stop"; 75628c2ecf20Sopenharmony_ci break; 75638c2ecf20Sopenharmony_ci } 75648c2ecf20Sopenharmony_ci case MPI_EVENT_LOG_ENTRY_ADDED: 75658c2ecf20Sopenharmony_ci ds = "SAS Log Entry Added"; 75668c2ecf20Sopenharmony_ci break; 75678c2ecf20Sopenharmony_ci 75688c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_BROADCAST_PRIMITIVE: 75698c2ecf20Sopenharmony_ci { 75708c2ecf20Sopenharmony_ci u8 phy_num = (u8)(evData0); 75718c2ecf20Sopenharmony_ci u8 port_num = (u8)(evData0 >> 8); 75728c2ecf20Sopenharmony_ci u8 port_width = (u8)(evData0 >> 16); 75738c2ecf20Sopenharmony_ci u8 primitive = (u8)(evData0 >> 24); 75748c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 75758c2ecf20Sopenharmony_ci "SAS Broadcast Primitive: phy=%d port=%d " 75768c2ecf20Sopenharmony_ci "width=%d primitive=0x%02x", 75778c2ecf20Sopenharmony_ci phy_num, port_num, port_width, primitive); 75788c2ecf20Sopenharmony_ci break; 75798c2ecf20Sopenharmony_ci } 75808c2ecf20Sopenharmony_ci 75818c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: 75828c2ecf20Sopenharmony_ci { 75838c2ecf20Sopenharmony_ci u8 reason = (u8)(evData0); 75848c2ecf20Sopenharmony_ci 75858c2ecf20Sopenharmony_ci switch (reason) { 75868c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_INIT_RC_ADDED: 75878c2ecf20Sopenharmony_ci ds = "SAS Initiator Status Change: Added"; 75888c2ecf20Sopenharmony_ci break; 75898c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_INIT_RC_REMOVED: 75908c2ecf20Sopenharmony_ci ds = "SAS Initiator Status Change: Deleted"; 75918c2ecf20Sopenharmony_ci break; 75928c2ecf20Sopenharmony_ci default: 75938c2ecf20Sopenharmony_ci ds = "SAS Initiator Status Change"; 75948c2ecf20Sopenharmony_ci break; 75958c2ecf20Sopenharmony_ci } 75968c2ecf20Sopenharmony_ci break; 75978c2ecf20Sopenharmony_ci } 75988c2ecf20Sopenharmony_ci 75998c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_INIT_TABLE_OVERFLOW: 76008c2ecf20Sopenharmony_ci { 76018c2ecf20Sopenharmony_ci u8 max_init = (u8)(evData0); 76028c2ecf20Sopenharmony_ci u8 current_init = (u8)(evData0 >> 8); 76038c2ecf20Sopenharmony_ci 76048c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76058c2ecf20Sopenharmony_ci "SAS Initiator Device Table Overflow: max initiators=%02d " 76068c2ecf20Sopenharmony_ci "current initiators=%02d", 76078c2ecf20Sopenharmony_ci max_init, current_init); 76088c2ecf20Sopenharmony_ci break; 76098c2ecf20Sopenharmony_ci } 76108c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_SMP_ERROR: 76118c2ecf20Sopenharmony_ci { 76128c2ecf20Sopenharmony_ci u8 status = (u8)(evData0); 76138c2ecf20Sopenharmony_ci u8 port_num = (u8)(evData0 >> 8); 76148c2ecf20Sopenharmony_ci u8 result = (u8)(evData0 >> 16); 76158c2ecf20Sopenharmony_ci 76168c2ecf20Sopenharmony_ci if (status == MPI_EVENT_SAS_SMP_FUNCTION_RESULT_VALID) 76178c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76188c2ecf20Sopenharmony_ci "SAS SMP Error: port=%d result=0x%02x", 76198c2ecf20Sopenharmony_ci port_num, result); 76208c2ecf20Sopenharmony_ci else if (status == MPI_EVENT_SAS_SMP_CRC_ERROR) 76218c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76228c2ecf20Sopenharmony_ci "SAS SMP Error: port=%d : CRC Error", 76238c2ecf20Sopenharmony_ci port_num); 76248c2ecf20Sopenharmony_ci else if (status == MPI_EVENT_SAS_SMP_TIMEOUT) 76258c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76268c2ecf20Sopenharmony_ci "SAS SMP Error: port=%d : Timeout", 76278c2ecf20Sopenharmony_ci port_num); 76288c2ecf20Sopenharmony_ci else if (status == MPI_EVENT_SAS_SMP_NO_DESTINATION) 76298c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76308c2ecf20Sopenharmony_ci "SAS SMP Error: port=%d : No Destination", 76318c2ecf20Sopenharmony_ci port_num); 76328c2ecf20Sopenharmony_ci else if (status == MPI_EVENT_SAS_SMP_BAD_DESTINATION) 76338c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76348c2ecf20Sopenharmony_ci "SAS SMP Error: port=%d : Bad Destination", 76358c2ecf20Sopenharmony_ci port_num); 76368c2ecf20Sopenharmony_ci else 76378c2ecf20Sopenharmony_ci snprintf(evStr, EVENT_DESCR_STR_SZ, 76388c2ecf20Sopenharmony_ci "SAS SMP Error: port=%d : status=0x%02x", 76398c2ecf20Sopenharmony_ci port_num, status); 76408c2ecf20Sopenharmony_ci break; 76418c2ecf20Sopenharmony_ci } 76428c2ecf20Sopenharmony_ci 76438c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE: 76448c2ecf20Sopenharmony_ci { 76458c2ecf20Sopenharmony_ci u8 reason = (u8)(evData0); 76468c2ecf20Sopenharmony_ci 76478c2ecf20Sopenharmony_ci switch (reason) { 76488c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_EXP_RC_ADDED: 76498c2ecf20Sopenharmony_ci ds = "Expander Status Change: Added"; 76508c2ecf20Sopenharmony_ci break; 76518c2ecf20Sopenharmony_ci case MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING: 76528c2ecf20Sopenharmony_ci ds = "Expander Status Change: Deleted"; 76538c2ecf20Sopenharmony_ci break; 76548c2ecf20Sopenharmony_ci default: 76558c2ecf20Sopenharmony_ci ds = "Expander Status Change"; 76568c2ecf20Sopenharmony_ci break; 76578c2ecf20Sopenharmony_ci } 76588c2ecf20Sopenharmony_ci break; 76598c2ecf20Sopenharmony_ci } 76608c2ecf20Sopenharmony_ci 76618c2ecf20Sopenharmony_ci /* 76628c2ecf20Sopenharmony_ci * MPT base "custom" events may be added here... 76638c2ecf20Sopenharmony_ci */ 76648c2ecf20Sopenharmony_ci default: 76658c2ecf20Sopenharmony_ci ds = "Unknown"; 76668c2ecf20Sopenharmony_ci break; 76678c2ecf20Sopenharmony_ci } 76688c2ecf20Sopenharmony_ci if (ds) 76698c2ecf20Sopenharmony_ci strlcpy(evStr, ds, EVENT_DESCR_STR_SZ); 76708c2ecf20Sopenharmony_ci 76718c2ecf20Sopenharmony_ci 76728c2ecf20Sopenharmony_ci devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT 76738c2ecf20Sopenharmony_ci "MPT event:(%02Xh) : %s\n", 76748c2ecf20Sopenharmony_ci ioc->name, event, evStr)); 76758c2ecf20Sopenharmony_ci 76768c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM 76778c2ecf20Sopenharmony_ci ": Event data:\n")); 76788c2ecf20Sopenharmony_ci for (ii = 0; ii < le16_to_cpu(pEventReply->EventDataLength); ii++) 76798c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(" %08x", 76808c2ecf20Sopenharmony_ci le32_to_cpu(pEventReply->Data[ii]))); 76818c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(KERN_DEBUG "\n")); 76828c2ecf20Sopenharmony_ci} 76838c2ecf20Sopenharmony_ci#endif 76848c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 76858c2ecf20Sopenharmony_ci/** 76868c2ecf20Sopenharmony_ci * ProcessEventNotification - Route EventNotificationReply to all event handlers 76878c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 76888c2ecf20Sopenharmony_ci * @pEventReply: Pointer to EventNotification reply frame 76898c2ecf20Sopenharmony_ci * @evHandlers: Pointer to integer, number of event handlers 76908c2ecf20Sopenharmony_ci * 76918c2ecf20Sopenharmony_ci * Routes a received EventNotificationReply to all currently registered 76928c2ecf20Sopenharmony_ci * event handlers. 76938c2ecf20Sopenharmony_ci * Returns sum of event handlers return values. 76948c2ecf20Sopenharmony_ci */ 76958c2ecf20Sopenharmony_cistatic int 76968c2ecf20Sopenharmony_ciProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply, int *evHandlers) 76978c2ecf20Sopenharmony_ci{ 76988c2ecf20Sopenharmony_ci u16 evDataLen; 76998c2ecf20Sopenharmony_ci u32 evData0 = 0; 77008c2ecf20Sopenharmony_ci int ii; 77018c2ecf20Sopenharmony_ci u8 cb_idx; 77028c2ecf20Sopenharmony_ci int r = 0; 77038c2ecf20Sopenharmony_ci int handlers = 0; 77048c2ecf20Sopenharmony_ci u8 event; 77058c2ecf20Sopenharmony_ci 77068c2ecf20Sopenharmony_ci /* 77078c2ecf20Sopenharmony_ci * Do platform normalization of values 77088c2ecf20Sopenharmony_ci */ 77098c2ecf20Sopenharmony_ci event = le32_to_cpu(pEventReply->Event) & 0xFF; 77108c2ecf20Sopenharmony_ci evDataLen = le16_to_cpu(pEventReply->EventDataLength); 77118c2ecf20Sopenharmony_ci if (evDataLen) { 77128c2ecf20Sopenharmony_ci evData0 = le32_to_cpu(pEventReply->Data[0]); 77138c2ecf20Sopenharmony_ci } 77148c2ecf20Sopenharmony_ci 77158c2ecf20Sopenharmony_ci#ifdef CONFIG_FUSION_LOGGING 77168c2ecf20Sopenharmony_ci if (evDataLen) 77178c2ecf20Sopenharmony_ci mpt_display_event_info(ioc, pEventReply); 77188c2ecf20Sopenharmony_ci#endif 77198c2ecf20Sopenharmony_ci 77208c2ecf20Sopenharmony_ci /* 77218c2ecf20Sopenharmony_ci * Do general / base driver event processing 77228c2ecf20Sopenharmony_ci */ 77238c2ecf20Sopenharmony_ci switch(event) { 77248c2ecf20Sopenharmony_ci case MPI_EVENT_EVENT_CHANGE: /* 0A */ 77258c2ecf20Sopenharmony_ci if (evDataLen) { 77268c2ecf20Sopenharmony_ci u8 evState = evData0 & 0xFF; 77278c2ecf20Sopenharmony_ci 77288c2ecf20Sopenharmony_ci /* CHECKME! What if evState unexpectedly says OFF (0)? */ 77298c2ecf20Sopenharmony_ci 77308c2ecf20Sopenharmony_ci /* Update EventState field in cached IocFacts */ 77318c2ecf20Sopenharmony_ci if (ioc->facts.Function) { 77328c2ecf20Sopenharmony_ci ioc->facts.EventState = evState; 77338c2ecf20Sopenharmony_ci } 77348c2ecf20Sopenharmony_ci } 77358c2ecf20Sopenharmony_ci break; 77368c2ecf20Sopenharmony_ci case MPI_EVENT_INTEGRATED_RAID: 77378c2ecf20Sopenharmony_ci mptbase_raid_process_event_data(ioc, 77388c2ecf20Sopenharmony_ci (MpiEventDataRaid_t *)pEventReply->Data); 77398c2ecf20Sopenharmony_ci break; 77408c2ecf20Sopenharmony_ci default: 77418c2ecf20Sopenharmony_ci break; 77428c2ecf20Sopenharmony_ci } 77438c2ecf20Sopenharmony_ci 77448c2ecf20Sopenharmony_ci /* 77458c2ecf20Sopenharmony_ci * Should this event be logged? Events are written sequentially. 77468c2ecf20Sopenharmony_ci * When buffer is full, start again at the top. 77478c2ecf20Sopenharmony_ci */ 77488c2ecf20Sopenharmony_ci if (ioc->events && (ioc->eventTypes & ( 1 << event))) { 77498c2ecf20Sopenharmony_ci int idx; 77508c2ecf20Sopenharmony_ci 77518c2ecf20Sopenharmony_ci idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; 77528c2ecf20Sopenharmony_ci 77538c2ecf20Sopenharmony_ci ioc->events[idx].event = event; 77548c2ecf20Sopenharmony_ci ioc->events[idx].eventContext = ioc->eventContext; 77558c2ecf20Sopenharmony_ci 77568c2ecf20Sopenharmony_ci for (ii = 0; ii < 2; ii++) { 77578c2ecf20Sopenharmony_ci if (ii < evDataLen) 77588c2ecf20Sopenharmony_ci ioc->events[idx].data[ii] = le32_to_cpu(pEventReply->Data[ii]); 77598c2ecf20Sopenharmony_ci else 77608c2ecf20Sopenharmony_ci ioc->events[idx].data[ii] = 0; 77618c2ecf20Sopenharmony_ci } 77628c2ecf20Sopenharmony_ci 77638c2ecf20Sopenharmony_ci ioc->eventContext++; 77648c2ecf20Sopenharmony_ci } 77658c2ecf20Sopenharmony_ci 77668c2ecf20Sopenharmony_ci 77678c2ecf20Sopenharmony_ci /* 77688c2ecf20Sopenharmony_ci * Call each currently registered protocol event handler. 77698c2ecf20Sopenharmony_ci */ 77708c2ecf20Sopenharmony_ci for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { 77718c2ecf20Sopenharmony_ci if (MptEvHandlers[cb_idx]) { 77728c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 77738c2ecf20Sopenharmony_ci "Routing Event to event handler #%d\n", 77748c2ecf20Sopenharmony_ci ioc->name, cb_idx)); 77758c2ecf20Sopenharmony_ci r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); 77768c2ecf20Sopenharmony_ci handlers++; 77778c2ecf20Sopenharmony_ci } 77788c2ecf20Sopenharmony_ci } 77798c2ecf20Sopenharmony_ci /* FIXME? Examine results here? */ 77808c2ecf20Sopenharmony_ci 77818c2ecf20Sopenharmony_ci /* 77828c2ecf20Sopenharmony_ci * If needed, send (a single) EventAck. 77838c2ecf20Sopenharmony_ci */ 77848c2ecf20Sopenharmony_ci if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) { 77858c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT 77868c2ecf20Sopenharmony_ci "EventAck required\n",ioc->name)); 77878c2ecf20Sopenharmony_ci if ((ii = SendEventAck(ioc, pEventReply)) != 0) { 77888c2ecf20Sopenharmony_ci devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SendEventAck returned %d\n", 77898c2ecf20Sopenharmony_ci ioc->name, ii)); 77908c2ecf20Sopenharmony_ci } 77918c2ecf20Sopenharmony_ci } 77928c2ecf20Sopenharmony_ci 77938c2ecf20Sopenharmony_ci *evHandlers = handlers; 77948c2ecf20Sopenharmony_ci return r; 77958c2ecf20Sopenharmony_ci} 77968c2ecf20Sopenharmony_ci 77978c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 77988c2ecf20Sopenharmony_ci/** 77998c2ecf20Sopenharmony_ci * mpt_fc_log_info - Log information returned from Fibre Channel IOC. 78008c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 78018c2ecf20Sopenharmony_ci * @log_info: U32 LogInfo reply word from the IOC 78028c2ecf20Sopenharmony_ci * 78038c2ecf20Sopenharmony_ci * Refer to lsi/mpi_log_fc.h. 78048c2ecf20Sopenharmony_ci */ 78058c2ecf20Sopenharmony_cistatic void 78068c2ecf20Sopenharmony_cimpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info) 78078c2ecf20Sopenharmony_ci{ 78088c2ecf20Sopenharmony_ci char *desc = "unknown"; 78098c2ecf20Sopenharmony_ci 78108c2ecf20Sopenharmony_ci switch (log_info & 0xFF000000) { 78118c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_INIT_BASE: 78128c2ecf20Sopenharmony_ci desc = "FCP Initiator"; 78138c2ecf20Sopenharmony_ci break; 78148c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_TARGET_BASE: 78158c2ecf20Sopenharmony_ci desc = "FCP Target"; 78168c2ecf20Sopenharmony_ci break; 78178c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_LAN_BASE: 78188c2ecf20Sopenharmony_ci desc = "LAN"; 78198c2ecf20Sopenharmony_ci break; 78208c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_MSG_BASE: 78218c2ecf20Sopenharmony_ci desc = "MPI Message Layer"; 78228c2ecf20Sopenharmony_ci break; 78238c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_LINK_BASE: 78248c2ecf20Sopenharmony_ci desc = "FC Link"; 78258c2ecf20Sopenharmony_ci break; 78268c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_CTX_BASE: 78278c2ecf20Sopenharmony_ci desc = "Context Manager"; 78288c2ecf20Sopenharmony_ci break; 78298c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET: 78308c2ecf20Sopenharmony_ci desc = "Invalid Field Offset"; 78318c2ecf20Sopenharmony_ci break; 78328c2ecf20Sopenharmony_ci case MPI_IOCLOGINFO_FC_STATE_CHANGE: 78338c2ecf20Sopenharmony_ci desc = "State Change Info"; 78348c2ecf20Sopenharmony_ci break; 78358c2ecf20Sopenharmony_ci } 78368c2ecf20Sopenharmony_ci 78378c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubClass={%s}, Value=(0x%06x)\n", 78388c2ecf20Sopenharmony_ci ioc->name, log_info, desc, (log_info & 0xFFFFFF)); 78398c2ecf20Sopenharmony_ci} 78408c2ecf20Sopenharmony_ci 78418c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 78428c2ecf20Sopenharmony_ci/** 78438c2ecf20Sopenharmony_ci * mpt_spi_log_info - Log information returned from SCSI Parallel IOC. 78448c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 78458c2ecf20Sopenharmony_ci * @log_info: U32 LogInfo word from the IOC 78468c2ecf20Sopenharmony_ci * 78478c2ecf20Sopenharmony_ci * Refer to lsi/sp_log.h. 78488c2ecf20Sopenharmony_ci */ 78498c2ecf20Sopenharmony_cistatic void 78508c2ecf20Sopenharmony_cimpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) 78518c2ecf20Sopenharmony_ci{ 78528c2ecf20Sopenharmony_ci u32 info = log_info & 0x00FF0000; 78538c2ecf20Sopenharmony_ci char *desc = "unknown"; 78548c2ecf20Sopenharmony_ci 78558c2ecf20Sopenharmony_ci switch (info) { 78568c2ecf20Sopenharmony_ci case 0x00010000: 78578c2ecf20Sopenharmony_ci desc = "bug! MID not found"; 78588c2ecf20Sopenharmony_ci break; 78598c2ecf20Sopenharmony_ci 78608c2ecf20Sopenharmony_ci case 0x00020000: 78618c2ecf20Sopenharmony_ci desc = "Parity Error"; 78628c2ecf20Sopenharmony_ci break; 78638c2ecf20Sopenharmony_ci 78648c2ecf20Sopenharmony_ci case 0x00030000: 78658c2ecf20Sopenharmony_ci desc = "ASYNC Outbound Overrun"; 78668c2ecf20Sopenharmony_ci break; 78678c2ecf20Sopenharmony_ci 78688c2ecf20Sopenharmony_ci case 0x00040000: 78698c2ecf20Sopenharmony_ci desc = "SYNC Offset Error"; 78708c2ecf20Sopenharmony_ci break; 78718c2ecf20Sopenharmony_ci 78728c2ecf20Sopenharmony_ci case 0x00050000: 78738c2ecf20Sopenharmony_ci desc = "BM Change"; 78748c2ecf20Sopenharmony_ci break; 78758c2ecf20Sopenharmony_ci 78768c2ecf20Sopenharmony_ci case 0x00060000: 78778c2ecf20Sopenharmony_ci desc = "Msg In Overflow"; 78788c2ecf20Sopenharmony_ci break; 78798c2ecf20Sopenharmony_ci 78808c2ecf20Sopenharmony_ci case 0x00070000: 78818c2ecf20Sopenharmony_ci desc = "DMA Error"; 78828c2ecf20Sopenharmony_ci break; 78838c2ecf20Sopenharmony_ci 78848c2ecf20Sopenharmony_ci case 0x00080000: 78858c2ecf20Sopenharmony_ci desc = "Outbound DMA Overrun"; 78868c2ecf20Sopenharmony_ci break; 78878c2ecf20Sopenharmony_ci 78888c2ecf20Sopenharmony_ci case 0x00090000: 78898c2ecf20Sopenharmony_ci desc = "Task Management"; 78908c2ecf20Sopenharmony_ci break; 78918c2ecf20Sopenharmony_ci 78928c2ecf20Sopenharmony_ci case 0x000A0000: 78938c2ecf20Sopenharmony_ci desc = "Device Problem"; 78948c2ecf20Sopenharmony_ci break; 78958c2ecf20Sopenharmony_ci 78968c2ecf20Sopenharmony_ci case 0x000B0000: 78978c2ecf20Sopenharmony_ci desc = "Invalid Phase Change"; 78988c2ecf20Sopenharmony_ci break; 78998c2ecf20Sopenharmony_ci 79008c2ecf20Sopenharmony_ci case 0x000C0000: 79018c2ecf20Sopenharmony_ci desc = "Untagged Table Size"; 79028c2ecf20Sopenharmony_ci break; 79038c2ecf20Sopenharmony_ci 79048c2ecf20Sopenharmony_ci } 79058c2ecf20Sopenharmony_ci 79068c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); 79078c2ecf20Sopenharmony_ci} 79088c2ecf20Sopenharmony_ci 79098c2ecf20Sopenharmony_ci/* strings for sas loginfo */ 79108c2ecf20Sopenharmony_ci static char *originator_str[] = { 79118c2ecf20Sopenharmony_ci "IOP", /* 00h */ 79128c2ecf20Sopenharmony_ci "PL", /* 01h */ 79138c2ecf20Sopenharmony_ci "IR" /* 02h */ 79148c2ecf20Sopenharmony_ci }; 79158c2ecf20Sopenharmony_ci static char *iop_code_str[] = { 79168c2ecf20Sopenharmony_ci NULL, /* 00h */ 79178c2ecf20Sopenharmony_ci "Invalid SAS Address", /* 01h */ 79188c2ecf20Sopenharmony_ci NULL, /* 02h */ 79198c2ecf20Sopenharmony_ci "Invalid Page", /* 03h */ 79208c2ecf20Sopenharmony_ci "Diag Message Error", /* 04h */ 79218c2ecf20Sopenharmony_ci "Task Terminated", /* 05h */ 79228c2ecf20Sopenharmony_ci "Enclosure Management", /* 06h */ 79238c2ecf20Sopenharmony_ci "Target Mode" /* 07h */ 79248c2ecf20Sopenharmony_ci }; 79258c2ecf20Sopenharmony_ci static char *pl_code_str[] = { 79268c2ecf20Sopenharmony_ci NULL, /* 00h */ 79278c2ecf20Sopenharmony_ci "Open Failure", /* 01h */ 79288c2ecf20Sopenharmony_ci "Invalid Scatter Gather List", /* 02h */ 79298c2ecf20Sopenharmony_ci "Wrong Relative Offset or Frame Length", /* 03h */ 79308c2ecf20Sopenharmony_ci "Frame Transfer Error", /* 04h */ 79318c2ecf20Sopenharmony_ci "Transmit Frame Connected Low", /* 05h */ 79328c2ecf20Sopenharmony_ci "SATA Non-NCQ RW Error Bit Set", /* 06h */ 79338c2ecf20Sopenharmony_ci "SATA Read Log Receive Data Error", /* 07h */ 79348c2ecf20Sopenharmony_ci "SATA NCQ Fail All Commands After Error", /* 08h */ 79358c2ecf20Sopenharmony_ci "SATA Error in Receive Set Device Bit FIS", /* 09h */ 79368c2ecf20Sopenharmony_ci "Receive Frame Invalid Message", /* 0Ah */ 79378c2ecf20Sopenharmony_ci "Receive Context Message Valid Error", /* 0Bh */ 79388c2ecf20Sopenharmony_ci "Receive Frame Current Frame Error", /* 0Ch */ 79398c2ecf20Sopenharmony_ci "SATA Link Down", /* 0Dh */ 79408c2ecf20Sopenharmony_ci "Discovery SATA Init W IOS", /* 0Eh */ 79418c2ecf20Sopenharmony_ci "Config Invalid Page", /* 0Fh */ 79428c2ecf20Sopenharmony_ci "Discovery SATA Init Timeout", /* 10h */ 79438c2ecf20Sopenharmony_ci "Reset", /* 11h */ 79448c2ecf20Sopenharmony_ci "Abort", /* 12h */ 79458c2ecf20Sopenharmony_ci "IO Not Yet Executed", /* 13h */ 79468c2ecf20Sopenharmony_ci "IO Executed", /* 14h */ 79478c2ecf20Sopenharmony_ci "Persistent Reservation Out Not Affiliation " 79488c2ecf20Sopenharmony_ci "Owner", /* 15h */ 79498c2ecf20Sopenharmony_ci "Open Transmit DMA Abort", /* 16h */ 79508c2ecf20Sopenharmony_ci "IO Device Missing Delay Retry", /* 17h */ 79518c2ecf20Sopenharmony_ci "IO Cancelled Due to Receive Error", /* 18h */ 79528c2ecf20Sopenharmony_ci NULL, /* 19h */ 79538c2ecf20Sopenharmony_ci NULL, /* 1Ah */ 79548c2ecf20Sopenharmony_ci NULL, /* 1Bh */ 79558c2ecf20Sopenharmony_ci NULL, /* 1Ch */ 79568c2ecf20Sopenharmony_ci NULL, /* 1Dh */ 79578c2ecf20Sopenharmony_ci NULL, /* 1Eh */ 79588c2ecf20Sopenharmony_ci NULL, /* 1Fh */ 79598c2ecf20Sopenharmony_ci "Enclosure Management" /* 20h */ 79608c2ecf20Sopenharmony_ci }; 79618c2ecf20Sopenharmony_ci static char *ir_code_str[] = { 79628c2ecf20Sopenharmony_ci "Raid Action Error", /* 00h */ 79638c2ecf20Sopenharmony_ci NULL, /* 00h */ 79648c2ecf20Sopenharmony_ci NULL, /* 01h */ 79658c2ecf20Sopenharmony_ci NULL, /* 02h */ 79668c2ecf20Sopenharmony_ci NULL, /* 03h */ 79678c2ecf20Sopenharmony_ci NULL, /* 04h */ 79688c2ecf20Sopenharmony_ci NULL, /* 05h */ 79698c2ecf20Sopenharmony_ci NULL, /* 06h */ 79708c2ecf20Sopenharmony_ci NULL /* 07h */ 79718c2ecf20Sopenharmony_ci }; 79728c2ecf20Sopenharmony_ci static char *raid_sub_code_str[] = { 79738c2ecf20Sopenharmony_ci NULL, /* 00h */ 79748c2ecf20Sopenharmony_ci "Volume Creation Failed: Data Passed too " 79758c2ecf20Sopenharmony_ci "Large", /* 01h */ 79768c2ecf20Sopenharmony_ci "Volume Creation Failed: Duplicate Volumes " 79778c2ecf20Sopenharmony_ci "Attempted", /* 02h */ 79788c2ecf20Sopenharmony_ci "Volume Creation Failed: Max Number " 79798c2ecf20Sopenharmony_ci "Supported Volumes Exceeded", /* 03h */ 79808c2ecf20Sopenharmony_ci "Volume Creation Failed: DMA Error", /* 04h */ 79818c2ecf20Sopenharmony_ci "Volume Creation Failed: Invalid Volume Type", /* 05h */ 79828c2ecf20Sopenharmony_ci "Volume Creation Failed: Error Reading " 79838c2ecf20Sopenharmony_ci "MFG Page 4", /* 06h */ 79848c2ecf20Sopenharmony_ci "Volume Creation Failed: Creating Internal " 79858c2ecf20Sopenharmony_ci "Structures", /* 07h */ 79868c2ecf20Sopenharmony_ci NULL, /* 08h */ 79878c2ecf20Sopenharmony_ci NULL, /* 09h */ 79888c2ecf20Sopenharmony_ci NULL, /* 0Ah */ 79898c2ecf20Sopenharmony_ci NULL, /* 0Bh */ 79908c2ecf20Sopenharmony_ci NULL, /* 0Ch */ 79918c2ecf20Sopenharmony_ci NULL, /* 0Dh */ 79928c2ecf20Sopenharmony_ci NULL, /* 0Eh */ 79938c2ecf20Sopenharmony_ci NULL, /* 0Fh */ 79948c2ecf20Sopenharmony_ci "Activation failed: Already Active Volume", /* 10h */ 79958c2ecf20Sopenharmony_ci "Activation failed: Unsupported Volume Type", /* 11h */ 79968c2ecf20Sopenharmony_ci "Activation failed: Too Many Active Volumes", /* 12h */ 79978c2ecf20Sopenharmony_ci "Activation failed: Volume ID in Use", /* 13h */ 79988c2ecf20Sopenharmony_ci "Activation failed: Reported Failure", /* 14h */ 79998c2ecf20Sopenharmony_ci "Activation failed: Importing a Volume", /* 15h */ 80008c2ecf20Sopenharmony_ci NULL, /* 16h */ 80018c2ecf20Sopenharmony_ci NULL, /* 17h */ 80028c2ecf20Sopenharmony_ci NULL, /* 18h */ 80038c2ecf20Sopenharmony_ci NULL, /* 19h */ 80048c2ecf20Sopenharmony_ci NULL, /* 1Ah */ 80058c2ecf20Sopenharmony_ci NULL, /* 1Bh */ 80068c2ecf20Sopenharmony_ci NULL, /* 1Ch */ 80078c2ecf20Sopenharmony_ci NULL, /* 1Dh */ 80088c2ecf20Sopenharmony_ci NULL, /* 1Eh */ 80098c2ecf20Sopenharmony_ci NULL, /* 1Fh */ 80108c2ecf20Sopenharmony_ci "Phys Disk failed: Too Many Phys Disks", /* 20h */ 80118c2ecf20Sopenharmony_ci "Phys Disk failed: Data Passed too Large", /* 21h */ 80128c2ecf20Sopenharmony_ci "Phys Disk failed: DMA Error", /* 22h */ 80138c2ecf20Sopenharmony_ci "Phys Disk failed: Invalid <channel:id>", /* 23h */ 80148c2ecf20Sopenharmony_ci "Phys Disk failed: Creating Phys Disk Config " 80158c2ecf20Sopenharmony_ci "Page", /* 24h */ 80168c2ecf20Sopenharmony_ci NULL, /* 25h */ 80178c2ecf20Sopenharmony_ci NULL, /* 26h */ 80188c2ecf20Sopenharmony_ci NULL, /* 27h */ 80198c2ecf20Sopenharmony_ci NULL, /* 28h */ 80208c2ecf20Sopenharmony_ci NULL, /* 29h */ 80218c2ecf20Sopenharmony_ci NULL, /* 2Ah */ 80228c2ecf20Sopenharmony_ci NULL, /* 2Bh */ 80238c2ecf20Sopenharmony_ci NULL, /* 2Ch */ 80248c2ecf20Sopenharmony_ci NULL, /* 2Dh */ 80258c2ecf20Sopenharmony_ci NULL, /* 2Eh */ 80268c2ecf20Sopenharmony_ci NULL, /* 2Fh */ 80278c2ecf20Sopenharmony_ci "Compatibility Error: IR Disabled", /* 30h */ 80288c2ecf20Sopenharmony_ci "Compatibility Error: Inquiry Command Failed", /* 31h */ 80298c2ecf20Sopenharmony_ci "Compatibility Error: Device not Direct Access " 80308c2ecf20Sopenharmony_ci "Device ", /* 32h */ 80318c2ecf20Sopenharmony_ci "Compatibility Error: Removable Device Found", /* 33h */ 80328c2ecf20Sopenharmony_ci "Compatibility Error: Device SCSI Version not " 80338c2ecf20Sopenharmony_ci "2 or Higher", /* 34h */ 80348c2ecf20Sopenharmony_ci "Compatibility Error: SATA Device, 48 BIT LBA " 80358c2ecf20Sopenharmony_ci "not Supported", /* 35h */ 80368c2ecf20Sopenharmony_ci "Compatibility Error: Device doesn't have " 80378c2ecf20Sopenharmony_ci "512 Byte Block Sizes", /* 36h */ 80388c2ecf20Sopenharmony_ci "Compatibility Error: Volume Type Check Failed", /* 37h */ 80398c2ecf20Sopenharmony_ci "Compatibility Error: Volume Type is " 80408c2ecf20Sopenharmony_ci "Unsupported by FW", /* 38h */ 80418c2ecf20Sopenharmony_ci "Compatibility Error: Disk Drive too Small for " 80428c2ecf20Sopenharmony_ci "use in Volume", /* 39h */ 80438c2ecf20Sopenharmony_ci "Compatibility Error: Phys Disk for Create " 80448c2ecf20Sopenharmony_ci "Volume not Found", /* 3Ah */ 80458c2ecf20Sopenharmony_ci "Compatibility Error: Too Many or too Few " 80468c2ecf20Sopenharmony_ci "Disks for Volume Type", /* 3Bh */ 80478c2ecf20Sopenharmony_ci "Compatibility Error: Disk stripe Sizes " 80488c2ecf20Sopenharmony_ci "Must be 64KB", /* 3Ch */ 80498c2ecf20Sopenharmony_ci "Compatibility Error: IME Size Limited to < 2TB", /* 3Dh */ 80508c2ecf20Sopenharmony_ci }; 80518c2ecf20Sopenharmony_ci 80528c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 80538c2ecf20Sopenharmony_ci/** 80548c2ecf20Sopenharmony_ci * mpt_sas_log_info - Log information returned from SAS IOC. 80558c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 80568c2ecf20Sopenharmony_ci * @log_info: U32 LogInfo reply word from the IOC 80578c2ecf20Sopenharmony_ci * @cb_idx: callback function's handle 80588c2ecf20Sopenharmony_ci * 80598c2ecf20Sopenharmony_ci * Refer to lsi/mpi_log_sas.h. 80608c2ecf20Sopenharmony_ci **/ 80618c2ecf20Sopenharmony_cistatic void 80628c2ecf20Sopenharmony_cimpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info, u8 cb_idx) 80638c2ecf20Sopenharmony_ci{ 80648c2ecf20Sopenharmony_ci union loginfo_type { 80658c2ecf20Sopenharmony_ci u32 loginfo; 80668c2ecf20Sopenharmony_ci struct { 80678c2ecf20Sopenharmony_ci u32 subcode:16; 80688c2ecf20Sopenharmony_ci u32 code:8; 80698c2ecf20Sopenharmony_ci u32 originator:4; 80708c2ecf20Sopenharmony_ci u32 bus_type:4; 80718c2ecf20Sopenharmony_ci } dw; 80728c2ecf20Sopenharmony_ci }; 80738c2ecf20Sopenharmony_ci union loginfo_type sas_loginfo; 80748c2ecf20Sopenharmony_ci char *originator_desc = NULL; 80758c2ecf20Sopenharmony_ci char *code_desc = NULL; 80768c2ecf20Sopenharmony_ci char *sub_code_desc = NULL; 80778c2ecf20Sopenharmony_ci 80788c2ecf20Sopenharmony_ci sas_loginfo.loginfo = log_info; 80798c2ecf20Sopenharmony_ci if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) && 80808c2ecf20Sopenharmony_ci (sas_loginfo.dw.originator < ARRAY_SIZE(originator_str))) 80818c2ecf20Sopenharmony_ci return; 80828c2ecf20Sopenharmony_ci 80838c2ecf20Sopenharmony_ci originator_desc = originator_str[sas_loginfo.dw.originator]; 80848c2ecf20Sopenharmony_ci 80858c2ecf20Sopenharmony_ci switch (sas_loginfo.dw.originator) { 80868c2ecf20Sopenharmony_ci 80878c2ecf20Sopenharmony_ci case 0: /* IOP */ 80888c2ecf20Sopenharmony_ci if (sas_loginfo.dw.code < 80898c2ecf20Sopenharmony_ci ARRAY_SIZE(iop_code_str)) 80908c2ecf20Sopenharmony_ci code_desc = iop_code_str[sas_loginfo.dw.code]; 80918c2ecf20Sopenharmony_ci break; 80928c2ecf20Sopenharmony_ci case 1: /* PL */ 80938c2ecf20Sopenharmony_ci if (sas_loginfo.dw.code < 80948c2ecf20Sopenharmony_ci ARRAY_SIZE(pl_code_str)) 80958c2ecf20Sopenharmony_ci code_desc = pl_code_str[sas_loginfo.dw.code]; 80968c2ecf20Sopenharmony_ci break; 80978c2ecf20Sopenharmony_ci case 2: /* IR */ 80988c2ecf20Sopenharmony_ci if (sas_loginfo.dw.code >= 80998c2ecf20Sopenharmony_ci ARRAY_SIZE(ir_code_str)) 81008c2ecf20Sopenharmony_ci break; 81018c2ecf20Sopenharmony_ci code_desc = ir_code_str[sas_loginfo.dw.code]; 81028c2ecf20Sopenharmony_ci if (sas_loginfo.dw.subcode >= 81038c2ecf20Sopenharmony_ci ARRAY_SIZE(raid_sub_code_str)) 81048c2ecf20Sopenharmony_ci break; 81058c2ecf20Sopenharmony_ci if (sas_loginfo.dw.code == 0) 81068c2ecf20Sopenharmony_ci sub_code_desc = 81078c2ecf20Sopenharmony_ci raid_sub_code_str[sas_loginfo.dw.subcode]; 81088c2ecf20Sopenharmony_ci break; 81098c2ecf20Sopenharmony_ci default: 81108c2ecf20Sopenharmony_ci return; 81118c2ecf20Sopenharmony_ci } 81128c2ecf20Sopenharmony_ci 81138c2ecf20Sopenharmony_ci if (sub_code_desc != NULL) 81148c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT 81158c2ecf20Sopenharmony_ci "LogInfo(0x%08x): Originator={%s}, Code={%s}," 81168c2ecf20Sopenharmony_ci " SubCode={%s} cb_idx %s\n", 81178c2ecf20Sopenharmony_ci ioc->name, log_info, originator_desc, code_desc, 81188c2ecf20Sopenharmony_ci sub_code_desc, MptCallbacksName[cb_idx]); 81198c2ecf20Sopenharmony_ci else if (code_desc != NULL) 81208c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT 81218c2ecf20Sopenharmony_ci "LogInfo(0x%08x): Originator={%s}, Code={%s}," 81228c2ecf20Sopenharmony_ci " SubCode(0x%04x) cb_idx %s\n", 81238c2ecf20Sopenharmony_ci ioc->name, log_info, originator_desc, code_desc, 81248c2ecf20Sopenharmony_ci sas_loginfo.dw.subcode, MptCallbacksName[cb_idx]); 81258c2ecf20Sopenharmony_ci else 81268c2ecf20Sopenharmony_ci printk(MYIOC_s_INFO_FMT 81278c2ecf20Sopenharmony_ci "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," 81288c2ecf20Sopenharmony_ci " SubCode(0x%04x) cb_idx %s\n", 81298c2ecf20Sopenharmony_ci ioc->name, log_info, originator_desc, 81308c2ecf20Sopenharmony_ci sas_loginfo.dw.code, sas_loginfo.dw.subcode, 81318c2ecf20Sopenharmony_ci MptCallbacksName[cb_idx]); 81328c2ecf20Sopenharmony_ci} 81338c2ecf20Sopenharmony_ci 81348c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 81358c2ecf20Sopenharmony_ci/** 81368c2ecf20Sopenharmony_ci * mpt_iocstatus_info_config - IOCSTATUS information for config pages 81378c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 81388c2ecf20Sopenharmony_ci * @ioc_status: U32 IOCStatus word from IOC 81398c2ecf20Sopenharmony_ci * @mf: Pointer to MPT request frame 81408c2ecf20Sopenharmony_ci * 81418c2ecf20Sopenharmony_ci * Refer to lsi/mpi.h. 81428c2ecf20Sopenharmony_ci **/ 81438c2ecf20Sopenharmony_cistatic void 81448c2ecf20Sopenharmony_cimpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) 81458c2ecf20Sopenharmony_ci{ 81468c2ecf20Sopenharmony_ci Config_t *pReq = (Config_t *)mf; 81478c2ecf20Sopenharmony_ci char extend_desc[EVENT_DESCR_STR_SZ]; 81488c2ecf20Sopenharmony_ci char *desc = NULL; 81498c2ecf20Sopenharmony_ci u32 form; 81508c2ecf20Sopenharmony_ci u8 page_type; 81518c2ecf20Sopenharmony_ci 81528c2ecf20Sopenharmony_ci if (pReq->Header.PageType == MPI_CONFIG_PAGETYPE_EXTENDED) 81538c2ecf20Sopenharmony_ci page_type = pReq->ExtPageType; 81548c2ecf20Sopenharmony_ci else 81558c2ecf20Sopenharmony_ci page_type = pReq->Header.PageType; 81568c2ecf20Sopenharmony_ci 81578c2ecf20Sopenharmony_ci /* 81588c2ecf20Sopenharmony_ci * ignore invalid page messages for GET_NEXT_HANDLE 81598c2ecf20Sopenharmony_ci */ 81608c2ecf20Sopenharmony_ci form = le32_to_cpu(pReq->PageAddress); 81618c2ecf20Sopenharmony_ci if (ioc_status == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) { 81628c2ecf20Sopenharmony_ci if (page_type == MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE || 81638c2ecf20Sopenharmony_ci page_type == MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER || 81648c2ecf20Sopenharmony_ci page_type == MPI_CONFIG_EXTPAGETYPE_ENCLOSURE) { 81658c2ecf20Sopenharmony_ci if ((form >> MPI_SAS_DEVICE_PGAD_FORM_SHIFT) == 81668c2ecf20Sopenharmony_ci MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE) 81678c2ecf20Sopenharmony_ci return; 81688c2ecf20Sopenharmony_ci } 81698c2ecf20Sopenharmony_ci if (page_type == MPI_CONFIG_PAGETYPE_FC_DEVICE) 81708c2ecf20Sopenharmony_ci if ((form & MPI_FC_DEVICE_PGAD_FORM_MASK) == 81718c2ecf20Sopenharmony_ci MPI_FC_DEVICE_PGAD_FORM_NEXT_DID) 81728c2ecf20Sopenharmony_ci return; 81738c2ecf20Sopenharmony_ci } 81748c2ecf20Sopenharmony_ci 81758c2ecf20Sopenharmony_ci snprintf(extend_desc, EVENT_DESCR_STR_SZ, 81768c2ecf20Sopenharmony_ci "type=%02Xh, page=%02Xh, action=%02Xh, form=%08Xh", 81778c2ecf20Sopenharmony_ci page_type, pReq->Header.PageNumber, pReq->Action, form); 81788c2ecf20Sopenharmony_ci 81798c2ecf20Sopenharmony_ci switch (ioc_status) { 81808c2ecf20Sopenharmony_ci 81818c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ 81828c2ecf20Sopenharmony_ci desc = "Config Page Invalid Action"; 81838c2ecf20Sopenharmony_ci break; 81848c2ecf20Sopenharmony_ci 81858c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ 81868c2ecf20Sopenharmony_ci desc = "Config Page Invalid Type"; 81878c2ecf20Sopenharmony_ci break; 81888c2ecf20Sopenharmony_ci 81898c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ 81908c2ecf20Sopenharmony_ci desc = "Config Page Invalid Page"; 81918c2ecf20Sopenharmony_ci break; 81928c2ecf20Sopenharmony_ci 81938c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ 81948c2ecf20Sopenharmony_ci desc = "Config Page Invalid Data"; 81958c2ecf20Sopenharmony_ci break; 81968c2ecf20Sopenharmony_ci 81978c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ 81988c2ecf20Sopenharmony_ci desc = "Config Page No Defaults"; 81998c2ecf20Sopenharmony_ci break; 82008c2ecf20Sopenharmony_ci 82018c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ 82028c2ecf20Sopenharmony_ci desc = "Config Page Can't Commit"; 82038c2ecf20Sopenharmony_ci break; 82048c2ecf20Sopenharmony_ci } 82058c2ecf20Sopenharmony_ci 82068c2ecf20Sopenharmony_ci if (!desc) 82078c2ecf20Sopenharmony_ci return; 82088c2ecf20Sopenharmony_ci 82098c2ecf20Sopenharmony_ci dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n", 82108c2ecf20Sopenharmony_ci ioc->name, ioc_status, desc, extend_desc)); 82118c2ecf20Sopenharmony_ci} 82128c2ecf20Sopenharmony_ci 82138c2ecf20Sopenharmony_ci/** 82148c2ecf20Sopenharmony_ci * mpt_iocstatus_info - IOCSTATUS information returned from IOC. 82158c2ecf20Sopenharmony_ci * @ioc: Pointer to MPT_ADAPTER structure 82168c2ecf20Sopenharmony_ci * @ioc_status: U32 IOCStatus word from IOC 82178c2ecf20Sopenharmony_ci * @mf: Pointer to MPT request frame 82188c2ecf20Sopenharmony_ci * 82198c2ecf20Sopenharmony_ci * Refer to lsi/mpi.h. 82208c2ecf20Sopenharmony_ci **/ 82218c2ecf20Sopenharmony_cistatic void 82228c2ecf20Sopenharmony_cimpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) 82238c2ecf20Sopenharmony_ci{ 82248c2ecf20Sopenharmony_ci u32 status = ioc_status & MPI_IOCSTATUS_MASK; 82258c2ecf20Sopenharmony_ci char *desc = NULL; 82268c2ecf20Sopenharmony_ci 82278c2ecf20Sopenharmony_ci switch (status) { 82288c2ecf20Sopenharmony_ci 82298c2ecf20Sopenharmony_ci/****************************************************************************/ 82308c2ecf20Sopenharmony_ci/* Common IOCStatus values for all replies */ 82318c2ecf20Sopenharmony_ci/****************************************************************************/ 82328c2ecf20Sopenharmony_ci 82338c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_INVALID_FUNCTION: /* 0x0001 */ 82348c2ecf20Sopenharmony_ci desc = "Invalid Function"; 82358c2ecf20Sopenharmony_ci break; 82368c2ecf20Sopenharmony_ci 82378c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_BUSY: /* 0x0002 */ 82388c2ecf20Sopenharmony_ci desc = "Busy"; 82398c2ecf20Sopenharmony_ci break; 82408c2ecf20Sopenharmony_ci 82418c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_INVALID_SGL: /* 0x0003 */ 82428c2ecf20Sopenharmony_ci desc = "Invalid SGL"; 82438c2ecf20Sopenharmony_ci break; 82448c2ecf20Sopenharmony_ci 82458c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_INTERNAL_ERROR: /* 0x0004 */ 82468c2ecf20Sopenharmony_ci desc = "Internal Error"; 82478c2ecf20Sopenharmony_ci break; 82488c2ecf20Sopenharmony_ci 82498c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_RESERVED: /* 0x0005 */ 82508c2ecf20Sopenharmony_ci desc = "Reserved"; 82518c2ecf20Sopenharmony_ci break; 82528c2ecf20Sopenharmony_ci 82538c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: /* 0x0006 */ 82548c2ecf20Sopenharmony_ci desc = "Insufficient Resources"; 82558c2ecf20Sopenharmony_ci break; 82568c2ecf20Sopenharmony_ci 82578c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_INVALID_FIELD: /* 0x0007 */ 82588c2ecf20Sopenharmony_ci desc = "Invalid Field"; 82598c2ecf20Sopenharmony_ci break; 82608c2ecf20Sopenharmony_ci 82618c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_INVALID_STATE: /* 0x0008 */ 82628c2ecf20Sopenharmony_ci desc = "Invalid State"; 82638c2ecf20Sopenharmony_ci break; 82648c2ecf20Sopenharmony_ci 82658c2ecf20Sopenharmony_ci/****************************************************************************/ 82668c2ecf20Sopenharmony_ci/* Config IOCStatus values */ 82678c2ecf20Sopenharmony_ci/****************************************************************************/ 82688c2ecf20Sopenharmony_ci 82698c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_ACTION: /* 0x0020 */ 82708c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_TYPE: /* 0x0021 */ 82718c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_PAGE: /* 0x0022 */ 82728c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_INVALID_DATA: /* 0x0023 */ 82738c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_NO_DEFAULTS: /* 0x0024 */ 82748c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_CONFIG_CANT_COMMIT: /* 0x0025 */ 82758c2ecf20Sopenharmony_ci mpt_iocstatus_info_config(ioc, status, mf); 82768c2ecf20Sopenharmony_ci break; 82778c2ecf20Sopenharmony_ci 82788c2ecf20Sopenharmony_ci/****************************************************************************/ 82798c2ecf20Sopenharmony_ci/* SCSIIO Reply (SPI, FCP, SAS) initiator values */ 82808c2ecf20Sopenharmony_ci/* */ 82818c2ecf20Sopenharmony_ci/* Look at mptscsih_iocstatus_info_scsiio in mptscsih.c */ 82828c2ecf20Sopenharmony_ci/* */ 82838c2ecf20Sopenharmony_ci/****************************************************************************/ 82848c2ecf20Sopenharmony_ci 82858c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ 82868c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ 82878c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_INVALID_BUS: /* 0x0041 */ 82888c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: /* 0x0042 */ 82898c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ 82908c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ 82918c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ 82928c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ 82938c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ 82948c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ 82958c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: /* 0x004A */ 82968c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ 82978c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ 82988c2ecf20Sopenharmony_ci break; 82998c2ecf20Sopenharmony_ci 83008c2ecf20Sopenharmony_ci/****************************************************************************/ 83018c2ecf20Sopenharmony_ci/* SCSI Target values */ 83028c2ecf20Sopenharmony_ci/****************************************************************************/ 83038c2ecf20Sopenharmony_ci 83048c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_PRIORITY_IO: /* 0x0060 */ 83058c2ecf20Sopenharmony_ci desc = "Target: Priority IO"; 83068c2ecf20Sopenharmony_ci break; 83078c2ecf20Sopenharmony_ci 83088c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_INVALID_PORT: /* 0x0061 */ 83098c2ecf20Sopenharmony_ci desc = "Target: Invalid Port"; 83108c2ecf20Sopenharmony_ci break; 83118c2ecf20Sopenharmony_ci 83128c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX: /* 0x0062 */ 83138c2ecf20Sopenharmony_ci desc = "Target Invalid IO Index:"; 83148c2ecf20Sopenharmony_ci break; 83158c2ecf20Sopenharmony_ci 83168c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_ABORTED: /* 0x0063 */ 83178c2ecf20Sopenharmony_ci desc = "Target: Aborted"; 83188c2ecf20Sopenharmony_ci break; 83198c2ecf20Sopenharmony_ci 83208c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: /* 0x0064 */ 83218c2ecf20Sopenharmony_ci desc = "Target: No Conn Retryable"; 83228c2ecf20Sopenharmony_ci break; 83238c2ecf20Sopenharmony_ci 83248c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_NO_CONNECTION: /* 0x0065 */ 83258c2ecf20Sopenharmony_ci desc = "Target: No Connection"; 83268c2ecf20Sopenharmony_ci break; 83278c2ecf20Sopenharmony_ci 83288c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: /* 0x006A */ 83298c2ecf20Sopenharmony_ci desc = "Target: Transfer Count Mismatch"; 83308c2ecf20Sopenharmony_ci break; 83318c2ecf20Sopenharmony_ci 83328c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT: /* 0x006B */ 83338c2ecf20Sopenharmony_ci desc = "Target: STS Data not Sent"; 83348c2ecf20Sopenharmony_ci break; 83358c2ecf20Sopenharmony_ci 83368c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: /* 0x006D */ 83378c2ecf20Sopenharmony_ci desc = "Target: Data Offset Error"; 83388c2ecf20Sopenharmony_ci break; 83398c2ecf20Sopenharmony_ci 83408c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: /* 0x006E */ 83418c2ecf20Sopenharmony_ci desc = "Target: Too Much Write Data"; 83428c2ecf20Sopenharmony_ci break; 83438c2ecf20Sopenharmony_ci 83448c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_IU_TOO_SHORT: /* 0x006F */ 83458c2ecf20Sopenharmony_ci desc = "Target: IU Too Short"; 83468c2ecf20Sopenharmony_ci break; 83478c2ecf20Sopenharmony_ci 83488c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: /* 0x0070 */ 83498c2ecf20Sopenharmony_ci desc = "Target: ACK NAK Timeout"; 83508c2ecf20Sopenharmony_ci break; 83518c2ecf20Sopenharmony_ci 83528c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_TARGET_NAK_RECEIVED: /* 0x0071 */ 83538c2ecf20Sopenharmony_ci desc = "Target: Nak Received"; 83548c2ecf20Sopenharmony_ci break; 83558c2ecf20Sopenharmony_ci 83568c2ecf20Sopenharmony_ci/****************************************************************************/ 83578c2ecf20Sopenharmony_ci/* Fibre Channel Direct Access values */ 83588c2ecf20Sopenharmony_ci/****************************************************************************/ 83598c2ecf20Sopenharmony_ci 83608c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_FC_ABORTED: /* 0x0066 */ 83618c2ecf20Sopenharmony_ci desc = "FC: Aborted"; 83628c2ecf20Sopenharmony_ci break; 83638c2ecf20Sopenharmony_ci 83648c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_FC_RX_ID_INVALID: /* 0x0067 */ 83658c2ecf20Sopenharmony_ci desc = "FC: RX ID Invalid"; 83668c2ecf20Sopenharmony_ci break; 83678c2ecf20Sopenharmony_ci 83688c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_FC_DID_INVALID: /* 0x0068 */ 83698c2ecf20Sopenharmony_ci desc = "FC: DID Invalid"; 83708c2ecf20Sopenharmony_ci break; 83718c2ecf20Sopenharmony_ci 83728c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_FC_NODE_LOGGED_OUT: /* 0x0069 */ 83738c2ecf20Sopenharmony_ci desc = "FC: Node Logged Out"; 83748c2ecf20Sopenharmony_ci break; 83758c2ecf20Sopenharmony_ci 83768c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_FC_EXCHANGE_CANCELED: /* 0x006C */ 83778c2ecf20Sopenharmony_ci desc = "FC: Exchange Canceled"; 83788c2ecf20Sopenharmony_ci break; 83798c2ecf20Sopenharmony_ci 83808c2ecf20Sopenharmony_ci/****************************************************************************/ 83818c2ecf20Sopenharmony_ci/* LAN values */ 83828c2ecf20Sopenharmony_ci/****************************************************************************/ 83838c2ecf20Sopenharmony_ci 83848c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_DEVICE_NOT_FOUND: /* 0x0080 */ 83858c2ecf20Sopenharmony_ci desc = "LAN: Device not Found"; 83868c2ecf20Sopenharmony_ci break; 83878c2ecf20Sopenharmony_ci 83888c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_DEVICE_FAILURE: /* 0x0081 */ 83898c2ecf20Sopenharmony_ci desc = "LAN: Device Failure"; 83908c2ecf20Sopenharmony_ci break; 83918c2ecf20Sopenharmony_ci 83928c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_TRANSMIT_ERROR: /* 0x0082 */ 83938c2ecf20Sopenharmony_ci desc = "LAN: Transmit Error"; 83948c2ecf20Sopenharmony_ci break; 83958c2ecf20Sopenharmony_ci 83968c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: /* 0x0083 */ 83978c2ecf20Sopenharmony_ci desc = "LAN: Transmit Aborted"; 83988c2ecf20Sopenharmony_ci break; 83998c2ecf20Sopenharmony_ci 84008c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_RECEIVE_ERROR: /* 0x0084 */ 84018c2ecf20Sopenharmony_ci desc = "LAN: Receive Error"; 84028c2ecf20Sopenharmony_ci break; 84038c2ecf20Sopenharmony_ci 84048c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_RECEIVE_ABORTED: /* 0x0085 */ 84058c2ecf20Sopenharmony_ci desc = "LAN: Receive Aborted"; 84068c2ecf20Sopenharmony_ci break; 84078c2ecf20Sopenharmony_ci 84088c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_PARTIAL_PACKET: /* 0x0086 */ 84098c2ecf20Sopenharmony_ci desc = "LAN: Partial Packet"; 84108c2ecf20Sopenharmony_ci break; 84118c2ecf20Sopenharmony_ci 84128c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_LAN_CANCELED: /* 0x0087 */ 84138c2ecf20Sopenharmony_ci desc = "LAN: Canceled"; 84148c2ecf20Sopenharmony_ci break; 84158c2ecf20Sopenharmony_ci 84168c2ecf20Sopenharmony_ci/****************************************************************************/ 84178c2ecf20Sopenharmony_ci/* Serial Attached SCSI values */ 84188c2ecf20Sopenharmony_ci/****************************************************************************/ 84198c2ecf20Sopenharmony_ci 84208c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED: /* 0x0090 */ 84218c2ecf20Sopenharmony_ci desc = "SAS: SMP Request Failed"; 84228c2ecf20Sopenharmony_ci break; 84238c2ecf20Sopenharmony_ci 84248c2ecf20Sopenharmony_ci case MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN: /* 0x0090 */ 84258c2ecf20Sopenharmony_ci desc = "SAS: SMP Data Overrun"; 84268c2ecf20Sopenharmony_ci break; 84278c2ecf20Sopenharmony_ci 84288c2ecf20Sopenharmony_ci default: 84298c2ecf20Sopenharmony_ci desc = "Others"; 84308c2ecf20Sopenharmony_ci break; 84318c2ecf20Sopenharmony_ci } 84328c2ecf20Sopenharmony_ci 84338c2ecf20Sopenharmony_ci if (!desc) 84348c2ecf20Sopenharmony_ci return; 84358c2ecf20Sopenharmony_ci 84368c2ecf20Sopenharmony_ci dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n", 84378c2ecf20Sopenharmony_ci ioc->name, status, desc)); 84388c2ecf20Sopenharmony_ci} 84398c2ecf20Sopenharmony_ci 84408c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 84418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_attach); 84428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_detach); 84438c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 84448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_resume); 84458c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_suspend); 84468c2ecf20Sopenharmony_ci#endif 84478c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ioc_list); 84488c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_register); 84498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_deregister); 84508c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_event_register); 84518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_event_deregister); 84528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_reset_register); 84538c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_reset_deregister); 84548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_device_driver_register); 84558c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_device_driver_deregister); 84568c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_get_msg_frame); 84578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_put_msg_frame); 84588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_put_msg_frame_hi_pri); 84598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_free_msg_frame); 84608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_send_handshake_request); 84618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_verify_adapter); 84628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_GetIocState); 84638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_print_ioc_summary); 84648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_HardResetHandler); 84658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_config); 84668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_findImVolumes); 84678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_alloc_fw_memory); 84688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_free_fw_memory); 84698c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mptbase_sas_persist_operation); 84708c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mpt_raid_phys_disk_pg0); 84718c2ecf20Sopenharmony_ci 84728c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 84738c2ecf20Sopenharmony_ci/** 84748c2ecf20Sopenharmony_ci * fusion_init - Fusion MPT base driver initialization routine. 84758c2ecf20Sopenharmony_ci * 84768c2ecf20Sopenharmony_ci * Returns 0 for success, non-zero for failure. 84778c2ecf20Sopenharmony_ci */ 84788c2ecf20Sopenharmony_cistatic int __init 84798c2ecf20Sopenharmony_cifusion_init(void) 84808c2ecf20Sopenharmony_ci{ 84818c2ecf20Sopenharmony_ci u8 cb_idx; 84828c2ecf20Sopenharmony_ci 84838c2ecf20Sopenharmony_ci show_mptmod_ver(my_NAME, my_VERSION); 84848c2ecf20Sopenharmony_ci printk(KERN_INFO COPYRIGHT "\n"); 84858c2ecf20Sopenharmony_ci 84868c2ecf20Sopenharmony_ci for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) { 84878c2ecf20Sopenharmony_ci MptCallbacks[cb_idx] = NULL; 84888c2ecf20Sopenharmony_ci MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; 84898c2ecf20Sopenharmony_ci MptEvHandlers[cb_idx] = NULL; 84908c2ecf20Sopenharmony_ci MptResetHandlers[cb_idx] = NULL; 84918c2ecf20Sopenharmony_ci } 84928c2ecf20Sopenharmony_ci 84938c2ecf20Sopenharmony_ci /* Register ourselves (mptbase) in order to facilitate 84948c2ecf20Sopenharmony_ci * EventNotification handling. 84958c2ecf20Sopenharmony_ci */ 84968c2ecf20Sopenharmony_ci mpt_base_index = mpt_register(mptbase_reply, MPTBASE_DRIVER, 84978c2ecf20Sopenharmony_ci "mptbase_reply"); 84988c2ecf20Sopenharmony_ci 84998c2ecf20Sopenharmony_ci /* Register for hard reset handling callbacks. 85008c2ecf20Sopenharmony_ci */ 85018c2ecf20Sopenharmony_ci mpt_reset_register(mpt_base_index, mpt_ioc_reset); 85028c2ecf20Sopenharmony_ci 85038c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 85048c2ecf20Sopenharmony_ci (void) procmpt_create(); 85058c2ecf20Sopenharmony_ci#endif 85068c2ecf20Sopenharmony_ci return 0; 85078c2ecf20Sopenharmony_ci} 85088c2ecf20Sopenharmony_ci 85098c2ecf20Sopenharmony_ci/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ 85108c2ecf20Sopenharmony_ci/** 85118c2ecf20Sopenharmony_ci * fusion_exit - Perform driver unload cleanup. 85128c2ecf20Sopenharmony_ci * 85138c2ecf20Sopenharmony_ci * This routine frees all resources associated with each MPT adapter 85148c2ecf20Sopenharmony_ci * and removes all %MPT_PROCFS_MPTBASEDIR entries. 85158c2ecf20Sopenharmony_ci */ 85168c2ecf20Sopenharmony_cistatic void __exit 85178c2ecf20Sopenharmony_cifusion_exit(void) 85188c2ecf20Sopenharmony_ci{ 85198c2ecf20Sopenharmony_ci 85208c2ecf20Sopenharmony_ci mpt_reset_deregister(mpt_base_index); 85218c2ecf20Sopenharmony_ci 85228c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 85238c2ecf20Sopenharmony_ci procmpt_destroy(); 85248c2ecf20Sopenharmony_ci#endif 85258c2ecf20Sopenharmony_ci} 85268c2ecf20Sopenharmony_ci 85278c2ecf20Sopenharmony_cimodule_init(fusion_init); 85288c2ecf20Sopenharmony_cimodule_exit(fusion_exit); 8529