18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic Fibre Channel HBA Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2014 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include "qla_def.h" 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 98c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 108c2ecf20Sopenharmony_ci#include <linux/delay.h> 118c2ecf20Sopenharmony_ci#include <linux/kthread.h> 128c2ecf20Sopenharmony_ci#include <linux/mutex.h> 138c2ecf20Sopenharmony_ci#include <linux/kobject.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/blk-mq-pci.h> 168c2ecf20Sopenharmony_ci#include <linux/refcount.h> 178c2ecf20Sopenharmony_ci#include <linux/crash_dump.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <scsi/scsi_tcq.h> 208c2ecf20Sopenharmony_ci#include <scsi/scsicam.h> 218c2ecf20Sopenharmony_ci#include <scsi/scsi_transport.h> 228c2ecf20Sopenharmony_ci#include <scsi/scsi_transport_fc.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "qla_target.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* 278c2ecf20Sopenharmony_ci * Driver version 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_cichar qla2x00_version_str[40]; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int apidev_major; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* 348c2ecf20Sopenharmony_ci * SRB allocation cache 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cistruct kmem_cache *srb_cachep; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ciint ql2xfulldump_on_mpifail; 398c2ecf20Sopenharmony_cimodule_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR); 408c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xfulldump_on_mpifail, 418c2ecf20Sopenharmony_ci "Set this to take full dump on MPI hang."); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciint ql2xenforce_iocb_limit = 1; 448c2ecf20Sopenharmony_cimodule_param(ql2xenforce_iocb_limit, int, S_IRUGO | S_IWUSR); 458c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xenforce_iocb_limit, 468c2ecf20Sopenharmony_ci "Enforce IOCB throttling, to avoid FW congestion. (default: 1)"); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* 498c2ecf20Sopenharmony_ci * CT6 CTX allocation cache 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_cistatic struct kmem_cache *ctx_cachep; 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci * error level for logging 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ciuint ql_errlev = 0x8001; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic int ql2xenableclass2; 588c2ecf20Sopenharmony_cimodule_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR); 598c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xenableclass2, 608c2ecf20Sopenharmony_ci "Specify if Class 2 operations are supported from the very " 618c2ecf20Sopenharmony_ci "beginning. Default is 0 - class 2 not supported."); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ciint ql2xlogintimeout = 20; 658c2ecf20Sopenharmony_cimodule_param(ql2xlogintimeout, int, S_IRUGO); 668c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xlogintimeout, 678c2ecf20Sopenharmony_ci "Login timeout value in seconds."); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ciint qlport_down_retry; 708c2ecf20Sopenharmony_cimodule_param(qlport_down_retry, int, S_IRUGO); 718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(qlport_down_retry, 728c2ecf20Sopenharmony_ci "Maximum number of command retries to a port that returns " 738c2ecf20Sopenharmony_ci "a PORT-DOWN status."); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciint ql2xplogiabsentdevice; 768c2ecf20Sopenharmony_cimodule_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR); 778c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xplogiabsentdevice, 788c2ecf20Sopenharmony_ci "Option to enable PLOGI to devices that are not present after " 798c2ecf20Sopenharmony_ci "a Fabric scan. This is needed for several broken switches. " 808c2ecf20Sopenharmony_ci "Default is 0 - no PLOGI. 1 - perform PLOGI."); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciint ql2xloginretrycount; 838c2ecf20Sopenharmony_cimodule_param(ql2xloginretrycount, int, S_IRUGO); 848c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xloginretrycount, 858c2ecf20Sopenharmony_ci "Specify an alternate value for the NVRAM login retry count."); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciint ql2xallocfwdump = 1; 888c2ecf20Sopenharmony_cimodule_param(ql2xallocfwdump, int, S_IRUGO); 898c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xallocfwdump, 908c2ecf20Sopenharmony_ci "Option to enable allocation of memory for a firmware dump " 918c2ecf20Sopenharmony_ci "during HBA initialization. Memory allocation requirements " 928c2ecf20Sopenharmony_ci "vary by ISP type. Default is 1 - allocate memory."); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciint ql2xextended_error_logging; 958c2ecf20Sopenharmony_cimodule_param(ql2xextended_error_logging, int, S_IRUGO|S_IWUSR); 968c2ecf20Sopenharmony_cimodule_param_named(logging, ql2xextended_error_logging, int, S_IRUGO|S_IWUSR); 978c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xextended_error_logging, 988c2ecf20Sopenharmony_ci "Option to enable extended error logging,\n" 998c2ecf20Sopenharmony_ci "\t\tDefault is 0 - no logging. 0x40000000 - Module Init & Probe.\n" 1008c2ecf20Sopenharmony_ci "\t\t0x20000000 - Mailbox Cmnds. 0x10000000 - Device Discovery.\n" 1018c2ecf20Sopenharmony_ci "\t\t0x08000000 - IO tracing. 0x04000000 - DPC Thread.\n" 1028c2ecf20Sopenharmony_ci "\t\t0x02000000 - Async events. 0x01000000 - Timer routines.\n" 1038c2ecf20Sopenharmony_ci "\t\t0x00800000 - User space. 0x00400000 - Task Management.\n" 1048c2ecf20Sopenharmony_ci "\t\t0x00200000 - AER/EEH. 0x00100000 - Multi Q.\n" 1058c2ecf20Sopenharmony_ci "\t\t0x00080000 - P3P Specific. 0x00040000 - Virtual Port.\n" 1068c2ecf20Sopenharmony_ci "\t\t0x00020000 - Buffer Dump. 0x00010000 - Misc.\n" 1078c2ecf20Sopenharmony_ci "\t\t0x00008000 - Verbose. 0x00004000 - Target.\n" 1088c2ecf20Sopenharmony_ci "\t\t0x00002000 - Target Mgmt. 0x00001000 - Target TMF.\n" 1098c2ecf20Sopenharmony_ci "\t\t0x7fffffff - For enabling all logs, can be too many logs.\n" 1108c2ecf20Sopenharmony_ci "\t\t0x1e400000 - Preferred value for capturing essential " 1118c2ecf20Sopenharmony_ci "debug information (equivalent to old " 1128c2ecf20Sopenharmony_ci "ql2xextended_error_logging=1).\n" 1138c2ecf20Sopenharmony_ci "\t\tDo LOGICAL OR of the value to enable more than one level"); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciint ql2xshiftctondsd = 6; 1168c2ecf20Sopenharmony_cimodule_param(ql2xshiftctondsd, int, S_IRUGO); 1178c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xshiftctondsd, 1188c2ecf20Sopenharmony_ci "Set to control shifting of command type processing " 1198c2ecf20Sopenharmony_ci "based on total number of SG elements."); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ciint ql2xfdmienable = 1; 1228c2ecf20Sopenharmony_cimodule_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR); 1238c2ecf20Sopenharmony_cimodule_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR); 1248c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xfdmienable, 1258c2ecf20Sopenharmony_ci "Enables FDMI registrations. " 1268c2ecf20Sopenharmony_ci "0 - no FDMI registrations. " 1278c2ecf20Sopenharmony_ci "1 - provide FDMI registrations (default)."); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#define MAX_Q_DEPTH 64 1308c2ecf20Sopenharmony_cistatic int ql2xmaxqdepth = MAX_Q_DEPTH; 1318c2ecf20Sopenharmony_cimodule_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); 1328c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xmaxqdepth, 1338c2ecf20Sopenharmony_ci "Maximum queue depth to set for each LUN. " 1348c2ecf20Sopenharmony_ci "Default is 64."); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ciint ql2xenabledif = 2; 1378c2ecf20Sopenharmony_cimodule_param(ql2xenabledif, int, S_IRUGO); 1388c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xenabledif, 1398c2ecf20Sopenharmony_ci " Enable T10-CRC-DIF:\n" 1408c2ecf20Sopenharmony_ci " Default is 2.\n" 1418c2ecf20Sopenharmony_ci " 0 -- No DIF Support\n" 1428c2ecf20Sopenharmony_ci " 1 -- Enable DIF for all types\n" 1438c2ecf20Sopenharmony_ci " 2 -- Enable DIF for all types, except Type 0.\n"); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci#if (IS_ENABLED(CONFIG_NVME_FC)) 1468c2ecf20Sopenharmony_ciint ql2xnvmeenable = 1; 1478c2ecf20Sopenharmony_ci#else 1488c2ecf20Sopenharmony_ciint ql2xnvmeenable; 1498c2ecf20Sopenharmony_ci#endif 1508c2ecf20Sopenharmony_cimodule_param(ql2xnvmeenable, int, 0644); 1518c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xnvmeenable, 1528c2ecf20Sopenharmony_ci "Enables NVME support. " 1538c2ecf20Sopenharmony_ci "0 - no NVMe. Default is Y"); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ciint ql2xenablehba_err_chk = 2; 1568c2ecf20Sopenharmony_cimodule_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR); 1578c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xenablehba_err_chk, 1588c2ecf20Sopenharmony_ci " Enable T10-CRC-DIF Error isolation by HBA:\n" 1598c2ecf20Sopenharmony_ci " Default is 2.\n" 1608c2ecf20Sopenharmony_ci " 0 -- Error isolation disabled\n" 1618c2ecf20Sopenharmony_ci " 1 -- Error isolation enabled only for DIX Type 0\n" 1628c2ecf20Sopenharmony_ci " 2 -- Error isolation enabled for all Types\n"); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ciint ql2xiidmaenable = 1; 1658c2ecf20Sopenharmony_cimodule_param(ql2xiidmaenable, int, S_IRUGO); 1668c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xiidmaenable, 1678c2ecf20Sopenharmony_ci "Enables iIDMA settings " 1688c2ecf20Sopenharmony_ci "Default is 1 - perform iIDMA. 0 - no iIDMA."); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ciint ql2xmqsupport = 1; 1718c2ecf20Sopenharmony_cimodule_param(ql2xmqsupport, int, S_IRUGO); 1728c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xmqsupport, 1738c2ecf20Sopenharmony_ci "Enable on demand multiple queue pairs support " 1748c2ecf20Sopenharmony_ci "Default is 1 for supported. " 1758c2ecf20Sopenharmony_ci "Set it to 0 to turn off mq qpair support."); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ciint ql2xfwloadbin; 1788c2ecf20Sopenharmony_cimodule_param(ql2xfwloadbin, int, S_IRUGO|S_IWUSR); 1798c2ecf20Sopenharmony_cimodule_param_named(fwload, ql2xfwloadbin, int, S_IRUGO|S_IWUSR); 1808c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xfwloadbin, 1818c2ecf20Sopenharmony_ci "Option to specify location from which to load ISP firmware:.\n" 1828c2ecf20Sopenharmony_ci " 2 -- load firmware via the request_firmware() (hotplug).\n" 1838c2ecf20Sopenharmony_ci " interface.\n" 1848c2ecf20Sopenharmony_ci " 1 -- load firmware from flash.\n" 1858c2ecf20Sopenharmony_ci " 0 -- use default semantics.\n"); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ciint ql2xetsenable; 1888c2ecf20Sopenharmony_cimodule_param(ql2xetsenable, int, S_IRUGO); 1898c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xetsenable, 1908c2ecf20Sopenharmony_ci "Enables firmware ETS burst." 1918c2ecf20Sopenharmony_ci "Default is 0 - skip ETS enablement."); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciint ql2xdbwr = 1; 1948c2ecf20Sopenharmony_cimodule_param(ql2xdbwr, int, S_IRUGO|S_IWUSR); 1958c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xdbwr, 1968c2ecf20Sopenharmony_ci "Option to specify scheme for request queue posting.\n" 1978c2ecf20Sopenharmony_ci " 0 -- Regular doorbell.\n" 1988c2ecf20Sopenharmony_ci " 1 -- CAMRAM doorbell (faster).\n"); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ciint ql2xgffidenable; 2018c2ecf20Sopenharmony_cimodule_param(ql2xgffidenable, int, S_IRUGO); 2028c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xgffidenable, 2038c2ecf20Sopenharmony_ci "Enables GFF_ID checks of port type. " 2048c2ecf20Sopenharmony_ci "Default is 0 - Do not use GFF_ID information."); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ciint ql2xasynctmfenable = 1; 2078c2ecf20Sopenharmony_cimodule_param(ql2xasynctmfenable, int, S_IRUGO); 2088c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xasynctmfenable, 2098c2ecf20Sopenharmony_ci "Enables issue of TM IOCBs asynchronously via IOCB mechanism" 2108c2ecf20Sopenharmony_ci "Default is 1 - Issue TM IOCBs via mailbox mechanism."); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ciint ql2xdontresethba; 2138c2ecf20Sopenharmony_cimodule_param(ql2xdontresethba, int, S_IRUGO|S_IWUSR); 2148c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xdontresethba, 2158c2ecf20Sopenharmony_ci "Option to specify reset behaviour.\n" 2168c2ecf20Sopenharmony_ci " 0 (Default) -- Reset on failure.\n" 2178c2ecf20Sopenharmony_ci " 1 -- Do not reset on failure.\n"); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ciuint64_t ql2xmaxlun = MAX_LUNS; 2208c2ecf20Sopenharmony_cimodule_param(ql2xmaxlun, ullong, S_IRUGO); 2218c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xmaxlun, 2228c2ecf20Sopenharmony_ci "Defines the maximum LU number to register with the SCSI " 2238c2ecf20Sopenharmony_ci "midlayer. Default is 65535."); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ciint ql2xmdcapmask = 0x1F; 2268c2ecf20Sopenharmony_cimodule_param(ql2xmdcapmask, int, S_IRUGO); 2278c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xmdcapmask, 2288c2ecf20Sopenharmony_ci "Set the Minidump driver capture mask level. " 2298c2ecf20Sopenharmony_ci "Default is 0x1F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F."); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciint ql2xmdenable = 1; 2328c2ecf20Sopenharmony_cimodule_param(ql2xmdenable, int, S_IRUGO); 2338c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xmdenable, 2348c2ecf20Sopenharmony_ci "Enable/disable MiniDump. " 2358c2ecf20Sopenharmony_ci "0 - MiniDump disabled. " 2368c2ecf20Sopenharmony_ci "1 (Default) - MiniDump enabled."); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciint ql2xexlogins; 2398c2ecf20Sopenharmony_cimodule_param(ql2xexlogins, uint, S_IRUGO|S_IWUSR); 2408c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xexlogins, 2418c2ecf20Sopenharmony_ci "Number of extended Logins. " 2428c2ecf20Sopenharmony_ci "0 (Default)- Disabled."); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ciint ql2xexchoffld = 1024; 2458c2ecf20Sopenharmony_cimodule_param(ql2xexchoffld, uint, 0644); 2468c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xexchoffld, 2478c2ecf20Sopenharmony_ci "Number of target exchanges."); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ciint ql2xiniexchg = 1024; 2508c2ecf20Sopenharmony_cimodule_param(ql2xiniexchg, uint, 0644); 2518c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xiniexchg, 2528c2ecf20Sopenharmony_ci "Number of initiator exchanges."); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ciint ql2xfwholdabts; 2558c2ecf20Sopenharmony_cimodule_param(ql2xfwholdabts, int, S_IRUGO); 2568c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xfwholdabts, 2578c2ecf20Sopenharmony_ci "Allow FW to hold status IOCB until ABTS rsp received. " 2588c2ecf20Sopenharmony_ci "0 (Default) Do not set fw option. " 2598c2ecf20Sopenharmony_ci "1 - Set fw option to hold ABTS."); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ciint ql2xmvasynctoatio = 1; 2628c2ecf20Sopenharmony_cimodule_param(ql2xmvasynctoatio, int, S_IRUGO|S_IWUSR); 2638c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xmvasynctoatio, 2648c2ecf20Sopenharmony_ci "Move PUREX, ABTS RX and RIDA IOCBs to ATIOQ" 2658c2ecf20Sopenharmony_ci "0 (Default). Do not move IOCBs" 2668c2ecf20Sopenharmony_ci "1 - Move IOCBs."); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ciint ql2xautodetectsfp = 1; 2698c2ecf20Sopenharmony_cimodule_param(ql2xautodetectsfp, int, 0444); 2708c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xautodetectsfp, 2718c2ecf20Sopenharmony_ci "Detect SFP range and set appropriate distance.\n" 2728c2ecf20Sopenharmony_ci "1 (Default): Enable\n"); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciint ql2xenablemsix = 1; 2758c2ecf20Sopenharmony_cimodule_param(ql2xenablemsix, int, 0444); 2768c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xenablemsix, 2778c2ecf20Sopenharmony_ci "Set to enable MSI or MSI-X interrupt mechanism.\n" 2788c2ecf20Sopenharmony_ci " Default is 1, enable MSI-X interrupt mechanism.\n" 2798c2ecf20Sopenharmony_ci " 0 -- enable traditional pin-based mechanism.\n" 2808c2ecf20Sopenharmony_ci " 1 -- enable MSI-X interrupt mechanism.\n" 2818c2ecf20Sopenharmony_ci " 2 -- enable MSI interrupt mechanism.\n"); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ciint qla2xuseresexchforels; 2848c2ecf20Sopenharmony_cimodule_param(qla2xuseresexchforels, int, 0444); 2858c2ecf20Sopenharmony_ciMODULE_PARM_DESC(qla2xuseresexchforels, 2868c2ecf20Sopenharmony_ci "Reserve 1/2 of emergency exchanges for ELS.\n" 2878c2ecf20Sopenharmony_ci " 0 (default): disabled"); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic int ql2xprotmask; 2908c2ecf20Sopenharmony_cimodule_param(ql2xprotmask, int, 0644); 2918c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xprotmask, 2928c2ecf20Sopenharmony_ci "Override DIF/DIX protection capabilities mask\n" 2938c2ecf20Sopenharmony_ci "Default is 0 which sets protection mask based on " 2948c2ecf20Sopenharmony_ci "capabilities reported by HBA firmware.\n"); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic int ql2xprotguard; 2978c2ecf20Sopenharmony_cimodule_param(ql2xprotguard, int, 0644); 2988c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xprotguard, "Override choice of DIX checksum\n" 2998c2ecf20Sopenharmony_ci " 0 -- Let HBA firmware decide\n" 3008c2ecf20Sopenharmony_ci " 1 -- Force T10 CRC\n" 3018c2ecf20Sopenharmony_ci " 2 -- Force IP checksum\n"); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ciint ql2xdifbundlinginternalbuffers; 3048c2ecf20Sopenharmony_cimodule_param(ql2xdifbundlinginternalbuffers, int, 0644); 3058c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xdifbundlinginternalbuffers, 3068c2ecf20Sopenharmony_ci "Force using internal buffers for DIF information\n" 3078c2ecf20Sopenharmony_ci "0 (Default). Based on check.\n" 3088c2ecf20Sopenharmony_ci "1 Force using internal buffers\n"); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ciint ql2xsmartsan; 3118c2ecf20Sopenharmony_cimodule_param(ql2xsmartsan, int, 0444); 3128c2ecf20Sopenharmony_cimodule_param_named(smartsan, ql2xsmartsan, int, 0444); 3138c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xsmartsan, 3148c2ecf20Sopenharmony_ci "Send SmartSAN Management Attributes for FDMI Registration." 3158c2ecf20Sopenharmony_ci " Default is 0 - No SmartSAN registration," 3168c2ecf20Sopenharmony_ci " 1 - Register SmartSAN Management Attributes."); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ciint ql2xrdpenable; 3198c2ecf20Sopenharmony_cimodule_param(ql2xrdpenable, int, 0444); 3208c2ecf20Sopenharmony_cimodule_param_named(rdpenable, ql2xrdpenable, int, 0444); 3218c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql2xrdpenable, 3228c2ecf20Sopenharmony_ci "Enables RDP responses. " 3238c2ecf20Sopenharmony_ci "0 - no RDP responses (default). " 3248c2ecf20Sopenharmony_ci "1 - provide RDP responses."); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic void qla2x00_clear_drv_active(struct qla_hw_data *); 3278c2ecf20Sopenharmony_cistatic void qla2x00_free_device(scsi_qla_host_t *); 3288c2ecf20Sopenharmony_cistatic int qla2xxx_map_queues(struct Scsi_Host *shost); 3298c2ecf20Sopenharmony_cistatic void qla2x00_destroy_deferred_work(struct qla_hw_data *); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic struct scsi_transport_template *qla2xxx_transport_template = NULL; 3338c2ecf20Sopenharmony_cistruct scsi_transport_template *qla2xxx_transport_vport_template = NULL; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/* TODO Convert to inlines 3368c2ecf20Sopenharmony_ci * 3378c2ecf20Sopenharmony_ci * Timer routines 3388c2ecf20Sopenharmony_ci */ 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci__inline__ void 3418c2ecf20Sopenharmony_ciqla2x00_start_timer(scsi_qla_host_t *vha, unsigned long interval) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci timer_setup(&vha->timer, qla2x00_timer, 0); 3448c2ecf20Sopenharmony_ci vha->timer.expires = jiffies + interval * HZ; 3458c2ecf20Sopenharmony_ci add_timer(&vha->timer); 3468c2ecf20Sopenharmony_ci vha->timer_active = 1; 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic inline void 3508c2ecf20Sopenharmony_ciqla2x00_restart_timer(scsi_qla_host_t *vha, unsigned long interval) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci /* Currently used for 82XX only. */ 3538c2ecf20Sopenharmony_ci if (vha->device_flags & DFLG_DEV_FAILED) { 3548c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_timer, vha, 0x600d, 3558c2ecf20Sopenharmony_ci "Device in a failed state, returning.\n"); 3568c2ecf20Sopenharmony_ci return; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci mod_timer(&vha->timer, jiffies + interval * HZ); 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic __inline__ void 3638c2ecf20Sopenharmony_ciqla2x00_stop_timer(scsi_qla_host_t *vha) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci del_timer_sync(&vha->timer); 3668c2ecf20Sopenharmony_ci vha->timer_active = 0; 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic int qla2x00_do_dpc(void *data); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic void qla2x00_rst_aen(scsi_qla_host_t *); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic int qla2x00_mem_alloc(struct qla_hw_data *, uint16_t, uint16_t, 3748c2ecf20Sopenharmony_ci struct req_que **, struct rsp_que **); 3758c2ecf20Sopenharmony_cistatic void qla2x00_free_fw_dump(struct qla_hw_data *); 3768c2ecf20Sopenharmony_cistatic void qla2x00_mem_free(struct qla_hw_data *); 3778c2ecf20Sopenharmony_ciint qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, 3788c2ecf20Sopenharmony_ci struct qla_qpair *qpair); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/* -------------------------------------------------------------------------- */ 3818c2ecf20Sopenharmony_cistatic void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, 3828c2ecf20Sopenharmony_ci struct rsp_que *rsp) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci rsp->qpair = ha->base_qpair; 3878c2ecf20Sopenharmony_ci rsp->req = req; 3888c2ecf20Sopenharmony_ci ha->base_qpair->hw = ha; 3898c2ecf20Sopenharmony_ci ha->base_qpair->req = req; 3908c2ecf20Sopenharmony_ci ha->base_qpair->rsp = rsp; 3918c2ecf20Sopenharmony_ci ha->base_qpair->vha = vha; 3928c2ecf20Sopenharmony_ci ha->base_qpair->qp_lock_ptr = &ha->hardware_lock; 3938c2ecf20Sopenharmony_ci ha->base_qpair->use_shadow_reg = IS_SHADOW_REG_CAPABLE(ha) ? 1 : 0; 3948c2ecf20Sopenharmony_ci ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q]; 3958c2ecf20Sopenharmony_ci ha->base_qpair->srb_mempool = ha->srb_mempool; 3968c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->base_qpair->hints_list); 3978c2ecf20Sopenharmony_ci ha->base_qpair->enable_class_2 = ql2xenableclass2; 3988c2ecf20Sopenharmony_ci /* init qpair to this cpu. Will adjust at run time. */ 3998c2ecf20Sopenharmony_ci qla_cpu_update(rsp->qpair, raw_smp_processor_id()); 4008c2ecf20Sopenharmony_ci ha->base_qpair->pdev = ha->pdev; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) 4038c2ecf20Sopenharmony_ci ha->base_qpair->reqq_start_iocbs = qla_83xx_start_iocbs; 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req, 4078c2ecf20Sopenharmony_ci struct rsp_que *rsp) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci ha->req_q_map = kcalloc(ha->max_req_queues, sizeof(struct req_que *), 4128c2ecf20Sopenharmony_ci GFP_KERNEL); 4138c2ecf20Sopenharmony_ci if (!ha->req_q_map) { 4148c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0x003b, 4158c2ecf20Sopenharmony_ci "Unable to allocate memory for request queue ptrs.\n"); 4168c2ecf20Sopenharmony_ci goto fail_req_map; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci ha->rsp_q_map = kcalloc(ha->max_rsp_queues, sizeof(struct rsp_que *), 4208c2ecf20Sopenharmony_ci GFP_KERNEL); 4218c2ecf20Sopenharmony_ci if (!ha->rsp_q_map) { 4228c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0x003c, 4238c2ecf20Sopenharmony_ci "Unable to allocate memory for response queue ptrs.\n"); 4248c2ecf20Sopenharmony_ci goto fail_rsp_map; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci ha->base_qpair = kzalloc(sizeof(struct qla_qpair), GFP_KERNEL); 4288c2ecf20Sopenharmony_ci if (ha->base_qpair == NULL) { 4298c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x00e0, 4308c2ecf20Sopenharmony_ci "Failed to allocate base queue pair memory.\n"); 4318c2ecf20Sopenharmony_ci goto fail_base_qpair; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci qla_init_base_qpair(vha, req, rsp); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if ((ql2xmqsupport || ql2xnvmeenable) && ha->max_qpairs) { 4378c2ecf20Sopenharmony_ci ha->queue_pair_map = kcalloc(ha->max_qpairs, sizeof(struct qla_qpair *), 4388c2ecf20Sopenharmony_ci GFP_KERNEL); 4398c2ecf20Sopenharmony_ci if (!ha->queue_pair_map) { 4408c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0x0180, 4418c2ecf20Sopenharmony_ci "Unable to allocate memory for queue pair ptrs.\n"); 4428c2ecf20Sopenharmony_ci goto fail_qpair_map; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci /* 4478c2ecf20Sopenharmony_ci * Make sure we record at least the request and response queue zero in 4488c2ecf20Sopenharmony_ci * case we need to free them if part of the probe fails. 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci ha->rsp_q_map[0] = rsp; 4518c2ecf20Sopenharmony_ci ha->req_q_map[0] = req; 4528c2ecf20Sopenharmony_ci set_bit(0, ha->rsp_qid_map); 4538c2ecf20Sopenharmony_ci set_bit(0, ha->req_qid_map); 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cifail_qpair_map: 4578c2ecf20Sopenharmony_ci kfree(ha->base_qpair); 4588c2ecf20Sopenharmony_ci ha->base_qpair = NULL; 4598c2ecf20Sopenharmony_cifail_base_qpair: 4608c2ecf20Sopenharmony_ci kfree(ha->rsp_q_map); 4618c2ecf20Sopenharmony_ci ha->rsp_q_map = NULL; 4628c2ecf20Sopenharmony_cifail_rsp_map: 4638c2ecf20Sopenharmony_ci kfree(ha->req_q_map); 4648c2ecf20Sopenharmony_ci ha->req_q_map = NULL; 4658c2ecf20Sopenharmony_cifail_req_map: 4668c2ecf20Sopenharmony_ci return -ENOMEM; 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req) 4708c2ecf20Sopenharmony_ci{ 4718c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) { 4728c2ecf20Sopenharmony_ci if (req && req->ring_fx00) 4738c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 4748c2ecf20Sopenharmony_ci (req->length_fx00 + 1) * sizeof(request_t), 4758c2ecf20Sopenharmony_ci req->ring_fx00, req->dma_fx00); 4768c2ecf20Sopenharmony_ci } else if (req && req->ring) 4778c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 4788c2ecf20Sopenharmony_ci (req->length + 1) * sizeof(request_t), 4798c2ecf20Sopenharmony_ci req->ring, req->dma); 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci if (req) 4828c2ecf20Sopenharmony_ci kfree(req->outstanding_cmds); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci kfree(req); 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_cistatic void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) { 4908c2ecf20Sopenharmony_ci if (rsp && rsp->ring_fx00) 4918c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 4928c2ecf20Sopenharmony_ci (rsp->length_fx00 + 1) * sizeof(request_t), 4938c2ecf20Sopenharmony_ci rsp->ring_fx00, rsp->dma_fx00); 4948c2ecf20Sopenharmony_ci } else if (rsp && rsp->ring) { 4958c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 4968c2ecf20Sopenharmony_ci (rsp->length + 1) * sizeof(response_t), 4978c2ecf20Sopenharmony_ci rsp->ring, rsp->dma); 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci kfree(rsp); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic void qla2x00_free_queues(struct qla_hw_data *ha) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci struct req_que *req; 5058c2ecf20Sopenharmony_ci struct rsp_que *rsp; 5068c2ecf20Sopenharmony_ci int cnt; 5078c2ecf20Sopenharmony_ci unsigned long flags; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci if (ha->queue_pair_map) { 5108c2ecf20Sopenharmony_ci kfree(ha->queue_pair_map); 5118c2ecf20Sopenharmony_ci ha->queue_pair_map = NULL; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci if (ha->base_qpair) { 5148c2ecf20Sopenharmony_ci kfree(ha->base_qpair); 5158c2ecf20Sopenharmony_ci ha->base_qpair = NULL; 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 5198c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ha->max_req_queues; cnt++) { 5208c2ecf20Sopenharmony_ci if (!test_bit(cnt, ha->req_qid_map)) 5218c2ecf20Sopenharmony_ci continue; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci req = ha->req_q_map[cnt]; 5248c2ecf20Sopenharmony_ci clear_bit(cnt, ha->req_qid_map); 5258c2ecf20Sopenharmony_ci ha->req_q_map[cnt] = NULL; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 5288c2ecf20Sopenharmony_ci qla2x00_free_req_que(ha, req); 5298c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci kfree(ha->req_q_map); 5348c2ecf20Sopenharmony_ci ha->req_q_map = NULL; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 5388c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) { 5398c2ecf20Sopenharmony_ci if (!test_bit(cnt, ha->rsp_qid_map)) 5408c2ecf20Sopenharmony_ci continue; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci rsp = ha->rsp_q_map[cnt]; 5438c2ecf20Sopenharmony_ci clear_bit(cnt, ha->rsp_qid_map); 5448c2ecf20Sopenharmony_ci ha->rsp_q_map[cnt] = NULL; 5458c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 5468c2ecf20Sopenharmony_ci qla2x00_free_rsp_que(ha, rsp); 5478c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci kfree(ha->rsp_q_map); 5528c2ecf20Sopenharmony_ci ha->rsp_q_map = NULL; 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_cistatic char * 5568c2ecf20Sopenharmony_ciqla2x00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 5598c2ecf20Sopenharmony_ci static const char *const pci_bus_modes[] = { 5608c2ecf20Sopenharmony_ci "33", "66", "100", "133", 5618c2ecf20Sopenharmony_ci }; 5628c2ecf20Sopenharmony_ci uint16_t pci_bus; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9; 5658c2ecf20Sopenharmony_ci if (pci_bus) { 5668c2ecf20Sopenharmony_ci snprintf(str, str_len, "PCI-X (%s MHz)", 5678c2ecf20Sopenharmony_ci pci_bus_modes[pci_bus]); 5688c2ecf20Sopenharmony_ci } else { 5698c2ecf20Sopenharmony_ci pci_bus = (ha->pci_attr & BIT_8) >> 8; 5708c2ecf20Sopenharmony_ci snprintf(str, str_len, "PCI (%s MHz)", pci_bus_modes[pci_bus]); 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci return str; 5748c2ecf20Sopenharmony_ci} 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_cistatic char * 5778c2ecf20Sopenharmony_ciqla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci static const char *const pci_bus_modes[] = { 5808c2ecf20Sopenharmony_ci "33", "66", "100", "133", 5818c2ecf20Sopenharmony_ci }; 5828c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 5838c2ecf20Sopenharmony_ci uint32_t pci_bus; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci if (pci_is_pcie(ha->pdev)) { 5868c2ecf20Sopenharmony_ci uint32_t lstat, lspeed, lwidth; 5878c2ecf20Sopenharmony_ci const char *speed_str; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci pcie_capability_read_dword(ha->pdev, PCI_EXP_LNKCAP, &lstat); 5908c2ecf20Sopenharmony_ci lspeed = lstat & PCI_EXP_LNKCAP_SLS; 5918c2ecf20Sopenharmony_ci lwidth = (lstat & PCI_EXP_LNKCAP_MLW) >> 4; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci switch (lspeed) { 5948c2ecf20Sopenharmony_ci case 1: 5958c2ecf20Sopenharmony_ci speed_str = "2.5GT/s"; 5968c2ecf20Sopenharmony_ci break; 5978c2ecf20Sopenharmony_ci case 2: 5988c2ecf20Sopenharmony_ci speed_str = "5.0GT/s"; 5998c2ecf20Sopenharmony_ci break; 6008c2ecf20Sopenharmony_ci case 3: 6018c2ecf20Sopenharmony_ci speed_str = "8.0GT/s"; 6028c2ecf20Sopenharmony_ci break; 6038c2ecf20Sopenharmony_ci case 4: 6048c2ecf20Sopenharmony_ci speed_str = "16.0GT/s"; 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci default: 6078c2ecf20Sopenharmony_ci speed_str = "<unknown>"; 6088c2ecf20Sopenharmony_ci break; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci snprintf(str, str_len, "PCIe (%s x%d)", speed_str, lwidth); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return str; 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci pci_bus = (ha->pci_attr & CSRX_PCIX_BUS_MODE_MASK) >> 8; 6168c2ecf20Sopenharmony_ci if (pci_bus == 0 || pci_bus == 8) 6178c2ecf20Sopenharmony_ci snprintf(str, str_len, "PCI (%s MHz)", 6188c2ecf20Sopenharmony_ci pci_bus_modes[pci_bus >> 3]); 6198c2ecf20Sopenharmony_ci else 6208c2ecf20Sopenharmony_ci snprintf(str, str_len, "PCI-X Mode %d (%s MHz)", 6218c2ecf20Sopenharmony_ci pci_bus & 4 ? 2 : 1, 6228c2ecf20Sopenharmony_ci pci_bus_modes[pci_bus & 3]); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci return str; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic char * 6288c2ecf20Sopenharmony_ciqla2x00_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci char un_str[10]; 6318c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci snprintf(str, size, "%d.%02d.%02d ", ha->fw_major_version, 6348c2ecf20Sopenharmony_ci ha->fw_minor_version, ha->fw_subminor_version); 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci if (ha->fw_attributes & BIT_9) { 6378c2ecf20Sopenharmony_ci strcat(str, "FLX"); 6388c2ecf20Sopenharmony_ci return (str); 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci switch (ha->fw_attributes & 0xFF) { 6428c2ecf20Sopenharmony_ci case 0x7: 6438c2ecf20Sopenharmony_ci strcat(str, "EF"); 6448c2ecf20Sopenharmony_ci break; 6458c2ecf20Sopenharmony_ci case 0x17: 6468c2ecf20Sopenharmony_ci strcat(str, "TP"); 6478c2ecf20Sopenharmony_ci break; 6488c2ecf20Sopenharmony_ci case 0x37: 6498c2ecf20Sopenharmony_ci strcat(str, "IP"); 6508c2ecf20Sopenharmony_ci break; 6518c2ecf20Sopenharmony_ci case 0x77: 6528c2ecf20Sopenharmony_ci strcat(str, "VI"); 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci default: 6558c2ecf20Sopenharmony_ci sprintf(un_str, "(%x)", ha->fw_attributes); 6568c2ecf20Sopenharmony_ci strcat(str, un_str); 6578c2ecf20Sopenharmony_ci break; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci if (ha->fw_attributes & 0x100) 6608c2ecf20Sopenharmony_ci strcat(str, "X"); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci return (str); 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_cistatic char * 6668c2ecf20Sopenharmony_ciqla24xx_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size) 6678c2ecf20Sopenharmony_ci{ 6688c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci snprintf(str, size, "%d.%02d.%02d (%x)", ha->fw_major_version, 6718c2ecf20Sopenharmony_ci ha->fw_minor_version, ha->fw_subminor_version, ha->fw_attributes); 6728c2ecf20Sopenharmony_ci return str; 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_civoid qla2x00_sp_free_dma(srb_t *sp) 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci struct qla_hw_data *ha = sp->vha->hw; 6788c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci if (sp->flags & SRB_DMA_VALID) { 6818c2ecf20Sopenharmony_ci scsi_dma_unmap(cmd); 6828c2ecf20Sopenharmony_ci sp->flags &= ~SRB_DMA_VALID; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci if (sp->flags & SRB_CRC_PROT_DMA_VALID) { 6868c2ecf20Sopenharmony_ci dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), 6878c2ecf20Sopenharmony_ci scsi_prot_sg_count(cmd), cmd->sc_data_direction); 6888c2ecf20Sopenharmony_ci sp->flags &= ~SRB_CRC_PROT_DMA_VALID; 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci if (sp->flags & SRB_CRC_CTX_DSD_VALID) { 6928c2ecf20Sopenharmony_ci /* List assured to be having elements */ 6938c2ecf20Sopenharmony_ci qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx); 6948c2ecf20Sopenharmony_ci sp->flags &= ~SRB_CRC_CTX_DSD_VALID; 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci if (sp->flags & SRB_CRC_CTX_DMA_VALID) { 6988c2ecf20Sopenharmony_ci struct crc_context *ctx0 = sp->u.scmd.crc_ctx; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); 7018c2ecf20Sopenharmony_ci sp->flags &= ~SRB_CRC_CTX_DMA_VALID; 7028c2ecf20Sopenharmony_ci } 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci if (sp->flags & SRB_FCP_CMND_DMA_VALID) { 7058c2ecf20Sopenharmony_ci struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, 7088c2ecf20Sopenharmony_ci ctx1->fcp_cmnd_dma); 7098c2ecf20Sopenharmony_ci list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); 7108c2ecf20Sopenharmony_ci ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; 7118c2ecf20Sopenharmony_ci ha->gbl_dsd_avail += ctx1->dsd_use_cnt; 7128c2ecf20Sopenharmony_ci mempool_free(ctx1, ha->ctx_mempool); 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_civoid qla2x00_sp_compl(srb_t *sp, int res) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 7198c2ecf20Sopenharmony_ci struct completion *comp = sp->comp; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci sp->free(sp); 7228c2ecf20Sopenharmony_ci cmd->result = res; 7238c2ecf20Sopenharmony_ci CMD_SP(cmd) = NULL; 7248c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 7258c2ecf20Sopenharmony_ci if (comp) 7268c2ecf20Sopenharmony_ci complete(comp); 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_civoid qla2xxx_qpair_sp_free_dma(srb_t *sp) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 7328c2ecf20Sopenharmony_ci struct qla_hw_data *ha = sp->fcport->vha->hw; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci if (sp->flags & SRB_DMA_VALID) { 7358c2ecf20Sopenharmony_ci scsi_dma_unmap(cmd); 7368c2ecf20Sopenharmony_ci sp->flags &= ~SRB_DMA_VALID; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci if (sp->flags & SRB_CRC_PROT_DMA_VALID) { 7408c2ecf20Sopenharmony_ci dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), 7418c2ecf20Sopenharmony_ci scsi_prot_sg_count(cmd), cmd->sc_data_direction); 7428c2ecf20Sopenharmony_ci sp->flags &= ~SRB_CRC_PROT_DMA_VALID; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (sp->flags & SRB_CRC_CTX_DSD_VALID) { 7468c2ecf20Sopenharmony_ci /* List assured to be having elements */ 7478c2ecf20Sopenharmony_ci qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx); 7488c2ecf20Sopenharmony_ci sp->flags &= ~SRB_CRC_CTX_DSD_VALID; 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) { 7528c2ecf20Sopenharmony_ci struct crc_context *difctx = sp->u.scmd.crc_ctx; 7538c2ecf20Sopenharmony_ci struct dsd_dma *dif_dsd, *nxt_dsd; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci list_for_each_entry_safe(dif_dsd, nxt_dsd, 7568c2ecf20Sopenharmony_ci &difctx->ldif_dma_hndl_list, list) { 7578c2ecf20Sopenharmony_ci list_del(&dif_dsd->list); 7588c2ecf20Sopenharmony_ci dma_pool_free(ha->dif_bundl_pool, dif_dsd->dsd_addr, 7598c2ecf20Sopenharmony_ci dif_dsd->dsd_list_dma); 7608c2ecf20Sopenharmony_ci kfree(dif_dsd); 7618c2ecf20Sopenharmony_ci difctx->no_dif_bundl--; 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci list_for_each_entry_safe(dif_dsd, nxt_dsd, 7658c2ecf20Sopenharmony_ci &difctx->ldif_dsd_list, list) { 7668c2ecf20Sopenharmony_ci list_del(&dif_dsd->list); 7678c2ecf20Sopenharmony_ci dma_pool_free(ha->dl_dma_pool, dif_dsd->dsd_addr, 7688c2ecf20Sopenharmony_ci dif_dsd->dsd_list_dma); 7698c2ecf20Sopenharmony_ci kfree(dif_dsd); 7708c2ecf20Sopenharmony_ci difctx->no_ldif_dsd--; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (difctx->no_ldif_dsd) { 7748c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_tgt+ql_dbg_verbose, sp->vha, 0xe022, 7758c2ecf20Sopenharmony_ci "%s: difctx->no_ldif_dsd=%x\n", 7768c2ecf20Sopenharmony_ci __func__, difctx->no_ldif_dsd); 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci if (difctx->no_dif_bundl) { 7808c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_tgt+ql_dbg_verbose, sp->vha, 0xe022, 7818c2ecf20Sopenharmony_ci "%s: difctx->no_dif_bundl=%x\n", 7828c2ecf20Sopenharmony_ci __func__, difctx->no_dif_bundl); 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID; 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if (sp->flags & SRB_FCP_CMND_DMA_VALID) { 7888c2ecf20Sopenharmony_ci struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, 7918c2ecf20Sopenharmony_ci ctx1->fcp_cmnd_dma); 7928c2ecf20Sopenharmony_ci list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); 7938c2ecf20Sopenharmony_ci ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; 7948c2ecf20Sopenharmony_ci ha->gbl_dsd_avail += ctx1->dsd_use_cnt; 7958c2ecf20Sopenharmony_ci mempool_free(ctx1, ha->ctx_mempool); 7968c2ecf20Sopenharmony_ci sp->flags &= ~SRB_FCP_CMND_DMA_VALID; 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci if (sp->flags & SRB_CRC_CTX_DMA_VALID) { 8008c2ecf20Sopenharmony_ci struct crc_context *ctx0 = sp->u.scmd.crc_ctx; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma); 8038c2ecf20Sopenharmony_ci sp->flags &= ~SRB_CRC_CTX_DMA_VALID; 8048c2ecf20Sopenharmony_ci } 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_civoid qla2xxx_qpair_sp_compl(srb_t *sp, int res) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 8108c2ecf20Sopenharmony_ci struct completion *comp = sp->comp; 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci sp->free(sp); 8138c2ecf20Sopenharmony_ci cmd->result = res; 8148c2ecf20Sopenharmony_ci CMD_SP(cmd) = NULL; 8158c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 8168c2ecf20Sopenharmony_ci if (comp) 8178c2ecf20Sopenharmony_ci complete(comp); 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic int 8218c2ecf20Sopenharmony_ciqla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) 8228c2ecf20Sopenharmony_ci{ 8238c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(host); 8248c2ecf20Sopenharmony_ci fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 8258c2ecf20Sopenharmony_ci struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); 8268c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 8278c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 8288c2ecf20Sopenharmony_ci srb_t *sp; 8298c2ecf20Sopenharmony_ci int rval; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags)) || 8328c2ecf20Sopenharmony_ci WARN_ON_ONCE(!rport)) { 8338c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 8348c2ecf20Sopenharmony_ci goto qc24_fail_command; 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if (ha->mqenable) { 8388c2ecf20Sopenharmony_ci uint32_t tag; 8398c2ecf20Sopenharmony_ci uint16_t hwq; 8408c2ecf20Sopenharmony_ci struct qla_qpair *qpair = NULL; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci tag = blk_mq_unique_tag(scsi_cmd_to_rq(cmd)); 8438c2ecf20Sopenharmony_ci hwq = blk_mq_unique_tag_to_hwq(tag); 8448c2ecf20Sopenharmony_ci qpair = ha->queue_pair_map[hwq]; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (qpair) 8478c2ecf20Sopenharmony_ci return qla2xxx_mqueuecommand(host, cmd, qpair); 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci if (ha->flags.eeh_busy) { 8518c2ecf20Sopenharmony_ci if (ha->flags.pci_channel_io_perm_failure) { 8528c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, vha, 0x9010, 8538c2ecf20Sopenharmony_ci "PCI Channel IO permanent failure, exiting " 8548c2ecf20Sopenharmony_ci "cmd=%p.\n", cmd); 8558c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 8568c2ecf20Sopenharmony_ci } else { 8578c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, vha, 0x9011, 8588c2ecf20Sopenharmony_ci "EEH_Busy, Requeuing the cmd=%p.\n", cmd); 8598c2ecf20Sopenharmony_ci cmd->result = DID_REQUEUE << 16; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci goto qc24_fail_command; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci rval = fc_remote_port_chkready(rport); 8658c2ecf20Sopenharmony_ci if (rval) { 8668c2ecf20Sopenharmony_ci cmd->result = rval; 8678c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3003, 8688c2ecf20Sopenharmony_ci "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n", 8698c2ecf20Sopenharmony_ci cmd, rval); 8708c2ecf20Sopenharmony_ci goto qc24_fail_command; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (!vha->flags.difdix_supported && 8748c2ecf20Sopenharmony_ci scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { 8758c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3004, 8768c2ecf20Sopenharmony_ci "DIF Cap not reg, fail DIF capable cmd's:%p.\n", 8778c2ecf20Sopenharmony_ci cmd); 8788c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 8798c2ecf20Sopenharmony_ci goto qc24_fail_command; 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci if (!fcport || fcport->deleted) { 8838c2ecf20Sopenharmony_ci cmd->result = DID_IMM_RETRY << 16; 8848c2ecf20Sopenharmony_ci goto qc24_fail_command; 8858c2ecf20Sopenharmony_ci } 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) != FCS_ONLINE || fcport->deleted) { 8888c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || 8898c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state) == LOOP_DEAD) { 8908c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3005, 8918c2ecf20Sopenharmony_ci "Returning DNC, fcport_state=%d loop_state=%d.\n", 8928c2ecf20Sopenharmony_ci atomic_read(&fcport->state), 8938c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state)); 8948c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 8958c2ecf20Sopenharmony_ci goto qc24_fail_command; 8968c2ecf20Sopenharmony_ci } 8978c2ecf20Sopenharmony_ci goto qc24_target_busy; 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci /* 9018c2ecf20Sopenharmony_ci * Return target busy if we've received a non-zero retry_delay_timer 9028c2ecf20Sopenharmony_ci * in a FCP_RSP. 9038c2ecf20Sopenharmony_ci */ 9048c2ecf20Sopenharmony_ci if (fcport->retry_delay_timestamp == 0) { 9058c2ecf20Sopenharmony_ci /* retry delay not set */ 9068c2ecf20Sopenharmony_ci } else if (time_after(jiffies, fcport->retry_delay_timestamp)) 9078c2ecf20Sopenharmony_ci fcport->retry_delay_timestamp = 0; 9088c2ecf20Sopenharmony_ci else 9098c2ecf20Sopenharmony_ci goto qc24_target_busy; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci sp = scsi_cmd_priv(cmd); 9128c2ecf20Sopenharmony_ci qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci sp->u.scmd.cmd = cmd; 9158c2ecf20Sopenharmony_ci sp->type = SRB_SCSI_CMD; 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci CMD_SP(cmd) = (void *)sp; 9188c2ecf20Sopenharmony_ci sp->free = qla2x00_sp_free_dma; 9198c2ecf20Sopenharmony_ci sp->done = qla2x00_sp_compl; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci rval = ha->isp_ops->start_scsi(sp); 9228c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 9238c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3013, 9248c2ecf20Sopenharmony_ci "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd); 9258c2ecf20Sopenharmony_ci goto qc24_host_busy_free_sp; 9268c2ecf20Sopenharmony_ci } 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci return 0; 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ciqc24_host_busy_free_sp: 9318c2ecf20Sopenharmony_ci sp->free(sp); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ciqc24_target_busy: 9348c2ecf20Sopenharmony_ci return SCSI_MLQUEUE_TARGET_BUSY; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ciqc24_fail_command: 9378c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci return 0; 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci/* For MQ supported I/O */ 9438c2ecf20Sopenharmony_ciint 9448c2ecf20Sopenharmony_ciqla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, 9458c2ecf20Sopenharmony_ci struct qla_qpair *qpair) 9468c2ecf20Sopenharmony_ci{ 9478c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(host); 9488c2ecf20Sopenharmony_ci fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 9498c2ecf20Sopenharmony_ci struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); 9508c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 9518c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 9528c2ecf20Sopenharmony_ci srb_t *sp; 9538c2ecf20Sopenharmony_ci int rval; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci rval = rport ? fc_remote_port_chkready(rport) : FC_PORTSTATE_OFFLINE; 9568c2ecf20Sopenharmony_ci if (rval) { 9578c2ecf20Sopenharmony_ci cmd->result = rval; 9588c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3076, 9598c2ecf20Sopenharmony_ci "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n", 9608c2ecf20Sopenharmony_ci cmd, rval); 9618c2ecf20Sopenharmony_ci goto qc24_fail_command; 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci if (!qpair->online) { 9658c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3077, 9668c2ecf20Sopenharmony_ci "qpair not online. eeh_busy=%d.\n", ha->flags.eeh_busy); 9678c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 9688c2ecf20Sopenharmony_ci goto qc24_fail_command; 9698c2ecf20Sopenharmony_ci } 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci if (!fcport || fcport->deleted) { 9728c2ecf20Sopenharmony_ci cmd->result = DID_IMM_RETRY << 16; 9738c2ecf20Sopenharmony_ci goto qc24_fail_command; 9748c2ecf20Sopenharmony_ci } 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) != FCS_ONLINE || fcport->deleted) { 9778c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || 9788c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state) == LOOP_DEAD) { 9798c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io, vha, 0x3077, 9808c2ecf20Sopenharmony_ci "Returning DNC, fcport_state=%d loop_state=%d.\n", 9818c2ecf20Sopenharmony_ci atomic_read(&fcport->state), 9828c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state)); 9838c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 9848c2ecf20Sopenharmony_ci goto qc24_fail_command; 9858c2ecf20Sopenharmony_ci } 9868c2ecf20Sopenharmony_ci goto qc24_target_busy; 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci /* 9908c2ecf20Sopenharmony_ci * Return target busy if we've received a non-zero retry_delay_timer 9918c2ecf20Sopenharmony_ci * in a FCP_RSP. 9928c2ecf20Sopenharmony_ci */ 9938c2ecf20Sopenharmony_ci if (fcport->retry_delay_timestamp == 0) { 9948c2ecf20Sopenharmony_ci /* retry delay not set */ 9958c2ecf20Sopenharmony_ci } else if (time_after(jiffies, fcport->retry_delay_timestamp)) 9968c2ecf20Sopenharmony_ci fcport->retry_delay_timestamp = 0; 9978c2ecf20Sopenharmony_ci else 9988c2ecf20Sopenharmony_ci goto qc24_target_busy; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci sp = scsi_cmd_priv(cmd); 10018c2ecf20Sopenharmony_ci qla2xxx_init_sp(sp, vha, qpair, fcport); 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci sp->u.scmd.cmd = cmd; 10048c2ecf20Sopenharmony_ci sp->type = SRB_SCSI_CMD; 10058c2ecf20Sopenharmony_ci CMD_SP(cmd) = (void *)sp; 10068c2ecf20Sopenharmony_ci sp->free = qla2xxx_qpair_sp_free_dma; 10078c2ecf20Sopenharmony_ci sp->done = qla2xxx_qpair_sp_compl; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci rval = ha->isp_ops->start_scsi_mq(sp); 10108c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 10118c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3078, 10128c2ecf20Sopenharmony_ci "Start scsi failed rval=%d for cmd=%p.\n", rval, cmd); 10138c2ecf20Sopenharmony_ci goto qc24_host_busy_free_sp; 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci return 0; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ciqc24_host_busy_free_sp: 10198c2ecf20Sopenharmony_ci sp->free(sp); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ciqc24_target_busy: 10228c2ecf20Sopenharmony_ci return SCSI_MLQUEUE_TARGET_BUSY; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ciqc24_fail_command: 10258c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci return 0; 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci/* 10318c2ecf20Sopenharmony_ci * qla2x00_eh_wait_on_command 10328c2ecf20Sopenharmony_ci * Waits for the command to be returned by the Firmware for some 10338c2ecf20Sopenharmony_ci * max time. 10348c2ecf20Sopenharmony_ci * 10358c2ecf20Sopenharmony_ci * Input: 10368c2ecf20Sopenharmony_ci * cmd = Scsi Command to wait on. 10378c2ecf20Sopenharmony_ci * 10388c2ecf20Sopenharmony_ci * Return: 10398c2ecf20Sopenharmony_ci * Completed in time : QLA_SUCCESS 10408c2ecf20Sopenharmony_ci * Did not complete in time : QLA_FUNCTION_FAILED 10418c2ecf20Sopenharmony_ci */ 10428c2ecf20Sopenharmony_cistatic int 10438c2ecf20Sopenharmony_ciqla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci#define ABORT_POLLING_PERIOD 1000 10468c2ecf20Sopenharmony_ci#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) 10478c2ecf20Sopenharmony_ci unsigned long wait_iter = ABORT_WAIT_ITER; 10488c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 10498c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 10508c2ecf20Sopenharmony_ci int ret = QLA_SUCCESS; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) { 10538c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0x8005, 10548c2ecf20Sopenharmony_ci "Return:eh_wait.\n"); 10558c2ecf20Sopenharmony_ci return ret; 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci while (CMD_SP(cmd) && wait_iter--) { 10598c2ecf20Sopenharmony_ci msleep(ABORT_POLLING_PERIOD); 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci if (CMD_SP(cmd)) 10628c2ecf20Sopenharmony_ci ret = QLA_FUNCTION_FAILED; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci return ret; 10658c2ecf20Sopenharmony_ci} 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci/* 10688c2ecf20Sopenharmony_ci * qla2x00_wait_for_hba_online 10698c2ecf20Sopenharmony_ci * Wait till the HBA is online after going through 10708c2ecf20Sopenharmony_ci * <= MAX_RETRIES_OF_ISP_ABORT or 10718c2ecf20Sopenharmony_ci * finally HBA is disabled ie marked offline 10728c2ecf20Sopenharmony_ci * 10738c2ecf20Sopenharmony_ci * Input: 10748c2ecf20Sopenharmony_ci * ha - pointer to host adapter structure 10758c2ecf20Sopenharmony_ci * 10768c2ecf20Sopenharmony_ci * Note: 10778c2ecf20Sopenharmony_ci * Does context switching-Release SPIN_LOCK 10788c2ecf20Sopenharmony_ci * (if any) before calling this routine. 10798c2ecf20Sopenharmony_ci * 10808c2ecf20Sopenharmony_ci * Return: 10818c2ecf20Sopenharmony_ci * Success (Adapter is online) : 0 10828c2ecf20Sopenharmony_ci * Failed (Adapter is offline/disabled) : 1 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ciint 10858c2ecf20Sopenharmony_ciqla2x00_wait_for_hba_online(scsi_qla_host_t *vha) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci int return_status; 10888c2ecf20Sopenharmony_ci unsigned long wait_online; 10898c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 10908c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); 10938c2ecf20Sopenharmony_ci while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) || 10948c2ecf20Sopenharmony_ci test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) || 10958c2ecf20Sopenharmony_ci test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) || 10968c2ecf20Sopenharmony_ci ha->dpc_active) && time_before(jiffies, wait_online)) { 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci msleep(1000); 10998c2ecf20Sopenharmony_ci } 11008c2ecf20Sopenharmony_ci if (base_vha->flags.online) 11018c2ecf20Sopenharmony_ci return_status = QLA_SUCCESS; 11028c2ecf20Sopenharmony_ci else 11038c2ecf20Sopenharmony_ci return_status = QLA_FUNCTION_FAILED; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci return (return_status); 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic inline int test_fcport_count(scsi_qla_host_t *vha) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 11118c2ecf20Sopenharmony_ci unsigned long flags; 11128c2ecf20Sopenharmony_ci int res; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->tgt.sess_lock, flags); 11158c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x00ec, 11168c2ecf20Sopenharmony_ci "tgt %p, fcport_count=%d\n", 11178c2ecf20Sopenharmony_ci vha, vha->fcport_count); 11188c2ecf20Sopenharmony_ci res = (vha->fcport_count == 0); 11198c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci return res; 11228c2ecf20Sopenharmony_ci} 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci/* 11258c2ecf20Sopenharmony_ci * qla2x00_wait_for_sess_deletion can only be called from remove_one. 11268c2ecf20Sopenharmony_ci * it has dependency on UNLOADING flag to stop device discovery 11278c2ecf20Sopenharmony_ci */ 11288c2ecf20Sopenharmony_civoid 11298c2ecf20Sopenharmony_ciqla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci u8 i; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci qla2x00_mark_all_devices_lost(vha); 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 11368c2ecf20Sopenharmony_ci if (wait_event_timeout(vha->fcport_waitQ, 11378c2ecf20Sopenharmony_ci test_fcport_count(vha), HZ) > 0) 11388c2ecf20Sopenharmony_ci break; 11398c2ecf20Sopenharmony_ci } 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci flush_workqueue(vha->hw->wq); 11428c2ecf20Sopenharmony_ci} 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci/* 11458c2ecf20Sopenharmony_ci * qla2x00_wait_for_hba_ready 11468c2ecf20Sopenharmony_ci * Wait till the HBA is ready before doing driver unload 11478c2ecf20Sopenharmony_ci * 11488c2ecf20Sopenharmony_ci * Input: 11498c2ecf20Sopenharmony_ci * ha - pointer to host adapter structure 11508c2ecf20Sopenharmony_ci * 11518c2ecf20Sopenharmony_ci * Note: 11528c2ecf20Sopenharmony_ci * Does context switching-Release SPIN_LOCK 11538c2ecf20Sopenharmony_ci * (if any) before calling this routine. 11548c2ecf20Sopenharmony_ci * 11558c2ecf20Sopenharmony_ci */ 11568c2ecf20Sopenharmony_cistatic void 11578c2ecf20Sopenharmony_ciqla2x00_wait_for_hba_ready(scsi_qla_host_t *vha) 11588c2ecf20Sopenharmony_ci{ 11598c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 11608c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci while ((qla2x00_reset_active(vha) || ha->dpc_active || 11638c2ecf20Sopenharmony_ci ha->flags.mbox_busy) || 11648c2ecf20Sopenharmony_ci test_bit(FX00_RESET_RECOVERY, &vha->dpc_flags) || 11658c2ecf20Sopenharmony_ci test_bit(FX00_TARGET_SCAN, &vha->dpc_flags)) { 11668c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &base_vha->dpc_flags)) 11678c2ecf20Sopenharmony_ci break; 11688c2ecf20Sopenharmony_ci msleep(1000); 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci} 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ciint 11738c2ecf20Sopenharmony_ciqla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) 11748c2ecf20Sopenharmony_ci{ 11758c2ecf20Sopenharmony_ci int return_status; 11768c2ecf20Sopenharmony_ci unsigned long wait_reset; 11778c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 11788c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ); 11818c2ecf20Sopenharmony_ci while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) || 11828c2ecf20Sopenharmony_ci test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) || 11838c2ecf20Sopenharmony_ci test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) || 11848c2ecf20Sopenharmony_ci ha->dpc_active) && time_before(jiffies, wait_reset)) { 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci msleep(1000); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) && 11898c2ecf20Sopenharmony_ci ha->flags.chip_reset_done) 11908c2ecf20Sopenharmony_ci break; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci if (ha->flags.chip_reset_done) 11938c2ecf20Sopenharmony_ci return_status = QLA_SUCCESS; 11948c2ecf20Sopenharmony_ci else 11958c2ecf20Sopenharmony_ci return_status = QLA_FUNCTION_FAILED; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci return return_status; 11988c2ecf20Sopenharmony_ci} 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci/************************************************************************** 12018c2ecf20Sopenharmony_ci* qla2xxx_eh_abort 12028c2ecf20Sopenharmony_ci* 12038c2ecf20Sopenharmony_ci* Description: 12048c2ecf20Sopenharmony_ci* The abort function will abort the specified command. 12058c2ecf20Sopenharmony_ci* 12068c2ecf20Sopenharmony_ci* Input: 12078c2ecf20Sopenharmony_ci* cmd = Linux SCSI command packet to be aborted. 12088c2ecf20Sopenharmony_ci* 12098c2ecf20Sopenharmony_ci* Returns: 12108c2ecf20Sopenharmony_ci* Either SUCCESS or FAILED. 12118c2ecf20Sopenharmony_ci* 12128c2ecf20Sopenharmony_ci* Note: 12138c2ecf20Sopenharmony_ci* Only return FAILED if command not returned by firmware. 12148c2ecf20Sopenharmony_ci**************************************************************************/ 12158c2ecf20Sopenharmony_cistatic int 12168c2ecf20Sopenharmony_ciqla2xxx_eh_abort(struct scsi_cmnd *cmd) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 12198c2ecf20Sopenharmony_ci DECLARE_COMPLETION_ONSTACK(comp); 12208c2ecf20Sopenharmony_ci srb_t *sp; 12218c2ecf20Sopenharmony_ci int ret; 12228c2ecf20Sopenharmony_ci unsigned int id; 12238c2ecf20Sopenharmony_ci uint64_t lun; 12248c2ecf20Sopenharmony_ci int rval; 12258c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 12268c2ecf20Sopenharmony_ci uint32_t ratov_j; 12278c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 12288c2ecf20Sopenharmony_ci unsigned long flags; 12298c2ecf20Sopenharmony_ci int fast_fail_status = SUCCESS; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci if (qla2x00_isp_reg_stat(ha)) { 12328c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8042, 12338c2ecf20Sopenharmony_ci "PCI/Register disconnect, exiting.\n"); 12348c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(vha); 12358c2ecf20Sopenharmony_ci return FAILED; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* Save any FAST_IO_FAIL value to return later if abort succeeds */ 12398c2ecf20Sopenharmony_ci ret = fc_block_scsi_eh(cmd); 12408c2ecf20Sopenharmony_ci if (ret != 0) 12418c2ecf20Sopenharmony_ci fast_fail_status = ret; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci sp = scsi_cmd_priv(cmd); 12448c2ecf20Sopenharmony_ci qpair = sp->qpair; 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci if ((sp->fcport && sp->fcport->deleted) || !qpair) 12478c2ecf20Sopenharmony_ci return fast_fail_status != SUCCESS ? fast_fail_status : FAILED; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci spin_lock_irqsave(qpair->qp_lock_ptr, flags); 12508c2ecf20Sopenharmony_ci sp->comp = ∁ 12518c2ecf20Sopenharmony_ci spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci id = cmd->device->id; 12558c2ecf20Sopenharmony_ci lun = cmd->device->lun; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0x8002, 12588c2ecf20Sopenharmony_ci "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p handle=%x\n", 12598c2ecf20Sopenharmony_ci vha->host_no, id, lun, sp, cmd, sp->handle); 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci /* 12628c2ecf20Sopenharmony_ci * Abort will release the original Command/sp from FW. Let the 12638c2ecf20Sopenharmony_ci * original command call scsi_done. In return, he will wakeup 12648c2ecf20Sopenharmony_ci * this sleeping thread. 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_ci rval = ha->isp_ops->abort_command(sp); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0x8003, 12698c2ecf20Sopenharmony_ci "Abort command mbx cmd=%p, rval=%x.\n", cmd, rval); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci /* Wait for the command completion. */ 12728c2ecf20Sopenharmony_ci ratov_j = ha->r_a_tov/10 * 4 * 1000; 12738c2ecf20Sopenharmony_ci ratov_j = msecs_to_jiffies(ratov_j); 12748c2ecf20Sopenharmony_ci switch (rval) { 12758c2ecf20Sopenharmony_ci case QLA_SUCCESS: 12768c2ecf20Sopenharmony_ci if (!wait_for_completion_timeout(&comp, ratov_j)) { 12778c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0xffff, 12788c2ecf20Sopenharmony_ci "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", 12798c2ecf20Sopenharmony_ci __func__, ha->r_a_tov/10); 12808c2ecf20Sopenharmony_ci ret = FAILED; 12818c2ecf20Sopenharmony_ci } else { 12828c2ecf20Sopenharmony_ci ret = fast_fail_status; 12838c2ecf20Sopenharmony_ci } 12848c2ecf20Sopenharmony_ci break; 12858c2ecf20Sopenharmony_ci default: 12868c2ecf20Sopenharmony_ci ret = FAILED; 12878c2ecf20Sopenharmony_ci break; 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci sp->comp = NULL; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x801c, 12938c2ecf20Sopenharmony_ci "Abort command issued nexus=%ld:%d:%llu -- %x.\n", 12948c2ecf20Sopenharmony_ci vha->host_no, id, lun, ret); 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci return ret; 12978c2ecf20Sopenharmony_ci} 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci/* 13008c2ecf20Sopenharmony_ci * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. 13018c2ecf20Sopenharmony_ci */ 13028c2ecf20Sopenharmony_ciint 13038c2ecf20Sopenharmony_ciqla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, 13048c2ecf20Sopenharmony_ci uint64_t l, enum nexus_wait_type type) 13058c2ecf20Sopenharmony_ci{ 13068c2ecf20Sopenharmony_ci int cnt, match, status; 13078c2ecf20Sopenharmony_ci unsigned long flags; 13088c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 13098c2ecf20Sopenharmony_ci struct req_que *req; 13108c2ecf20Sopenharmony_ci srb_t *sp; 13118c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd; 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 13168c2ecf20Sopenharmony_ci req = vha->req; 13178c2ecf20Sopenharmony_ci for (cnt = 1; status == QLA_SUCCESS && 13188c2ecf20Sopenharmony_ci cnt < req->num_outstanding_cmds; cnt++) { 13198c2ecf20Sopenharmony_ci sp = req->outstanding_cmds[cnt]; 13208c2ecf20Sopenharmony_ci if (!sp) 13218c2ecf20Sopenharmony_ci continue; 13228c2ecf20Sopenharmony_ci if (sp->type != SRB_SCSI_CMD) 13238c2ecf20Sopenharmony_ci continue; 13248c2ecf20Sopenharmony_ci if (vha->vp_idx != sp->vha->vp_idx) 13258c2ecf20Sopenharmony_ci continue; 13268c2ecf20Sopenharmony_ci match = 0; 13278c2ecf20Sopenharmony_ci cmd = GET_CMD_SP(sp); 13288c2ecf20Sopenharmony_ci switch (type) { 13298c2ecf20Sopenharmony_ci case WAIT_HOST: 13308c2ecf20Sopenharmony_ci match = 1; 13318c2ecf20Sopenharmony_ci break; 13328c2ecf20Sopenharmony_ci case WAIT_TARGET: 13338c2ecf20Sopenharmony_ci match = cmd->device->id == t; 13348c2ecf20Sopenharmony_ci break; 13358c2ecf20Sopenharmony_ci case WAIT_LUN: 13368c2ecf20Sopenharmony_ci match = (cmd->device->id == t && 13378c2ecf20Sopenharmony_ci cmd->device->lun == l); 13388c2ecf20Sopenharmony_ci break; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci if (!match) 13418c2ecf20Sopenharmony_ci continue; 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 13448c2ecf20Sopenharmony_ci status = qla2x00_eh_wait_on_command(cmd); 13458c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci return status; 13508c2ecf20Sopenharmony_ci} 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_cistatic char *reset_errors[] = { 13538c2ecf20Sopenharmony_ci "HBA not online", 13548c2ecf20Sopenharmony_ci "HBA not ready", 13558c2ecf20Sopenharmony_ci "Task management failed", 13568c2ecf20Sopenharmony_ci "Waiting for command completions", 13578c2ecf20Sopenharmony_ci}; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_cistatic int 13608c2ecf20Sopenharmony_ci__qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, 13618c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, uint64_t, int)) 13628c2ecf20Sopenharmony_ci{ 13638c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 13648c2ecf20Sopenharmony_ci fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 13658c2ecf20Sopenharmony_ci int err; 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci if (!fcport) { 13688c2ecf20Sopenharmony_ci return FAILED; 13698c2ecf20Sopenharmony_ci } 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci err = fc_block_scsi_eh(cmd); 13728c2ecf20Sopenharmony_ci if (err != 0) 13738c2ecf20Sopenharmony_ci return err; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci if (fcport->deleted) 13768c2ecf20Sopenharmony_ci return SUCCESS; 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8009, 13798c2ecf20Sopenharmony_ci "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no, 13808c2ecf20Sopenharmony_ci cmd->device->id, cmd->device->lun, cmd); 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci err = 0; 13838c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 13848c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x800a, 13858c2ecf20Sopenharmony_ci "Wait for hba online failed for cmd=%p.\n", cmd); 13868c2ecf20Sopenharmony_ci goto eh_reset_failed; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci err = 2; 13898c2ecf20Sopenharmony_ci if (do_reset(fcport, cmd->device->lun, 1) 13908c2ecf20Sopenharmony_ci != QLA_SUCCESS) { 13918c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x800c, 13928c2ecf20Sopenharmony_ci "do_reset failed for cmd=%p.\n", cmd); 13938c2ecf20Sopenharmony_ci goto eh_reset_failed; 13948c2ecf20Sopenharmony_ci } 13958c2ecf20Sopenharmony_ci err = 3; 13968c2ecf20Sopenharmony_ci if (qla2x00_eh_wait_for_pending_commands(vha, cmd->device->id, 13978c2ecf20Sopenharmony_ci cmd->device->lun, type) != QLA_SUCCESS) { 13988c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x800d, 13998c2ecf20Sopenharmony_ci "wait for pending cmds failed for cmd=%p.\n", cmd); 14008c2ecf20Sopenharmony_ci goto eh_reset_failed; 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x800e, 14048c2ecf20Sopenharmony_ci "%s RESET SUCCEEDED nexus:%ld:%d:%llu cmd=%p.\n", name, 14058c2ecf20Sopenharmony_ci vha->host_no, cmd->device->id, cmd->device->lun, cmd); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci return SUCCESS; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_cieh_reset_failed: 14108c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x800f, 14118c2ecf20Sopenharmony_ci "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name, 14128c2ecf20Sopenharmony_ci reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun, 14138c2ecf20Sopenharmony_ci cmd); 14148c2ecf20Sopenharmony_ci return FAILED; 14158c2ecf20Sopenharmony_ci} 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_cistatic int 14188c2ecf20Sopenharmony_ciqla2xxx_eh_device_reset(struct scsi_cmnd *cmd) 14198c2ecf20Sopenharmony_ci{ 14208c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 14218c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if (qla2x00_isp_reg_stat(ha)) { 14248c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x803e, 14258c2ecf20Sopenharmony_ci "PCI/Register disconnect, exiting.\n"); 14268c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(vha); 14278c2ecf20Sopenharmony_ci return FAILED; 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci return __qla2xxx_eh_generic_reset("DEVICE", WAIT_LUN, cmd, 14318c2ecf20Sopenharmony_ci ha->isp_ops->lun_reset); 14328c2ecf20Sopenharmony_ci} 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_cistatic int 14358c2ecf20Sopenharmony_ciqla2xxx_eh_target_reset(struct scsi_cmnd *cmd) 14368c2ecf20Sopenharmony_ci{ 14378c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 14388c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci if (qla2x00_isp_reg_stat(ha)) { 14418c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x803f, 14428c2ecf20Sopenharmony_ci "PCI/Register disconnect, exiting.\n"); 14438c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(vha); 14448c2ecf20Sopenharmony_ci return FAILED; 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci return __qla2xxx_eh_generic_reset("TARGET", WAIT_TARGET, cmd, 14488c2ecf20Sopenharmony_ci ha->isp_ops->target_reset); 14498c2ecf20Sopenharmony_ci} 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci/************************************************************************** 14528c2ecf20Sopenharmony_ci* qla2xxx_eh_bus_reset 14538c2ecf20Sopenharmony_ci* 14548c2ecf20Sopenharmony_ci* Description: 14558c2ecf20Sopenharmony_ci* The bus reset function will reset the bus and abort any executing 14568c2ecf20Sopenharmony_ci* commands. 14578c2ecf20Sopenharmony_ci* 14588c2ecf20Sopenharmony_ci* Input: 14598c2ecf20Sopenharmony_ci* cmd = Linux SCSI command packet of the command that cause the 14608c2ecf20Sopenharmony_ci* bus reset. 14618c2ecf20Sopenharmony_ci* 14628c2ecf20Sopenharmony_ci* Returns: 14638c2ecf20Sopenharmony_ci* SUCCESS/FAILURE (defined as macro in scsi.h). 14648c2ecf20Sopenharmony_ci* 14658c2ecf20Sopenharmony_ci**************************************************************************/ 14668c2ecf20Sopenharmony_cistatic int 14678c2ecf20Sopenharmony_ciqla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) 14688c2ecf20Sopenharmony_ci{ 14698c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 14708c2ecf20Sopenharmony_ci fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 14718c2ecf20Sopenharmony_ci int ret = FAILED; 14728c2ecf20Sopenharmony_ci unsigned int id; 14738c2ecf20Sopenharmony_ci uint64_t lun; 14748c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci if (qla2x00_isp_reg_stat(ha)) { 14778c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8040, 14788c2ecf20Sopenharmony_ci "PCI/Register disconnect, exiting.\n"); 14798c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(vha); 14808c2ecf20Sopenharmony_ci return FAILED; 14818c2ecf20Sopenharmony_ci } 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci id = cmd->device->id; 14848c2ecf20Sopenharmony_ci lun = cmd->device->lun; 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci if (!fcport) { 14878c2ecf20Sopenharmony_ci return ret; 14888c2ecf20Sopenharmony_ci } 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci ret = fc_block_scsi_eh(cmd); 14918c2ecf20Sopenharmony_ci if (ret != 0) 14928c2ecf20Sopenharmony_ci return ret; 14938c2ecf20Sopenharmony_ci ret = FAILED; 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) 14968c2ecf20Sopenharmony_ci return ret; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8012, 14998c2ecf20Sopenharmony_ci "BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 15028c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0x8013, 15038c2ecf20Sopenharmony_ci "Wait for hba online failed board disabled.\n"); 15048c2ecf20Sopenharmony_ci goto eh_bus_reset_done; 15058c2ecf20Sopenharmony_ci } 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci if (qla2x00_loop_reset(vha) == QLA_SUCCESS) 15088c2ecf20Sopenharmony_ci ret = SUCCESS; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (ret == FAILED) 15118c2ecf20Sopenharmony_ci goto eh_bus_reset_done; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci /* Flush outstanding commands. */ 15148c2ecf20Sopenharmony_ci if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) != 15158c2ecf20Sopenharmony_ci QLA_SUCCESS) { 15168c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x8014, 15178c2ecf20Sopenharmony_ci "Wait for pending commands failed.\n"); 15188c2ecf20Sopenharmony_ci ret = FAILED; 15198c2ecf20Sopenharmony_ci } 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cieh_bus_reset_done: 15228c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x802b, 15238c2ecf20Sopenharmony_ci "BUS RESET %s nexus=%ld:%d:%llu.\n", 15248c2ecf20Sopenharmony_ci (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci return ret; 15278c2ecf20Sopenharmony_ci} 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci/************************************************************************** 15308c2ecf20Sopenharmony_ci* qla2xxx_eh_host_reset 15318c2ecf20Sopenharmony_ci* 15328c2ecf20Sopenharmony_ci* Description: 15338c2ecf20Sopenharmony_ci* The reset function will reset the Adapter. 15348c2ecf20Sopenharmony_ci* 15358c2ecf20Sopenharmony_ci* Input: 15368c2ecf20Sopenharmony_ci* cmd = Linux SCSI command packet of the command that cause the 15378c2ecf20Sopenharmony_ci* adapter reset. 15388c2ecf20Sopenharmony_ci* 15398c2ecf20Sopenharmony_ci* Returns: 15408c2ecf20Sopenharmony_ci* Either SUCCESS or FAILED. 15418c2ecf20Sopenharmony_ci* 15428c2ecf20Sopenharmony_ci* Note: 15438c2ecf20Sopenharmony_ci**************************************************************************/ 15448c2ecf20Sopenharmony_cistatic int 15458c2ecf20Sopenharmony_ciqla2xxx_eh_host_reset(struct scsi_cmnd *cmd) 15468c2ecf20Sopenharmony_ci{ 15478c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(cmd->device->host); 15488c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 15498c2ecf20Sopenharmony_ci int ret = FAILED; 15508c2ecf20Sopenharmony_ci unsigned int id; 15518c2ecf20Sopenharmony_ci uint64_t lun; 15528c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci if (qla2x00_isp_reg_stat(ha)) { 15558c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8041, 15568c2ecf20Sopenharmony_ci "PCI/Register disconnect, exiting.\n"); 15578c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(vha); 15588c2ecf20Sopenharmony_ci return SUCCESS; 15598c2ecf20Sopenharmony_ci } 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_ci id = cmd->device->id; 15628c2ecf20Sopenharmony_ci lun = cmd->device->lun; 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8018, 15658c2ecf20Sopenharmony_ci "ADAPTER RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci /* 15688c2ecf20Sopenharmony_ci * No point in issuing another reset if one is active. Also do not 15698c2ecf20Sopenharmony_ci * attempt a reset if we are updating flash. 15708c2ecf20Sopenharmony_ci */ 15718c2ecf20Sopenharmony_ci if (qla2x00_reset_active(vha) || ha->optrom_state != QLA_SWAITING) 15728c2ecf20Sopenharmony_ci goto eh_host_reset_lock; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci if (vha != base_vha) { 15758c2ecf20Sopenharmony_ci if (qla2x00_vp_abort_isp(vha)) 15768c2ecf20Sopenharmony_ci goto eh_host_reset_lock; 15778c2ecf20Sopenharmony_ci } else { 15788c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(vha->hw)) { 15798c2ecf20Sopenharmony_ci if (!qla82xx_fcoe_ctx_reset(vha)) { 15808c2ecf20Sopenharmony_ci /* Ctx reset success */ 15818c2ecf20Sopenharmony_ci ret = SUCCESS; 15828c2ecf20Sopenharmony_ci goto eh_host_reset_lock; 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci /* fall thru if ctx reset failed */ 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci if (ha->wq) 15878c2ecf20Sopenharmony_ci flush_workqueue(ha->wq); 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 15908c2ecf20Sopenharmony_ci if (ha->isp_ops->abort_isp(base_vha)) { 15918c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 15928c2ecf20Sopenharmony_ci /* failed. schedule dpc to try */ 15938c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { 15968c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x802a, 15978c2ecf20Sopenharmony_ci "wait for hba online failed.\n"); 15988c2ecf20Sopenharmony_ci goto eh_host_reset_lock; 15998c2ecf20Sopenharmony_ci } 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 16028c2ecf20Sopenharmony_ci } 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci /* Waiting for command to be returned to OS.*/ 16058c2ecf20Sopenharmony_ci if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST) == 16068c2ecf20Sopenharmony_ci QLA_SUCCESS) 16078c2ecf20Sopenharmony_ci ret = SUCCESS; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_cieh_host_reset_lock: 16108c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x8017, 16118c2ecf20Sopenharmony_ci "ADAPTER RESET %s nexus=%ld:%d:%llu.\n", 16128c2ecf20Sopenharmony_ci (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci return ret; 16158c2ecf20Sopenharmony_ci} 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci/* 16188c2ecf20Sopenharmony_ci* qla2x00_loop_reset 16198c2ecf20Sopenharmony_ci* Issue loop reset. 16208c2ecf20Sopenharmony_ci* 16218c2ecf20Sopenharmony_ci* Input: 16228c2ecf20Sopenharmony_ci* ha = adapter block pointer. 16238c2ecf20Sopenharmony_ci* 16248c2ecf20Sopenharmony_ci* Returns: 16258c2ecf20Sopenharmony_ci* 0 = success 16268c2ecf20Sopenharmony_ci*/ 16278c2ecf20Sopenharmony_ciint 16288c2ecf20Sopenharmony_ciqla2x00_loop_reset(scsi_qla_host_t *vha) 16298c2ecf20Sopenharmony_ci{ 16308c2ecf20Sopenharmony_ci int ret; 16318c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) 16348c2ecf20Sopenharmony_ci return QLA_SUCCESS; 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci if (ha->flags.enable_lip_full_login && !IS_CNA_CAPABLE(ha)) { 16378c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DOWN); 16388c2ecf20Sopenharmony_ci atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); 16398c2ecf20Sopenharmony_ci qla2x00_mark_all_devices_lost(vha); 16408c2ecf20Sopenharmony_ci ret = qla2x00_full_login_lip(vha); 16418c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 16428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0x802d, 16438c2ecf20Sopenharmony_ci "full_login_lip=%d.\n", ret); 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci } 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci if (ha->flags.enable_lip_reset) { 16488c2ecf20Sopenharmony_ci ret = qla2x00_lip_reset(vha); 16498c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) 16508c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0x802e, 16518c2ecf20Sopenharmony_ci "lip_reset failed (%d).\n", ret); 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci /* Issue marker command only when we are going to start the I/O */ 16558c2ecf20Sopenharmony_ci vha->marker_needed = 1; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci return QLA_SUCCESS; 16588c2ecf20Sopenharmony_ci} 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci/* 16618c2ecf20Sopenharmony_ci * The caller must ensure that no completion interrupts will happen 16628c2ecf20Sopenharmony_ci * while this function is in progress. 16638c2ecf20Sopenharmony_ci */ 16648c2ecf20Sopenharmony_cistatic void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res, 16658c2ecf20Sopenharmony_ci unsigned long *flags) 16668c2ecf20Sopenharmony_ci __releases(qp->qp_lock_ptr) 16678c2ecf20Sopenharmony_ci __acquires(qp->qp_lock_ptr) 16688c2ecf20Sopenharmony_ci{ 16698c2ecf20Sopenharmony_ci DECLARE_COMPLETION_ONSTACK(comp); 16708c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = qp->vha; 16718c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 16728c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = GET_CMD_SP(sp); 16738c2ecf20Sopenharmony_ci int rval; 16748c2ecf20Sopenharmony_ci bool ret_cmd; 16758c2ecf20Sopenharmony_ci uint32_t ratov_j; 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci lockdep_assert_held(qp->qp_lock_ptr); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 16808c2ecf20Sopenharmony_ci sp->done(sp, res); 16818c2ecf20Sopenharmony_ci return; 16828c2ecf20Sopenharmony_ci } 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS || 16858c2ecf20Sopenharmony_ci (sp->type == SRB_SCSI_CMD && !ha->flags.eeh_busy && 16868c2ecf20Sopenharmony_ci !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && 16878c2ecf20Sopenharmony_ci !qla2x00_isp_reg_stat(ha))) { 16888c2ecf20Sopenharmony_ci if (sp->comp) { 16898c2ecf20Sopenharmony_ci sp->done(sp, res); 16908c2ecf20Sopenharmony_ci return; 16918c2ecf20Sopenharmony_ci } 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci sp->comp = ∁ 16948c2ecf20Sopenharmony_ci spin_unlock_irqrestore(qp->qp_lock_ptr, *flags); 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci rval = ha->isp_ops->abort_command(sp); 16978c2ecf20Sopenharmony_ci /* Wait for command completion. */ 16988c2ecf20Sopenharmony_ci ret_cmd = false; 16998c2ecf20Sopenharmony_ci ratov_j = ha->r_a_tov/10 * 4 * 1000; 17008c2ecf20Sopenharmony_ci ratov_j = msecs_to_jiffies(ratov_j); 17018c2ecf20Sopenharmony_ci switch (rval) { 17028c2ecf20Sopenharmony_ci case QLA_SUCCESS: 17038c2ecf20Sopenharmony_ci if (wait_for_completion_timeout(&comp, ratov_j)) { 17048c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_taskm, vha, 0xffff, 17058c2ecf20Sopenharmony_ci "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n", 17068c2ecf20Sopenharmony_ci __func__, ha->r_a_tov/10); 17078c2ecf20Sopenharmony_ci ret_cmd = true; 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci /* else FW return SP to driver */ 17108c2ecf20Sopenharmony_ci break; 17118c2ecf20Sopenharmony_ci default: 17128c2ecf20Sopenharmony_ci ret_cmd = true; 17138c2ecf20Sopenharmony_ci break; 17148c2ecf20Sopenharmony_ci } 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci spin_lock_irqsave(qp->qp_lock_ptr, *flags); 17178c2ecf20Sopenharmony_ci switch (sp->type) { 17188c2ecf20Sopenharmony_ci case SRB_SCSI_CMD: 17198c2ecf20Sopenharmony_ci if (ret_cmd && blk_mq_request_started(scsi_cmd_to_rq(cmd))) 17208c2ecf20Sopenharmony_ci sp->done(sp, res); 17218c2ecf20Sopenharmony_ci break; 17228c2ecf20Sopenharmony_ci default: 17238c2ecf20Sopenharmony_ci if (ret_cmd) 17248c2ecf20Sopenharmony_ci sp->done(sp, res); 17258c2ecf20Sopenharmony_ci break; 17268c2ecf20Sopenharmony_ci } 17278c2ecf20Sopenharmony_ci } else { 17288c2ecf20Sopenharmony_ci sp->done(sp, res); 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci/* 17338c2ecf20Sopenharmony_ci * The caller must ensure that no completion interrupts will happen 17348c2ecf20Sopenharmony_ci * while this function is in progress. 17358c2ecf20Sopenharmony_ci */ 17368c2ecf20Sopenharmony_cistatic void 17378c2ecf20Sopenharmony_ci__qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) 17388c2ecf20Sopenharmony_ci{ 17398c2ecf20Sopenharmony_ci int cnt; 17408c2ecf20Sopenharmony_ci unsigned long flags; 17418c2ecf20Sopenharmony_ci srb_t *sp; 17428c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = qp->vha; 17438c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 17448c2ecf20Sopenharmony_ci struct req_que *req; 17458c2ecf20Sopenharmony_ci struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 17468c2ecf20Sopenharmony_ci struct qla_tgt_cmd *cmd; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci if (!ha->req_q_map) 17498c2ecf20Sopenharmony_ci return; 17508c2ecf20Sopenharmony_ci spin_lock_irqsave(qp->qp_lock_ptr, flags); 17518c2ecf20Sopenharmony_ci req = qp->req; 17528c2ecf20Sopenharmony_ci for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { 17538c2ecf20Sopenharmony_ci sp = req->outstanding_cmds[cnt]; 17548c2ecf20Sopenharmony_ci if (sp) { 17558c2ecf20Sopenharmony_ci /* 17568c2ecf20Sopenharmony_ci * perform lockless completion during driver unload 17578c2ecf20Sopenharmony_ci */ 17588c2ecf20Sopenharmony_ci if (qla2x00_chip_is_down(vha)) { 17598c2ecf20Sopenharmony_ci req->outstanding_cmds[cnt] = NULL; 17608c2ecf20Sopenharmony_ci spin_unlock_irqrestore(qp->qp_lock_ptr, flags); 17618c2ecf20Sopenharmony_ci sp->done(sp, res); 17628c2ecf20Sopenharmony_ci spin_lock_irqsave(qp->qp_lock_ptr, flags); 17638c2ecf20Sopenharmony_ci continue; 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci switch (sp->cmd_type) { 17678c2ecf20Sopenharmony_ci case TYPE_SRB: 17688c2ecf20Sopenharmony_ci qla2x00_abort_srb(qp, sp, res, &flags); 17698c2ecf20Sopenharmony_ci break; 17708c2ecf20Sopenharmony_ci case TYPE_TGT_CMD: 17718c2ecf20Sopenharmony_ci if (!vha->hw->tgt.tgt_ops || !tgt || 17728c2ecf20Sopenharmony_ci qla_ini_mode_enabled(vha)) { 17738c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003, 17748c2ecf20Sopenharmony_ci "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n", 17758c2ecf20Sopenharmony_ci vha->dpc_flags); 17768c2ecf20Sopenharmony_ci continue; 17778c2ecf20Sopenharmony_ci } 17788c2ecf20Sopenharmony_ci cmd = (struct qla_tgt_cmd *)sp; 17798c2ecf20Sopenharmony_ci cmd->aborted = 1; 17808c2ecf20Sopenharmony_ci break; 17818c2ecf20Sopenharmony_ci case TYPE_TGT_TMCMD: 17828c2ecf20Sopenharmony_ci /* Skip task management functions. */ 17838c2ecf20Sopenharmony_ci break; 17848c2ecf20Sopenharmony_ci default: 17858c2ecf20Sopenharmony_ci break; 17868c2ecf20Sopenharmony_ci } 17878c2ecf20Sopenharmony_ci req->outstanding_cmds[cnt] = NULL; 17888c2ecf20Sopenharmony_ci } 17898c2ecf20Sopenharmony_ci } 17908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(qp->qp_lock_ptr, flags); 17918c2ecf20Sopenharmony_ci} 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci/* 17948c2ecf20Sopenharmony_ci * The caller must ensure that no completion interrupts will happen 17958c2ecf20Sopenharmony_ci * while this function is in progress. 17968c2ecf20Sopenharmony_ci */ 17978c2ecf20Sopenharmony_civoid 17988c2ecf20Sopenharmony_ciqla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) 17998c2ecf20Sopenharmony_ci{ 18008c2ecf20Sopenharmony_ci int que; 18018c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci /* Continue only if initialization complete. */ 18048c2ecf20Sopenharmony_ci if (!ha->base_qpair) 18058c2ecf20Sopenharmony_ci return; 18068c2ecf20Sopenharmony_ci __qla2x00_abort_all_cmds(ha->base_qpair, res); 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci if (!ha->queue_pair_map) 18098c2ecf20Sopenharmony_ci return; 18108c2ecf20Sopenharmony_ci for (que = 0; que < ha->max_qpairs; que++) { 18118c2ecf20Sopenharmony_ci if (!ha->queue_pair_map[que]) 18128c2ecf20Sopenharmony_ci continue; 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci __qla2x00_abort_all_cmds(ha->queue_pair_map[que], res); 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci} 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_cistatic int 18198c2ecf20Sopenharmony_ciqla2xxx_slave_alloc(struct scsi_device *sdev) 18208c2ecf20Sopenharmony_ci{ 18218c2ecf20Sopenharmony_ci struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci if (!rport || fc_remote_port_chkready(rport)) 18248c2ecf20Sopenharmony_ci return -ENXIO; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci sdev->hostdata = *(fc_port_t **)rport->dd_data; 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci return 0; 18298c2ecf20Sopenharmony_ci} 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_cistatic int 18328c2ecf20Sopenharmony_ciqla2xxx_slave_configure(struct scsi_device *sdev) 18338c2ecf20Sopenharmony_ci{ 18348c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(sdev->host); 18358c2ecf20Sopenharmony_ci struct req_que *req = vha->req; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci if (IS_T10_PI_CAPABLE(vha->hw)) 18388c2ecf20Sopenharmony_ci blk_queue_update_dma_alignment(sdev->request_queue, 0x7); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci scsi_change_queue_depth(sdev, req->max_q_depth); 18418c2ecf20Sopenharmony_ci return 0; 18428c2ecf20Sopenharmony_ci} 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_cistatic void 18458c2ecf20Sopenharmony_ciqla2xxx_slave_destroy(struct scsi_device *sdev) 18468c2ecf20Sopenharmony_ci{ 18478c2ecf20Sopenharmony_ci sdev->hostdata = NULL; 18488c2ecf20Sopenharmony_ci} 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci/** 18518c2ecf20Sopenharmony_ci * qla2x00_config_dma_addressing() - Configure OS DMA addressing method. 18528c2ecf20Sopenharmony_ci * @ha: HA context 18538c2ecf20Sopenharmony_ci * 18548c2ecf20Sopenharmony_ci * At exit, the @ha's flags.enable_64bit_addressing set to indicated 18558c2ecf20Sopenharmony_ci * supported addressing method. 18568c2ecf20Sopenharmony_ci */ 18578c2ecf20Sopenharmony_cistatic void 18588c2ecf20Sopenharmony_ciqla2x00_config_dma_addressing(struct qla_hw_data *ha) 18598c2ecf20Sopenharmony_ci{ 18608c2ecf20Sopenharmony_ci /* Assume a 32bit DMA mask. */ 18618c2ecf20Sopenharmony_ci ha->flags.enable_64bit_addressing = 0; 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci if (!dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) { 18648c2ecf20Sopenharmony_ci /* Any upper-dword bits set? */ 18658c2ecf20Sopenharmony_ci if (MSD(dma_get_required_mask(&ha->pdev->dev)) && 18668c2ecf20Sopenharmony_ci !dma_set_coherent_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) { 18678c2ecf20Sopenharmony_ci /* Ok, a 64bit DMA mask is applicable. */ 18688c2ecf20Sopenharmony_ci ha->flags.enable_64bit_addressing = 1; 18698c2ecf20Sopenharmony_ci ha->isp_ops->calc_req_entries = qla2x00_calc_iocbs_64; 18708c2ecf20Sopenharmony_ci ha->isp_ops->build_iocbs = qla2x00_build_scsi_iocbs_64; 18718c2ecf20Sopenharmony_ci return; 18728c2ecf20Sopenharmony_ci } 18738c2ecf20Sopenharmony_ci } 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32)); 18768c2ecf20Sopenharmony_ci dma_set_coherent_mask(&ha->pdev->dev, DMA_BIT_MASK(32)); 18778c2ecf20Sopenharmony_ci} 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_cistatic void 18808c2ecf20Sopenharmony_ciqla2x00_enable_intrs(struct qla_hw_data *ha) 18818c2ecf20Sopenharmony_ci{ 18828c2ecf20Sopenharmony_ci unsigned long flags = 0; 18838c2ecf20Sopenharmony_ci struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 18868c2ecf20Sopenharmony_ci ha->interrupts_on = 1; 18878c2ecf20Sopenharmony_ci /* enable risc and host interrupts */ 18888c2ecf20Sopenharmony_ci wrt_reg_word(®->ictrl, ICR_EN_INT | ICR_EN_RISC); 18898c2ecf20Sopenharmony_ci rd_reg_word(®->ictrl); 18908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci} 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_cistatic void 18958c2ecf20Sopenharmony_ciqla2x00_disable_intrs(struct qla_hw_data *ha) 18968c2ecf20Sopenharmony_ci{ 18978c2ecf20Sopenharmony_ci unsigned long flags = 0; 18988c2ecf20Sopenharmony_ci struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 19018c2ecf20Sopenharmony_ci ha->interrupts_on = 0; 19028c2ecf20Sopenharmony_ci /* disable risc and host interrupts */ 19038c2ecf20Sopenharmony_ci wrt_reg_word(®->ictrl, 0); 19048c2ecf20Sopenharmony_ci rd_reg_word(®->ictrl); 19058c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 19068c2ecf20Sopenharmony_ci} 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_cistatic void 19098c2ecf20Sopenharmony_ciqla24xx_enable_intrs(struct qla_hw_data *ha) 19108c2ecf20Sopenharmony_ci{ 19118c2ecf20Sopenharmony_ci unsigned long flags = 0; 19128c2ecf20Sopenharmony_ci struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 19158c2ecf20Sopenharmony_ci ha->interrupts_on = 1; 19168c2ecf20Sopenharmony_ci wrt_reg_dword(®->ictrl, ICRX_EN_RISC_INT); 19178c2ecf20Sopenharmony_ci rd_reg_dword(®->ictrl); 19188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 19198c2ecf20Sopenharmony_ci} 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_cistatic void 19228c2ecf20Sopenharmony_ciqla24xx_disable_intrs(struct qla_hw_data *ha) 19238c2ecf20Sopenharmony_ci{ 19248c2ecf20Sopenharmony_ci unsigned long flags = 0; 19258c2ecf20Sopenharmony_ci struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci if (IS_NOPOLLING_TYPE(ha)) 19288c2ecf20Sopenharmony_ci return; 19298c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 19308c2ecf20Sopenharmony_ci ha->interrupts_on = 0; 19318c2ecf20Sopenharmony_ci wrt_reg_dword(®->ictrl, 0); 19328c2ecf20Sopenharmony_ci rd_reg_dword(®->ictrl); 19338c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 19348c2ecf20Sopenharmony_ci} 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_cistatic int 19378c2ecf20Sopenharmony_ciqla2x00_iospace_config(struct qla_hw_data *ha) 19388c2ecf20Sopenharmony_ci{ 19398c2ecf20Sopenharmony_ci resource_size_t pio; 19408c2ecf20Sopenharmony_ci uint16_t msix; 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci if (pci_request_selected_regions(ha->pdev, ha->bars, 19438c2ecf20Sopenharmony_ci QLA2XXX_DRIVER_NAME)) { 19448c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0011, 19458c2ecf20Sopenharmony_ci "Failed to reserve PIO/MMIO regions (%s), aborting.\n", 19468c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 19478c2ecf20Sopenharmony_ci goto iospace_error_exit; 19488c2ecf20Sopenharmony_ci } 19498c2ecf20Sopenharmony_ci if (!(ha->bars & 1)) 19508c2ecf20Sopenharmony_ci goto skip_pio; 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci /* We only need PIO for Flash operations on ISP2312 v2 chips. */ 19538c2ecf20Sopenharmony_ci pio = pci_resource_start(ha->pdev, 0); 19548c2ecf20Sopenharmony_ci if (pci_resource_flags(ha->pdev, 0) & IORESOURCE_IO) { 19558c2ecf20Sopenharmony_ci if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) { 19568c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x0012, 19578c2ecf20Sopenharmony_ci "Invalid pci I/O region size (%s).\n", 19588c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 19598c2ecf20Sopenharmony_ci pio = 0; 19608c2ecf20Sopenharmony_ci } 19618c2ecf20Sopenharmony_ci } else { 19628c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x0013, 19638c2ecf20Sopenharmony_ci "Region #0 no a PIO resource (%s).\n", 19648c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 19658c2ecf20Sopenharmony_ci pio = 0; 19668c2ecf20Sopenharmony_ci } 19678c2ecf20Sopenharmony_ci ha->pio_address = pio; 19688c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0014, 19698c2ecf20Sopenharmony_ci "PIO address=%llu.\n", 19708c2ecf20Sopenharmony_ci (unsigned long long)ha->pio_address); 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ciskip_pio: 19738c2ecf20Sopenharmony_ci /* Use MMIO operations for all accesses. */ 19748c2ecf20Sopenharmony_ci if (!(pci_resource_flags(ha->pdev, 1) & IORESOURCE_MEM)) { 19758c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0015, 19768c2ecf20Sopenharmony_ci "Region #1 not an MMIO resource (%s), aborting.\n", 19778c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 19788c2ecf20Sopenharmony_ci goto iospace_error_exit; 19798c2ecf20Sopenharmony_ci } 19808c2ecf20Sopenharmony_ci if (pci_resource_len(ha->pdev, 1) < MIN_IOBASE_LEN) { 19818c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0016, 19828c2ecf20Sopenharmony_ci "Invalid PCI mem region size (%s), aborting.\n", 19838c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 19848c2ecf20Sopenharmony_ci goto iospace_error_exit; 19858c2ecf20Sopenharmony_ci } 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci ha->iobase = ioremap(pci_resource_start(ha->pdev, 1), MIN_IOBASE_LEN); 19888c2ecf20Sopenharmony_ci if (!ha->iobase) { 19898c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0017, 19908c2ecf20Sopenharmony_ci "Cannot remap MMIO (%s), aborting.\n", 19918c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 19928c2ecf20Sopenharmony_ci goto iospace_error_exit; 19938c2ecf20Sopenharmony_ci } 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci /* Determine queue resources */ 19968c2ecf20Sopenharmony_ci ha->max_req_queues = ha->max_rsp_queues = 1; 19978c2ecf20Sopenharmony_ci ha->msix_count = QLA_BASE_VECTORS; 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci /* Check if FW supports MQ or not */ 20008c2ecf20Sopenharmony_ci if (!(ha->fw_attributes & BIT_6)) 20018c2ecf20Sopenharmony_ci goto mqiobase_exit; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci if (!ql2xmqsupport || !ql2xnvmeenable || 20048c2ecf20Sopenharmony_ci (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) 20058c2ecf20Sopenharmony_ci goto mqiobase_exit; 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), 20088c2ecf20Sopenharmony_ci pci_resource_len(ha->pdev, 3)); 20098c2ecf20Sopenharmony_ci if (ha->mqiobase) { 20108c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0018, 20118c2ecf20Sopenharmony_ci "MQIO Base=%p.\n", ha->mqiobase); 20128c2ecf20Sopenharmony_ci /* Read MSIX vector size of the board */ 20138c2ecf20Sopenharmony_ci pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix); 20148c2ecf20Sopenharmony_ci ha->msix_count = msix + 1; 20158c2ecf20Sopenharmony_ci /* Max queues are bounded by available msix vectors */ 20168c2ecf20Sopenharmony_ci /* MB interrupt uses 1 vector */ 20178c2ecf20Sopenharmony_ci ha->max_req_queues = ha->msix_count - 1; 20188c2ecf20Sopenharmony_ci ha->max_rsp_queues = ha->max_req_queues; 20198c2ecf20Sopenharmony_ci /* Queue pairs is the max value minus the base queue pair */ 20208c2ecf20Sopenharmony_ci ha->max_qpairs = ha->max_rsp_queues - 1; 20218c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0188, 20228c2ecf20Sopenharmony_ci "Max no of queues pairs: %d.\n", ha->max_qpairs); 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x001a, 20258c2ecf20Sopenharmony_ci "MSI-X vector count: %d.\n", ha->msix_count); 20268c2ecf20Sopenharmony_ci } else 20278c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x001b, 20288c2ecf20Sopenharmony_ci "BAR 3 not enabled.\n"); 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_cimqiobase_exit: 20318c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x001c, 20328c2ecf20Sopenharmony_ci "MSIX Count: %d.\n", ha->msix_count); 20338c2ecf20Sopenharmony_ci return (0); 20348c2ecf20Sopenharmony_ci 20358c2ecf20Sopenharmony_ciiospace_error_exit: 20368c2ecf20Sopenharmony_ci return (-ENOMEM); 20378c2ecf20Sopenharmony_ci} 20388c2ecf20Sopenharmony_ci 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_cistatic int 20418c2ecf20Sopenharmony_ciqla83xx_iospace_config(struct qla_hw_data *ha) 20428c2ecf20Sopenharmony_ci{ 20438c2ecf20Sopenharmony_ci uint16_t msix; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci if (pci_request_selected_regions(ha->pdev, ha->bars, 20468c2ecf20Sopenharmony_ci QLA2XXX_DRIVER_NAME)) { 20478c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0117, 20488c2ecf20Sopenharmony_ci "Failed to reserve PIO/MMIO regions (%s), aborting.\n", 20498c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci goto iospace_error_exit; 20528c2ecf20Sopenharmony_ci } 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci /* Use MMIO operations for all accesses. */ 20558c2ecf20Sopenharmony_ci if (!(pci_resource_flags(ha->pdev, 0) & IORESOURCE_MEM)) { 20568c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x0118, 20578c2ecf20Sopenharmony_ci "Invalid pci I/O region size (%s).\n", 20588c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 20598c2ecf20Sopenharmony_ci goto iospace_error_exit; 20608c2ecf20Sopenharmony_ci } 20618c2ecf20Sopenharmony_ci if (pci_resource_len(ha->pdev, 0) < MIN_IOBASE_LEN) { 20628c2ecf20Sopenharmony_ci ql_log_pci(ql_log_warn, ha->pdev, 0x0119, 20638c2ecf20Sopenharmony_ci "Invalid PCI mem region size (%s), aborting\n", 20648c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 20658c2ecf20Sopenharmony_ci goto iospace_error_exit; 20668c2ecf20Sopenharmony_ci } 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci ha->iobase = ioremap(pci_resource_start(ha->pdev, 0), MIN_IOBASE_LEN); 20698c2ecf20Sopenharmony_ci if (!ha->iobase) { 20708c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x011a, 20718c2ecf20Sopenharmony_ci "Cannot remap MMIO (%s), aborting.\n", 20728c2ecf20Sopenharmony_ci pci_name(ha->pdev)); 20738c2ecf20Sopenharmony_ci goto iospace_error_exit; 20748c2ecf20Sopenharmony_ci } 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci /* 64bit PCI BAR - BAR2 will correspoond to region 4 */ 20778c2ecf20Sopenharmony_ci /* 83XX 26XX always use MQ type access for queues 20788c2ecf20Sopenharmony_ci * - mbar 2, a.k.a region 4 */ 20798c2ecf20Sopenharmony_ci ha->max_req_queues = ha->max_rsp_queues = 1; 20808c2ecf20Sopenharmony_ci ha->msix_count = QLA_BASE_VECTORS; 20818c2ecf20Sopenharmony_ci ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 4), 20828c2ecf20Sopenharmony_ci pci_resource_len(ha->pdev, 4)); 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci if (!ha->mqiobase) { 20858c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x011d, 20868c2ecf20Sopenharmony_ci "BAR2/region4 not enabled\n"); 20878c2ecf20Sopenharmony_ci goto mqiobase_exit; 20888c2ecf20Sopenharmony_ci } 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci ha->msixbase = ioremap(pci_resource_start(ha->pdev, 2), 20918c2ecf20Sopenharmony_ci pci_resource_len(ha->pdev, 2)); 20928c2ecf20Sopenharmony_ci if (ha->msixbase) { 20938c2ecf20Sopenharmony_ci /* Read MSIX vector size of the board */ 20948c2ecf20Sopenharmony_ci pci_read_config_word(ha->pdev, 20958c2ecf20Sopenharmony_ci QLA_83XX_PCI_MSIX_CONTROL, &msix); 20968c2ecf20Sopenharmony_ci ha->msix_count = (msix & PCI_MSIX_FLAGS_QSIZE) + 1; 20978c2ecf20Sopenharmony_ci /* 20988c2ecf20Sopenharmony_ci * By default, driver uses at least two msix vectors 20998c2ecf20Sopenharmony_ci * (default & rspq) 21008c2ecf20Sopenharmony_ci */ 21018c2ecf20Sopenharmony_ci if (ql2xmqsupport || ql2xnvmeenable) { 21028c2ecf20Sopenharmony_ci /* MB interrupt uses 1 vector */ 21038c2ecf20Sopenharmony_ci ha->max_req_queues = ha->msix_count - 1; 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci /* ATIOQ needs 1 vector. That's 1 less QPair */ 21068c2ecf20Sopenharmony_ci if (QLA_TGT_MODE_ENABLED()) 21078c2ecf20Sopenharmony_ci ha->max_req_queues--; 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci ha->max_rsp_queues = ha->max_req_queues; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci /* Queue pairs is the max value minus 21128c2ecf20Sopenharmony_ci * the base queue pair */ 21138c2ecf20Sopenharmony_ci ha->max_qpairs = ha->max_req_queues - 1; 21148c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x00e3, 21158c2ecf20Sopenharmony_ci "Max no of queues pairs: %d.\n", ha->max_qpairs); 21168c2ecf20Sopenharmony_ci } 21178c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x011c, 21188c2ecf20Sopenharmony_ci "MSI-X vector count: %d.\n", ha->msix_count); 21198c2ecf20Sopenharmony_ci } else 21208c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, ha->pdev, 0x011e, 21218c2ecf20Sopenharmony_ci "BAR 1 not enabled.\n"); 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_cimqiobase_exit: 21248c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011f, 21258c2ecf20Sopenharmony_ci "MSIX Count: %d.\n", ha->msix_count); 21268c2ecf20Sopenharmony_ci return 0; 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ciiospace_error_exit: 21298c2ecf20Sopenharmony_ci return -ENOMEM; 21308c2ecf20Sopenharmony_ci} 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_cistatic struct isp_operations qla2100_isp_ops = { 21338c2ecf20Sopenharmony_ci .pci_config = qla2100_pci_config, 21348c2ecf20Sopenharmony_ci .reset_chip = qla2x00_reset_chip, 21358c2ecf20Sopenharmony_ci .chip_diag = qla2x00_chip_diag, 21368c2ecf20Sopenharmony_ci .config_rings = qla2x00_config_rings, 21378c2ecf20Sopenharmony_ci .reset_adapter = qla2x00_reset_adapter, 21388c2ecf20Sopenharmony_ci .nvram_config = qla2x00_nvram_config, 21398c2ecf20Sopenharmony_ci .update_fw_options = qla2x00_update_fw_options, 21408c2ecf20Sopenharmony_ci .load_risc = qla2x00_load_risc, 21418c2ecf20Sopenharmony_ci .pci_info_str = qla2x00_pci_info_str, 21428c2ecf20Sopenharmony_ci .fw_version_str = qla2x00_fw_version_str, 21438c2ecf20Sopenharmony_ci .intr_handler = qla2100_intr_handler, 21448c2ecf20Sopenharmony_ci .enable_intrs = qla2x00_enable_intrs, 21458c2ecf20Sopenharmony_ci .disable_intrs = qla2x00_disable_intrs, 21468c2ecf20Sopenharmony_ci .abort_command = qla2x00_abort_command, 21478c2ecf20Sopenharmony_ci .target_reset = qla2x00_abort_target, 21488c2ecf20Sopenharmony_ci .lun_reset = qla2x00_lun_reset, 21498c2ecf20Sopenharmony_ci .fabric_login = qla2x00_login_fabric, 21508c2ecf20Sopenharmony_ci .fabric_logout = qla2x00_fabric_logout, 21518c2ecf20Sopenharmony_ci .calc_req_entries = qla2x00_calc_iocbs_32, 21528c2ecf20Sopenharmony_ci .build_iocbs = qla2x00_build_scsi_iocbs_32, 21538c2ecf20Sopenharmony_ci .prep_ms_iocb = qla2x00_prep_ms_iocb, 21548c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb, 21558c2ecf20Sopenharmony_ci .read_nvram = qla2x00_read_nvram_data, 21568c2ecf20Sopenharmony_ci .write_nvram = qla2x00_write_nvram_data, 21578c2ecf20Sopenharmony_ci .fw_dump = qla2100_fw_dump, 21588c2ecf20Sopenharmony_ci .beacon_on = NULL, 21598c2ecf20Sopenharmony_ci .beacon_off = NULL, 21608c2ecf20Sopenharmony_ci .beacon_blink = NULL, 21618c2ecf20Sopenharmony_ci .read_optrom = qla2x00_read_optrom_data, 21628c2ecf20Sopenharmony_ci .write_optrom = qla2x00_write_optrom_data, 21638c2ecf20Sopenharmony_ci .get_flash_version = qla2x00_get_flash_version, 21648c2ecf20Sopenharmony_ci .start_scsi = qla2x00_start_scsi, 21658c2ecf20Sopenharmony_ci .start_scsi_mq = NULL, 21668c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 21678c2ecf20Sopenharmony_ci .iospace_config = qla2x00_iospace_config, 21688c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 21698c2ecf20Sopenharmony_ci}; 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_cistatic struct isp_operations qla2300_isp_ops = { 21728c2ecf20Sopenharmony_ci .pci_config = qla2300_pci_config, 21738c2ecf20Sopenharmony_ci .reset_chip = qla2x00_reset_chip, 21748c2ecf20Sopenharmony_ci .chip_diag = qla2x00_chip_diag, 21758c2ecf20Sopenharmony_ci .config_rings = qla2x00_config_rings, 21768c2ecf20Sopenharmony_ci .reset_adapter = qla2x00_reset_adapter, 21778c2ecf20Sopenharmony_ci .nvram_config = qla2x00_nvram_config, 21788c2ecf20Sopenharmony_ci .update_fw_options = qla2x00_update_fw_options, 21798c2ecf20Sopenharmony_ci .load_risc = qla2x00_load_risc, 21808c2ecf20Sopenharmony_ci .pci_info_str = qla2x00_pci_info_str, 21818c2ecf20Sopenharmony_ci .fw_version_str = qla2x00_fw_version_str, 21828c2ecf20Sopenharmony_ci .intr_handler = qla2300_intr_handler, 21838c2ecf20Sopenharmony_ci .enable_intrs = qla2x00_enable_intrs, 21848c2ecf20Sopenharmony_ci .disable_intrs = qla2x00_disable_intrs, 21858c2ecf20Sopenharmony_ci .abort_command = qla2x00_abort_command, 21868c2ecf20Sopenharmony_ci .target_reset = qla2x00_abort_target, 21878c2ecf20Sopenharmony_ci .lun_reset = qla2x00_lun_reset, 21888c2ecf20Sopenharmony_ci .fabric_login = qla2x00_login_fabric, 21898c2ecf20Sopenharmony_ci .fabric_logout = qla2x00_fabric_logout, 21908c2ecf20Sopenharmony_ci .calc_req_entries = qla2x00_calc_iocbs_32, 21918c2ecf20Sopenharmony_ci .build_iocbs = qla2x00_build_scsi_iocbs_32, 21928c2ecf20Sopenharmony_ci .prep_ms_iocb = qla2x00_prep_ms_iocb, 21938c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla2x00_prep_ms_fdmi_iocb, 21948c2ecf20Sopenharmony_ci .read_nvram = qla2x00_read_nvram_data, 21958c2ecf20Sopenharmony_ci .write_nvram = qla2x00_write_nvram_data, 21968c2ecf20Sopenharmony_ci .fw_dump = qla2300_fw_dump, 21978c2ecf20Sopenharmony_ci .beacon_on = qla2x00_beacon_on, 21988c2ecf20Sopenharmony_ci .beacon_off = qla2x00_beacon_off, 21998c2ecf20Sopenharmony_ci .beacon_blink = qla2x00_beacon_blink, 22008c2ecf20Sopenharmony_ci .read_optrom = qla2x00_read_optrom_data, 22018c2ecf20Sopenharmony_ci .write_optrom = qla2x00_write_optrom_data, 22028c2ecf20Sopenharmony_ci .get_flash_version = qla2x00_get_flash_version, 22038c2ecf20Sopenharmony_ci .start_scsi = qla2x00_start_scsi, 22048c2ecf20Sopenharmony_ci .start_scsi_mq = NULL, 22058c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 22068c2ecf20Sopenharmony_ci .iospace_config = qla2x00_iospace_config, 22078c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 22088c2ecf20Sopenharmony_ci}; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_cistatic struct isp_operations qla24xx_isp_ops = { 22118c2ecf20Sopenharmony_ci .pci_config = qla24xx_pci_config, 22128c2ecf20Sopenharmony_ci .reset_chip = qla24xx_reset_chip, 22138c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 22148c2ecf20Sopenharmony_ci .config_rings = qla24xx_config_rings, 22158c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 22168c2ecf20Sopenharmony_ci .nvram_config = qla24xx_nvram_config, 22178c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 22188c2ecf20Sopenharmony_ci .load_risc = qla24xx_load_risc, 22198c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 22208c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 22218c2ecf20Sopenharmony_ci .intr_handler = qla24xx_intr_handler, 22228c2ecf20Sopenharmony_ci .enable_intrs = qla24xx_enable_intrs, 22238c2ecf20Sopenharmony_ci .disable_intrs = qla24xx_disable_intrs, 22248c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 22258c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 22268c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 22278c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 22288c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 22298c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 22308c2ecf20Sopenharmony_ci .build_iocbs = NULL, 22318c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 22328c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 22338c2ecf20Sopenharmony_ci .read_nvram = qla24xx_read_nvram_data, 22348c2ecf20Sopenharmony_ci .write_nvram = qla24xx_write_nvram_data, 22358c2ecf20Sopenharmony_ci .fw_dump = qla24xx_fw_dump, 22368c2ecf20Sopenharmony_ci .beacon_on = qla24xx_beacon_on, 22378c2ecf20Sopenharmony_ci .beacon_off = qla24xx_beacon_off, 22388c2ecf20Sopenharmony_ci .beacon_blink = qla24xx_beacon_blink, 22398c2ecf20Sopenharmony_ci .read_optrom = qla24xx_read_optrom_data, 22408c2ecf20Sopenharmony_ci .write_optrom = qla24xx_write_optrom_data, 22418c2ecf20Sopenharmony_ci .get_flash_version = qla24xx_get_flash_version, 22428c2ecf20Sopenharmony_ci .start_scsi = qla24xx_start_scsi, 22438c2ecf20Sopenharmony_ci .start_scsi_mq = NULL, 22448c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 22458c2ecf20Sopenharmony_ci .iospace_config = qla2x00_iospace_config, 22468c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 22478c2ecf20Sopenharmony_ci}; 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_cistatic struct isp_operations qla25xx_isp_ops = { 22508c2ecf20Sopenharmony_ci .pci_config = qla25xx_pci_config, 22518c2ecf20Sopenharmony_ci .reset_chip = qla24xx_reset_chip, 22528c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 22538c2ecf20Sopenharmony_ci .config_rings = qla24xx_config_rings, 22548c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 22558c2ecf20Sopenharmony_ci .nvram_config = qla24xx_nvram_config, 22568c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 22578c2ecf20Sopenharmony_ci .load_risc = qla24xx_load_risc, 22588c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 22598c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 22608c2ecf20Sopenharmony_ci .intr_handler = qla24xx_intr_handler, 22618c2ecf20Sopenharmony_ci .enable_intrs = qla24xx_enable_intrs, 22628c2ecf20Sopenharmony_ci .disable_intrs = qla24xx_disable_intrs, 22638c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 22648c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 22658c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 22668c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 22678c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 22688c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 22698c2ecf20Sopenharmony_ci .build_iocbs = NULL, 22708c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 22718c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 22728c2ecf20Sopenharmony_ci .read_nvram = qla25xx_read_nvram_data, 22738c2ecf20Sopenharmony_ci .write_nvram = qla25xx_write_nvram_data, 22748c2ecf20Sopenharmony_ci .fw_dump = qla25xx_fw_dump, 22758c2ecf20Sopenharmony_ci .beacon_on = qla24xx_beacon_on, 22768c2ecf20Sopenharmony_ci .beacon_off = qla24xx_beacon_off, 22778c2ecf20Sopenharmony_ci .beacon_blink = qla24xx_beacon_blink, 22788c2ecf20Sopenharmony_ci .read_optrom = qla25xx_read_optrom_data, 22798c2ecf20Sopenharmony_ci .write_optrom = qla24xx_write_optrom_data, 22808c2ecf20Sopenharmony_ci .get_flash_version = qla24xx_get_flash_version, 22818c2ecf20Sopenharmony_ci .start_scsi = qla24xx_dif_start_scsi, 22828c2ecf20Sopenharmony_ci .start_scsi_mq = qla2xxx_dif_start_scsi_mq, 22838c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 22848c2ecf20Sopenharmony_ci .iospace_config = qla2x00_iospace_config, 22858c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 22868c2ecf20Sopenharmony_ci}; 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_cistatic struct isp_operations qla81xx_isp_ops = { 22898c2ecf20Sopenharmony_ci .pci_config = qla25xx_pci_config, 22908c2ecf20Sopenharmony_ci .reset_chip = qla24xx_reset_chip, 22918c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 22928c2ecf20Sopenharmony_ci .config_rings = qla24xx_config_rings, 22938c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 22948c2ecf20Sopenharmony_ci .nvram_config = qla81xx_nvram_config, 22958c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 22968c2ecf20Sopenharmony_ci .load_risc = qla81xx_load_risc, 22978c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 22988c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 22998c2ecf20Sopenharmony_ci .intr_handler = qla24xx_intr_handler, 23008c2ecf20Sopenharmony_ci .enable_intrs = qla24xx_enable_intrs, 23018c2ecf20Sopenharmony_ci .disable_intrs = qla24xx_disable_intrs, 23028c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 23038c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 23048c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 23058c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 23068c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 23078c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 23088c2ecf20Sopenharmony_ci .build_iocbs = NULL, 23098c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 23108c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 23118c2ecf20Sopenharmony_ci .read_nvram = NULL, 23128c2ecf20Sopenharmony_ci .write_nvram = NULL, 23138c2ecf20Sopenharmony_ci .fw_dump = qla81xx_fw_dump, 23148c2ecf20Sopenharmony_ci .beacon_on = qla24xx_beacon_on, 23158c2ecf20Sopenharmony_ci .beacon_off = qla24xx_beacon_off, 23168c2ecf20Sopenharmony_ci .beacon_blink = qla83xx_beacon_blink, 23178c2ecf20Sopenharmony_ci .read_optrom = qla25xx_read_optrom_data, 23188c2ecf20Sopenharmony_ci .write_optrom = qla24xx_write_optrom_data, 23198c2ecf20Sopenharmony_ci .get_flash_version = qla24xx_get_flash_version, 23208c2ecf20Sopenharmony_ci .start_scsi = qla24xx_dif_start_scsi, 23218c2ecf20Sopenharmony_ci .start_scsi_mq = qla2xxx_dif_start_scsi_mq, 23228c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 23238c2ecf20Sopenharmony_ci .iospace_config = qla2x00_iospace_config, 23248c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 23258c2ecf20Sopenharmony_ci}; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_cistatic struct isp_operations qla82xx_isp_ops = { 23288c2ecf20Sopenharmony_ci .pci_config = qla82xx_pci_config, 23298c2ecf20Sopenharmony_ci .reset_chip = qla82xx_reset_chip, 23308c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 23318c2ecf20Sopenharmony_ci .config_rings = qla82xx_config_rings, 23328c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 23338c2ecf20Sopenharmony_ci .nvram_config = qla81xx_nvram_config, 23348c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 23358c2ecf20Sopenharmony_ci .load_risc = qla82xx_load_risc, 23368c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 23378c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 23388c2ecf20Sopenharmony_ci .intr_handler = qla82xx_intr_handler, 23398c2ecf20Sopenharmony_ci .enable_intrs = qla82xx_enable_intrs, 23408c2ecf20Sopenharmony_ci .disable_intrs = qla82xx_disable_intrs, 23418c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 23428c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 23438c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 23448c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 23458c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 23468c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 23478c2ecf20Sopenharmony_ci .build_iocbs = NULL, 23488c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 23498c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 23508c2ecf20Sopenharmony_ci .read_nvram = qla24xx_read_nvram_data, 23518c2ecf20Sopenharmony_ci .write_nvram = qla24xx_write_nvram_data, 23528c2ecf20Sopenharmony_ci .fw_dump = qla82xx_fw_dump, 23538c2ecf20Sopenharmony_ci .beacon_on = qla82xx_beacon_on, 23548c2ecf20Sopenharmony_ci .beacon_off = qla82xx_beacon_off, 23558c2ecf20Sopenharmony_ci .beacon_blink = NULL, 23568c2ecf20Sopenharmony_ci .read_optrom = qla82xx_read_optrom_data, 23578c2ecf20Sopenharmony_ci .write_optrom = qla82xx_write_optrom_data, 23588c2ecf20Sopenharmony_ci .get_flash_version = qla82xx_get_flash_version, 23598c2ecf20Sopenharmony_ci .start_scsi = qla82xx_start_scsi, 23608c2ecf20Sopenharmony_ci .start_scsi_mq = NULL, 23618c2ecf20Sopenharmony_ci .abort_isp = qla82xx_abort_isp, 23628c2ecf20Sopenharmony_ci .iospace_config = qla82xx_iospace_config, 23638c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 23648c2ecf20Sopenharmony_ci}; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_cistatic struct isp_operations qla8044_isp_ops = { 23678c2ecf20Sopenharmony_ci .pci_config = qla82xx_pci_config, 23688c2ecf20Sopenharmony_ci .reset_chip = qla82xx_reset_chip, 23698c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 23708c2ecf20Sopenharmony_ci .config_rings = qla82xx_config_rings, 23718c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 23728c2ecf20Sopenharmony_ci .nvram_config = qla81xx_nvram_config, 23738c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 23748c2ecf20Sopenharmony_ci .load_risc = qla82xx_load_risc, 23758c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 23768c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 23778c2ecf20Sopenharmony_ci .intr_handler = qla8044_intr_handler, 23788c2ecf20Sopenharmony_ci .enable_intrs = qla82xx_enable_intrs, 23798c2ecf20Sopenharmony_ci .disable_intrs = qla82xx_disable_intrs, 23808c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 23818c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 23828c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 23838c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 23848c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 23858c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 23868c2ecf20Sopenharmony_ci .build_iocbs = NULL, 23878c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 23888c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 23898c2ecf20Sopenharmony_ci .read_nvram = NULL, 23908c2ecf20Sopenharmony_ci .write_nvram = NULL, 23918c2ecf20Sopenharmony_ci .fw_dump = qla8044_fw_dump, 23928c2ecf20Sopenharmony_ci .beacon_on = qla82xx_beacon_on, 23938c2ecf20Sopenharmony_ci .beacon_off = qla82xx_beacon_off, 23948c2ecf20Sopenharmony_ci .beacon_blink = NULL, 23958c2ecf20Sopenharmony_ci .read_optrom = qla8044_read_optrom_data, 23968c2ecf20Sopenharmony_ci .write_optrom = qla8044_write_optrom_data, 23978c2ecf20Sopenharmony_ci .get_flash_version = qla82xx_get_flash_version, 23988c2ecf20Sopenharmony_ci .start_scsi = qla82xx_start_scsi, 23998c2ecf20Sopenharmony_ci .start_scsi_mq = NULL, 24008c2ecf20Sopenharmony_ci .abort_isp = qla8044_abort_isp, 24018c2ecf20Sopenharmony_ci .iospace_config = qla82xx_iospace_config, 24028c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 24038c2ecf20Sopenharmony_ci}; 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_cistatic struct isp_operations qla83xx_isp_ops = { 24068c2ecf20Sopenharmony_ci .pci_config = qla25xx_pci_config, 24078c2ecf20Sopenharmony_ci .reset_chip = qla24xx_reset_chip, 24088c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 24098c2ecf20Sopenharmony_ci .config_rings = qla24xx_config_rings, 24108c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 24118c2ecf20Sopenharmony_ci .nvram_config = qla81xx_nvram_config, 24128c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 24138c2ecf20Sopenharmony_ci .load_risc = qla81xx_load_risc, 24148c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 24158c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 24168c2ecf20Sopenharmony_ci .intr_handler = qla24xx_intr_handler, 24178c2ecf20Sopenharmony_ci .enable_intrs = qla24xx_enable_intrs, 24188c2ecf20Sopenharmony_ci .disable_intrs = qla24xx_disable_intrs, 24198c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 24208c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 24218c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 24228c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 24238c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 24248c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 24258c2ecf20Sopenharmony_ci .build_iocbs = NULL, 24268c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 24278c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 24288c2ecf20Sopenharmony_ci .read_nvram = NULL, 24298c2ecf20Sopenharmony_ci .write_nvram = NULL, 24308c2ecf20Sopenharmony_ci .fw_dump = qla83xx_fw_dump, 24318c2ecf20Sopenharmony_ci .beacon_on = qla24xx_beacon_on, 24328c2ecf20Sopenharmony_ci .beacon_off = qla24xx_beacon_off, 24338c2ecf20Sopenharmony_ci .beacon_blink = qla83xx_beacon_blink, 24348c2ecf20Sopenharmony_ci .read_optrom = qla25xx_read_optrom_data, 24358c2ecf20Sopenharmony_ci .write_optrom = qla24xx_write_optrom_data, 24368c2ecf20Sopenharmony_ci .get_flash_version = qla24xx_get_flash_version, 24378c2ecf20Sopenharmony_ci .start_scsi = qla24xx_dif_start_scsi, 24388c2ecf20Sopenharmony_ci .start_scsi_mq = qla2xxx_dif_start_scsi_mq, 24398c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 24408c2ecf20Sopenharmony_ci .iospace_config = qla83xx_iospace_config, 24418c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 24428c2ecf20Sopenharmony_ci}; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_cistatic struct isp_operations qlafx00_isp_ops = { 24458c2ecf20Sopenharmony_ci .pci_config = qlafx00_pci_config, 24468c2ecf20Sopenharmony_ci .reset_chip = qlafx00_soft_reset, 24478c2ecf20Sopenharmony_ci .chip_diag = qlafx00_chip_diag, 24488c2ecf20Sopenharmony_ci .config_rings = qlafx00_config_rings, 24498c2ecf20Sopenharmony_ci .reset_adapter = qlafx00_soft_reset, 24508c2ecf20Sopenharmony_ci .nvram_config = NULL, 24518c2ecf20Sopenharmony_ci .update_fw_options = NULL, 24528c2ecf20Sopenharmony_ci .load_risc = NULL, 24538c2ecf20Sopenharmony_ci .pci_info_str = qlafx00_pci_info_str, 24548c2ecf20Sopenharmony_ci .fw_version_str = qlafx00_fw_version_str, 24558c2ecf20Sopenharmony_ci .intr_handler = qlafx00_intr_handler, 24568c2ecf20Sopenharmony_ci .enable_intrs = qlafx00_enable_intrs, 24578c2ecf20Sopenharmony_ci .disable_intrs = qlafx00_disable_intrs, 24588c2ecf20Sopenharmony_ci .abort_command = qla24xx_async_abort_command, 24598c2ecf20Sopenharmony_ci .target_reset = qlafx00_abort_target, 24608c2ecf20Sopenharmony_ci .lun_reset = qlafx00_lun_reset, 24618c2ecf20Sopenharmony_ci .fabric_login = NULL, 24628c2ecf20Sopenharmony_ci .fabric_logout = NULL, 24638c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 24648c2ecf20Sopenharmony_ci .build_iocbs = NULL, 24658c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 24668c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 24678c2ecf20Sopenharmony_ci .read_nvram = qla24xx_read_nvram_data, 24688c2ecf20Sopenharmony_ci .write_nvram = qla24xx_write_nvram_data, 24698c2ecf20Sopenharmony_ci .fw_dump = NULL, 24708c2ecf20Sopenharmony_ci .beacon_on = qla24xx_beacon_on, 24718c2ecf20Sopenharmony_ci .beacon_off = qla24xx_beacon_off, 24728c2ecf20Sopenharmony_ci .beacon_blink = NULL, 24738c2ecf20Sopenharmony_ci .read_optrom = qla24xx_read_optrom_data, 24748c2ecf20Sopenharmony_ci .write_optrom = qla24xx_write_optrom_data, 24758c2ecf20Sopenharmony_ci .get_flash_version = qla24xx_get_flash_version, 24768c2ecf20Sopenharmony_ci .start_scsi = qlafx00_start_scsi, 24778c2ecf20Sopenharmony_ci .start_scsi_mq = NULL, 24788c2ecf20Sopenharmony_ci .abort_isp = qlafx00_abort_isp, 24798c2ecf20Sopenharmony_ci .iospace_config = qlafx00_iospace_config, 24808c2ecf20Sopenharmony_ci .initialize_adapter = qlafx00_initialize_adapter, 24818c2ecf20Sopenharmony_ci}; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_cistatic struct isp_operations qla27xx_isp_ops = { 24848c2ecf20Sopenharmony_ci .pci_config = qla25xx_pci_config, 24858c2ecf20Sopenharmony_ci .reset_chip = qla24xx_reset_chip, 24868c2ecf20Sopenharmony_ci .chip_diag = qla24xx_chip_diag, 24878c2ecf20Sopenharmony_ci .config_rings = qla24xx_config_rings, 24888c2ecf20Sopenharmony_ci .reset_adapter = qla24xx_reset_adapter, 24898c2ecf20Sopenharmony_ci .nvram_config = qla81xx_nvram_config, 24908c2ecf20Sopenharmony_ci .update_fw_options = qla24xx_update_fw_options, 24918c2ecf20Sopenharmony_ci .load_risc = qla81xx_load_risc, 24928c2ecf20Sopenharmony_ci .pci_info_str = qla24xx_pci_info_str, 24938c2ecf20Sopenharmony_ci .fw_version_str = qla24xx_fw_version_str, 24948c2ecf20Sopenharmony_ci .intr_handler = qla24xx_intr_handler, 24958c2ecf20Sopenharmony_ci .enable_intrs = qla24xx_enable_intrs, 24968c2ecf20Sopenharmony_ci .disable_intrs = qla24xx_disable_intrs, 24978c2ecf20Sopenharmony_ci .abort_command = qla24xx_abort_command, 24988c2ecf20Sopenharmony_ci .target_reset = qla24xx_abort_target, 24998c2ecf20Sopenharmony_ci .lun_reset = qla24xx_lun_reset, 25008c2ecf20Sopenharmony_ci .fabric_login = qla24xx_login_fabric, 25018c2ecf20Sopenharmony_ci .fabric_logout = qla24xx_fabric_logout, 25028c2ecf20Sopenharmony_ci .calc_req_entries = NULL, 25038c2ecf20Sopenharmony_ci .build_iocbs = NULL, 25048c2ecf20Sopenharmony_ci .prep_ms_iocb = qla24xx_prep_ms_iocb, 25058c2ecf20Sopenharmony_ci .prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb, 25068c2ecf20Sopenharmony_ci .read_nvram = NULL, 25078c2ecf20Sopenharmony_ci .write_nvram = NULL, 25088c2ecf20Sopenharmony_ci .fw_dump = qla27xx_fwdump, 25098c2ecf20Sopenharmony_ci .mpi_fw_dump = qla27xx_mpi_fwdump, 25108c2ecf20Sopenharmony_ci .beacon_on = qla24xx_beacon_on, 25118c2ecf20Sopenharmony_ci .beacon_off = qla24xx_beacon_off, 25128c2ecf20Sopenharmony_ci .beacon_blink = qla83xx_beacon_blink, 25138c2ecf20Sopenharmony_ci .read_optrom = qla25xx_read_optrom_data, 25148c2ecf20Sopenharmony_ci .write_optrom = qla24xx_write_optrom_data, 25158c2ecf20Sopenharmony_ci .get_flash_version = qla24xx_get_flash_version, 25168c2ecf20Sopenharmony_ci .start_scsi = qla24xx_dif_start_scsi, 25178c2ecf20Sopenharmony_ci .start_scsi_mq = qla2xxx_dif_start_scsi_mq, 25188c2ecf20Sopenharmony_ci .abort_isp = qla2x00_abort_isp, 25198c2ecf20Sopenharmony_ci .iospace_config = qla83xx_iospace_config, 25208c2ecf20Sopenharmony_ci .initialize_adapter = qla2x00_initialize_adapter, 25218c2ecf20Sopenharmony_ci}; 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_cistatic inline void 25248c2ecf20Sopenharmony_ciqla2x00_set_isp_flags(struct qla_hw_data *ha) 25258c2ecf20Sopenharmony_ci{ 25268c2ecf20Sopenharmony_ci ha->device_type = DT_EXTENDED_IDS; 25278c2ecf20Sopenharmony_ci switch (ha->pdev->device) { 25288c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2100: 25298c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2100; 25308c2ecf20Sopenharmony_ci ha->device_type &= ~DT_EXTENDED_IDS; 25318c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2100; 25328c2ecf20Sopenharmony_ci break; 25338c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2200: 25348c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2200; 25358c2ecf20Sopenharmony_ci ha->device_type &= ~DT_EXTENDED_IDS; 25368c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2100; 25378c2ecf20Sopenharmony_ci break; 25388c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2300: 25398c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2300; 25408c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25418c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2300; 25428c2ecf20Sopenharmony_ci break; 25438c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2312: 25448c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2312; 25458c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25468c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2300; 25478c2ecf20Sopenharmony_ci break; 25488c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2322: 25498c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2322; 25508c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25518c2ecf20Sopenharmony_ci if (ha->pdev->subsystem_vendor == 0x1028 && 25528c2ecf20Sopenharmony_ci ha->pdev->subsystem_device == 0x0170) 25538c2ecf20Sopenharmony_ci ha->device_type |= DT_OEM_001; 25548c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2300; 25558c2ecf20Sopenharmony_ci break; 25568c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP6312: 25578c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP6312; 25588c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2300; 25598c2ecf20Sopenharmony_ci break; 25608c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP6322: 25618c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP6322; 25628c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2300; 25638c2ecf20Sopenharmony_ci break; 25648c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2422: 25658c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2422; 25668c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25678c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 25688c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 25698c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 25708c2ecf20Sopenharmony_ci break; 25718c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2432: 25728c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2432; 25738c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25748c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 25758c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 25768c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 25778c2ecf20Sopenharmony_ci break; 25788c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP8432: 25798c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP8432; 25808c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25818c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 25828c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 25838c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 25848c2ecf20Sopenharmony_ci break; 25858c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP5422: 25868c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP5422; 25878c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 25888c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 25898c2ecf20Sopenharmony_ci break; 25908c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP5432: 25918c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP5432; 25928c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 25938c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 25948c2ecf20Sopenharmony_ci break; 25958c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2532: 25968c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2532; 25978c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 25988c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 25998c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26008c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26018c2ecf20Sopenharmony_ci break; 26028c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP8001: 26038c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP8001; 26048c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26058c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26068c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26078c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26088c2ecf20Sopenharmony_ci break; 26098c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP8021: 26108c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP8021; 26118c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26128c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26138c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26148c2ecf20Sopenharmony_ci /* Initialize 82XX ISP flags */ 26158c2ecf20Sopenharmony_ci qla82xx_init_flags(ha); 26168c2ecf20Sopenharmony_ci break; 26178c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP8044: 26188c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP8044; 26198c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26208c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26218c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26228c2ecf20Sopenharmony_ci /* Initialize 82XX ISP flags */ 26238c2ecf20Sopenharmony_ci qla82xx_init_flags(ha); 26248c2ecf20Sopenharmony_ci break; 26258c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2031: 26268c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2031; 26278c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26288c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26298c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26308c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26318c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26328c2ecf20Sopenharmony_ci break; 26338c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP8031: 26348c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP8031; 26358c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26368c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26378c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26388c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26398c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26408c2ecf20Sopenharmony_ci break; 26418c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISPF001: 26428c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISPFX00; 26438c2ecf20Sopenharmony_ci break; 26448c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2071: 26458c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2071; 26468c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26478c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26488c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26498c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26508c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26518c2ecf20Sopenharmony_ci break; 26528c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2271: 26538c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2271; 26548c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26558c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26568c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26578c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26588c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26598c2ecf20Sopenharmony_ci break; 26608c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2261: 26618c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2261; 26628c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26638c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26648c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26658c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26668c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26678c2ecf20Sopenharmony_ci break; 26688c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2081: 26698c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2089: 26708c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2081; 26718c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26728c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26738c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26748c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26758c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26768c2ecf20Sopenharmony_ci break; 26778c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2281: 26788c2ecf20Sopenharmony_ci case PCI_DEVICE_ID_QLOGIC_ISP2289: 26798c2ecf20Sopenharmony_ci ha->isp_type |= DT_ISP2281; 26808c2ecf20Sopenharmony_ci ha->device_type |= DT_ZIO_SUPPORTED; 26818c2ecf20Sopenharmony_ci ha->device_type |= DT_FWI2; 26828c2ecf20Sopenharmony_ci ha->device_type |= DT_IIDMA; 26838c2ecf20Sopenharmony_ci ha->device_type |= DT_T10_PI; 26848c2ecf20Sopenharmony_ci ha->fw_srisc_address = RISC_START_ADDRESS_2400; 26858c2ecf20Sopenharmony_ci break; 26868c2ecf20Sopenharmony_ci } 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) 26898c2ecf20Sopenharmony_ci ha->port_no = ha->portnum & 1; 26908c2ecf20Sopenharmony_ci else { 26918c2ecf20Sopenharmony_ci /* Get adapter physical port no from interrupt pin register. */ 26928c2ecf20Sopenharmony_ci pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no); 26938c2ecf20Sopenharmony_ci if (IS_QLA25XX(ha) || IS_QLA2031(ha) || 26948c2ecf20Sopenharmony_ci IS_QLA27XX(ha) || IS_QLA28XX(ha)) 26958c2ecf20Sopenharmony_ci ha->port_no--; 26968c2ecf20Sopenharmony_ci else 26978c2ecf20Sopenharmony_ci ha->port_no = !(ha->port_no & 1); 26988c2ecf20Sopenharmony_ci } 26998c2ecf20Sopenharmony_ci 27008c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x000b, 27018c2ecf20Sopenharmony_ci "device_type=0x%x port=%d fw_srisc_address=0x%x.\n", 27028c2ecf20Sopenharmony_ci ha->device_type, ha->port_no, ha->fw_srisc_address); 27038c2ecf20Sopenharmony_ci} 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_cistatic void 27068c2ecf20Sopenharmony_ciqla2xxx_scan_start(struct Scsi_Host *shost) 27078c2ecf20Sopenharmony_ci{ 27088c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci if (vha->hw->flags.running_gold_fw) 27118c2ecf20Sopenharmony_ci return; 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 27148c2ecf20Sopenharmony_ci set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); 27158c2ecf20Sopenharmony_ci set_bit(RSCN_UPDATE, &vha->dpc_flags); 27168c2ecf20Sopenharmony_ci set_bit(NPIV_CONFIG_NEEDED, &vha->dpc_flags); 27178c2ecf20Sopenharmony_ci} 27188c2ecf20Sopenharmony_ci 27198c2ecf20Sopenharmony_cistatic int 27208c2ecf20Sopenharmony_ciqla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) 27218c2ecf20Sopenharmony_ci{ 27228c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = shost_priv(shost); 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &vha->dpc_flags)) 27258c2ecf20Sopenharmony_ci return 1; 27268c2ecf20Sopenharmony_ci if (!vha->host) 27278c2ecf20Sopenharmony_ci return 1; 27288c2ecf20Sopenharmony_ci if (time > vha->hw->loop_reset_delay * HZ) 27298c2ecf20Sopenharmony_ci return 1; 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_ci return atomic_read(&vha->loop_state) == LOOP_READY; 27328c2ecf20Sopenharmony_ci} 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_cistatic void qla2x00_iocb_work_fn(struct work_struct *work) 27358c2ecf20Sopenharmony_ci{ 27368c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = container_of(work, 27378c2ecf20Sopenharmony_ci struct scsi_qla_host, iocb_work); 27388c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 27398c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 27408c2ecf20Sopenharmony_ci int i = 2; 27418c2ecf20Sopenharmony_ci unsigned long flags; 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &base_vha->dpc_flags)) 27448c2ecf20Sopenharmony_ci return; 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_ci while (!list_empty(&vha->work_list) && i > 0) { 27478c2ecf20Sopenharmony_ci qla2x00_do_work(vha); 27488c2ecf20Sopenharmony_ci i--; 27498c2ecf20Sopenharmony_ci } 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->work_lock, flags); 27528c2ecf20Sopenharmony_ci clear_bit(IOCB_WORK_ACTIVE, &vha->dpc_flags); 27538c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->work_lock, flags); 27548c2ecf20Sopenharmony_ci} 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci/* 27578c2ecf20Sopenharmony_ci * PCI driver interface 27588c2ecf20Sopenharmony_ci */ 27598c2ecf20Sopenharmony_cistatic int 27608c2ecf20Sopenharmony_ciqla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) 27618c2ecf20Sopenharmony_ci{ 27628c2ecf20Sopenharmony_ci int ret = -ENODEV; 27638c2ecf20Sopenharmony_ci struct Scsi_Host *host; 27648c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = NULL; 27658c2ecf20Sopenharmony_ci struct qla_hw_data *ha; 27668c2ecf20Sopenharmony_ci char pci_info[30]; 27678c2ecf20Sopenharmony_ci char fw_str[30], wq_name[30]; 27688c2ecf20Sopenharmony_ci struct scsi_host_template *sht; 27698c2ecf20Sopenharmony_ci int bars, mem_only = 0; 27708c2ecf20Sopenharmony_ci uint16_t req_length = 0, rsp_length = 0; 27718c2ecf20Sopenharmony_ci struct req_que *req = NULL; 27728c2ecf20Sopenharmony_ci struct rsp_que *rsp = NULL; 27738c2ecf20Sopenharmony_ci int i; 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); 27768c2ecf20Sopenharmony_ci sht = &qla2xxx_driver_template; 27778c2ecf20Sopenharmony_ci if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || 27788c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || 27798c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 || 27808c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5422 || 27818c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP5432 || 27828c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 || 27838c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001 || 27848c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8021 || 27858c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2031 || 27868c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8031 || 27878c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISPF001 || 27888c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8044 || 27898c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2071 || 27908c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2271 || 27918c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261 || 27928c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2081 || 27938c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2281 || 27948c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2089 || 27958c2ecf20Sopenharmony_ci pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2289) { 27968c2ecf20Sopenharmony_ci bars = pci_select_bars(pdev, IORESOURCE_MEM); 27978c2ecf20Sopenharmony_ci mem_only = 1; 27988c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, pdev, 0x0007, 27998c2ecf20Sopenharmony_ci "Mem only adapter.\n"); 28008c2ecf20Sopenharmony_ci } 28018c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, pdev, 0x0008, 28028c2ecf20Sopenharmony_ci "Bars=%d.\n", bars); 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci if (mem_only) { 28058c2ecf20Sopenharmony_ci if (pci_enable_device_mem(pdev)) 28068c2ecf20Sopenharmony_ci return ret; 28078c2ecf20Sopenharmony_ci } else { 28088c2ecf20Sopenharmony_ci if (pci_enable_device(pdev)) 28098c2ecf20Sopenharmony_ci return ret; 28108c2ecf20Sopenharmony_ci } 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci if (is_kdump_kernel()) { 28138c2ecf20Sopenharmony_ci ql2xmqsupport = 0; 28148c2ecf20Sopenharmony_ci ql2xallocfwdump = 0; 28158c2ecf20Sopenharmony_ci } 28168c2ecf20Sopenharmony_ci 28178c2ecf20Sopenharmony_ci /* This may fail but that's ok */ 28188c2ecf20Sopenharmony_ci pci_enable_pcie_error_reporting(pdev); 28198c2ecf20Sopenharmony_ci 28208c2ecf20Sopenharmony_ci ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); 28218c2ecf20Sopenharmony_ci if (!ha) { 28228c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, pdev, 0x0009, 28238c2ecf20Sopenharmony_ci "Unable to allocate memory for ha.\n"); 28248c2ecf20Sopenharmony_ci goto disable_device; 28258c2ecf20Sopenharmony_ci } 28268c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, pdev, 0x000a, 28278c2ecf20Sopenharmony_ci "Memory allocated for ha=%p.\n", ha); 28288c2ecf20Sopenharmony_ci ha->pdev = pdev; 28298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->tgt.q_full_list); 28308c2ecf20Sopenharmony_ci spin_lock_init(&ha->tgt.q_full_lock); 28318c2ecf20Sopenharmony_ci spin_lock_init(&ha->tgt.sess_lock); 28328c2ecf20Sopenharmony_ci spin_lock_init(&ha->tgt.atio_lock); 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci atomic_set(&ha->nvme_active_aen_cnt, 0); 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci /* Clear our data area */ 28378c2ecf20Sopenharmony_ci ha->bars = bars; 28388c2ecf20Sopenharmony_ci ha->mem_only = mem_only; 28398c2ecf20Sopenharmony_ci spin_lock_init(&ha->hardware_lock); 28408c2ecf20Sopenharmony_ci spin_lock_init(&ha->vport_slock); 28418c2ecf20Sopenharmony_ci mutex_init(&ha->selflogin_lock); 28428c2ecf20Sopenharmony_ci mutex_init(&ha->optrom_mutex); 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci /* Set ISP-type information. */ 28458c2ecf20Sopenharmony_ci qla2x00_set_isp_flags(ha); 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci /* Set EEH reset type to fundamental if required by hba */ 28488c2ecf20Sopenharmony_ci if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha) || 28498c2ecf20Sopenharmony_ci IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) 28508c2ecf20Sopenharmony_ci pdev->needs_freset = 1; 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci ha->prev_topology = 0; 28538c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(init_cb_t); 28548c2ecf20Sopenharmony_ci ha->link_data_rate = PORT_SPEED_UNKNOWN; 28558c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_2300; 28568c2ecf20Sopenharmony_ci ha->max_exchg = FW_MAX_EXCHANGES_CNT; 28578c2ecf20Sopenharmony_ci atomic_set(&ha->num_pend_mbx_stage1, 0); 28588c2ecf20Sopenharmony_ci atomic_set(&ha->num_pend_mbx_stage2, 0); 28598c2ecf20Sopenharmony_ci atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD); 28608c2ecf20Sopenharmony_ci ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD; 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci /* Assign ISP specific operations. */ 28638c2ecf20Sopenharmony_ci if (IS_QLA2100(ha)) { 28648c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2100; 28658c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT_2100; 28668c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_2100; 28678c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2100; 28688c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2100; 28698c2ecf20Sopenharmony_ci ha->gid_list_info_size = 4; 28708c2ecf20Sopenharmony_ci ha->flash_conf_off = ~0; 28718c2ecf20Sopenharmony_ci ha->flash_data_off = ~0; 28728c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 28738c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 28748c2ecf20Sopenharmony_ci ha->isp_ops = &qla2100_isp_ops; 28758c2ecf20Sopenharmony_ci } else if (IS_QLA2200(ha)) { 28768c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2100; 28778c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT_2200; 28788c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_2200; 28798c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2100; 28808c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2100; 28818c2ecf20Sopenharmony_ci ha->gid_list_info_size = 4; 28828c2ecf20Sopenharmony_ci ha->flash_conf_off = ~0; 28838c2ecf20Sopenharmony_ci ha->flash_data_off = ~0; 28848c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 28858c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 28868c2ecf20Sopenharmony_ci ha->isp_ops = &qla2100_isp_ops; 28878c2ecf20Sopenharmony_ci } else if (IS_QLA23XX(ha)) { 28888c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2100; 28898c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 28908c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_2200; 28918c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2300; 28928c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 28938c2ecf20Sopenharmony_ci ha->gid_list_info_size = 6; 28948c2ecf20Sopenharmony_ci if (IS_QLA2322(ha) || IS_QLA6322(ha)) 28958c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_2322; 28968c2ecf20Sopenharmony_ci ha->flash_conf_off = ~0; 28978c2ecf20Sopenharmony_ci ha->flash_data_off = ~0; 28988c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 28998c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 29008c2ecf20Sopenharmony_ci ha->isp_ops = &qla2300_isp_ops; 29018c2ecf20Sopenharmony_ci } else if (IS_QLA24XX_TYPE(ha)) { 29028c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 29038c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 29048c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_24XX; 29058c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2300; 29068c2ecf20Sopenharmony_ci ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 29078c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 29088c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_24xx); 29098c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 29108c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_24XX; 29118c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA24XX; 29128c2ecf20Sopenharmony_ci ha->isp_ops = &qla24xx_isp_ops; 29138c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF; 29148c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA; 29158c2ecf20Sopenharmony_ci ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF; 29168c2ecf20Sopenharmony_ci ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA; 29178c2ecf20Sopenharmony_ci } else if (IS_QLA25XX(ha)) { 29188c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 29198c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 29208c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_24XX; 29218c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2300; 29228c2ecf20Sopenharmony_ci ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 29238c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 29248c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_24xx); 29258c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 29268c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_25XX; 29278c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 29288c2ecf20Sopenharmony_ci ha->isp_ops = &qla25xx_isp_ops; 29298c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF; 29308c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA; 29318c2ecf20Sopenharmony_ci ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF; 29328c2ecf20Sopenharmony_ci ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA; 29338c2ecf20Sopenharmony_ci } else if (IS_QLA81XX(ha)) { 29348c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 29358c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 29368c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_24XX; 29378c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2300; 29388c2ecf20Sopenharmony_ci ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 29398c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 29408c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 29418c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 29428c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_81XX; 29438c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 29448c2ecf20Sopenharmony_ci ha->isp_ops = &qla81xx_isp_ops; 29458c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_81XX; 29468c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; 29478c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 29488c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 29498c2ecf20Sopenharmony_ci } else if (IS_QLA82XX(ha)) { 29508c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 29518c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 29528c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_82XX; 29538c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_82XX; 29548c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 29558c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 29568c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 29578c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_82XX; 29588c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 29598c2ecf20Sopenharmony_ci ha->isp_ops = &qla82xx_isp_ops; 29608c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF; 29618c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA; 29628c2ecf20Sopenharmony_ci ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF; 29638c2ecf20Sopenharmony_ci ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA; 29648c2ecf20Sopenharmony_ci } else if (IS_QLA8044(ha)) { 29658c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 29668c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 29678c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_82XX; 29688c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_82XX; 29698c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 29708c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 29718c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 29728c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_83XX; 29738c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 29748c2ecf20Sopenharmony_ci ha->isp_ops = &qla8044_isp_ops; 29758c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF; 29768c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA; 29778c2ecf20Sopenharmony_ci ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF; 29788c2ecf20Sopenharmony_ci ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA; 29798c2ecf20Sopenharmony_ci } else if (IS_QLA83XX(ha)) { 29808c2ecf20Sopenharmony_ci ha->portnum = PCI_FUNC(ha->pdev->devfn); 29818c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 29828c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 29838c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_83XX; 29848c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_83XX; 29858c2ecf20Sopenharmony_ci ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 29868c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 29878c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 29888c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 29898c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_83XX; 29908c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 29918c2ecf20Sopenharmony_ci ha->isp_ops = &qla83xx_isp_ops; 29928c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_81XX; 29938c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; 29948c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 29958c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 29968c2ecf20Sopenharmony_ci } else if (IS_QLAFX00(ha)) { 29978c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_FX00; 29988c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT_FX00; 29998c2ecf20Sopenharmony_ci ha->aen_mbx_count = AEN_MAILBOX_REGISTER_COUNT_FX00; 30008c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_FX00; 30018c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_FX00; 30028c2ecf20Sopenharmony_ci ha->isp_ops = &qlafx00_isp_ops; 30038c2ecf20Sopenharmony_ci ha->port_down_retry_count = 30; /* default value */ 30048c2ecf20Sopenharmony_ci ha->mr.fw_hbt_cnt = QLAFX00_HEARTBEAT_INTERVAL; 30058c2ecf20Sopenharmony_ci ha->mr.fw_reset_timer_tick = QLAFX00_RESET_INTERVAL; 30068c2ecf20Sopenharmony_ci ha->mr.fw_critemp_timer_tick = QLAFX00_CRITEMP_INTERVAL; 30078c2ecf20Sopenharmony_ci ha->mr.fw_hbt_en = 1; 30088c2ecf20Sopenharmony_ci ha->mr.host_info_resend = false; 30098c2ecf20Sopenharmony_ci ha->mr.hinfo_resend_timer_tick = QLAFX00_HINFO_RESEND_INTERVAL; 30108c2ecf20Sopenharmony_ci } else if (IS_QLA27XX(ha)) { 30118c2ecf20Sopenharmony_ci ha->portnum = PCI_FUNC(ha->pdev->devfn); 30128c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 30138c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 30148c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_83XX; 30158c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_83XX; 30168c2ecf20Sopenharmony_ci ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 30178c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 30188c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 30198c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 30208c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_83XX; 30218c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 30228c2ecf20Sopenharmony_ci ha->isp_ops = &qla27xx_isp_ops; 30238c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_81XX; 30248c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX; 30258c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 30268c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 30278c2ecf20Sopenharmony_ci } else if (IS_QLA28XX(ha)) { 30288c2ecf20Sopenharmony_ci ha->portnum = PCI_FUNC(ha->pdev->devfn); 30298c2ecf20Sopenharmony_ci ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 30308c2ecf20Sopenharmony_ci ha->mbx_count = MAILBOX_REGISTER_COUNT; 30318c2ecf20Sopenharmony_ci req_length = REQUEST_ENTRY_CNT_24XX; 30328c2ecf20Sopenharmony_ci rsp_length = RESPONSE_ENTRY_CNT_2300; 30338c2ecf20Sopenharmony_ci ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 30348c2ecf20Sopenharmony_ci ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 30358c2ecf20Sopenharmony_ci ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 30368c2ecf20Sopenharmony_ci ha->gid_list_info_size = 8; 30378c2ecf20Sopenharmony_ci ha->optrom_size = OPTROM_SIZE_28XX; 30388c2ecf20Sopenharmony_ci ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX; 30398c2ecf20Sopenharmony_ci ha->isp_ops = &qla27xx_isp_ops; 30408c2ecf20Sopenharmony_ci ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_28XX; 30418c2ecf20Sopenharmony_ci ha->flash_data_off = FARX_ACCESS_FLASH_DATA_28XX; 30428c2ecf20Sopenharmony_ci ha->nvram_conf_off = ~0; 30438c2ecf20Sopenharmony_ci ha->nvram_data_off = ~0; 30448c2ecf20Sopenharmony_ci } 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, pdev, 0x001e, 30478c2ecf20Sopenharmony_ci "mbx_count=%d, req_length=%d, " 30488c2ecf20Sopenharmony_ci "rsp_length=%d, max_loop_id=%d, init_cb_size=%d, " 30498c2ecf20Sopenharmony_ci "gid_list_info_size=%d, optrom_size=%d, nvram_npiv_size=%d, " 30508c2ecf20Sopenharmony_ci "max_fibre_devices=%d.\n", 30518c2ecf20Sopenharmony_ci ha->mbx_count, req_length, rsp_length, ha->max_loop_id, 30528c2ecf20Sopenharmony_ci ha->init_cb_size, ha->gid_list_info_size, ha->optrom_size, 30538c2ecf20Sopenharmony_ci ha->nvram_npiv_size, ha->max_fibre_devices); 30548c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, pdev, 0x001f, 30558c2ecf20Sopenharmony_ci "isp_ops=%p, flash_conf_off=%d, " 30568c2ecf20Sopenharmony_ci "flash_data_off=%d, nvram_conf_off=%d, nvram_data_off=%d.\n", 30578c2ecf20Sopenharmony_ci ha->isp_ops, ha->flash_conf_off, ha->flash_data_off, 30588c2ecf20Sopenharmony_ci ha->nvram_conf_off, ha->nvram_data_off); 30598c2ecf20Sopenharmony_ci 30608c2ecf20Sopenharmony_ci /* Configure PCI I/O space */ 30618c2ecf20Sopenharmony_ci ret = ha->isp_ops->iospace_config(ha); 30628c2ecf20Sopenharmony_ci if (ret) 30638c2ecf20Sopenharmony_ci goto iospace_config_failed; 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_ci ql_log_pci(ql_log_info, pdev, 0x001d, 30668c2ecf20Sopenharmony_ci "Found an ISP%04X irq %d iobase 0x%p.\n", 30678c2ecf20Sopenharmony_ci pdev->device, pdev->irq, ha->iobase); 30688c2ecf20Sopenharmony_ci mutex_init(&ha->vport_lock); 30698c2ecf20Sopenharmony_ci mutex_init(&ha->mq_lock); 30708c2ecf20Sopenharmony_ci init_completion(&ha->mbx_cmd_comp); 30718c2ecf20Sopenharmony_ci complete(&ha->mbx_cmd_comp); 30728c2ecf20Sopenharmony_ci init_completion(&ha->mbx_intr_comp); 30738c2ecf20Sopenharmony_ci init_completion(&ha->dcbx_comp); 30748c2ecf20Sopenharmony_ci init_completion(&ha->lb_portup_comp); 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci set_bit(0, (unsigned long *) ha->vp_idx_map); 30778c2ecf20Sopenharmony_ci 30788c2ecf20Sopenharmony_ci qla2x00_config_dma_addressing(ha); 30798c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, pdev, 0x0020, 30808c2ecf20Sopenharmony_ci "64 Bit addressing is %s.\n", 30818c2ecf20Sopenharmony_ci ha->flags.enable_64bit_addressing ? "enable" : 30828c2ecf20Sopenharmony_ci "disable"); 30838c2ecf20Sopenharmony_ci ret = qla2x00_mem_alloc(ha, req_length, rsp_length, &req, &rsp); 30848c2ecf20Sopenharmony_ci if (ret) { 30858c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, pdev, 0x0031, 30868c2ecf20Sopenharmony_ci "Failed to allocate memory for adapter, aborting.\n"); 30878c2ecf20Sopenharmony_ci 30888c2ecf20Sopenharmony_ci goto probe_hw_failed; 30898c2ecf20Sopenharmony_ci } 30908c2ecf20Sopenharmony_ci 30918c2ecf20Sopenharmony_ci req->max_q_depth = MAX_Q_DEPTH; 30928c2ecf20Sopenharmony_ci if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU) 30938c2ecf20Sopenharmony_ci req->max_q_depth = ql2xmaxqdepth; 30948c2ecf20Sopenharmony_ci 30958c2ecf20Sopenharmony_ci 30968c2ecf20Sopenharmony_ci base_vha = qla2x00_create_host(sht, ha); 30978c2ecf20Sopenharmony_ci if (!base_vha) { 30988c2ecf20Sopenharmony_ci ret = -ENOMEM; 30998c2ecf20Sopenharmony_ci goto probe_hw_failed; 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci 31028c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, base_vha); 31038c2ecf20Sopenharmony_ci set_bit(PFLG_DRIVER_PROBING, &base_vha->pci_flags); 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci host = base_vha->host; 31068c2ecf20Sopenharmony_ci base_vha->req = req; 31078c2ecf20Sopenharmony_ci if (IS_QLA2XXX_MIDTYPE(ha)) 31088c2ecf20Sopenharmony_ci base_vha->mgmt_svr_loop_id = 31098c2ecf20Sopenharmony_ci qla2x00_reserve_mgmt_server_loop_id(base_vha); 31108c2ecf20Sopenharmony_ci else 31118c2ecf20Sopenharmony_ci base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER + 31128c2ecf20Sopenharmony_ci base_vha->vp_idx; 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci /* Setup fcport template structure. */ 31158c2ecf20Sopenharmony_ci ha->mr.fcport.vha = base_vha; 31168c2ecf20Sopenharmony_ci ha->mr.fcport.port_type = FCT_UNKNOWN; 31178c2ecf20Sopenharmony_ci ha->mr.fcport.loop_id = FC_NO_LOOP_ID; 31188c2ecf20Sopenharmony_ci qla2x00_set_fcport_state(&ha->mr.fcport, FCS_UNCONFIGURED); 31198c2ecf20Sopenharmony_ci ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED; 31208c2ecf20Sopenharmony_ci ha->mr.fcport.scan_state = 1; 31218c2ecf20Sopenharmony_ci 31228c2ecf20Sopenharmony_ci /* Set the SG table size based on ISP type */ 31238c2ecf20Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) { 31248c2ecf20Sopenharmony_ci if (IS_QLA2100(ha)) 31258c2ecf20Sopenharmony_ci host->sg_tablesize = 32; 31268c2ecf20Sopenharmony_ci } else { 31278c2ecf20Sopenharmony_ci if (!IS_QLA82XX(ha)) 31288c2ecf20Sopenharmony_ci host->sg_tablesize = QLA_SG_ALL; 31298c2ecf20Sopenharmony_ci } 31308c2ecf20Sopenharmony_ci host->max_id = ha->max_fibre_devices; 31318c2ecf20Sopenharmony_ci host->cmd_per_lun = 3; 31328c2ecf20Sopenharmony_ci host->unique_id = host->host_no; 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci if (ql2xenabledif && ql2xenabledif != 2) { 31358c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x302d, 31368c2ecf20Sopenharmony_ci "Invalid value for ql2xenabledif, resetting it to default (2)\n"); 31378c2ecf20Sopenharmony_ci ql2xenabledif = 2; 31388c2ecf20Sopenharmony_ci } 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_ci if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) 31418c2ecf20Sopenharmony_ci host->max_cmd_len = 32; 31428c2ecf20Sopenharmony_ci else 31438c2ecf20Sopenharmony_ci host->max_cmd_len = MAX_CMDSZ; 31448c2ecf20Sopenharmony_ci host->max_channel = MAX_BUSES - 1; 31458c2ecf20Sopenharmony_ci /* Older HBAs support only 16-bit LUNs */ 31468c2ecf20Sopenharmony_ci if (!IS_QLAFX00(ha) && !IS_FWI2_CAPABLE(ha) && 31478c2ecf20Sopenharmony_ci ql2xmaxlun > 0xffff) 31488c2ecf20Sopenharmony_ci host->max_lun = 0xffff; 31498c2ecf20Sopenharmony_ci else 31508c2ecf20Sopenharmony_ci host->max_lun = ql2xmaxlun; 31518c2ecf20Sopenharmony_ci host->transportt = qla2xxx_transport_template; 31528c2ecf20Sopenharmony_ci sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC); 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x0033, 31558c2ecf20Sopenharmony_ci "max_id=%d this_id=%d " 31568c2ecf20Sopenharmony_ci "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d " 31578c2ecf20Sopenharmony_ci "max_lun=%llu transportt=%p, vendor_id=%llu.\n", host->max_id, 31588c2ecf20Sopenharmony_ci host->this_id, host->cmd_per_lun, host->unique_id, 31598c2ecf20Sopenharmony_ci host->max_cmd_len, host->max_channel, host->max_lun, 31608c2ecf20Sopenharmony_ci host->transportt, sht->vendor_id); 31618c2ecf20Sopenharmony_ci 31628c2ecf20Sopenharmony_ci INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn); 31638c2ecf20Sopenharmony_ci 31648c2ecf20Sopenharmony_ci /* Set up the irqs */ 31658c2ecf20Sopenharmony_ci ret = qla2x00_request_irqs(ha, rsp); 31668c2ecf20Sopenharmony_ci if (ret) 31678c2ecf20Sopenharmony_ci goto probe_failed; 31688c2ecf20Sopenharmony_ci 31698c2ecf20Sopenharmony_ci /* Alloc arrays of request and response ring ptrs */ 31708c2ecf20Sopenharmony_ci ret = qla2x00_alloc_queues(ha, req, rsp); 31718c2ecf20Sopenharmony_ci if (ret) { 31728c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, base_vha, 0x003d, 31738c2ecf20Sopenharmony_ci "Failed to allocate memory for queue pointers..." 31748c2ecf20Sopenharmony_ci "aborting.\n"); 31758c2ecf20Sopenharmony_ci ret = -ENODEV; 31768c2ecf20Sopenharmony_ci goto probe_failed; 31778c2ecf20Sopenharmony_ci } 31788c2ecf20Sopenharmony_ci 31798c2ecf20Sopenharmony_ci if (ha->mqenable) { 31808c2ecf20Sopenharmony_ci /* number of hardware queues supported by blk/scsi-mq*/ 31818c2ecf20Sopenharmony_ci host->nr_hw_queues = ha->max_qpairs; 31828c2ecf20Sopenharmony_ci 31838c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x0192, 31848c2ecf20Sopenharmony_ci "blk/scsi-mq enabled, HW queues = %d.\n", host->nr_hw_queues); 31858c2ecf20Sopenharmony_ci } else { 31868c2ecf20Sopenharmony_ci if (ql2xnvmeenable) { 31878c2ecf20Sopenharmony_ci host->nr_hw_queues = ha->max_qpairs; 31888c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x0194, 31898c2ecf20Sopenharmony_ci "FC-NVMe support is enabled, HW queues=%d\n", 31908c2ecf20Sopenharmony_ci host->nr_hw_queues); 31918c2ecf20Sopenharmony_ci } else { 31928c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x0193, 31938c2ecf20Sopenharmony_ci "blk/scsi-mq disabled.\n"); 31948c2ecf20Sopenharmony_ci } 31958c2ecf20Sopenharmony_ci } 31968c2ecf20Sopenharmony_ci 31978c2ecf20Sopenharmony_ci qlt_probe_one_stage1(base_vha, ha); 31988c2ecf20Sopenharmony_ci 31998c2ecf20Sopenharmony_ci pci_save_state(pdev); 32008c2ecf20Sopenharmony_ci 32018c2ecf20Sopenharmony_ci /* Assign back pointers */ 32028c2ecf20Sopenharmony_ci rsp->req = req; 32038c2ecf20Sopenharmony_ci req->rsp = rsp; 32048c2ecf20Sopenharmony_ci 32058c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) { 32068c2ecf20Sopenharmony_ci ha->rsp_q_map[0] = rsp; 32078c2ecf20Sopenharmony_ci ha->req_q_map[0] = req; 32088c2ecf20Sopenharmony_ci set_bit(0, ha->req_qid_map); 32098c2ecf20Sopenharmony_ci set_bit(0, ha->rsp_qid_map); 32108c2ecf20Sopenharmony_ci } 32118c2ecf20Sopenharmony_ci 32128c2ecf20Sopenharmony_ci /* FWI2-capable only. */ 32138c2ecf20Sopenharmony_ci req->req_q_in = &ha->iobase->isp24.req_q_in; 32148c2ecf20Sopenharmony_ci req->req_q_out = &ha->iobase->isp24.req_q_out; 32158c2ecf20Sopenharmony_ci rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in; 32168c2ecf20Sopenharmony_ci rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out; 32178c2ecf20Sopenharmony_ci if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || 32188c2ecf20Sopenharmony_ci IS_QLA28XX(ha)) { 32198c2ecf20Sopenharmony_ci req->req_q_in = &ha->mqiobase->isp25mq.req_q_in; 32208c2ecf20Sopenharmony_ci req->req_q_out = &ha->mqiobase->isp25mq.req_q_out; 32218c2ecf20Sopenharmony_ci rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in; 32228c2ecf20Sopenharmony_ci rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out; 32238c2ecf20Sopenharmony_ci } 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) { 32268c2ecf20Sopenharmony_ci req->req_q_in = &ha->iobase->ispfx00.req_q_in; 32278c2ecf20Sopenharmony_ci req->req_q_out = &ha->iobase->ispfx00.req_q_out; 32288c2ecf20Sopenharmony_ci rsp->rsp_q_in = &ha->iobase->ispfx00.rsp_q_in; 32298c2ecf20Sopenharmony_ci rsp->rsp_q_out = &ha->iobase->ispfx00.rsp_q_out; 32308c2ecf20Sopenharmony_ci } 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 32338c2ecf20Sopenharmony_ci req->req_q_out = &ha->iobase->isp82.req_q_out[0]; 32348c2ecf20Sopenharmony_ci rsp->rsp_q_in = &ha->iobase->isp82.rsp_q_in[0]; 32358c2ecf20Sopenharmony_ci rsp->rsp_q_out = &ha->iobase->isp82.rsp_q_out[0]; 32368c2ecf20Sopenharmony_ci } 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_multiq, base_vha, 0xc009, 32398c2ecf20Sopenharmony_ci "rsp_q_map=%p req_q_map=%p rsp->req=%p req->rsp=%p.\n", 32408c2ecf20Sopenharmony_ci ha->rsp_q_map, ha->req_q_map, rsp->req, req->rsp); 32418c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_multiq, base_vha, 0xc00a, 32428c2ecf20Sopenharmony_ci "req->req_q_in=%p req->req_q_out=%p " 32438c2ecf20Sopenharmony_ci "rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n", 32448c2ecf20Sopenharmony_ci req->req_q_in, req->req_q_out, 32458c2ecf20Sopenharmony_ci rsp->rsp_q_in, rsp->rsp_q_out); 32468c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x003e, 32478c2ecf20Sopenharmony_ci "rsp_q_map=%p req_q_map=%p rsp->req=%p req->rsp=%p.\n", 32488c2ecf20Sopenharmony_ci ha->rsp_q_map, ha->req_q_map, rsp->req, req->rsp); 32498c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x003f, 32508c2ecf20Sopenharmony_ci "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n", 32518c2ecf20Sopenharmony_ci req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); 32528c2ecf20Sopenharmony_ci 32538c2ecf20Sopenharmony_ci ha->wq = alloc_workqueue("qla2xxx_wq", 0, 0); 32548c2ecf20Sopenharmony_ci if (unlikely(!ha->wq)) { 32558c2ecf20Sopenharmony_ci ret = -ENOMEM; 32568c2ecf20Sopenharmony_ci goto probe_failed; 32578c2ecf20Sopenharmony_ci } 32588c2ecf20Sopenharmony_ci 32598c2ecf20Sopenharmony_ci if (ha->isp_ops->initialize_adapter(base_vha)) { 32608c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, base_vha, 0x00d6, 32618c2ecf20Sopenharmony_ci "Failed to initialize adapter - Adapter flags %x.\n", 32628c2ecf20Sopenharmony_ci base_vha->device_flags); 32638c2ecf20Sopenharmony_ci 32648c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) { 32658c2ecf20Sopenharmony_ci qla82xx_idc_lock(ha); 32668c2ecf20Sopenharmony_ci qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 32678c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 32688c2ecf20Sopenharmony_ci qla82xx_idc_unlock(ha); 32698c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, base_vha, 0x00d7, 32708c2ecf20Sopenharmony_ci "HW State: FAILED.\n"); 32718c2ecf20Sopenharmony_ci } else if (IS_QLA8044(ha)) { 32728c2ecf20Sopenharmony_ci qla8044_idc_lock(ha); 32738c2ecf20Sopenharmony_ci qla8044_wr_direct(base_vha, 32748c2ecf20Sopenharmony_ci QLA8044_CRB_DEV_STATE_INDEX, 32758c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 32768c2ecf20Sopenharmony_ci qla8044_idc_unlock(ha); 32778c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, base_vha, 0x0150, 32788c2ecf20Sopenharmony_ci "HW State: FAILED.\n"); 32798c2ecf20Sopenharmony_ci } 32808c2ecf20Sopenharmony_ci 32818c2ecf20Sopenharmony_ci ret = -ENODEV; 32828c2ecf20Sopenharmony_ci goto probe_failed; 32838c2ecf20Sopenharmony_ci } 32848c2ecf20Sopenharmony_ci 32858c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) 32868c2ecf20Sopenharmony_ci host->can_queue = QLAFX00_MAX_CANQUEUE; 32878c2ecf20Sopenharmony_ci else 32888c2ecf20Sopenharmony_ci host->can_queue = req->num_outstanding_cmds - 10; 32898c2ecf20Sopenharmony_ci 32908c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x0032, 32918c2ecf20Sopenharmony_ci "can_queue=%d, req=%p, mgmt_svr_loop_id=%d, sg_tablesize=%d.\n", 32928c2ecf20Sopenharmony_ci host->can_queue, base_vha->req, 32938c2ecf20Sopenharmony_ci base_vha->mgmt_svr_loop_id, host->sg_tablesize); 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci if (ha->mqenable) { 32968c2ecf20Sopenharmony_ci bool startit = false; 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci if (QLA_TGT_MODE_ENABLED()) 32998c2ecf20Sopenharmony_ci startit = false; 33008c2ecf20Sopenharmony_ci 33018c2ecf20Sopenharmony_ci if (ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED) 33028c2ecf20Sopenharmony_ci startit = true; 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_ci /* Create start of day qpairs for Block MQ */ 33058c2ecf20Sopenharmony_ci for (i = 0; i < ha->max_qpairs; i++) 33068c2ecf20Sopenharmony_ci qla2xxx_create_qpair(base_vha, 5, 0, startit); 33078c2ecf20Sopenharmony_ci } 33088c2ecf20Sopenharmony_ci qla_init_iocb_limit(base_vha); 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_ci if (ha->flags.running_gold_fw) 33118c2ecf20Sopenharmony_ci goto skip_dpc; 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci /* 33148c2ecf20Sopenharmony_ci * Startup the kernel thread for this host adapter 33158c2ecf20Sopenharmony_ci */ 33168c2ecf20Sopenharmony_ci ha->dpc_thread = kthread_create(qla2x00_do_dpc, ha, 33178c2ecf20Sopenharmony_ci "%s_dpc", base_vha->host_str); 33188c2ecf20Sopenharmony_ci if (IS_ERR(ha->dpc_thread)) { 33198c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, base_vha, 0x00ed, 33208c2ecf20Sopenharmony_ci "Failed to start DPC thread.\n"); 33218c2ecf20Sopenharmony_ci ret = PTR_ERR(ha->dpc_thread); 33228c2ecf20Sopenharmony_ci ha->dpc_thread = NULL; 33238c2ecf20Sopenharmony_ci goto probe_failed; 33248c2ecf20Sopenharmony_ci } 33258c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x00ee, 33268c2ecf20Sopenharmony_ci "DPC thread started successfully.\n"); 33278c2ecf20Sopenharmony_ci 33288c2ecf20Sopenharmony_ci /* 33298c2ecf20Sopenharmony_ci * If we're not coming up in initiator mode, we might sit for 33308c2ecf20Sopenharmony_ci * a while without waking up the dpc thread, which leads to a 33318c2ecf20Sopenharmony_ci * stuck process warning. So just kick the dpc once here and 33328c2ecf20Sopenharmony_ci * let the kthread start (and go back to sleep in qla2x00_do_dpc). 33338c2ecf20Sopenharmony_ci */ 33348c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(base_vha); 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci INIT_WORK(&ha->board_disable, qla2x00_disable_board_on_pci_error); 33378c2ecf20Sopenharmony_ci 33388c2ecf20Sopenharmony_ci if (IS_QLA8031(ha) || IS_MCTP_CAPABLE(ha)) { 33398c2ecf20Sopenharmony_ci sprintf(wq_name, "qla2xxx_%lu_dpc_lp_wq", base_vha->host_no); 33408c2ecf20Sopenharmony_ci ha->dpc_lp_wq = create_singlethread_workqueue(wq_name); 33418c2ecf20Sopenharmony_ci INIT_WORK(&ha->idc_aen, qla83xx_service_idc_aen); 33428c2ecf20Sopenharmony_ci 33438c2ecf20Sopenharmony_ci sprintf(wq_name, "qla2xxx_%lu_dpc_hp_wq", base_vha->host_no); 33448c2ecf20Sopenharmony_ci ha->dpc_hp_wq = create_singlethread_workqueue(wq_name); 33458c2ecf20Sopenharmony_ci INIT_WORK(&ha->nic_core_reset, qla83xx_nic_core_reset_work); 33468c2ecf20Sopenharmony_ci INIT_WORK(&ha->idc_state_handler, 33478c2ecf20Sopenharmony_ci qla83xx_idc_state_handler_work); 33488c2ecf20Sopenharmony_ci INIT_WORK(&ha->nic_core_unrecoverable, 33498c2ecf20Sopenharmony_ci qla83xx_nic_core_unrecoverable_work); 33508c2ecf20Sopenharmony_ci } 33518c2ecf20Sopenharmony_ci 33528c2ecf20Sopenharmony_ciskip_dpc: 33538c2ecf20Sopenharmony_ci list_add_tail(&base_vha->list, &ha->vp_list); 33548c2ecf20Sopenharmony_ci base_vha->host->irq = ha->pdev->irq; 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci /* Initialized the timer */ 33578c2ecf20Sopenharmony_ci qla2x00_start_timer(base_vha, WATCH_INTERVAL); 33588c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x00ef, 33598c2ecf20Sopenharmony_ci "Started qla2x00_timer with " 33608c2ecf20Sopenharmony_ci "interval=%d.\n", WATCH_INTERVAL); 33618c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x00f0, 33628c2ecf20Sopenharmony_ci "Detected hba at address=%p.\n", 33638c2ecf20Sopenharmony_ci ha); 33648c2ecf20Sopenharmony_ci 33658c2ecf20Sopenharmony_ci if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { 33668c2ecf20Sopenharmony_ci if (ha->fw_attributes & BIT_4) { 33678c2ecf20Sopenharmony_ci int prot = 0, guard; 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci base_vha->flags.difdix_supported = 1; 33708c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x00f1, 33718c2ecf20Sopenharmony_ci "Registering for DIF/DIX type 1 and 3 protection.\n"); 33728c2ecf20Sopenharmony_ci if (ql2xprotmask) 33738c2ecf20Sopenharmony_ci scsi_host_set_prot(host, ql2xprotmask); 33748c2ecf20Sopenharmony_ci else 33758c2ecf20Sopenharmony_ci scsi_host_set_prot(host, 33768c2ecf20Sopenharmony_ci prot | SHOST_DIF_TYPE1_PROTECTION 33778c2ecf20Sopenharmony_ci | SHOST_DIF_TYPE2_PROTECTION 33788c2ecf20Sopenharmony_ci | SHOST_DIF_TYPE3_PROTECTION 33798c2ecf20Sopenharmony_ci | SHOST_DIX_TYPE1_PROTECTION 33808c2ecf20Sopenharmony_ci | SHOST_DIX_TYPE2_PROTECTION 33818c2ecf20Sopenharmony_ci | SHOST_DIX_TYPE3_PROTECTION); 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci guard = SHOST_DIX_GUARD_CRC; 33848c2ecf20Sopenharmony_ci 33858c2ecf20Sopenharmony_ci if (IS_PI_IPGUARD_CAPABLE(ha) && 33868c2ecf20Sopenharmony_ci (ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha))) 33878c2ecf20Sopenharmony_ci guard |= SHOST_DIX_GUARD_IP; 33888c2ecf20Sopenharmony_ci 33898c2ecf20Sopenharmony_ci if (ql2xprotguard) 33908c2ecf20Sopenharmony_ci scsi_host_set_guard(host, ql2xprotguard); 33918c2ecf20Sopenharmony_ci else 33928c2ecf20Sopenharmony_ci scsi_host_set_guard(host, guard); 33938c2ecf20Sopenharmony_ci } else 33948c2ecf20Sopenharmony_ci base_vha->flags.difdix_supported = 0; 33958c2ecf20Sopenharmony_ci } 33968c2ecf20Sopenharmony_ci 33978c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) { 34008c2ecf20Sopenharmony_ci ret = qlafx00_fx_disc(base_vha, 34018c2ecf20Sopenharmony_ci &base_vha->hw->mr.fcport, FXDISC_GET_CONFIG_INFO); 34028c2ecf20Sopenharmony_ci host->sg_tablesize = (ha->mr.extended_io_enabled) ? 34038c2ecf20Sopenharmony_ci QLA_SG_ALL : 128; 34048c2ecf20Sopenharmony_ci } 34058c2ecf20Sopenharmony_ci 34068c2ecf20Sopenharmony_ci ret = scsi_add_host(host, &pdev->dev); 34078c2ecf20Sopenharmony_ci if (ret) 34088c2ecf20Sopenharmony_ci goto probe_failed; 34098c2ecf20Sopenharmony_ci 34108c2ecf20Sopenharmony_ci base_vha->flags.init_done = 1; 34118c2ecf20Sopenharmony_ci base_vha->flags.online = 1; 34128c2ecf20Sopenharmony_ci ha->prev_minidump_failed = 0; 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x00f2, 34158c2ecf20Sopenharmony_ci "Init done and hba is online.\n"); 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci if (qla_ini_mode_enabled(base_vha) || 34188c2ecf20Sopenharmony_ci qla_dual_mode_enabled(base_vha)) 34198c2ecf20Sopenharmony_ci scsi_scan_host(host); 34208c2ecf20Sopenharmony_ci else 34218c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, base_vha, 0x0122, 34228c2ecf20Sopenharmony_ci "skipping scsi_scan_host() for non-initiator port\n"); 34238c2ecf20Sopenharmony_ci 34248c2ecf20Sopenharmony_ci qla2x00_alloc_sysfs_attr(base_vha); 34258c2ecf20Sopenharmony_ci 34268c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) { 34278c2ecf20Sopenharmony_ci ret = qlafx00_fx_disc(base_vha, 34288c2ecf20Sopenharmony_ci &base_vha->hw->mr.fcport, FXDISC_GET_PORT_INFO); 34298c2ecf20Sopenharmony_ci 34308c2ecf20Sopenharmony_ci /* Register system information */ 34318c2ecf20Sopenharmony_ci ret = qlafx00_fx_disc(base_vha, 34328c2ecf20Sopenharmony_ci &base_vha->hw->mr.fcport, FXDISC_REG_HOST_INFO); 34338c2ecf20Sopenharmony_ci } 34348c2ecf20Sopenharmony_ci 34358c2ecf20Sopenharmony_ci qla2x00_init_host_attr(base_vha); 34368c2ecf20Sopenharmony_ci 34378c2ecf20Sopenharmony_ci qla2x00_dfs_setup(base_vha); 34388c2ecf20Sopenharmony_ci 34398c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x00fb, 34408c2ecf20Sopenharmony_ci "QLogic %s - %s.\n", ha->model_number, ha->model_desc); 34418c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x00fc, 34428c2ecf20Sopenharmony_ci "ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n", 34438c2ecf20Sopenharmony_ci pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info, 34448c2ecf20Sopenharmony_ci sizeof(pci_info)), 34458c2ecf20Sopenharmony_ci pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-', 34468c2ecf20Sopenharmony_ci base_vha->host_no, 34478c2ecf20Sopenharmony_ci ha->isp_ops->fw_version_str(base_vha, fw_str, sizeof(fw_str))); 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ci qlt_add_target(ha, base_vha); 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ci clear_bit(PFLG_DRIVER_PROBING, &base_vha->pci_flags); 34528c2ecf20Sopenharmony_ci 34538c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &base_vha->dpc_flags)) 34548c2ecf20Sopenharmony_ci return -ENODEV; 34558c2ecf20Sopenharmony_ci 34568c2ecf20Sopenharmony_ci return 0; 34578c2ecf20Sopenharmony_ci 34588c2ecf20Sopenharmony_ciprobe_failed: 34598c2ecf20Sopenharmony_ci if (base_vha->gnl.l) { 34608c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, 34618c2ecf20Sopenharmony_ci base_vha->gnl.l, base_vha->gnl.ldma); 34628c2ecf20Sopenharmony_ci base_vha->gnl.l = NULL; 34638c2ecf20Sopenharmony_ci } 34648c2ecf20Sopenharmony_ci 34658c2ecf20Sopenharmony_ci if (base_vha->timer_active) 34668c2ecf20Sopenharmony_ci qla2x00_stop_timer(base_vha); 34678c2ecf20Sopenharmony_ci base_vha->flags.online = 0; 34688c2ecf20Sopenharmony_ci if (ha->dpc_thread) { 34698c2ecf20Sopenharmony_ci struct task_struct *t = ha->dpc_thread; 34708c2ecf20Sopenharmony_ci 34718c2ecf20Sopenharmony_ci ha->dpc_thread = NULL; 34728c2ecf20Sopenharmony_ci kthread_stop(t); 34738c2ecf20Sopenharmony_ci } 34748c2ecf20Sopenharmony_ci 34758c2ecf20Sopenharmony_ci qla2x00_free_device(base_vha); 34768c2ecf20Sopenharmony_ci scsi_host_put(base_vha->host); 34778c2ecf20Sopenharmony_ci /* 34788c2ecf20Sopenharmony_ci * Need to NULL out local req/rsp after 34798c2ecf20Sopenharmony_ci * qla2x00_free_device => qla2x00_free_queues frees 34808c2ecf20Sopenharmony_ci * what these are pointing to. Or else we'll 34818c2ecf20Sopenharmony_ci * fall over below in qla2x00_free_req/rsp_que. 34828c2ecf20Sopenharmony_ci */ 34838c2ecf20Sopenharmony_ci req = NULL; 34848c2ecf20Sopenharmony_ci rsp = NULL; 34858c2ecf20Sopenharmony_ci 34868c2ecf20Sopenharmony_ciprobe_hw_failed: 34878c2ecf20Sopenharmony_ci qla2x00_mem_free(ha); 34888c2ecf20Sopenharmony_ci qla2x00_free_req_que(ha, req); 34898c2ecf20Sopenharmony_ci qla2x00_free_rsp_que(ha, rsp); 34908c2ecf20Sopenharmony_ci qla2x00_clear_drv_active(ha); 34918c2ecf20Sopenharmony_ci 34928c2ecf20Sopenharmony_ciiospace_config_failed: 34938c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 34948c2ecf20Sopenharmony_ci if (!ha->nx_pcibase) 34958c2ecf20Sopenharmony_ci iounmap((device_reg_t *)ha->nx_pcibase); 34968c2ecf20Sopenharmony_ci if (!ql2xdbwr) 34978c2ecf20Sopenharmony_ci iounmap((device_reg_t *)ha->nxdb_wr_ptr); 34988c2ecf20Sopenharmony_ci } else { 34998c2ecf20Sopenharmony_ci if (ha->iobase) 35008c2ecf20Sopenharmony_ci iounmap(ha->iobase); 35018c2ecf20Sopenharmony_ci if (ha->cregbase) 35028c2ecf20Sopenharmony_ci iounmap(ha->cregbase); 35038c2ecf20Sopenharmony_ci } 35048c2ecf20Sopenharmony_ci pci_release_selected_regions(ha->pdev, ha->bars); 35058c2ecf20Sopenharmony_ci kfree(ha); 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_cidisable_device: 35088c2ecf20Sopenharmony_ci pci_disable_device(pdev); 35098c2ecf20Sopenharmony_ci return ret; 35108c2ecf20Sopenharmony_ci} 35118c2ecf20Sopenharmony_ci 35128c2ecf20Sopenharmony_cistatic void __qla_set_remove_flag(scsi_qla_host_t *base_vha) 35138c2ecf20Sopenharmony_ci{ 35148c2ecf20Sopenharmony_ci scsi_qla_host_t *vp; 35158c2ecf20Sopenharmony_ci unsigned long flags; 35168c2ecf20Sopenharmony_ci struct qla_hw_data *ha; 35178c2ecf20Sopenharmony_ci 35188c2ecf20Sopenharmony_ci if (!base_vha) 35198c2ecf20Sopenharmony_ci return; 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci ha = base_vha->hw; 35228c2ecf20Sopenharmony_ci 35238c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 35248c2ecf20Sopenharmony_ci list_for_each_entry(vp, &ha->vp_list, list) 35258c2ecf20Sopenharmony_ci set_bit(PFLG_DRIVER_REMOVING, &vp->pci_flags); 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_ci /* 35288c2ecf20Sopenharmony_ci * Indicate device removal to prevent future board_disable 35298c2ecf20Sopenharmony_ci * and wait until any pending board_disable has completed. 35308c2ecf20Sopenharmony_ci */ 35318c2ecf20Sopenharmony_ci set_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags); 35328c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 35338c2ecf20Sopenharmony_ci} 35348c2ecf20Sopenharmony_ci 35358c2ecf20Sopenharmony_cistatic void 35368c2ecf20Sopenharmony_ciqla2x00_shutdown(struct pci_dev *pdev) 35378c2ecf20Sopenharmony_ci{ 35388c2ecf20Sopenharmony_ci scsi_qla_host_t *vha; 35398c2ecf20Sopenharmony_ci struct qla_hw_data *ha; 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci vha = pci_get_drvdata(pdev); 35428c2ecf20Sopenharmony_ci ha = vha->hw; 35438c2ecf20Sopenharmony_ci 35448c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xfffa, 35458c2ecf20Sopenharmony_ci "Adapter shutdown\n"); 35468c2ecf20Sopenharmony_ci 35478c2ecf20Sopenharmony_ci /* 35488c2ecf20Sopenharmony_ci * Prevent future board_disable and wait 35498c2ecf20Sopenharmony_ci * until any pending board_disable has completed. 35508c2ecf20Sopenharmony_ci */ 35518c2ecf20Sopenharmony_ci __qla_set_remove_flag(vha); 35528c2ecf20Sopenharmony_ci cancel_work_sync(&ha->board_disable); 35538c2ecf20Sopenharmony_ci 35548c2ecf20Sopenharmony_ci if (!atomic_read(&pdev->enable_cnt)) 35558c2ecf20Sopenharmony_ci return; 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci /* Notify ISPFX00 firmware */ 35588c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) 35598c2ecf20Sopenharmony_ci qlafx00_driver_shutdown(vha, 20); 35608c2ecf20Sopenharmony_ci 35618c2ecf20Sopenharmony_ci /* Turn-off FCE trace */ 35628c2ecf20Sopenharmony_ci if (ha->flags.fce_enabled) { 35638c2ecf20Sopenharmony_ci qla2x00_disable_fce_trace(vha, NULL, NULL); 35648c2ecf20Sopenharmony_ci ha->flags.fce_enabled = 0; 35658c2ecf20Sopenharmony_ci } 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_ci /* Turn-off EFT trace */ 35688c2ecf20Sopenharmony_ci if (ha->eft) 35698c2ecf20Sopenharmony_ci qla2x00_disable_eft_trace(vha); 35708c2ecf20Sopenharmony_ci 35718c2ecf20Sopenharmony_ci if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || 35728c2ecf20Sopenharmony_ci IS_QLA28XX(ha)) { 35738c2ecf20Sopenharmony_ci if (ha->flags.fw_started) 35748c2ecf20Sopenharmony_ci qla2x00_abort_isp_cleanup(vha); 35758c2ecf20Sopenharmony_ci } else { 35768c2ecf20Sopenharmony_ci /* Stop currently executing firmware. */ 35778c2ecf20Sopenharmony_ci qla2x00_try_to_stop_firmware(vha); 35788c2ecf20Sopenharmony_ci } 35798c2ecf20Sopenharmony_ci 35808c2ecf20Sopenharmony_ci /* Disable timer */ 35818c2ecf20Sopenharmony_ci if (vha->timer_active) 35828c2ecf20Sopenharmony_ci qla2x00_stop_timer(vha); 35838c2ecf20Sopenharmony_ci 35848c2ecf20Sopenharmony_ci /* Turn adapter off line */ 35858c2ecf20Sopenharmony_ci vha->flags.online = 0; 35868c2ecf20Sopenharmony_ci 35878c2ecf20Sopenharmony_ci /* turn-off interrupts on the card */ 35888c2ecf20Sopenharmony_ci if (ha->interrupts_on) { 35898c2ecf20Sopenharmony_ci vha->flags.init_done = 0; 35908c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 35918c2ecf20Sopenharmony_ci } 35928c2ecf20Sopenharmony_ci 35938c2ecf20Sopenharmony_ci qla2x00_free_irqs(vha); 35948c2ecf20Sopenharmony_ci 35958c2ecf20Sopenharmony_ci qla2x00_free_fw_dump(ha); 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_ci pci_disable_device(pdev); 35988c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xfffe, 35998c2ecf20Sopenharmony_ci "Adapter shutdown successfully.\n"); 36008c2ecf20Sopenharmony_ci} 36018c2ecf20Sopenharmony_ci 36028c2ecf20Sopenharmony_ci/* Deletes all the virtual ports for a given ha */ 36038c2ecf20Sopenharmony_cistatic void 36048c2ecf20Sopenharmony_ciqla2x00_delete_all_vps(struct qla_hw_data *ha, scsi_qla_host_t *base_vha) 36058c2ecf20Sopenharmony_ci{ 36068c2ecf20Sopenharmony_ci scsi_qla_host_t *vha; 36078c2ecf20Sopenharmony_ci unsigned long flags; 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_ci mutex_lock(&ha->vport_lock); 36108c2ecf20Sopenharmony_ci while (ha->cur_vport_count) { 36118c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci BUG_ON(base_vha->list.next == &ha->vp_list); 36148c2ecf20Sopenharmony_ci /* This assumes first entry in ha->vp_list is always base vha */ 36158c2ecf20Sopenharmony_ci vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list); 36168c2ecf20Sopenharmony_ci scsi_host_get(vha->host); 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 36198c2ecf20Sopenharmony_ci mutex_unlock(&ha->vport_lock); 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_ci qla_nvme_delete(vha); 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci fc_vport_terminate(vha->fc_vport); 36248c2ecf20Sopenharmony_ci scsi_host_put(vha->host); 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci mutex_lock(&ha->vport_lock); 36278c2ecf20Sopenharmony_ci } 36288c2ecf20Sopenharmony_ci mutex_unlock(&ha->vport_lock); 36298c2ecf20Sopenharmony_ci} 36308c2ecf20Sopenharmony_ci 36318c2ecf20Sopenharmony_ci/* Stops all deferred work threads */ 36328c2ecf20Sopenharmony_cistatic void 36338c2ecf20Sopenharmony_ciqla2x00_destroy_deferred_work(struct qla_hw_data *ha) 36348c2ecf20Sopenharmony_ci{ 36358c2ecf20Sopenharmony_ci /* Cancel all work and destroy DPC workqueues */ 36368c2ecf20Sopenharmony_ci if (ha->dpc_lp_wq) { 36378c2ecf20Sopenharmony_ci cancel_work_sync(&ha->idc_aen); 36388c2ecf20Sopenharmony_ci destroy_workqueue(ha->dpc_lp_wq); 36398c2ecf20Sopenharmony_ci ha->dpc_lp_wq = NULL; 36408c2ecf20Sopenharmony_ci } 36418c2ecf20Sopenharmony_ci 36428c2ecf20Sopenharmony_ci if (ha->dpc_hp_wq) { 36438c2ecf20Sopenharmony_ci cancel_work_sync(&ha->nic_core_reset); 36448c2ecf20Sopenharmony_ci cancel_work_sync(&ha->idc_state_handler); 36458c2ecf20Sopenharmony_ci cancel_work_sync(&ha->nic_core_unrecoverable); 36468c2ecf20Sopenharmony_ci destroy_workqueue(ha->dpc_hp_wq); 36478c2ecf20Sopenharmony_ci ha->dpc_hp_wq = NULL; 36488c2ecf20Sopenharmony_ci } 36498c2ecf20Sopenharmony_ci 36508c2ecf20Sopenharmony_ci /* Kill the kernel thread for this host */ 36518c2ecf20Sopenharmony_ci if (ha->dpc_thread) { 36528c2ecf20Sopenharmony_ci struct task_struct *t = ha->dpc_thread; 36538c2ecf20Sopenharmony_ci 36548c2ecf20Sopenharmony_ci /* 36558c2ecf20Sopenharmony_ci * qla2xxx_wake_dpc checks for ->dpc_thread 36568c2ecf20Sopenharmony_ci * so we need to zero it out. 36578c2ecf20Sopenharmony_ci */ 36588c2ecf20Sopenharmony_ci ha->dpc_thread = NULL; 36598c2ecf20Sopenharmony_ci kthread_stop(t); 36608c2ecf20Sopenharmony_ci } 36618c2ecf20Sopenharmony_ci} 36628c2ecf20Sopenharmony_ci 36638c2ecf20Sopenharmony_cistatic void 36648c2ecf20Sopenharmony_ciqla2x00_unmap_iobases(struct qla_hw_data *ha) 36658c2ecf20Sopenharmony_ci{ 36668c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) { 36678c2ecf20Sopenharmony_ci 36688c2ecf20Sopenharmony_ci iounmap((device_reg_t *)ha->nx_pcibase); 36698c2ecf20Sopenharmony_ci if (!ql2xdbwr) 36708c2ecf20Sopenharmony_ci iounmap((device_reg_t *)ha->nxdb_wr_ptr); 36718c2ecf20Sopenharmony_ci } else { 36728c2ecf20Sopenharmony_ci if (ha->iobase) 36738c2ecf20Sopenharmony_ci iounmap(ha->iobase); 36748c2ecf20Sopenharmony_ci 36758c2ecf20Sopenharmony_ci if (ha->cregbase) 36768c2ecf20Sopenharmony_ci iounmap(ha->cregbase); 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_ci if (ha->mqiobase) 36798c2ecf20Sopenharmony_ci iounmap(ha->mqiobase); 36808c2ecf20Sopenharmony_ci 36818c2ecf20Sopenharmony_ci if (ha->msixbase) 36828c2ecf20Sopenharmony_ci iounmap(ha->msixbase); 36838c2ecf20Sopenharmony_ci } 36848c2ecf20Sopenharmony_ci} 36858c2ecf20Sopenharmony_ci 36868c2ecf20Sopenharmony_cistatic void 36878c2ecf20Sopenharmony_ciqla2x00_clear_drv_active(struct qla_hw_data *ha) 36888c2ecf20Sopenharmony_ci{ 36898c2ecf20Sopenharmony_ci if (IS_QLA8044(ha)) { 36908c2ecf20Sopenharmony_ci qla8044_idc_lock(ha); 36918c2ecf20Sopenharmony_ci qla8044_clear_drv_active(ha); 36928c2ecf20Sopenharmony_ci qla8044_idc_unlock(ha); 36938c2ecf20Sopenharmony_ci } else if (IS_QLA82XX(ha)) { 36948c2ecf20Sopenharmony_ci qla82xx_idc_lock(ha); 36958c2ecf20Sopenharmony_ci qla82xx_clear_drv_active(ha); 36968c2ecf20Sopenharmony_ci qla82xx_idc_unlock(ha); 36978c2ecf20Sopenharmony_ci } 36988c2ecf20Sopenharmony_ci} 36998c2ecf20Sopenharmony_ci 37008c2ecf20Sopenharmony_cistatic void 37018c2ecf20Sopenharmony_ciqla2x00_remove_one(struct pci_dev *pdev) 37028c2ecf20Sopenharmony_ci{ 37038c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha; 37048c2ecf20Sopenharmony_ci struct qla_hw_data *ha; 37058c2ecf20Sopenharmony_ci 37068c2ecf20Sopenharmony_ci base_vha = pci_get_drvdata(pdev); 37078c2ecf20Sopenharmony_ci ha = base_vha->hw; 37088c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0xb079, 37098c2ecf20Sopenharmony_ci "Removing driver\n"); 37108c2ecf20Sopenharmony_ci __qla_set_remove_flag(base_vha); 37118c2ecf20Sopenharmony_ci cancel_work_sync(&ha->board_disable); 37128c2ecf20Sopenharmony_ci 37138c2ecf20Sopenharmony_ci /* 37148c2ecf20Sopenharmony_ci * If the PCI device is disabled then there was a PCI-disconnect and 37158c2ecf20Sopenharmony_ci * qla2x00_disable_board_on_pci_error has taken care of most of the 37168c2ecf20Sopenharmony_ci * resources. 37178c2ecf20Sopenharmony_ci */ 37188c2ecf20Sopenharmony_ci if (!atomic_read(&pdev->enable_cnt)) { 37198c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size, 37208c2ecf20Sopenharmony_ci base_vha->gnl.l, base_vha->gnl.ldma); 37218c2ecf20Sopenharmony_ci base_vha->gnl.l = NULL; 37228c2ecf20Sopenharmony_ci scsi_host_put(base_vha->host); 37238c2ecf20Sopenharmony_ci kfree(ha); 37248c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, NULL); 37258c2ecf20Sopenharmony_ci return; 37268c2ecf20Sopenharmony_ci } 37278c2ecf20Sopenharmony_ci qla2x00_wait_for_hba_ready(base_vha); 37288c2ecf20Sopenharmony_ci 37298c2ecf20Sopenharmony_ci /* 37308c2ecf20Sopenharmony_ci * if UNLOADING flag is already set, then continue unload, 37318c2ecf20Sopenharmony_ci * where it was set first. 37328c2ecf20Sopenharmony_ci */ 37338c2ecf20Sopenharmony_ci if (test_and_set_bit(UNLOADING, &base_vha->dpc_flags)) 37348c2ecf20Sopenharmony_ci return; 37358c2ecf20Sopenharmony_ci 37368c2ecf20Sopenharmony_ci if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || 37378c2ecf20Sopenharmony_ci IS_QLA28XX(ha)) { 37388c2ecf20Sopenharmony_ci if (ha->flags.fw_started) 37398c2ecf20Sopenharmony_ci qla2x00_abort_isp_cleanup(base_vha); 37408c2ecf20Sopenharmony_ci } else if (!IS_QLAFX00(ha)) { 37418c2ecf20Sopenharmony_ci if (IS_QLA8031(ha)) { 37428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb07e, 37438c2ecf20Sopenharmony_ci "Clearing fcoe driver presence.\n"); 37448c2ecf20Sopenharmony_ci if (qla83xx_clear_drv_presence(base_vha) != QLA_SUCCESS) 37458c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb079, 37468c2ecf20Sopenharmony_ci "Error while clearing DRV-Presence.\n"); 37478c2ecf20Sopenharmony_ci } 37488c2ecf20Sopenharmony_ci 37498c2ecf20Sopenharmony_ci qla2x00_try_to_stop_firmware(base_vha); 37508c2ecf20Sopenharmony_ci } 37518c2ecf20Sopenharmony_ci 37528c2ecf20Sopenharmony_ci qla2x00_wait_for_sess_deletion(base_vha); 37538c2ecf20Sopenharmony_ci 37548c2ecf20Sopenharmony_ci qla_nvme_delete(base_vha); 37558c2ecf20Sopenharmony_ci 37568c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 37578c2ecf20Sopenharmony_ci base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma); 37588c2ecf20Sopenharmony_ci 37598c2ecf20Sopenharmony_ci base_vha->gnl.l = NULL; 37608c2ecf20Sopenharmony_ci 37618c2ecf20Sopenharmony_ci vfree(base_vha->scan.l); 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) 37648c2ecf20Sopenharmony_ci qlafx00_driver_shutdown(base_vha, 20); 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ci qla2x00_delete_all_vps(ha, base_vha); 37678c2ecf20Sopenharmony_ci 37688c2ecf20Sopenharmony_ci qla2x00_dfs_remove(base_vha); 37698c2ecf20Sopenharmony_ci 37708c2ecf20Sopenharmony_ci qla84xx_put_chip(base_vha); 37718c2ecf20Sopenharmony_ci 37728c2ecf20Sopenharmony_ci /* Disable timer */ 37738c2ecf20Sopenharmony_ci if (base_vha->timer_active) 37748c2ecf20Sopenharmony_ci qla2x00_stop_timer(base_vha); 37758c2ecf20Sopenharmony_ci 37768c2ecf20Sopenharmony_ci base_vha->flags.online = 0; 37778c2ecf20Sopenharmony_ci 37788c2ecf20Sopenharmony_ci /* free DMA memory */ 37798c2ecf20Sopenharmony_ci if (ha->exlogin_buf) 37808c2ecf20Sopenharmony_ci qla2x00_free_exlogin_buffer(ha); 37818c2ecf20Sopenharmony_ci 37828c2ecf20Sopenharmony_ci /* free DMA memory */ 37838c2ecf20Sopenharmony_ci if (ha->exchoffld_buf) 37848c2ecf20Sopenharmony_ci qla2x00_free_exchoffld_buffer(ha); 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_ci qla2x00_destroy_deferred_work(ha); 37878c2ecf20Sopenharmony_ci 37888c2ecf20Sopenharmony_ci qlt_remove_target(ha, base_vha); 37898c2ecf20Sopenharmony_ci 37908c2ecf20Sopenharmony_ci qla2x00_free_sysfs_attr(base_vha, true); 37918c2ecf20Sopenharmony_ci 37928c2ecf20Sopenharmony_ci fc_remove_host(base_vha->host); 37938c2ecf20Sopenharmony_ci qlt_remove_target_resources(ha); 37948c2ecf20Sopenharmony_ci 37958c2ecf20Sopenharmony_ci scsi_remove_host(base_vha->host); 37968c2ecf20Sopenharmony_ci 37978c2ecf20Sopenharmony_ci qla2x00_free_device(base_vha); 37988c2ecf20Sopenharmony_ci 37998c2ecf20Sopenharmony_ci qla2x00_clear_drv_active(ha); 38008c2ecf20Sopenharmony_ci 38018c2ecf20Sopenharmony_ci scsi_host_put(base_vha->host); 38028c2ecf20Sopenharmony_ci 38038c2ecf20Sopenharmony_ci qla2x00_unmap_iobases(ha); 38048c2ecf20Sopenharmony_ci 38058c2ecf20Sopenharmony_ci pci_release_selected_regions(ha->pdev, ha->bars); 38068c2ecf20Sopenharmony_ci kfree(ha); 38078c2ecf20Sopenharmony_ci 38088c2ecf20Sopenharmony_ci pci_disable_pcie_error_reporting(pdev); 38098c2ecf20Sopenharmony_ci 38108c2ecf20Sopenharmony_ci pci_disable_device(pdev); 38118c2ecf20Sopenharmony_ci} 38128c2ecf20Sopenharmony_ci 38138c2ecf20Sopenharmony_cistatic inline void 38148c2ecf20Sopenharmony_ciqla24xx_free_purex_list(struct purex_list *list) 38158c2ecf20Sopenharmony_ci{ 38168c2ecf20Sopenharmony_ci struct list_head *item, *next; 38178c2ecf20Sopenharmony_ci ulong flags; 38188c2ecf20Sopenharmony_ci 38198c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 38208c2ecf20Sopenharmony_ci list_for_each_safe(item, next, &list->head) { 38218c2ecf20Sopenharmony_ci list_del(item); 38228c2ecf20Sopenharmony_ci kfree(list_entry(item, struct purex_item, list)); 38238c2ecf20Sopenharmony_ci } 38248c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 38258c2ecf20Sopenharmony_ci} 38268c2ecf20Sopenharmony_ci 38278c2ecf20Sopenharmony_cistatic void 38288c2ecf20Sopenharmony_ciqla2x00_free_device(scsi_qla_host_t *vha) 38298c2ecf20Sopenharmony_ci{ 38308c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 38318c2ecf20Sopenharmony_ci 38328c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); 38338c2ecf20Sopenharmony_ci 38348c2ecf20Sopenharmony_ci /* Disable timer */ 38358c2ecf20Sopenharmony_ci if (vha->timer_active) 38368c2ecf20Sopenharmony_ci qla2x00_stop_timer(vha); 38378c2ecf20Sopenharmony_ci 38388c2ecf20Sopenharmony_ci qla25xx_delete_queues(vha); 38398c2ecf20Sopenharmony_ci vha->flags.online = 0; 38408c2ecf20Sopenharmony_ci 38418c2ecf20Sopenharmony_ci /* turn-off interrupts on the card */ 38428c2ecf20Sopenharmony_ci if (ha->interrupts_on) { 38438c2ecf20Sopenharmony_ci vha->flags.init_done = 0; 38448c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 38458c2ecf20Sopenharmony_ci } 38468c2ecf20Sopenharmony_ci 38478c2ecf20Sopenharmony_ci qla2x00_free_fcports(vha); 38488c2ecf20Sopenharmony_ci 38498c2ecf20Sopenharmony_ci qla2x00_free_irqs(vha); 38508c2ecf20Sopenharmony_ci 38518c2ecf20Sopenharmony_ci /* Flush the work queue and remove it */ 38528c2ecf20Sopenharmony_ci if (ha->wq) { 38538c2ecf20Sopenharmony_ci flush_workqueue(ha->wq); 38548c2ecf20Sopenharmony_ci destroy_workqueue(ha->wq); 38558c2ecf20Sopenharmony_ci ha->wq = NULL; 38568c2ecf20Sopenharmony_ci } 38578c2ecf20Sopenharmony_ci 38588c2ecf20Sopenharmony_ci 38598c2ecf20Sopenharmony_ci qla24xx_free_purex_list(&vha->purex_list); 38608c2ecf20Sopenharmony_ci 38618c2ecf20Sopenharmony_ci qla2x00_mem_free(ha); 38628c2ecf20Sopenharmony_ci 38638c2ecf20Sopenharmony_ci qla82xx_md_free(vha); 38648c2ecf20Sopenharmony_ci 38658c2ecf20Sopenharmony_ci qla2x00_free_queues(ha); 38668c2ecf20Sopenharmony_ci} 38678c2ecf20Sopenharmony_ci 38688c2ecf20Sopenharmony_civoid qla2x00_free_fcports(struct scsi_qla_host *vha) 38698c2ecf20Sopenharmony_ci{ 38708c2ecf20Sopenharmony_ci fc_port_t *fcport, *tfcport; 38718c2ecf20Sopenharmony_ci 38728c2ecf20Sopenharmony_ci list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) 38738c2ecf20Sopenharmony_ci qla2x00_free_fcport(fcport); 38748c2ecf20Sopenharmony_ci} 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_cistatic inline void 38778c2ecf20Sopenharmony_ciqla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport) 38788c2ecf20Sopenharmony_ci{ 38798c2ecf20Sopenharmony_ci int now; 38808c2ecf20Sopenharmony_ci 38818c2ecf20Sopenharmony_ci if (!fcport->rport) 38828c2ecf20Sopenharmony_ci return; 38838c2ecf20Sopenharmony_ci 38848c2ecf20Sopenharmony_ci if (fcport->rport) { 38858c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, fcport->vha, 0x2109, 38868c2ecf20Sopenharmony_ci "%s %8phN. rport %p roles %x\n", 38878c2ecf20Sopenharmony_ci __func__, fcport->port_name, fcport->rport, 38888c2ecf20Sopenharmony_ci fcport->rport->roles); 38898c2ecf20Sopenharmony_ci fc_remote_port_delete(fcport->rport); 38908c2ecf20Sopenharmony_ci } 38918c2ecf20Sopenharmony_ci qlt_do_generation_tick(vha, &now); 38928c2ecf20Sopenharmony_ci} 38938c2ecf20Sopenharmony_ci 38948c2ecf20Sopenharmony_ci/* 38958c2ecf20Sopenharmony_ci * qla2x00_mark_device_lost Updates fcport state when device goes offline. 38968c2ecf20Sopenharmony_ci * 38978c2ecf20Sopenharmony_ci * Input: ha = adapter block pointer. fcport = port structure pointer. 38988c2ecf20Sopenharmony_ci * 38998c2ecf20Sopenharmony_ci * Return: None. 39008c2ecf20Sopenharmony_ci * 39018c2ecf20Sopenharmony_ci * Context: 39028c2ecf20Sopenharmony_ci */ 39038c2ecf20Sopenharmony_civoid qla2x00_mark_device_lost(scsi_qla_host_t *vha, fc_port_t *fcport, 39048c2ecf20Sopenharmony_ci int do_login) 39058c2ecf20Sopenharmony_ci{ 39068c2ecf20Sopenharmony_ci if (IS_QLAFX00(vha->hw)) { 39078c2ecf20Sopenharmony_ci qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); 39088c2ecf20Sopenharmony_ci qla2x00_schedule_rport_del(vha, fcport); 39098c2ecf20Sopenharmony_ci return; 39108c2ecf20Sopenharmony_ci } 39118c2ecf20Sopenharmony_ci 39128c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) == FCS_ONLINE && 39138c2ecf20Sopenharmony_ci vha->vp_idx == fcport->vha->vp_idx) { 39148c2ecf20Sopenharmony_ci qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); 39158c2ecf20Sopenharmony_ci qla2x00_schedule_rport_del(vha, fcport); 39168c2ecf20Sopenharmony_ci } 39178c2ecf20Sopenharmony_ci /* 39188c2ecf20Sopenharmony_ci * We may need to retry the login, so don't change the state of the 39198c2ecf20Sopenharmony_ci * port but do the retries. 39208c2ecf20Sopenharmony_ci */ 39218c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) != FCS_DEVICE_DEAD) 39228c2ecf20Sopenharmony_ci qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST); 39238c2ecf20Sopenharmony_ci 39248c2ecf20Sopenharmony_ci if (!do_login) 39258c2ecf20Sopenharmony_ci return; 39268c2ecf20Sopenharmony_ci 39278c2ecf20Sopenharmony_ci set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 39288c2ecf20Sopenharmony_ci} 39298c2ecf20Sopenharmony_ci 39308c2ecf20Sopenharmony_civoid 39318c2ecf20Sopenharmony_ciqla2x00_mark_all_devices_lost(scsi_qla_host_t *vha) 39328c2ecf20Sopenharmony_ci{ 39338c2ecf20Sopenharmony_ci fc_port_t *fcport; 39348c2ecf20Sopenharmony_ci 39358c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x20f1, 39368c2ecf20Sopenharmony_ci "Mark all dev lost\n"); 39378c2ecf20Sopenharmony_ci 39388c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 39398c2ecf20Sopenharmony_ci if (fcport->loop_id != FC_NO_LOOP_ID && 39408c2ecf20Sopenharmony_ci (fcport->flags & FCF_FCP2_DEVICE) && 39418c2ecf20Sopenharmony_ci fcport->port_type == FCT_TARGET && 39428c2ecf20Sopenharmony_ci !qla2x00_reset_active(vha)) { 39438c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x211a, 39448c2ecf20Sopenharmony_ci "Delaying session delete for FCP2 flags 0x%x port_type = 0x%x port_id=%06x %phC", 39458c2ecf20Sopenharmony_ci fcport->flags, fcport->port_type, 39468c2ecf20Sopenharmony_ci fcport->d_id.b24, fcport->port_name); 39478c2ecf20Sopenharmony_ci continue; 39488c2ecf20Sopenharmony_ci } 39498c2ecf20Sopenharmony_ci fcport->scan_state = 0; 39508c2ecf20Sopenharmony_ci qlt_schedule_sess_for_deletion(fcport); 39518c2ecf20Sopenharmony_ci } 39528c2ecf20Sopenharmony_ci} 39538c2ecf20Sopenharmony_ci 39548c2ecf20Sopenharmony_cistatic void qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha) 39558c2ecf20Sopenharmony_ci{ 39568c2ecf20Sopenharmony_ci int i; 39578c2ecf20Sopenharmony_ci 39588c2ecf20Sopenharmony_ci if (IS_FWI2_CAPABLE(ha)) 39598c2ecf20Sopenharmony_ci return; 39608c2ecf20Sopenharmony_ci 39618c2ecf20Sopenharmony_ci for (i = 0; i < SNS_FIRST_LOOP_ID; i++) 39628c2ecf20Sopenharmony_ci set_bit(i, ha->loop_id_map); 39638c2ecf20Sopenharmony_ci set_bit(MANAGEMENT_SERVER, ha->loop_id_map); 39648c2ecf20Sopenharmony_ci set_bit(BROADCAST, ha->loop_id_map); 39658c2ecf20Sopenharmony_ci} 39668c2ecf20Sopenharmony_ci 39678c2ecf20Sopenharmony_ci/* 39688c2ecf20Sopenharmony_ci* qla2x00_mem_alloc 39698c2ecf20Sopenharmony_ci* Allocates adapter memory. 39708c2ecf20Sopenharmony_ci* 39718c2ecf20Sopenharmony_ci* Returns: 39728c2ecf20Sopenharmony_ci* 0 = success. 39738c2ecf20Sopenharmony_ci* !0 = failure. 39748c2ecf20Sopenharmony_ci*/ 39758c2ecf20Sopenharmony_cistatic int 39768c2ecf20Sopenharmony_ciqla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, 39778c2ecf20Sopenharmony_ci struct req_que **req, struct rsp_que **rsp) 39788c2ecf20Sopenharmony_ci{ 39798c2ecf20Sopenharmony_ci char name[16]; 39808c2ecf20Sopenharmony_ci 39818c2ecf20Sopenharmony_ci ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, 39828c2ecf20Sopenharmony_ci &ha->init_cb_dma, GFP_KERNEL); 39838c2ecf20Sopenharmony_ci if (!ha->init_cb) 39848c2ecf20Sopenharmony_ci goto fail; 39858c2ecf20Sopenharmony_ci 39868c2ecf20Sopenharmony_ci if (qlt_mem_alloc(ha) < 0) 39878c2ecf20Sopenharmony_ci goto fail_free_init_cb; 39888c2ecf20Sopenharmony_ci 39898c2ecf20Sopenharmony_ci ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, 39908c2ecf20Sopenharmony_ci qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL); 39918c2ecf20Sopenharmony_ci if (!ha->gid_list) 39928c2ecf20Sopenharmony_ci goto fail_free_tgt_mem; 39938c2ecf20Sopenharmony_ci 39948c2ecf20Sopenharmony_ci ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep); 39958c2ecf20Sopenharmony_ci if (!ha->srb_mempool) 39968c2ecf20Sopenharmony_ci goto fail_free_gid_list; 39978c2ecf20Sopenharmony_ci 39988c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 39998c2ecf20Sopenharmony_ci /* Allocate cache for CT6 Ctx. */ 40008c2ecf20Sopenharmony_ci if (!ctx_cachep) { 40018c2ecf20Sopenharmony_ci ctx_cachep = kmem_cache_create("qla2xxx_ctx", 40028c2ecf20Sopenharmony_ci sizeof(struct ct6_dsd), 0, 40038c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL); 40048c2ecf20Sopenharmony_ci if (!ctx_cachep) 40058c2ecf20Sopenharmony_ci goto fail_free_srb_mempool; 40068c2ecf20Sopenharmony_ci } 40078c2ecf20Sopenharmony_ci ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ, 40088c2ecf20Sopenharmony_ci ctx_cachep); 40098c2ecf20Sopenharmony_ci if (!ha->ctx_mempool) 40108c2ecf20Sopenharmony_ci goto fail_free_srb_mempool; 40118c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0021, 40128c2ecf20Sopenharmony_ci "ctx_cachep=%p ctx_mempool=%p.\n", 40138c2ecf20Sopenharmony_ci ctx_cachep, ha->ctx_mempool); 40148c2ecf20Sopenharmony_ci } 40158c2ecf20Sopenharmony_ci 40168c2ecf20Sopenharmony_ci /* Get memory for cached NVRAM */ 40178c2ecf20Sopenharmony_ci ha->nvram = kzalloc(MAX_NVRAM_SIZE, GFP_KERNEL); 40188c2ecf20Sopenharmony_ci if (!ha->nvram) 40198c2ecf20Sopenharmony_ci goto fail_free_ctx_mempool; 40208c2ecf20Sopenharmony_ci 40218c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "%s_%d", QLA2XXX_DRIVER_NAME, 40228c2ecf20Sopenharmony_ci ha->pdev->device); 40238c2ecf20Sopenharmony_ci ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, 40248c2ecf20Sopenharmony_ci DMA_POOL_SIZE, 8, 0); 40258c2ecf20Sopenharmony_ci if (!ha->s_dma_pool) 40268c2ecf20Sopenharmony_ci goto fail_free_nvram; 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0022, 40298c2ecf20Sopenharmony_ci "init_cb=%p gid_list=%p, srb_mempool=%p s_dma_pool=%p.\n", 40308c2ecf20Sopenharmony_ci ha->init_cb, ha->gid_list, ha->srb_mempool, ha->s_dma_pool); 40318c2ecf20Sopenharmony_ci 40328c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha) || ql2xenabledif) { 40338c2ecf20Sopenharmony_ci ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev, 40348c2ecf20Sopenharmony_ci DSD_LIST_DMA_POOL_SIZE, 8, 0); 40358c2ecf20Sopenharmony_ci if (!ha->dl_dma_pool) { 40368c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0023, 40378c2ecf20Sopenharmony_ci "Failed to allocate memory for dl_dma_pool.\n"); 40388c2ecf20Sopenharmony_ci goto fail_s_dma_pool; 40398c2ecf20Sopenharmony_ci } 40408c2ecf20Sopenharmony_ci 40418c2ecf20Sopenharmony_ci ha->fcp_cmnd_dma_pool = dma_pool_create(name, &ha->pdev->dev, 40428c2ecf20Sopenharmony_ci FCP_CMND_DMA_POOL_SIZE, 8, 0); 40438c2ecf20Sopenharmony_ci if (!ha->fcp_cmnd_dma_pool) { 40448c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0024, 40458c2ecf20Sopenharmony_ci "Failed to allocate memory for fcp_cmnd_dma_pool.\n"); 40468c2ecf20Sopenharmony_ci goto fail_dl_dma_pool; 40478c2ecf20Sopenharmony_ci } 40488c2ecf20Sopenharmony_ci 40498c2ecf20Sopenharmony_ci if (ql2xenabledif) { 40508c2ecf20Sopenharmony_ci u64 bufsize = DIF_BUNDLING_DMA_POOL_SIZE; 40518c2ecf20Sopenharmony_ci struct dsd_dma *dsd, *nxt; 40528c2ecf20Sopenharmony_ci uint i; 40538c2ecf20Sopenharmony_ci /* Creata a DMA pool of buffers for DIF bundling */ 40548c2ecf20Sopenharmony_ci ha->dif_bundl_pool = dma_pool_create(name, 40558c2ecf20Sopenharmony_ci &ha->pdev->dev, DIF_BUNDLING_DMA_POOL_SIZE, 8, 0); 40568c2ecf20Sopenharmony_ci if (!ha->dif_bundl_pool) { 40578c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0024, 40588c2ecf20Sopenharmony_ci "%s: failed create dif_bundl_pool\n", 40598c2ecf20Sopenharmony_ci __func__); 40608c2ecf20Sopenharmony_ci goto fail_dif_bundl_dma_pool; 40618c2ecf20Sopenharmony_ci } 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->pool.good.head); 40648c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->pool.unusable.head); 40658c2ecf20Sopenharmony_ci ha->pool.good.count = 0; 40668c2ecf20Sopenharmony_ci ha->pool.unusable.count = 0; 40678c2ecf20Sopenharmony_ci for (i = 0; i < 128; i++) { 40688c2ecf20Sopenharmony_ci dsd = kzalloc(sizeof(*dsd), GFP_ATOMIC); 40698c2ecf20Sopenharmony_ci if (!dsd) { 40708c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 40718c2ecf20Sopenharmony_ci 0xe0ee, "%s: failed alloc dsd\n", 40728c2ecf20Sopenharmony_ci __func__); 40738c2ecf20Sopenharmony_ci return -ENOMEM; 40748c2ecf20Sopenharmony_ci } 40758c2ecf20Sopenharmony_ci ha->dif_bundle_kallocs++; 40768c2ecf20Sopenharmony_ci 40778c2ecf20Sopenharmony_ci dsd->dsd_addr = dma_pool_alloc( 40788c2ecf20Sopenharmony_ci ha->dif_bundl_pool, GFP_ATOMIC, 40798c2ecf20Sopenharmony_ci &dsd->dsd_list_dma); 40808c2ecf20Sopenharmony_ci if (!dsd->dsd_addr) { 40818c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 40828c2ecf20Sopenharmony_ci 0xe0ee, 40838c2ecf20Sopenharmony_ci "%s: failed alloc ->dsd_addr\n", 40848c2ecf20Sopenharmony_ci __func__); 40858c2ecf20Sopenharmony_ci kfree(dsd); 40868c2ecf20Sopenharmony_ci ha->dif_bundle_kallocs--; 40878c2ecf20Sopenharmony_ci continue; 40888c2ecf20Sopenharmony_ci } 40898c2ecf20Sopenharmony_ci ha->dif_bundle_dma_allocs++; 40908c2ecf20Sopenharmony_ci 40918c2ecf20Sopenharmony_ci /* 40928c2ecf20Sopenharmony_ci * if DMA buffer crosses 4G boundary, 40938c2ecf20Sopenharmony_ci * put it on bad list 40948c2ecf20Sopenharmony_ci */ 40958c2ecf20Sopenharmony_ci if (MSD(dsd->dsd_list_dma) ^ 40968c2ecf20Sopenharmony_ci MSD(dsd->dsd_list_dma + bufsize)) { 40978c2ecf20Sopenharmony_ci list_add_tail(&dsd->list, 40988c2ecf20Sopenharmony_ci &ha->pool.unusable.head); 40998c2ecf20Sopenharmony_ci ha->pool.unusable.count++; 41008c2ecf20Sopenharmony_ci } else { 41018c2ecf20Sopenharmony_ci list_add_tail(&dsd->list, 41028c2ecf20Sopenharmony_ci &ha->pool.good.head); 41038c2ecf20Sopenharmony_ci ha->pool.good.count++; 41048c2ecf20Sopenharmony_ci } 41058c2ecf20Sopenharmony_ci } 41068c2ecf20Sopenharmony_ci 41078c2ecf20Sopenharmony_ci /* return the good ones back to the pool */ 41088c2ecf20Sopenharmony_ci list_for_each_entry_safe(dsd, nxt, 41098c2ecf20Sopenharmony_ci &ha->pool.good.head, list) { 41108c2ecf20Sopenharmony_ci list_del(&dsd->list); 41118c2ecf20Sopenharmony_ci dma_pool_free(ha->dif_bundl_pool, 41128c2ecf20Sopenharmony_ci dsd->dsd_addr, dsd->dsd_list_dma); 41138c2ecf20Sopenharmony_ci ha->dif_bundle_dma_allocs--; 41148c2ecf20Sopenharmony_ci kfree(dsd); 41158c2ecf20Sopenharmony_ci ha->dif_bundle_kallocs--; 41168c2ecf20Sopenharmony_ci } 41178c2ecf20Sopenharmony_ci 41188c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0024, 41198c2ecf20Sopenharmony_ci "%s: dif dma pool (good=%u unusable=%u)\n", 41208c2ecf20Sopenharmony_ci __func__, ha->pool.good.count, 41218c2ecf20Sopenharmony_ci ha->pool.unusable.count); 41228c2ecf20Sopenharmony_ci } 41238c2ecf20Sopenharmony_ci 41248c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0025, 41258c2ecf20Sopenharmony_ci "dl_dma_pool=%p fcp_cmnd_dma_pool=%p dif_bundl_pool=%p.\n", 41268c2ecf20Sopenharmony_ci ha->dl_dma_pool, ha->fcp_cmnd_dma_pool, 41278c2ecf20Sopenharmony_ci ha->dif_bundl_pool); 41288c2ecf20Sopenharmony_ci } 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci /* Allocate memory for SNS commands */ 41318c2ecf20Sopenharmony_ci if (IS_QLA2100(ha) || IS_QLA2200(ha)) { 41328c2ecf20Sopenharmony_ci /* Get consistent memory allocated for SNS commands */ 41338c2ecf20Sopenharmony_ci ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev, 41348c2ecf20Sopenharmony_ci sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma, GFP_KERNEL); 41358c2ecf20Sopenharmony_ci if (!ha->sns_cmd) 41368c2ecf20Sopenharmony_ci goto fail_dma_pool; 41378c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0026, 41388c2ecf20Sopenharmony_ci "sns_cmd: %p.\n", ha->sns_cmd); 41398c2ecf20Sopenharmony_ci } else { 41408c2ecf20Sopenharmony_ci /* Get consistent memory allocated for MS IOCB */ 41418c2ecf20Sopenharmony_ci ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, 41428c2ecf20Sopenharmony_ci &ha->ms_iocb_dma); 41438c2ecf20Sopenharmony_ci if (!ha->ms_iocb) 41448c2ecf20Sopenharmony_ci goto fail_dma_pool; 41458c2ecf20Sopenharmony_ci /* Get consistent memory allocated for CT SNS commands */ 41468c2ecf20Sopenharmony_ci ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev, 41478c2ecf20Sopenharmony_ci sizeof(struct ct_sns_pkt), &ha->ct_sns_dma, GFP_KERNEL); 41488c2ecf20Sopenharmony_ci if (!ha->ct_sns) 41498c2ecf20Sopenharmony_ci goto fail_free_ms_iocb; 41508c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0027, 41518c2ecf20Sopenharmony_ci "ms_iocb=%p ct_sns=%p.\n", 41528c2ecf20Sopenharmony_ci ha->ms_iocb, ha->ct_sns); 41538c2ecf20Sopenharmony_ci } 41548c2ecf20Sopenharmony_ci 41558c2ecf20Sopenharmony_ci /* Allocate memory for request ring */ 41568c2ecf20Sopenharmony_ci *req = kzalloc(sizeof(struct req_que), GFP_KERNEL); 41578c2ecf20Sopenharmony_ci if (!*req) { 41588c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0028, 41598c2ecf20Sopenharmony_ci "Failed to allocate memory for req.\n"); 41608c2ecf20Sopenharmony_ci goto fail_req; 41618c2ecf20Sopenharmony_ci } 41628c2ecf20Sopenharmony_ci (*req)->length = req_len; 41638c2ecf20Sopenharmony_ci (*req)->ring = dma_alloc_coherent(&ha->pdev->dev, 41648c2ecf20Sopenharmony_ci ((*req)->length + 1) * sizeof(request_t), 41658c2ecf20Sopenharmony_ci &(*req)->dma, GFP_KERNEL); 41668c2ecf20Sopenharmony_ci if (!(*req)->ring) { 41678c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0029, 41688c2ecf20Sopenharmony_ci "Failed to allocate memory for req_ring.\n"); 41698c2ecf20Sopenharmony_ci goto fail_req_ring; 41708c2ecf20Sopenharmony_ci } 41718c2ecf20Sopenharmony_ci /* Allocate memory for response ring */ 41728c2ecf20Sopenharmony_ci *rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL); 41738c2ecf20Sopenharmony_ci if (!*rsp) { 41748c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x002a, 41758c2ecf20Sopenharmony_ci "Failed to allocate memory for rsp.\n"); 41768c2ecf20Sopenharmony_ci goto fail_rsp; 41778c2ecf20Sopenharmony_ci } 41788c2ecf20Sopenharmony_ci (*rsp)->hw = ha; 41798c2ecf20Sopenharmony_ci (*rsp)->length = rsp_len; 41808c2ecf20Sopenharmony_ci (*rsp)->ring = dma_alloc_coherent(&ha->pdev->dev, 41818c2ecf20Sopenharmony_ci ((*rsp)->length + 1) * sizeof(response_t), 41828c2ecf20Sopenharmony_ci &(*rsp)->dma, GFP_KERNEL); 41838c2ecf20Sopenharmony_ci if (!(*rsp)->ring) { 41848c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x002b, 41858c2ecf20Sopenharmony_ci "Failed to allocate memory for rsp_ring.\n"); 41868c2ecf20Sopenharmony_ci goto fail_rsp_ring; 41878c2ecf20Sopenharmony_ci } 41888c2ecf20Sopenharmony_ci (*req)->rsp = *rsp; 41898c2ecf20Sopenharmony_ci (*rsp)->req = *req; 41908c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002c, 41918c2ecf20Sopenharmony_ci "req=%p req->length=%d req->ring=%p rsp=%p " 41928c2ecf20Sopenharmony_ci "rsp->length=%d rsp->ring=%p.\n", 41938c2ecf20Sopenharmony_ci *req, (*req)->length, (*req)->ring, *rsp, (*rsp)->length, 41948c2ecf20Sopenharmony_ci (*rsp)->ring); 41958c2ecf20Sopenharmony_ci /* Allocate memory for NVRAM data for vports */ 41968c2ecf20Sopenharmony_ci if (ha->nvram_npiv_size) { 41978c2ecf20Sopenharmony_ci ha->npiv_info = kcalloc(ha->nvram_npiv_size, 41988c2ecf20Sopenharmony_ci sizeof(struct qla_npiv_entry), 41998c2ecf20Sopenharmony_ci GFP_KERNEL); 42008c2ecf20Sopenharmony_ci if (!ha->npiv_info) { 42018c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x002d, 42028c2ecf20Sopenharmony_ci "Failed to allocate memory for npiv_info.\n"); 42038c2ecf20Sopenharmony_ci goto fail_npiv_info; 42048c2ecf20Sopenharmony_ci } 42058c2ecf20Sopenharmony_ci } else 42068c2ecf20Sopenharmony_ci ha->npiv_info = NULL; 42078c2ecf20Sopenharmony_ci 42088c2ecf20Sopenharmony_ci /* Get consistent memory allocated for EX-INIT-CB. */ 42098c2ecf20Sopenharmony_ci if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || 42108c2ecf20Sopenharmony_ci IS_QLA28XX(ha)) { 42118c2ecf20Sopenharmony_ci ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, 42128c2ecf20Sopenharmony_ci &ha->ex_init_cb_dma); 42138c2ecf20Sopenharmony_ci if (!ha->ex_init_cb) 42148c2ecf20Sopenharmony_ci goto fail_ex_init_cb; 42158c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002e, 42168c2ecf20Sopenharmony_ci "ex_init_cb=%p.\n", ha->ex_init_cb); 42178c2ecf20Sopenharmony_ci } 42188c2ecf20Sopenharmony_ci 42198c2ecf20Sopenharmony_ci /* Get consistent memory allocated for Special Features-CB. */ 42208c2ecf20Sopenharmony_ci if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) { 42218c2ecf20Sopenharmony_ci ha->sf_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, 42228c2ecf20Sopenharmony_ci &ha->sf_init_cb_dma); 42238c2ecf20Sopenharmony_ci if (!ha->sf_init_cb) 42248c2ecf20Sopenharmony_ci goto fail_sf_init_cb; 42258c2ecf20Sopenharmony_ci memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb)); 42268c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0199, 42278c2ecf20Sopenharmony_ci "sf_init_cb=%p.\n", ha->sf_init_cb); 42288c2ecf20Sopenharmony_ci } 42298c2ecf20Sopenharmony_ci 42308c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->gbl_dsd_list); 42318c2ecf20Sopenharmony_ci 42328c2ecf20Sopenharmony_ci /* Get consistent memory allocated for Async Port-Database. */ 42338c2ecf20Sopenharmony_ci if (!IS_FWI2_CAPABLE(ha)) { 42348c2ecf20Sopenharmony_ci ha->async_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, 42358c2ecf20Sopenharmony_ci &ha->async_pd_dma); 42368c2ecf20Sopenharmony_ci if (!ha->async_pd) 42378c2ecf20Sopenharmony_ci goto fail_async_pd; 42388c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x002f, 42398c2ecf20Sopenharmony_ci "async_pd=%p.\n", ha->async_pd); 42408c2ecf20Sopenharmony_ci } 42418c2ecf20Sopenharmony_ci 42428c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->vp_list); 42438c2ecf20Sopenharmony_ci 42448c2ecf20Sopenharmony_ci /* Allocate memory for our loop_id bitmap */ 42458c2ecf20Sopenharmony_ci ha->loop_id_map = kcalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE), 42468c2ecf20Sopenharmony_ci sizeof(long), 42478c2ecf20Sopenharmony_ci GFP_KERNEL); 42488c2ecf20Sopenharmony_ci if (!ha->loop_id_map) 42498c2ecf20Sopenharmony_ci goto fail_loop_id_map; 42508c2ecf20Sopenharmony_ci else { 42518c2ecf20Sopenharmony_ci qla2x00_set_reserved_loop_ids(ha); 42528c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123, 42538c2ecf20Sopenharmony_ci "loop_id_map=%p.\n", ha->loop_id_map); 42548c2ecf20Sopenharmony_ci } 42558c2ecf20Sopenharmony_ci 42568c2ecf20Sopenharmony_ci ha->sfp_data = dma_alloc_coherent(&ha->pdev->dev, 42578c2ecf20Sopenharmony_ci SFP_DEV_SIZE, &ha->sfp_data_dma, GFP_KERNEL); 42588c2ecf20Sopenharmony_ci if (!ha->sfp_data) { 42598c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, 42608c2ecf20Sopenharmony_ci "Unable to allocate memory for SFP read-data.\n"); 42618c2ecf20Sopenharmony_ci goto fail_sfp_data; 42628c2ecf20Sopenharmony_ci } 42638c2ecf20Sopenharmony_ci 42648c2ecf20Sopenharmony_ci ha->flt = dma_alloc_coherent(&ha->pdev->dev, 42658c2ecf20Sopenharmony_ci sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE, &ha->flt_dma, 42668c2ecf20Sopenharmony_ci GFP_KERNEL); 42678c2ecf20Sopenharmony_ci if (!ha->flt) { 42688c2ecf20Sopenharmony_ci ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b, 42698c2ecf20Sopenharmony_ci "Unable to allocate memory for FLT.\n"); 42708c2ecf20Sopenharmony_ci goto fail_flt_buffer; 42718c2ecf20Sopenharmony_ci } 42728c2ecf20Sopenharmony_ci 42738c2ecf20Sopenharmony_ci return 0; 42748c2ecf20Sopenharmony_ci 42758c2ecf20Sopenharmony_cifail_flt_buffer: 42768c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, 42778c2ecf20Sopenharmony_ci ha->sfp_data, ha->sfp_data_dma); 42788c2ecf20Sopenharmony_cifail_sfp_data: 42798c2ecf20Sopenharmony_ci kfree(ha->loop_id_map); 42808c2ecf20Sopenharmony_cifail_loop_id_map: 42818c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); 42828c2ecf20Sopenharmony_cifail_async_pd: 42838c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, ha->sf_init_cb, ha->sf_init_cb_dma); 42848c2ecf20Sopenharmony_cifail_sf_init_cb: 42858c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); 42868c2ecf20Sopenharmony_cifail_ex_init_cb: 42878c2ecf20Sopenharmony_ci kfree(ha->npiv_info); 42888c2ecf20Sopenharmony_cifail_npiv_info: 42898c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ((*rsp)->length + 1) * 42908c2ecf20Sopenharmony_ci sizeof(response_t), (*rsp)->ring, (*rsp)->dma); 42918c2ecf20Sopenharmony_ci (*rsp)->ring = NULL; 42928c2ecf20Sopenharmony_ci (*rsp)->dma = 0; 42938c2ecf20Sopenharmony_cifail_rsp_ring: 42948c2ecf20Sopenharmony_ci kfree(*rsp); 42958c2ecf20Sopenharmony_ci *rsp = NULL; 42968c2ecf20Sopenharmony_cifail_rsp: 42978c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ((*req)->length + 1) * 42988c2ecf20Sopenharmony_ci sizeof(request_t), (*req)->ring, (*req)->dma); 42998c2ecf20Sopenharmony_ci (*req)->ring = NULL; 43008c2ecf20Sopenharmony_ci (*req)->dma = 0; 43018c2ecf20Sopenharmony_cifail_req_ring: 43028c2ecf20Sopenharmony_ci kfree(*req); 43038c2ecf20Sopenharmony_ci *req = NULL; 43048c2ecf20Sopenharmony_cifail_req: 43058c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt), 43068c2ecf20Sopenharmony_ci ha->ct_sns, ha->ct_sns_dma); 43078c2ecf20Sopenharmony_ci ha->ct_sns = NULL; 43088c2ecf20Sopenharmony_ci ha->ct_sns_dma = 0; 43098c2ecf20Sopenharmony_cifail_free_ms_iocb: 43108c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); 43118c2ecf20Sopenharmony_ci ha->ms_iocb = NULL; 43128c2ecf20Sopenharmony_ci ha->ms_iocb_dma = 0; 43138c2ecf20Sopenharmony_ci 43148c2ecf20Sopenharmony_ci if (ha->sns_cmd) 43158c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), 43168c2ecf20Sopenharmony_ci ha->sns_cmd, ha->sns_cmd_dma); 43178c2ecf20Sopenharmony_cifail_dma_pool: 43188c2ecf20Sopenharmony_ci if (ql2xenabledif) { 43198c2ecf20Sopenharmony_ci struct dsd_dma *dsd, *nxt; 43208c2ecf20Sopenharmony_ci 43218c2ecf20Sopenharmony_ci list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head, 43228c2ecf20Sopenharmony_ci list) { 43238c2ecf20Sopenharmony_ci list_del(&dsd->list); 43248c2ecf20Sopenharmony_ci dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr, 43258c2ecf20Sopenharmony_ci dsd->dsd_list_dma); 43268c2ecf20Sopenharmony_ci ha->dif_bundle_dma_allocs--; 43278c2ecf20Sopenharmony_ci kfree(dsd); 43288c2ecf20Sopenharmony_ci ha->dif_bundle_kallocs--; 43298c2ecf20Sopenharmony_ci ha->pool.unusable.count--; 43308c2ecf20Sopenharmony_ci } 43318c2ecf20Sopenharmony_ci dma_pool_destroy(ha->dif_bundl_pool); 43328c2ecf20Sopenharmony_ci ha->dif_bundl_pool = NULL; 43338c2ecf20Sopenharmony_ci } 43348c2ecf20Sopenharmony_ci 43358c2ecf20Sopenharmony_cifail_dif_bundl_dma_pool: 43368c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha) || ql2xenabledif) { 43378c2ecf20Sopenharmony_ci dma_pool_destroy(ha->fcp_cmnd_dma_pool); 43388c2ecf20Sopenharmony_ci ha->fcp_cmnd_dma_pool = NULL; 43398c2ecf20Sopenharmony_ci } 43408c2ecf20Sopenharmony_cifail_dl_dma_pool: 43418c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha) || ql2xenabledif) { 43428c2ecf20Sopenharmony_ci dma_pool_destroy(ha->dl_dma_pool); 43438c2ecf20Sopenharmony_ci ha->dl_dma_pool = NULL; 43448c2ecf20Sopenharmony_ci } 43458c2ecf20Sopenharmony_cifail_s_dma_pool: 43468c2ecf20Sopenharmony_ci dma_pool_destroy(ha->s_dma_pool); 43478c2ecf20Sopenharmony_ci ha->s_dma_pool = NULL; 43488c2ecf20Sopenharmony_cifail_free_nvram: 43498c2ecf20Sopenharmony_ci kfree(ha->nvram); 43508c2ecf20Sopenharmony_ci ha->nvram = NULL; 43518c2ecf20Sopenharmony_cifail_free_ctx_mempool: 43528c2ecf20Sopenharmony_ci mempool_destroy(ha->ctx_mempool); 43538c2ecf20Sopenharmony_ci ha->ctx_mempool = NULL; 43548c2ecf20Sopenharmony_cifail_free_srb_mempool: 43558c2ecf20Sopenharmony_ci mempool_destroy(ha->srb_mempool); 43568c2ecf20Sopenharmony_ci ha->srb_mempool = NULL; 43578c2ecf20Sopenharmony_cifail_free_gid_list: 43588c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), 43598c2ecf20Sopenharmony_ci ha->gid_list, 43608c2ecf20Sopenharmony_ci ha->gid_list_dma); 43618c2ecf20Sopenharmony_ci ha->gid_list = NULL; 43628c2ecf20Sopenharmony_ci ha->gid_list_dma = 0; 43638c2ecf20Sopenharmony_cifail_free_tgt_mem: 43648c2ecf20Sopenharmony_ci qlt_mem_free(ha); 43658c2ecf20Sopenharmony_cifail_free_init_cb: 43668c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb, 43678c2ecf20Sopenharmony_ci ha->init_cb_dma); 43688c2ecf20Sopenharmony_ci ha->init_cb = NULL; 43698c2ecf20Sopenharmony_ci ha->init_cb_dma = 0; 43708c2ecf20Sopenharmony_cifail: 43718c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, NULL, 0x0030, 43728c2ecf20Sopenharmony_ci "Memory allocation failure.\n"); 43738c2ecf20Sopenharmony_ci return -ENOMEM; 43748c2ecf20Sopenharmony_ci} 43758c2ecf20Sopenharmony_ci 43768c2ecf20Sopenharmony_ciint 43778c2ecf20Sopenharmony_ciqla2x00_set_exlogins_buffer(scsi_qla_host_t *vha) 43788c2ecf20Sopenharmony_ci{ 43798c2ecf20Sopenharmony_ci int rval; 43808c2ecf20Sopenharmony_ci uint16_t size, max_cnt; 43818c2ecf20Sopenharmony_ci uint32_t temp; 43828c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 43838c2ecf20Sopenharmony_ci 43848c2ecf20Sopenharmony_ci /* Return if we don't need to alloacate any extended logins */ 43858c2ecf20Sopenharmony_ci if (ql2xexlogins <= MAX_FIBRE_DEVICES_2400) 43868c2ecf20Sopenharmony_ci return QLA_SUCCESS; 43878c2ecf20Sopenharmony_ci 43888c2ecf20Sopenharmony_ci if (!IS_EXLOGIN_OFFLD_CAPABLE(ha)) 43898c2ecf20Sopenharmony_ci return QLA_SUCCESS; 43908c2ecf20Sopenharmony_ci 43918c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd021, "EXLOGIN count: %d.\n", ql2xexlogins); 43928c2ecf20Sopenharmony_ci max_cnt = 0; 43938c2ecf20Sopenharmony_ci rval = qla_get_exlogin_status(vha, &size, &max_cnt); 43948c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 43958c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0xd029, 43968c2ecf20Sopenharmony_ci "Failed to get exlogin status.\n"); 43978c2ecf20Sopenharmony_ci return rval; 43988c2ecf20Sopenharmony_ci } 43998c2ecf20Sopenharmony_ci 44008c2ecf20Sopenharmony_ci temp = (ql2xexlogins > max_cnt) ? max_cnt : ql2xexlogins; 44018c2ecf20Sopenharmony_ci temp *= size; 44028c2ecf20Sopenharmony_ci 44038c2ecf20Sopenharmony_ci if (temp != ha->exlogin_size) { 44048c2ecf20Sopenharmony_ci qla2x00_free_exlogin_buffer(ha); 44058c2ecf20Sopenharmony_ci ha->exlogin_size = temp; 44068c2ecf20Sopenharmony_ci 44078c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd024, 44088c2ecf20Sopenharmony_ci "EXLOGIN: max_logins=%d, portdb=0x%x, total=%d.\n", 44098c2ecf20Sopenharmony_ci max_cnt, size, temp); 44108c2ecf20Sopenharmony_ci 44118c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd025, 44128c2ecf20Sopenharmony_ci "EXLOGIN: requested size=0x%x\n", ha->exlogin_size); 44138c2ecf20Sopenharmony_ci 44148c2ecf20Sopenharmony_ci /* Get consistent memory for extended logins */ 44158c2ecf20Sopenharmony_ci ha->exlogin_buf = dma_alloc_coherent(&ha->pdev->dev, 44168c2ecf20Sopenharmony_ci ha->exlogin_size, &ha->exlogin_buf_dma, GFP_KERNEL); 44178c2ecf20Sopenharmony_ci if (!ha->exlogin_buf) { 44188c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0xd02a, 44198c2ecf20Sopenharmony_ci "Failed to allocate memory for exlogin_buf_dma.\n"); 44208c2ecf20Sopenharmony_ci return -ENOMEM; 44218c2ecf20Sopenharmony_ci } 44228c2ecf20Sopenharmony_ci } 44238c2ecf20Sopenharmony_ci 44248c2ecf20Sopenharmony_ci /* Now configure the dma buffer */ 44258c2ecf20Sopenharmony_ci rval = qla_set_exlogin_mem_cfg(vha, ha->exlogin_buf_dma); 44268c2ecf20Sopenharmony_ci if (rval) { 44278c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0xd033, 44288c2ecf20Sopenharmony_ci "Setup extended login buffer ****FAILED****.\n"); 44298c2ecf20Sopenharmony_ci qla2x00_free_exlogin_buffer(ha); 44308c2ecf20Sopenharmony_ci } 44318c2ecf20Sopenharmony_ci 44328c2ecf20Sopenharmony_ci return rval; 44338c2ecf20Sopenharmony_ci} 44348c2ecf20Sopenharmony_ci 44358c2ecf20Sopenharmony_ci/* 44368c2ecf20Sopenharmony_ci* qla2x00_free_exlogin_buffer 44378c2ecf20Sopenharmony_ci* 44388c2ecf20Sopenharmony_ci* Input: 44398c2ecf20Sopenharmony_ci* ha = adapter block pointer 44408c2ecf20Sopenharmony_ci*/ 44418c2ecf20Sopenharmony_civoid 44428c2ecf20Sopenharmony_ciqla2x00_free_exlogin_buffer(struct qla_hw_data *ha) 44438c2ecf20Sopenharmony_ci{ 44448c2ecf20Sopenharmony_ci if (ha->exlogin_buf) { 44458c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ha->exlogin_size, 44468c2ecf20Sopenharmony_ci ha->exlogin_buf, ha->exlogin_buf_dma); 44478c2ecf20Sopenharmony_ci ha->exlogin_buf = NULL; 44488c2ecf20Sopenharmony_ci ha->exlogin_size = 0; 44498c2ecf20Sopenharmony_ci } 44508c2ecf20Sopenharmony_ci} 44518c2ecf20Sopenharmony_ci 44528c2ecf20Sopenharmony_cistatic void 44538c2ecf20Sopenharmony_ciqla2x00_number_of_exch(scsi_qla_host_t *vha, u32 *ret_cnt, u16 max_cnt) 44548c2ecf20Sopenharmony_ci{ 44558c2ecf20Sopenharmony_ci u32 temp; 44568c2ecf20Sopenharmony_ci struct init_cb_81xx *icb = (struct init_cb_81xx *)vha->hw->init_cb; 44578c2ecf20Sopenharmony_ci *ret_cnt = FW_DEF_EXCHANGES_CNT; 44588c2ecf20Sopenharmony_ci 44598c2ecf20Sopenharmony_ci if (max_cnt > vha->hw->max_exchg) 44608c2ecf20Sopenharmony_ci max_cnt = vha->hw->max_exchg; 44618c2ecf20Sopenharmony_ci 44628c2ecf20Sopenharmony_ci if (qla_ini_mode_enabled(vha)) { 44638c2ecf20Sopenharmony_ci if (vha->ql2xiniexchg > max_cnt) 44648c2ecf20Sopenharmony_ci vha->ql2xiniexchg = max_cnt; 44658c2ecf20Sopenharmony_ci 44668c2ecf20Sopenharmony_ci if (vha->ql2xiniexchg > FW_DEF_EXCHANGES_CNT) 44678c2ecf20Sopenharmony_ci *ret_cnt = vha->ql2xiniexchg; 44688c2ecf20Sopenharmony_ci 44698c2ecf20Sopenharmony_ci } else if (qla_tgt_mode_enabled(vha)) { 44708c2ecf20Sopenharmony_ci if (vha->ql2xexchoffld > max_cnt) { 44718c2ecf20Sopenharmony_ci vha->ql2xexchoffld = max_cnt; 44728c2ecf20Sopenharmony_ci icb->exchange_count = cpu_to_le16(vha->ql2xexchoffld); 44738c2ecf20Sopenharmony_ci } 44748c2ecf20Sopenharmony_ci 44758c2ecf20Sopenharmony_ci if (vha->ql2xexchoffld > FW_DEF_EXCHANGES_CNT) 44768c2ecf20Sopenharmony_ci *ret_cnt = vha->ql2xexchoffld; 44778c2ecf20Sopenharmony_ci } else if (qla_dual_mode_enabled(vha)) { 44788c2ecf20Sopenharmony_ci temp = vha->ql2xiniexchg + vha->ql2xexchoffld; 44798c2ecf20Sopenharmony_ci if (temp > max_cnt) { 44808c2ecf20Sopenharmony_ci vha->ql2xiniexchg -= (temp - max_cnt)/2; 44818c2ecf20Sopenharmony_ci vha->ql2xexchoffld -= (((temp - max_cnt)/2) + 1); 44828c2ecf20Sopenharmony_ci temp = max_cnt; 44838c2ecf20Sopenharmony_ci icb->exchange_count = cpu_to_le16(vha->ql2xexchoffld); 44848c2ecf20Sopenharmony_ci } 44858c2ecf20Sopenharmony_ci 44868c2ecf20Sopenharmony_ci if (temp > FW_DEF_EXCHANGES_CNT) 44878c2ecf20Sopenharmony_ci *ret_cnt = temp; 44888c2ecf20Sopenharmony_ci } 44898c2ecf20Sopenharmony_ci} 44908c2ecf20Sopenharmony_ci 44918c2ecf20Sopenharmony_ciint 44928c2ecf20Sopenharmony_ciqla2x00_set_exchoffld_buffer(scsi_qla_host_t *vha) 44938c2ecf20Sopenharmony_ci{ 44948c2ecf20Sopenharmony_ci int rval; 44958c2ecf20Sopenharmony_ci u16 size, max_cnt; 44968c2ecf20Sopenharmony_ci u32 actual_cnt, totsz; 44978c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 44988c2ecf20Sopenharmony_ci 44998c2ecf20Sopenharmony_ci if (!ha->flags.exchoffld_enabled) 45008c2ecf20Sopenharmony_ci return QLA_SUCCESS; 45018c2ecf20Sopenharmony_ci 45028c2ecf20Sopenharmony_ci if (!IS_EXCHG_OFFLD_CAPABLE(ha)) 45038c2ecf20Sopenharmony_ci return QLA_SUCCESS; 45048c2ecf20Sopenharmony_ci 45058c2ecf20Sopenharmony_ci max_cnt = 0; 45068c2ecf20Sopenharmony_ci rval = qla_get_exchoffld_status(vha, &size, &max_cnt); 45078c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 45088c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0xd012, 45098c2ecf20Sopenharmony_ci "Failed to get exlogin status.\n"); 45108c2ecf20Sopenharmony_ci return rval; 45118c2ecf20Sopenharmony_ci } 45128c2ecf20Sopenharmony_ci 45138c2ecf20Sopenharmony_ci qla2x00_number_of_exch(vha, &actual_cnt, max_cnt); 45148c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd014, 45158c2ecf20Sopenharmony_ci "Actual exchange offload count: %d.\n", actual_cnt); 45168c2ecf20Sopenharmony_ci 45178c2ecf20Sopenharmony_ci totsz = actual_cnt * size; 45188c2ecf20Sopenharmony_ci 45198c2ecf20Sopenharmony_ci if (totsz != ha->exchoffld_size) { 45208c2ecf20Sopenharmony_ci qla2x00_free_exchoffld_buffer(ha); 45218c2ecf20Sopenharmony_ci if (actual_cnt <= FW_DEF_EXCHANGES_CNT) { 45228c2ecf20Sopenharmony_ci ha->exchoffld_size = 0; 45238c2ecf20Sopenharmony_ci ha->flags.exchoffld_enabled = 0; 45248c2ecf20Sopenharmony_ci return QLA_SUCCESS; 45258c2ecf20Sopenharmony_ci } 45268c2ecf20Sopenharmony_ci 45278c2ecf20Sopenharmony_ci ha->exchoffld_size = totsz; 45288c2ecf20Sopenharmony_ci 45298c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd016, 45308c2ecf20Sopenharmony_ci "Exchange offload: max_count=%d, actual count=%d entry sz=0x%x, total sz=0x%x\n", 45318c2ecf20Sopenharmony_ci max_cnt, actual_cnt, size, totsz); 45328c2ecf20Sopenharmony_ci 45338c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd017, 45348c2ecf20Sopenharmony_ci "Exchange Buffers requested size = 0x%x\n", 45358c2ecf20Sopenharmony_ci ha->exchoffld_size); 45368c2ecf20Sopenharmony_ci 45378c2ecf20Sopenharmony_ci /* Get consistent memory for extended logins */ 45388c2ecf20Sopenharmony_ci ha->exchoffld_buf = dma_alloc_coherent(&ha->pdev->dev, 45398c2ecf20Sopenharmony_ci ha->exchoffld_size, &ha->exchoffld_buf_dma, GFP_KERNEL); 45408c2ecf20Sopenharmony_ci if (!ha->exchoffld_buf) { 45418c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0xd013, 45428c2ecf20Sopenharmony_ci "Failed to allocate memory for Exchange Offload.\n"); 45438c2ecf20Sopenharmony_ci 45448c2ecf20Sopenharmony_ci if (ha->max_exchg > 45458c2ecf20Sopenharmony_ci (FW_DEF_EXCHANGES_CNT + REDUCE_EXCHANGES_CNT)) { 45468c2ecf20Sopenharmony_ci ha->max_exchg -= REDUCE_EXCHANGES_CNT; 45478c2ecf20Sopenharmony_ci } else if (ha->max_exchg > 45488c2ecf20Sopenharmony_ci (FW_DEF_EXCHANGES_CNT + 512)) { 45498c2ecf20Sopenharmony_ci ha->max_exchg -= 512; 45508c2ecf20Sopenharmony_ci } else { 45518c2ecf20Sopenharmony_ci ha->flags.exchoffld_enabled = 0; 45528c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0xd013, 45538c2ecf20Sopenharmony_ci "Disabling Exchange offload due to lack of memory\n"); 45548c2ecf20Sopenharmony_ci } 45558c2ecf20Sopenharmony_ci ha->exchoffld_size = 0; 45568c2ecf20Sopenharmony_ci 45578c2ecf20Sopenharmony_ci return -ENOMEM; 45588c2ecf20Sopenharmony_ci } 45598c2ecf20Sopenharmony_ci } else if (!ha->exchoffld_buf || (actual_cnt <= FW_DEF_EXCHANGES_CNT)) { 45608c2ecf20Sopenharmony_ci /* pathological case */ 45618c2ecf20Sopenharmony_ci qla2x00_free_exchoffld_buffer(ha); 45628c2ecf20Sopenharmony_ci ha->exchoffld_size = 0; 45638c2ecf20Sopenharmony_ci ha->flags.exchoffld_enabled = 0; 45648c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xd016, 45658c2ecf20Sopenharmony_ci "Exchange offload not enable: offld size=%d, actual count=%d entry sz=0x%x, total sz=0x%x.\n", 45668c2ecf20Sopenharmony_ci ha->exchoffld_size, actual_cnt, size, totsz); 45678c2ecf20Sopenharmony_ci return 0; 45688c2ecf20Sopenharmony_ci } 45698c2ecf20Sopenharmony_ci 45708c2ecf20Sopenharmony_ci /* Now configure the dma buffer */ 45718c2ecf20Sopenharmony_ci rval = qla_set_exchoffld_mem_cfg(vha); 45728c2ecf20Sopenharmony_ci if (rval) { 45738c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0xd02e, 45748c2ecf20Sopenharmony_ci "Setup exchange offload buffer ****FAILED****.\n"); 45758c2ecf20Sopenharmony_ci qla2x00_free_exchoffld_buffer(ha); 45768c2ecf20Sopenharmony_ci } else { 45778c2ecf20Sopenharmony_ci /* re-adjust number of target exchange */ 45788c2ecf20Sopenharmony_ci struct init_cb_81xx *icb = (struct init_cb_81xx *)ha->init_cb; 45798c2ecf20Sopenharmony_ci 45808c2ecf20Sopenharmony_ci if (qla_ini_mode_enabled(vha)) 45818c2ecf20Sopenharmony_ci icb->exchange_count = 0; 45828c2ecf20Sopenharmony_ci else 45838c2ecf20Sopenharmony_ci icb->exchange_count = cpu_to_le16(vha->ql2xexchoffld); 45848c2ecf20Sopenharmony_ci } 45858c2ecf20Sopenharmony_ci 45868c2ecf20Sopenharmony_ci return rval; 45878c2ecf20Sopenharmony_ci} 45888c2ecf20Sopenharmony_ci 45898c2ecf20Sopenharmony_ci/* 45908c2ecf20Sopenharmony_ci* qla2x00_free_exchoffld_buffer 45918c2ecf20Sopenharmony_ci* 45928c2ecf20Sopenharmony_ci* Input: 45938c2ecf20Sopenharmony_ci* ha = adapter block pointer 45948c2ecf20Sopenharmony_ci*/ 45958c2ecf20Sopenharmony_civoid 45968c2ecf20Sopenharmony_ciqla2x00_free_exchoffld_buffer(struct qla_hw_data *ha) 45978c2ecf20Sopenharmony_ci{ 45988c2ecf20Sopenharmony_ci if (ha->exchoffld_buf) { 45998c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ha->exchoffld_size, 46008c2ecf20Sopenharmony_ci ha->exchoffld_buf, ha->exchoffld_buf_dma); 46018c2ecf20Sopenharmony_ci ha->exchoffld_buf = NULL; 46028c2ecf20Sopenharmony_ci ha->exchoffld_size = 0; 46038c2ecf20Sopenharmony_ci } 46048c2ecf20Sopenharmony_ci} 46058c2ecf20Sopenharmony_ci 46068c2ecf20Sopenharmony_ci/* 46078c2ecf20Sopenharmony_ci* qla2x00_free_fw_dump 46088c2ecf20Sopenharmony_ci* Frees fw dump stuff. 46098c2ecf20Sopenharmony_ci* 46108c2ecf20Sopenharmony_ci* Input: 46118c2ecf20Sopenharmony_ci* ha = adapter block pointer 46128c2ecf20Sopenharmony_ci*/ 46138c2ecf20Sopenharmony_cistatic void 46148c2ecf20Sopenharmony_ciqla2x00_free_fw_dump(struct qla_hw_data *ha) 46158c2ecf20Sopenharmony_ci{ 46168c2ecf20Sopenharmony_ci struct fwdt *fwdt = ha->fwdt; 46178c2ecf20Sopenharmony_ci uint j; 46188c2ecf20Sopenharmony_ci 46198c2ecf20Sopenharmony_ci if (ha->fce) 46208c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 46218c2ecf20Sopenharmony_ci FCE_SIZE, ha->fce, ha->fce_dma); 46228c2ecf20Sopenharmony_ci 46238c2ecf20Sopenharmony_ci if (ha->eft) 46248c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 46258c2ecf20Sopenharmony_ci EFT_SIZE, ha->eft, ha->eft_dma); 46268c2ecf20Sopenharmony_ci 46278c2ecf20Sopenharmony_ci if (ha->fw_dump) 46288c2ecf20Sopenharmony_ci vfree(ha->fw_dump); 46298c2ecf20Sopenharmony_ci 46308c2ecf20Sopenharmony_ci ha->fce = NULL; 46318c2ecf20Sopenharmony_ci ha->fce_dma = 0; 46328c2ecf20Sopenharmony_ci ha->flags.fce_enabled = 0; 46338c2ecf20Sopenharmony_ci ha->eft = NULL; 46348c2ecf20Sopenharmony_ci ha->eft_dma = 0; 46358c2ecf20Sopenharmony_ci ha->fw_dumped = false; 46368c2ecf20Sopenharmony_ci ha->fw_dump_cap_flags = 0; 46378c2ecf20Sopenharmony_ci ha->fw_dump_reading = 0; 46388c2ecf20Sopenharmony_ci ha->fw_dump = NULL; 46398c2ecf20Sopenharmony_ci ha->fw_dump_len = 0; 46408c2ecf20Sopenharmony_ci 46418c2ecf20Sopenharmony_ci for (j = 0; j < 2; j++, fwdt++) { 46428c2ecf20Sopenharmony_ci if (fwdt->template) 46438c2ecf20Sopenharmony_ci vfree(fwdt->template); 46448c2ecf20Sopenharmony_ci fwdt->template = NULL; 46458c2ecf20Sopenharmony_ci fwdt->length = 0; 46468c2ecf20Sopenharmony_ci } 46478c2ecf20Sopenharmony_ci} 46488c2ecf20Sopenharmony_ci 46498c2ecf20Sopenharmony_ci/* 46508c2ecf20Sopenharmony_ci* qla2x00_mem_free 46518c2ecf20Sopenharmony_ci* Frees all adapter allocated memory. 46528c2ecf20Sopenharmony_ci* 46538c2ecf20Sopenharmony_ci* Input: 46548c2ecf20Sopenharmony_ci* ha = adapter block pointer. 46558c2ecf20Sopenharmony_ci*/ 46568c2ecf20Sopenharmony_cistatic void 46578c2ecf20Sopenharmony_ciqla2x00_mem_free(struct qla_hw_data *ha) 46588c2ecf20Sopenharmony_ci{ 46598c2ecf20Sopenharmony_ci qla2x00_free_fw_dump(ha); 46608c2ecf20Sopenharmony_ci 46618c2ecf20Sopenharmony_ci if (ha->mctp_dump) 46628c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, MCTP_DUMP_SIZE, ha->mctp_dump, 46638c2ecf20Sopenharmony_ci ha->mctp_dump_dma); 46648c2ecf20Sopenharmony_ci ha->mctp_dump = NULL; 46658c2ecf20Sopenharmony_ci 46668c2ecf20Sopenharmony_ci mempool_destroy(ha->srb_mempool); 46678c2ecf20Sopenharmony_ci ha->srb_mempool = NULL; 46688c2ecf20Sopenharmony_ci 46698c2ecf20Sopenharmony_ci if (ha->dcbx_tlv) 46708c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE, 46718c2ecf20Sopenharmony_ci ha->dcbx_tlv, ha->dcbx_tlv_dma); 46728c2ecf20Sopenharmony_ci ha->dcbx_tlv = NULL; 46738c2ecf20Sopenharmony_ci 46748c2ecf20Sopenharmony_ci if (ha->xgmac_data) 46758c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE, 46768c2ecf20Sopenharmony_ci ha->xgmac_data, ha->xgmac_data_dma); 46778c2ecf20Sopenharmony_ci ha->xgmac_data = NULL; 46788c2ecf20Sopenharmony_ci 46798c2ecf20Sopenharmony_ci if (ha->sns_cmd) 46808c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), 46818c2ecf20Sopenharmony_ci ha->sns_cmd, ha->sns_cmd_dma); 46828c2ecf20Sopenharmony_ci ha->sns_cmd = NULL; 46838c2ecf20Sopenharmony_ci ha->sns_cmd_dma = 0; 46848c2ecf20Sopenharmony_ci 46858c2ecf20Sopenharmony_ci if (ha->ct_sns) 46868c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt), 46878c2ecf20Sopenharmony_ci ha->ct_sns, ha->ct_sns_dma); 46888c2ecf20Sopenharmony_ci ha->ct_sns = NULL; 46898c2ecf20Sopenharmony_ci ha->ct_sns_dma = 0; 46908c2ecf20Sopenharmony_ci 46918c2ecf20Sopenharmony_ci if (ha->sfp_data) 46928c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ha->sfp_data, 46938c2ecf20Sopenharmony_ci ha->sfp_data_dma); 46948c2ecf20Sopenharmony_ci ha->sfp_data = NULL; 46958c2ecf20Sopenharmony_ci 46968c2ecf20Sopenharmony_ci if (ha->flt) 46978c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, 46988c2ecf20Sopenharmony_ci sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE, 46998c2ecf20Sopenharmony_ci ha->flt, ha->flt_dma); 47008c2ecf20Sopenharmony_ci ha->flt = NULL; 47018c2ecf20Sopenharmony_ci ha->flt_dma = 0; 47028c2ecf20Sopenharmony_ci 47038c2ecf20Sopenharmony_ci if (ha->ms_iocb) 47048c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); 47058c2ecf20Sopenharmony_ci ha->ms_iocb = NULL; 47068c2ecf20Sopenharmony_ci ha->ms_iocb_dma = 0; 47078c2ecf20Sopenharmony_ci 47088c2ecf20Sopenharmony_ci if (ha->sf_init_cb) 47098c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, 47108c2ecf20Sopenharmony_ci ha->sf_init_cb, ha->sf_init_cb_dma); 47118c2ecf20Sopenharmony_ci 47128c2ecf20Sopenharmony_ci if (ha->ex_init_cb) 47138c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, 47148c2ecf20Sopenharmony_ci ha->ex_init_cb, ha->ex_init_cb_dma); 47158c2ecf20Sopenharmony_ci ha->ex_init_cb = NULL; 47168c2ecf20Sopenharmony_ci ha->ex_init_cb_dma = 0; 47178c2ecf20Sopenharmony_ci 47188c2ecf20Sopenharmony_ci if (ha->async_pd) 47198c2ecf20Sopenharmony_ci dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); 47208c2ecf20Sopenharmony_ci ha->async_pd = NULL; 47218c2ecf20Sopenharmony_ci ha->async_pd_dma = 0; 47228c2ecf20Sopenharmony_ci 47238c2ecf20Sopenharmony_ci dma_pool_destroy(ha->s_dma_pool); 47248c2ecf20Sopenharmony_ci ha->s_dma_pool = NULL; 47258c2ecf20Sopenharmony_ci 47268c2ecf20Sopenharmony_ci if (ha->gid_list) 47278c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), 47288c2ecf20Sopenharmony_ci ha->gid_list, ha->gid_list_dma); 47298c2ecf20Sopenharmony_ci ha->gid_list = NULL; 47308c2ecf20Sopenharmony_ci ha->gid_list_dma = 0; 47318c2ecf20Sopenharmony_ci 47328c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) { 47338c2ecf20Sopenharmony_ci if (!list_empty(&ha->gbl_dsd_list)) { 47348c2ecf20Sopenharmony_ci struct dsd_dma *dsd_ptr, *tdsd_ptr; 47358c2ecf20Sopenharmony_ci 47368c2ecf20Sopenharmony_ci /* clean up allocated prev pool */ 47378c2ecf20Sopenharmony_ci list_for_each_entry_safe(dsd_ptr, 47388c2ecf20Sopenharmony_ci tdsd_ptr, &ha->gbl_dsd_list, list) { 47398c2ecf20Sopenharmony_ci dma_pool_free(ha->dl_dma_pool, 47408c2ecf20Sopenharmony_ci dsd_ptr->dsd_addr, dsd_ptr->dsd_list_dma); 47418c2ecf20Sopenharmony_ci list_del(&dsd_ptr->list); 47428c2ecf20Sopenharmony_ci kfree(dsd_ptr); 47438c2ecf20Sopenharmony_ci } 47448c2ecf20Sopenharmony_ci } 47458c2ecf20Sopenharmony_ci } 47468c2ecf20Sopenharmony_ci 47478c2ecf20Sopenharmony_ci dma_pool_destroy(ha->dl_dma_pool); 47488c2ecf20Sopenharmony_ci ha->dl_dma_pool = NULL; 47498c2ecf20Sopenharmony_ci 47508c2ecf20Sopenharmony_ci dma_pool_destroy(ha->fcp_cmnd_dma_pool); 47518c2ecf20Sopenharmony_ci ha->fcp_cmnd_dma_pool = NULL; 47528c2ecf20Sopenharmony_ci 47538c2ecf20Sopenharmony_ci mempool_destroy(ha->ctx_mempool); 47548c2ecf20Sopenharmony_ci ha->ctx_mempool = NULL; 47558c2ecf20Sopenharmony_ci 47568c2ecf20Sopenharmony_ci if (ql2xenabledif && ha->dif_bundl_pool) { 47578c2ecf20Sopenharmony_ci struct dsd_dma *dsd, *nxt; 47588c2ecf20Sopenharmony_ci 47598c2ecf20Sopenharmony_ci list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head, 47608c2ecf20Sopenharmony_ci list) { 47618c2ecf20Sopenharmony_ci list_del(&dsd->list); 47628c2ecf20Sopenharmony_ci dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr, 47638c2ecf20Sopenharmony_ci dsd->dsd_list_dma); 47648c2ecf20Sopenharmony_ci ha->dif_bundle_dma_allocs--; 47658c2ecf20Sopenharmony_ci kfree(dsd); 47668c2ecf20Sopenharmony_ci ha->dif_bundle_kallocs--; 47678c2ecf20Sopenharmony_ci ha->pool.unusable.count--; 47688c2ecf20Sopenharmony_ci } 47698c2ecf20Sopenharmony_ci list_for_each_entry_safe(dsd, nxt, &ha->pool.good.head, list) { 47708c2ecf20Sopenharmony_ci list_del(&dsd->list); 47718c2ecf20Sopenharmony_ci dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr, 47728c2ecf20Sopenharmony_ci dsd->dsd_list_dma); 47738c2ecf20Sopenharmony_ci ha->dif_bundle_dma_allocs--; 47748c2ecf20Sopenharmony_ci kfree(dsd); 47758c2ecf20Sopenharmony_ci ha->dif_bundle_kallocs--; 47768c2ecf20Sopenharmony_ci } 47778c2ecf20Sopenharmony_ci } 47788c2ecf20Sopenharmony_ci 47798c2ecf20Sopenharmony_ci dma_pool_destroy(ha->dif_bundl_pool); 47808c2ecf20Sopenharmony_ci ha->dif_bundl_pool = NULL; 47818c2ecf20Sopenharmony_ci 47828c2ecf20Sopenharmony_ci qlt_mem_free(ha); 47838c2ecf20Sopenharmony_ci 47848c2ecf20Sopenharmony_ci if (ha->init_cb) 47858c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, 47868c2ecf20Sopenharmony_ci ha->init_cb, ha->init_cb_dma); 47878c2ecf20Sopenharmony_ci ha->init_cb = NULL; 47888c2ecf20Sopenharmony_ci ha->init_cb_dma = 0; 47898c2ecf20Sopenharmony_ci 47908c2ecf20Sopenharmony_ci vfree(ha->optrom_buffer); 47918c2ecf20Sopenharmony_ci ha->optrom_buffer = NULL; 47928c2ecf20Sopenharmony_ci kfree(ha->nvram); 47938c2ecf20Sopenharmony_ci ha->nvram = NULL; 47948c2ecf20Sopenharmony_ci kfree(ha->npiv_info); 47958c2ecf20Sopenharmony_ci ha->npiv_info = NULL; 47968c2ecf20Sopenharmony_ci kfree(ha->swl); 47978c2ecf20Sopenharmony_ci ha->swl = NULL; 47988c2ecf20Sopenharmony_ci kfree(ha->loop_id_map); 47998c2ecf20Sopenharmony_ci ha->sf_init_cb = NULL; 48008c2ecf20Sopenharmony_ci ha->sf_init_cb_dma = 0; 48018c2ecf20Sopenharmony_ci ha->loop_id_map = NULL; 48028c2ecf20Sopenharmony_ci} 48038c2ecf20Sopenharmony_ci 48048c2ecf20Sopenharmony_cistruct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, 48058c2ecf20Sopenharmony_ci struct qla_hw_data *ha) 48068c2ecf20Sopenharmony_ci{ 48078c2ecf20Sopenharmony_ci struct Scsi_Host *host; 48088c2ecf20Sopenharmony_ci struct scsi_qla_host *vha = NULL; 48098c2ecf20Sopenharmony_ci 48108c2ecf20Sopenharmony_ci host = scsi_host_alloc(sht, sizeof(scsi_qla_host_t)); 48118c2ecf20Sopenharmony_ci if (!host) { 48128c2ecf20Sopenharmony_ci ql_log_pci(ql_log_fatal, ha->pdev, 0x0107, 48138c2ecf20Sopenharmony_ci "Failed to allocate host from the scsi layer, aborting.\n"); 48148c2ecf20Sopenharmony_ci return NULL; 48158c2ecf20Sopenharmony_ci } 48168c2ecf20Sopenharmony_ci 48178c2ecf20Sopenharmony_ci /* Clear our data area */ 48188c2ecf20Sopenharmony_ci vha = shost_priv(host); 48198c2ecf20Sopenharmony_ci memset(vha, 0, sizeof(scsi_qla_host_t)); 48208c2ecf20Sopenharmony_ci 48218c2ecf20Sopenharmony_ci vha->host = host; 48228c2ecf20Sopenharmony_ci vha->host_no = host->host_no; 48238c2ecf20Sopenharmony_ci vha->hw = ha; 48248c2ecf20Sopenharmony_ci 48258c2ecf20Sopenharmony_ci vha->qlini_mode = ql2x_ini_mode; 48268c2ecf20Sopenharmony_ci vha->ql2xexchoffld = ql2xexchoffld; 48278c2ecf20Sopenharmony_ci vha->ql2xiniexchg = ql2xiniexchg; 48288c2ecf20Sopenharmony_ci 48298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->vp_fcports); 48308c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->work_list); 48318c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->list); 48328c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->qla_cmd_list); 48338c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list); 48348c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->logo_list); 48358c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->plogi_ack_list); 48368c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->qp_list); 48378c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->gnl.fcports); 48388c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->gpnid_list); 48398c2ecf20Sopenharmony_ci INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn); 48408c2ecf20Sopenharmony_ci 48418c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&vha->purex_list.head); 48428c2ecf20Sopenharmony_ci spin_lock_init(&vha->purex_list.lock); 48438c2ecf20Sopenharmony_ci 48448c2ecf20Sopenharmony_ci spin_lock_init(&vha->work_lock); 48458c2ecf20Sopenharmony_ci spin_lock_init(&vha->cmd_list_lock); 48468c2ecf20Sopenharmony_ci init_waitqueue_head(&vha->fcport_waitQ); 48478c2ecf20Sopenharmony_ci init_waitqueue_head(&vha->vref_waitq); 48488c2ecf20Sopenharmony_ci 48498c2ecf20Sopenharmony_ci vha->gnl.size = sizeof(struct get_name_list_extended) * 48508c2ecf20Sopenharmony_ci (ha->max_loop_id + 1); 48518c2ecf20Sopenharmony_ci vha->gnl.l = dma_alloc_coherent(&ha->pdev->dev, 48528c2ecf20Sopenharmony_ci vha->gnl.size, &vha->gnl.ldma, GFP_KERNEL); 48538c2ecf20Sopenharmony_ci if (!vha->gnl.l) { 48548c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0xd04a, 48558c2ecf20Sopenharmony_ci "Alloc failed for name list.\n"); 48568c2ecf20Sopenharmony_ci scsi_host_put(vha->host); 48578c2ecf20Sopenharmony_ci return NULL; 48588c2ecf20Sopenharmony_ci } 48598c2ecf20Sopenharmony_ci 48608c2ecf20Sopenharmony_ci /* todo: what about ext login? */ 48618c2ecf20Sopenharmony_ci vha->scan.size = ha->max_fibre_devices * sizeof(struct fab_scan_rp); 48628c2ecf20Sopenharmony_ci vha->scan.l = vmalloc(vha->scan.size); 48638c2ecf20Sopenharmony_ci if (!vha->scan.l) { 48648c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0xd04a, 48658c2ecf20Sopenharmony_ci "Alloc failed for scan database.\n"); 48668c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, vha->gnl.size, 48678c2ecf20Sopenharmony_ci vha->gnl.l, vha->gnl.ldma); 48688c2ecf20Sopenharmony_ci vha->gnl.l = NULL; 48698c2ecf20Sopenharmony_ci scsi_host_put(vha->host); 48708c2ecf20Sopenharmony_ci return NULL; 48718c2ecf20Sopenharmony_ci } 48728c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); 48738c2ecf20Sopenharmony_ci 48748c2ecf20Sopenharmony_ci snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", 48758c2ecf20Sopenharmony_ci QLA2XXX_DRIVER_NAME, vha->host_no); 48768c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0041, 48778c2ecf20Sopenharmony_ci "Allocated the host=%p hw=%p vha=%p dev_name=%s", 48788c2ecf20Sopenharmony_ci vha->host, vha->hw, vha, 48798c2ecf20Sopenharmony_ci dev_name(&(ha->pdev->dev))); 48808c2ecf20Sopenharmony_ci 48818c2ecf20Sopenharmony_ci return vha; 48828c2ecf20Sopenharmony_ci} 48838c2ecf20Sopenharmony_ci 48848c2ecf20Sopenharmony_cistruct qla_work_evt * 48858c2ecf20Sopenharmony_ciqla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) 48868c2ecf20Sopenharmony_ci{ 48878c2ecf20Sopenharmony_ci struct qla_work_evt *e; 48888c2ecf20Sopenharmony_ci uint8_t bail; 48898c2ecf20Sopenharmony_ci 48908c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &vha->dpc_flags)) 48918c2ecf20Sopenharmony_ci return NULL; 48928c2ecf20Sopenharmony_ci 48938c2ecf20Sopenharmony_ci QLA_VHA_MARK_BUSY(vha, bail); 48948c2ecf20Sopenharmony_ci if (bail) 48958c2ecf20Sopenharmony_ci return NULL; 48968c2ecf20Sopenharmony_ci 48978c2ecf20Sopenharmony_ci e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); 48988c2ecf20Sopenharmony_ci if (!e) { 48998c2ecf20Sopenharmony_ci QLA_VHA_MARK_NOT_BUSY(vha); 49008c2ecf20Sopenharmony_ci return NULL; 49018c2ecf20Sopenharmony_ci } 49028c2ecf20Sopenharmony_ci 49038c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&e->list); 49048c2ecf20Sopenharmony_ci e->type = type; 49058c2ecf20Sopenharmony_ci e->flags = QLA_EVT_FLAG_FREE; 49068c2ecf20Sopenharmony_ci return e; 49078c2ecf20Sopenharmony_ci} 49088c2ecf20Sopenharmony_ci 49098c2ecf20Sopenharmony_ciint 49108c2ecf20Sopenharmony_ciqla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e) 49118c2ecf20Sopenharmony_ci{ 49128c2ecf20Sopenharmony_ci unsigned long flags; 49138c2ecf20Sopenharmony_ci bool q = false; 49148c2ecf20Sopenharmony_ci 49158c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->work_lock, flags); 49168c2ecf20Sopenharmony_ci list_add_tail(&e->list, &vha->work_list); 49178c2ecf20Sopenharmony_ci 49188c2ecf20Sopenharmony_ci if (!test_and_set_bit(IOCB_WORK_ACTIVE, &vha->dpc_flags)) 49198c2ecf20Sopenharmony_ci q = true; 49208c2ecf20Sopenharmony_ci 49218c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->work_lock, flags); 49228c2ecf20Sopenharmony_ci 49238c2ecf20Sopenharmony_ci if (q) 49248c2ecf20Sopenharmony_ci queue_work(vha->hw->wq, &vha->iocb_work); 49258c2ecf20Sopenharmony_ci 49268c2ecf20Sopenharmony_ci return QLA_SUCCESS; 49278c2ecf20Sopenharmony_ci} 49288c2ecf20Sopenharmony_ci 49298c2ecf20Sopenharmony_ciint 49308c2ecf20Sopenharmony_ciqla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code, 49318c2ecf20Sopenharmony_ci u32 data) 49328c2ecf20Sopenharmony_ci{ 49338c2ecf20Sopenharmony_ci struct qla_work_evt *e; 49348c2ecf20Sopenharmony_ci 49358c2ecf20Sopenharmony_ci e = qla2x00_alloc_work(vha, QLA_EVT_AEN); 49368c2ecf20Sopenharmony_ci if (!e) 49378c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 49388c2ecf20Sopenharmony_ci 49398c2ecf20Sopenharmony_ci e->u.aen.code = code; 49408c2ecf20Sopenharmony_ci e->u.aen.data = data; 49418c2ecf20Sopenharmony_ci return qla2x00_post_work(vha, e); 49428c2ecf20Sopenharmony_ci} 49438c2ecf20Sopenharmony_ci 49448c2ecf20Sopenharmony_ciint 49458c2ecf20Sopenharmony_ciqla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb) 49468c2ecf20Sopenharmony_ci{ 49478c2ecf20Sopenharmony_ci struct qla_work_evt *e; 49488c2ecf20Sopenharmony_ci 49498c2ecf20Sopenharmony_ci e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK); 49508c2ecf20Sopenharmony_ci if (!e) 49518c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 49528c2ecf20Sopenharmony_ci 49538c2ecf20Sopenharmony_ci memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t)); 49548c2ecf20Sopenharmony_ci return qla2x00_post_work(vha, e); 49558c2ecf20Sopenharmony_ci} 49568c2ecf20Sopenharmony_ci 49578c2ecf20Sopenharmony_ci#define qla2x00_post_async_work(name, type) \ 49588c2ecf20Sopenharmony_ciint qla2x00_post_async_##name##_work( \ 49598c2ecf20Sopenharmony_ci struct scsi_qla_host *vha, \ 49608c2ecf20Sopenharmony_ci fc_port_t *fcport, uint16_t *data) \ 49618c2ecf20Sopenharmony_ci{ \ 49628c2ecf20Sopenharmony_ci struct qla_work_evt *e; \ 49638c2ecf20Sopenharmony_ci \ 49648c2ecf20Sopenharmony_ci e = qla2x00_alloc_work(vha, type); \ 49658c2ecf20Sopenharmony_ci if (!e) \ 49668c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; \ 49678c2ecf20Sopenharmony_ci \ 49688c2ecf20Sopenharmony_ci e->u.logio.fcport = fcport; \ 49698c2ecf20Sopenharmony_ci if (data) { \ 49708c2ecf20Sopenharmony_ci e->u.logio.data[0] = data[0]; \ 49718c2ecf20Sopenharmony_ci e->u.logio.data[1] = data[1]; \ 49728c2ecf20Sopenharmony_ci } \ 49738c2ecf20Sopenharmony_ci fcport->flags |= FCF_ASYNC_ACTIVE; \ 49748c2ecf20Sopenharmony_ci return qla2x00_post_work(vha, e); \ 49758c2ecf20Sopenharmony_ci} 49768c2ecf20Sopenharmony_ci 49778c2ecf20Sopenharmony_ciqla2x00_post_async_work(login, QLA_EVT_ASYNC_LOGIN); 49788c2ecf20Sopenharmony_ciqla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT); 49798c2ecf20Sopenharmony_ciqla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC); 49808c2ecf20Sopenharmony_ciqla2x00_post_async_work(prlo, QLA_EVT_ASYNC_PRLO); 49818c2ecf20Sopenharmony_ciqla2x00_post_async_work(prlo_done, QLA_EVT_ASYNC_PRLO_DONE); 49828c2ecf20Sopenharmony_ci 49838c2ecf20Sopenharmony_ciint 49848c2ecf20Sopenharmony_ciqla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code) 49858c2ecf20Sopenharmony_ci{ 49868c2ecf20Sopenharmony_ci struct qla_work_evt *e; 49878c2ecf20Sopenharmony_ci 49888c2ecf20Sopenharmony_ci e = qla2x00_alloc_work(vha, QLA_EVT_UEVENT); 49898c2ecf20Sopenharmony_ci if (!e) 49908c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 49918c2ecf20Sopenharmony_ci 49928c2ecf20Sopenharmony_ci e->u.uevent.code = code; 49938c2ecf20Sopenharmony_ci return qla2x00_post_work(vha, e); 49948c2ecf20Sopenharmony_ci} 49958c2ecf20Sopenharmony_ci 49968c2ecf20Sopenharmony_cistatic void 49978c2ecf20Sopenharmony_ciqla2x00_uevent_emit(struct scsi_qla_host *vha, u32 code) 49988c2ecf20Sopenharmony_ci{ 49998c2ecf20Sopenharmony_ci char event_string[40]; 50008c2ecf20Sopenharmony_ci char *envp[] = { event_string, NULL }; 50018c2ecf20Sopenharmony_ci 50028c2ecf20Sopenharmony_ci switch (code) { 50038c2ecf20Sopenharmony_ci case QLA_UEVENT_CODE_FW_DUMP: 50048c2ecf20Sopenharmony_ci snprintf(event_string, sizeof(event_string), "FW_DUMP=%lu", 50058c2ecf20Sopenharmony_ci vha->host_no); 50068c2ecf20Sopenharmony_ci break; 50078c2ecf20Sopenharmony_ci default: 50088c2ecf20Sopenharmony_ci /* do nothing */ 50098c2ecf20Sopenharmony_ci break; 50108c2ecf20Sopenharmony_ci } 50118c2ecf20Sopenharmony_ci kobject_uevent_env(&vha->hw->pdev->dev.kobj, KOBJ_CHANGE, envp); 50128c2ecf20Sopenharmony_ci} 50138c2ecf20Sopenharmony_ci 50148c2ecf20Sopenharmony_ciint 50158c2ecf20Sopenharmony_ciqlafx00_post_aenfx_work(struct scsi_qla_host *vha, uint32_t evtcode, 50168c2ecf20Sopenharmony_ci uint32_t *data, int cnt) 50178c2ecf20Sopenharmony_ci{ 50188c2ecf20Sopenharmony_ci struct qla_work_evt *e; 50198c2ecf20Sopenharmony_ci 50208c2ecf20Sopenharmony_ci e = qla2x00_alloc_work(vha, QLA_EVT_AENFX); 50218c2ecf20Sopenharmony_ci if (!e) 50228c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 50238c2ecf20Sopenharmony_ci 50248c2ecf20Sopenharmony_ci e->u.aenfx.evtcode = evtcode; 50258c2ecf20Sopenharmony_ci e->u.aenfx.count = cnt; 50268c2ecf20Sopenharmony_ci memcpy(e->u.aenfx.mbx, data, sizeof(*data) * cnt); 50278c2ecf20Sopenharmony_ci return qla2x00_post_work(vha, e); 50288c2ecf20Sopenharmony_ci} 50298c2ecf20Sopenharmony_ci 50308c2ecf20Sopenharmony_civoid qla24xx_sched_upd_fcport(fc_port_t *fcport) 50318c2ecf20Sopenharmony_ci{ 50328c2ecf20Sopenharmony_ci unsigned long flags; 50338c2ecf20Sopenharmony_ci 50348c2ecf20Sopenharmony_ci if (IS_SW_RESV_ADDR(fcport->d_id)) 50358c2ecf20Sopenharmony_ci return; 50368c2ecf20Sopenharmony_ci 50378c2ecf20Sopenharmony_ci spin_lock_irqsave(&fcport->vha->work_lock, flags); 50388c2ecf20Sopenharmony_ci if (fcport->disc_state == DSC_UPD_FCPORT) { 50398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&fcport->vha->work_lock, flags); 50408c2ecf20Sopenharmony_ci return; 50418c2ecf20Sopenharmony_ci } 50428c2ecf20Sopenharmony_ci fcport->jiffies_at_registration = jiffies; 50438c2ecf20Sopenharmony_ci fcport->sec_since_registration = 0; 50448c2ecf20Sopenharmony_ci fcport->next_disc_state = DSC_DELETED; 50458c2ecf20Sopenharmony_ci qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT); 50468c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&fcport->vha->work_lock, flags); 50478c2ecf20Sopenharmony_ci 50488c2ecf20Sopenharmony_ci queue_work(system_unbound_wq, &fcport->reg_work); 50498c2ecf20Sopenharmony_ci} 50508c2ecf20Sopenharmony_ci 50518c2ecf20Sopenharmony_cistatic 50528c2ecf20Sopenharmony_civoid qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) 50538c2ecf20Sopenharmony_ci{ 50548c2ecf20Sopenharmony_ci unsigned long flags; 50558c2ecf20Sopenharmony_ci fc_port_t *fcport = NULL, *tfcp; 50568c2ecf20Sopenharmony_ci struct qlt_plogi_ack_t *pla = 50578c2ecf20Sopenharmony_ci (struct qlt_plogi_ack_t *)e->u.new_sess.pla; 50588c2ecf20Sopenharmony_ci uint8_t free_fcport = 0; 50598c2ecf20Sopenharmony_ci 50608c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0xffff, 50618c2ecf20Sopenharmony_ci "%s %d %8phC enter\n", 50628c2ecf20Sopenharmony_ci __func__, __LINE__, e->u.new_sess.port_name); 50638c2ecf20Sopenharmony_ci 50648c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); 50658c2ecf20Sopenharmony_ci fcport = qla2x00_find_fcport_by_wwpn(vha, e->u.new_sess.port_name, 1); 50668c2ecf20Sopenharmony_ci if (fcport) { 50678c2ecf20Sopenharmony_ci fcport->d_id = e->u.new_sess.id; 50688c2ecf20Sopenharmony_ci if (pla) { 50698c2ecf20Sopenharmony_ci fcport->fw_login_state = DSC_LS_PLOGI_PEND; 50708c2ecf20Sopenharmony_ci memcpy(fcport->node_name, 50718c2ecf20Sopenharmony_ci pla->iocb.u.isp24.u.plogi.node_name, 50728c2ecf20Sopenharmony_ci WWN_SIZE); 50738c2ecf20Sopenharmony_ci qlt_plogi_ack_link(vha, pla, fcport, QLT_PLOGI_LINK_SAME_WWN); 50748c2ecf20Sopenharmony_ci /* we took an extra ref_count to prevent PLOGI ACK when 50758c2ecf20Sopenharmony_ci * fcport/sess has not been created. 50768c2ecf20Sopenharmony_ci */ 50778c2ecf20Sopenharmony_ci pla->ref_count--; 50788c2ecf20Sopenharmony_ci } 50798c2ecf20Sopenharmony_ci } else { 50808c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); 50818c2ecf20Sopenharmony_ci fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL); 50828c2ecf20Sopenharmony_ci if (fcport) { 50838c2ecf20Sopenharmony_ci fcport->d_id = e->u.new_sess.id; 50848c2ecf20Sopenharmony_ci fcport->flags |= FCF_FABRIC_DEVICE; 50858c2ecf20Sopenharmony_ci fcport->fw_login_state = DSC_LS_PLOGI_PEND; 50868c2ecf20Sopenharmony_ci 50878c2ecf20Sopenharmony_ci memcpy(fcport->port_name, e->u.new_sess.port_name, 50888c2ecf20Sopenharmony_ci WWN_SIZE); 50898c2ecf20Sopenharmony_ci 50908c2ecf20Sopenharmony_ci fcport->fc4_type = e->u.new_sess.fc4_type; 50918c2ecf20Sopenharmony_ci if (e->u.new_sess.fc4_type & FS_FCP_IS_N2N) { 50928c2ecf20Sopenharmony_ci fcport->dm_login_expire = jiffies + 50938c2ecf20Sopenharmony_ci QLA_N2N_WAIT_TIME * HZ; 50948c2ecf20Sopenharmony_ci fcport->fc4_type = FS_FC4TYPE_FCP; 50958c2ecf20Sopenharmony_ci fcport->n2n_flag = 1; 50968c2ecf20Sopenharmony_ci if (vha->flags.nvme_enabled) 50978c2ecf20Sopenharmony_ci fcport->fc4_type |= FS_FC4TYPE_NVME; 50988c2ecf20Sopenharmony_ci } 50998c2ecf20Sopenharmony_ci 51008c2ecf20Sopenharmony_ci } else { 51018c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0xffff, 51028c2ecf20Sopenharmony_ci "%s %8phC mem alloc fail.\n", 51038c2ecf20Sopenharmony_ci __func__, e->u.new_sess.port_name); 51048c2ecf20Sopenharmony_ci 51058c2ecf20Sopenharmony_ci if (pla) { 51068c2ecf20Sopenharmony_ci list_del(&pla->list); 51078c2ecf20Sopenharmony_ci kmem_cache_free(qla_tgt_plogi_cachep, pla); 51088c2ecf20Sopenharmony_ci } 51098c2ecf20Sopenharmony_ci return; 51108c2ecf20Sopenharmony_ci } 51118c2ecf20Sopenharmony_ci 51128c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); 51138c2ecf20Sopenharmony_ci /* search again to make sure no one else got ahead */ 51148c2ecf20Sopenharmony_ci tfcp = qla2x00_find_fcport_by_wwpn(vha, 51158c2ecf20Sopenharmony_ci e->u.new_sess.port_name, 1); 51168c2ecf20Sopenharmony_ci if (tfcp) { 51178c2ecf20Sopenharmony_ci /* should rarily happen */ 51188c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0xffff, 51198c2ecf20Sopenharmony_ci "%s %8phC found existing fcport b4 add. DS %d LS %d\n", 51208c2ecf20Sopenharmony_ci __func__, tfcp->port_name, tfcp->disc_state, 51218c2ecf20Sopenharmony_ci tfcp->fw_login_state); 51228c2ecf20Sopenharmony_ci 51238c2ecf20Sopenharmony_ci free_fcport = 1; 51248c2ecf20Sopenharmony_ci } else { 51258c2ecf20Sopenharmony_ci list_add_tail(&fcport->list, &vha->vp_fcports); 51268c2ecf20Sopenharmony_ci 51278c2ecf20Sopenharmony_ci } 51288c2ecf20Sopenharmony_ci if (pla) { 51298c2ecf20Sopenharmony_ci qlt_plogi_ack_link(vha, pla, fcport, 51308c2ecf20Sopenharmony_ci QLT_PLOGI_LINK_SAME_WWN); 51318c2ecf20Sopenharmony_ci pla->ref_count--; 51328c2ecf20Sopenharmony_ci } 51338c2ecf20Sopenharmony_ci } 51348c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); 51358c2ecf20Sopenharmony_ci 51368c2ecf20Sopenharmony_ci if (fcport) { 51378c2ecf20Sopenharmony_ci fcport->id_changed = 1; 51388c2ecf20Sopenharmony_ci fcport->scan_state = QLA_FCPORT_FOUND; 51398c2ecf20Sopenharmony_ci fcport->chip_reset = vha->hw->base_qpair->chip_reset; 51408c2ecf20Sopenharmony_ci memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE); 51418c2ecf20Sopenharmony_ci 51428c2ecf20Sopenharmony_ci if (pla) { 51438c2ecf20Sopenharmony_ci if (pla->iocb.u.isp24.status_subcode == ELS_PRLI) { 51448c2ecf20Sopenharmony_ci u16 wd3_lo; 51458c2ecf20Sopenharmony_ci 51468c2ecf20Sopenharmony_ci fcport->fw_login_state = DSC_LS_PRLI_PEND; 51478c2ecf20Sopenharmony_ci fcport->local = 0; 51488c2ecf20Sopenharmony_ci fcport->loop_id = 51498c2ecf20Sopenharmony_ci le16_to_cpu( 51508c2ecf20Sopenharmony_ci pla->iocb.u.isp24.nport_handle); 51518c2ecf20Sopenharmony_ci fcport->fw_login_state = DSC_LS_PRLI_PEND; 51528c2ecf20Sopenharmony_ci wd3_lo = 51538c2ecf20Sopenharmony_ci le16_to_cpu( 51548c2ecf20Sopenharmony_ci pla->iocb.u.isp24.u.prli.wd3_lo); 51558c2ecf20Sopenharmony_ci 51568c2ecf20Sopenharmony_ci if (wd3_lo & BIT_7) 51578c2ecf20Sopenharmony_ci fcport->conf_compl_supported = 1; 51588c2ecf20Sopenharmony_ci 51598c2ecf20Sopenharmony_ci if ((wd3_lo & BIT_4) == 0) 51608c2ecf20Sopenharmony_ci fcport->port_type = FCT_INITIATOR; 51618c2ecf20Sopenharmony_ci else 51628c2ecf20Sopenharmony_ci fcport->port_type = FCT_TARGET; 51638c2ecf20Sopenharmony_ci } 51648c2ecf20Sopenharmony_ci qlt_plogi_ack_unref(vha, pla); 51658c2ecf20Sopenharmony_ci } else { 51668c2ecf20Sopenharmony_ci fc_port_t *dfcp = NULL; 51678c2ecf20Sopenharmony_ci 51688c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); 51698c2ecf20Sopenharmony_ci tfcp = qla2x00_find_fcport_by_nportid(vha, 51708c2ecf20Sopenharmony_ci &e->u.new_sess.id, 1); 51718c2ecf20Sopenharmony_ci if (tfcp && (tfcp != fcport)) { 51728c2ecf20Sopenharmony_ci /* 51738c2ecf20Sopenharmony_ci * We have a conflict fcport with same NportID. 51748c2ecf20Sopenharmony_ci */ 51758c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0xffff, 51768c2ecf20Sopenharmony_ci "%s %8phC found conflict b4 add. DS %d LS %d\n", 51778c2ecf20Sopenharmony_ci __func__, tfcp->port_name, tfcp->disc_state, 51788c2ecf20Sopenharmony_ci tfcp->fw_login_state); 51798c2ecf20Sopenharmony_ci 51808c2ecf20Sopenharmony_ci switch (tfcp->disc_state) { 51818c2ecf20Sopenharmony_ci case DSC_DELETED: 51828c2ecf20Sopenharmony_ci break; 51838c2ecf20Sopenharmony_ci case DSC_DELETE_PEND: 51848c2ecf20Sopenharmony_ci fcport->login_pause = 1; 51858c2ecf20Sopenharmony_ci tfcp->conflict = fcport; 51868c2ecf20Sopenharmony_ci break; 51878c2ecf20Sopenharmony_ci default: 51888c2ecf20Sopenharmony_ci fcport->login_pause = 1; 51898c2ecf20Sopenharmony_ci tfcp->conflict = fcport; 51908c2ecf20Sopenharmony_ci dfcp = tfcp; 51918c2ecf20Sopenharmony_ci break; 51928c2ecf20Sopenharmony_ci } 51938c2ecf20Sopenharmony_ci } 51948c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); 51958c2ecf20Sopenharmony_ci if (dfcp) 51968c2ecf20Sopenharmony_ci qlt_schedule_sess_for_deletion(tfcp); 51978c2ecf20Sopenharmony_ci 51988c2ecf20Sopenharmony_ci if (N2N_TOPO(vha->hw)) { 51998c2ecf20Sopenharmony_ci fcport->flags &= ~FCF_FABRIC_DEVICE; 52008c2ecf20Sopenharmony_ci fcport->keep_nport_handle = 1; 52018c2ecf20Sopenharmony_ci if (vha->flags.nvme_enabled) { 52028c2ecf20Sopenharmony_ci fcport->fc4_type = 52038c2ecf20Sopenharmony_ci (FS_FC4TYPE_NVME | FS_FC4TYPE_FCP); 52048c2ecf20Sopenharmony_ci fcport->n2n_flag = 1; 52058c2ecf20Sopenharmony_ci } 52068c2ecf20Sopenharmony_ci fcport->fw_login_state = 0; 52078c2ecf20Sopenharmony_ci 52088c2ecf20Sopenharmony_ci schedule_delayed_work(&vha->scan.scan_work, 5); 52098c2ecf20Sopenharmony_ci } else { 52108c2ecf20Sopenharmony_ci qla24xx_fcport_handle_login(vha, fcport); 52118c2ecf20Sopenharmony_ci } 52128c2ecf20Sopenharmony_ci } 52138c2ecf20Sopenharmony_ci } 52148c2ecf20Sopenharmony_ci 52158c2ecf20Sopenharmony_ci if (free_fcport) { 52168c2ecf20Sopenharmony_ci qla2x00_free_fcport(fcport); 52178c2ecf20Sopenharmony_ci if (pla) { 52188c2ecf20Sopenharmony_ci list_del(&pla->list); 52198c2ecf20Sopenharmony_ci kmem_cache_free(qla_tgt_plogi_cachep, pla); 52208c2ecf20Sopenharmony_ci } 52218c2ecf20Sopenharmony_ci } 52228c2ecf20Sopenharmony_ci} 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_cistatic void qla_sp_retry(struct scsi_qla_host *vha, struct qla_work_evt *e) 52258c2ecf20Sopenharmony_ci{ 52268c2ecf20Sopenharmony_ci struct srb *sp = e->u.iosb.sp; 52278c2ecf20Sopenharmony_ci int rval; 52288c2ecf20Sopenharmony_ci 52298c2ecf20Sopenharmony_ci rval = qla2x00_start_sp(sp); 52308c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 52318c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2043, 52328c2ecf20Sopenharmony_ci "%s: %s: Re-issue IOCB failed (%d).\n", 52338c2ecf20Sopenharmony_ci __func__, sp->name, rval); 52348c2ecf20Sopenharmony_ci qla24xx_sp_unmap(vha, sp); 52358c2ecf20Sopenharmony_ci } 52368c2ecf20Sopenharmony_ci} 52378c2ecf20Sopenharmony_ci 52388c2ecf20Sopenharmony_civoid 52398c2ecf20Sopenharmony_ciqla2x00_do_work(struct scsi_qla_host *vha) 52408c2ecf20Sopenharmony_ci{ 52418c2ecf20Sopenharmony_ci struct qla_work_evt *e, *tmp; 52428c2ecf20Sopenharmony_ci unsigned long flags; 52438c2ecf20Sopenharmony_ci LIST_HEAD(work); 52448c2ecf20Sopenharmony_ci int rc; 52458c2ecf20Sopenharmony_ci 52468c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->work_lock, flags); 52478c2ecf20Sopenharmony_ci list_splice_init(&vha->work_list, &work); 52488c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->work_lock, flags); 52498c2ecf20Sopenharmony_ci 52508c2ecf20Sopenharmony_ci list_for_each_entry_safe(e, tmp, &work, list) { 52518c2ecf20Sopenharmony_ci rc = QLA_SUCCESS; 52528c2ecf20Sopenharmony_ci switch (e->type) { 52538c2ecf20Sopenharmony_ci case QLA_EVT_AEN: 52548c2ecf20Sopenharmony_ci fc_host_post_event(vha->host, fc_get_event_number(), 52558c2ecf20Sopenharmony_ci e->u.aen.code, e->u.aen.data); 52568c2ecf20Sopenharmony_ci break; 52578c2ecf20Sopenharmony_ci case QLA_EVT_IDC_ACK: 52588c2ecf20Sopenharmony_ci qla81xx_idc_ack(vha, e->u.idc_ack.mb); 52598c2ecf20Sopenharmony_ci break; 52608c2ecf20Sopenharmony_ci case QLA_EVT_ASYNC_LOGIN: 52618c2ecf20Sopenharmony_ci qla2x00_async_login(vha, e->u.logio.fcport, 52628c2ecf20Sopenharmony_ci e->u.logio.data); 52638c2ecf20Sopenharmony_ci break; 52648c2ecf20Sopenharmony_ci case QLA_EVT_ASYNC_LOGOUT: 52658c2ecf20Sopenharmony_ci rc = qla2x00_async_logout(vha, e->u.logio.fcport); 52668c2ecf20Sopenharmony_ci break; 52678c2ecf20Sopenharmony_ci case QLA_EVT_ASYNC_ADISC: 52688c2ecf20Sopenharmony_ci qla2x00_async_adisc(vha, e->u.logio.fcport, 52698c2ecf20Sopenharmony_ci e->u.logio.data); 52708c2ecf20Sopenharmony_ci break; 52718c2ecf20Sopenharmony_ci case QLA_EVT_UEVENT: 52728c2ecf20Sopenharmony_ci qla2x00_uevent_emit(vha, e->u.uevent.code); 52738c2ecf20Sopenharmony_ci break; 52748c2ecf20Sopenharmony_ci case QLA_EVT_AENFX: 52758c2ecf20Sopenharmony_ci qlafx00_process_aen(vha, e); 52768c2ecf20Sopenharmony_ci break; 52778c2ecf20Sopenharmony_ci case QLA_EVT_GPNID: 52788c2ecf20Sopenharmony_ci qla24xx_async_gpnid(vha, &e->u.gpnid.id); 52798c2ecf20Sopenharmony_ci break; 52808c2ecf20Sopenharmony_ci case QLA_EVT_UNMAP: 52818c2ecf20Sopenharmony_ci qla24xx_sp_unmap(vha, e->u.iosb.sp); 52828c2ecf20Sopenharmony_ci break; 52838c2ecf20Sopenharmony_ci case QLA_EVT_RELOGIN: 52848c2ecf20Sopenharmony_ci qla2x00_relogin(vha); 52858c2ecf20Sopenharmony_ci break; 52868c2ecf20Sopenharmony_ci case QLA_EVT_NEW_SESS: 52878c2ecf20Sopenharmony_ci qla24xx_create_new_sess(vha, e); 52888c2ecf20Sopenharmony_ci break; 52898c2ecf20Sopenharmony_ci case QLA_EVT_GPDB: 52908c2ecf20Sopenharmony_ci qla24xx_async_gpdb(vha, e->u.fcport.fcport, 52918c2ecf20Sopenharmony_ci e->u.fcport.opt); 52928c2ecf20Sopenharmony_ci break; 52938c2ecf20Sopenharmony_ci case QLA_EVT_PRLI: 52948c2ecf20Sopenharmony_ci qla24xx_async_prli(vha, e->u.fcport.fcport); 52958c2ecf20Sopenharmony_ci break; 52968c2ecf20Sopenharmony_ci case QLA_EVT_GPSC: 52978c2ecf20Sopenharmony_ci qla24xx_async_gpsc(vha, e->u.fcport.fcport); 52988c2ecf20Sopenharmony_ci break; 52998c2ecf20Sopenharmony_ci case QLA_EVT_GNL: 53008c2ecf20Sopenharmony_ci qla24xx_async_gnl(vha, e->u.fcport.fcport); 53018c2ecf20Sopenharmony_ci break; 53028c2ecf20Sopenharmony_ci case QLA_EVT_NACK: 53038c2ecf20Sopenharmony_ci qla24xx_do_nack_work(vha, e); 53048c2ecf20Sopenharmony_ci break; 53058c2ecf20Sopenharmony_ci case QLA_EVT_ASYNC_PRLO: 53068c2ecf20Sopenharmony_ci rc = qla2x00_async_prlo(vha, e->u.logio.fcport); 53078c2ecf20Sopenharmony_ci break; 53088c2ecf20Sopenharmony_ci case QLA_EVT_ASYNC_PRLO_DONE: 53098c2ecf20Sopenharmony_ci qla2x00_async_prlo_done(vha, e->u.logio.fcport, 53108c2ecf20Sopenharmony_ci e->u.logio.data); 53118c2ecf20Sopenharmony_ci break; 53128c2ecf20Sopenharmony_ci case QLA_EVT_GPNFT: 53138c2ecf20Sopenharmony_ci qla24xx_async_gpnft(vha, e->u.gpnft.fc4_type, 53148c2ecf20Sopenharmony_ci e->u.gpnft.sp); 53158c2ecf20Sopenharmony_ci break; 53168c2ecf20Sopenharmony_ci case QLA_EVT_GPNFT_DONE: 53178c2ecf20Sopenharmony_ci qla24xx_async_gpnft_done(vha, e->u.iosb.sp); 53188c2ecf20Sopenharmony_ci break; 53198c2ecf20Sopenharmony_ci case QLA_EVT_GNNFT_DONE: 53208c2ecf20Sopenharmony_ci qla24xx_async_gnnft_done(vha, e->u.iosb.sp); 53218c2ecf20Sopenharmony_ci break; 53228c2ecf20Sopenharmony_ci case QLA_EVT_GNNID: 53238c2ecf20Sopenharmony_ci qla24xx_async_gnnid(vha, e->u.fcport.fcport); 53248c2ecf20Sopenharmony_ci break; 53258c2ecf20Sopenharmony_ci case QLA_EVT_GFPNID: 53268c2ecf20Sopenharmony_ci qla24xx_async_gfpnid(vha, e->u.fcport.fcport); 53278c2ecf20Sopenharmony_ci break; 53288c2ecf20Sopenharmony_ci case QLA_EVT_SP_RETRY: 53298c2ecf20Sopenharmony_ci qla_sp_retry(vha, e); 53308c2ecf20Sopenharmony_ci break; 53318c2ecf20Sopenharmony_ci case QLA_EVT_IIDMA: 53328c2ecf20Sopenharmony_ci qla_do_iidma_work(vha, e->u.fcport.fcport); 53338c2ecf20Sopenharmony_ci break; 53348c2ecf20Sopenharmony_ci case QLA_EVT_ELS_PLOGI: 53358c2ecf20Sopenharmony_ci qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI, 53368c2ecf20Sopenharmony_ci e->u.fcport.fcport, false); 53378c2ecf20Sopenharmony_ci break; 53388c2ecf20Sopenharmony_ci } 53398c2ecf20Sopenharmony_ci 53408c2ecf20Sopenharmony_ci if (rc == EAGAIN) { 53418c2ecf20Sopenharmony_ci /* put 'work' at head of 'vha->work_list' */ 53428c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->work_lock, flags); 53438c2ecf20Sopenharmony_ci list_splice(&work, &vha->work_list); 53448c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->work_lock, flags); 53458c2ecf20Sopenharmony_ci break; 53468c2ecf20Sopenharmony_ci } 53478c2ecf20Sopenharmony_ci list_del_init(&e->list); 53488c2ecf20Sopenharmony_ci if (e->flags & QLA_EVT_FLAG_FREE) 53498c2ecf20Sopenharmony_ci kfree(e); 53508c2ecf20Sopenharmony_ci 53518c2ecf20Sopenharmony_ci /* For each work completed decrement vha ref count */ 53528c2ecf20Sopenharmony_ci QLA_VHA_MARK_NOT_BUSY(vha); 53538c2ecf20Sopenharmony_ci } 53548c2ecf20Sopenharmony_ci} 53558c2ecf20Sopenharmony_ci 53568c2ecf20Sopenharmony_ciint qla24xx_post_relogin_work(struct scsi_qla_host *vha) 53578c2ecf20Sopenharmony_ci{ 53588c2ecf20Sopenharmony_ci struct qla_work_evt *e; 53598c2ecf20Sopenharmony_ci 53608c2ecf20Sopenharmony_ci e = qla2x00_alloc_work(vha, QLA_EVT_RELOGIN); 53618c2ecf20Sopenharmony_ci 53628c2ecf20Sopenharmony_ci if (!e) { 53638c2ecf20Sopenharmony_ci set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 53648c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 53658c2ecf20Sopenharmony_ci } 53668c2ecf20Sopenharmony_ci 53678c2ecf20Sopenharmony_ci return qla2x00_post_work(vha, e); 53688c2ecf20Sopenharmony_ci} 53698c2ecf20Sopenharmony_ci 53708c2ecf20Sopenharmony_ci/* Relogins all the fcports of a vport 53718c2ecf20Sopenharmony_ci * Context: dpc thread 53728c2ecf20Sopenharmony_ci */ 53738c2ecf20Sopenharmony_civoid qla2x00_relogin(struct scsi_qla_host *vha) 53748c2ecf20Sopenharmony_ci{ 53758c2ecf20Sopenharmony_ci fc_port_t *fcport; 53768c2ecf20Sopenharmony_ci int status, relogin_needed = 0; 53778c2ecf20Sopenharmony_ci struct event_arg ea; 53788c2ecf20Sopenharmony_ci 53798c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) { 53808c2ecf20Sopenharmony_ci /* 53818c2ecf20Sopenharmony_ci * If the port is not ONLINE then try to login 53828c2ecf20Sopenharmony_ci * to it if we haven't run out of retries. 53838c2ecf20Sopenharmony_ci */ 53848c2ecf20Sopenharmony_ci if (atomic_read(&fcport->state) != FCS_ONLINE && 53858c2ecf20Sopenharmony_ci fcport->login_retry) { 53868c2ecf20Sopenharmony_ci if (fcport->scan_state != QLA_FCPORT_FOUND || 53878c2ecf20Sopenharmony_ci fcport->disc_state == DSC_LOGIN_COMPLETE) 53888c2ecf20Sopenharmony_ci continue; 53898c2ecf20Sopenharmony_ci 53908c2ecf20Sopenharmony_ci if (fcport->flags & (FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE) || 53918c2ecf20Sopenharmony_ci fcport->disc_state == DSC_DELETE_PEND) { 53928c2ecf20Sopenharmony_ci relogin_needed = 1; 53938c2ecf20Sopenharmony_ci } else { 53948c2ecf20Sopenharmony_ci if (vha->hw->current_topology != ISP_CFG_NL) { 53958c2ecf20Sopenharmony_ci memset(&ea, 0, sizeof(ea)); 53968c2ecf20Sopenharmony_ci ea.fcport = fcport; 53978c2ecf20Sopenharmony_ci qla24xx_handle_relogin_event(vha, &ea); 53988c2ecf20Sopenharmony_ci } else if (vha->hw->current_topology == 53998c2ecf20Sopenharmony_ci ISP_CFG_NL && 54008c2ecf20Sopenharmony_ci IS_QLA2XXX_MIDTYPE(vha->hw)) { 54018c2ecf20Sopenharmony_ci (void)qla24xx_fcport_handle_login(vha, 54028c2ecf20Sopenharmony_ci fcport); 54038c2ecf20Sopenharmony_ci } else if (vha->hw->current_topology == 54048c2ecf20Sopenharmony_ci ISP_CFG_NL) { 54058c2ecf20Sopenharmony_ci fcport->login_retry--; 54068c2ecf20Sopenharmony_ci status = 54078c2ecf20Sopenharmony_ci qla2x00_local_device_login(vha, 54088c2ecf20Sopenharmony_ci fcport); 54098c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 54108c2ecf20Sopenharmony_ci fcport->old_loop_id = 54118c2ecf20Sopenharmony_ci fcport->loop_id; 54128c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2003, 54138c2ecf20Sopenharmony_ci "Port login OK: logged in ID 0x%x.\n", 54148c2ecf20Sopenharmony_ci fcport->loop_id); 54158c2ecf20Sopenharmony_ci qla2x00_update_fcport 54168c2ecf20Sopenharmony_ci (vha, fcport); 54178c2ecf20Sopenharmony_ci } else if (status == 1) { 54188c2ecf20Sopenharmony_ci set_bit(RELOGIN_NEEDED, 54198c2ecf20Sopenharmony_ci &vha->dpc_flags); 54208c2ecf20Sopenharmony_ci /* retry the login again */ 54218c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x2007, 54228c2ecf20Sopenharmony_ci "Retrying %d login again loop_id 0x%x.\n", 54238c2ecf20Sopenharmony_ci fcport->login_retry, 54248c2ecf20Sopenharmony_ci fcport->loop_id); 54258c2ecf20Sopenharmony_ci } else { 54268c2ecf20Sopenharmony_ci fcport->login_retry = 0; 54278c2ecf20Sopenharmony_ci } 54288c2ecf20Sopenharmony_ci 54298c2ecf20Sopenharmony_ci if (fcport->login_retry == 0 && 54308c2ecf20Sopenharmony_ci status != QLA_SUCCESS) 54318c2ecf20Sopenharmony_ci qla2x00_clear_loop_id(fcport); 54328c2ecf20Sopenharmony_ci } 54338c2ecf20Sopenharmony_ci } 54348c2ecf20Sopenharmony_ci } 54358c2ecf20Sopenharmony_ci if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) 54368c2ecf20Sopenharmony_ci break; 54378c2ecf20Sopenharmony_ci } 54388c2ecf20Sopenharmony_ci 54398c2ecf20Sopenharmony_ci if (relogin_needed) 54408c2ecf20Sopenharmony_ci set_bit(RELOGIN_NEEDED, &vha->dpc_flags); 54418c2ecf20Sopenharmony_ci 54428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, vha, 0x400e, 54438c2ecf20Sopenharmony_ci "Relogin end.\n"); 54448c2ecf20Sopenharmony_ci} 54458c2ecf20Sopenharmony_ci 54468c2ecf20Sopenharmony_ci/* Schedule work on any of the dpc-workqueues */ 54478c2ecf20Sopenharmony_civoid 54488c2ecf20Sopenharmony_ciqla83xx_schedule_work(scsi_qla_host_t *base_vha, int work_code) 54498c2ecf20Sopenharmony_ci{ 54508c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 54518c2ecf20Sopenharmony_ci 54528c2ecf20Sopenharmony_ci switch (work_code) { 54538c2ecf20Sopenharmony_ci case MBA_IDC_AEN: /* 0x8200 */ 54548c2ecf20Sopenharmony_ci if (ha->dpc_lp_wq) 54558c2ecf20Sopenharmony_ci queue_work(ha->dpc_lp_wq, &ha->idc_aen); 54568c2ecf20Sopenharmony_ci break; 54578c2ecf20Sopenharmony_ci 54588c2ecf20Sopenharmony_ci case QLA83XX_NIC_CORE_RESET: /* 0x1 */ 54598c2ecf20Sopenharmony_ci if (!ha->flags.nic_core_reset_hdlr_active) { 54608c2ecf20Sopenharmony_ci if (ha->dpc_hp_wq) 54618c2ecf20Sopenharmony_ci queue_work(ha->dpc_hp_wq, &ha->nic_core_reset); 54628c2ecf20Sopenharmony_ci } else 54638c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb05e, 54648c2ecf20Sopenharmony_ci "NIC Core reset is already active. Skip " 54658c2ecf20Sopenharmony_ci "scheduling it again.\n"); 54668c2ecf20Sopenharmony_ci break; 54678c2ecf20Sopenharmony_ci case QLA83XX_IDC_STATE_HANDLER: /* 0x2 */ 54688c2ecf20Sopenharmony_ci if (ha->dpc_hp_wq) 54698c2ecf20Sopenharmony_ci queue_work(ha->dpc_hp_wq, &ha->idc_state_handler); 54708c2ecf20Sopenharmony_ci break; 54718c2ecf20Sopenharmony_ci case QLA83XX_NIC_CORE_UNRECOVERABLE: /* 0x3 */ 54728c2ecf20Sopenharmony_ci if (ha->dpc_hp_wq) 54738c2ecf20Sopenharmony_ci queue_work(ha->dpc_hp_wq, &ha->nic_core_unrecoverable); 54748c2ecf20Sopenharmony_ci break; 54758c2ecf20Sopenharmony_ci default: 54768c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xb05f, 54778c2ecf20Sopenharmony_ci "Unknown work-code=0x%x.\n", work_code); 54788c2ecf20Sopenharmony_ci } 54798c2ecf20Sopenharmony_ci 54808c2ecf20Sopenharmony_ci return; 54818c2ecf20Sopenharmony_ci} 54828c2ecf20Sopenharmony_ci 54838c2ecf20Sopenharmony_ci/* Work: Perform NIC Core Unrecoverable state handling */ 54848c2ecf20Sopenharmony_civoid 54858c2ecf20Sopenharmony_ciqla83xx_nic_core_unrecoverable_work(struct work_struct *work) 54868c2ecf20Sopenharmony_ci{ 54878c2ecf20Sopenharmony_ci struct qla_hw_data *ha = 54888c2ecf20Sopenharmony_ci container_of(work, struct qla_hw_data, nic_core_unrecoverable); 54898c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 54908c2ecf20Sopenharmony_ci uint32_t dev_state = 0; 54918c2ecf20Sopenharmony_ci 54928c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 54938c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state); 54948c2ecf20Sopenharmony_ci qla83xx_reset_ownership(base_vha); 54958c2ecf20Sopenharmony_ci if (ha->flags.nic_core_reset_owner) { 54968c2ecf20Sopenharmony_ci ha->flags.nic_core_reset_owner = 0; 54978c2ecf20Sopenharmony_ci qla83xx_wr_reg(base_vha, QLA83XX_IDC_DEV_STATE, 54988c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 54998c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0xb060, "HW State: FAILED.\n"); 55008c2ecf20Sopenharmony_ci qla83xx_schedule_work(base_vha, QLA83XX_IDC_STATE_HANDLER); 55018c2ecf20Sopenharmony_ci } 55028c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 55038c2ecf20Sopenharmony_ci} 55048c2ecf20Sopenharmony_ci 55058c2ecf20Sopenharmony_ci/* Work: Execute IDC state handler */ 55068c2ecf20Sopenharmony_civoid 55078c2ecf20Sopenharmony_ciqla83xx_idc_state_handler_work(struct work_struct *work) 55088c2ecf20Sopenharmony_ci{ 55098c2ecf20Sopenharmony_ci struct qla_hw_data *ha = 55108c2ecf20Sopenharmony_ci container_of(work, struct qla_hw_data, idc_state_handler); 55118c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 55128c2ecf20Sopenharmony_ci uint32_t dev_state = 0; 55138c2ecf20Sopenharmony_ci 55148c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 55158c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state); 55168c2ecf20Sopenharmony_ci if (dev_state == QLA8XXX_DEV_FAILED || 55178c2ecf20Sopenharmony_ci dev_state == QLA8XXX_DEV_NEED_QUIESCENT) 55188c2ecf20Sopenharmony_ci qla83xx_idc_state_handler(base_vha); 55198c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 55208c2ecf20Sopenharmony_ci} 55218c2ecf20Sopenharmony_ci 55228c2ecf20Sopenharmony_cistatic int 55238c2ecf20Sopenharmony_ciqla83xx_check_nic_core_fw_alive(scsi_qla_host_t *base_vha) 55248c2ecf20Sopenharmony_ci{ 55258c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 55268c2ecf20Sopenharmony_ci unsigned long heart_beat_wait = jiffies + (1 * HZ); 55278c2ecf20Sopenharmony_ci uint32_t heart_beat_counter1, heart_beat_counter2; 55288c2ecf20Sopenharmony_ci 55298c2ecf20Sopenharmony_ci do { 55308c2ecf20Sopenharmony_ci if (time_after(jiffies, heart_beat_wait)) { 55318c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb07c, 55328c2ecf20Sopenharmony_ci "Nic Core f/w is not alive.\n"); 55338c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 55348c2ecf20Sopenharmony_ci break; 55358c2ecf20Sopenharmony_ci } 55368c2ecf20Sopenharmony_ci 55378c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 55388c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_FW_HEARTBEAT, 55398c2ecf20Sopenharmony_ci &heart_beat_counter1); 55408c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 55418c2ecf20Sopenharmony_ci msleep(100); 55428c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 55438c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_FW_HEARTBEAT, 55448c2ecf20Sopenharmony_ci &heart_beat_counter2); 55458c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 55468c2ecf20Sopenharmony_ci } while (heart_beat_counter1 == heart_beat_counter2); 55478c2ecf20Sopenharmony_ci 55488c2ecf20Sopenharmony_ci return rval; 55498c2ecf20Sopenharmony_ci} 55508c2ecf20Sopenharmony_ci 55518c2ecf20Sopenharmony_ci/* Work: Perform NIC Core Reset handling */ 55528c2ecf20Sopenharmony_civoid 55538c2ecf20Sopenharmony_ciqla83xx_nic_core_reset_work(struct work_struct *work) 55548c2ecf20Sopenharmony_ci{ 55558c2ecf20Sopenharmony_ci struct qla_hw_data *ha = 55568c2ecf20Sopenharmony_ci container_of(work, struct qla_hw_data, nic_core_reset); 55578c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 55588c2ecf20Sopenharmony_ci uint32_t dev_state = 0; 55598c2ecf20Sopenharmony_ci 55608c2ecf20Sopenharmony_ci if (IS_QLA2031(ha)) { 55618c2ecf20Sopenharmony_ci if (qla2xxx_mctp_dump(base_vha) != QLA_SUCCESS) 55628c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xb081, 55638c2ecf20Sopenharmony_ci "Failed to dump mctp\n"); 55648c2ecf20Sopenharmony_ci return; 55658c2ecf20Sopenharmony_ci } 55668c2ecf20Sopenharmony_ci 55678c2ecf20Sopenharmony_ci if (!ha->flags.nic_core_reset_hdlr_active) { 55688c2ecf20Sopenharmony_ci if (qla83xx_check_nic_core_fw_alive(base_vha) == QLA_SUCCESS) { 55698c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 55708c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, 55718c2ecf20Sopenharmony_ci &dev_state); 55728c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 55738c2ecf20Sopenharmony_ci if (dev_state != QLA8XXX_DEV_NEED_RESET) { 55748c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb07a, 55758c2ecf20Sopenharmony_ci "Nic Core f/w is alive.\n"); 55768c2ecf20Sopenharmony_ci return; 55778c2ecf20Sopenharmony_ci } 55788c2ecf20Sopenharmony_ci } 55798c2ecf20Sopenharmony_ci 55808c2ecf20Sopenharmony_ci ha->flags.nic_core_reset_hdlr_active = 1; 55818c2ecf20Sopenharmony_ci if (qla83xx_nic_core_reset(base_vha)) { 55828c2ecf20Sopenharmony_ci /* NIC Core reset failed. */ 55838c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb061, 55848c2ecf20Sopenharmony_ci "NIC Core reset failed.\n"); 55858c2ecf20Sopenharmony_ci } 55868c2ecf20Sopenharmony_ci ha->flags.nic_core_reset_hdlr_active = 0; 55878c2ecf20Sopenharmony_ci } 55888c2ecf20Sopenharmony_ci} 55898c2ecf20Sopenharmony_ci 55908c2ecf20Sopenharmony_ci/* Work: Handle 8200 IDC aens */ 55918c2ecf20Sopenharmony_civoid 55928c2ecf20Sopenharmony_ciqla83xx_service_idc_aen(struct work_struct *work) 55938c2ecf20Sopenharmony_ci{ 55948c2ecf20Sopenharmony_ci struct qla_hw_data *ha = 55958c2ecf20Sopenharmony_ci container_of(work, struct qla_hw_data, idc_aen); 55968c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 55978c2ecf20Sopenharmony_ci uint32_t dev_state, idc_control; 55988c2ecf20Sopenharmony_ci 55998c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 56008c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state); 56018c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_IDC_CONTROL, &idc_control); 56028c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 56038c2ecf20Sopenharmony_ci if (dev_state == QLA8XXX_DEV_NEED_RESET) { 56048c2ecf20Sopenharmony_ci if (idc_control & QLA83XX_IDC_GRACEFUL_RESET) { 56058c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb062, 56068c2ecf20Sopenharmony_ci "Application requested NIC Core Reset.\n"); 56078c2ecf20Sopenharmony_ci qla83xx_schedule_work(base_vha, QLA83XX_NIC_CORE_RESET); 56088c2ecf20Sopenharmony_ci } else if (qla83xx_check_nic_core_fw_alive(base_vha) == 56098c2ecf20Sopenharmony_ci QLA_SUCCESS) { 56108c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb07b, 56118c2ecf20Sopenharmony_ci "Other protocol driver requested NIC Core Reset.\n"); 56128c2ecf20Sopenharmony_ci qla83xx_schedule_work(base_vha, QLA83XX_NIC_CORE_RESET); 56138c2ecf20Sopenharmony_ci } 56148c2ecf20Sopenharmony_ci } else if (dev_state == QLA8XXX_DEV_FAILED || 56158c2ecf20Sopenharmony_ci dev_state == QLA8XXX_DEV_NEED_QUIESCENT) { 56168c2ecf20Sopenharmony_ci qla83xx_schedule_work(base_vha, QLA83XX_IDC_STATE_HANDLER); 56178c2ecf20Sopenharmony_ci } 56188c2ecf20Sopenharmony_ci} 56198c2ecf20Sopenharmony_ci 56208c2ecf20Sopenharmony_cistatic void 56218c2ecf20Sopenharmony_ciqla83xx_wait_logic(void) 56228c2ecf20Sopenharmony_ci{ 56238c2ecf20Sopenharmony_ci int i; 56248c2ecf20Sopenharmony_ci 56258c2ecf20Sopenharmony_ci /* Yield CPU */ 56268c2ecf20Sopenharmony_ci if (!in_interrupt()) { 56278c2ecf20Sopenharmony_ci /* 56288c2ecf20Sopenharmony_ci * Wait about 200ms before retrying again. 56298c2ecf20Sopenharmony_ci * This controls the number of retries for single 56308c2ecf20Sopenharmony_ci * lock operation. 56318c2ecf20Sopenharmony_ci */ 56328c2ecf20Sopenharmony_ci msleep(100); 56338c2ecf20Sopenharmony_ci schedule(); 56348c2ecf20Sopenharmony_ci } else { 56358c2ecf20Sopenharmony_ci for (i = 0; i < 20; i++) 56368c2ecf20Sopenharmony_ci cpu_relax(); /* This a nop instr on i386 */ 56378c2ecf20Sopenharmony_ci } 56388c2ecf20Sopenharmony_ci} 56398c2ecf20Sopenharmony_ci 56408c2ecf20Sopenharmony_cistatic int 56418c2ecf20Sopenharmony_ciqla83xx_force_lock_recovery(scsi_qla_host_t *base_vha) 56428c2ecf20Sopenharmony_ci{ 56438c2ecf20Sopenharmony_ci int rval; 56448c2ecf20Sopenharmony_ci uint32_t data; 56458c2ecf20Sopenharmony_ci uint32_t idc_lck_rcvry_stage_mask = 0x3; 56468c2ecf20Sopenharmony_ci uint32_t idc_lck_rcvry_owner_mask = 0x3c; 56478c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 56488c2ecf20Sopenharmony_ci 56498c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb086, 56508c2ecf20Sopenharmony_ci "Trying force recovery of the IDC lock.\n"); 56518c2ecf20Sopenharmony_ci 56528c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY, &data); 56538c2ecf20Sopenharmony_ci if (rval) 56548c2ecf20Sopenharmony_ci return rval; 56558c2ecf20Sopenharmony_ci 56568c2ecf20Sopenharmony_ci if ((data & idc_lck_rcvry_stage_mask) > 0) { 56578c2ecf20Sopenharmony_ci return QLA_SUCCESS; 56588c2ecf20Sopenharmony_ci } else { 56598c2ecf20Sopenharmony_ci data = (IDC_LOCK_RECOVERY_STAGE1) | (ha->portnum << 2); 56608c2ecf20Sopenharmony_ci rval = qla83xx_wr_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY, 56618c2ecf20Sopenharmony_ci data); 56628c2ecf20Sopenharmony_ci if (rval) 56638c2ecf20Sopenharmony_ci return rval; 56648c2ecf20Sopenharmony_ci 56658c2ecf20Sopenharmony_ci msleep(200); 56668c2ecf20Sopenharmony_ci 56678c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY, 56688c2ecf20Sopenharmony_ci &data); 56698c2ecf20Sopenharmony_ci if (rval) 56708c2ecf20Sopenharmony_ci return rval; 56718c2ecf20Sopenharmony_ci 56728c2ecf20Sopenharmony_ci if (((data & idc_lck_rcvry_owner_mask) >> 2) == ha->portnum) { 56738c2ecf20Sopenharmony_ci data &= (IDC_LOCK_RECOVERY_STAGE2 | 56748c2ecf20Sopenharmony_ci ~(idc_lck_rcvry_stage_mask)); 56758c2ecf20Sopenharmony_ci rval = qla83xx_wr_reg(base_vha, 56768c2ecf20Sopenharmony_ci QLA83XX_IDC_LOCK_RECOVERY, data); 56778c2ecf20Sopenharmony_ci if (rval) 56788c2ecf20Sopenharmony_ci return rval; 56798c2ecf20Sopenharmony_ci 56808c2ecf20Sopenharmony_ci /* Forcefully perform IDC UnLock */ 56818c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_UNLOCK, 56828c2ecf20Sopenharmony_ci &data); 56838c2ecf20Sopenharmony_ci if (rval) 56848c2ecf20Sopenharmony_ci return rval; 56858c2ecf20Sopenharmony_ci /* Clear lock-id by setting 0xff */ 56868c2ecf20Sopenharmony_ci rval = qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID, 56878c2ecf20Sopenharmony_ci 0xff); 56888c2ecf20Sopenharmony_ci if (rval) 56898c2ecf20Sopenharmony_ci return rval; 56908c2ecf20Sopenharmony_ci /* Clear lock-recovery by setting 0x0 */ 56918c2ecf20Sopenharmony_ci rval = qla83xx_wr_reg(base_vha, 56928c2ecf20Sopenharmony_ci QLA83XX_IDC_LOCK_RECOVERY, 0x0); 56938c2ecf20Sopenharmony_ci if (rval) 56948c2ecf20Sopenharmony_ci return rval; 56958c2ecf20Sopenharmony_ci } else 56968c2ecf20Sopenharmony_ci return QLA_SUCCESS; 56978c2ecf20Sopenharmony_ci } 56988c2ecf20Sopenharmony_ci 56998c2ecf20Sopenharmony_ci return rval; 57008c2ecf20Sopenharmony_ci} 57018c2ecf20Sopenharmony_ci 57028c2ecf20Sopenharmony_cistatic int 57038c2ecf20Sopenharmony_ciqla83xx_idc_lock_recovery(scsi_qla_host_t *base_vha) 57048c2ecf20Sopenharmony_ci{ 57058c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 57068c2ecf20Sopenharmony_ci uint32_t o_drv_lockid, n_drv_lockid; 57078c2ecf20Sopenharmony_ci unsigned long lock_recovery_timeout; 57088c2ecf20Sopenharmony_ci 57098c2ecf20Sopenharmony_ci lock_recovery_timeout = jiffies + QLA83XX_MAX_LOCK_RECOVERY_WAIT; 57108c2ecf20Sopenharmony_ciretry_lockid: 57118c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, &o_drv_lockid); 57128c2ecf20Sopenharmony_ci if (rval) 57138c2ecf20Sopenharmony_ci goto exit; 57148c2ecf20Sopenharmony_ci 57158c2ecf20Sopenharmony_ci /* MAX wait time before forcing IDC Lock recovery = 2 secs */ 57168c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, lock_recovery_timeout)) { 57178c2ecf20Sopenharmony_ci if (qla83xx_force_lock_recovery(base_vha) == QLA_SUCCESS) 57188c2ecf20Sopenharmony_ci return QLA_SUCCESS; 57198c2ecf20Sopenharmony_ci else 57208c2ecf20Sopenharmony_ci return QLA_FUNCTION_FAILED; 57218c2ecf20Sopenharmony_ci } 57228c2ecf20Sopenharmony_ci 57238c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, &n_drv_lockid); 57248c2ecf20Sopenharmony_ci if (rval) 57258c2ecf20Sopenharmony_ci goto exit; 57268c2ecf20Sopenharmony_ci 57278c2ecf20Sopenharmony_ci if (o_drv_lockid == n_drv_lockid) { 57288c2ecf20Sopenharmony_ci qla83xx_wait_logic(); 57298c2ecf20Sopenharmony_ci goto retry_lockid; 57308c2ecf20Sopenharmony_ci } else 57318c2ecf20Sopenharmony_ci return QLA_SUCCESS; 57328c2ecf20Sopenharmony_ci 57338c2ecf20Sopenharmony_ciexit: 57348c2ecf20Sopenharmony_ci return rval; 57358c2ecf20Sopenharmony_ci} 57368c2ecf20Sopenharmony_ci 57378c2ecf20Sopenharmony_civoid 57388c2ecf20Sopenharmony_ciqla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id) 57398c2ecf20Sopenharmony_ci{ 57408c2ecf20Sopenharmony_ci uint32_t data; 57418c2ecf20Sopenharmony_ci uint32_t lock_owner; 57428c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 57438c2ecf20Sopenharmony_ci 57448c2ecf20Sopenharmony_ci /* IDC-lock implementation using driver-lock/lock-id remote registers */ 57458c2ecf20Sopenharmony_ciretry_lock: 57468c2ecf20Sopenharmony_ci if (qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCK, &data) 57478c2ecf20Sopenharmony_ci == QLA_SUCCESS) { 57488c2ecf20Sopenharmony_ci if (data) { 57498c2ecf20Sopenharmony_ci /* Setting lock-id to our function-number */ 57508c2ecf20Sopenharmony_ci qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID, 57518c2ecf20Sopenharmony_ci ha->portnum); 57528c2ecf20Sopenharmony_ci } else { 57538c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, 57548c2ecf20Sopenharmony_ci &lock_owner); 57558c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb063, 57568c2ecf20Sopenharmony_ci "Failed to acquire IDC lock, acquired by %d, " 57578c2ecf20Sopenharmony_ci "retrying...\n", lock_owner); 57588c2ecf20Sopenharmony_ci 57598c2ecf20Sopenharmony_ci /* Retry/Perform IDC-Lock recovery */ 57608c2ecf20Sopenharmony_ci if (qla83xx_idc_lock_recovery(base_vha) 57618c2ecf20Sopenharmony_ci == QLA_SUCCESS) { 57628c2ecf20Sopenharmony_ci qla83xx_wait_logic(); 57638c2ecf20Sopenharmony_ci goto retry_lock; 57648c2ecf20Sopenharmony_ci } else 57658c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xb075, 57668c2ecf20Sopenharmony_ci "IDC Lock recovery FAILED.\n"); 57678c2ecf20Sopenharmony_ci } 57688c2ecf20Sopenharmony_ci 57698c2ecf20Sopenharmony_ci } 57708c2ecf20Sopenharmony_ci 57718c2ecf20Sopenharmony_ci return; 57728c2ecf20Sopenharmony_ci} 57738c2ecf20Sopenharmony_ci 57748c2ecf20Sopenharmony_cistatic bool 57758c2ecf20Sopenharmony_ciqla25xx_rdp_rsp_reduce_size(struct scsi_qla_host *vha, 57768c2ecf20Sopenharmony_ci struct purex_entry_24xx *purex) 57778c2ecf20Sopenharmony_ci{ 57788c2ecf20Sopenharmony_ci char fwstr[16]; 57798c2ecf20Sopenharmony_ci u32 sid = purex->s_id[2] << 16 | purex->s_id[1] << 8 | purex->s_id[0]; 57808c2ecf20Sopenharmony_ci struct port_database_24xx *pdb; 57818c2ecf20Sopenharmony_ci 57828c2ecf20Sopenharmony_ci /* Domain Controller is always logged-out. */ 57838c2ecf20Sopenharmony_ci /* if RDP request is not from Domain Controller: */ 57848c2ecf20Sopenharmony_ci if (sid != 0xfffc01) 57858c2ecf20Sopenharmony_ci return false; 57868c2ecf20Sopenharmony_ci 57878c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0181, "%s: s_id=%#x\n", __func__, sid); 57888c2ecf20Sopenharmony_ci 57898c2ecf20Sopenharmony_ci pdb = kzalloc(sizeof(*pdb), GFP_KERNEL); 57908c2ecf20Sopenharmony_ci if (!pdb) { 57918c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0181, 57928c2ecf20Sopenharmony_ci "%s: Failed allocate pdb\n", __func__); 57938c2ecf20Sopenharmony_ci } else if (qla24xx_get_port_database(vha, 57948c2ecf20Sopenharmony_ci le16_to_cpu(purex->nport_handle), pdb)) { 57958c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0181, 57968c2ecf20Sopenharmony_ci "%s: Failed get pdb sid=%x\n", __func__, sid); 57978c2ecf20Sopenharmony_ci } else if (pdb->current_login_state != PDS_PLOGI_COMPLETE && 57988c2ecf20Sopenharmony_ci pdb->current_login_state != PDS_PRLI_COMPLETE) { 57998c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0181, 58008c2ecf20Sopenharmony_ci "%s: Port not logged in sid=%#x\n", __func__, sid); 58018c2ecf20Sopenharmony_ci } else { 58028c2ecf20Sopenharmony_ci /* RDP request is from logged in port */ 58038c2ecf20Sopenharmony_ci kfree(pdb); 58048c2ecf20Sopenharmony_ci return false; 58058c2ecf20Sopenharmony_ci } 58068c2ecf20Sopenharmony_ci kfree(pdb); 58078c2ecf20Sopenharmony_ci 58088c2ecf20Sopenharmony_ci vha->hw->isp_ops->fw_version_str(vha, fwstr, sizeof(fwstr)); 58098c2ecf20Sopenharmony_ci fwstr[strcspn(fwstr, " ")] = 0; 58108c2ecf20Sopenharmony_ci /* if FW version allows RDP response length upto 2048 bytes: */ 58118c2ecf20Sopenharmony_ci if (strcmp(fwstr, "8.09.00") > 0 || strcmp(fwstr, "8.05.65") == 0) 58128c2ecf20Sopenharmony_ci return false; 58138c2ecf20Sopenharmony_ci 58148c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0181, "%s: fw=%s\n", __func__, fwstr); 58158c2ecf20Sopenharmony_ci 58168c2ecf20Sopenharmony_ci /* RDP response length is to be reduced to maximum 256 bytes */ 58178c2ecf20Sopenharmony_ci return true; 58188c2ecf20Sopenharmony_ci} 58198c2ecf20Sopenharmony_ci 58208c2ecf20Sopenharmony_ci/* 58218c2ecf20Sopenharmony_ci * Function Name: qla24xx_process_purex_iocb 58228c2ecf20Sopenharmony_ci * 58238c2ecf20Sopenharmony_ci * Description: 58248c2ecf20Sopenharmony_ci * Prepare a RDP response and send to Fabric switch 58258c2ecf20Sopenharmony_ci * 58268c2ecf20Sopenharmony_ci * PARAMETERS: 58278c2ecf20Sopenharmony_ci * vha: SCSI qla host 58288c2ecf20Sopenharmony_ci * purex: RDP request received by HBA 58298c2ecf20Sopenharmony_ci */ 58308c2ecf20Sopenharmony_civoid qla24xx_process_purex_rdp(struct scsi_qla_host *vha, 58318c2ecf20Sopenharmony_ci struct purex_item *item) 58328c2ecf20Sopenharmony_ci{ 58338c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 58348c2ecf20Sopenharmony_ci struct purex_entry_24xx *purex = 58358c2ecf20Sopenharmony_ci (struct purex_entry_24xx *)&item->iocb; 58368c2ecf20Sopenharmony_ci dma_addr_t rsp_els_dma; 58378c2ecf20Sopenharmony_ci dma_addr_t rsp_payload_dma; 58388c2ecf20Sopenharmony_ci dma_addr_t stat_dma; 58398c2ecf20Sopenharmony_ci dma_addr_t sfp_dma; 58408c2ecf20Sopenharmony_ci struct els_entry_24xx *rsp_els = NULL; 58418c2ecf20Sopenharmony_ci struct rdp_rsp_payload *rsp_payload = NULL; 58428c2ecf20Sopenharmony_ci struct link_statistics *stat = NULL; 58438c2ecf20Sopenharmony_ci uint8_t *sfp = NULL; 58448c2ecf20Sopenharmony_ci uint16_t sfp_flags = 0; 58458c2ecf20Sopenharmony_ci uint rsp_payload_length = sizeof(*rsp_payload); 58468c2ecf20Sopenharmony_ci int rval; 58478c2ecf20Sopenharmony_ci 58488c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0180, 58498c2ecf20Sopenharmony_ci "%s: Enter\n", __func__); 58508c2ecf20Sopenharmony_ci 58518c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0181, 58528c2ecf20Sopenharmony_ci "-------- ELS REQ -------\n"); 58538c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0182, 58548c2ecf20Sopenharmony_ci purex, sizeof(*purex)); 58558c2ecf20Sopenharmony_ci 58568c2ecf20Sopenharmony_ci if (qla25xx_rdp_rsp_reduce_size(vha, purex)) { 58578c2ecf20Sopenharmony_ci rsp_payload_length = 58588c2ecf20Sopenharmony_ci offsetof(typeof(*rsp_payload), optical_elmt_desc); 58598c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0181, 58608c2ecf20Sopenharmony_ci "Reducing RSP payload length to %u bytes...\n", 58618c2ecf20Sopenharmony_ci rsp_payload_length); 58628c2ecf20Sopenharmony_ci } 58638c2ecf20Sopenharmony_ci 58648c2ecf20Sopenharmony_ci rsp_els = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_els), 58658c2ecf20Sopenharmony_ci &rsp_els_dma, GFP_KERNEL); 58668c2ecf20Sopenharmony_ci if (!rsp_els) { 58678c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x0183, 58688c2ecf20Sopenharmony_ci "Failed allocate dma buffer ELS RSP.\n"); 58698c2ecf20Sopenharmony_ci goto dealloc; 58708c2ecf20Sopenharmony_ci } 58718c2ecf20Sopenharmony_ci 58728c2ecf20Sopenharmony_ci rsp_payload = dma_alloc_coherent(&ha->pdev->dev, sizeof(*rsp_payload), 58738c2ecf20Sopenharmony_ci &rsp_payload_dma, GFP_KERNEL); 58748c2ecf20Sopenharmony_ci if (!rsp_payload) { 58758c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x0184, 58768c2ecf20Sopenharmony_ci "Failed allocate dma buffer ELS RSP payload.\n"); 58778c2ecf20Sopenharmony_ci goto dealloc; 58788c2ecf20Sopenharmony_ci } 58798c2ecf20Sopenharmony_ci 58808c2ecf20Sopenharmony_ci sfp = dma_alloc_coherent(&ha->pdev->dev, SFP_RTDI_LEN, 58818c2ecf20Sopenharmony_ci &sfp_dma, GFP_KERNEL); 58828c2ecf20Sopenharmony_ci 58838c2ecf20Sopenharmony_ci stat = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stat), 58848c2ecf20Sopenharmony_ci &stat_dma, GFP_KERNEL); 58858c2ecf20Sopenharmony_ci 58868c2ecf20Sopenharmony_ci /* Prepare Response IOCB */ 58878c2ecf20Sopenharmony_ci rsp_els->entry_type = ELS_IOCB_TYPE; 58888c2ecf20Sopenharmony_ci rsp_els->entry_count = 1; 58898c2ecf20Sopenharmony_ci rsp_els->sys_define = 0; 58908c2ecf20Sopenharmony_ci rsp_els->entry_status = 0; 58918c2ecf20Sopenharmony_ci rsp_els->handle = 0; 58928c2ecf20Sopenharmony_ci rsp_els->nport_handle = purex->nport_handle; 58938c2ecf20Sopenharmony_ci rsp_els->tx_dsd_count = cpu_to_le16(1); 58948c2ecf20Sopenharmony_ci rsp_els->vp_index = purex->vp_idx; 58958c2ecf20Sopenharmony_ci rsp_els->sof_type = EST_SOFI3; 58968c2ecf20Sopenharmony_ci rsp_els->rx_xchg_address = purex->rx_xchg_addr; 58978c2ecf20Sopenharmony_ci rsp_els->rx_dsd_count = 0; 58988c2ecf20Sopenharmony_ci rsp_els->opcode = purex->els_frame_payload[0]; 58998c2ecf20Sopenharmony_ci 59008c2ecf20Sopenharmony_ci rsp_els->d_id[0] = purex->s_id[0]; 59018c2ecf20Sopenharmony_ci rsp_els->d_id[1] = purex->s_id[1]; 59028c2ecf20Sopenharmony_ci rsp_els->d_id[2] = purex->s_id[2]; 59038c2ecf20Sopenharmony_ci 59048c2ecf20Sopenharmony_ci rsp_els->control_flags = cpu_to_le16(EPD_ELS_ACC); 59058c2ecf20Sopenharmony_ci rsp_els->rx_byte_count = 0; 59068c2ecf20Sopenharmony_ci rsp_els->tx_byte_count = cpu_to_le32(rsp_payload_length); 59078c2ecf20Sopenharmony_ci 59088c2ecf20Sopenharmony_ci put_unaligned_le64(rsp_payload_dma, &rsp_els->tx_address); 59098c2ecf20Sopenharmony_ci rsp_els->tx_len = rsp_els->tx_byte_count; 59108c2ecf20Sopenharmony_ci 59118c2ecf20Sopenharmony_ci rsp_els->rx_address = 0; 59128c2ecf20Sopenharmony_ci rsp_els->rx_len = 0; 59138c2ecf20Sopenharmony_ci 59148c2ecf20Sopenharmony_ci /* Prepare Response Payload */ 59158c2ecf20Sopenharmony_ci rsp_payload->hdr.cmd = cpu_to_be32(0x2 << 24); /* LS_ACC */ 59168c2ecf20Sopenharmony_ci rsp_payload->hdr.len = cpu_to_be32(le32_to_cpu(rsp_els->tx_byte_count) - 59178c2ecf20Sopenharmony_ci sizeof(rsp_payload->hdr)); 59188c2ecf20Sopenharmony_ci 59198c2ecf20Sopenharmony_ci /* Link service Request Info Descriptor */ 59208c2ecf20Sopenharmony_ci rsp_payload->ls_req_info_desc.desc_tag = cpu_to_be32(0x1); 59218c2ecf20Sopenharmony_ci rsp_payload->ls_req_info_desc.desc_len = 59228c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc)); 59238c2ecf20Sopenharmony_ci rsp_payload->ls_req_info_desc.req_payload_word_0 = 59248c2ecf20Sopenharmony_ci cpu_to_be32p((uint32_t *)purex->els_frame_payload); 59258c2ecf20Sopenharmony_ci 59268c2ecf20Sopenharmony_ci /* Link service Request Info Descriptor 2 */ 59278c2ecf20Sopenharmony_ci rsp_payload->ls_req_info_desc2.desc_tag = cpu_to_be32(0x1); 59288c2ecf20Sopenharmony_ci rsp_payload->ls_req_info_desc2.desc_len = 59298c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_req_info_desc2)); 59308c2ecf20Sopenharmony_ci rsp_payload->ls_req_info_desc2.req_payload_word_0 = 59318c2ecf20Sopenharmony_ci cpu_to_be32p((uint32_t *)purex->els_frame_payload); 59328c2ecf20Sopenharmony_ci 59338c2ecf20Sopenharmony_ci 59348c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.desc_tag = cpu_to_be32(0x10000); 59358c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.desc_len = 59368c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->sfp_diag_desc)); 59378c2ecf20Sopenharmony_ci 59388c2ecf20Sopenharmony_ci if (sfp) { 59398c2ecf20Sopenharmony_ci /* SFP Flags */ 59408c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 59418c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x7, 2, 0); 59428c2ecf20Sopenharmony_ci if (!rval) { 59438c2ecf20Sopenharmony_ci /* SFP Flags bits 3-0: Port Tx Laser Type */ 59448c2ecf20Sopenharmony_ci if (sfp[0] & BIT_2 || sfp[1] & (BIT_6|BIT_5)) 59458c2ecf20Sopenharmony_ci sfp_flags |= BIT_0; /* short wave */ 59468c2ecf20Sopenharmony_ci else if (sfp[0] & BIT_1) 59478c2ecf20Sopenharmony_ci sfp_flags |= BIT_1; /* long wave 1310nm */ 59488c2ecf20Sopenharmony_ci else if (sfp[1] & BIT_4) 59498c2ecf20Sopenharmony_ci sfp_flags |= BIT_1|BIT_0; /* long wave 1550nm */ 59508c2ecf20Sopenharmony_ci } 59518c2ecf20Sopenharmony_ci 59528c2ecf20Sopenharmony_ci /* SFP Type */ 59538c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 59548c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 0x0, 1, 0); 59558c2ecf20Sopenharmony_ci if (!rval) { 59568c2ecf20Sopenharmony_ci sfp_flags |= BIT_4; /* optical */ 59578c2ecf20Sopenharmony_ci if (sfp[0] == 0x3) 59588c2ecf20Sopenharmony_ci sfp_flags |= BIT_6; /* sfp+ */ 59598c2ecf20Sopenharmony_ci } 59608c2ecf20Sopenharmony_ci 59618c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.sfp_flags = cpu_to_be16(sfp_flags); 59628c2ecf20Sopenharmony_ci 59638c2ecf20Sopenharmony_ci /* SFP Diagnostics */ 59648c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 59658c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0x60, 10, 0); 59668c2ecf20Sopenharmony_ci if (!rval) { 59678c2ecf20Sopenharmony_ci __be16 *trx = (__force __be16 *)sfp; /* already be16 */ 59688c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.temperature = trx[0]; 59698c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.vcc = trx[1]; 59708c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.tx_bias = trx[2]; 59718c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.tx_power = trx[3]; 59728c2ecf20Sopenharmony_ci rsp_payload->sfp_diag_desc.rx_power = trx[4]; 59738c2ecf20Sopenharmony_ci } 59748c2ecf20Sopenharmony_ci } 59758c2ecf20Sopenharmony_ci 59768c2ecf20Sopenharmony_ci /* Port Speed Descriptor */ 59778c2ecf20Sopenharmony_ci rsp_payload->port_speed_desc.desc_tag = cpu_to_be32(0x10001); 59788c2ecf20Sopenharmony_ci rsp_payload->port_speed_desc.desc_len = 59798c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_speed_desc)); 59808c2ecf20Sopenharmony_ci rsp_payload->port_speed_desc.speed_capab = cpu_to_be16( 59818c2ecf20Sopenharmony_ci qla25xx_fdmi_port_speed_capability(ha)); 59828c2ecf20Sopenharmony_ci rsp_payload->port_speed_desc.operating_speed = cpu_to_be16( 59838c2ecf20Sopenharmony_ci qla25xx_fdmi_port_speed_currently(ha)); 59848c2ecf20Sopenharmony_ci 59858c2ecf20Sopenharmony_ci /* Link Error Status Descriptor */ 59868c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.desc_tag = cpu_to_be32(0x10002); 59878c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.desc_len = 59888c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->ls_err_desc)); 59898c2ecf20Sopenharmony_ci 59908c2ecf20Sopenharmony_ci if (stat) { 59918c2ecf20Sopenharmony_ci rval = qla24xx_get_isp_stats(vha, stat, stat_dma, 0); 59928c2ecf20Sopenharmony_ci if (!rval) { 59938c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.link_fail_cnt = 59948c2ecf20Sopenharmony_ci cpu_to_be32(le32_to_cpu(stat->link_fail_cnt)); 59958c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.loss_sync_cnt = 59968c2ecf20Sopenharmony_ci cpu_to_be32(le32_to_cpu(stat->loss_sync_cnt)); 59978c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.loss_sig_cnt = 59988c2ecf20Sopenharmony_ci cpu_to_be32(le32_to_cpu(stat->loss_sig_cnt)); 59998c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.prim_seq_err_cnt = 60008c2ecf20Sopenharmony_ci cpu_to_be32(le32_to_cpu(stat->prim_seq_err_cnt)); 60018c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.inval_xmit_word_cnt = 60028c2ecf20Sopenharmony_ci cpu_to_be32(le32_to_cpu(stat->inval_xmit_word_cnt)); 60038c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.inval_crc_cnt = 60048c2ecf20Sopenharmony_ci cpu_to_be32(le32_to_cpu(stat->inval_crc_cnt)); 60058c2ecf20Sopenharmony_ci rsp_payload->ls_err_desc.pn_port_phy_type |= BIT_6; 60068c2ecf20Sopenharmony_ci } 60078c2ecf20Sopenharmony_ci } 60088c2ecf20Sopenharmony_ci 60098c2ecf20Sopenharmony_ci /* Portname Descriptor */ 60108c2ecf20Sopenharmony_ci rsp_payload->port_name_diag_desc.desc_tag = cpu_to_be32(0x10003); 60118c2ecf20Sopenharmony_ci rsp_payload->port_name_diag_desc.desc_len = 60128c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_diag_desc)); 60138c2ecf20Sopenharmony_ci memcpy(rsp_payload->port_name_diag_desc.WWNN, 60148c2ecf20Sopenharmony_ci vha->node_name, 60158c2ecf20Sopenharmony_ci sizeof(rsp_payload->port_name_diag_desc.WWNN)); 60168c2ecf20Sopenharmony_ci memcpy(rsp_payload->port_name_diag_desc.WWPN, 60178c2ecf20Sopenharmony_ci vha->port_name, 60188c2ecf20Sopenharmony_ci sizeof(rsp_payload->port_name_diag_desc.WWPN)); 60198c2ecf20Sopenharmony_ci 60208c2ecf20Sopenharmony_ci /* F-Port Portname Descriptor */ 60218c2ecf20Sopenharmony_ci rsp_payload->port_name_direct_desc.desc_tag = cpu_to_be32(0x10003); 60228c2ecf20Sopenharmony_ci rsp_payload->port_name_direct_desc.desc_len = 60238c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->port_name_direct_desc)); 60248c2ecf20Sopenharmony_ci memcpy(rsp_payload->port_name_direct_desc.WWNN, 60258c2ecf20Sopenharmony_ci vha->fabric_node_name, 60268c2ecf20Sopenharmony_ci sizeof(rsp_payload->port_name_direct_desc.WWNN)); 60278c2ecf20Sopenharmony_ci memcpy(rsp_payload->port_name_direct_desc.WWPN, 60288c2ecf20Sopenharmony_ci vha->fabric_port_name, 60298c2ecf20Sopenharmony_ci sizeof(rsp_payload->port_name_direct_desc.WWPN)); 60308c2ecf20Sopenharmony_ci 60318c2ecf20Sopenharmony_ci /* Bufer Credit Descriptor */ 60328c2ecf20Sopenharmony_ci rsp_payload->buffer_credit_desc.desc_tag = cpu_to_be32(0x10006); 60338c2ecf20Sopenharmony_ci rsp_payload->buffer_credit_desc.desc_len = 60348c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->buffer_credit_desc)); 60358c2ecf20Sopenharmony_ci rsp_payload->buffer_credit_desc.fcport_b2b = 0; 60368c2ecf20Sopenharmony_ci rsp_payload->buffer_credit_desc.attached_fcport_b2b = cpu_to_be32(0); 60378c2ecf20Sopenharmony_ci rsp_payload->buffer_credit_desc.fcport_rtt = cpu_to_be32(0); 60388c2ecf20Sopenharmony_ci 60398c2ecf20Sopenharmony_ci if (ha->flags.plogi_template_valid) { 60408c2ecf20Sopenharmony_ci uint32_t tmp = 60418c2ecf20Sopenharmony_ci be16_to_cpu(ha->plogi_els_payld.fl_csp.sp_bb_cred); 60428c2ecf20Sopenharmony_ci rsp_payload->buffer_credit_desc.fcport_b2b = cpu_to_be32(tmp); 60438c2ecf20Sopenharmony_ci } 60448c2ecf20Sopenharmony_ci 60458c2ecf20Sopenharmony_ci if (rsp_payload_length < sizeof(*rsp_payload)) 60468c2ecf20Sopenharmony_ci goto send; 60478c2ecf20Sopenharmony_ci 60488c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Temperature */ 60498c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].desc_tag = cpu_to_be32(0x10007); 60508c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].desc_len = 60518c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); 60528c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Voltage */ 60538c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].desc_tag = cpu_to_be32(0x10007); 60548c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].desc_len = 60558c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); 60568c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Tx Bias Current */ 60578c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].desc_tag = cpu_to_be32(0x10007); 60588c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].desc_len = 60598c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); 60608c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Tx Power */ 60618c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].desc_tag = cpu_to_be32(0x10007); 60628c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].desc_len = 60638c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); 60648c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Rx Power */ 60658c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].desc_tag = cpu_to_be32(0x10007); 60668c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].desc_len = 60678c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(*rsp_payload->optical_elmt_desc)); 60688c2ecf20Sopenharmony_ci 60698c2ecf20Sopenharmony_ci if (sfp) { 60708c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 60718c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 0, 64, 0); 60728c2ecf20Sopenharmony_ci if (!rval) { 60738c2ecf20Sopenharmony_ci __be16 *trx = (__force __be16 *)sfp; /* already be16 */ 60748c2ecf20Sopenharmony_ci 60758c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Temperature */ 60768c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].high_alarm = trx[0]; 60778c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].low_alarm = trx[1]; 60788c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].high_warn = trx[2]; 60798c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].low_warn = trx[3]; 60808c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].element_flags = 60818c2ecf20Sopenharmony_ci cpu_to_be32(1 << 28); 60828c2ecf20Sopenharmony_ci 60838c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Voltage */ 60848c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].high_alarm = trx[4]; 60858c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].low_alarm = trx[5]; 60868c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].high_warn = trx[6]; 60878c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].low_warn = trx[7]; 60888c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].element_flags = 60898c2ecf20Sopenharmony_ci cpu_to_be32(2 << 28); 60908c2ecf20Sopenharmony_ci 60918c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Tx Bias Current */ 60928c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].high_alarm = trx[8]; 60938c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].low_alarm = trx[9]; 60948c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].high_warn = trx[10]; 60958c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].low_warn = trx[11]; 60968c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].element_flags = 60978c2ecf20Sopenharmony_ci cpu_to_be32(3 << 28); 60988c2ecf20Sopenharmony_ci 60998c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Tx Power */ 61008c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].high_alarm = trx[12]; 61018c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].low_alarm = trx[13]; 61028c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].high_warn = trx[14]; 61038c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].low_warn = trx[15]; 61048c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].element_flags = 61058c2ecf20Sopenharmony_ci cpu_to_be32(4 << 28); 61068c2ecf20Sopenharmony_ci 61078c2ecf20Sopenharmony_ci /* Optical Element Descriptor, Rx Power */ 61088c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].high_alarm = trx[16]; 61098c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].low_alarm = trx[17]; 61108c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].high_warn = trx[18]; 61118c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].low_warn = trx[19]; 61128c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].element_flags = 61138c2ecf20Sopenharmony_ci cpu_to_be32(5 << 28); 61148c2ecf20Sopenharmony_ci } 61158c2ecf20Sopenharmony_ci 61168c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 61178c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa2, 112, 64, 0); 61188c2ecf20Sopenharmony_ci if (!rval) { 61198c2ecf20Sopenharmony_ci /* Temperature high/low alarm/warning */ 61208c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[0].element_flags |= 61218c2ecf20Sopenharmony_ci cpu_to_be32( 61228c2ecf20Sopenharmony_ci (sfp[0] >> 7 & 1) << 3 | 61238c2ecf20Sopenharmony_ci (sfp[0] >> 6 & 1) << 2 | 61248c2ecf20Sopenharmony_ci (sfp[4] >> 7 & 1) << 1 | 61258c2ecf20Sopenharmony_ci (sfp[4] >> 6 & 1) << 0); 61268c2ecf20Sopenharmony_ci 61278c2ecf20Sopenharmony_ci /* Voltage high/low alarm/warning */ 61288c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[1].element_flags |= 61298c2ecf20Sopenharmony_ci cpu_to_be32( 61308c2ecf20Sopenharmony_ci (sfp[0] >> 5 & 1) << 3 | 61318c2ecf20Sopenharmony_ci (sfp[0] >> 4 & 1) << 2 | 61328c2ecf20Sopenharmony_ci (sfp[4] >> 5 & 1) << 1 | 61338c2ecf20Sopenharmony_ci (sfp[4] >> 4 & 1) << 0); 61348c2ecf20Sopenharmony_ci 61358c2ecf20Sopenharmony_ci /* Tx Bias Current high/low alarm/warning */ 61368c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[2].element_flags |= 61378c2ecf20Sopenharmony_ci cpu_to_be32( 61388c2ecf20Sopenharmony_ci (sfp[0] >> 3 & 1) << 3 | 61398c2ecf20Sopenharmony_ci (sfp[0] >> 2 & 1) << 2 | 61408c2ecf20Sopenharmony_ci (sfp[4] >> 3 & 1) << 1 | 61418c2ecf20Sopenharmony_ci (sfp[4] >> 2 & 1) << 0); 61428c2ecf20Sopenharmony_ci 61438c2ecf20Sopenharmony_ci /* Tx Power high/low alarm/warning */ 61448c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[3].element_flags |= 61458c2ecf20Sopenharmony_ci cpu_to_be32( 61468c2ecf20Sopenharmony_ci (sfp[0] >> 1 & 1) << 3 | 61478c2ecf20Sopenharmony_ci (sfp[0] >> 0 & 1) << 2 | 61488c2ecf20Sopenharmony_ci (sfp[4] >> 1 & 1) << 1 | 61498c2ecf20Sopenharmony_ci (sfp[4] >> 0 & 1) << 0); 61508c2ecf20Sopenharmony_ci 61518c2ecf20Sopenharmony_ci /* Rx Power high/low alarm/warning */ 61528c2ecf20Sopenharmony_ci rsp_payload->optical_elmt_desc[4].element_flags |= 61538c2ecf20Sopenharmony_ci cpu_to_be32( 61548c2ecf20Sopenharmony_ci (sfp[1] >> 7 & 1) << 3 | 61558c2ecf20Sopenharmony_ci (sfp[1] >> 6 & 1) << 2 | 61568c2ecf20Sopenharmony_ci (sfp[5] >> 7 & 1) << 1 | 61578c2ecf20Sopenharmony_ci (sfp[5] >> 6 & 1) << 0); 61588c2ecf20Sopenharmony_ci } 61598c2ecf20Sopenharmony_ci } 61608c2ecf20Sopenharmony_ci 61618c2ecf20Sopenharmony_ci /* Optical Product Data Descriptor */ 61628c2ecf20Sopenharmony_ci rsp_payload->optical_prod_desc.desc_tag = cpu_to_be32(0x10008); 61638c2ecf20Sopenharmony_ci rsp_payload->optical_prod_desc.desc_len = 61648c2ecf20Sopenharmony_ci cpu_to_be32(RDP_DESC_LEN(rsp_payload->optical_prod_desc)); 61658c2ecf20Sopenharmony_ci 61668c2ecf20Sopenharmony_ci if (sfp) { 61678c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 61688c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 20, 64, 0); 61698c2ecf20Sopenharmony_ci if (!rval) { 61708c2ecf20Sopenharmony_ci memcpy(rsp_payload->optical_prod_desc.vendor_name, 61718c2ecf20Sopenharmony_ci sfp + 0, 61728c2ecf20Sopenharmony_ci sizeof(rsp_payload->optical_prod_desc.vendor_name)); 61738c2ecf20Sopenharmony_ci memcpy(rsp_payload->optical_prod_desc.part_number, 61748c2ecf20Sopenharmony_ci sfp + 20, 61758c2ecf20Sopenharmony_ci sizeof(rsp_payload->optical_prod_desc.part_number)); 61768c2ecf20Sopenharmony_ci memcpy(rsp_payload->optical_prod_desc.revision, 61778c2ecf20Sopenharmony_ci sfp + 36, 61788c2ecf20Sopenharmony_ci sizeof(rsp_payload->optical_prod_desc.revision)); 61798c2ecf20Sopenharmony_ci memcpy(rsp_payload->optical_prod_desc.serial_number, 61808c2ecf20Sopenharmony_ci sfp + 48, 61818c2ecf20Sopenharmony_ci sizeof(rsp_payload->optical_prod_desc.serial_number)); 61828c2ecf20Sopenharmony_ci } 61838c2ecf20Sopenharmony_ci 61848c2ecf20Sopenharmony_ci memset(sfp, 0, SFP_RTDI_LEN); 61858c2ecf20Sopenharmony_ci rval = qla2x00_read_sfp(vha, sfp_dma, sfp, 0xa0, 84, 8, 0); 61868c2ecf20Sopenharmony_ci if (!rval) { 61878c2ecf20Sopenharmony_ci memcpy(rsp_payload->optical_prod_desc.date, 61888c2ecf20Sopenharmony_ci sfp + 0, 61898c2ecf20Sopenharmony_ci sizeof(rsp_payload->optical_prod_desc.date)); 61908c2ecf20Sopenharmony_ci } 61918c2ecf20Sopenharmony_ci } 61928c2ecf20Sopenharmony_ci 61938c2ecf20Sopenharmony_cisend: 61948c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x0183, 61958c2ecf20Sopenharmony_ci "Sending ELS Response to RDP Request...\n"); 61968c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0184, 61978c2ecf20Sopenharmony_ci "-------- ELS RSP -------\n"); 61988c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0185, 61998c2ecf20Sopenharmony_ci rsp_els, sizeof(*rsp_els)); 62008c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x0186, 62018c2ecf20Sopenharmony_ci "-------- ELS RSP PAYLOAD -------\n"); 62028c2ecf20Sopenharmony_ci ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x0187, 62038c2ecf20Sopenharmony_ci rsp_payload, rsp_payload_length); 62048c2ecf20Sopenharmony_ci 62058c2ecf20Sopenharmony_ci rval = qla2x00_issue_iocb(vha, rsp_els, rsp_els_dma, 0); 62068c2ecf20Sopenharmony_ci 62078c2ecf20Sopenharmony_ci if (rval) { 62088c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x0188, 62098c2ecf20Sopenharmony_ci "%s: iocb failed to execute -> %x\n", __func__, rval); 62108c2ecf20Sopenharmony_ci } else if (rsp_els->comp_status) { 62118c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x0189, 62128c2ecf20Sopenharmony_ci "%s: iocb failed to complete -> completion=%#x subcode=(%#x,%#x)\n", 62138c2ecf20Sopenharmony_ci __func__, rsp_els->comp_status, 62148c2ecf20Sopenharmony_ci rsp_els->error_subcode_1, rsp_els->error_subcode_2); 62158c2ecf20Sopenharmony_ci } else { 62168c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_init, vha, 0x018a, "%s: done.\n", __func__); 62178c2ecf20Sopenharmony_ci } 62188c2ecf20Sopenharmony_ci 62198c2ecf20Sopenharmony_cidealloc: 62208c2ecf20Sopenharmony_ci if (stat) 62218c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*stat), 62228c2ecf20Sopenharmony_ci stat, stat_dma); 62238c2ecf20Sopenharmony_ci if (sfp) 62248c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, SFP_RTDI_LEN, 62258c2ecf20Sopenharmony_ci sfp, sfp_dma); 62268c2ecf20Sopenharmony_ci if (rsp_payload) 62278c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_payload), 62288c2ecf20Sopenharmony_ci rsp_payload, rsp_payload_dma); 62298c2ecf20Sopenharmony_ci if (rsp_els) 62308c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*rsp_els), 62318c2ecf20Sopenharmony_ci rsp_els, rsp_els_dma); 62328c2ecf20Sopenharmony_ci} 62338c2ecf20Sopenharmony_ci 62348c2ecf20Sopenharmony_civoid 62358c2ecf20Sopenharmony_ciqla24xx_free_purex_item(struct purex_item *item) 62368c2ecf20Sopenharmony_ci{ 62378c2ecf20Sopenharmony_ci if (item == &item->vha->default_item) 62388c2ecf20Sopenharmony_ci memset(&item->vha->default_item, 0, sizeof(struct purex_item)); 62398c2ecf20Sopenharmony_ci else 62408c2ecf20Sopenharmony_ci kfree(item); 62418c2ecf20Sopenharmony_ci} 62428c2ecf20Sopenharmony_ci 62438c2ecf20Sopenharmony_civoid qla24xx_process_purex_list(struct purex_list *list) 62448c2ecf20Sopenharmony_ci{ 62458c2ecf20Sopenharmony_ci struct list_head head = LIST_HEAD_INIT(head); 62468c2ecf20Sopenharmony_ci struct purex_item *item, *next; 62478c2ecf20Sopenharmony_ci ulong flags; 62488c2ecf20Sopenharmony_ci 62498c2ecf20Sopenharmony_ci spin_lock_irqsave(&list->lock, flags); 62508c2ecf20Sopenharmony_ci list_splice_init(&list->head, &head); 62518c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&list->lock, flags); 62528c2ecf20Sopenharmony_ci 62538c2ecf20Sopenharmony_ci list_for_each_entry_safe(item, next, &head, list) { 62548c2ecf20Sopenharmony_ci list_del(&item->list); 62558c2ecf20Sopenharmony_ci item->process_item(item->vha, item); 62568c2ecf20Sopenharmony_ci qla24xx_free_purex_item(item); 62578c2ecf20Sopenharmony_ci } 62588c2ecf20Sopenharmony_ci} 62598c2ecf20Sopenharmony_ci 62608c2ecf20Sopenharmony_civoid 62618c2ecf20Sopenharmony_ciqla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) 62628c2ecf20Sopenharmony_ci{ 62638c2ecf20Sopenharmony_ci#if 0 62648c2ecf20Sopenharmony_ci uint16_t options = (requester_id << 15) | BIT_7; 62658c2ecf20Sopenharmony_ci#endif 62668c2ecf20Sopenharmony_ci uint16_t retry; 62678c2ecf20Sopenharmony_ci uint32_t data; 62688c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 62698c2ecf20Sopenharmony_ci 62708c2ecf20Sopenharmony_ci /* IDC-unlock implementation using driver-unlock/lock-id 62718c2ecf20Sopenharmony_ci * remote registers 62728c2ecf20Sopenharmony_ci */ 62738c2ecf20Sopenharmony_ci retry = 0; 62748c2ecf20Sopenharmony_ciretry_unlock: 62758c2ecf20Sopenharmony_ci if (qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, &data) 62768c2ecf20Sopenharmony_ci == QLA_SUCCESS) { 62778c2ecf20Sopenharmony_ci if (data == ha->portnum) { 62788c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_UNLOCK, &data); 62798c2ecf20Sopenharmony_ci /* Clearing lock-id by setting 0xff */ 62808c2ecf20Sopenharmony_ci qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID, 0xff); 62818c2ecf20Sopenharmony_ci } else if (retry < 10) { 62828c2ecf20Sopenharmony_ci /* SV: XXX: IDC unlock retrying needed here? */ 62838c2ecf20Sopenharmony_ci 62848c2ecf20Sopenharmony_ci /* Retry for IDC-unlock */ 62858c2ecf20Sopenharmony_ci qla83xx_wait_logic(); 62868c2ecf20Sopenharmony_ci retry++; 62878c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb064, 62888c2ecf20Sopenharmony_ci "Failed to release IDC lock, retrying=%d\n", retry); 62898c2ecf20Sopenharmony_ci goto retry_unlock; 62908c2ecf20Sopenharmony_ci } 62918c2ecf20Sopenharmony_ci } else if (retry < 10) { 62928c2ecf20Sopenharmony_ci /* Retry for IDC-unlock */ 62938c2ecf20Sopenharmony_ci qla83xx_wait_logic(); 62948c2ecf20Sopenharmony_ci retry++; 62958c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb065, 62968c2ecf20Sopenharmony_ci "Failed to read drv-lockid, retrying=%d\n", retry); 62978c2ecf20Sopenharmony_ci goto retry_unlock; 62988c2ecf20Sopenharmony_ci } 62998c2ecf20Sopenharmony_ci 63008c2ecf20Sopenharmony_ci return; 63018c2ecf20Sopenharmony_ci 63028c2ecf20Sopenharmony_ci#if 0 63038c2ecf20Sopenharmony_ci /* XXX: IDC-unlock implementation using access-control mbx */ 63048c2ecf20Sopenharmony_ci retry = 0; 63058c2ecf20Sopenharmony_ciretry_unlock2: 63068c2ecf20Sopenharmony_ci if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) { 63078c2ecf20Sopenharmony_ci if (retry < 10) { 63088c2ecf20Sopenharmony_ci /* Retry for IDC-unlock */ 63098c2ecf20Sopenharmony_ci qla83xx_wait_logic(); 63108c2ecf20Sopenharmony_ci retry++; 63118c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb066, 63128c2ecf20Sopenharmony_ci "Failed to release IDC lock, retrying=%d\n", retry); 63138c2ecf20Sopenharmony_ci goto retry_unlock2; 63148c2ecf20Sopenharmony_ci } 63158c2ecf20Sopenharmony_ci } 63168c2ecf20Sopenharmony_ci 63178c2ecf20Sopenharmony_ci return; 63188c2ecf20Sopenharmony_ci#endif 63198c2ecf20Sopenharmony_ci} 63208c2ecf20Sopenharmony_ci 63218c2ecf20Sopenharmony_ciint 63228c2ecf20Sopenharmony_ci__qla83xx_set_drv_presence(scsi_qla_host_t *vha) 63238c2ecf20Sopenharmony_ci{ 63248c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 63258c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 63268c2ecf20Sopenharmony_ci uint32_t drv_presence; 63278c2ecf20Sopenharmony_ci 63288c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence); 63298c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 63308c2ecf20Sopenharmony_ci drv_presence |= (1 << ha->portnum); 63318c2ecf20Sopenharmony_ci rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRV_PRESENCE, 63328c2ecf20Sopenharmony_ci drv_presence); 63338c2ecf20Sopenharmony_ci } 63348c2ecf20Sopenharmony_ci 63358c2ecf20Sopenharmony_ci return rval; 63368c2ecf20Sopenharmony_ci} 63378c2ecf20Sopenharmony_ci 63388c2ecf20Sopenharmony_ciint 63398c2ecf20Sopenharmony_ciqla83xx_set_drv_presence(scsi_qla_host_t *vha) 63408c2ecf20Sopenharmony_ci{ 63418c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 63428c2ecf20Sopenharmony_ci 63438c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 63448c2ecf20Sopenharmony_ci rval = __qla83xx_set_drv_presence(vha); 63458c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 63468c2ecf20Sopenharmony_ci 63478c2ecf20Sopenharmony_ci return rval; 63488c2ecf20Sopenharmony_ci} 63498c2ecf20Sopenharmony_ci 63508c2ecf20Sopenharmony_ciint 63518c2ecf20Sopenharmony_ci__qla83xx_clear_drv_presence(scsi_qla_host_t *vha) 63528c2ecf20Sopenharmony_ci{ 63538c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 63548c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 63558c2ecf20Sopenharmony_ci uint32_t drv_presence; 63568c2ecf20Sopenharmony_ci 63578c2ecf20Sopenharmony_ci rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence); 63588c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 63598c2ecf20Sopenharmony_ci drv_presence &= ~(1 << ha->portnum); 63608c2ecf20Sopenharmony_ci rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRV_PRESENCE, 63618c2ecf20Sopenharmony_ci drv_presence); 63628c2ecf20Sopenharmony_ci } 63638c2ecf20Sopenharmony_ci 63648c2ecf20Sopenharmony_ci return rval; 63658c2ecf20Sopenharmony_ci} 63668c2ecf20Sopenharmony_ci 63678c2ecf20Sopenharmony_ciint 63688c2ecf20Sopenharmony_ciqla83xx_clear_drv_presence(scsi_qla_host_t *vha) 63698c2ecf20Sopenharmony_ci{ 63708c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 63718c2ecf20Sopenharmony_ci 63728c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 63738c2ecf20Sopenharmony_ci rval = __qla83xx_clear_drv_presence(vha); 63748c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 63758c2ecf20Sopenharmony_ci 63768c2ecf20Sopenharmony_ci return rval; 63778c2ecf20Sopenharmony_ci} 63788c2ecf20Sopenharmony_ci 63798c2ecf20Sopenharmony_cistatic void 63808c2ecf20Sopenharmony_ciqla83xx_need_reset_handler(scsi_qla_host_t *vha) 63818c2ecf20Sopenharmony_ci{ 63828c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 63838c2ecf20Sopenharmony_ci uint32_t drv_ack, drv_presence; 63848c2ecf20Sopenharmony_ci unsigned long ack_timeout; 63858c2ecf20Sopenharmony_ci 63868c2ecf20Sopenharmony_ci /* Wait for IDC ACK from all functions (DRV-ACK == DRV-PRESENCE) */ 63878c2ecf20Sopenharmony_ci ack_timeout = jiffies + (ha->fcoe_reset_timeout * HZ); 63888c2ecf20Sopenharmony_ci while (1) { 63898c2ecf20Sopenharmony_ci qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack); 63908c2ecf20Sopenharmony_ci qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence); 63918c2ecf20Sopenharmony_ci if ((drv_ack & drv_presence) == drv_presence) 63928c2ecf20Sopenharmony_ci break; 63938c2ecf20Sopenharmony_ci 63948c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, ack_timeout)) { 63958c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0xb067, 63968c2ecf20Sopenharmony_ci "RESET ACK TIMEOUT! drv_presence=0x%x " 63978c2ecf20Sopenharmony_ci "drv_ack=0x%x\n", drv_presence, drv_ack); 63988c2ecf20Sopenharmony_ci /* 63998c2ecf20Sopenharmony_ci * The function(s) which did not ack in time are forced 64008c2ecf20Sopenharmony_ci * to withdraw any further participation in the IDC 64018c2ecf20Sopenharmony_ci * reset. 64028c2ecf20Sopenharmony_ci */ 64038c2ecf20Sopenharmony_ci if (drv_ack != drv_presence) 64048c2ecf20Sopenharmony_ci qla83xx_wr_reg(vha, QLA83XX_IDC_DRV_PRESENCE, 64058c2ecf20Sopenharmony_ci drv_ack); 64068c2ecf20Sopenharmony_ci break; 64078c2ecf20Sopenharmony_ci } 64088c2ecf20Sopenharmony_ci 64098c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 64108c2ecf20Sopenharmony_ci msleep(1000); 64118c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 64128c2ecf20Sopenharmony_ci } 64138c2ecf20Sopenharmony_ci 64148c2ecf20Sopenharmony_ci qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_COLD); 64158c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xb068, "HW State: COLD/RE-INIT.\n"); 64168c2ecf20Sopenharmony_ci} 64178c2ecf20Sopenharmony_ci 64188c2ecf20Sopenharmony_cistatic int 64198c2ecf20Sopenharmony_ciqla83xx_device_bootstrap(scsi_qla_host_t *vha) 64208c2ecf20Sopenharmony_ci{ 64218c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 64228c2ecf20Sopenharmony_ci uint32_t idc_control; 64238c2ecf20Sopenharmony_ci 64248c2ecf20Sopenharmony_ci qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_INITIALIZING); 64258c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xb069, "HW State: INITIALIZING.\n"); 64268c2ecf20Sopenharmony_ci 64278c2ecf20Sopenharmony_ci /* Clearing IDC-Control Graceful-Reset Bit before resetting f/w */ 64288c2ecf20Sopenharmony_ci __qla83xx_get_idc_control(vha, &idc_control); 64298c2ecf20Sopenharmony_ci idc_control &= ~QLA83XX_IDC_GRACEFUL_RESET; 64308c2ecf20Sopenharmony_ci __qla83xx_set_idc_control(vha, 0); 64318c2ecf20Sopenharmony_ci 64328c2ecf20Sopenharmony_ci qla83xx_idc_unlock(vha, 0); 64338c2ecf20Sopenharmony_ci rval = qla83xx_restart_nic_firmware(vha); 64348c2ecf20Sopenharmony_ci qla83xx_idc_lock(vha, 0); 64358c2ecf20Sopenharmony_ci 64368c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 64378c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, vha, 0xb06a, 64388c2ecf20Sopenharmony_ci "Failed to restart NIC f/w.\n"); 64398c2ecf20Sopenharmony_ci qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_FAILED); 64408c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xb06b, "HW State: FAILED.\n"); 64418c2ecf20Sopenharmony_ci } else { 64428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, vha, 0xb06c, 64438c2ecf20Sopenharmony_ci "Success in restarting nic f/w.\n"); 64448c2ecf20Sopenharmony_ci qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_READY); 64458c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xb06d, "HW State: READY.\n"); 64468c2ecf20Sopenharmony_ci } 64478c2ecf20Sopenharmony_ci 64488c2ecf20Sopenharmony_ci return rval; 64498c2ecf20Sopenharmony_ci} 64508c2ecf20Sopenharmony_ci 64518c2ecf20Sopenharmony_ci/* Assumes idc_lock always held on entry */ 64528c2ecf20Sopenharmony_ciint 64538c2ecf20Sopenharmony_ciqla83xx_idc_state_handler(scsi_qla_host_t *base_vha) 64548c2ecf20Sopenharmony_ci{ 64558c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 64568c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 64578c2ecf20Sopenharmony_ci unsigned long dev_init_timeout; 64588c2ecf20Sopenharmony_ci uint32_t dev_state; 64598c2ecf20Sopenharmony_ci 64608c2ecf20Sopenharmony_ci /* Wait for MAX-INIT-TIMEOUT for the device to go ready */ 64618c2ecf20Sopenharmony_ci dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ); 64628c2ecf20Sopenharmony_ci 64638c2ecf20Sopenharmony_ci while (1) { 64648c2ecf20Sopenharmony_ci 64658c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, dev_init_timeout)) { 64668c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xb06e, 64678c2ecf20Sopenharmony_ci "Initialization TIMEOUT!\n"); 64688c2ecf20Sopenharmony_ci /* Init timeout. Disable further NIC Core 64698c2ecf20Sopenharmony_ci * communication. 64708c2ecf20Sopenharmony_ci */ 64718c2ecf20Sopenharmony_ci qla83xx_wr_reg(base_vha, QLA83XX_IDC_DEV_STATE, 64728c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 64738c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0xb06f, 64748c2ecf20Sopenharmony_ci "HW State: FAILED.\n"); 64758c2ecf20Sopenharmony_ci } 64768c2ecf20Sopenharmony_ci 64778c2ecf20Sopenharmony_ci qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state); 64788c2ecf20Sopenharmony_ci switch (dev_state) { 64798c2ecf20Sopenharmony_ci case QLA8XXX_DEV_READY: 64808c2ecf20Sopenharmony_ci if (ha->flags.nic_core_reset_owner) 64818c2ecf20Sopenharmony_ci qla83xx_idc_audit(base_vha, 64828c2ecf20Sopenharmony_ci IDC_AUDIT_COMPLETION); 64838c2ecf20Sopenharmony_ci ha->flags.nic_core_reset_owner = 0; 64848c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_p3p, base_vha, 0xb070, 64858c2ecf20Sopenharmony_ci "Reset_owner reset by 0x%x.\n", 64868c2ecf20Sopenharmony_ci ha->portnum); 64878c2ecf20Sopenharmony_ci goto exit; 64888c2ecf20Sopenharmony_ci case QLA8XXX_DEV_COLD: 64898c2ecf20Sopenharmony_ci if (ha->flags.nic_core_reset_owner) 64908c2ecf20Sopenharmony_ci rval = qla83xx_device_bootstrap(base_vha); 64918c2ecf20Sopenharmony_ci else { 64928c2ecf20Sopenharmony_ci /* Wait for AEN to change device-state */ 64938c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 64948c2ecf20Sopenharmony_ci msleep(1000); 64958c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 64968c2ecf20Sopenharmony_ci } 64978c2ecf20Sopenharmony_ci break; 64988c2ecf20Sopenharmony_ci case QLA8XXX_DEV_INITIALIZING: 64998c2ecf20Sopenharmony_ci /* Wait for AEN to change device-state */ 65008c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65018c2ecf20Sopenharmony_ci msleep(1000); 65028c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65038c2ecf20Sopenharmony_ci break; 65048c2ecf20Sopenharmony_ci case QLA8XXX_DEV_NEED_RESET: 65058c2ecf20Sopenharmony_ci if (!ql2xdontresethba && ha->flags.nic_core_reset_owner) 65068c2ecf20Sopenharmony_ci qla83xx_need_reset_handler(base_vha); 65078c2ecf20Sopenharmony_ci else { 65088c2ecf20Sopenharmony_ci /* Wait for AEN to change device-state */ 65098c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65108c2ecf20Sopenharmony_ci msleep(1000); 65118c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65128c2ecf20Sopenharmony_ci } 65138c2ecf20Sopenharmony_ci /* reset timeout value after need reset handler */ 65148c2ecf20Sopenharmony_ci dev_init_timeout = jiffies + 65158c2ecf20Sopenharmony_ci (ha->fcoe_dev_init_timeout * HZ); 65168c2ecf20Sopenharmony_ci break; 65178c2ecf20Sopenharmony_ci case QLA8XXX_DEV_NEED_QUIESCENT: 65188c2ecf20Sopenharmony_ci /* XXX: DEBUG for now */ 65198c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65208c2ecf20Sopenharmony_ci msleep(1000); 65218c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65228c2ecf20Sopenharmony_ci break; 65238c2ecf20Sopenharmony_ci case QLA8XXX_DEV_QUIESCENT: 65248c2ecf20Sopenharmony_ci /* XXX: DEBUG for now */ 65258c2ecf20Sopenharmony_ci if (ha->flags.quiesce_owner) 65268c2ecf20Sopenharmony_ci goto exit; 65278c2ecf20Sopenharmony_ci 65288c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65298c2ecf20Sopenharmony_ci msleep(1000); 65308c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65318c2ecf20Sopenharmony_ci dev_init_timeout = jiffies + 65328c2ecf20Sopenharmony_ci (ha->fcoe_dev_init_timeout * HZ); 65338c2ecf20Sopenharmony_ci break; 65348c2ecf20Sopenharmony_ci case QLA8XXX_DEV_FAILED: 65358c2ecf20Sopenharmony_ci if (ha->flags.nic_core_reset_owner) 65368c2ecf20Sopenharmony_ci qla83xx_idc_audit(base_vha, 65378c2ecf20Sopenharmony_ci IDC_AUDIT_COMPLETION); 65388c2ecf20Sopenharmony_ci ha->flags.nic_core_reset_owner = 0; 65398c2ecf20Sopenharmony_ci __qla83xx_clear_drv_presence(base_vha); 65408c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65418c2ecf20Sopenharmony_ci qla8xxx_dev_failed_handler(base_vha); 65428c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 65438c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65448c2ecf20Sopenharmony_ci goto exit; 65458c2ecf20Sopenharmony_ci case QLA8XXX_BAD_VALUE: 65468c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65478c2ecf20Sopenharmony_ci msleep(1000); 65488c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65498c2ecf20Sopenharmony_ci break; 65508c2ecf20Sopenharmony_ci default: 65518c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xb071, 65528c2ecf20Sopenharmony_ci "Unknown Device State: %x.\n", dev_state); 65538c2ecf20Sopenharmony_ci qla83xx_idc_unlock(base_vha, 0); 65548c2ecf20Sopenharmony_ci qla8xxx_dev_failed_handler(base_vha); 65558c2ecf20Sopenharmony_ci rval = QLA_FUNCTION_FAILED; 65568c2ecf20Sopenharmony_ci qla83xx_idc_lock(base_vha, 0); 65578c2ecf20Sopenharmony_ci goto exit; 65588c2ecf20Sopenharmony_ci } 65598c2ecf20Sopenharmony_ci } 65608c2ecf20Sopenharmony_ci 65618c2ecf20Sopenharmony_ciexit: 65628c2ecf20Sopenharmony_ci return rval; 65638c2ecf20Sopenharmony_ci} 65648c2ecf20Sopenharmony_ci 65658c2ecf20Sopenharmony_civoid 65668c2ecf20Sopenharmony_ciqla2x00_disable_board_on_pci_error(struct work_struct *work) 65678c2ecf20Sopenharmony_ci{ 65688c2ecf20Sopenharmony_ci struct qla_hw_data *ha = container_of(work, struct qla_hw_data, 65698c2ecf20Sopenharmony_ci board_disable); 65708c2ecf20Sopenharmony_ci struct pci_dev *pdev = ha->pdev; 65718c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 65728c2ecf20Sopenharmony_ci 65738c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x015b, 65748c2ecf20Sopenharmony_ci "Disabling adapter.\n"); 65758c2ecf20Sopenharmony_ci 65768c2ecf20Sopenharmony_ci if (!atomic_read(&pdev->enable_cnt)) { 65778c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0xfffc, 65788c2ecf20Sopenharmony_ci "PCI device disabled, no action req for PCI error=%lx\n", 65798c2ecf20Sopenharmony_ci base_vha->pci_flags); 65808c2ecf20Sopenharmony_ci return; 65818c2ecf20Sopenharmony_ci } 65828c2ecf20Sopenharmony_ci 65838c2ecf20Sopenharmony_ci /* 65848c2ecf20Sopenharmony_ci * if UNLOADING flag is already set, then continue unload, 65858c2ecf20Sopenharmony_ci * where it was set first. 65868c2ecf20Sopenharmony_ci */ 65878c2ecf20Sopenharmony_ci if (test_and_set_bit(UNLOADING, &base_vha->dpc_flags)) 65888c2ecf20Sopenharmony_ci return; 65898c2ecf20Sopenharmony_ci 65908c2ecf20Sopenharmony_ci qla2x00_wait_for_sess_deletion(base_vha); 65918c2ecf20Sopenharmony_ci 65928c2ecf20Sopenharmony_ci qla2x00_delete_all_vps(ha, base_vha); 65938c2ecf20Sopenharmony_ci 65948c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); 65958c2ecf20Sopenharmony_ci 65968c2ecf20Sopenharmony_ci qla2x00_dfs_remove(base_vha); 65978c2ecf20Sopenharmony_ci 65988c2ecf20Sopenharmony_ci qla84xx_put_chip(base_vha); 65998c2ecf20Sopenharmony_ci 66008c2ecf20Sopenharmony_ci if (base_vha->timer_active) 66018c2ecf20Sopenharmony_ci qla2x00_stop_timer(base_vha); 66028c2ecf20Sopenharmony_ci 66038c2ecf20Sopenharmony_ci base_vha->flags.online = 0; 66048c2ecf20Sopenharmony_ci 66058c2ecf20Sopenharmony_ci qla2x00_destroy_deferred_work(ha); 66068c2ecf20Sopenharmony_ci 66078c2ecf20Sopenharmony_ci /* 66088c2ecf20Sopenharmony_ci * Do not try to stop beacon blink as it will issue a mailbox 66098c2ecf20Sopenharmony_ci * command. 66108c2ecf20Sopenharmony_ci */ 66118c2ecf20Sopenharmony_ci qla2x00_free_sysfs_attr(base_vha, false); 66128c2ecf20Sopenharmony_ci 66138c2ecf20Sopenharmony_ci fc_remove_host(base_vha->host); 66148c2ecf20Sopenharmony_ci 66158c2ecf20Sopenharmony_ci scsi_remove_host(base_vha->host); 66168c2ecf20Sopenharmony_ci 66178c2ecf20Sopenharmony_ci base_vha->flags.init_done = 0; 66188c2ecf20Sopenharmony_ci qla25xx_delete_queues(base_vha); 66198c2ecf20Sopenharmony_ci qla2x00_free_fcports(base_vha); 66208c2ecf20Sopenharmony_ci qla2x00_free_irqs(base_vha); 66218c2ecf20Sopenharmony_ci qla2x00_mem_free(ha); 66228c2ecf20Sopenharmony_ci qla82xx_md_free(base_vha); 66238c2ecf20Sopenharmony_ci qla2x00_free_queues(ha); 66248c2ecf20Sopenharmony_ci 66258c2ecf20Sopenharmony_ci qla2x00_unmap_iobases(ha); 66268c2ecf20Sopenharmony_ci 66278c2ecf20Sopenharmony_ci pci_release_selected_regions(ha->pdev, ha->bars); 66288c2ecf20Sopenharmony_ci pci_disable_pcie_error_reporting(pdev); 66298c2ecf20Sopenharmony_ci pci_disable_device(pdev); 66308c2ecf20Sopenharmony_ci 66318c2ecf20Sopenharmony_ci /* 66328c2ecf20Sopenharmony_ci * Let qla2x00_remove_one cleanup qla_hw_data on device removal. 66338c2ecf20Sopenharmony_ci */ 66348c2ecf20Sopenharmony_ci} 66358c2ecf20Sopenharmony_ci 66368c2ecf20Sopenharmony_ci/************************************************************************** 66378c2ecf20Sopenharmony_ci* qla2x00_do_dpc 66388c2ecf20Sopenharmony_ci* This kernel thread is a task that is schedule by the interrupt handler 66398c2ecf20Sopenharmony_ci* to perform the background processing for interrupts. 66408c2ecf20Sopenharmony_ci* 66418c2ecf20Sopenharmony_ci* Notes: 66428c2ecf20Sopenharmony_ci* This task always run in the context of a kernel thread. It 66438c2ecf20Sopenharmony_ci* is kick-off by the driver's detect code and starts up 66448c2ecf20Sopenharmony_ci* up one per adapter. It immediately goes to sleep and waits for 66458c2ecf20Sopenharmony_ci* some fibre event. When either the interrupt handler or 66468c2ecf20Sopenharmony_ci* the timer routine detects a event it will one of the task 66478c2ecf20Sopenharmony_ci* bits then wake us up. 66488c2ecf20Sopenharmony_ci**************************************************************************/ 66498c2ecf20Sopenharmony_cistatic int 66508c2ecf20Sopenharmony_ciqla2x00_do_dpc(void *data) 66518c2ecf20Sopenharmony_ci{ 66528c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha; 66538c2ecf20Sopenharmony_ci struct qla_hw_data *ha; 66548c2ecf20Sopenharmony_ci uint32_t online; 66558c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 66568c2ecf20Sopenharmony_ci 66578c2ecf20Sopenharmony_ci ha = (struct qla_hw_data *)data; 66588c2ecf20Sopenharmony_ci base_vha = pci_get_drvdata(ha->pdev); 66598c2ecf20Sopenharmony_ci 66608c2ecf20Sopenharmony_ci set_user_nice(current, MIN_NICE); 66618c2ecf20Sopenharmony_ci 66628c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 66638c2ecf20Sopenharmony_ci while (!kthread_should_stop()) { 66648c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4000, 66658c2ecf20Sopenharmony_ci "DPC handler sleeping.\n"); 66668c2ecf20Sopenharmony_ci 66678c2ecf20Sopenharmony_ci schedule(); 66688c2ecf20Sopenharmony_ci 66698c2ecf20Sopenharmony_ci if (test_and_clear_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags)) 66708c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(base_vha); 66718c2ecf20Sopenharmony_ci 66728c2ecf20Sopenharmony_ci if (!base_vha->flags.init_done || ha->flags.mbox_busy) 66738c2ecf20Sopenharmony_ci goto end_loop; 66748c2ecf20Sopenharmony_ci 66758c2ecf20Sopenharmony_ci if (ha->flags.eeh_busy) { 66768c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4003, 66778c2ecf20Sopenharmony_ci "eeh_busy=%d.\n", ha->flags.eeh_busy); 66788c2ecf20Sopenharmony_ci goto end_loop; 66798c2ecf20Sopenharmony_ci } 66808c2ecf20Sopenharmony_ci 66818c2ecf20Sopenharmony_ci ha->dpc_active = 1; 66828c2ecf20Sopenharmony_ci 66838c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc + ql_dbg_verbose, base_vha, 0x4001, 66848c2ecf20Sopenharmony_ci "DPC handler waking up, dpc_flags=0x%lx.\n", 66858c2ecf20Sopenharmony_ci base_vha->dpc_flags); 66868c2ecf20Sopenharmony_ci 66878c2ecf20Sopenharmony_ci if (test_bit(UNLOADING, &base_vha->dpc_flags)) 66888c2ecf20Sopenharmony_ci break; 66898c2ecf20Sopenharmony_ci 66908c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 66918c2ecf20Sopenharmony_ci if (IS_QLA8044(ha)) { 66928c2ecf20Sopenharmony_ci if (test_and_clear_bit(ISP_UNRECOVERABLE, 66938c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 66948c2ecf20Sopenharmony_ci qla8044_idc_lock(ha); 66958c2ecf20Sopenharmony_ci qla8044_wr_direct(base_vha, 66968c2ecf20Sopenharmony_ci QLA8044_CRB_DEV_STATE_INDEX, 66978c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 66988c2ecf20Sopenharmony_ci qla8044_idc_unlock(ha); 66998c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x4004, 67008c2ecf20Sopenharmony_ci "HW State: FAILED.\n"); 67018c2ecf20Sopenharmony_ci qla8044_device_state_handler(base_vha); 67028c2ecf20Sopenharmony_ci continue; 67038c2ecf20Sopenharmony_ci } 67048c2ecf20Sopenharmony_ci 67058c2ecf20Sopenharmony_ci } else { 67068c2ecf20Sopenharmony_ci if (test_and_clear_bit(ISP_UNRECOVERABLE, 67078c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67088c2ecf20Sopenharmony_ci qla82xx_idc_lock(ha); 67098c2ecf20Sopenharmony_ci qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 67108c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 67118c2ecf20Sopenharmony_ci qla82xx_idc_unlock(ha); 67128c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x0151, 67138c2ecf20Sopenharmony_ci "HW State: FAILED.\n"); 67148c2ecf20Sopenharmony_ci qla82xx_device_state_handler(base_vha); 67158c2ecf20Sopenharmony_ci continue; 67168c2ecf20Sopenharmony_ci } 67178c2ecf20Sopenharmony_ci } 67188c2ecf20Sopenharmony_ci 67198c2ecf20Sopenharmony_ci if (test_and_clear_bit(FCOE_CTX_RESET_NEEDED, 67208c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67218c2ecf20Sopenharmony_ci 67228c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4005, 67238c2ecf20Sopenharmony_ci "FCoE context reset scheduled.\n"); 67248c2ecf20Sopenharmony_ci if (!(test_and_set_bit(ABORT_ISP_ACTIVE, 67258c2ecf20Sopenharmony_ci &base_vha->dpc_flags))) { 67268c2ecf20Sopenharmony_ci if (qla82xx_fcoe_ctx_reset(base_vha)) { 67278c2ecf20Sopenharmony_ci /* FCoE-ctx reset failed. 67288c2ecf20Sopenharmony_ci * Escalate to chip-reset 67298c2ecf20Sopenharmony_ci */ 67308c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 67318c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 67328c2ecf20Sopenharmony_ci } 67338c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, 67348c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 67358c2ecf20Sopenharmony_ci } 67368c2ecf20Sopenharmony_ci 67378c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4006, 67388c2ecf20Sopenharmony_ci "FCoE context reset end.\n"); 67398c2ecf20Sopenharmony_ci } 67408c2ecf20Sopenharmony_ci } else if (IS_QLAFX00(ha)) { 67418c2ecf20Sopenharmony_ci if (test_and_clear_bit(ISP_UNRECOVERABLE, 67428c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67438c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4020, 67448c2ecf20Sopenharmony_ci "Firmware Reset Recovery\n"); 67458c2ecf20Sopenharmony_ci if (qlafx00_reset_initialize(base_vha)) { 67468c2ecf20Sopenharmony_ci /* Failed. Abort isp later. */ 67478c2ecf20Sopenharmony_ci if (!test_bit(UNLOADING, 67488c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67498c2ecf20Sopenharmony_ci set_bit(ISP_UNRECOVERABLE, 67508c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 67518c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 67528c2ecf20Sopenharmony_ci 0x4021, 67538c2ecf20Sopenharmony_ci "Reset Recovery Failed\n"); 67548c2ecf20Sopenharmony_ci } 67558c2ecf20Sopenharmony_ci } 67568c2ecf20Sopenharmony_ci } 67578c2ecf20Sopenharmony_ci 67588c2ecf20Sopenharmony_ci if (test_and_clear_bit(FX00_TARGET_SCAN, 67598c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67608c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4022, 67618c2ecf20Sopenharmony_ci "ISPFx00 Target Scan scheduled\n"); 67628c2ecf20Sopenharmony_ci if (qlafx00_rescan_isp(base_vha)) { 67638c2ecf20Sopenharmony_ci if (!test_bit(UNLOADING, 67648c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) 67658c2ecf20Sopenharmony_ci set_bit(ISP_UNRECOVERABLE, 67668c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 67678c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x401e, 67688c2ecf20Sopenharmony_ci "ISPFx00 Target Scan Failed\n"); 67698c2ecf20Sopenharmony_ci } 67708c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x401f, 67718c2ecf20Sopenharmony_ci "ISPFx00 Target Scan End\n"); 67728c2ecf20Sopenharmony_ci } 67738c2ecf20Sopenharmony_ci if (test_and_clear_bit(FX00_HOST_INFO_RESEND, 67748c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67758c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4023, 67768c2ecf20Sopenharmony_ci "ISPFx00 Host Info resend scheduled\n"); 67778c2ecf20Sopenharmony_ci qlafx00_fx_disc(base_vha, 67788c2ecf20Sopenharmony_ci &base_vha->hw->mr.fcport, 67798c2ecf20Sopenharmony_ci FXDISC_REG_HOST_INFO); 67808c2ecf20Sopenharmony_ci } 67818c2ecf20Sopenharmony_ci } 67828c2ecf20Sopenharmony_ci 67838c2ecf20Sopenharmony_ci if (test_and_clear_bit(DETECT_SFP_CHANGE, 67848c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 67858c2ecf20Sopenharmony_ci /* Semantic: 67868c2ecf20Sopenharmony_ci * - NO-OP -- await next ISP-ABORT. Preferred method 67878c2ecf20Sopenharmony_ci * to minimize disruptions that will occur 67888c2ecf20Sopenharmony_ci * when a forced chip-reset occurs. 67898c2ecf20Sopenharmony_ci * - Force -- ISP-ABORT scheduled. 67908c2ecf20Sopenharmony_ci */ 67918c2ecf20Sopenharmony_ci /* set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); */ 67928c2ecf20Sopenharmony_ci } 67938c2ecf20Sopenharmony_ci 67948c2ecf20Sopenharmony_ci if (test_and_clear_bit 67958c2ecf20Sopenharmony_ci (ISP_ABORT_NEEDED, &base_vha->dpc_flags) && 67968c2ecf20Sopenharmony_ci !test_bit(UNLOADING, &base_vha->dpc_flags)) { 67978c2ecf20Sopenharmony_ci bool do_reset = true; 67988c2ecf20Sopenharmony_ci 67998c2ecf20Sopenharmony_ci switch (base_vha->qlini_mode) { 68008c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_ENABLED: 68018c2ecf20Sopenharmony_ci break; 68028c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DISABLED: 68038c2ecf20Sopenharmony_ci if (!qla_tgt_mode_enabled(base_vha) && 68048c2ecf20Sopenharmony_ci !ha->flags.fw_started) 68058c2ecf20Sopenharmony_ci do_reset = false; 68068c2ecf20Sopenharmony_ci break; 68078c2ecf20Sopenharmony_ci case QLA2XXX_INI_MODE_DUAL: 68088c2ecf20Sopenharmony_ci if (!qla_dual_mode_enabled(base_vha) && 68098c2ecf20Sopenharmony_ci !ha->flags.fw_started) 68108c2ecf20Sopenharmony_ci do_reset = false; 68118c2ecf20Sopenharmony_ci break; 68128c2ecf20Sopenharmony_ci default: 68138c2ecf20Sopenharmony_ci break; 68148c2ecf20Sopenharmony_ci } 68158c2ecf20Sopenharmony_ci 68168c2ecf20Sopenharmony_ci if (do_reset && !(test_and_set_bit(ABORT_ISP_ACTIVE, 68178c2ecf20Sopenharmony_ci &base_vha->dpc_flags))) { 68188c2ecf20Sopenharmony_ci base_vha->flags.online = 1; 68198c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4007, 68208c2ecf20Sopenharmony_ci "ISP abort scheduled.\n"); 68218c2ecf20Sopenharmony_ci if (ha->isp_ops->abort_isp(base_vha)) { 68228c2ecf20Sopenharmony_ci /* failed. retry later */ 68238c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 68248c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 68258c2ecf20Sopenharmony_ci } 68268c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, 68278c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 68288c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4008, 68298c2ecf20Sopenharmony_ci "ISP abort end.\n"); 68308c2ecf20Sopenharmony_ci } 68318c2ecf20Sopenharmony_ci } 68328c2ecf20Sopenharmony_ci 68338c2ecf20Sopenharmony_ci if (test_bit(PROCESS_PUREX_IOCB, &base_vha->dpc_flags)) { 68348c2ecf20Sopenharmony_ci if (atomic_read(&base_vha->loop_state) == LOOP_READY) { 68358c2ecf20Sopenharmony_ci qla24xx_process_purex_list 68368c2ecf20Sopenharmony_ci (&base_vha->purex_list); 68378c2ecf20Sopenharmony_ci clear_bit(PROCESS_PUREX_IOCB, 68388c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 68398c2ecf20Sopenharmony_ci } 68408c2ecf20Sopenharmony_ci } 68418c2ecf20Sopenharmony_ci 68428c2ecf20Sopenharmony_ci if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, 68438c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 68448c2ecf20Sopenharmony_ci qla2x00_update_fcports(base_vha); 68458c2ecf20Sopenharmony_ci } 68468c2ecf20Sopenharmony_ci 68478c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) 68488c2ecf20Sopenharmony_ci goto loop_resync_check; 68498c2ecf20Sopenharmony_ci 68508c2ecf20Sopenharmony_ci if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { 68518c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4009, 68528c2ecf20Sopenharmony_ci "Quiescence mode scheduled.\n"); 68538c2ecf20Sopenharmony_ci if (IS_P3P_TYPE(ha)) { 68548c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) 68558c2ecf20Sopenharmony_ci qla82xx_device_state_handler(base_vha); 68568c2ecf20Sopenharmony_ci if (IS_QLA8044(ha)) 68578c2ecf20Sopenharmony_ci qla8044_device_state_handler(base_vha); 68588c2ecf20Sopenharmony_ci clear_bit(ISP_QUIESCE_NEEDED, 68598c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 68608c2ecf20Sopenharmony_ci if (!ha->flags.quiesce_owner) { 68618c2ecf20Sopenharmony_ci qla2x00_perform_loop_resync(base_vha); 68628c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) { 68638c2ecf20Sopenharmony_ci qla82xx_idc_lock(ha); 68648c2ecf20Sopenharmony_ci qla82xx_clear_qsnt_ready( 68658c2ecf20Sopenharmony_ci base_vha); 68668c2ecf20Sopenharmony_ci qla82xx_idc_unlock(ha); 68678c2ecf20Sopenharmony_ci } else if (IS_QLA8044(ha)) { 68688c2ecf20Sopenharmony_ci qla8044_idc_lock(ha); 68698c2ecf20Sopenharmony_ci qla8044_clear_qsnt_ready( 68708c2ecf20Sopenharmony_ci base_vha); 68718c2ecf20Sopenharmony_ci qla8044_idc_unlock(ha); 68728c2ecf20Sopenharmony_ci } 68738c2ecf20Sopenharmony_ci } 68748c2ecf20Sopenharmony_ci } else { 68758c2ecf20Sopenharmony_ci clear_bit(ISP_QUIESCE_NEEDED, 68768c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 68778c2ecf20Sopenharmony_ci qla2x00_quiesce_io(base_vha); 68788c2ecf20Sopenharmony_ci } 68798c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x400a, 68808c2ecf20Sopenharmony_ci "Quiescence mode end.\n"); 68818c2ecf20Sopenharmony_ci } 68828c2ecf20Sopenharmony_ci 68838c2ecf20Sopenharmony_ci if (test_and_clear_bit(RESET_MARKER_NEEDED, 68848c2ecf20Sopenharmony_ci &base_vha->dpc_flags) && 68858c2ecf20Sopenharmony_ci (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) { 68868c2ecf20Sopenharmony_ci 68878c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x400b, 68888c2ecf20Sopenharmony_ci "Reset marker scheduled.\n"); 68898c2ecf20Sopenharmony_ci qla2x00_rst_aen(base_vha); 68908c2ecf20Sopenharmony_ci clear_bit(RESET_ACTIVE, &base_vha->dpc_flags); 68918c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x400c, 68928c2ecf20Sopenharmony_ci "Reset marker end.\n"); 68938c2ecf20Sopenharmony_ci } 68948c2ecf20Sopenharmony_ci 68958c2ecf20Sopenharmony_ci /* Retry each device up to login retry count */ 68968c2ecf20Sopenharmony_ci if (test_bit(RELOGIN_NEEDED, &base_vha->dpc_flags) && 68978c2ecf20Sopenharmony_ci !test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags) && 68988c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state) != LOOP_DOWN) { 68998c2ecf20Sopenharmony_ci 69008c2ecf20Sopenharmony_ci if (!base_vha->relogin_jif || 69018c2ecf20Sopenharmony_ci time_after_eq(jiffies, base_vha->relogin_jif)) { 69028c2ecf20Sopenharmony_ci base_vha->relogin_jif = jiffies + HZ; 69038c2ecf20Sopenharmony_ci clear_bit(RELOGIN_NEEDED, &base_vha->dpc_flags); 69048c2ecf20Sopenharmony_ci 69058c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_disc, base_vha, 0x400d, 69068c2ecf20Sopenharmony_ci "Relogin scheduled.\n"); 69078c2ecf20Sopenharmony_ci qla24xx_post_relogin_work(base_vha); 69088c2ecf20Sopenharmony_ci } 69098c2ecf20Sopenharmony_ci } 69108c2ecf20Sopenharmony_ciloop_resync_check: 69118c2ecf20Sopenharmony_ci if (!qla2x00_reset_active(base_vha) && 69128c2ecf20Sopenharmony_ci test_and_clear_bit(LOOP_RESYNC_NEEDED, 69138c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 69148c2ecf20Sopenharmony_ci /* 69158c2ecf20Sopenharmony_ci * Allow abort_isp to complete before moving on to scanning. 69168c2ecf20Sopenharmony_ci */ 69178c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x400f, 69188c2ecf20Sopenharmony_ci "Loop resync scheduled.\n"); 69198c2ecf20Sopenharmony_ci 69208c2ecf20Sopenharmony_ci if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, 69218c2ecf20Sopenharmony_ci &base_vha->dpc_flags))) { 69228c2ecf20Sopenharmony_ci 69238c2ecf20Sopenharmony_ci qla2x00_loop_resync(base_vha); 69248c2ecf20Sopenharmony_ci 69258c2ecf20Sopenharmony_ci clear_bit(LOOP_RESYNC_ACTIVE, 69268c2ecf20Sopenharmony_ci &base_vha->dpc_flags); 69278c2ecf20Sopenharmony_ci } 69288c2ecf20Sopenharmony_ci 69298c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4010, 69308c2ecf20Sopenharmony_ci "Loop resync end.\n"); 69318c2ecf20Sopenharmony_ci } 69328c2ecf20Sopenharmony_ci 69338c2ecf20Sopenharmony_ci if (IS_QLAFX00(ha)) 69348c2ecf20Sopenharmony_ci goto intr_on_check; 69358c2ecf20Sopenharmony_ci 69368c2ecf20Sopenharmony_ci if (test_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags) && 69378c2ecf20Sopenharmony_ci atomic_read(&base_vha->loop_state) == LOOP_READY) { 69388c2ecf20Sopenharmony_ci clear_bit(NPIV_CONFIG_NEEDED, &base_vha->dpc_flags); 69398c2ecf20Sopenharmony_ci qla2xxx_flash_npiv_conf(base_vha); 69408c2ecf20Sopenharmony_ci } 69418c2ecf20Sopenharmony_ci 69428c2ecf20Sopenharmony_ciintr_on_check: 69438c2ecf20Sopenharmony_ci if (!ha->interrupts_on) 69448c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 69458c2ecf20Sopenharmony_ci 69468c2ecf20Sopenharmony_ci if (test_and_clear_bit(BEACON_BLINK_NEEDED, 69478c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 69488c2ecf20Sopenharmony_ci if (ha->beacon_blink_led == 1) 69498c2ecf20Sopenharmony_ci ha->isp_ops->beacon_blink(base_vha); 69508c2ecf20Sopenharmony_ci } 69518c2ecf20Sopenharmony_ci 69528c2ecf20Sopenharmony_ci /* qpair online check */ 69538c2ecf20Sopenharmony_ci if (test_and_clear_bit(QPAIR_ONLINE_CHECK_NEEDED, 69548c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 69558c2ecf20Sopenharmony_ci if (ha->flags.eeh_busy || 69568c2ecf20Sopenharmony_ci ha->flags.pci_channel_io_perm_failure) 69578c2ecf20Sopenharmony_ci online = 0; 69588c2ecf20Sopenharmony_ci else 69598c2ecf20Sopenharmony_ci online = 1; 69608c2ecf20Sopenharmony_ci 69618c2ecf20Sopenharmony_ci mutex_lock(&ha->mq_lock); 69628c2ecf20Sopenharmony_ci list_for_each_entry(qpair, &base_vha->qp_list, 69638c2ecf20Sopenharmony_ci qp_list_elem) 69648c2ecf20Sopenharmony_ci qpair->online = online; 69658c2ecf20Sopenharmony_ci mutex_unlock(&ha->mq_lock); 69668c2ecf20Sopenharmony_ci } 69678c2ecf20Sopenharmony_ci 69688c2ecf20Sopenharmony_ci if (test_and_clear_bit(SET_ZIO_THRESHOLD_NEEDED, 69698c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 69708c2ecf20Sopenharmony_ci u16 threshold = ha->nvme_last_rptd_aen + ha->last_zio_threshold; 69718c2ecf20Sopenharmony_ci 69728c2ecf20Sopenharmony_ci if (threshold > ha->orig_fw_xcb_count) 69738c2ecf20Sopenharmony_ci threshold = ha->orig_fw_xcb_count; 69748c2ecf20Sopenharmony_ci 69758c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0xffffff, 69768c2ecf20Sopenharmony_ci "SET ZIO Activity exchange threshold to %d.\n", 69778c2ecf20Sopenharmony_ci threshold); 69788c2ecf20Sopenharmony_ci if (qla27xx_set_zio_threshold(base_vha, threshold)) { 69798c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0xffffff, 69808c2ecf20Sopenharmony_ci "Unable to SET ZIO Activity exchange threshold to %d.\n", 69818c2ecf20Sopenharmony_ci threshold); 69828c2ecf20Sopenharmony_ci } 69838c2ecf20Sopenharmony_ci } 69848c2ecf20Sopenharmony_ci 69858c2ecf20Sopenharmony_ci if (!IS_QLAFX00(ha)) 69868c2ecf20Sopenharmony_ci qla2x00_do_dpc_all_vps(base_vha); 69878c2ecf20Sopenharmony_ci 69888c2ecf20Sopenharmony_ci if (test_and_clear_bit(N2N_LINK_RESET, 69898c2ecf20Sopenharmony_ci &base_vha->dpc_flags)) { 69908c2ecf20Sopenharmony_ci qla2x00_lip_reset(base_vha); 69918c2ecf20Sopenharmony_ci } 69928c2ecf20Sopenharmony_ci 69938c2ecf20Sopenharmony_ci ha->dpc_active = 0; 69948c2ecf20Sopenharmony_ciend_loop: 69958c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 69968c2ecf20Sopenharmony_ci } /* End of while(1) */ 69978c2ecf20Sopenharmony_ci __set_current_state(TASK_RUNNING); 69988c2ecf20Sopenharmony_ci 69998c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_dpc, base_vha, 0x4011, 70008c2ecf20Sopenharmony_ci "DPC handler exiting.\n"); 70018c2ecf20Sopenharmony_ci 70028c2ecf20Sopenharmony_ci /* 70038c2ecf20Sopenharmony_ci * Make sure that nobody tries to wake us up again. 70048c2ecf20Sopenharmony_ci */ 70058c2ecf20Sopenharmony_ci ha->dpc_active = 0; 70068c2ecf20Sopenharmony_ci 70078c2ecf20Sopenharmony_ci /* Cleanup any residual CTX SRBs. */ 70088c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); 70098c2ecf20Sopenharmony_ci 70108c2ecf20Sopenharmony_ci return 0; 70118c2ecf20Sopenharmony_ci} 70128c2ecf20Sopenharmony_ci 70138c2ecf20Sopenharmony_civoid 70148c2ecf20Sopenharmony_ciqla2xxx_wake_dpc(struct scsi_qla_host *vha) 70158c2ecf20Sopenharmony_ci{ 70168c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 70178c2ecf20Sopenharmony_ci struct task_struct *t = ha->dpc_thread; 70188c2ecf20Sopenharmony_ci 70198c2ecf20Sopenharmony_ci if (!test_bit(UNLOADING, &vha->dpc_flags) && t) 70208c2ecf20Sopenharmony_ci wake_up_process(t); 70218c2ecf20Sopenharmony_ci} 70228c2ecf20Sopenharmony_ci 70238c2ecf20Sopenharmony_ci/* 70248c2ecf20Sopenharmony_ci* qla2x00_rst_aen 70258c2ecf20Sopenharmony_ci* Processes asynchronous reset. 70268c2ecf20Sopenharmony_ci* 70278c2ecf20Sopenharmony_ci* Input: 70288c2ecf20Sopenharmony_ci* ha = adapter block pointer. 70298c2ecf20Sopenharmony_ci*/ 70308c2ecf20Sopenharmony_cistatic void 70318c2ecf20Sopenharmony_ciqla2x00_rst_aen(scsi_qla_host_t *vha) 70328c2ecf20Sopenharmony_ci{ 70338c2ecf20Sopenharmony_ci if (vha->flags.online && !vha->flags.reset_active && 70348c2ecf20Sopenharmony_ci !atomic_read(&vha->loop_down_timer) && 70358c2ecf20Sopenharmony_ci !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))) { 70368c2ecf20Sopenharmony_ci do { 70378c2ecf20Sopenharmony_ci clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags); 70388c2ecf20Sopenharmony_ci 70398c2ecf20Sopenharmony_ci /* 70408c2ecf20Sopenharmony_ci * Issue marker command only when we are going to start 70418c2ecf20Sopenharmony_ci * the I/O. 70428c2ecf20Sopenharmony_ci */ 70438c2ecf20Sopenharmony_ci vha->marker_needed = 1; 70448c2ecf20Sopenharmony_ci } while (!atomic_read(&vha->loop_down_timer) && 70458c2ecf20Sopenharmony_ci (test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags))); 70468c2ecf20Sopenharmony_ci } 70478c2ecf20Sopenharmony_ci} 70488c2ecf20Sopenharmony_ci 70498c2ecf20Sopenharmony_ci/************************************************************************** 70508c2ecf20Sopenharmony_ci* qla2x00_timer 70518c2ecf20Sopenharmony_ci* 70528c2ecf20Sopenharmony_ci* Description: 70538c2ecf20Sopenharmony_ci* One second timer 70548c2ecf20Sopenharmony_ci* 70558c2ecf20Sopenharmony_ci* Context: Interrupt 70568c2ecf20Sopenharmony_ci***************************************************************************/ 70578c2ecf20Sopenharmony_civoid 70588c2ecf20Sopenharmony_ciqla2x00_timer(struct timer_list *t) 70598c2ecf20Sopenharmony_ci{ 70608c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = from_timer(vha, t, timer); 70618c2ecf20Sopenharmony_ci unsigned long cpu_flags = 0; 70628c2ecf20Sopenharmony_ci int start_dpc = 0; 70638c2ecf20Sopenharmony_ci int index; 70648c2ecf20Sopenharmony_ci srb_t *sp; 70658c2ecf20Sopenharmony_ci uint16_t w; 70668c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 70678c2ecf20Sopenharmony_ci struct req_que *req; 70688c2ecf20Sopenharmony_ci 70698c2ecf20Sopenharmony_ci if (ha->flags.eeh_busy) { 70708c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_timer, vha, 0x6000, 70718c2ecf20Sopenharmony_ci "EEH = %d, restarting timer.\n", 70728c2ecf20Sopenharmony_ci ha->flags.eeh_busy); 70738c2ecf20Sopenharmony_ci qla2x00_restart_timer(vha, WATCH_INTERVAL); 70748c2ecf20Sopenharmony_ci return; 70758c2ecf20Sopenharmony_ci } 70768c2ecf20Sopenharmony_ci 70778c2ecf20Sopenharmony_ci /* 70788c2ecf20Sopenharmony_ci * Hardware read to raise pending EEH errors during mailbox waits. If 70798c2ecf20Sopenharmony_ci * the read returns -1 then disable the board. 70808c2ecf20Sopenharmony_ci */ 70818c2ecf20Sopenharmony_ci if (!pci_channel_offline(ha->pdev)) { 70828c2ecf20Sopenharmony_ci pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); 70838c2ecf20Sopenharmony_ci qla2x00_check_reg16_for_disconnect(vha, w); 70848c2ecf20Sopenharmony_ci } 70858c2ecf20Sopenharmony_ci 70868c2ecf20Sopenharmony_ci /* Make sure qla82xx_watchdog is run only for physical port */ 70878c2ecf20Sopenharmony_ci if (!vha->vp_idx && IS_P3P_TYPE(ha)) { 70888c2ecf20Sopenharmony_ci if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) 70898c2ecf20Sopenharmony_ci start_dpc++; 70908c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) 70918c2ecf20Sopenharmony_ci qla82xx_watchdog(vha); 70928c2ecf20Sopenharmony_ci else if (IS_QLA8044(ha)) 70938c2ecf20Sopenharmony_ci qla8044_watchdog(vha); 70948c2ecf20Sopenharmony_ci } 70958c2ecf20Sopenharmony_ci 70968c2ecf20Sopenharmony_ci if (!vha->vp_idx && IS_QLAFX00(ha)) 70978c2ecf20Sopenharmony_ci qlafx00_timer_routine(vha); 70988c2ecf20Sopenharmony_ci 70998c2ecf20Sopenharmony_ci /* Loop down handler. */ 71008c2ecf20Sopenharmony_ci if (atomic_read(&vha->loop_down_timer) > 0 && 71018c2ecf20Sopenharmony_ci !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) && 71028c2ecf20Sopenharmony_ci !(test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags)) 71038c2ecf20Sopenharmony_ci && vha->flags.online) { 71048c2ecf20Sopenharmony_ci 71058c2ecf20Sopenharmony_ci if (atomic_read(&vha->loop_down_timer) == 71068c2ecf20Sopenharmony_ci vha->loop_down_abort_time) { 71078c2ecf20Sopenharmony_ci 71088c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x6008, 71098c2ecf20Sopenharmony_ci "Loop down - aborting the queues before time expires.\n"); 71108c2ecf20Sopenharmony_ci 71118c2ecf20Sopenharmony_ci if (!IS_QLA2100(ha) && vha->link_down_timeout) 71128c2ecf20Sopenharmony_ci atomic_set(&vha->loop_state, LOOP_DEAD); 71138c2ecf20Sopenharmony_ci 71148c2ecf20Sopenharmony_ci /* 71158c2ecf20Sopenharmony_ci * Schedule an ISP abort to return any FCP2-device 71168c2ecf20Sopenharmony_ci * commands. 71178c2ecf20Sopenharmony_ci */ 71188c2ecf20Sopenharmony_ci /* NPIV - scan physical port only */ 71198c2ecf20Sopenharmony_ci if (!vha->vp_idx) { 71208c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, 71218c2ecf20Sopenharmony_ci cpu_flags); 71228c2ecf20Sopenharmony_ci req = ha->req_q_map[0]; 71238c2ecf20Sopenharmony_ci for (index = 1; 71248c2ecf20Sopenharmony_ci index < req->num_outstanding_cmds; 71258c2ecf20Sopenharmony_ci index++) { 71268c2ecf20Sopenharmony_ci fc_port_t *sfcp; 71278c2ecf20Sopenharmony_ci 71288c2ecf20Sopenharmony_ci sp = req->outstanding_cmds[index]; 71298c2ecf20Sopenharmony_ci if (!sp) 71308c2ecf20Sopenharmony_ci continue; 71318c2ecf20Sopenharmony_ci if (sp->cmd_type != TYPE_SRB) 71328c2ecf20Sopenharmony_ci continue; 71338c2ecf20Sopenharmony_ci if (sp->type != SRB_SCSI_CMD) 71348c2ecf20Sopenharmony_ci continue; 71358c2ecf20Sopenharmony_ci sfcp = sp->fcport; 71368c2ecf20Sopenharmony_ci if (!(sfcp->flags & FCF_FCP2_DEVICE)) 71378c2ecf20Sopenharmony_ci continue; 71388c2ecf20Sopenharmony_ci 71398c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) 71408c2ecf20Sopenharmony_ci set_bit(FCOE_CTX_RESET_NEEDED, 71418c2ecf20Sopenharmony_ci &vha->dpc_flags); 71428c2ecf20Sopenharmony_ci else 71438c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 71448c2ecf20Sopenharmony_ci &vha->dpc_flags); 71458c2ecf20Sopenharmony_ci break; 71468c2ecf20Sopenharmony_ci } 71478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, 71488c2ecf20Sopenharmony_ci cpu_flags); 71498c2ecf20Sopenharmony_ci } 71508c2ecf20Sopenharmony_ci start_dpc++; 71518c2ecf20Sopenharmony_ci } 71528c2ecf20Sopenharmony_ci 71538c2ecf20Sopenharmony_ci /* if the loop has been down for 4 minutes, reinit adapter */ 71548c2ecf20Sopenharmony_ci if (atomic_dec_and_test(&vha->loop_down_timer) != 0) { 71558c2ecf20Sopenharmony_ci if (!(vha->device_flags & DFLG_NO_CABLE) && !vha->vp_idx) { 71568c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x6009, 71578c2ecf20Sopenharmony_ci "Loop down - aborting ISP.\n"); 71588c2ecf20Sopenharmony_ci 71598c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) 71608c2ecf20Sopenharmony_ci set_bit(FCOE_CTX_RESET_NEEDED, 71618c2ecf20Sopenharmony_ci &vha->dpc_flags); 71628c2ecf20Sopenharmony_ci else 71638c2ecf20Sopenharmony_ci set_bit(ISP_ABORT_NEEDED, 71648c2ecf20Sopenharmony_ci &vha->dpc_flags); 71658c2ecf20Sopenharmony_ci } 71668c2ecf20Sopenharmony_ci } 71678c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_timer, vha, 0x600a, 71688c2ecf20Sopenharmony_ci "Loop down - seconds remaining %d.\n", 71698c2ecf20Sopenharmony_ci atomic_read(&vha->loop_down_timer)); 71708c2ecf20Sopenharmony_ci } 71718c2ecf20Sopenharmony_ci /* Check if beacon LED needs to be blinked for physical host only */ 71728c2ecf20Sopenharmony_ci if (!vha->vp_idx && (ha->beacon_blink_led == 1)) { 71738c2ecf20Sopenharmony_ci /* There is no beacon_blink function for ISP82xx */ 71748c2ecf20Sopenharmony_ci if (!IS_P3P_TYPE(ha)) { 71758c2ecf20Sopenharmony_ci set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags); 71768c2ecf20Sopenharmony_ci start_dpc++; 71778c2ecf20Sopenharmony_ci } 71788c2ecf20Sopenharmony_ci } 71798c2ecf20Sopenharmony_ci 71808c2ecf20Sopenharmony_ci /* Process any deferred work. */ 71818c2ecf20Sopenharmony_ci if (!list_empty(&vha->work_list)) { 71828c2ecf20Sopenharmony_ci unsigned long flags; 71838c2ecf20Sopenharmony_ci bool q = false; 71848c2ecf20Sopenharmony_ci 71858c2ecf20Sopenharmony_ci spin_lock_irqsave(&vha->work_lock, flags); 71868c2ecf20Sopenharmony_ci if (!test_and_set_bit(IOCB_WORK_ACTIVE, &vha->dpc_flags)) 71878c2ecf20Sopenharmony_ci q = true; 71888c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&vha->work_lock, flags); 71898c2ecf20Sopenharmony_ci if (q) 71908c2ecf20Sopenharmony_ci queue_work(vha->hw->wq, &vha->iocb_work); 71918c2ecf20Sopenharmony_ci } 71928c2ecf20Sopenharmony_ci 71938c2ecf20Sopenharmony_ci /* 71948c2ecf20Sopenharmony_ci * FC-NVME 71958c2ecf20Sopenharmony_ci * see if the active AEN count has changed from what was last reported. 71968c2ecf20Sopenharmony_ci */ 71978c2ecf20Sopenharmony_ci index = atomic_read(&ha->nvme_active_aen_cnt); 71988c2ecf20Sopenharmony_ci if (!vha->vp_idx && 71998c2ecf20Sopenharmony_ci (index != ha->nvme_last_rptd_aen) && 72008c2ecf20Sopenharmony_ci ha->zio_mode == QLA_ZIO_MODE_6 && 72018c2ecf20Sopenharmony_ci !ha->flags.host_shutting_down) { 72028c2ecf20Sopenharmony_ci ha->nvme_last_rptd_aen = atomic_read(&ha->nvme_active_aen_cnt); 72038c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x3002, 72048c2ecf20Sopenharmony_ci "nvme: Sched: Set ZIO exchange threshold to %d.\n", 72058c2ecf20Sopenharmony_ci ha->nvme_last_rptd_aen); 72068c2ecf20Sopenharmony_ci set_bit(SET_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags); 72078c2ecf20Sopenharmony_ci start_dpc++; 72088c2ecf20Sopenharmony_ci } 72098c2ecf20Sopenharmony_ci 72108c2ecf20Sopenharmony_ci if (!vha->vp_idx && 72118c2ecf20Sopenharmony_ci atomic_read(&ha->zio_threshold) != ha->last_zio_threshold && 72128c2ecf20Sopenharmony_ci IS_ZIO_THRESHOLD_CAPABLE(ha)) { 72138c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0x3002, 72148c2ecf20Sopenharmony_ci "Sched: Set ZIO exchange threshold to %d.\n", 72158c2ecf20Sopenharmony_ci ha->last_zio_threshold); 72168c2ecf20Sopenharmony_ci ha->last_zio_threshold = atomic_read(&ha->zio_threshold); 72178c2ecf20Sopenharmony_ci set_bit(SET_ZIO_THRESHOLD_NEEDED, &vha->dpc_flags); 72188c2ecf20Sopenharmony_ci start_dpc++; 72198c2ecf20Sopenharmony_ci } 72208c2ecf20Sopenharmony_ci 72218c2ecf20Sopenharmony_ci /* Schedule the DPC routine if needed */ 72228c2ecf20Sopenharmony_ci if ((test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) || 72238c2ecf20Sopenharmony_ci test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) || 72248c2ecf20Sopenharmony_ci test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags) || 72258c2ecf20Sopenharmony_ci start_dpc || 72268c2ecf20Sopenharmony_ci test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) || 72278c2ecf20Sopenharmony_ci test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags) || 72288c2ecf20Sopenharmony_ci test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags) || 72298c2ecf20Sopenharmony_ci test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags) || 72308c2ecf20Sopenharmony_ci test_bit(VP_DPC_NEEDED, &vha->dpc_flags) || 72318c2ecf20Sopenharmony_ci test_bit(RELOGIN_NEEDED, &vha->dpc_flags) || 72328c2ecf20Sopenharmony_ci test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags))) { 72338c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_timer, vha, 0x600b, 72348c2ecf20Sopenharmony_ci "isp_abort_needed=%d loop_resync_needed=%d " 72358c2ecf20Sopenharmony_ci "fcport_update_needed=%d start_dpc=%d " 72368c2ecf20Sopenharmony_ci "reset_marker_needed=%d", 72378c2ecf20Sopenharmony_ci test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags), 72388c2ecf20Sopenharmony_ci test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags), 72398c2ecf20Sopenharmony_ci test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags), 72408c2ecf20Sopenharmony_ci start_dpc, 72418c2ecf20Sopenharmony_ci test_bit(RESET_MARKER_NEEDED, &vha->dpc_flags)); 72428c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_timer, vha, 0x600c, 72438c2ecf20Sopenharmony_ci "beacon_blink_needed=%d isp_unrecoverable=%d " 72448c2ecf20Sopenharmony_ci "fcoe_ctx_reset_needed=%d vp_dpc_needed=%d " 72458c2ecf20Sopenharmony_ci "relogin_needed=%d, Process_purex_iocb=%d.\n", 72468c2ecf20Sopenharmony_ci test_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags), 72478c2ecf20Sopenharmony_ci test_bit(ISP_UNRECOVERABLE, &vha->dpc_flags), 72488c2ecf20Sopenharmony_ci test_bit(FCOE_CTX_RESET_NEEDED, &vha->dpc_flags), 72498c2ecf20Sopenharmony_ci test_bit(VP_DPC_NEEDED, &vha->dpc_flags), 72508c2ecf20Sopenharmony_ci test_bit(RELOGIN_NEEDED, &vha->dpc_flags), 72518c2ecf20Sopenharmony_ci test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)); 72528c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 72538c2ecf20Sopenharmony_ci } 72548c2ecf20Sopenharmony_ci 72558c2ecf20Sopenharmony_ci qla2x00_restart_timer(vha, WATCH_INTERVAL); 72568c2ecf20Sopenharmony_ci} 72578c2ecf20Sopenharmony_ci 72588c2ecf20Sopenharmony_ci/* Firmware interface routines. */ 72598c2ecf20Sopenharmony_ci 72608c2ecf20Sopenharmony_ci#define FW_ISP21XX 0 72618c2ecf20Sopenharmony_ci#define FW_ISP22XX 1 72628c2ecf20Sopenharmony_ci#define FW_ISP2300 2 72638c2ecf20Sopenharmony_ci#define FW_ISP2322 3 72648c2ecf20Sopenharmony_ci#define FW_ISP24XX 4 72658c2ecf20Sopenharmony_ci#define FW_ISP25XX 5 72668c2ecf20Sopenharmony_ci#define FW_ISP81XX 6 72678c2ecf20Sopenharmony_ci#define FW_ISP82XX 7 72688c2ecf20Sopenharmony_ci#define FW_ISP2031 8 72698c2ecf20Sopenharmony_ci#define FW_ISP8031 9 72708c2ecf20Sopenharmony_ci#define FW_ISP27XX 10 72718c2ecf20Sopenharmony_ci#define FW_ISP28XX 11 72728c2ecf20Sopenharmony_ci 72738c2ecf20Sopenharmony_ci#define FW_FILE_ISP21XX "ql2100_fw.bin" 72748c2ecf20Sopenharmony_ci#define FW_FILE_ISP22XX "ql2200_fw.bin" 72758c2ecf20Sopenharmony_ci#define FW_FILE_ISP2300 "ql2300_fw.bin" 72768c2ecf20Sopenharmony_ci#define FW_FILE_ISP2322 "ql2322_fw.bin" 72778c2ecf20Sopenharmony_ci#define FW_FILE_ISP24XX "ql2400_fw.bin" 72788c2ecf20Sopenharmony_ci#define FW_FILE_ISP25XX "ql2500_fw.bin" 72798c2ecf20Sopenharmony_ci#define FW_FILE_ISP81XX "ql8100_fw.bin" 72808c2ecf20Sopenharmony_ci#define FW_FILE_ISP82XX "ql8200_fw.bin" 72818c2ecf20Sopenharmony_ci#define FW_FILE_ISP2031 "ql2600_fw.bin" 72828c2ecf20Sopenharmony_ci#define FW_FILE_ISP8031 "ql8300_fw.bin" 72838c2ecf20Sopenharmony_ci#define FW_FILE_ISP27XX "ql2700_fw.bin" 72848c2ecf20Sopenharmony_ci#define FW_FILE_ISP28XX "ql2800_fw.bin" 72858c2ecf20Sopenharmony_ci 72868c2ecf20Sopenharmony_ci 72878c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(qla_fw_lock); 72888c2ecf20Sopenharmony_ci 72898c2ecf20Sopenharmony_cistatic struct fw_blob qla_fw_blobs[] = { 72908c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, }, 72918c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, }, 72928c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, }, 72938c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, }, 72948c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP24XX, }, 72958c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP25XX, }, 72968c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP81XX, }, 72978c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP82XX, }, 72988c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP2031, }, 72998c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP8031, }, 73008c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP27XX, }, 73018c2ecf20Sopenharmony_ci { .name = FW_FILE_ISP28XX, }, 73028c2ecf20Sopenharmony_ci { .name = NULL, }, 73038c2ecf20Sopenharmony_ci}; 73048c2ecf20Sopenharmony_ci 73058c2ecf20Sopenharmony_cistruct fw_blob * 73068c2ecf20Sopenharmony_ciqla2x00_request_firmware(scsi_qla_host_t *vha) 73078c2ecf20Sopenharmony_ci{ 73088c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 73098c2ecf20Sopenharmony_ci struct fw_blob *blob; 73108c2ecf20Sopenharmony_ci 73118c2ecf20Sopenharmony_ci if (IS_QLA2100(ha)) { 73128c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP21XX]; 73138c2ecf20Sopenharmony_ci } else if (IS_QLA2200(ha)) { 73148c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP22XX]; 73158c2ecf20Sopenharmony_ci } else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) { 73168c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP2300]; 73178c2ecf20Sopenharmony_ci } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) { 73188c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP2322]; 73198c2ecf20Sopenharmony_ci } else if (IS_QLA24XX_TYPE(ha)) { 73208c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP24XX]; 73218c2ecf20Sopenharmony_ci } else if (IS_QLA25XX(ha)) { 73228c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP25XX]; 73238c2ecf20Sopenharmony_ci } else if (IS_QLA81XX(ha)) { 73248c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP81XX]; 73258c2ecf20Sopenharmony_ci } else if (IS_QLA82XX(ha)) { 73268c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP82XX]; 73278c2ecf20Sopenharmony_ci } else if (IS_QLA2031(ha)) { 73288c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP2031]; 73298c2ecf20Sopenharmony_ci } else if (IS_QLA8031(ha)) { 73308c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP8031]; 73318c2ecf20Sopenharmony_ci } else if (IS_QLA27XX(ha)) { 73328c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP27XX]; 73338c2ecf20Sopenharmony_ci } else if (IS_QLA28XX(ha)) { 73348c2ecf20Sopenharmony_ci blob = &qla_fw_blobs[FW_ISP28XX]; 73358c2ecf20Sopenharmony_ci } else { 73368c2ecf20Sopenharmony_ci return NULL; 73378c2ecf20Sopenharmony_ci } 73388c2ecf20Sopenharmony_ci 73398c2ecf20Sopenharmony_ci if (!blob->name) 73408c2ecf20Sopenharmony_ci return NULL; 73418c2ecf20Sopenharmony_ci 73428c2ecf20Sopenharmony_ci mutex_lock(&qla_fw_lock); 73438c2ecf20Sopenharmony_ci if (blob->fw) 73448c2ecf20Sopenharmony_ci goto out; 73458c2ecf20Sopenharmony_ci 73468c2ecf20Sopenharmony_ci if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) { 73478c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x0063, 73488c2ecf20Sopenharmony_ci "Failed to load firmware image (%s).\n", blob->name); 73498c2ecf20Sopenharmony_ci blob->fw = NULL; 73508c2ecf20Sopenharmony_ci blob = NULL; 73518c2ecf20Sopenharmony_ci } 73528c2ecf20Sopenharmony_ci 73538c2ecf20Sopenharmony_ciout: 73548c2ecf20Sopenharmony_ci mutex_unlock(&qla_fw_lock); 73558c2ecf20Sopenharmony_ci return blob; 73568c2ecf20Sopenharmony_ci} 73578c2ecf20Sopenharmony_ci 73588c2ecf20Sopenharmony_cistatic void 73598c2ecf20Sopenharmony_ciqla2x00_release_firmware(void) 73608c2ecf20Sopenharmony_ci{ 73618c2ecf20Sopenharmony_ci struct fw_blob *blob; 73628c2ecf20Sopenharmony_ci 73638c2ecf20Sopenharmony_ci mutex_lock(&qla_fw_lock); 73648c2ecf20Sopenharmony_ci for (blob = qla_fw_blobs; blob->name; blob++) 73658c2ecf20Sopenharmony_ci release_firmware(blob->fw); 73668c2ecf20Sopenharmony_ci mutex_unlock(&qla_fw_lock); 73678c2ecf20Sopenharmony_ci} 73688c2ecf20Sopenharmony_ci 73698c2ecf20Sopenharmony_cistatic void qla_pci_error_cleanup(scsi_qla_host_t *vha) 73708c2ecf20Sopenharmony_ci{ 73718c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 73728c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); 73738c2ecf20Sopenharmony_ci struct qla_qpair *qpair = NULL; 73748c2ecf20Sopenharmony_ci struct scsi_qla_host *vp; 73758c2ecf20Sopenharmony_ci fc_port_t *fcport; 73768c2ecf20Sopenharmony_ci int i; 73778c2ecf20Sopenharmony_ci unsigned long flags; 73788c2ecf20Sopenharmony_ci 73798c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, vha, 0x9000, 73808c2ecf20Sopenharmony_ci "%s\n", __func__); 73818c2ecf20Sopenharmony_ci ha->chip_reset++; 73828c2ecf20Sopenharmony_ci 73838c2ecf20Sopenharmony_ci ha->base_qpair->chip_reset = ha->chip_reset; 73848c2ecf20Sopenharmony_ci for (i = 0; i < ha->max_qpairs; i++) { 73858c2ecf20Sopenharmony_ci if (ha->queue_pair_map[i]) 73868c2ecf20Sopenharmony_ci ha->queue_pair_map[i]->chip_reset = 73878c2ecf20Sopenharmony_ci ha->base_qpair->chip_reset; 73888c2ecf20Sopenharmony_ci } 73898c2ecf20Sopenharmony_ci 73908c2ecf20Sopenharmony_ci /* 73918c2ecf20Sopenharmony_ci * purge mailbox might take a while. Slot Reset/chip reset 73928c2ecf20Sopenharmony_ci * will take care of the purge 73938c2ecf20Sopenharmony_ci */ 73948c2ecf20Sopenharmony_ci 73958c2ecf20Sopenharmony_ci mutex_lock(&ha->mq_lock); 73968c2ecf20Sopenharmony_ci ha->base_qpair->online = 0; 73978c2ecf20Sopenharmony_ci list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem) 73988c2ecf20Sopenharmony_ci qpair->online = 0; 73998c2ecf20Sopenharmony_ci wmb(); 74008c2ecf20Sopenharmony_ci mutex_unlock(&ha->mq_lock); 74018c2ecf20Sopenharmony_ci 74028c2ecf20Sopenharmony_ci qla2x00_mark_all_devices_lost(vha); 74038c2ecf20Sopenharmony_ci 74048c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 74058c2ecf20Sopenharmony_ci list_for_each_entry(vp, &ha->vp_list, list) { 74068c2ecf20Sopenharmony_ci atomic_inc(&vp->vref_count); 74078c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 74088c2ecf20Sopenharmony_ci qla2x00_mark_all_devices_lost(vp); 74098c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 74108c2ecf20Sopenharmony_ci atomic_dec(&vp->vref_count); 74118c2ecf20Sopenharmony_ci } 74128c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 74138c2ecf20Sopenharmony_ci 74148c2ecf20Sopenharmony_ci /* Clear all async request states across all VPs. */ 74158c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vha->vp_fcports, list) 74168c2ecf20Sopenharmony_ci fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); 74178c2ecf20Sopenharmony_ci 74188c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 74198c2ecf20Sopenharmony_ci list_for_each_entry(vp, &ha->vp_list, list) { 74208c2ecf20Sopenharmony_ci atomic_inc(&vp->vref_count); 74218c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 74228c2ecf20Sopenharmony_ci list_for_each_entry(fcport, &vp->vp_fcports, list) 74238c2ecf20Sopenharmony_ci fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); 74248c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->vport_slock, flags); 74258c2ecf20Sopenharmony_ci atomic_dec(&vp->vref_count); 74268c2ecf20Sopenharmony_ci } 74278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->vport_slock, flags); 74288c2ecf20Sopenharmony_ci} 74298c2ecf20Sopenharmony_ci 74308c2ecf20Sopenharmony_ci 74318c2ecf20Sopenharmony_cistatic pci_ers_result_t 74328c2ecf20Sopenharmony_ciqla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) 74338c2ecf20Sopenharmony_ci{ 74348c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = pci_get_drvdata(pdev); 74358c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 74368c2ecf20Sopenharmony_ci pci_ers_result_t ret = PCI_ERS_RESULT_NEED_RESET; 74378c2ecf20Sopenharmony_ci 74388c2ecf20Sopenharmony_ci ql_log(ql_log_warn, vha, 0x9000, 74398c2ecf20Sopenharmony_ci "PCI error detected, state %x.\n", state); 74408c2ecf20Sopenharmony_ci ha->pci_error_state = QLA_PCI_ERR_DETECTED; 74418c2ecf20Sopenharmony_ci 74428c2ecf20Sopenharmony_ci if (!atomic_read(&pdev->enable_cnt)) { 74438c2ecf20Sopenharmony_ci ql_log(ql_log_info, vha, 0xffff, 74448c2ecf20Sopenharmony_ci "PCI device is disabled,state %x\n", state); 74458c2ecf20Sopenharmony_ci ret = PCI_ERS_RESULT_NEED_RESET; 74468c2ecf20Sopenharmony_ci goto out; 74478c2ecf20Sopenharmony_ci } 74488c2ecf20Sopenharmony_ci 74498c2ecf20Sopenharmony_ci switch (state) { 74508c2ecf20Sopenharmony_ci case pci_channel_io_normal: 74518c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 0; 74528c2ecf20Sopenharmony_ci if (ql2xmqsupport || ql2xnvmeenable) { 74538c2ecf20Sopenharmony_ci set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); 74548c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 74558c2ecf20Sopenharmony_ci } 74568c2ecf20Sopenharmony_ci ret = PCI_ERS_RESULT_CAN_RECOVER; 74578c2ecf20Sopenharmony_ci break; 74588c2ecf20Sopenharmony_ci case pci_channel_io_frozen: 74598c2ecf20Sopenharmony_ci qla_pci_set_eeh_busy(vha); 74608c2ecf20Sopenharmony_ci ret = PCI_ERS_RESULT_NEED_RESET; 74618c2ecf20Sopenharmony_ci break; 74628c2ecf20Sopenharmony_ci case pci_channel_io_perm_failure: 74638c2ecf20Sopenharmony_ci ha->flags.pci_channel_io_perm_failure = 1; 74648c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); 74658c2ecf20Sopenharmony_ci if (ql2xmqsupport || ql2xnvmeenable) { 74668c2ecf20Sopenharmony_ci set_bit(QPAIR_ONLINE_CHECK_NEEDED, &vha->dpc_flags); 74678c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(vha); 74688c2ecf20Sopenharmony_ci } 74698c2ecf20Sopenharmony_ci ret = PCI_ERS_RESULT_DISCONNECT; 74708c2ecf20Sopenharmony_ci } 74718c2ecf20Sopenharmony_ciout: 74728c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, vha, 0x600d, 74738c2ecf20Sopenharmony_ci "PCI error detected returning [%x].\n", ret); 74748c2ecf20Sopenharmony_ci return ret; 74758c2ecf20Sopenharmony_ci} 74768c2ecf20Sopenharmony_ci 74778c2ecf20Sopenharmony_cistatic pci_ers_result_t 74788c2ecf20Sopenharmony_ciqla2xxx_pci_mmio_enabled(struct pci_dev *pdev) 74798c2ecf20Sopenharmony_ci{ 74808c2ecf20Sopenharmony_ci int risc_paused = 0; 74818c2ecf20Sopenharmony_ci uint32_t stat; 74828c2ecf20Sopenharmony_ci unsigned long flags; 74838c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); 74848c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 74858c2ecf20Sopenharmony_ci struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 74868c2ecf20Sopenharmony_ci struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; 74878c2ecf20Sopenharmony_ci 74888c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x9000, 74898c2ecf20Sopenharmony_ci "mmio enabled\n"); 74908c2ecf20Sopenharmony_ci 74918c2ecf20Sopenharmony_ci ha->pci_error_state = QLA_PCI_MMIO_ENABLED; 74928c2ecf20Sopenharmony_ci if (IS_QLA82XX(ha)) 74938c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_RECOVERED; 74948c2ecf20Sopenharmony_ci 74958c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 74968c2ecf20Sopenharmony_ci if (IS_QLA2100(ha) || IS_QLA2200(ha)){ 74978c2ecf20Sopenharmony_ci stat = rd_reg_word(®->hccr); 74988c2ecf20Sopenharmony_ci if (stat & HCCR_RISC_PAUSE) 74998c2ecf20Sopenharmony_ci risc_paused = 1; 75008c2ecf20Sopenharmony_ci } else if (IS_QLA23XX(ha)) { 75018c2ecf20Sopenharmony_ci stat = rd_reg_dword(®->u.isp2300.host_status); 75028c2ecf20Sopenharmony_ci if (stat & HSR_RISC_PAUSED) 75038c2ecf20Sopenharmony_ci risc_paused = 1; 75048c2ecf20Sopenharmony_ci } else if (IS_FWI2_CAPABLE(ha)) { 75058c2ecf20Sopenharmony_ci stat = rd_reg_dword(®24->host_status); 75068c2ecf20Sopenharmony_ci if (stat & HSRX_RISC_PAUSED) 75078c2ecf20Sopenharmony_ci risc_paused = 1; 75088c2ecf20Sopenharmony_ci } 75098c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 75108c2ecf20Sopenharmony_ci 75118c2ecf20Sopenharmony_ci if (risc_paused) { 75128c2ecf20Sopenharmony_ci ql_log(ql_log_info, base_vha, 0x9003, 75138c2ecf20Sopenharmony_ci "RISC paused -- mmio_enabled, Dumping firmware.\n"); 75148c2ecf20Sopenharmony_ci qla2xxx_dump_fw(base_vha); 75158c2ecf20Sopenharmony_ci } 75168c2ecf20Sopenharmony_ci /* set PCI_ERS_RESULT_NEED_RESET to trigger call to qla2xxx_pci_slot_reset */ 75178c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, base_vha, 0x600d, 75188c2ecf20Sopenharmony_ci "mmio enabled returning.\n"); 75198c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NEED_RESET; 75208c2ecf20Sopenharmony_ci} 75218c2ecf20Sopenharmony_ci 75228c2ecf20Sopenharmony_cistatic pci_ers_result_t 75238c2ecf20Sopenharmony_ciqla2xxx_pci_slot_reset(struct pci_dev *pdev) 75248c2ecf20Sopenharmony_ci{ 75258c2ecf20Sopenharmony_ci pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; 75268c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); 75278c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 75288c2ecf20Sopenharmony_ci int rc; 75298c2ecf20Sopenharmony_ci struct qla_qpair *qpair = NULL; 75308c2ecf20Sopenharmony_ci 75318c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x9004, 75328c2ecf20Sopenharmony_ci "Slot Reset.\n"); 75338c2ecf20Sopenharmony_ci 75348c2ecf20Sopenharmony_ci ha->pci_error_state = QLA_PCI_SLOT_RESET; 75358c2ecf20Sopenharmony_ci /* Workaround: qla2xxx driver which access hardware earlier 75368c2ecf20Sopenharmony_ci * needs error state to be pci_channel_io_online. 75378c2ecf20Sopenharmony_ci * Otherwise mailbox command timesout. 75388c2ecf20Sopenharmony_ci */ 75398c2ecf20Sopenharmony_ci pdev->error_state = pci_channel_io_normal; 75408c2ecf20Sopenharmony_ci 75418c2ecf20Sopenharmony_ci pci_restore_state(pdev); 75428c2ecf20Sopenharmony_ci 75438c2ecf20Sopenharmony_ci /* pci_restore_state() clears the saved_state flag of the device 75448c2ecf20Sopenharmony_ci * save restored state which resets saved_state flag 75458c2ecf20Sopenharmony_ci */ 75468c2ecf20Sopenharmony_ci pci_save_state(pdev); 75478c2ecf20Sopenharmony_ci 75488c2ecf20Sopenharmony_ci if (ha->mem_only) 75498c2ecf20Sopenharmony_ci rc = pci_enable_device_mem(pdev); 75508c2ecf20Sopenharmony_ci else 75518c2ecf20Sopenharmony_ci rc = pci_enable_device(pdev); 75528c2ecf20Sopenharmony_ci 75538c2ecf20Sopenharmony_ci if (rc) { 75548c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x9005, 75558c2ecf20Sopenharmony_ci "Can't re-enable PCI device after reset.\n"); 75568c2ecf20Sopenharmony_ci goto exit_slot_reset; 75578c2ecf20Sopenharmony_ci } 75588c2ecf20Sopenharmony_ci 75598c2ecf20Sopenharmony_ci 75608c2ecf20Sopenharmony_ci if (ha->isp_ops->pci_config(base_vha)) 75618c2ecf20Sopenharmony_ci goto exit_slot_reset; 75628c2ecf20Sopenharmony_ci 75638c2ecf20Sopenharmony_ci mutex_lock(&ha->mq_lock); 75648c2ecf20Sopenharmony_ci list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem) 75658c2ecf20Sopenharmony_ci qpair->online = 1; 75668c2ecf20Sopenharmony_ci mutex_unlock(&ha->mq_lock); 75678c2ecf20Sopenharmony_ci 75688c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 0; 75698c2ecf20Sopenharmony_ci base_vha->flags.online = 1; 75708c2ecf20Sopenharmony_ci set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 75718c2ecf20Sopenharmony_ci ha->isp_ops->abort_isp(base_vha); 75728c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 75738c2ecf20Sopenharmony_ci 75748c2ecf20Sopenharmony_ci if (qla2x00_isp_reg_stat(ha)) { 75758c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 1; 75768c2ecf20Sopenharmony_ci qla_pci_error_cleanup(base_vha); 75778c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x9005, 75788c2ecf20Sopenharmony_ci "Device unable to recover from PCI error.\n"); 75798c2ecf20Sopenharmony_ci } else { 75808c2ecf20Sopenharmony_ci ret = PCI_ERS_RESULT_RECOVERED; 75818c2ecf20Sopenharmony_ci } 75828c2ecf20Sopenharmony_ci 75838c2ecf20Sopenharmony_ciexit_slot_reset: 75848c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, base_vha, 0x900e, 75858c2ecf20Sopenharmony_ci "Slot Reset returning %x.\n", ret); 75868c2ecf20Sopenharmony_ci 75878c2ecf20Sopenharmony_ci return ret; 75888c2ecf20Sopenharmony_ci} 75898c2ecf20Sopenharmony_ci 75908c2ecf20Sopenharmony_cistatic void 75918c2ecf20Sopenharmony_ciqla2xxx_pci_resume(struct pci_dev *pdev) 75928c2ecf20Sopenharmony_ci{ 75938c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); 75948c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 75958c2ecf20Sopenharmony_ci int ret; 75968c2ecf20Sopenharmony_ci 75978c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0x900f, 75988c2ecf20Sopenharmony_ci "Pci Resume.\n"); 75998c2ecf20Sopenharmony_ci 76008c2ecf20Sopenharmony_ci 76018c2ecf20Sopenharmony_ci ret = qla2x00_wait_for_hba_online(base_vha); 76028c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 76038c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, base_vha, 0x9002, 76048c2ecf20Sopenharmony_ci "The device failed to resume I/O from slot/link_reset.\n"); 76058c2ecf20Sopenharmony_ci } 76068c2ecf20Sopenharmony_ci ha->pci_error_state = QLA_PCI_RESUME; 76078c2ecf20Sopenharmony_ci ql_dbg(ql_dbg_aer, base_vha, 0x600d, 76088c2ecf20Sopenharmony_ci "Pci Resume returning.\n"); 76098c2ecf20Sopenharmony_ci} 76108c2ecf20Sopenharmony_ci 76118c2ecf20Sopenharmony_civoid qla_pci_set_eeh_busy(struct scsi_qla_host *vha) 76128c2ecf20Sopenharmony_ci{ 76138c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 76148c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 76158c2ecf20Sopenharmony_ci bool do_cleanup = false; 76168c2ecf20Sopenharmony_ci unsigned long flags; 76178c2ecf20Sopenharmony_ci 76188c2ecf20Sopenharmony_ci if (ha->flags.eeh_busy) 76198c2ecf20Sopenharmony_ci return; 76208c2ecf20Sopenharmony_ci 76218c2ecf20Sopenharmony_ci spin_lock_irqsave(&base_vha->work_lock, flags); 76228c2ecf20Sopenharmony_ci if (!ha->flags.eeh_busy) { 76238c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 1; 76248c2ecf20Sopenharmony_ci do_cleanup = true; 76258c2ecf20Sopenharmony_ci } 76268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&base_vha->work_lock, flags); 76278c2ecf20Sopenharmony_ci 76288c2ecf20Sopenharmony_ci if (do_cleanup) 76298c2ecf20Sopenharmony_ci qla_pci_error_cleanup(base_vha); 76308c2ecf20Sopenharmony_ci} 76318c2ecf20Sopenharmony_ci 76328c2ecf20Sopenharmony_ci/* 76338c2ecf20Sopenharmony_ci * this routine will schedule a task to pause IO from interrupt context 76348c2ecf20Sopenharmony_ci * if caller sees a PCIE error event (register read = 0xf's) 76358c2ecf20Sopenharmony_ci */ 76368c2ecf20Sopenharmony_civoid qla_schedule_eeh_work(struct scsi_qla_host *vha) 76378c2ecf20Sopenharmony_ci{ 76388c2ecf20Sopenharmony_ci struct qla_hw_data *ha = vha->hw; 76398c2ecf20Sopenharmony_ci struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 76408c2ecf20Sopenharmony_ci 76418c2ecf20Sopenharmony_ci if (ha->flags.eeh_busy) 76428c2ecf20Sopenharmony_ci return; 76438c2ecf20Sopenharmony_ci 76448c2ecf20Sopenharmony_ci set_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags); 76458c2ecf20Sopenharmony_ci qla2xxx_wake_dpc(base_vha); 76468c2ecf20Sopenharmony_ci} 76478c2ecf20Sopenharmony_ci 76488c2ecf20Sopenharmony_cistatic void 76498c2ecf20Sopenharmony_ciqla_pci_reset_prepare(struct pci_dev *pdev) 76508c2ecf20Sopenharmony_ci{ 76518c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); 76528c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 76538c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 76548c2ecf20Sopenharmony_ci 76558c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xffff, 76568c2ecf20Sopenharmony_ci "%s.\n", __func__); 76578c2ecf20Sopenharmony_ci 76588c2ecf20Sopenharmony_ci /* 76598c2ecf20Sopenharmony_ci * PCI FLR/function reset is about to reset the 76608c2ecf20Sopenharmony_ci * slot. Stop the chip to stop all DMA access. 76618c2ecf20Sopenharmony_ci * It is assumed that pci_reset_done will be called 76628c2ecf20Sopenharmony_ci * after FLR to resume Chip operation. 76638c2ecf20Sopenharmony_ci */ 76648c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 1; 76658c2ecf20Sopenharmony_ci mutex_lock(&ha->mq_lock); 76668c2ecf20Sopenharmony_ci list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem) 76678c2ecf20Sopenharmony_ci qpair->online = 0; 76688c2ecf20Sopenharmony_ci mutex_unlock(&ha->mq_lock); 76698c2ecf20Sopenharmony_ci 76708c2ecf20Sopenharmony_ci set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 76718c2ecf20Sopenharmony_ci qla2x00_abort_isp_cleanup(base_vha); 76728c2ecf20Sopenharmony_ci qla2x00_abort_all_cmds(base_vha, DID_RESET << 16); 76738c2ecf20Sopenharmony_ci} 76748c2ecf20Sopenharmony_ci 76758c2ecf20Sopenharmony_cistatic void 76768c2ecf20Sopenharmony_ciqla_pci_reset_done(struct pci_dev *pdev) 76778c2ecf20Sopenharmony_ci{ 76788c2ecf20Sopenharmony_ci scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); 76798c2ecf20Sopenharmony_ci struct qla_hw_data *ha = base_vha->hw; 76808c2ecf20Sopenharmony_ci struct qla_qpair *qpair; 76818c2ecf20Sopenharmony_ci 76828c2ecf20Sopenharmony_ci ql_log(ql_log_warn, base_vha, 0xffff, 76838c2ecf20Sopenharmony_ci "%s.\n", __func__); 76848c2ecf20Sopenharmony_ci 76858c2ecf20Sopenharmony_ci /* 76868c2ecf20Sopenharmony_ci * FLR just completed by PCI layer. Resume adapter 76878c2ecf20Sopenharmony_ci */ 76888c2ecf20Sopenharmony_ci ha->flags.eeh_busy = 0; 76898c2ecf20Sopenharmony_ci mutex_lock(&ha->mq_lock); 76908c2ecf20Sopenharmony_ci list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem) 76918c2ecf20Sopenharmony_ci qpair->online = 1; 76928c2ecf20Sopenharmony_ci mutex_unlock(&ha->mq_lock); 76938c2ecf20Sopenharmony_ci 76948c2ecf20Sopenharmony_ci base_vha->flags.online = 1; 76958c2ecf20Sopenharmony_ci ha->isp_ops->abort_isp(base_vha); 76968c2ecf20Sopenharmony_ci clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 76978c2ecf20Sopenharmony_ci} 76988c2ecf20Sopenharmony_ci 76998c2ecf20Sopenharmony_cistatic int qla2xxx_map_queues(struct Scsi_Host *shost) 77008c2ecf20Sopenharmony_ci{ 77018c2ecf20Sopenharmony_ci int rc; 77028c2ecf20Sopenharmony_ci scsi_qla_host_t *vha = (scsi_qla_host_t *)shost->hostdata; 77038c2ecf20Sopenharmony_ci struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT]; 77048c2ecf20Sopenharmony_ci 77058c2ecf20Sopenharmony_ci if (USER_CTRL_IRQ(vha->hw) || !vha->hw->mqiobase) 77068c2ecf20Sopenharmony_ci rc = blk_mq_map_queues(qmap); 77078c2ecf20Sopenharmony_ci else 77088c2ecf20Sopenharmony_ci rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, vha->irq_offset); 77098c2ecf20Sopenharmony_ci return rc; 77108c2ecf20Sopenharmony_ci} 77118c2ecf20Sopenharmony_ci 77128c2ecf20Sopenharmony_cistruct scsi_host_template qla2xxx_driver_template = { 77138c2ecf20Sopenharmony_ci .module = THIS_MODULE, 77148c2ecf20Sopenharmony_ci .name = QLA2XXX_DRIVER_NAME, 77158c2ecf20Sopenharmony_ci .queuecommand = qla2xxx_queuecommand, 77168c2ecf20Sopenharmony_ci 77178c2ecf20Sopenharmony_ci .eh_timed_out = fc_eh_timed_out, 77188c2ecf20Sopenharmony_ci .eh_abort_handler = qla2xxx_eh_abort, 77198c2ecf20Sopenharmony_ci .eh_device_reset_handler = qla2xxx_eh_device_reset, 77208c2ecf20Sopenharmony_ci .eh_target_reset_handler = qla2xxx_eh_target_reset, 77218c2ecf20Sopenharmony_ci .eh_bus_reset_handler = qla2xxx_eh_bus_reset, 77228c2ecf20Sopenharmony_ci .eh_host_reset_handler = qla2xxx_eh_host_reset, 77238c2ecf20Sopenharmony_ci 77248c2ecf20Sopenharmony_ci .slave_configure = qla2xxx_slave_configure, 77258c2ecf20Sopenharmony_ci 77268c2ecf20Sopenharmony_ci .slave_alloc = qla2xxx_slave_alloc, 77278c2ecf20Sopenharmony_ci .slave_destroy = qla2xxx_slave_destroy, 77288c2ecf20Sopenharmony_ci .scan_finished = qla2xxx_scan_finished, 77298c2ecf20Sopenharmony_ci .scan_start = qla2xxx_scan_start, 77308c2ecf20Sopenharmony_ci .change_queue_depth = scsi_change_queue_depth, 77318c2ecf20Sopenharmony_ci .map_queues = qla2xxx_map_queues, 77328c2ecf20Sopenharmony_ci .this_id = -1, 77338c2ecf20Sopenharmony_ci .cmd_per_lun = 3, 77348c2ecf20Sopenharmony_ci .sg_tablesize = SG_ALL, 77358c2ecf20Sopenharmony_ci 77368c2ecf20Sopenharmony_ci .max_sectors = 0xFFFF, 77378c2ecf20Sopenharmony_ci .shost_attrs = qla2x00_host_attrs, 77388c2ecf20Sopenharmony_ci 77398c2ecf20Sopenharmony_ci .supported_mode = MODE_INITIATOR, 77408c2ecf20Sopenharmony_ci .track_queue_depth = 1, 77418c2ecf20Sopenharmony_ci .cmd_size = sizeof(srb_t), 77428c2ecf20Sopenharmony_ci}; 77438c2ecf20Sopenharmony_ci 77448c2ecf20Sopenharmony_cistatic const struct pci_error_handlers qla2xxx_err_handler = { 77458c2ecf20Sopenharmony_ci .error_detected = qla2xxx_pci_error_detected, 77468c2ecf20Sopenharmony_ci .mmio_enabled = qla2xxx_pci_mmio_enabled, 77478c2ecf20Sopenharmony_ci .slot_reset = qla2xxx_pci_slot_reset, 77488c2ecf20Sopenharmony_ci .resume = qla2xxx_pci_resume, 77498c2ecf20Sopenharmony_ci .reset_prepare = qla_pci_reset_prepare, 77508c2ecf20Sopenharmony_ci .reset_done = qla_pci_reset_done, 77518c2ecf20Sopenharmony_ci}; 77528c2ecf20Sopenharmony_ci 77538c2ecf20Sopenharmony_cistatic struct pci_device_id qla2xxx_pci_tbl[] = { 77548c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, 77558c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, 77568c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300) }, 77578c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312) }, 77588c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322) }, 77598c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312) }, 77608c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) }, 77618c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) }, 77628c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) }, 77638c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8432) }, 77648c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) }, 77658c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) }, 77668c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2532) }, 77678c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2031) }, 77688c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8001) }, 77698c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8021) }, 77708c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8031) }, 77718c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISPF001) }, 77728c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP8044) }, 77738c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2071) }, 77748c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2271) }, 77758c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2261) }, 77768c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2061) }, 77778c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2081) }, 77788c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2281) }, 77798c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2089) }, 77808c2ecf20Sopenharmony_ci { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2289) }, 77818c2ecf20Sopenharmony_ci { 0 }, 77828c2ecf20Sopenharmony_ci}; 77838c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl); 77848c2ecf20Sopenharmony_ci 77858c2ecf20Sopenharmony_cistatic struct pci_driver qla2xxx_pci_driver = { 77868c2ecf20Sopenharmony_ci .name = QLA2XXX_DRIVER_NAME, 77878c2ecf20Sopenharmony_ci .driver = { 77888c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 77898c2ecf20Sopenharmony_ci }, 77908c2ecf20Sopenharmony_ci .id_table = qla2xxx_pci_tbl, 77918c2ecf20Sopenharmony_ci .probe = qla2x00_probe_one, 77928c2ecf20Sopenharmony_ci .remove = qla2x00_remove_one, 77938c2ecf20Sopenharmony_ci .shutdown = qla2x00_shutdown, 77948c2ecf20Sopenharmony_ci .err_handler = &qla2xxx_err_handler, 77958c2ecf20Sopenharmony_ci}; 77968c2ecf20Sopenharmony_ci 77978c2ecf20Sopenharmony_cistatic const struct file_operations apidev_fops = { 77988c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 77998c2ecf20Sopenharmony_ci .llseek = noop_llseek, 78008c2ecf20Sopenharmony_ci}; 78018c2ecf20Sopenharmony_ci 78028c2ecf20Sopenharmony_ci/** 78038c2ecf20Sopenharmony_ci * qla2x00_module_init - Module initialization. 78048c2ecf20Sopenharmony_ci **/ 78058c2ecf20Sopenharmony_cistatic int __init 78068c2ecf20Sopenharmony_ciqla2x00_module_init(void) 78078c2ecf20Sopenharmony_ci{ 78088c2ecf20Sopenharmony_ci int ret = 0; 78098c2ecf20Sopenharmony_ci 78108c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(cmd_a64_entry_t) != 64); 78118c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(cmd_entry_t) != 64); 78128c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(cont_a64_entry_t) != 64); 78138c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(cont_entry_t) != 64); 78148c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(init_cb_t) != 96); 78158c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(mrk_entry_t) != 64); 78168c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(ms_iocb_entry_t) != 64); 78178c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(request_t) != 64); 78188c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct abort_entry_24xx) != 64); 78198c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct abort_iocb_entry_fx00) != 64); 78208c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct abts_entry_24xx) != 64); 78218c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct access_chip_84xx) != 64); 78228c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct access_chip_rsp_84xx) != 64); 78238c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct cmd_bidir) != 64); 78248c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct cmd_nvme) != 64); 78258c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct cmd_type_6) != 64); 78268c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct cmd_type_7) != 64); 78278c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct cmd_type_7_fx00) != 64); 78288c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct cmd_type_crc_2) != 64); 78298c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_entry_24xx) != 64); 78308c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_fdmi1_hba_attributes) != 2344); 78318c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_fdmi2_hba_attributes) != 4424); 78328c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_fdmi2_port_attributes) != 4164); 78338c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_fdmi_hba_attr) != 260); 78348c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_fdmi_port_attr) != 260); 78358c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ct_rsp_hdr) != 16); 78368c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64); 78378c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct device_reg_24xx) != 256); 78388c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct device_reg_25xxmq) != 24); 78398c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct device_reg_2xxx) != 256); 78408c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct device_reg_82xx) != 1288); 78418c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct device_reg_fx00) != 216); 78428c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct els_entry_24xx) != 64); 78438c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct els_sts_entry_24xx) != 64); 78448c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct fxdisc_entry_fx00) != 64); 78458c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct imm_ntfy_from_isp) != 64); 78468c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct init_cb_24xx) != 128); 78478c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct init_cb_81xx) != 128); 78488c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct logio_entry_24xx) != 64); 78498c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct mbx_entry) != 64); 78508c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct mid_init_cb_24xx) != 5252); 78518c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct mrk_entry_24xx) != 64); 78528c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct nvram_24xx) != 512); 78538c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct nvram_81xx) != 512); 78548c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct pt_ls4_request) != 64); 78558c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct pt_ls4_rx_unsol) != 64); 78568c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct purex_entry_24xx) != 64); 78578c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2100_fw_dump) != 123634); 78588c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2300_fw_dump) != 136100); 78598c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla24xx_fw_dump) != 37976); 78608c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla25xx_fw_dump) != 39228); 78618c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2xxx_fce_chain) != 52); 78628c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2xxx_fw_dump) != 136172); 78638c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2xxx_mq_chain) != 524); 78648c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2xxx_mqueue_chain) != 8); 78658c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2xxx_mqueue_header) != 12); 78668c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla2xxx_offld_chain) != 24); 78678c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla81xx_fw_dump) != 39420); 78688c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla82xx_uri_data_desc) != 28); 78698c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla82xx_uri_table_desc) != 32); 78708c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla83xx_fw_dump) != 51196); 78718c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla_fcp_prio_cfg) != FCP_PRIO_CFG_SIZE); 78728c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla_fdt_layout) != 128); 78738c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla_flt_header) != 8); 78748c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla_flt_region) != 16); 78758c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla_npiv_entry) != 24); 78768c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct qla_npiv_header) != 16); 78778c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct rdp_rsp_payload) != 336); 78788c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct sns_cmd_pkt) != 2064); 78798c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct sts_entry_24xx) != 64); 78808c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct tsk_mgmt_entry) != 64); 78818c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct tsk_mgmt_entry_fx00) != 64); 78828c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct verify_chip_entry_84xx) != 64); 78838c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct verify_chip_rsp_84xx) != 52); 78848c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct vf_evfp_entry_24xx) != 56); 78858c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct vp_config_entry_24xx) != 64); 78868c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct vp_ctrl_entry_24xx) != 64); 78878c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct vp_rpt_id_entry_24xx) != 64); 78888c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(sts21_entry_t) != 64); 78898c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(sts22_entry_t) != 64); 78908c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(sts_cont_entry_t) != 64); 78918c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(sts_entry_t) != 64); 78928c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(sw_info_t) != 32); 78938c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(target_id_t) != 2); 78948c2ecf20Sopenharmony_ci 78958c2ecf20Sopenharmony_ci /* Allocate cache for SRBs. */ 78968c2ecf20Sopenharmony_ci srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0, 78978c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL); 78988c2ecf20Sopenharmony_ci if (srb_cachep == NULL) { 78998c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, NULL, 0x0001, 79008c2ecf20Sopenharmony_ci "Unable to allocate SRB cache...Failing load!.\n"); 79018c2ecf20Sopenharmony_ci return -ENOMEM; 79028c2ecf20Sopenharmony_ci } 79038c2ecf20Sopenharmony_ci 79048c2ecf20Sopenharmony_ci /* Initialize target kmem_cache and mem_pools */ 79058c2ecf20Sopenharmony_ci ret = qlt_init(); 79068c2ecf20Sopenharmony_ci if (ret < 0) { 79078c2ecf20Sopenharmony_ci goto destroy_cache; 79088c2ecf20Sopenharmony_ci } else if (ret > 0) { 79098c2ecf20Sopenharmony_ci /* 79108c2ecf20Sopenharmony_ci * If initiator mode is explictly disabled by qlt_init(), 79118c2ecf20Sopenharmony_ci * prevent scsi_transport_fc.c:fc_scsi_scan_rport() from 79128c2ecf20Sopenharmony_ci * performing scsi_scan_target() during LOOP UP event. 79138c2ecf20Sopenharmony_ci */ 79148c2ecf20Sopenharmony_ci qla2xxx_transport_functions.disable_target_scan = 1; 79158c2ecf20Sopenharmony_ci qla2xxx_transport_vport_functions.disable_target_scan = 1; 79168c2ecf20Sopenharmony_ci } 79178c2ecf20Sopenharmony_ci 79188c2ecf20Sopenharmony_ci /* Derive version string. */ 79198c2ecf20Sopenharmony_ci strcpy(qla2x00_version_str, QLA2XXX_VERSION); 79208c2ecf20Sopenharmony_ci if (ql2xextended_error_logging) 79218c2ecf20Sopenharmony_ci strcat(qla2x00_version_str, "-debug"); 79228c2ecf20Sopenharmony_ci if (ql2xextended_error_logging == 1) 79238c2ecf20Sopenharmony_ci ql2xextended_error_logging = QL_DBG_DEFAULT1_MASK; 79248c2ecf20Sopenharmony_ci 79258c2ecf20Sopenharmony_ci if (ql2x_ini_mode == QLA2XXX_INI_MODE_DUAL) 79268c2ecf20Sopenharmony_ci qla_insert_tgt_attrs(); 79278c2ecf20Sopenharmony_ci 79288c2ecf20Sopenharmony_ci qla2xxx_transport_template = 79298c2ecf20Sopenharmony_ci fc_attach_transport(&qla2xxx_transport_functions); 79308c2ecf20Sopenharmony_ci if (!qla2xxx_transport_template) { 79318c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, NULL, 0x0002, 79328c2ecf20Sopenharmony_ci "fc_attach_transport failed...Failing load!.\n"); 79338c2ecf20Sopenharmony_ci ret = -ENODEV; 79348c2ecf20Sopenharmony_ci goto qlt_exit; 79358c2ecf20Sopenharmony_ci } 79368c2ecf20Sopenharmony_ci 79378c2ecf20Sopenharmony_ci apidev_major = register_chrdev(0, QLA2XXX_APIDEV, &apidev_fops); 79388c2ecf20Sopenharmony_ci if (apidev_major < 0) { 79398c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, NULL, 0x0003, 79408c2ecf20Sopenharmony_ci "Unable to register char device %s.\n", QLA2XXX_APIDEV); 79418c2ecf20Sopenharmony_ci } 79428c2ecf20Sopenharmony_ci 79438c2ecf20Sopenharmony_ci qla2xxx_transport_vport_template = 79448c2ecf20Sopenharmony_ci fc_attach_transport(&qla2xxx_transport_vport_functions); 79458c2ecf20Sopenharmony_ci if (!qla2xxx_transport_vport_template) { 79468c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, NULL, 0x0004, 79478c2ecf20Sopenharmony_ci "fc_attach_transport vport failed...Failing load!.\n"); 79488c2ecf20Sopenharmony_ci ret = -ENODEV; 79498c2ecf20Sopenharmony_ci goto unreg_chrdev; 79508c2ecf20Sopenharmony_ci } 79518c2ecf20Sopenharmony_ci ql_log(ql_log_info, NULL, 0x0005, 79528c2ecf20Sopenharmony_ci "QLogic Fibre Channel HBA Driver: %s.\n", 79538c2ecf20Sopenharmony_ci qla2x00_version_str); 79548c2ecf20Sopenharmony_ci ret = pci_register_driver(&qla2xxx_pci_driver); 79558c2ecf20Sopenharmony_ci if (ret) { 79568c2ecf20Sopenharmony_ci ql_log(ql_log_fatal, NULL, 0x0006, 79578c2ecf20Sopenharmony_ci "pci_register_driver failed...ret=%d Failing load!.\n", 79588c2ecf20Sopenharmony_ci ret); 79598c2ecf20Sopenharmony_ci goto release_vport_transport; 79608c2ecf20Sopenharmony_ci } 79618c2ecf20Sopenharmony_ci return ret; 79628c2ecf20Sopenharmony_ci 79638c2ecf20Sopenharmony_cirelease_vport_transport: 79648c2ecf20Sopenharmony_ci fc_release_transport(qla2xxx_transport_vport_template); 79658c2ecf20Sopenharmony_ci 79668c2ecf20Sopenharmony_ciunreg_chrdev: 79678c2ecf20Sopenharmony_ci if (apidev_major >= 0) 79688c2ecf20Sopenharmony_ci unregister_chrdev(apidev_major, QLA2XXX_APIDEV); 79698c2ecf20Sopenharmony_ci fc_release_transport(qla2xxx_transport_template); 79708c2ecf20Sopenharmony_ci 79718c2ecf20Sopenharmony_ciqlt_exit: 79728c2ecf20Sopenharmony_ci qlt_exit(); 79738c2ecf20Sopenharmony_ci 79748c2ecf20Sopenharmony_cidestroy_cache: 79758c2ecf20Sopenharmony_ci kmem_cache_destroy(srb_cachep); 79768c2ecf20Sopenharmony_ci return ret; 79778c2ecf20Sopenharmony_ci} 79788c2ecf20Sopenharmony_ci 79798c2ecf20Sopenharmony_ci/** 79808c2ecf20Sopenharmony_ci * qla2x00_module_exit - Module cleanup. 79818c2ecf20Sopenharmony_ci **/ 79828c2ecf20Sopenharmony_cistatic void __exit 79838c2ecf20Sopenharmony_ciqla2x00_module_exit(void) 79848c2ecf20Sopenharmony_ci{ 79858c2ecf20Sopenharmony_ci pci_unregister_driver(&qla2xxx_pci_driver); 79868c2ecf20Sopenharmony_ci qla2x00_release_firmware(); 79878c2ecf20Sopenharmony_ci kmem_cache_destroy(ctx_cachep); 79888c2ecf20Sopenharmony_ci fc_release_transport(qla2xxx_transport_vport_template); 79898c2ecf20Sopenharmony_ci if (apidev_major >= 0) 79908c2ecf20Sopenharmony_ci unregister_chrdev(apidev_major, QLA2XXX_APIDEV); 79918c2ecf20Sopenharmony_ci fc_release_transport(qla2xxx_transport_template); 79928c2ecf20Sopenharmony_ci qlt_exit(); 79938c2ecf20Sopenharmony_ci kmem_cache_destroy(srb_cachep); 79948c2ecf20Sopenharmony_ci} 79958c2ecf20Sopenharmony_ci 79968c2ecf20Sopenharmony_cimodule_init(qla2x00_module_init); 79978c2ecf20Sopenharmony_cimodule_exit(qla2x00_module_exit); 79988c2ecf20Sopenharmony_ci 79998c2ecf20Sopenharmony_ciMODULE_AUTHOR("QLogic Corporation"); 80008c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver"); 80018c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 80028c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FW_FILE_ISP21XX); 80038c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FW_FILE_ISP22XX); 80048c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FW_FILE_ISP2300); 80058c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FW_FILE_ISP2322); 80068c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FW_FILE_ISP24XX); 80078c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FW_FILE_ISP25XX); 8008