18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QLogic iSCSI HBA Driver 48c2ecf20Sopenharmony_ci * Copyright (c) 2003-2013 QLogic Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 78c2ecf20Sopenharmony_ci#include <linux/slab.h> 88c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 98c2ecf20Sopenharmony_ci#include <linux/iscsi_boot_sysfs.h> 108c2ecf20Sopenharmony_ci#include <linux/inet.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <scsi/scsi_tcq.h> 138c2ecf20Sopenharmony_ci#include <scsi/scsicam.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "ql4_def.h" 168c2ecf20Sopenharmony_ci#include "ql4_version.h" 178c2ecf20Sopenharmony_ci#include "ql4_glbl.h" 188c2ecf20Sopenharmony_ci#include "ql4_dbg.h" 198c2ecf20Sopenharmony_ci#include "ql4_inline.h" 208c2ecf20Sopenharmony_ci#include "ql4_83xx.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* 238c2ecf20Sopenharmony_ci * Driver version 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_cistatic char qla4xxx_version_str[40]; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* 288c2ecf20Sopenharmony_ci * SRB allocation cache 298c2ecf20Sopenharmony_ci */ 308c2ecf20Sopenharmony_cistatic struct kmem_cache *srb_cachep; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * Module parameter information and variables 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistatic int ql4xdisablesysfsboot = 1; 368c2ecf20Sopenharmony_cimodule_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR); 378c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xdisablesysfsboot, 388c2ecf20Sopenharmony_ci " Set to disable exporting boot targets to sysfs.\n" 398c2ecf20Sopenharmony_ci "\t\t 0 - Export boot targets\n" 408c2ecf20Sopenharmony_ci "\t\t 1 - Do not export boot targets (Default)"); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciint ql4xdontresethba; 438c2ecf20Sopenharmony_cimodule_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); 448c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xdontresethba, 458c2ecf20Sopenharmony_ci " Don't reset the HBA for driver recovery.\n" 468c2ecf20Sopenharmony_ci "\t\t 0 - It will reset HBA (Default)\n" 478c2ecf20Sopenharmony_ci "\t\t 1 - It will NOT reset HBA"); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciint ql4xextended_error_logging; 508c2ecf20Sopenharmony_cimodule_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR); 518c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xextended_error_logging, 528c2ecf20Sopenharmony_ci " Option to enable extended error logging.\n" 538c2ecf20Sopenharmony_ci "\t\t 0 - no logging (Default)\n" 548c2ecf20Sopenharmony_ci "\t\t 2 - debug logging"); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint ql4xenablemsix = 1; 578c2ecf20Sopenharmony_cimodule_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR); 588c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xenablemsix, 598c2ecf20Sopenharmony_ci " Set to enable MSI or MSI-X interrupt mechanism.\n" 608c2ecf20Sopenharmony_ci "\t\t 0 = enable INTx interrupt mechanism.\n" 618c2ecf20Sopenharmony_ci "\t\t 1 = enable MSI-X interrupt mechanism (Default).\n" 628c2ecf20Sopenharmony_ci "\t\t 2 = enable MSI interrupt mechanism."); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define QL4_DEF_QDEPTH 32 658c2ecf20Sopenharmony_cistatic int ql4xmaxqdepth = QL4_DEF_QDEPTH; 668c2ecf20Sopenharmony_cimodule_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR); 678c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xmaxqdepth, 688c2ecf20Sopenharmony_ci " Maximum queue depth to report for target devices.\n" 698c2ecf20Sopenharmony_ci "\t\t Default: 32."); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic int ql4xqfulltracking = 1; 728c2ecf20Sopenharmony_cimodule_param(ql4xqfulltracking, int, S_IRUGO | S_IWUSR); 738c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xqfulltracking, 748c2ecf20Sopenharmony_ci " Enable or disable dynamic tracking and adjustment of\n" 758c2ecf20Sopenharmony_ci "\t\t scsi device queue depth.\n" 768c2ecf20Sopenharmony_ci "\t\t 0 - Disable.\n" 778c2ecf20Sopenharmony_ci "\t\t 1 - Enable. (Default)"); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; 808c2ecf20Sopenharmony_cimodule_param(ql4xsess_recovery_tmo, int, S_IRUGO); 818c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xsess_recovery_tmo, 828c2ecf20Sopenharmony_ci " Target Session Recovery Timeout.\n" 838c2ecf20Sopenharmony_ci "\t\t Default: 120 sec."); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciint ql4xmdcapmask = 0; 868c2ecf20Sopenharmony_cimodule_param(ql4xmdcapmask, int, S_IRUGO); 878c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xmdcapmask, 888c2ecf20Sopenharmony_ci " Set the Minidump driver capture mask level.\n" 898c2ecf20Sopenharmony_ci "\t\t Default is 0 (firmware default capture mask)\n" 908c2ecf20Sopenharmony_ci "\t\t Can be set to 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF"); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciint ql4xenablemd = 1; 938c2ecf20Sopenharmony_cimodule_param(ql4xenablemd, int, S_IRUGO | S_IWUSR); 948c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ql4xenablemd, 958c2ecf20Sopenharmony_ci " Set to enable minidump.\n" 968c2ecf20Sopenharmony_ci "\t\t 0 - disable minidump\n" 978c2ecf20Sopenharmony_ci "\t\t 1 - enable minidump (Default)"); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * SCSI host template entry points 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_cistatic void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * iSCSI template entry points 1078c2ecf20Sopenharmony_ci */ 1088c2ecf20Sopenharmony_cistatic int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, 1098c2ecf20Sopenharmony_ci enum iscsi_param param, char *buf); 1108c2ecf20Sopenharmony_cistatic int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn, 1118c2ecf20Sopenharmony_ci enum iscsi_param param, char *buf); 1128c2ecf20Sopenharmony_cistatic int qla4xxx_host_get_param(struct Scsi_Host *shost, 1138c2ecf20Sopenharmony_ci enum iscsi_host_param param, char *buf); 1148c2ecf20Sopenharmony_cistatic int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, 1158c2ecf20Sopenharmony_ci uint32_t len); 1168c2ecf20Sopenharmony_cistatic int qla4xxx_get_iface_param(struct iscsi_iface *iface, 1178c2ecf20Sopenharmony_ci enum iscsi_param_type param_type, 1188c2ecf20Sopenharmony_ci int param, char *buf); 1198c2ecf20Sopenharmony_cistatic enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc); 1208c2ecf20Sopenharmony_cistatic struct iscsi_endpoint *qla4xxx_ep_connect(struct Scsi_Host *shost, 1218c2ecf20Sopenharmony_ci struct sockaddr *dst_addr, 1228c2ecf20Sopenharmony_ci int non_blocking); 1238c2ecf20Sopenharmony_cistatic int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms); 1248c2ecf20Sopenharmony_cistatic void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep); 1258c2ecf20Sopenharmony_cistatic int qla4xxx_get_ep_param(struct iscsi_endpoint *ep, 1268c2ecf20Sopenharmony_ci enum iscsi_param param, char *buf); 1278c2ecf20Sopenharmony_cistatic int qla4xxx_conn_start(struct iscsi_cls_conn *conn); 1288c2ecf20Sopenharmony_cistatic struct iscsi_cls_conn * 1298c2ecf20Sopenharmony_ciqla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx); 1308c2ecf20Sopenharmony_cistatic int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session, 1318c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn, 1328c2ecf20Sopenharmony_ci uint64_t transport_fd, int is_leading); 1338c2ecf20Sopenharmony_cistatic void qla4xxx_conn_destroy(struct iscsi_cls_conn *conn); 1348c2ecf20Sopenharmony_cistatic struct iscsi_cls_session * 1358c2ecf20Sopenharmony_ciqla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, 1368c2ecf20Sopenharmony_ci uint16_t qdepth, uint32_t initial_cmdsn); 1378c2ecf20Sopenharmony_cistatic void qla4xxx_session_destroy(struct iscsi_cls_session *sess); 1388c2ecf20Sopenharmony_cistatic void qla4xxx_task_work(struct work_struct *wdata); 1398c2ecf20Sopenharmony_cistatic int qla4xxx_alloc_pdu(struct iscsi_task *, uint8_t); 1408c2ecf20Sopenharmony_cistatic int qla4xxx_task_xmit(struct iscsi_task *); 1418c2ecf20Sopenharmony_cistatic void qla4xxx_task_cleanup(struct iscsi_task *); 1428c2ecf20Sopenharmony_cistatic void qla4xxx_fail_session(struct iscsi_cls_session *cls_session); 1438c2ecf20Sopenharmony_cistatic void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, 1448c2ecf20Sopenharmony_ci struct iscsi_stats *stats); 1458c2ecf20Sopenharmony_cistatic int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, 1468c2ecf20Sopenharmony_ci uint32_t iface_type, uint32_t payload_size, 1478c2ecf20Sopenharmony_ci uint32_t pid, struct sockaddr *dst_addr); 1488c2ecf20Sopenharmony_cistatic int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, 1498c2ecf20Sopenharmony_ci uint32_t *num_entries, char *buf); 1508c2ecf20Sopenharmony_cistatic int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); 1518c2ecf20Sopenharmony_cistatic int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, 1528c2ecf20Sopenharmony_ci int len); 1538c2ecf20Sopenharmony_cistatic int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/* 1568c2ecf20Sopenharmony_ci * SCSI host template entry points 1578c2ecf20Sopenharmony_ci */ 1588c2ecf20Sopenharmony_cistatic int qla4xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd); 1598c2ecf20Sopenharmony_cistatic int qla4xxx_eh_abort(struct scsi_cmnd *cmd); 1608c2ecf20Sopenharmony_cistatic int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd); 1618c2ecf20Sopenharmony_cistatic int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd); 1628c2ecf20Sopenharmony_cistatic int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd); 1638c2ecf20Sopenharmony_cistatic int qla4xxx_slave_alloc(struct scsi_device *device); 1648c2ecf20Sopenharmony_cistatic umode_t qla4_attr_is_visible(int param_type, int param); 1658c2ecf20Sopenharmony_cistatic int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* 1688c2ecf20Sopenharmony_ci * iSCSI Flash DDB sysfs entry points 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_cistatic int 1718c2ecf20Sopenharmony_ciqla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, 1728c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn, 1738c2ecf20Sopenharmony_ci void *data, int len); 1748c2ecf20Sopenharmony_cistatic int 1758c2ecf20Sopenharmony_ciqla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, 1768c2ecf20Sopenharmony_ci int param, char *buf); 1778c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, 1788c2ecf20Sopenharmony_ci int len); 1798c2ecf20Sopenharmony_cistatic int 1808c2ecf20Sopenharmony_ciqla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess); 1818c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, 1828c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn); 1838c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, 1848c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn); 1858c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_cistatic struct qla4_8xxx_legacy_intr_set legacy_intr[] = 1888c2ecf20Sopenharmony_ci QLA82XX_LEGACY_INTR_CONFIG; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic const uint32_t qla4_82xx_reg_tbl[] = { 1918c2ecf20Sopenharmony_ci QLA82XX_PEG_HALT_STATUS1, 1928c2ecf20Sopenharmony_ci QLA82XX_PEG_HALT_STATUS2, 1938c2ecf20Sopenharmony_ci QLA82XX_PEG_ALIVE_COUNTER, 1948c2ecf20Sopenharmony_ci QLA82XX_CRB_DRV_ACTIVE, 1958c2ecf20Sopenharmony_ci QLA82XX_CRB_DEV_STATE, 1968c2ecf20Sopenharmony_ci QLA82XX_CRB_DRV_STATE, 1978c2ecf20Sopenharmony_ci QLA82XX_CRB_DRV_SCRATCH, 1988c2ecf20Sopenharmony_ci QLA82XX_CRB_DEV_PART_INFO, 1998c2ecf20Sopenharmony_ci QLA82XX_CRB_DRV_IDC_VERSION, 2008c2ecf20Sopenharmony_ci QLA82XX_FW_VERSION_MAJOR, 2018c2ecf20Sopenharmony_ci QLA82XX_FW_VERSION_MINOR, 2028c2ecf20Sopenharmony_ci QLA82XX_FW_VERSION_SUB, 2038c2ecf20Sopenharmony_ci CRB_CMDPEG_STATE, 2048c2ecf20Sopenharmony_ci CRB_TEMP_STATE, 2058c2ecf20Sopenharmony_ci}; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic const uint32_t qla4_83xx_reg_tbl[] = { 2088c2ecf20Sopenharmony_ci QLA83XX_PEG_HALT_STATUS1, 2098c2ecf20Sopenharmony_ci QLA83XX_PEG_HALT_STATUS2, 2108c2ecf20Sopenharmony_ci QLA83XX_PEG_ALIVE_COUNTER, 2118c2ecf20Sopenharmony_ci QLA83XX_CRB_DRV_ACTIVE, 2128c2ecf20Sopenharmony_ci QLA83XX_CRB_DEV_STATE, 2138c2ecf20Sopenharmony_ci QLA83XX_CRB_DRV_STATE, 2148c2ecf20Sopenharmony_ci QLA83XX_CRB_DRV_SCRATCH, 2158c2ecf20Sopenharmony_ci QLA83XX_CRB_DEV_PART_INFO1, 2168c2ecf20Sopenharmony_ci QLA83XX_CRB_IDC_VER_MAJOR, 2178c2ecf20Sopenharmony_ci QLA83XX_FW_VER_MAJOR, 2188c2ecf20Sopenharmony_ci QLA83XX_FW_VER_MINOR, 2198c2ecf20Sopenharmony_ci QLA83XX_FW_VER_SUB, 2208c2ecf20Sopenharmony_ci QLA83XX_CMDPEG_STATE, 2218c2ecf20Sopenharmony_ci QLA83XX_ASIC_TEMP, 2228c2ecf20Sopenharmony_ci}; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic struct scsi_host_template qla4xxx_driver_template = { 2258c2ecf20Sopenharmony_ci .module = THIS_MODULE, 2268c2ecf20Sopenharmony_ci .name = DRIVER_NAME, 2278c2ecf20Sopenharmony_ci .proc_name = DRIVER_NAME, 2288c2ecf20Sopenharmony_ci .queuecommand = qla4xxx_queuecommand, 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci .eh_abort_handler = qla4xxx_eh_abort, 2318c2ecf20Sopenharmony_ci .eh_device_reset_handler = qla4xxx_eh_device_reset, 2328c2ecf20Sopenharmony_ci .eh_target_reset_handler = qla4xxx_eh_target_reset, 2338c2ecf20Sopenharmony_ci .eh_host_reset_handler = qla4xxx_eh_host_reset, 2348c2ecf20Sopenharmony_ci .eh_timed_out = qla4xxx_eh_cmd_timed_out, 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci .slave_alloc = qla4xxx_slave_alloc, 2378c2ecf20Sopenharmony_ci .change_queue_depth = scsi_change_queue_depth, 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci .this_id = -1, 2408c2ecf20Sopenharmony_ci .cmd_per_lun = 3, 2418c2ecf20Sopenharmony_ci .sg_tablesize = SG_ALL, 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci .max_sectors = 0xFFFF, 2448c2ecf20Sopenharmony_ci .shost_attrs = qla4xxx_host_attrs, 2458c2ecf20Sopenharmony_ci .host_reset = qla4xxx_host_reset, 2468c2ecf20Sopenharmony_ci .vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC, 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic struct iscsi_transport qla4xxx_iscsi_transport = { 2508c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 2518c2ecf20Sopenharmony_ci .name = DRIVER_NAME, 2528c2ecf20Sopenharmony_ci .caps = CAP_TEXT_NEGO | 2538c2ecf20Sopenharmony_ci CAP_DATA_PATH_OFFLOAD | CAP_HDRDGST | 2548c2ecf20Sopenharmony_ci CAP_DATADGST | CAP_LOGIN_OFFLOAD | 2558c2ecf20Sopenharmony_ci CAP_MULTI_R2T, 2568c2ecf20Sopenharmony_ci .attr_is_visible = qla4_attr_is_visible, 2578c2ecf20Sopenharmony_ci .create_session = qla4xxx_session_create, 2588c2ecf20Sopenharmony_ci .destroy_session = qla4xxx_session_destroy, 2598c2ecf20Sopenharmony_ci .start_conn = qla4xxx_conn_start, 2608c2ecf20Sopenharmony_ci .create_conn = qla4xxx_conn_create, 2618c2ecf20Sopenharmony_ci .bind_conn = qla4xxx_conn_bind, 2628c2ecf20Sopenharmony_ci .unbind_conn = iscsi_conn_unbind, 2638c2ecf20Sopenharmony_ci .stop_conn = iscsi_conn_stop, 2648c2ecf20Sopenharmony_ci .destroy_conn = qla4xxx_conn_destroy, 2658c2ecf20Sopenharmony_ci .set_param = iscsi_set_param, 2668c2ecf20Sopenharmony_ci .get_conn_param = qla4xxx_conn_get_param, 2678c2ecf20Sopenharmony_ci .get_session_param = qla4xxx_session_get_param, 2688c2ecf20Sopenharmony_ci .get_ep_param = qla4xxx_get_ep_param, 2698c2ecf20Sopenharmony_ci .ep_connect = qla4xxx_ep_connect, 2708c2ecf20Sopenharmony_ci .ep_poll = qla4xxx_ep_poll, 2718c2ecf20Sopenharmony_ci .ep_disconnect = qla4xxx_ep_disconnect, 2728c2ecf20Sopenharmony_ci .get_stats = qla4xxx_conn_get_stats, 2738c2ecf20Sopenharmony_ci .send_pdu = iscsi_conn_send_pdu, 2748c2ecf20Sopenharmony_ci .xmit_task = qla4xxx_task_xmit, 2758c2ecf20Sopenharmony_ci .cleanup_task = qla4xxx_task_cleanup, 2768c2ecf20Sopenharmony_ci .alloc_pdu = qla4xxx_alloc_pdu, 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci .get_host_param = qla4xxx_host_get_param, 2798c2ecf20Sopenharmony_ci .set_iface_param = qla4xxx_iface_set_param, 2808c2ecf20Sopenharmony_ci .get_iface_param = qla4xxx_get_iface_param, 2818c2ecf20Sopenharmony_ci .bsg_request = qla4xxx_bsg_request, 2828c2ecf20Sopenharmony_ci .send_ping = qla4xxx_send_ping, 2838c2ecf20Sopenharmony_ci .get_chap = qla4xxx_get_chap_list, 2848c2ecf20Sopenharmony_ci .delete_chap = qla4xxx_delete_chap, 2858c2ecf20Sopenharmony_ci .set_chap = qla4xxx_set_chap_entry, 2868c2ecf20Sopenharmony_ci .get_flashnode_param = qla4xxx_sysfs_ddb_get_param, 2878c2ecf20Sopenharmony_ci .set_flashnode_param = qla4xxx_sysfs_ddb_set_param, 2888c2ecf20Sopenharmony_ci .new_flashnode = qla4xxx_sysfs_ddb_add, 2898c2ecf20Sopenharmony_ci .del_flashnode = qla4xxx_sysfs_ddb_delete, 2908c2ecf20Sopenharmony_ci .login_flashnode = qla4xxx_sysfs_ddb_login, 2918c2ecf20Sopenharmony_ci .logout_flashnode = qla4xxx_sysfs_ddb_logout, 2928c2ecf20Sopenharmony_ci .logout_flashnode_sid = qla4xxx_sysfs_ddb_logout_sid, 2938c2ecf20Sopenharmony_ci .get_host_stats = qla4xxx_get_host_stats, 2948c2ecf20Sopenharmony_ci}; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic struct scsi_transport_template *qla4xxx_scsi_transport; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int qla4xxx_isp_check_reg(struct scsi_qla_host *ha) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci u32 reg_val = 0; 3018c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if (is_qla8022(ha)) 3048c2ecf20Sopenharmony_ci reg_val = readl(&ha->qla4_82xx_reg->host_status); 3058c2ecf20Sopenharmony_ci else if (is_qla8032(ha) || is_qla8042(ha)) 3068c2ecf20Sopenharmony_ci reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER); 3078c2ecf20Sopenharmony_ci else 3088c2ecf20Sopenharmony_ci reg_val = readw(&ha->reg->ctrl_status); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci if (reg_val == QL4_ISP_REG_DISCONNECT) 3118c2ecf20Sopenharmony_ci rval = QLA_ERROR; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci return rval; 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, 3178c2ecf20Sopenharmony_ci uint32_t iface_type, uint32_t payload_size, 3188c2ecf20Sopenharmony_ci uint32_t pid, struct sockaddr *dst_addr) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 3218c2ecf20Sopenharmony_ci struct sockaddr_in *addr; 3228c2ecf20Sopenharmony_ci struct sockaddr_in6 *addr6; 3238c2ecf20Sopenharmony_ci uint32_t options = 0; 3248c2ecf20Sopenharmony_ci uint8_t ipaddr[IPv6_ADDR_LEN]; 3258c2ecf20Sopenharmony_ci int rval; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci memset(ipaddr, 0, IPv6_ADDR_LEN); 3288c2ecf20Sopenharmony_ci /* IPv4 to IPv4 */ 3298c2ecf20Sopenharmony_ci if ((iface_type == ISCSI_IFACE_TYPE_IPV4) && 3308c2ecf20Sopenharmony_ci (dst_addr->sa_family == AF_INET)) { 3318c2ecf20Sopenharmony_ci addr = (struct sockaddr_in *)dst_addr; 3328c2ecf20Sopenharmony_ci memcpy(ipaddr, &addr->sin_addr.s_addr, IP_ADDR_LEN); 3338c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv4 Ping src: %pI4 " 3348c2ecf20Sopenharmony_ci "dest: %pI4\n", __func__, 3358c2ecf20Sopenharmony_ci &ha->ip_config.ip_address, ipaddr)); 3368c2ecf20Sopenharmony_ci rval = qla4xxx_ping_iocb(ha, options, payload_size, pid, 3378c2ecf20Sopenharmony_ci ipaddr); 3388c2ecf20Sopenharmony_ci if (rval) 3398c2ecf20Sopenharmony_ci rval = -EINVAL; 3408c2ecf20Sopenharmony_ci } else if ((iface_type == ISCSI_IFACE_TYPE_IPV6) && 3418c2ecf20Sopenharmony_ci (dst_addr->sa_family == AF_INET6)) { 3428c2ecf20Sopenharmony_ci /* IPv6 to IPv6 */ 3438c2ecf20Sopenharmony_ci addr6 = (struct sockaddr_in6 *)dst_addr; 3448c2ecf20Sopenharmony_ci memcpy(ipaddr, &addr6->sin6_addr.in6_u.u6_addr8, IPv6_ADDR_LEN); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci options |= PING_IPV6_PROTOCOL_ENABLE; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* Ping using LinkLocal address */ 3498c2ecf20Sopenharmony_ci if ((iface_num == 0) || (iface_num == 1)) { 3508c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: LinkLocal Ping " 3518c2ecf20Sopenharmony_ci "src: %pI6 dest: %pI6\n", __func__, 3528c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_link_local_addr, 3538c2ecf20Sopenharmony_ci ipaddr)); 3548c2ecf20Sopenharmony_ci options |= PING_IPV6_LINKLOCAL_ADDR; 3558c2ecf20Sopenharmony_ci rval = qla4xxx_ping_iocb(ha, options, payload_size, 3568c2ecf20Sopenharmony_ci pid, ipaddr); 3578c2ecf20Sopenharmony_ci } else { 3588c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: iface num = %d " 3598c2ecf20Sopenharmony_ci "not supported\n", __func__, iface_num); 3608c2ecf20Sopenharmony_ci rval = -ENOSYS; 3618c2ecf20Sopenharmony_ci goto exit_send_ping; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* 3658c2ecf20Sopenharmony_ci * If ping using LinkLocal address fails, try ping using 3668c2ecf20Sopenharmony_ci * IPv6 address 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 3698c2ecf20Sopenharmony_ci options &= ~PING_IPV6_LINKLOCAL_ADDR; 3708c2ecf20Sopenharmony_ci if (iface_num == 0) { 3718c2ecf20Sopenharmony_ci options |= PING_IPV6_ADDR0; 3728c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 " 3738c2ecf20Sopenharmony_ci "Ping src: %pI6 " 3748c2ecf20Sopenharmony_ci "dest: %pI6\n", __func__, 3758c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_addr0, 3768c2ecf20Sopenharmony_ci ipaddr)); 3778c2ecf20Sopenharmony_ci } else if (iface_num == 1) { 3788c2ecf20Sopenharmony_ci options |= PING_IPV6_ADDR1; 3798c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 " 3808c2ecf20Sopenharmony_ci "Ping src: %pI6 " 3818c2ecf20Sopenharmony_ci "dest: %pI6\n", __func__, 3828c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_addr1, 3838c2ecf20Sopenharmony_ci ipaddr)); 3848c2ecf20Sopenharmony_ci } 3858c2ecf20Sopenharmony_ci rval = qla4xxx_ping_iocb(ha, options, payload_size, 3868c2ecf20Sopenharmony_ci pid, ipaddr); 3878c2ecf20Sopenharmony_ci if (rval) 3888c2ecf20Sopenharmony_ci rval = -EINVAL; 3898c2ecf20Sopenharmony_ci } 3908c2ecf20Sopenharmony_ci } else 3918c2ecf20Sopenharmony_ci rval = -ENOSYS; 3928c2ecf20Sopenharmony_ciexit_send_ping: 3938c2ecf20Sopenharmony_ci return rval; 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_cistatic umode_t qla4_attr_is_visible(int param_type, int param) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci switch (param_type) { 3998c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM: 4008c2ecf20Sopenharmony_ci switch (param) { 4018c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_HWADDRESS: 4028c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_IPADDRESS: 4038c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_INITIATOR_NAME: 4048c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_STATE: 4058c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_SPEED: 4068c2ecf20Sopenharmony_ci return S_IRUGO; 4078c2ecf20Sopenharmony_ci default: 4088c2ecf20Sopenharmony_ci return 0; 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci case ISCSI_PARAM: 4118c2ecf20Sopenharmony_ci switch (param) { 4128c2ecf20Sopenharmony_ci case ISCSI_PARAM_PERSISTENT_ADDRESS: 4138c2ecf20Sopenharmony_ci case ISCSI_PARAM_PERSISTENT_PORT: 4148c2ecf20Sopenharmony_ci case ISCSI_PARAM_CONN_ADDRESS: 4158c2ecf20Sopenharmony_ci case ISCSI_PARAM_CONN_PORT: 4168c2ecf20Sopenharmony_ci case ISCSI_PARAM_TARGET_NAME: 4178c2ecf20Sopenharmony_ci case ISCSI_PARAM_TPGT: 4188c2ecf20Sopenharmony_ci case ISCSI_PARAM_TARGET_ALIAS: 4198c2ecf20Sopenharmony_ci case ISCSI_PARAM_MAX_BURST: 4208c2ecf20Sopenharmony_ci case ISCSI_PARAM_MAX_R2T: 4218c2ecf20Sopenharmony_ci case ISCSI_PARAM_FIRST_BURST: 4228c2ecf20Sopenharmony_ci case ISCSI_PARAM_MAX_RECV_DLENGTH: 4238c2ecf20Sopenharmony_ci case ISCSI_PARAM_MAX_XMIT_DLENGTH: 4248c2ecf20Sopenharmony_ci case ISCSI_PARAM_IFACE_NAME: 4258c2ecf20Sopenharmony_ci case ISCSI_PARAM_CHAP_OUT_IDX: 4268c2ecf20Sopenharmony_ci case ISCSI_PARAM_CHAP_IN_IDX: 4278c2ecf20Sopenharmony_ci case ISCSI_PARAM_USERNAME: 4288c2ecf20Sopenharmony_ci case ISCSI_PARAM_PASSWORD: 4298c2ecf20Sopenharmony_ci case ISCSI_PARAM_USERNAME_IN: 4308c2ecf20Sopenharmony_ci case ISCSI_PARAM_PASSWORD_IN: 4318c2ecf20Sopenharmony_ci case ISCSI_PARAM_AUTO_SND_TGT_DISABLE: 4328c2ecf20Sopenharmony_ci case ISCSI_PARAM_DISCOVERY_SESS: 4338c2ecf20Sopenharmony_ci case ISCSI_PARAM_PORTAL_TYPE: 4348c2ecf20Sopenharmony_ci case ISCSI_PARAM_CHAP_AUTH_EN: 4358c2ecf20Sopenharmony_ci case ISCSI_PARAM_DISCOVERY_LOGOUT_EN: 4368c2ecf20Sopenharmony_ci case ISCSI_PARAM_BIDI_CHAP_EN: 4378c2ecf20Sopenharmony_ci case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL: 4388c2ecf20Sopenharmony_ci case ISCSI_PARAM_DEF_TIME2WAIT: 4398c2ecf20Sopenharmony_ci case ISCSI_PARAM_DEF_TIME2RETAIN: 4408c2ecf20Sopenharmony_ci case ISCSI_PARAM_HDRDGST_EN: 4418c2ecf20Sopenharmony_ci case ISCSI_PARAM_DATADGST_EN: 4428c2ecf20Sopenharmony_ci case ISCSI_PARAM_INITIAL_R2T_EN: 4438c2ecf20Sopenharmony_ci case ISCSI_PARAM_IMM_DATA_EN: 4448c2ecf20Sopenharmony_ci case ISCSI_PARAM_PDU_INORDER_EN: 4458c2ecf20Sopenharmony_ci case ISCSI_PARAM_DATASEQ_INORDER_EN: 4468c2ecf20Sopenharmony_ci case ISCSI_PARAM_MAX_SEGMENT_SIZE: 4478c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_TIMESTAMP_STAT: 4488c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_WSF_DISABLE: 4498c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_NAGLE_DISABLE: 4508c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_TIMER_SCALE: 4518c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_TIMESTAMP_EN: 4528c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_XMIT_WSF: 4538c2ecf20Sopenharmony_ci case ISCSI_PARAM_TCP_RECV_WSF: 4548c2ecf20Sopenharmony_ci case ISCSI_PARAM_IP_FRAGMENT_DISABLE: 4558c2ecf20Sopenharmony_ci case ISCSI_PARAM_IPV4_TOS: 4568c2ecf20Sopenharmony_ci case ISCSI_PARAM_IPV6_TC: 4578c2ecf20Sopenharmony_ci case ISCSI_PARAM_IPV6_FLOW_LABEL: 4588c2ecf20Sopenharmony_ci case ISCSI_PARAM_IS_FW_ASSIGNED_IPV6: 4598c2ecf20Sopenharmony_ci case ISCSI_PARAM_KEEPALIVE_TMO: 4608c2ecf20Sopenharmony_ci case ISCSI_PARAM_LOCAL_PORT: 4618c2ecf20Sopenharmony_ci case ISCSI_PARAM_ISID: 4628c2ecf20Sopenharmony_ci case ISCSI_PARAM_TSID: 4638c2ecf20Sopenharmony_ci case ISCSI_PARAM_DEF_TASKMGMT_TMO: 4648c2ecf20Sopenharmony_ci case ISCSI_PARAM_ERL: 4658c2ecf20Sopenharmony_ci case ISCSI_PARAM_STATSN: 4668c2ecf20Sopenharmony_ci case ISCSI_PARAM_EXP_STATSN: 4678c2ecf20Sopenharmony_ci case ISCSI_PARAM_DISCOVERY_PARENT_IDX: 4688c2ecf20Sopenharmony_ci case ISCSI_PARAM_DISCOVERY_PARENT_TYPE: 4698c2ecf20Sopenharmony_ci case ISCSI_PARAM_LOCAL_IPADDR: 4708c2ecf20Sopenharmony_ci return S_IRUGO; 4718c2ecf20Sopenharmony_ci default: 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM: 4758c2ecf20Sopenharmony_ci switch (param) { 4768c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 4778c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 4788c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GW: 4798c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 4808c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 4818c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL: 4828c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 4838c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ROUTER: 4848c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: 4858c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: 4868c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ID: 4878c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_PRIORITY: 4888c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 4898c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_MTU: 4908c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_PORT: 4918c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPADDR_STATE: 4928c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE: 4938c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ROUTER_STATE: 4948c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_DELAYED_ACK_EN: 4958c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: 4968c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF_DISABLE: 4978c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF: 4988c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMER_SCALE: 4998c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: 5008c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_CACHE_ID: 5018c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: 5028c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: 5038c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TOS_EN: 5048c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TOS: 5058c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: 5068c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: 5078c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: 5088c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: 5098c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: 5108c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: 5118c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: 5128c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: 5138c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: 5148c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_REDIRECT_EN: 5158c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TTL: 5168c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: 5178c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_MLD_EN: 5188c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: 5198c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: 5208c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: 5218c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: 5228c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: 5238c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: 5248c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: 5258c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: 5268c2ecf20Sopenharmony_ci return S_IRUGO; 5278c2ecf20Sopenharmony_ci default: 5288c2ecf20Sopenharmony_ci return 0; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM: 5318c2ecf20Sopenharmony_ci switch (param) { 5328c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: 5338c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_HDRDGST_EN: 5348c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DATADGST_EN: 5358c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_IMM_DATA_EN: 5368c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: 5378c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: 5388c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_PDU_INORDER_EN: 5398c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_ERL: 5408c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: 5418c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_FIRST_BURST: 5428c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_R2T: 5438c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_BURST: 5448c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: 5458c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: 5468c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: 5478c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: 5488c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: 5498c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_INITIATOR_NAME: 5508c2ecf20Sopenharmony_ci return S_IRUGO; 5518c2ecf20Sopenharmony_ci default: 5528c2ecf20Sopenharmony_ci return 0; 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PARAM: 5558c2ecf20Sopenharmony_ci switch (param) { 5568c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: 5578c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PORTAL_TYPE: 5588c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: 5598c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_SESS: 5608c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ENTRY_EN: 5618c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_HDR_DGST_EN: 5628c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DATA_DGST_EN: 5638c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IMM_DATA_EN: 5648c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_INITIAL_R2T_EN: 5658c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DATASEQ_INORDER: 5668c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PDU_INORDER: 5678c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_CHAP_AUTH_EN: 5688c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_SNACK_REQ_EN: 5698c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: 5708c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_BIDI_CHAP_EN: 5718c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: 5728c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ERL: 5738c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: 5748c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: 5758c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_WSF_DISABLE: 5768c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMER_SCALE: 5778c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: 5788c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IP_FRAG_DISABLE: 5798c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: 5808c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: 5818c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_FIRST_BURST: 5828c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TIME2WAIT: 5838c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TIME2RETAIN: 5848c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_R2T: 5858c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_KEEPALIVE_TMO: 5868c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ISID: 5878c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TSID: 5888c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PORT: 5898c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_BURST: 5908c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: 5918c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPADDR: 5928c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ALIAS: 5938c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_REDIRECT_IPADDR: 5948c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: 5958c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_LOCAL_PORT: 5968c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV4_TOS: 5978c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV6_TC: 5988c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: 5998c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_NAME: 6008c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TPGT: 6018c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: 6028c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: 6038c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: 6048c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_XMIT_WSF: 6058c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_RECV_WSF: 6068c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_CHAP_OUT_IDX: 6078c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_USERNAME: 6088c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PASSWORD: 6098c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_STATSN: 6108c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_EXP_STATSN: 6118c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IS_BOOT_TGT: 6128c2ecf20Sopenharmony_ci return S_IRUGO; 6138c2ecf20Sopenharmony_ci default: 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci return 0; 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci/** 6228c2ecf20Sopenharmony_ci * qla4xxx_create chap_list - Create CHAP list from FLASH 6238c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 6248c2ecf20Sopenharmony_ci * 6258c2ecf20Sopenharmony_ci * Read flash and make a list of CHAP entries, during login when a CHAP entry 6268c2ecf20Sopenharmony_ci * is received, it will be checked in this list. If entry exist then the CHAP 6278c2ecf20Sopenharmony_ci * entry index is set in the DDB. If CHAP entry does not exist in this list 6288c2ecf20Sopenharmony_ci * then a new entry is added in FLASH in CHAP table and the index obtained is 6298c2ecf20Sopenharmony_ci * used in the DDB. 6308c2ecf20Sopenharmony_ci **/ 6318c2ecf20Sopenharmony_cistatic void qla4xxx_create_chap_list(struct scsi_qla_host *ha) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int rval = 0; 6348c2ecf20Sopenharmony_ci uint8_t *chap_flash_data = NULL; 6358c2ecf20Sopenharmony_ci uint32_t offset; 6368c2ecf20Sopenharmony_ci dma_addr_t chap_dma; 6378c2ecf20Sopenharmony_ci uint32_t chap_size = 0; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) 6408c2ecf20Sopenharmony_ci chap_size = MAX_CHAP_ENTRIES_40XX * 6418c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 6428c2ecf20Sopenharmony_ci else /* Single region contains CHAP info for both 6438c2ecf20Sopenharmony_ci * ports which is divided into half for each port. 6448c2ecf20Sopenharmony_ci */ 6458c2ecf20Sopenharmony_ci chap_size = ha->hw.flt_chap_size / 2; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size, 6488c2ecf20Sopenharmony_ci &chap_dma, GFP_KERNEL); 6498c2ecf20Sopenharmony_ci if (!chap_flash_data) { 6508c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n"); 6518c2ecf20Sopenharmony_ci return; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 6558c2ecf20Sopenharmony_ci offset = FLASH_CHAP_OFFSET; 6568c2ecf20Sopenharmony_ci } else { 6578c2ecf20Sopenharmony_ci offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 6588c2ecf20Sopenharmony_ci if (ha->port_num == 1) 6598c2ecf20Sopenharmony_ci offset += chap_size; 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); 6638c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 6648c2ecf20Sopenharmony_ci goto exit_chap_list; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci if (ha->chap_list == NULL) 6678c2ecf20Sopenharmony_ci ha->chap_list = vmalloc(chap_size); 6688c2ecf20Sopenharmony_ci if (ha->chap_list == NULL) { 6698c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n"); 6708c2ecf20Sopenharmony_ci goto exit_chap_list; 6718c2ecf20Sopenharmony_ci } 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci memset(ha->chap_list, 0, chap_size); 6748c2ecf20Sopenharmony_ci memcpy(ha->chap_list, chap_flash_data, chap_size); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ciexit_chap_list: 6778c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, chap_size, chap_flash_data, chap_dma); 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cistatic int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha, 6818c2ecf20Sopenharmony_ci int16_t chap_index, 6828c2ecf20Sopenharmony_ci struct ql4_chap_table **chap_entry) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci int rval = QLA_ERROR; 6858c2ecf20Sopenharmony_ci int max_chap_entries; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci if (!ha->chap_list) { 6888c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); 6898c2ecf20Sopenharmony_ci rval = QLA_ERROR; 6908c2ecf20Sopenharmony_ci goto exit_get_chap; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 6948c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 6958c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 6968c2ecf20Sopenharmony_ci else 6978c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci if (chap_index > max_chap_entries) { 7008c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); 7018c2ecf20Sopenharmony_ci rval = QLA_ERROR; 7028c2ecf20Sopenharmony_ci goto exit_get_chap; 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci *chap_entry = (struct ql4_chap_table *)ha->chap_list + chap_index; 7068c2ecf20Sopenharmony_ci if ((*chap_entry)->cookie != 7078c2ecf20Sopenharmony_ci __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { 7088c2ecf20Sopenharmony_ci rval = QLA_ERROR; 7098c2ecf20Sopenharmony_ci *chap_entry = NULL; 7108c2ecf20Sopenharmony_ci } else { 7118c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ciexit_get_chap: 7158c2ecf20Sopenharmony_ci return rval; 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci/** 7198c2ecf20Sopenharmony_ci * qla4xxx_find_free_chap_index - Find the first free chap index 7208c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 7218c2ecf20Sopenharmony_ci * @chap_index: CHAP index to be returned 7228c2ecf20Sopenharmony_ci * 7238c2ecf20Sopenharmony_ci * Find the first free chap index available in the chap table 7248c2ecf20Sopenharmony_ci * 7258c2ecf20Sopenharmony_ci * Note: Caller should acquire the chap lock before getting here. 7268c2ecf20Sopenharmony_ci **/ 7278c2ecf20Sopenharmony_cistatic int qla4xxx_find_free_chap_index(struct scsi_qla_host *ha, 7288c2ecf20Sopenharmony_ci uint16_t *chap_index) 7298c2ecf20Sopenharmony_ci{ 7308c2ecf20Sopenharmony_ci int i, rval; 7318c2ecf20Sopenharmony_ci int free_index = -1; 7328c2ecf20Sopenharmony_ci int max_chap_entries = 0; 7338c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 7368c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 7378c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 7388c2ecf20Sopenharmony_ci else 7398c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci if (!ha->chap_list) { 7428c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); 7438c2ecf20Sopenharmony_ci rval = QLA_ERROR; 7448c2ecf20Sopenharmony_ci goto exit_find_chap; 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci for (i = 0; i < max_chap_entries; i++) { 7488c2ecf20Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + i; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci if ((chap_table->cookie != 7518c2ecf20Sopenharmony_ci __constant_cpu_to_le16(CHAP_VALID_COOKIE)) && 7528c2ecf20Sopenharmony_ci (i > MAX_RESRV_CHAP_IDX)) { 7538c2ecf20Sopenharmony_ci free_index = i; 7548c2ecf20Sopenharmony_ci break; 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci if (free_index != -1) { 7598c2ecf20Sopenharmony_ci *chap_index = free_index; 7608c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 7618c2ecf20Sopenharmony_ci } else { 7628c2ecf20Sopenharmony_ci rval = QLA_ERROR; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ciexit_find_chap: 7668c2ecf20Sopenharmony_ci return rval; 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_cistatic int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, 7708c2ecf20Sopenharmony_ci uint32_t *num_entries, char *buf) 7718c2ecf20Sopenharmony_ci{ 7728c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 7738c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 7748c2ecf20Sopenharmony_ci struct iscsi_chap_rec *chap_rec; 7758c2ecf20Sopenharmony_ci int max_chap_entries = 0; 7768c2ecf20Sopenharmony_ci int valid_chap_entries = 0; 7778c2ecf20Sopenharmony_ci int ret = 0, i; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 7808c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 7818c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 7828c2ecf20Sopenharmony_ci else 7838c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: num_entries = %d, CHAP idx = %d\n", 7868c2ecf20Sopenharmony_ci __func__, *num_entries, chap_tbl_idx); 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci if (!buf) { 7898c2ecf20Sopenharmony_ci ret = -ENOMEM; 7908c2ecf20Sopenharmony_ci goto exit_get_chap_list; 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci qla4xxx_create_chap_list(ha); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci chap_rec = (struct iscsi_chap_rec *) buf; 7968c2ecf20Sopenharmony_ci mutex_lock(&ha->chap_sem); 7978c2ecf20Sopenharmony_ci for (i = chap_tbl_idx; i < max_chap_entries; i++) { 7988c2ecf20Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + i; 7998c2ecf20Sopenharmony_ci if (chap_table->cookie != 8008c2ecf20Sopenharmony_ci __constant_cpu_to_le16(CHAP_VALID_COOKIE)) 8018c2ecf20Sopenharmony_ci continue; 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci chap_rec->chap_tbl_idx = i; 8048c2ecf20Sopenharmony_ci strlcpy(chap_rec->username, chap_table->name, 8058c2ecf20Sopenharmony_ci ISCSI_CHAP_AUTH_NAME_MAX_LEN); 8068c2ecf20Sopenharmony_ci strlcpy(chap_rec->password, chap_table->secret, 8078c2ecf20Sopenharmony_ci QL4_CHAP_MAX_SECRET_LEN); 8088c2ecf20Sopenharmony_ci chap_rec->password_length = chap_table->secret_len; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci if (chap_table->flags & BIT_7) /* local */ 8118c2ecf20Sopenharmony_ci chap_rec->chap_type = CHAP_TYPE_OUT; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci if (chap_table->flags & BIT_6) /* peer */ 8148c2ecf20Sopenharmony_ci chap_rec->chap_type = CHAP_TYPE_IN; 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci chap_rec++; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci valid_chap_entries++; 8198c2ecf20Sopenharmony_ci if (valid_chap_entries == *num_entries) 8208c2ecf20Sopenharmony_ci break; 8218c2ecf20Sopenharmony_ci else 8228c2ecf20Sopenharmony_ci continue; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci mutex_unlock(&ha->chap_sem); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ciexit_get_chap_list: 8278c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Valid CHAP Entries = %d\n", 8288c2ecf20Sopenharmony_ci __func__, valid_chap_entries); 8298c2ecf20Sopenharmony_ci *num_entries = valid_chap_entries; 8308c2ecf20Sopenharmony_ci return ret; 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic int __qla4xxx_is_chap_active(struct device *dev, void *data) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci int ret = 0; 8368c2ecf20Sopenharmony_ci uint16_t *chap_tbl_idx = (uint16_t *) data; 8378c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_session; 8388c2ecf20Sopenharmony_ci struct iscsi_session *sess; 8398c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci if (!iscsi_is_session_dev(dev)) 8428c2ecf20Sopenharmony_ci goto exit_is_chap_active; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci cls_session = iscsi_dev_to_session(dev); 8458c2ecf20Sopenharmony_ci sess = cls_session->dd_data; 8468c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci if (iscsi_session_chkready(cls_session)) 8498c2ecf20Sopenharmony_ci goto exit_is_chap_active; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci if (ddb_entry->chap_tbl_idx == *chap_tbl_idx) 8528c2ecf20Sopenharmony_ci ret = 1; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ciexit_is_chap_active: 8558c2ecf20Sopenharmony_ci return ret; 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_cistatic int qla4xxx_is_chap_active(struct Scsi_Host *shost, 8598c2ecf20Sopenharmony_ci uint16_t chap_tbl_idx) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci int ret = 0; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci ret = device_for_each_child(&shost->shost_gendev, &chap_tbl_idx, 8648c2ecf20Sopenharmony_ci __qla4xxx_is_chap_active); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci return ret; 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 8728c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 8738c2ecf20Sopenharmony_ci dma_addr_t chap_dma; 8748c2ecf20Sopenharmony_ci int max_chap_entries = 0; 8758c2ecf20Sopenharmony_ci uint32_t offset = 0; 8768c2ecf20Sopenharmony_ci uint32_t chap_size; 8778c2ecf20Sopenharmony_ci int ret = 0; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma); 8808c2ecf20Sopenharmony_ci if (chap_table == NULL) 8818c2ecf20Sopenharmony_ci return -ENOMEM; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 8848c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 8858c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 8868c2ecf20Sopenharmony_ci else 8878c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci if (chap_tbl_idx > max_chap_entries) { 8908c2ecf20Sopenharmony_ci ret = -EINVAL; 8918c2ecf20Sopenharmony_ci goto exit_delete_chap; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci /* Check if chap index is in use. 8958c2ecf20Sopenharmony_ci * If chap is in use don't delet chap entry */ 8968c2ecf20Sopenharmony_ci ret = qla4xxx_is_chap_active(shost, chap_tbl_idx); 8978c2ecf20Sopenharmony_ci if (ret) { 8988c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "CHAP entry %d is in use, cannot " 8998c2ecf20Sopenharmony_ci "delete from flash\n", chap_tbl_idx); 9008c2ecf20Sopenharmony_ci ret = -EBUSY; 9018c2ecf20Sopenharmony_ci goto exit_delete_chap; 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci chap_size = sizeof(struct ql4_chap_table); 9058c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) 9068c2ecf20Sopenharmony_ci offset = FLASH_CHAP_OFFSET | (chap_tbl_idx * chap_size); 9078c2ecf20Sopenharmony_ci else { 9088c2ecf20Sopenharmony_ci offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); 9098c2ecf20Sopenharmony_ci /* flt_chap_size is CHAP table size for both ports 9108c2ecf20Sopenharmony_ci * so divide it by 2 to calculate the offset for second port 9118c2ecf20Sopenharmony_ci */ 9128c2ecf20Sopenharmony_ci if (ha->port_num == 1) 9138c2ecf20Sopenharmony_ci offset += (ha->hw.flt_chap_size / 2); 9148c2ecf20Sopenharmony_ci offset += (chap_tbl_idx * chap_size); 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci ret = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); 9188c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 9198c2ecf20Sopenharmony_ci ret = -EINVAL; 9208c2ecf20Sopenharmony_ci goto exit_delete_chap; 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n", 9248c2ecf20Sopenharmony_ci __le16_to_cpu(chap_table->cookie))); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) { 9278c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "No valid chap entry found\n"); 9288c2ecf20Sopenharmony_ci goto exit_delete_chap; 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci chap_table->cookie = __constant_cpu_to_le16(0xFFFF); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci offset = FLASH_CHAP_OFFSET | 9348c2ecf20Sopenharmony_ci (chap_tbl_idx * sizeof(struct ql4_chap_table)); 9358c2ecf20Sopenharmony_ci ret = qla4xxx_set_flash(ha, chap_dma, offset, chap_size, 9368c2ecf20Sopenharmony_ci FLASH_OPT_RMW_COMMIT); 9378c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS && ha->chap_list) { 9388c2ecf20Sopenharmony_ci mutex_lock(&ha->chap_sem); 9398c2ecf20Sopenharmony_ci /* Update ha chap_list cache */ 9408c2ecf20Sopenharmony_ci memcpy((struct ql4_chap_table *)ha->chap_list + chap_tbl_idx, 9418c2ecf20Sopenharmony_ci chap_table, sizeof(struct ql4_chap_table)); 9428c2ecf20Sopenharmony_ci mutex_unlock(&ha->chap_sem); 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) 9458c2ecf20Sopenharmony_ci ret = -EINVAL; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ciexit_delete_chap: 9488c2ecf20Sopenharmony_ci dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma); 9498c2ecf20Sopenharmony_ci return ret; 9508c2ecf20Sopenharmony_ci} 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci/** 9538c2ecf20Sopenharmony_ci * qla4xxx_set_chap_entry - Make chap entry with given information 9548c2ecf20Sopenharmony_ci * @shost: pointer to host 9558c2ecf20Sopenharmony_ci * @data: chap info - credentials, index and type to make chap entry 9568c2ecf20Sopenharmony_ci * @len: length of data 9578c2ecf20Sopenharmony_ci * 9588c2ecf20Sopenharmony_ci * Add or update chap entry with the given information 9598c2ecf20Sopenharmony_ci **/ 9608c2ecf20Sopenharmony_cistatic int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 9638c2ecf20Sopenharmony_ci struct iscsi_chap_rec chap_rec; 9648c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_entry = NULL; 9658c2ecf20Sopenharmony_ci struct iscsi_param_info *param_info; 9668c2ecf20Sopenharmony_ci struct nlattr *attr; 9678c2ecf20Sopenharmony_ci int max_chap_entries = 0; 9688c2ecf20Sopenharmony_ci int type; 9698c2ecf20Sopenharmony_ci int rem = len; 9708c2ecf20Sopenharmony_ci int rc = 0; 9718c2ecf20Sopenharmony_ci int size; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci memset(&chap_rec, 0, sizeof(chap_rec)); 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci nla_for_each_attr(attr, data, len, rem) { 9768c2ecf20Sopenharmony_ci if (nla_len(attr) < sizeof(*param_info)) { 9778c2ecf20Sopenharmony_ci rc = -EINVAL; 9788c2ecf20Sopenharmony_ci goto exit_set_chap; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci param_info = nla_data(attr); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci switch (param_info->param) { 9848c2ecf20Sopenharmony_ci case ISCSI_CHAP_PARAM_INDEX: 9858c2ecf20Sopenharmony_ci chap_rec.chap_tbl_idx = *(uint16_t *)param_info->value; 9868c2ecf20Sopenharmony_ci break; 9878c2ecf20Sopenharmony_ci case ISCSI_CHAP_PARAM_CHAP_TYPE: 9888c2ecf20Sopenharmony_ci chap_rec.chap_type = param_info->value[0]; 9898c2ecf20Sopenharmony_ci break; 9908c2ecf20Sopenharmony_ci case ISCSI_CHAP_PARAM_USERNAME: 9918c2ecf20Sopenharmony_ci size = min_t(size_t, sizeof(chap_rec.username), 9928c2ecf20Sopenharmony_ci param_info->len); 9938c2ecf20Sopenharmony_ci memcpy(chap_rec.username, param_info->value, size); 9948c2ecf20Sopenharmony_ci break; 9958c2ecf20Sopenharmony_ci case ISCSI_CHAP_PARAM_PASSWORD: 9968c2ecf20Sopenharmony_ci size = min_t(size_t, sizeof(chap_rec.password), 9978c2ecf20Sopenharmony_ci param_info->len); 9988c2ecf20Sopenharmony_ci memcpy(chap_rec.password, param_info->value, size); 9998c2ecf20Sopenharmony_ci break; 10008c2ecf20Sopenharmony_ci case ISCSI_CHAP_PARAM_PASSWORD_LEN: 10018c2ecf20Sopenharmony_ci chap_rec.password_length = param_info->value[0]; 10028c2ecf20Sopenharmony_ci break; 10038c2ecf20Sopenharmony_ci default: 10048c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 10058c2ecf20Sopenharmony_ci "%s: No such sysfs attribute\n", __func__); 10068c2ecf20Sopenharmony_ci rc = -ENOSYS; 10078c2ecf20Sopenharmony_ci goto exit_set_chap; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci if (chap_rec.chap_type == CHAP_TYPE_IN) 10128c2ecf20Sopenharmony_ci type = BIDI_CHAP; 10138c2ecf20Sopenharmony_ci else 10148c2ecf20Sopenharmony_ci type = LOCAL_CHAP; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 10178c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 10188c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 10198c2ecf20Sopenharmony_ci else 10208c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci mutex_lock(&ha->chap_sem); 10238c2ecf20Sopenharmony_ci if (chap_rec.chap_tbl_idx < max_chap_entries) { 10248c2ecf20Sopenharmony_ci rc = qla4xxx_get_chap_by_index(ha, chap_rec.chap_tbl_idx, 10258c2ecf20Sopenharmony_ci &chap_entry); 10268c2ecf20Sopenharmony_ci if (!rc) { 10278c2ecf20Sopenharmony_ci if (!(type == qla4xxx_get_chap_type(chap_entry))) { 10288c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 10298c2ecf20Sopenharmony_ci "Type mismatch for CHAP entry %d\n", 10308c2ecf20Sopenharmony_ci chap_rec.chap_tbl_idx); 10318c2ecf20Sopenharmony_ci rc = -EINVAL; 10328c2ecf20Sopenharmony_ci goto exit_unlock_chap; 10338c2ecf20Sopenharmony_ci } 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci /* If chap index is in use then don't modify it */ 10368c2ecf20Sopenharmony_ci rc = qla4xxx_is_chap_active(shost, 10378c2ecf20Sopenharmony_ci chap_rec.chap_tbl_idx); 10388c2ecf20Sopenharmony_ci if (rc) { 10398c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 10408c2ecf20Sopenharmony_ci "CHAP entry %d is in use\n", 10418c2ecf20Sopenharmony_ci chap_rec.chap_tbl_idx); 10428c2ecf20Sopenharmony_ci rc = -EBUSY; 10438c2ecf20Sopenharmony_ci goto exit_unlock_chap; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci } 10468c2ecf20Sopenharmony_ci } else { 10478c2ecf20Sopenharmony_ci rc = qla4xxx_find_free_chap_index(ha, &chap_rec.chap_tbl_idx); 10488c2ecf20Sopenharmony_ci if (rc) { 10498c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "CHAP entry not available\n"); 10508c2ecf20Sopenharmony_ci rc = -EBUSY; 10518c2ecf20Sopenharmony_ci goto exit_unlock_chap; 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci } 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci rc = qla4xxx_set_chap(ha, chap_rec.username, chap_rec.password, 10568c2ecf20Sopenharmony_ci chap_rec.chap_tbl_idx, type); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ciexit_unlock_chap: 10598c2ecf20Sopenharmony_ci mutex_unlock(&ha->chap_sem); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ciexit_set_chap: 10628c2ecf20Sopenharmony_ci return rc; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_cistatic int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 10698c2ecf20Sopenharmony_ci struct iscsi_offload_host_stats *host_stats = NULL; 10708c2ecf20Sopenharmony_ci int host_stats_size; 10718c2ecf20Sopenharmony_ci int ret = 0; 10728c2ecf20Sopenharmony_ci int ddb_idx = 0; 10738c2ecf20Sopenharmony_ci struct ql_iscsi_stats *ql_iscsi_stats = NULL; 10748c2ecf20Sopenharmony_ci int stats_size; 10758c2ecf20Sopenharmony_ci dma_addr_t iscsi_stats_dma; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Func: %s\n", __func__)); 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci host_stats_size = sizeof(struct iscsi_offload_host_stats); 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci if (host_stats_size != len) { 10828c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: host_stats size mismatch expected = %d, is = %d\n", 10838c2ecf20Sopenharmony_ci __func__, len, host_stats_size); 10848c2ecf20Sopenharmony_ci ret = -EINVAL; 10858c2ecf20Sopenharmony_ci goto exit_host_stats; 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci host_stats = (struct iscsi_offload_host_stats *)buf; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci if (!buf) { 10908c2ecf20Sopenharmony_ci ret = -ENOMEM; 10918c2ecf20Sopenharmony_ci goto exit_host_stats; 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats)); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size, 10978c2ecf20Sopenharmony_ci &iscsi_stats_dma, GFP_KERNEL); 10988c2ecf20Sopenharmony_ci if (!ql_iscsi_stats) { 10998c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 11008c2ecf20Sopenharmony_ci "Unable to allocate memory for iscsi stats\n"); 11018c2ecf20Sopenharmony_ci ret = -ENOMEM; 11028c2ecf20Sopenharmony_ci goto exit_host_stats; 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci ret = qla4xxx_get_mgmt_data(ha, ddb_idx, stats_size, 11068c2ecf20Sopenharmony_ci iscsi_stats_dma); 11078c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 11088c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 11098c2ecf20Sopenharmony_ci "Unable to retrieve iscsi stats\n"); 11108c2ecf20Sopenharmony_ci ret = -EIO; 11118c2ecf20Sopenharmony_ci goto exit_host_stats; 11128c2ecf20Sopenharmony_ci } 11138c2ecf20Sopenharmony_ci host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames); 11148c2ecf20Sopenharmony_ci host_stats->mactx_bytes = le64_to_cpu(ql_iscsi_stats->mac_tx_bytes); 11158c2ecf20Sopenharmony_ci host_stats->mactx_multicast_frames = 11168c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_multicast_frames); 11178c2ecf20Sopenharmony_ci host_stats->mactx_broadcast_frames = 11188c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_broadcast_frames); 11198c2ecf20Sopenharmony_ci host_stats->mactx_pause_frames = 11208c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_pause_frames); 11218c2ecf20Sopenharmony_ci host_stats->mactx_control_frames = 11228c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_control_frames); 11238c2ecf20Sopenharmony_ci host_stats->mactx_deferral = 11248c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_deferral); 11258c2ecf20Sopenharmony_ci host_stats->mactx_excess_deferral = 11268c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_excess_deferral); 11278c2ecf20Sopenharmony_ci host_stats->mactx_late_collision = 11288c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_late_collision); 11298c2ecf20Sopenharmony_ci host_stats->mactx_abort = le64_to_cpu(ql_iscsi_stats->mac_tx_abort); 11308c2ecf20Sopenharmony_ci host_stats->mactx_single_collision = 11318c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_single_collision); 11328c2ecf20Sopenharmony_ci host_stats->mactx_multiple_collision = 11338c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_multiple_collision); 11348c2ecf20Sopenharmony_ci host_stats->mactx_collision = 11358c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_collision); 11368c2ecf20Sopenharmony_ci host_stats->mactx_frames_dropped = 11378c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_frames_dropped); 11388c2ecf20Sopenharmony_ci host_stats->mactx_jumbo_frames = 11398c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_tx_jumbo_frames); 11408c2ecf20Sopenharmony_ci host_stats->macrx_frames = le64_to_cpu(ql_iscsi_stats->mac_rx_frames); 11418c2ecf20Sopenharmony_ci host_stats->macrx_bytes = le64_to_cpu(ql_iscsi_stats->mac_rx_bytes); 11428c2ecf20Sopenharmony_ci host_stats->macrx_unknown_control_frames = 11438c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_unknown_control_frames); 11448c2ecf20Sopenharmony_ci host_stats->macrx_pause_frames = 11458c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_pause_frames); 11468c2ecf20Sopenharmony_ci host_stats->macrx_control_frames = 11478c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_control_frames); 11488c2ecf20Sopenharmony_ci host_stats->macrx_dribble = 11498c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_dribble); 11508c2ecf20Sopenharmony_ci host_stats->macrx_frame_length_error = 11518c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_frame_length_error); 11528c2ecf20Sopenharmony_ci host_stats->macrx_jabber = le64_to_cpu(ql_iscsi_stats->mac_rx_jabber); 11538c2ecf20Sopenharmony_ci host_stats->macrx_carrier_sense_error = 11548c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_carrier_sense_error); 11558c2ecf20Sopenharmony_ci host_stats->macrx_frame_discarded = 11568c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_frame_discarded); 11578c2ecf20Sopenharmony_ci host_stats->macrx_frames_dropped = 11588c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_frames_dropped); 11598c2ecf20Sopenharmony_ci host_stats->mac_crc_error = le64_to_cpu(ql_iscsi_stats->mac_crc_error); 11608c2ecf20Sopenharmony_ci host_stats->mac_encoding_error = 11618c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_encoding_error); 11628c2ecf20Sopenharmony_ci host_stats->macrx_length_error_large = 11638c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_large); 11648c2ecf20Sopenharmony_ci host_stats->macrx_length_error_small = 11658c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_small); 11668c2ecf20Sopenharmony_ci host_stats->macrx_multicast_frames = 11678c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_multicast_frames); 11688c2ecf20Sopenharmony_ci host_stats->macrx_broadcast_frames = 11698c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->mac_rx_broadcast_frames); 11708c2ecf20Sopenharmony_ci host_stats->iptx_packets = le64_to_cpu(ql_iscsi_stats->ip_tx_packets); 11718c2ecf20Sopenharmony_ci host_stats->iptx_bytes = le64_to_cpu(ql_iscsi_stats->ip_tx_bytes); 11728c2ecf20Sopenharmony_ci host_stats->iptx_fragments = 11738c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_tx_fragments); 11748c2ecf20Sopenharmony_ci host_stats->iprx_packets = le64_to_cpu(ql_iscsi_stats->ip_rx_packets); 11758c2ecf20Sopenharmony_ci host_stats->iprx_bytes = le64_to_cpu(ql_iscsi_stats->ip_rx_bytes); 11768c2ecf20Sopenharmony_ci host_stats->iprx_fragments = 11778c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_rx_fragments); 11788c2ecf20Sopenharmony_ci host_stats->ip_datagram_reassembly = 11798c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly); 11808c2ecf20Sopenharmony_ci host_stats->ip_invalid_address_error = 11818c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_invalid_address_error); 11828c2ecf20Sopenharmony_ci host_stats->ip_error_packets = 11838c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_error_packets); 11848c2ecf20Sopenharmony_ci host_stats->ip_fragrx_overlap = 11858c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_fragrx_overlap); 11868c2ecf20Sopenharmony_ci host_stats->ip_fragrx_outoforder = 11878c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_fragrx_outoforder); 11888c2ecf20Sopenharmony_ci host_stats->ip_datagram_reassembly_timeout = 11898c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly_timeout); 11908c2ecf20Sopenharmony_ci host_stats->ipv6tx_packets = 11918c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_tx_packets); 11928c2ecf20Sopenharmony_ci host_stats->ipv6tx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_tx_bytes); 11938c2ecf20Sopenharmony_ci host_stats->ipv6tx_fragments = 11948c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_tx_fragments); 11958c2ecf20Sopenharmony_ci host_stats->ipv6rx_packets = 11968c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_rx_packets); 11978c2ecf20Sopenharmony_ci host_stats->ipv6rx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_rx_bytes); 11988c2ecf20Sopenharmony_ci host_stats->ipv6rx_fragments = 11998c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_rx_fragments); 12008c2ecf20Sopenharmony_ci host_stats->ipv6_datagram_reassembly = 12018c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly); 12028c2ecf20Sopenharmony_ci host_stats->ipv6_invalid_address_error = 12038c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_invalid_address_error); 12048c2ecf20Sopenharmony_ci host_stats->ipv6_error_packets = 12058c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_error_packets); 12068c2ecf20Sopenharmony_ci host_stats->ipv6_fragrx_overlap = 12078c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_overlap); 12088c2ecf20Sopenharmony_ci host_stats->ipv6_fragrx_outoforder = 12098c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_outoforder); 12108c2ecf20Sopenharmony_ci host_stats->ipv6_datagram_reassembly_timeout = 12118c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly_timeout); 12128c2ecf20Sopenharmony_ci host_stats->tcptx_segments = 12138c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_tx_segments); 12148c2ecf20Sopenharmony_ci host_stats->tcptx_bytes = le64_to_cpu(ql_iscsi_stats->tcp_tx_bytes); 12158c2ecf20Sopenharmony_ci host_stats->tcprx_segments = 12168c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_segments); 12178c2ecf20Sopenharmony_ci host_stats->tcprx_byte = le64_to_cpu(ql_iscsi_stats->tcp_rx_byte); 12188c2ecf20Sopenharmony_ci host_stats->tcp_duplicate_ack_retx = 12198c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_duplicate_ack_retx); 12208c2ecf20Sopenharmony_ci host_stats->tcp_retx_timer_expired = 12218c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_retx_timer_expired); 12228c2ecf20Sopenharmony_ci host_stats->tcprx_duplicate_ack = 12238c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_duplicate_ack); 12248c2ecf20Sopenharmony_ci host_stats->tcprx_pure_ackr = 12258c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_pure_ackr); 12268c2ecf20Sopenharmony_ci host_stats->tcptx_delayed_ack = 12278c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_tx_delayed_ack); 12288c2ecf20Sopenharmony_ci host_stats->tcptx_pure_ack = 12298c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_tx_pure_ack); 12308c2ecf20Sopenharmony_ci host_stats->tcprx_segment_error = 12318c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_error); 12328c2ecf20Sopenharmony_ci host_stats->tcprx_segment_outoforder = 12338c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_outoforder); 12348c2ecf20Sopenharmony_ci host_stats->tcprx_window_probe = 12358c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_window_probe); 12368c2ecf20Sopenharmony_ci host_stats->tcprx_window_update = 12378c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_rx_window_update); 12388c2ecf20Sopenharmony_ci host_stats->tcptx_window_probe_persist = 12398c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->tcp_tx_window_probe_persist); 12408c2ecf20Sopenharmony_ci host_stats->ecc_error_correction = 12418c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->ecc_error_correction); 12428c2ecf20Sopenharmony_ci host_stats->iscsi_pdu_tx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_tx); 12438c2ecf20Sopenharmony_ci host_stats->iscsi_data_bytes_tx = 12448c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_tx); 12458c2ecf20Sopenharmony_ci host_stats->iscsi_pdu_rx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_rx); 12468c2ecf20Sopenharmony_ci host_stats->iscsi_data_bytes_rx = 12478c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_rx); 12488c2ecf20Sopenharmony_ci host_stats->iscsi_io_completed = 12498c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_io_completed); 12508c2ecf20Sopenharmony_ci host_stats->iscsi_unexpected_io_rx = 12518c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_unexpected_io_rx); 12528c2ecf20Sopenharmony_ci host_stats->iscsi_format_error = 12538c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_format_error); 12548c2ecf20Sopenharmony_ci host_stats->iscsi_hdr_digest_error = 12558c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_hdr_digest_error); 12568c2ecf20Sopenharmony_ci host_stats->iscsi_data_digest_error = 12578c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_data_digest_error); 12588c2ecf20Sopenharmony_ci host_stats->iscsi_sequence_error = 12598c2ecf20Sopenharmony_ci le64_to_cpu(ql_iscsi_stats->iscsi_sequence_error); 12608c2ecf20Sopenharmony_ciexit_host_stats: 12618c2ecf20Sopenharmony_ci if (ql_iscsi_stats) 12628c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, stats_size, 12638c2ecf20Sopenharmony_ci ql_iscsi_stats, iscsi_stats_dma); 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Get host stats done\n", 12668c2ecf20Sopenharmony_ci __func__); 12678c2ecf20Sopenharmony_ci return ret; 12688c2ecf20Sopenharmony_ci} 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_cistatic int qla4xxx_get_iface_param(struct iscsi_iface *iface, 12718c2ecf20Sopenharmony_ci enum iscsi_param_type param_type, 12728c2ecf20Sopenharmony_ci int param, char *buf) 12738c2ecf20Sopenharmony_ci{ 12748c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_iface_to_shost(iface); 12758c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 12768c2ecf20Sopenharmony_ci int ival; 12778c2ecf20Sopenharmony_ci char *pval = NULL; 12788c2ecf20Sopenharmony_ci int len = -ENOSYS; 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci if (param_type == ISCSI_NET_PARAM) { 12818c2ecf20Sopenharmony_ci switch (param) { 12828c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 12838c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); 12848c2ecf20Sopenharmony_ci break; 12858c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 12868c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI4\n", 12878c2ecf20Sopenharmony_ci &ha->ip_config.subnet_mask); 12888c2ecf20Sopenharmony_ci break; 12898c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GW: 12908c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway); 12918c2ecf20Sopenharmony_ci break; 12928c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 12938c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 12948c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 12958c2ecf20Sopenharmony_ci IPOPT_IPV4_PROTOCOL_ENABLE, pval); 12968c2ecf20Sopenharmony_ci } else { 12978c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv6_options, 12988c2ecf20Sopenharmony_ci IPV6_OPT_IPV6_PROTOCOL_ENABLE, pval); 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 13028c2ecf20Sopenharmony_ci break; 13038c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 13048c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", 13058c2ecf20Sopenharmony_ci (ha->ip_config.tcp_options & 13068c2ecf20Sopenharmony_ci TCPOPT_DHCP_ENABLE) ? 13078c2ecf20Sopenharmony_ci "dhcp" : "static"); 13088c2ecf20Sopenharmony_ci break; 13098c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 13108c2ecf20Sopenharmony_ci if (iface->iface_num == 0) 13118c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI6\n", 13128c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_addr0); 13138c2ecf20Sopenharmony_ci if (iface->iface_num == 1) 13148c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI6\n", 13158c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_addr1); 13168c2ecf20Sopenharmony_ci break; 13178c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL: 13188c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI6\n", 13198c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_link_local_addr); 13208c2ecf20Sopenharmony_ci break; 13218c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ROUTER: 13228c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI6\n", 13238c2ecf20Sopenharmony_ci &ha->ip_config.ipv6_default_router_addr); 13248c2ecf20Sopenharmony_ci break; 13258c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: 13268c2ecf20Sopenharmony_ci pval = (ha->ip_config.ipv6_addl_options & 13278c2ecf20Sopenharmony_ci IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ? 13288c2ecf20Sopenharmony_ci "nd" : "static"; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 13318c2ecf20Sopenharmony_ci break; 13328c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: 13338c2ecf20Sopenharmony_ci pval = (ha->ip_config.ipv6_addl_options & 13348c2ecf20Sopenharmony_ci IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ? 13358c2ecf20Sopenharmony_ci "auto" : "static"; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 13388c2ecf20Sopenharmony_ci break; 13398c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ID: 13408c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 13418c2ecf20Sopenharmony_ci ival = ha->ip_config.ipv4_vlan_tag & 13428c2ecf20Sopenharmony_ci ISCSI_MAX_VLAN_ID; 13438c2ecf20Sopenharmony_ci else 13448c2ecf20Sopenharmony_ci ival = ha->ip_config.ipv6_vlan_tag & 13458c2ecf20Sopenharmony_ci ISCSI_MAX_VLAN_ID; 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ival); 13488c2ecf20Sopenharmony_ci break; 13498c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_PRIORITY: 13508c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 13518c2ecf20Sopenharmony_ci ival = (ha->ip_config.ipv4_vlan_tag >> 13) & 13528c2ecf20Sopenharmony_ci ISCSI_MAX_VLAN_PRIORITY; 13538c2ecf20Sopenharmony_ci else 13548c2ecf20Sopenharmony_ci ival = (ha->ip_config.ipv6_vlan_tag >> 13) & 13558c2ecf20Sopenharmony_ci ISCSI_MAX_VLAN_PRIORITY; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ival); 13588c2ecf20Sopenharmony_ci break; 13598c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 13608c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 13618c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 13628c2ecf20Sopenharmony_ci IPOPT_VLAN_TAGGING_ENABLE, pval); 13638c2ecf20Sopenharmony_ci } else { 13648c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv6_options, 13658c2ecf20Sopenharmony_ci IPV6_OPT_VLAN_TAGGING_ENABLE, pval); 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 13688c2ecf20Sopenharmony_ci break; 13698c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_MTU: 13708c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size); 13718c2ecf20Sopenharmony_ci break; 13728c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_PORT: 13738c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 13748c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 13758c2ecf20Sopenharmony_ci ha->ip_config.ipv4_port); 13768c2ecf20Sopenharmony_ci else 13778c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 13788c2ecf20Sopenharmony_ci ha->ip_config.ipv6_port); 13798c2ecf20Sopenharmony_ci break; 13808c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPADDR_STATE: 13818c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 13828c2ecf20Sopenharmony_ci pval = iscsi_get_ipaddress_state_name( 13838c2ecf20Sopenharmony_ci ha->ip_config.ipv4_addr_state); 13848c2ecf20Sopenharmony_ci } else { 13858c2ecf20Sopenharmony_ci if (iface->iface_num == 0) 13868c2ecf20Sopenharmony_ci pval = iscsi_get_ipaddress_state_name( 13878c2ecf20Sopenharmony_ci ha->ip_config.ipv6_addr0_state); 13888c2ecf20Sopenharmony_ci else if (iface->iface_num == 1) 13898c2ecf20Sopenharmony_ci pval = iscsi_get_ipaddress_state_name( 13908c2ecf20Sopenharmony_ci ha->ip_config.ipv6_addr1_state); 13918c2ecf20Sopenharmony_ci } 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 13948c2ecf20Sopenharmony_ci break; 13958c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE: 13968c2ecf20Sopenharmony_ci pval = iscsi_get_ipaddress_state_name( 13978c2ecf20Sopenharmony_ci ha->ip_config.ipv6_link_local_state); 13988c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 13998c2ecf20Sopenharmony_ci break; 14008c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ROUTER_STATE: 14018c2ecf20Sopenharmony_ci pval = iscsi_get_router_state_name( 14028c2ecf20Sopenharmony_ci ha->ip_config.ipv6_default_router_state); 14038c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14048c2ecf20Sopenharmony_ci break; 14058c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_DELAYED_ACK_EN: 14068c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 14078c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.tcp_options, 14088c2ecf20Sopenharmony_ci TCPOPT_DELAYED_ACK_DISABLE, pval); 14098c2ecf20Sopenharmony_ci } else { 14108c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.ipv6_tcp_options, 14118c2ecf20Sopenharmony_ci IPV6_TCPOPT_DELAYED_ACK_DISABLE, pval); 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14148c2ecf20Sopenharmony_ci break; 14158c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: 14168c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 14178c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.tcp_options, 14188c2ecf20Sopenharmony_ci TCPOPT_NAGLE_ALGO_DISABLE, pval); 14198c2ecf20Sopenharmony_ci } else { 14208c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.ipv6_tcp_options, 14218c2ecf20Sopenharmony_ci IPV6_TCPOPT_NAGLE_ALGO_DISABLE, pval); 14228c2ecf20Sopenharmony_ci } 14238c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14248c2ecf20Sopenharmony_ci break; 14258c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF_DISABLE: 14268c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 14278c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.tcp_options, 14288c2ecf20Sopenharmony_ci TCPOPT_WINDOW_SCALE_DISABLE, pval); 14298c2ecf20Sopenharmony_ci } else { 14308c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.ipv6_tcp_options, 14318c2ecf20Sopenharmony_ci IPV6_TCPOPT_WINDOW_SCALE_DISABLE, 14328c2ecf20Sopenharmony_ci pval); 14338c2ecf20Sopenharmony_ci } 14348c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14358c2ecf20Sopenharmony_ci break; 14368c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF: 14378c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 14388c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 14398c2ecf20Sopenharmony_ci ha->ip_config.tcp_wsf); 14408c2ecf20Sopenharmony_ci else 14418c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 14428c2ecf20Sopenharmony_ci ha->ip_config.ipv6_tcp_wsf); 14438c2ecf20Sopenharmony_ci break; 14448c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMER_SCALE: 14458c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 14468c2ecf20Sopenharmony_ci ival = (ha->ip_config.tcp_options & 14478c2ecf20Sopenharmony_ci TCPOPT_TIMER_SCALE) >> 1; 14488c2ecf20Sopenharmony_ci else 14498c2ecf20Sopenharmony_ci ival = (ha->ip_config.ipv6_tcp_options & 14508c2ecf20Sopenharmony_ci IPV6_TCPOPT_TIMER_SCALE) >> 1; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ival); 14538c2ecf20Sopenharmony_ci break; 14548c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: 14558c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 14568c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.tcp_options, 14578c2ecf20Sopenharmony_ci TCPOPT_TIMESTAMP_ENABLE, pval); 14588c2ecf20Sopenharmony_ci } else { 14598c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv6_tcp_options, 14608c2ecf20Sopenharmony_ci IPV6_TCPOPT_TIMESTAMP_EN, pval); 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14638c2ecf20Sopenharmony_ci break; 14648c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_CACHE_ID: 14658c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) 14668c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 14678c2ecf20Sopenharmony_ci ha->ip_config.ipv4_cache_id); 14688c2ecf20Sopenharmony_ci else 14698c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 14708c2ecf20Sopenharmony_ci ha->ip_config.ipv6_cache_id); 14718c2ecf20Sopenharmony_ci break; 14728c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: 14738c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.tcp_options, 14748c2ecf20Sopenharmony_ci TCPOPT_DNS_SERVER_IP_EN, pval); 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14778c2ecf20Sopenharmony_ci break; 14788c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: 14798c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.tcp_options, 14808c2ecf20Sopenharmony_ci TCPOPT_SLP_DA_INFO_EN, pval); 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14838c2ecf20Sopenharmony_ci break; 14848c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TOS_EN: 14858c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 14868c2ecf20Sopenharmony_ci IPOPT_IPV4_TOS_EN, pval); 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14898c2ecf20Sopenharmony_ci break; 14908c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TOS: 14918c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ha->ip_config.ipv4_tos); 14928c2ecf20Sopenharmony_ci break; 14938c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: 14948c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 14958c2ecf20Sopenharmony_ci IPOPT_GRAT_ARP_EN, pval); 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 14988c2ecf20Sopenharmony_ci break; 14998c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: 15008c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, IPOPT_ALT_CID_EN, 15018c2ecf20Sopenharmony_ci pval); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15048c2ecf20Sopenharmony_ci break; 15058c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: 15068c2ecf20Sopenharmony_ci pval = (ha->ip_config.ipv4_alt_cid_len) ? 15078c2ecf20Sopenharmony_ci (char *)ha->ip_config.ipv4_alt_cid : ""; 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15108c2ecf20Sopenharmony_ci break; 15118c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: 15128c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 15138c2ecf20Sopenharmony_ci IPOPT_REQ_VID_EN, pval); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15168c2ecf20Sopenharmony_ci break; 15178c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: 15188c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 15198c2ecf20Sopenharmony_ci IPOPT_USE_VID_EN, pval); 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15228c2ecf20Sopenharmony_ci break; 15238c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: 15248c2ecf20Sopenharmony_ci pval = (ha->ip_config.ipv4_vid_len) ? 15258c2ecf20Sopenharmony_ci (char *)ha->ip_config.ipv4_vid : ""; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15288c2ecf20Sopenharmony_ci break; 15298c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: 15308c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 15318c2ecf20Sopenharmony_ci IPOPT_LEARN_IQN_EN, pval); 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15348c2ecf20Sopenharmony_ci break; 15358c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: 15368c2ecf20Sopenharmony_ci OP_STATE(~ha->ip_config.ipv4_options, 15378c2ecf20Sopenharmony_ci IPOPT_FRAGMENTATION_DISABLE, pval); 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15408c2ecf20Sopenharmony_ci break; 15418c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: 15428c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 15438c2ecf20Sopenharmony_ci IPOPT_IN_FORWARD_EN, pval); 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15468c2ecf20Sopenharmony_ci break; 15478c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_REDIRECT_EN: 15488c2ecf20Sopenharmony_ci if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { 15498c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv4_options, 15508c2ecf20Sopenharmony_ci IPOPT_ARP_REDIRECT_EN, pval); 15518c2ecf20Sopenharmony_ci } else { 15528c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv6_options, 15538c2ecf20Sopenharmony_ci IPV6_OPT_REDIRECT_EN, pval); 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15568c2ecf20Sopenharmony_ci break; 15578c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TTL: 15588c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ha->ip_config.ipv4_ttl); 15598c2ecf20Sopenharmony_ci break; 15608c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: 15618c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv6_options, 15628c2ecf20Sopenharmony_ci IPV6_OPT_GRAT_NEIGHBOR_ADV_EN, pval); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15658c2ecf20Sopenharmony_ci break; 15668c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_MLD_EN: 15678c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.ipv6_addl_options, 15688c2ecf20Sopenharmony_ci IPV6_ADDOPT_MLD_EN, pval); 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 15718c2ecf20Sopenharmony_ci break; 15728c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: 15738c2ecf20Sopenharmony_ci len = sprintf(buf, "%u\n", ha->ip_config.ipv6_flow_lbl); 15748c2ecf20Sopenharmony_ci break; 15758c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: 15768c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 15778c2ecf20Sopenharmony_ci ha->ip_config.ipv6_traffic_class); 15788c2ecf20Sopenharmony_ci break; 15798c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: 15808c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 15818c2ecf20Sopenharmony_ci ha->ip_config.ipv6_hop_limit); 15828c2ecf20Sopenharmony_ci break; 15838c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: 15848c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 15858c2ecf20Sopenharmony_ci ha->ip_config.ipv6_nd_reach_time); 15868c2ecf20Sopenharmony_ci break; 15878c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: 15888c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 15898c2ecf20Sopenharmony_ci ha->ip_config.ipv6_nd_rexmit_timer); 15908c2ecf20Sopenharmony_ci break; 15918c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: 15928c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 15938c2ecf20Sopenharmony_ci ha->ip_config.ipv6_nd_stale_timeout); 15948c2ecf20Sopenharmony_ci break; 15958c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: 15968c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 15978c2ecf20Sopenharmony_ci ha->ip_config.ipv6_dup_addr_detect_count); 15988c2ecf20Sopenharmony_ci break; 15998c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: 16008c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 16018c2ecf20Sopenharmony_ci ha->ip_config.ipv6_gw_advrt_mtu); 16028c2ecf20Sopenharmony_ci break; 16038c2ecf20Sopenharmony_ci default: 16048c2ecf20Sopenharmony_ci len = -ENOSYS; 16058c2ecf20Sopenharmony_ci } 16068c2ecf20Sopenharmony_ci } else if (param_type == ISCSI_IFACE_PARAM) { 16078c2ecf20Sopenharmony_ci switch (param) { 16088c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: 16098c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", ha->ip_config.def_timeout); 16108c2ecf20Sopenharmony_ci break; 16118c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_HDRDGST_EN: 16128c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16138c2ecf20Sopenharmony_ci ISCSIOPTS_HEADER_DIGEST_EN, pval); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16168c2ecf20Sopenharmony_ci break; 16178c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DATADGST_EN: 16188c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16198c2ecf20Sopenharmony_ci ISCSIOPTS_DATA_DIGEST_EN, pval); 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16228c2ecf20Sopenharmony_ci break; 16238c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_IMM_DATA_EN: 16248c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16258c2ecf20Sopenharmony_ci ISCSIOPTS_IMMEDIATE_DATA_EN, pval); 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16288c2ecf20Sopenharmony_ci break; 16298c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: 16308c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16318c2ecf20Sopenharmony_ci ISCSIOPTS_INITIAL_R2T_EN, pval); 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16348c2ecf20Sopenharmony_ci break; 16358c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: 16368c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16378c2ecf20Sopenharmony_ci ISCSIOPTS_DATA_SEQ_INORDER_EN, pval); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16408c2ecf20Sopenharmony_ci break; 16418c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_PDU_INORDER_EN: 16428c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16438c2ecf20Sopenharmony_ci ISCSIOPTS_DATA_PDU_INORDER_EN, pval); 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16468c2ecf20Sopenharmony_ci break; 16478c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_ERL: 16488c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 16498c2ecf20Sopenharmony_ci (ha->ip_config.iscsi_options & 16508c2ecf20Sopenharmony_ci ISCSIOPTS_ERL)); 16518c2ecf20Sopenharmony_ci break; 16528c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: 16538c2ecf20Sopenharmony_ci len = sprintf(buf, "%u\n", 16548c2ecf20Sopenharmony_ci ha->ip_config.iscsi_max_pdu_size * 16558c2ecf20Sopenharmony_ci BYTE_UNITS); 16568c2ecf20Sopenharmony_ci break; 16578c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_FIRST_BURST: 16588c2ecf20Sopenharmony_ci len = sprintf(buf, "%u\n", 16598c2ecf20Sopenharmony_ci ha->ip_config.iscsi_first_burst_len * 16608c2ecf20Sopenharmony_ci BYTE_UNITS); 16618c2ecf20Sopenharmony_ci break; 16628c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_R2T: 16638c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", 16648c2ecf20Sopenharmony_ci ha->ip_config.iscsi_max_outstnd_r2t); 16658c2ecf20Sopenharmony_ci break; 16668c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_BURST: 16678c2ecf20Sopenharmony_ci len = sprintf(buf, "%u\n", 16688c2ecf20Sopenharmony_ci ha->ip_config.iscsi_max_burst_len * 16698c2ecf20Sopenharmony_ci BYTE_UNITS); 16708c2ecf20Sopenharmony_ci break; 16718c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: 16728c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16738c2ecf20Sopenharmony_ci ISCSIOPTS_CHAP_AUTH_EN, pval); 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16768c2ecf20Sopenharmony_ci break; 16778c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: 16788c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16798c2ecf20Sopenharmony_ci ISCSIOPTS_BIDI_CHAP_EN, pval); 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16828c2ecf20Sopenharmony_ci break; 16838c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: 16848c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16858c2ecf20Sopenharmony_ci ISCSIOPTS_DISCOVERY_AUTH_EN, pval); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16888c2ecf20Sopenharmony_ci break; 16898c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: 16908c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16918c2ecf20Sopenharmony_ci ISCSIOPTS_DISCOVERY_LOGOUT_EN, pval); 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 16948c2ecf20Sopenharmony_ci break; 16958c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: 16968c2ecf20Sopenharmony_ci OP_STATE(ha->ip_config.iscsi_options, 16978c2ecf20Sopenharmony_ci ISCSIOPTS_STRICT_LOGIN_COMP_EN, pval); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", pval); 17008c2ecf20Sopenharmony_ci break; 17018c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_INITIATOR_NAME: 17028c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", ha->ip_config.iscsi_name); 17038c2ecf20Sopenharmony_ci break; 17048c2ecf20Sopenharmony_ci default: 17058c2ecf20Sopenharmony_ci len = -ENOSYS; 17068c2ecf20Sopenharmony_ci } 17078c2ecf20Sopenharmony_ci } 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci return len; 17108c2ecf20Sopenharmony_ci} 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_cistatic struct iscsi_endpoint * 17138c2ecf20Sopenharmony_ciqla4xxx_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, 17148c2ecf20Sopenharmony_ci int non_blocking) 17158c2ecf20Sopenharmony_ci{ 17168c2ecf20Sopenharmony_ci int ret; 17178c2ecf20Sopenharmony_ci struct iscsi_endpoint *ep; 17188c2ecf20Sopenharmony_ci struct qla_endpoint *qla_ep; 17198c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 17208c2ecf20Sopenharmony_ci struct sockaddr_in *addr; 17218c2ecf20Sopenharmony_ci struct sockaddr_in6 *addr6; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if (!shost) { 17248c2ecf20Sopenharmony_ci ret = -ENXIO; 17258c2ecf20Sopenharmony_ci pr_err("%s: shost is NULL\n", __func__); 17268c2ecf20Sopenharmony_ci return ERR_PTR(ret); 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci ha = iscsi_host_priv(shost); 17308c2ecf20Sopenharmony_ci ep = iscsi_create_endpoint(sizeof(struct qla_endpoint)); 17318c2ecf20Sopenharmony_ci if (!ep) { 17328c2ecf20Sopenharmony_ci ret = -ENOMEM; 17338c2ecf20Sopenharmony_ci return ERR_PTR(ret); 17348c2ecf20Sopenharmony_ci } 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci qla_ep = ep->dd_data; 17378c2ecf20Sopenharmony_ci memset(qla_ep, 0, sizeof(struct qla_endpoint)); 17388c2ecf20Sopenharmony_ci if (dst_addr->sa_family == AF_INET) { 17398c2ecf20Sopenharmony_ci memcpy(&qla_ep->dst_addr, dst_addr, sizeof(struct sockaddr_in)); 17408c2ecf20Sopenharmony_ci addr = (struct sockaddr_in *)&qla_ep->dst_addr; 17418c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI4\n", __func__, 17428c2ecf20Sopenharmony_ci (char *)&addr->sin_addr)); 17438c2ecf20Sopenharmony_ci } else if (dst_addr->sa_family == AF_INET6) { 17448c2ecf20Sopenharmony_ci memcpy(&qla_ep->dst_addr, dst_addr, 17458c2ecf20Sopenharmony_ci sizeof(struct sockaddr_in6)); 17468c2ecf20Sopenharmony_ci addr6 = (struct sockaddr_in6 *)&qla_ep->dst_addr; 17478c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI6\n", __func__, 17488c2ecf20Sopenharmony_ci (char *)&addr6->sin6_addr)); 17498c2ecf20Sopenharmony_ci } else { 17508c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: Invalid endpoint\n", 17518c2ecf20Sopenharmony_ci __func__); 17528c2ecf20Sopenharmony_ci } 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci qla_ep->host = shost; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci return ep; 17578c2ecf20Sopenharmony_ci} 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_cistatic int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) 17608c2ecf20Sopenharmony_ci{ 17618c2ecf20Sopenharmony_ci struct qla_endpoint *qla_ep; 17628c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 17638c2ecf20Sopenharmony_ci int ret = 0; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci qla_ep = ep->dd_data; 17668c2ecf20Sopenharmony_ci ha = to_qla_host(qla_ep->host); 17678c2ecf20Sopenharmony_ci DEBUG2(pr_info_ratelimited("%s: host: %ld\n", __func__, ha->host_no)); 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags)) 17708c2ecf20Sopenharmony_ci ret = 1; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci return ret; 17738c2ecf20Sopenharmony_ci} 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_cistatic void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep) 17768c2ecf20Sopenharmony_ci{ 17778c2ecf20Sopenharmony_ci struct qla_endpoint *qla_ep; 17788c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci qla_ep = ep->dd_data; 17818c2ecf20Sopenharmony_ci ha = to_qla_host(qla_ep->host); 17828c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__, 17838c2ecf20Sopenharmony_ci ha->host_no)); 17848c2ecf20Sopenharmony_ci iscsi_destroy_endpoint(ep); 17858c2ecf20Sopenharmony_ci} 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_cistatic int qla4xxx_get_ep_param(struct iscsi_endpoint *ep, 17888c2ecf20Sopenharmony_ci enum iscsi_param param, 17898c2ecf20Sopenharmony_ci char *buf) 17908c2ecf20Sopenharmony_ci{ 17918c2ecf20Sopenharmony_ci struct qla_endpoint *qla_ep = ep->dd_data; 17928c2ecf20Sopenharmony_ci struct sockaddr *dst_addr; 17938c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci if (!qla_ep) 17968c2ecf20Sopenharmony_ci return -ENOTCONN; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci ha = to_qla_host(qla_ep->host); 17998c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__, 18008c2ecf20Sopenharmony_ci ha->host_no)); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci switch (param) { 18038c2ecf20Sopenharmony_ci case ISCSI_PARAM_CONN_PORT: 18048c2ecf20Sopenharmony_ci case ISCSI_PARAM_CONN_ADDRESS: 18058c2ecf20Sopenharmony_ci dst_addr = (struct sockaddr *)&qla_ep->dst_addr; 18068c2ecf20Sopenharmony_ci if (!dst_addr) 18078c2ecf20Sopenharmony_ci return -ENOTCONN; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci return iscsi_conn_get_addr_param((struct sockaddr_storage *) 18108c2ecf20Sopenharmony_ci &qla_ep->dst_addr, param, buf); 18118c2ecf20Sopenharmony_ci default: 18128c2ecf20Sopenharmony_ci return -ENOSYS; 18138c2ecf20Sopenharmony_ci } 18148c2ecf20Sopenharmony_ci} 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_cistatic void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, 18178c2ecf20Sopenharmony_ci struct iscsi_stats *stats) 18188c2ecf20Sopenharmony_ci{ 18198c2ecf20Sopenharmony_ci struct iscsi_session *sess; 18208c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 18218c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 18228c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 18238c2ecf20Sopenharmony_ci struct ql_iscsi_stats *ql_iscsi_stats; 18248c2ecf20Sopenharmony_ci int stats_size; 18258c2ecf20Sopenharmony_ci int ret; 18268c2ecf20Sopenharmony_ci dma_addr_t iscsi_stats_dma; 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci cls_sess = iscsi_conn_to_session(cls_conn); 18298c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 18308c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 18318c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__, 18348c2ecf20Sopenharmony_ci ha->host_no)); 18358c2ecf20Sopenharmony_ci stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats)); 18368c2ecf20Sopenharmony_ci /* Allocate memory */ 18378c2ecf20Sopenharmony_ci ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size, 18388c2ecf20Sopenharmony_ci &iscsi_stats_dma, GFP_KERNEL); 18398c2ecf20Sopenharmony_ci if (!ql_iscsi_stats) { 18408c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 18418c2ecf20Sopenharmony_ci "Unable to allocate memory for iscsi stats\n"); 18428c2ecf20Sopenharmony_ci goto exit_get_stats; 18438c2ecf20Sopenharmony_ci } 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci ret = qla4xxx_get_mgmt_data(ha, ddb_entry->fw_ddb_index, stats_size, 18468c2ecf20Sopenharmony_ci iscsi_stats_dma); 18478c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 18488c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 18498c2ecf20Sopenharmony_ci "Unable to retrieve iscsi stats\n"); 18508c2ecf20Sopenharmony_ci goto free_stats; 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci /* octets */ 18548c2ecf20Sopenharmony_ci stats->txdata_octets = le64_to_cpu(ql_iscsi_stats->tx_data_octets); 18558c2ecf20Sopenharmony_ci stats->rxdata_octets = le64_to_cpu(ql_iscsi_stats->rx_data_octets); 18568c2ecf20Sopenharmony_ci /* xmit pdus */ 18578c2ecf20Sopenharmony_ci stats->noptx_pdus = le32_to_cpu(ql_iscsi_stats->tx_nopout_pdus); 18588c2ecf20Sopenharmony_ci stats->scsicmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_cmd_pdus); 18598c2ecf20Sopenharmony_ci stats->tmfcmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_tmf_cmd_pdus); 18608c2ecf20Sopenharmony_ci stats->login_pdus = le32_to_cpu(ql_iscsi_stats->tx_login_cmd_pdus); 18618c2ecf20Sopenharmony_ci stats->text_pdus = le32_to_cpu(ql_iscsi_stats->tx_text_cmd_pdus); 18628c2ecf20Sopenharmony_ci stats->dataout_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_write_pdus); 18638c2ecf20Sopenharmony_ci stats->logout_pdus = le32_to_cpu(ql_iscsi_stats->tx_logout_cmd_pdus); 18648c2ecf20Sopenharmony_ci stats->snack_pdus = le32_to_cpu(ql_iscsi_stats->tx_snack_req_pdus); 18658c2ecf20Sopenharmony_ci /* recv pdus */ 18668c2ecf20Sopenharmony_ci stats->noprx_pdus = le32_to_cpu(ql_iscsi_stats->rx_nopin_pdus); 18678c2ecf20Sopenharmony_ci stats->scsirsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_resp_pdus); 18688c2ecf20Sopenharmony_ci stats->tmfrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_tmf_resp_pdus); 18698c2ecf20Sopenharmony_ci stats->textrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_text_resp_pdus); 18708c2ecf20Sopenharmony_ci stats->datain_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_read_pdus); 18718c2ecf20Sopenharmony_ci stats->logoutrsp_pdus = 18728c2ecf20Sopenharmony_ci le32_to_cpu(ql_iscsi_stats->rx_logout_resp_pdus); 18738c2ecf20Sopenharmony_ci stats->r2t_pdus = le32_to_cpu(ql_iscsi_stats->rx_r2t_pdus); 18748c2ecf20Sopenharmony_ci stats->async_pdus = le32_to_cpu(ql_iscsi_stats->rx_async_pdus); 18758c2ecf20Sopenharmony_ci stats->rjt_pdus = le32_to_cpu(ql_iscsi_stats->rx_reject_pdus); 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_cifree_stats: 18788c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, stats_size, ql_iscsi_stats, 18798c2ecf20Sopenharmony_ci iscsi_stats_dma); 18808c2ecf20Sopenharmony_ciexit_get_stats: 18818c2ecf20Sopenharmony_ci return; 18828c2ecf20Sopenharmony_ci} 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_cistatic enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc) 18858c2ecf20Sopenharmony_ci{ 18868c2ecf20Sopenharmony_ci struct iscsi_cls_session *session; 18878c2ecf20Sopenharmony_ci unsigned long flags; 18888c2ecf20Sopenharmony_ci enum blk_eh_timer_return ret = BLK_EH_DONE; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci session = starget_to_session(scsi_target(sc->device)); 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci spin_lock_irqsave(&session->lock, flags); 18938c2ecf20Sopenharmony_ci if (session->state == ISCSI_SESSION_FAILED) 18948c2ecf20Sopenharmony_ci ret = BLK_EH_RESET_TIMER; 18958c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&session->lock, flags); 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci return ret; 18988c2ecf20Sopenharmony_ci} 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_cistatic void qla4xxx_set_port_speed(struct Scsi_Host *shost) 19018c2ecf20Sopenharmony_ci{ 19028c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 19038c2ecf20Sopenharmony_ci struct iscsi_cls_host *ihost = shost->shost_data; 19048c2ecf20Sopenharmony_ci uint32_t speed = ISCSI_PORT_SPEED_UNKNOWN; 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci qla4xxx_get_firmware_state(ha); 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci switch (ha->addl_fw_state & 0x0F00) { 19098c2ecf20Sopenharmony_ci case FW_ADDSTATE_LINK_SPEED_10MBPS: 19108c2ecf20Sopenharmony_ci speed = ISCSI_PORT_SPEED_10MBPS; 19118c2ecf20Sopenharmony_ci break; 19128c2ecf20Sopenharmony_ci case FW_ADDSTATE_LINK_SPEED_100MBPS: 19138c2ecf20Sopenharmony_ci speed = ISCSI_PORT_SPEED_100MBPS; 19148c2ecf20Sopenharmony_ci break; 19158c2ecf20Sopenharmony_ci case FW_ADDSTATE_LINK_SPEED_1GBPS: 19168c2ecf20Sopenharmony_ci speed = ISCSI_PORT_SPEED_1GBPS; 19178c2ecf20Sopenharmony_ci break; 19188c2ecf20Sopenharmony_ci case FW_ADDSTATE_LINK_SPEED_10GBPS: 19198c2ecf20Sopenharmony_ci speed = ISCSI_PORT_SPEED_10GBPS; 19208c2ecf20Sopenharmony_ci break; 19218c2ecf20Sopenharmony_ci } 19228c2ecf20Sopenharmony_ci ihost->port_speed = speed; 19238c2ecf20Sopenharmony_ci} 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_cistatic void qla4xxx_set_port_state(struct Scsi_Host *shost) 19268c2ecf20Sopenharmony_ci{ 19278c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 19288c2ecf20Sopenharmony_ci struct iscsi_cls_host *ihost = shost->shost_data; 19298c2ecf20Sopenharmony_ci uint32_t state = ISCSI_PORT_STATE_DOWN; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci if (test_bit(AF_LINK_UP, &ha->flags)) 19328c2ecf20Sopenharmony_ci state = ISCSI_PORT_STATE_UP; 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci ihost->port_state = state; 19358c2ecf20Sopenharmony_ci} 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_cistatic int qla4xxx_host_get_param(struct Scsi_Host *shost, 19388c2ecf20Sopenharmony_ci enum iscsi_host_param param, char *buf) 19398c2ecf20Sopenharmony_ci{ 19408c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 19418c2ecf20Sopenharmony_ci int len; 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci switch (param) { 19448c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_HWADDRESS: 19458c2ecf20Sopenharmony_ci len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN); 19468c2ecf20Sopenharmony_ci break; 19478c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_IPADDRESS: 19488c2ecf20Sopenharmony_ci len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); 19498c2ecf20Sopenharmony_ci break; 19508c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_INITIATOR_NAME: 19518c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", ha->name_string); 19528c2ecf20Sopenharmony_ci break; 19538c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_STATE: 19548c2ecf20Sopenharmony_ci qla4xxx_set_port_state(shost); 19558c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost)); 19568c2ecf20Sopenharmony_ci break; 19578c2ecf20Sopenharmony_ci case ISCSI_HOST_PARAM_PORT_SPEED: 19588c2ecf20Sopenharmony_ci qla4xxx_set_port_speed(shost); 19598c2ecf20Sopenharmony_ci len = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost)); 19608c2ecf20Sopenharmony_ci break; 19618c2ecf20Sopenharmony_ci default: 19628c2ecf20Sopenharmony_ci return -ENOSYS; 19638c2ecf20Sopenharmony_ci } 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci return len; 19668c2ecf20Sopenharmony_ci} 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_cistatic void qla4xxx_create_ipv4_iface(struct scsi_qla_host *ha) 19698c2ecf20Sopenharmony_ci{ 19708c2ecf20Sopenharmony_ci if (ha->iface_ipv4) 19718c2ecf20Sopenharmony_ci return; 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci /* IPv4 */ 19748c2ecf20Sopenharmony_ci ha->iface_ipv4 = iscsi_create_iface(ha->host, 19758c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 19768c2ecf20Sopenharmony_ci ISCSI_IFACE_TYPE_IPV4, 0, 0); 19778c2ecf20Sopenharmony_ci if (!ha->iface_ipv4) 19788c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Could not create IPv4 iSCSI " 19798c2ecf20Sopenharmony_ci "iface0.\n"); 19808c2ecf20Sopenharmony_ci} 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_cistatic void qla4xxx_create_ipv6_iface(struct scsi_qla_host *ha) 19838c2ecf20Sopenharmony_ci{ 19848c2ecf20Sopenharmony_ci if (!ha->iface_ipv6_0) 19858c2ecf20Sopenharmony_ci /* IPv6 iface-0 */ 19868c2ecf20Sopenharmony_ci ha->iface_ipv6_0 = iscsi_create_iface(ha->host, 19878c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 19888c2ecf20Sopenharmony_ci ISCSI_IFACE_TYPE_IPV6, 0, 19898c2ecf20Sopenharmony_ci 0); 19908c2ecf20Sopenharmony_ci if (!ha->iface_ipv6_0) 19918c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI " 19928c2ecf20Sopenharmony_ci "iface0.\n"); 19938c2ecf20Sopenharmony_ci 19948c2ecf20Sopenharmony_ci if (!ha->iface_ipv6_1) 19958c2ecf20Sopenharmony_ci /* IPv6 iface-1 */ 19968c2ecf20Sopenharmony_ci ha->iface_ipv6_1 = iscsi_create_iface(ha->host, 19978c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 19988c2ecf20Sopenharmony_ci ISCSI_IFACE_TYPE_IPV6, 1, 19998c2ecf20Sopenharmony_ci 0); 20008c2ecf20Sopenharmony_ci if (!ha->iface_ipv6_1) 20018c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI " 20028c2ecf20Sopenharmony_ci "iface1.\n"); 20038c2ecf20Sopenharmony_ci} 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_cistatic void qla4xxx_create_ifaces(struct scsi_qla_host *ha) 20068c2ecf20Sopenharmony_ci{ 20078c2ecf20Sopenharmony_ci if (ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE) 20088c2ecf20Sopenharmony_ci qla4xxx_create_ipv4_iface(ha); 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci if (ha->ip_config.ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE) 20118c2ecf20Sopenharmony_ci qla4xxx_create_ipv6_iface(ha); 20128c2ecf20Sopenharmony_ci} 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_cistatic void qla4xxx_destroy_ipv4_iface(struct scsi_qla_host *ha) 20158c2ecf20Sopenharmony_ci{ 20168c2ecf20Sopenharmony_ci if (ha->iface_ipv4) { 20178c2ecf20Sopenharmony_ci iscsi_destroy_iface(ha->iface_ipv4); 20188c2ecf20Sopenharmony_ci ha->iface_ipv4 = NULL; 20198c2ecf20Sopenharmony_ci } 20208c2ecf20Sopenharmony_ci} 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_cistatic void qla4xxx_destroy_ipv6_iface(struct scsi_qla_host *ha) 20238c2ecf20Sopenharmony_ci{ 20248c2ecf20Sopenharmony_ci if (ha->iface_ipv6_0) { 20258c2ecf20Sopenharmony_ci iscsi_destroy_iface(ha->iface_ipv6_0); 20268c2ecf20Sopenharmony_ci ha->iface_ipv6_0 = NULL; 20278c2ecf20Sopenharmony_ci } 20288c2ecf20Sopenharmony_ci if (ha->iface_ipv6_1) { 20298c2ecf20Sopenharmony_ci iscsi_destroy_iface(ha->iface_ipv6_1); 20308c2ecf20Sopenharmony_ci ha->iface_ipv6_1 = NULL; 20318c2ecf20Sopenharmony_ci } 20328c2ecf20Sopenharmony_ci} 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_cistatic void qla4xxx_destroy_ifaces(struct scsi_qla_host *ha) 20358c2ecf20Sopenharmony_ci{ 20368c2ecf20Sopenharmony_ci qla4xxx_destroy_ipv4_iface(ha); 20378c2ecf20Sopenharmony_ci qla4xxx_destroy_ipv6_iface(ha); 20388c2ecf20Sopenharmony_ci} 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_cistatic void qla4xxx_set_ipv6(struct scsi_qla_host *ha, 20418c2ecf20Sopenharmony_ci struct iscsi_iface_param_info *iface_param, 20428c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb) 20438c2ecf20Sopenharmony_ci{ 20448c2ecf20Sopenharmony_ci /* 20458c2ecf20Sopenharmony_ci * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg. 20468c2ecf20Sopenharmony_ci * iface_num 1 is valid only for IPv6 Addr. 20478c2ecf20Sopenharmony_ci */ 20488c2ecf20Sopenharmony_ci switch (iface_param->param) { 20498c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR: 20508c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 20518c2ecf20Sopenharmony_ci /* IPv6 Addr 1 */ 20528c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv6_addr1, iface_param->value, 20538c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_addr1)); 20548c2ecf20Sopenharmony_ci else 20558c2ecf20Sopenharmony_ci /* IPv6 Addr 0 */ 20568c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv6_addr0, iface_param->value, 20578c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_addr0)); 20588c2ecf20Sopenharmony_ci break; 20598c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL: 20608c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 20618c2ecf20Sopenharmony_ci break; 20628c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8], 20638c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_if_id)); 20648c2ecf20Sopenharmony_ci break; 20658c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ROUTER: 20668c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 20678c2ecf20Sopenharmony_ci break; 20688c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value, 20698c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_dflt_rtr_addr)); 20708c2ecf20Sopenharmony_ci break; 20718c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: 20728c2ecf20Sopenharmony_ci /* Autocfg applies to even interface */ 20738c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 20748c2ecf20Sopenharmony_ci break; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE) 20778c2ecf20Sopenharmony_ci init_fw_cb->ipv6_addtl_opts &= 20788c2ecf20Sopenharmony_ci cpu_to_le16( 20798c2ecf20Sopenharmony_ci ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE); 20808c2ecf20Sopenharmony_ci else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE) 20818c2ecf20Sopenharmony_ci init_fw_cb->ipv6_addtl_opts |= 20828c2ecf20Sopenharmony_ci cpu_to_le16( 20838c2ecf20Sopenharmony_ci IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE); 20848c2ecf20Sopenharmony_ci else 20858c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 20868c2ecf20Sopenharmony_ci "Invalid autocfg setting for IPv6 addr\n"); 20878c2ecf20Sopenharmony_ci break; 20888c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: 20898c2ecf20Sopenharmony_ci /* Autocfg applies to even interface */ 20908c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 20918c2ecf20Sopenharmony_ci break; 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci if (iface_param->value[0] == 20948c2ecf20Sopenharmony_ci ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE) 20958c2ecf20Sopenharmony_ci init_fw_cb->ipv6_addtl_opts |= cpu_to_le16( 20968c2ecf20Sopenharmony_ci IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR); 20978c2ecf20Sopenharmony_ci else if (iface_param->value[0] == 20988c2ecf20Sopenharmony_ci ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE) 20998c2ecf20Sopenharmony_ci init_fw_cb->ipv6_addtl_opts &= cpu_to_le16( 21008c2ecf20Sopenharmony_ci ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR); 21018c2ecf20Sopenharmony_ci else 21028c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 21038c2ecf20Sopenharmony_ci "Invalid autocfg setting for IPv6 linklocal addr\n"); 21048c2ecf20Sopenharmony_ci break; 21058c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG: 21068c2ecf20Sopenharmony_ci /* Autocfg applies to even interface */ 21078c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21088c2ecf20Sopenharmony_ci break; 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE) 21118c2ecf20Sopenharmony_ci memset(init_fw_cb->ipv6_dflt_rtr_addr, 0, 21128c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv6_dflt_rtr_addr)); 21138c2ecf20Sopenharmony_ci break; 21148c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 21158c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_IFACE_ENABLE) { 21168c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts |= 21178c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE); 21188c2ecf20Sopenharmony_ci qla4xxx_create_ipv6_iface(ha); 21198c2ecf20Sopenharmony_ci } else { 21208c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts &= 21218c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE & 21228c2ecf20Sopenharmony_ci 0xFFFF); 21238c2ecf20Sopenharmony_ci qla4xxx_destroy_ipv6_iface(ha); 21248c2ecf20Sopenharmony_ci } 21258c2ecf20Sopenharmony_ci break; 21268c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_TAG: 21278c2ecf20Sopenharmony_ci if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag)) 21288c2ecf20Sopenharmony_ci break; 21298c2ecf20Sopenharmony_ci init_fw_cb->ipv6_vlan_tag = 21308c2ecf20Sopenharmony_ci cpu_to_be16(*(uint16_t *)iface_param->value); 21318c2ecf20Sopenharmony_ci break; 21328c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 21338c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_VLAN_ENABLE) 21348c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts |= 21358c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_OPT_VLAN_TAGGING_ENABLE); 21368c2ecf20Sopenharmony_ci else 21378c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts &= 21388c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_OPT_VLAN_TAGGING_ENABLE); 21398c2ecf20Sopenharmony_ci break; 21408c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_MTU: 21418c2ecf20Sopenharmony_ci init_fw_cb->eth_mtu_size = 21428c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 21438c2ecf20Sopenharmony_ci break; 21448c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_PORT: 21458c2ecf20Sopenharmony_ci /* Autocfg applies to even interface */ 21468c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21478c2ecf20Sopenharmony_ci break; 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci init_fw_cb->ipv6_port = 21508c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 21518c2ecf20Sopenharmony_ci break; 21528c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_DELAYED_ACK_EN: 21538c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21548c2ecf20Sopenharmony_ci break; 21558c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 21568c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts |= 21578c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_TCPOPT_DELAYED_ACK_DISABLE); 21588c2ecf20Sopenharmony_ci else 21598c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts &= 21608c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_TCPOPT_DELAYED_ACK_DISABLE & 21618c2ecf20Sopenharmony_ci 0xFFFF); 21628c2ecf20Sopenharmony_ci break; 21638c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: 21648c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21658c2ecf20Sopenharmony_ci break; 21668c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 21678c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts |= 21688c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_TCPOPT_NAGLE_ALGO_DISABLE); 21698c2ecf20Sopenharmony_ci else 21708c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts &= 21718c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_TCPOPT_NAGLE_ALGO_DISABLE); 21728c2ecf20Sopenharmony_ci break; 21738c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF_DISABLE: 21748c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21758c2ecf20Sopenharmony_ci break; 21768c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 21778c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts |= 21788c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_TCPOPT_WINDOW_SCALE_DISABLE); 21798c2ecf20Sopenharmony_ci else 21808c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts &= 21818c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_TCPOPT_WINDOW_SCALE_DISABLE); 21828c2ecf20Sopenharmony_ci break; 21838c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF: 21848c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21858c2ecf20Sopenharmony_ci break; 21868c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_wsf = iface_param->value[0]; 21878c2ecf20Sopenharmony_ci break; 21888c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMER_SCALE: 21898c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21908c2ecf20Sopenharmony_ci break; 21918c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts &= 21928c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_TCPOPT_TIMER_SCALE); 21938c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts |= 21948c2ecf20Sopenharmony_ci cpu_to_le16((iface_param->value[0] << 1) & 21958c2ecf20Sopenharmony_ci IPV6_TCPOPT_TIMER_SCALE); 21968c2ecf20Sopenharmony_ci break; 21978c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: 21988c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 21998c2ecf20Sopenharmony_ci break; 22008c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 22018c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts |= 22028c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_TCPOPT_TIMESTAMP_EN); 22038c2ecf20Sopenharmony_ci else 22048c2ecf20Sopenharmony_ci init_fw_cb->ipv6_tcp_opts &= 22058c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_TCPOPT_TIMESTAMP_EN); 22068c2ecf20Sopenharmony_ci break; 22078c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: 22088c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22098c2ecf20Sopenharmony_ci break; 22108c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 22118c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts |= 22128c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_OPT_GRAT_NEIGHBOR_ADV_EN); 22138c2ecf20Sopenharmony_ci else 22148c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts &= 22158c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_OPT_GRAT_NEIGHBOR_ADV_EN); 22168c2ecf20Sopenharmony_ci break; 22178c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_REDIRECT_EN: 22188c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22198c2ecf20Sopenharmony_ci break; 22208c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 22218c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts |= 22228c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_OPT_REDIRECT_EN); 22238c2ecf20Sopenharmony_ci else 22248c2ecf20Sopenharmony_ci init_fw_cb->ipv6_opts &= 22258c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_OPT_REDIRECT_EN); 22268c2ecf20Sopenharmony_ci break; 22278c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_MLD_EN: 22288c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22298c2ecf20Sopenharmony_ci break; 22308c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 22318c2ecf20Sopenharmony_ci init_fw_cb->ipv6_addtl_opts |= 22328c2ecf20Sopenharmony_ci cpu_to_le16(IPV6_ADDOPT_MLD_EN); 22338c2ecf20Sopenharmony_ci else 22348c2ecf20Sopenharmony_ci init_fw_cb->ipv6_addtl_opts &= 22358c2ecf20Sopenharmony_ci cpu_to_le16(~IPV6_ADDOPT_MLD_EN); 22368c2ecf20Sopenharmony_ci break; 22378c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: 22388c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22398c2ecf20Sopenharmony_ci break; 22408c2ecf20Sopenharmony_ci init_fw_cb->ipv6_flow_lbl = 22418c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 22428c2ecf20Sopenharmony_ci break; 22438c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: 22448c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22458c2ecf20Sopenharmony_ci break; 22468c2ecf20Sopenharmony_ci init_fw_cb->ipv6_traffic_class = iface_param->value[0]; 22478c2ecf20Sopenharmony_ci break; 22488c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: 22498c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22508c2ecf20Sopenharmony_ci break; 22518c2ecf20Sopenharmony_ci init_fw_cb->ipv6_hop_limit = iface_param->value[0]; 22528c2ecf20Sopenharmony_ci break; 22538c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: 22548c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22558c2ecf20Sopenharmony_ci break; 22568c2ecf20Sopenharmony_ci init_fw_cb->ipv6_nd_reach_time = 22578c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value); 22588c2ecf20Sopenharmony_ci break; 22598c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: 22608c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22618c2ecf20Sopenharmony_ci break; 22628c2ecf20Sopenharmony_ci init_fw_cb->ipv6_nd_rexmit_timer = 22638c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value); 22648c2ecf20Sopenharmony_ci break; 22658c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: 22668c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22678c2ecf20Sopenharmony_ci break; 22688c2ecf20Sopenharmony_ci init_fw_cb->ipv6_nd_stale_timeout = 22698c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value); 22708c2ecf20Sopenharmony_ci break; 22718c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: 22728c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22738c2ecf20Sopenharmony_ci break; 22748c2ecf20Sopenharmony_ci init_fw_cb->ipv6_dup_addr_detect_count = iface_param->value[0]; 22758c2ecf20Sopenharmony_ci break; 22768c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: 22778c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 22788c2ecf20Sopenharmony_ci break; 22798c2ecf20Sopenharmony_ci init_fw_cb->ipv6_gw_advrt_mtu = 22808c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value); 22818c2ecf20Sopenharmony_ci break; 22828c2ecf20Sopenharmony_ci default: 22838c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n", 22848c2ecf20Sopenharmony_ci iface_param->param); 22858c2ecf20Sopenharmony_ci break; 22868c2ecf20Sopenharmony_ci } 22878c2ecf20Sopenharmony_ci} 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_cistatic void qla4xxx_set_ipv4(struct scsi_qla_host *ha, 22908c2ecf20Sopenharmony_ci struct iscsi_iface_param_info *iface_param, 22918c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb) 22928c2ecf20Sopenharmony_ci{ 22938c2ecf20Sopenharmony_ci switch (iface_param->param) { 22948c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_ADDR: 22958c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv4_addr, iface_param->value, 22968c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_addr)); 22978c2ecf20Sopenharmony_ci break; 22988c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_SUBNET: 22998c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv4_subnet, iface_param->value, 23008c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_subnet)); 23018c2ecf20Sopenharmony_ci break; 23028c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GW: 23038c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value, 23048c2ecf20Sopenharmony_ci sizeof(init_fw_cb->ipv4_gw_addr)); 23058c2ecf20Sopenharmony_ci break; 23068c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_BOOTPROTO: 23078c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP) 23088c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 23098c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_DHCP_ENABLE); 23108c2ecf20Sopenharmony_ci else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC) 23118c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 23128c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_DHCP_ENABLE); 23138c2ecf20Sopenharmony_ci else 23148c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n"); 23158c2ecf20Sopenharmony_ci break; 23168c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IFACE_ENABLE: 23178c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_IFACE_ENABLE) { 23188c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 23198c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE); 23208c2ecf20Sopenharmony_ci qla4xxx_create_ipv4_iface(ha); 23218c2ecf20Sopenharmony_ci } else { 23228c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 23238c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE & 23248c2ecf20Sopenharmony_ci 0xFFFF); 23258c2ecf20Sopenharmony_ci qla4xxx_destroy_ipv4_iface(ha); 23268c2ecf20Sopenharmony_ci } 23278c2ecf20Sopenharmony_ci break; 23288c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_TAG: 23298c2ecf20Sopenharmony_ci if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag)) 23308c2ecf20Sopenharmony_ci break; 23318c2ecf20Sopenharmony_ci init_fw_cb->ipv4_vlan_tag = 23328c2ecf20Sopenharmony_ci cpu_to_be16(*(uint16_t *)iface_param->value); 23338c2ecf20Sopenharmony_ci break; 23348c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_VLAN_ENABLED: 23358c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_VLAN_ENABLE) 23368c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 23378c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_VLAN_TAGGING_ENABLE); 23388c2ecf20Sopenharmony_ci else 23398c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 23408c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_VLAN_TAGGING_ENABLE); 23418c2ecf20Sopenharmony_ci break; 23428c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_MTU: 23438c2ecf20Sopenharmony_ci init_fw_cb->eth_mtu_size = 23448c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 23458c2ecf20Sopenharmony_ci break; 23468c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_PORT: 23478c2ecf20Sopenharmony_ci init_fw_cb->ipv4_port = 23488c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 23498c2ecf20Sopenharmony_ci break; 23508c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_DELAYED_ACK_EN: 23518c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 23528c2ecf20Sopenharmony_ci break; 23538c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 23548c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 23558c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_DELAYED_ACK_DISABLE); 23568c2ecf20Sopenharmony_ci else 23578c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 23588c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_DELAYED_ACK_DISABLE & 23598c2ecf20Sopenharmony_ci 0xFFFF); 23608c2ecf20Sopenharmony_ci break; 23618c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: 23628c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 23638c2ecf20Sopenharmony_ci break; 23648c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 23658c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 23668c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_NAGLE_ALGO_DISABLE); 23678c2ecf20Sopenharmony_ci else 23688c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 23698c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_NAGLE_ALGO_DISABLE); 23708c2ecf20Sopenharmony_ci break; 23718c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF_DISABLE: 23728c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 23738c2ecf20Sopenharmony_ci break; 23748c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 23758c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 23768c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_WINDOW_SCALE_DISABLE); 23778c2ecf20Sopenharmony_ci else 23788c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 23798c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_WINDOW_SCALE_DISABLE); 23808c2ecf20Sopenharmony_ci break; 23818c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_WSF: 23828c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 23838c2ecf20Sopenharmony_ci break; 23848c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_wsf = iface_param->value[0]; 23858c2ecf20Sopenharmony_ci break; 23868c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMER_SCALE: 23878c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 23888c2ecf20Sopenharmony_ci break; 23898c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= cpu_to_le16(~TCPOPT_TIMER_SCALE); 23908c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 23918c2ecf20Sopenharmony_ci cpu_to_le16((iface_param->value[0] << 1) & 23928c2ecf20Sopenharmony_ci TCPOPT_TIMER_SCALE); 23938c2ecf20Sopenharmony_ci break; 23948c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: 23958c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 23968c2ecf20Sopenharmony_ci break; 23978c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 23988c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 23998c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_TIMESTAMP_ENABLE); 24008c2ecf20Sopenharmony_ci else 24018c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 24028c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_TIMESTAMP_ENABLE); 24038c2ecf20Sopenharmony_ci break; 24048c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: 24058c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24068c2ecf20Sopenharmony_ci break; 24078c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24088c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 24098c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_DNS_SERVER_IP_EN); 24108c2ecf20Sopenharmony_ci else 24118c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 24128c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_DNS_SERVER_IP_EN); 24138c2ecf20Sopenharmony_ci break; 24148c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: 24158c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24168c2ecf20Sopenharmony_ci break; 24178c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24188c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts |= 24198c2ecf20Sopenharmony_ci cpu_to_le16(TCPOPT_SLP_DA_INFO_EN); 24208c2ecf20Sopenharmony_ci else 24218c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tcp_opts &= 24228c2ecf20Sopenharmony_ci cpu_to_le16(~TCPOPT_SLP_DA_INFO_EN); 24238c2ecf20Sopenharmony_ci break; 24248c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TOS_EN: 24258c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24268c2ecf20Sopenharmony_ci break; 24278c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24288c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 24298c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_IPV4_TOS_EN); 24308c2ecf20Sopenharmony_ci else 24318c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 24328c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_IPV4_TOS_EN); 24338c2ecf20Sopenharmony_ci break; 24348c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TOS: 24358c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24368c2ecf20Sopenharmony_ci break; 24378c2ecf20Sopenharmony_ci init_fw_cb->ipv4_tos = iface_param->value[0]; 24388c2ecf20Sopenharmony_ci break; 24398c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: 24408c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24418c2ecf20Sopenharmony_ci break; 24428c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24438c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 24448c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_GRAT_ARP_EN); 24458c2ecf20Sopenharmony_ci else 24468c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 24478c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_GRAT_ARP_EN); 24488c2ecf20Sopenharmony_ci break; 24498c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: 24508c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24518c2ecf20Sopenharmony_ci break; 24528c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24538c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 24548c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_ALT_CID_EN); 24558c2ecf20Sopenharmony_ci else 24568c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 24578c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_ALT_CID_EN); 24588c2ecf20Sopenharmony_ci break; 24598c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: 24608c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24618c2ecf20Sopenharmony_ci break; 24628c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv4_dhcp_alt_cid, iface_param->value, 24638c2ecf20Sopenharmony_ci (sizeof(init_fw_cb->ipv4_dhcp_alt_cid) - 1)); 24648c2ecf20Sopenharmony_ci init_fw_cb->ipv4_dhcp_alt_cid_len = 24658c2ecf20Sopenharmony_ci strlen(init_fw_cb->ipv4_dhcp_alt_cid); 24668c2ecf20Sopenharmony_ci break; 24678c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: 24688c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24698c2ecf20Sopenharmony_ci break; 24708c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24718c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 24728c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_REQ_VID_EN); 24738c2ecf20Sopenharmony_ci else 24748c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 24758c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_REQ_VID_EN); 24768c2ecf20Sopenharmony_ci break; 24778c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: 24788c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24798c2ecf20Sopenharmony_ci break; 24808c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24818c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 24828c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_USE_VID_EN); 24838c2ecf20Sopenharmony_ci else 24848c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 24858c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_USE_VID_EN); 24868c2ecf20Sopenharmony_ci break; 24878c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: 24888c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24898c2ecf20Sopenharmony_ci break; 24908c2ecf20Sopenharmony_ci memcpy(init_fw_cb->ipv4_dhcp_vid, iface_param->value, 24918c2ecf20Sopenharmony_ci (sizeof(init_fw_cb->ipv4_dhcp_vid) - 1)); 24928c2ecf20Sopenharmony_ci init_fw_cb->ipv4_dhcp_vid_len = 24938c2ecf20Sopenharmony_ci strlen(init_fw_cb->ipv4_dhcp_vid); 24948c2ecf20Sopenharmony_ci break; 24958c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: 24968c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 24978c2ecf20Sopenharmony_ci break; 24988c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 24998c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 25008c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_LEARN_IQN_EN); 25018c2ecf20Sopenharmony_ci else 25028c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 25038c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_LEARN_IQN_EN); 25048c2ecf20Sopenharmony_ci break; 25058c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: 25068c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25078c2ecf20Sopenharmony_ci break; 25088c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) 25098c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 25108c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_FRAGMENTATION_DISABLE); 25118c2ecf20Sopenharmony_ci else 25128c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 25138c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_FRAGMENTATION_DISABLE); 25148c2ecf20Sopenharmony_ci break; 25158c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: 25168c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25178c2ecf20Sopenharmony_ci break; 25188c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 25198c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 25208c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_IN_FORWARD_EN); 25218c2ecf20Sopenharmony_ci else 25228c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 25238c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_IN_FORWARD_EN); 25248c2ecf20Sopenharmony_ci break; 25258c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_REDIRECT_EN: 25268c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25278c2ecf20Sopenharmony_ci break; 25288c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 25298c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts |= 25308c2ecf20Sopenharmony_ci cpu_to_le16(IPOPT_ARP_REDIRECT_EN); 25318c2ecf20Sopenharmony_ci else 25328c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ip_opts &= 25338c2ecf20Sopenharmony_ci cpu_to_le16(~IPOPT_ARP_REDIRECT_EN); 25348c2ecf20Sopenharmony_ci break; 25358c2ecf20Sopenharmony_ci case ISCSI_NET_PARAM_IPV4_TTL: 25368c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25378c2ecf20Sopenharmony_ci break; 25388c2ecf20Sopenharmony_ci init_fw_cb->ipv4_ttl = iface_param->value[0]; 25398c2ecf20Sopenharmony_ci break; 25408c2ecf20Sopenharmony_ci default: 25418c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n", 25428c2ecf20Sopenharmony_ci iface_param->param); 25438c2ecf20Sopenharmony_ci break; 25448c2ecf20Sopenharmony_ci } 25458c2ecf20Sopenharmony_ci} 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_cistatic void qla4xxx_set_iscsi_param(struct scsi_qla_host *ha, 25488c2ecf20Sopenharmony_ci struct iscsi_iface_param_info *iface_param, 25498c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb) 25508c2ecf20Sopenharmony_ci{ 25518c2ecf20Sopenharmony_ci switch (iface_param->param) { 25528c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: 25538c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25548c2ecf20Sopenharmony_ci break; 25558c2ecf20Sopenharmony_ci init_fw_cb->def_timeout = 25568c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 25578c2ecf20Sopenharmony_ci break; 25588c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_HDRDGST_EN: 25598c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25608c2ecf20Sopenharmony_ci break; 25618c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 25628c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 25638c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_HEADER_DIGEST_EN); 25648c2ecf20Sopenharmony_ci else 25658c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 25668c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_HEADER_DIGEST_EN); 25678c2ecf20Sopenharmony_ci break; 25688c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DATADGST_EN: 25698c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25708c2ecf20Sopenharmony_ci break; 25718c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 25728c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 25738c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_DATA_DIGEST_EN); 25748c2ecf20Sopenharmony_ci else 25758c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 25768c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_DATA_DIGEST_EN); 25778c2ecf20Sopenharmony_ci break; 25788c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_IMM_DATA_EN: 25798c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25808c2ecf20Sopenharmony_ci break; 25818c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 25828c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 25838c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_IMMEDIATE_DATA_EN); 25848c2ecf20Sopenharmony_ci else 25858c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 25868c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_IMMEDIATE_DATA_EN); 25878c2ecf20Sopenharmony_ci break; 25888c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: 25898c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 25908c2ecf20Sopenharmony_ci break; 25918c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 25928c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 25938c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_INITIAL_R2T_EN); 25948c2ecf20Sopenharmony_ci else 25958c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 25968c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_INITIAL_R2T_EN); 25978c2ecf20Sopenharmony_ci break; 25988c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: 25998c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26008c2ecf20Sopenharmony_ci break; 26018c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26028c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26038c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_DATA_SEQ_INORDER_EN); 26048c2ecf20Sopenharmony_ci else 26058c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 26068c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_DATA_SEQ_INORDER_EN); 26078c2ecf20Sopenharmony_ci break; 26088c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_PDU_INORDER_EN: 26098c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26108c2ecf20Sopenharmony_ci break; 26118c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26128c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26138c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_DATA_PDU_INORDER_EN); 26148c2ecf20Sopenharmony_ci else 26158c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 26168c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_DATA_PDU_INORDER_EN); 26178c2ecf20Sopenharmony_ci break; 26188c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_ERL: 26198c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26208c2ecf20Sopenharmony_ci break; 26218c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= cpu_to_le16(~ISCSIOPTS_ERL); 26228c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= cpu_to_le16(iface_param->value[0] & 26238c2ecf20Sopenharmony_ci ISCSIOPTS_ERL); 26248c2ecf20Sopenharmony_ci break; 26258c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: 26268c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26278c2ecf20Sopenharmony_ci break; 26288c2ecf20Sopenharmony_ci init_fw_cb->iscsi_max_pdu_size = 26298c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value) / 26308c2ecf20Sopenharmony_ci BYTE_UNITS; 26318c2ecf20Sopenharmony_ci break; 26328c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_FIRST_BURST: 26338c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26348c2ecf20Sopenharmony_ci break; 26358c2ecf20Sopenharmony_ci init_fw_cb->iscsi_fburst_len = 26368c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value) / 26378c2ecf20Sopenharmony_ci BYTE_UNITS; 26388c2ecf20Sopenharmony_ci break; 26398c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_R2T: 26408c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26418c2ecf20Sopenharmony_ci break; 26428c2ecf20Sopenharmony_ci init_fw_cb->iscsi_max_outstnd_r2t = 26438c2ecf20Sopenharmony_ci cpu_to_le16(*(uint16_t *)iface_param->value); 26448c2ecf20Sopenharmony_ci break; 26458c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_MAX_BURST: 26468c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26478c2ecf20Sopenharmony_ci break; 26488c2ecf20Sopenharmony_ci init_fw_cb->iscsi_max_burst_len = 26498c2ecf20Sopenharmony_ci cpu_to_le32(*(uint32_t *)iface_param->value) / 26508c2ecf20Sopenharmony_ci BYTE_UNITS; 26518c2ecf20Sopenharmony_ci break; 26528c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: 26538c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26548c2ecf20Sopenharmony_ci break; 26558c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26568c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26578c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_CHAP_AUTH_EN); 26588c2ecf20Sopenharmony_ci else 26598c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 26608c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_CHAP_AUTH_EN); 26618c2ecf20Sopenharmony_ci break; 26628c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: 26638c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26648c2ecf20Sopenharmony_ci break; 26658c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26668c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26678c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_BIDI_CHAP_EN); 26688c2ecf20Sopenharmony_ci else 26698c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 26708c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_BIDI_CHAP_EN); 26718c2ecf20Sopenharmony_ci break; 26728c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: 26738c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26748c2ecf20Sopenharmony_ci break; 26758c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26768c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26778c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_DISCOVERY_AUTH_EN); 26788c2ecf20Sopenharmony_ci else 26798c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 26808c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_DISCOVERY_AUTH_EN); 26818c2ecf20Sopenharmony_ci break; 26828c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: 26838c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26848c2ecf20Sopenharmony_ci break; 26858c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26868c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26878c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_DISCOVERY_LOGOUT_EN); 26888c2ecf20Sopenharmony_ci else 26898c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 26908c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_DISCOVERY_LOGOUT_EN); 26918c2ecf20Sopenharmony_ci break; 26928c2ecf20Sopenharmony_ci case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: 26938c2ecf20Sopenharmony_ci if (iface_param->iface_num & 0x1) 26948c2ecf20Sopenharmony_ci break; 26958c2ecf20Sopenharmony_ci if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) 26968c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts |= 26978c2ecf20Sopenharmony_ci cpu_to_le16(ISCSIOPTS_STRICT_LOGIN_COMP_EN); 26988c2ecf20Sopenharmony_ci else 26998c2ecf20Sopenharmony_ci init_fw_cb->iscsi_opts &= 27008c2ecf20Sopenharmony_ci cpu_to_le16(~ISCSIOPTS_STRICT_LOGIN_COMP_EN); 27018c2ecf20Sopenharmony_ci break; 27028c2ecf20Sopenharmony_ci default: 27038c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Unknown iscsi param = %d\n", 27048c2ecf20Sopenharmony_ci iface_param->param); 27058c2ecf20Sopenharmony_ci break; 27068c2ecf20Sopenharmony_ci } 27078c2ecf20Sopenharmony_ci} 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_cistatic void 27108c2ecf20Sopenharmony_ciqla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb) 27118c2ecf20Sopenharmony_ci{ 27128c2ecf20Sopenharmony_ci struct addr_ctrl_blk_def *acb; 27138c2ecf20Sopenharmony_ci acb = (struct addr_ctrl_blk_def *)init_fw_cb; 27148c2ecf20Sopenharmony_ci memset(acb->reserved1, 0, sizeof(acb->reserved1)); 27158c2ecf20Sopenharmony_ci memset(acb->reserved2, 0, sizeof(acb->reserved2)); 27168c2ecf20Sopenharmony_ci memset(acb->reserved3, 0, sizeof(acb->reserved3)); 27178c2ecf20Sopenharmony_ci memset(acb->reserved4, 0, sizeof(acb->reserved4)); 27188c2ecf20Sopenharmony_ci memset(acb->reserved5, 0, sizeof(acb->reserved5)); 27198c2ecf20Sopenharmony_ci memset(acb->reserved6, 0, sizeof(acb->reserved6)); 27208c2ecf20Sopenharmony_ci memset(acb->reserved7, 0, sizeof(acb->reserved7)); 27218c2ecf20Sopenharmony_ci memset(acb->reserved8, 0, sizeof(acb->reserved8)); 27228c2ecf20Sopenharmony_ci memset(acb->reserved9, 0, sizeof(acb->reserved9)); 27238c2ecf20Sopenharmony_ci memset(acb->reserved10, 0, sizeof(acb->reserved10)); 27248c2ecf20Sopenharmony_ci memset(acb->reserved11, 0, sizeof(acb->reserved11)); 27258c2ecf20Sopenharmony_ci memset(acb->reserved12, 0, sizeof(acb->reserved12)); 27268c2ecf20Sopenharmony_ci memset(acb->reserved13, 0, sizeof(acb->reserved13)); 27278c2ecf20Sopenharmony_ci memset(acb->reserved14, 0, sizeof(acb->reserved14)); 27288c2ecf20Sopenharmony_ci memset(acb->reserved15, 0, sizeof(acb->reserved15)); 27298c2ecf20Sopenharmony_ci} 27308c2ecf20Sopenharmony_ci 27318c2ecf20Sopenharmony_cistatic int 27328c2ecf20Sopenharmony_ciqla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) 27338c2ecf20Sopenharmony_ci{ 27348c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 27358c2ecf20Sopenharmony_ci int rval = 0; 27368c2ecf20Sopenharmony_ci struct iscsi_iface_param_info *iface_param = NULL; 27378c2ecf20Sopenharmony_ci struct addr_ctrl_blk *init_fw_cb = NULL; 27388c2ecf20Sopenharmony_ci dma_addr_t init_fw_cb_dma; 27398c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 27408c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 27418c2ecf20Sopenharmony_ci uint32_t rem = len; 27428c2ecf20Sopenharmony_ci struct nlattr *attr; 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci init_fw_cb = dma_alloc_coherent(&ha->pdev->dev, 27458c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk), 27468c2ecf20Sopenharmony_ci &init_fw_cb_dma, GFP_KERNEL); 27478c2ecf20Sopenharmony_ci if (!init_fw_cb) { 27488c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n", 27498c2ecf20Sopenharmony_ci __func__); 27508c2ecf20Sopenharmony_ci return -ENOMEM; 27518c2ecf20Sopenharmony_ci } 27528c2ecf20Sopenharmony_ci 27538c2ecf20Sopenharmony_ci memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 27548c2ecf20Sopenharmony_ci memset(&mbox_sts, 0, sizeof(mbox_sts)); 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) { 27578c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__); 27588c2ecf20Sopenharmony_ci rval = -EIO; 27598c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 27608c2ecf20Sopenharmony_ci } 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci nla_for_each_attr(attr, data, len, rem) { 27638c2ecf20Sopenharmony_ci if (nla_len(attr) < sizeof(*iface_param)) { 27648c2ecf20Sopenharmony_ci rval = -EINVAL; 27658c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 27668c2ecf20Sopenharmony_ci } 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci iface_param = nla_data(attr); 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_ci if (iface_param->param_type == ISCSI_NET_PARAM) { 27718c2ecf20Sopenharmony_ci switch (iface_param->iface_type) { 27728c2ecf20Sopenharmony_ci case ISCSI_IFACE_TYPE_IPV4: 27738c2ecf20Sopenharmony_ci switch (iface_param->iface_num) { 27748c2ecf20Sopenharmony_ci case 0: 27758c2ecf20Sopenharmony_ci qla4xxx_set_ipv4(ha, iface_param, 27768c2ecf20Sopenharmony_ci init_fw_cb); 27778c2ecf20Sopenharmony_ci break; 27788c2ecf20Sopenharmony_ci default: 27798c2ecf20Sopenharmony_ci /* Cannot have more than one IPv4 interface */ 27808c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 27818c2ecf20Sopenharmony_ci "Invalid IPv4 iface number = %d\n", 27828c2ecf20Sopenharmony_ci iface_param->iface_num); 27838c2ecf20Sopenharmony_ci break; 27848c2ecf20Sopenharmony_ci } 27858c2ecf20Sopenharmony_ci break; 27868c2ecf20Sopenharmony_ci case ISCSI_IFACE_TYPE_IPV6: 27878c2ecf20Sopenharmony_ci switch (iface_param->iface_num) { 27888c2ecf20Sopenharmony_ci case 0: 27898c2ecf20Sopenharmony_ci case 1: 27908c2ecf20Sopenharmony_ci qla4xxx_set_ipv6(ha, iface_param, 27918c2ecf20Sopenharmony_ci init_fw_cb); 27928c2ecf20Sopenharmony_ci break; 27938c2ecf20Sopenharmony_ci default: 27948c2ecf20Sopenharmony_ci /* Cannot have more than two IPv6 interface */ 27958c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 27968c2ecf20Sopenharmony_ci "Invalid IPv6 iface number = %d\n", 27978c2ecf20Sopenharmony_ci iface_param->iface_num); 27988c2ecf20Sopenharmony_ci break; 27998c2ecf20Sopenharmony_ci } 28008c2ecf20Sopenharmony_ci break; 28018c2ecf20Sopenharmony_ci default: 28028c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 28038c2ecf20Sopenharmony_ci "Invalid iface type\n"); 28048c2ecf20Sopenharmony_ci break; 28058c2ecf20Sopenharmony_ci } 28068c2ecf20Sopenharmony_ci } else if (iface_param->param_type == ISCSI_IFACE_PARAM) { 28078c2ecf20Sopenharmony_ci qla4xxx_set_iscsi_param(ha, iface_param, 28088c2ecf20Sopenharmony_ci init_fw_cb); 28098c2ecf20Sopenharmony_ci } else { 28108c2ecf20Sopenharmony_ci continue; 28118c2ecf20Sopenharmony_ci } 28128c2ecf20Sopenharmony_ci } 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A); 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB, 28178c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk), 28188c2ecf20Sopenharmony_ci FLASH_OPT_RMW_COMMIT); 28198c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 28208c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n", 28218c2ecf20Sopenharmony_ci __func__); 28228c2ecf20Sopenharmony_ci rval = -EIO; 28238c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 28248c2ecf20Sopenharmony_ci } 28258c2ecf20Sopenharmony_ci 28268c2ecf20Sopenharmony_ci rval = qla4xxx_disable_acb(ha); 28278c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 28288c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: disable acb mbx failed\n", 28298c2ecf20Sopenharmony_ci __func__); 28308c2ecf20Sopenharmony_ci rval = -EIO; 28318c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 28328c2ecf20Sopenharmony_ci } 28338c2ecf20Sopenharmony_ci 28348c2ecf20Sopenharmony_ci wait_for_completion_timeout(&ha->disable_acb_comp, 28358c2ecf20Sopenharmony_ci DISABLE_ACB_TOV * HZ); 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci qla4xxx_initcb_to_acb(init_fw_cb); 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma); 28408c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 28418c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n", 28428c2ecf20Sopenharmony_ci __func__); 28438c2ecf20Sopenharmony_ci rval = -EIO; 28448c2ecf20Sopenharmony_ci goto exit_init_fw_cb; 28458c2ecf20Sopenharmony_ci } 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_ci memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk)); 28488c2ecf20Sopenharmony_ci qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb, 28498c2ecf20Sopenharmony_ci init_fw_cb_dma); 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ciexit_init_fw_cb: 28528c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk), 28538c2ecf20Sopenharmony_ci init_fw_cb, init_fw_cb_dma); 28548c2ecf20Sopenharmony_ci 28558c2ecf20Sopenharmony_ci return rval; 28568c2ecf20Sopenharmony_ci} 28578c2ecf20Sopenharmony_ci 28588c2ecf20Sopenharmony_cistatic int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, 28598c2ecf20Sopenharmony_ci enum iscsi_param param, char *buf) 28608c2ecf20Sopenharmony_ci{ 28618c2ecf20Sopenharmony_ci struct iscsi_session *sess = cls_sess->dd_data; 28628c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = sess->dd_data; 28638c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = ddb_entry->ha; 28648c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn = ddb_entry->conn; 28658c2ecf20Sopenharmony_ci struct ql4_chap_table chap_tbl; 28668c2ecf20Sopenharmony_ci int rval, len; 28678c2ecf20Sopenharmony_ci uint16_t idx; 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_ci memset(&chap_tbl, 0, sizeof(chap_tbl)); 28708c2ecf20Sopenharmony_ci switch (param) { 28718c2ecf20Sopenharmony_ci case ISCSI_PARAM_CHAP_IN_IDX: 28728c2ecf20Sopenharmony_ci rval = qla4xxx_get_chap_index(ha, sess->username_in, 28738c2ecf20Sopenharmony_ci sess->password_in, BIDI_CHAP, 28748c2ecf20Sopenharmony_ci &idx); 28758c2ecf20Sopenharmony_ci if (rval) 28768c2ecf20Sopenharmony_ci len = sprintf(buf, "\n"); 28778c2ecf20Sopenharmony_ci else 28788c2ecf20Sopenharmony_ci len = sprintf(buf, "%hu\n", idx); 28798c2ecf20Sopenharmony_ci break; 28808c2ecf20Sopenharmony_ci case ISCSI_PARAM_CHAP_OUT_IDX: 28818c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type == FLASH_DDB) { 28828c2ecf20Sopenharmony_ci if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) { 28838c2ecf20Sopenharmony_ci idx = ddb_entry->chap_tbl_idx; 28848c2ecf20Sopenharmony_ci rval = QLA_SUCCESS; 28858c2ecf20Sopenharmony_ci } else { 28868c2ecf20Sopenharmony_ci rval = QLA_ERROR; 28878c2ecf20Sopenharmony_ci } 28888c2ecf20Sopenharmony_ci } else { 28898c2ecf20Sopenharmony_ci rval = qla4xxx_get_chap_index(ha, sess->username, 28908c2ecf20Sopenharmony_ci sess->password, 28918c2ecf20Sopenharmony_ci LOCAL_CHAP, &idx); 28928c2ecf20Sopenharmony_ci } 28938c2ecf20Sopenharmony_ci if (rval) 28948c2ecf20Sopenharmony_ci len = sprintf(buf, "\n"); 28958c2ecf20Sopenharmony_ci else 28968c2ecf20Sopenharmony_ci len = sprintf(buf, "%hu\n", idx); 28978c2ecf20Sopenharmony_ci break; 28988c2ecf20Sopenharmony_ci case ISCSI_PARAM_USERNAME: 28998c2ecf20Sopenharmony_ci case ISCSI_PARAM_PASSWORD: 29008c2ecf20Sopenharmony_ci /* First, populate session username and password for FLASH DDB, 29018c2ecf20Sopenharmony_ci * if not already done. This happens when session login fails 29028c2ecf20Sopenharmony_ci * for a FLASH DDB. 29038c2ecf20Sopenharmony_ci */ 29048c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type == FLASH_DDB && 29058c2ecf20Sopenharmony_ci ddb_entry->chap_tbl_idx != INVALID_ENTRY && 29068c2ecf20Sopenharmony_ci !sess->username && !sess->password) { 29078c2ecf20Sopenharmony_ci idx = ddb_entry->chap_tbl_idx; 29088c2ecf20Sopenharmony_ci rval = qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name, 29098c2ecf20Sopenharmony_ci chap_tbl.secret, 29108c2ecf20Sopenharmony_ci idx); 29118c2ecf20Sopenharmony_ci if (!rval) { 29128c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME, 29138c2ecf20Sopenharmony_ci (char *)chap_tbl.name, 29148c2ecf20Sopenharmony_ci strlen((char *)chap_tbl.name)); 29158c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD, 29168c2ecf20Sopenharmony_ci (char *)chap_tbl.secret, 29178c2ecf20Sopenharmony_ci chap_tbl.secret_len); 29188c2ecf20Sopenharmony_ci } 29198c2ecf20Sopenharmony_ci } 29208c2ecf20Sopenharmony_ci fallthrough; 29218c2ecf20Sopenharmony_ci default: 29228c2ecf20Sopenharmony_ci return iscsi_session_get_param(cls_sess, param, buf); 29238c2ecf20Sopenharmony_ci } 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci return len; 29268c2ecf20Sopenharmony_ci} 29278c2ecf20Sopenharmony_ci 29288c2ecf20Sopenharmony_cistatic int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn, 29298c2ecf20Sopenharmony_ci enum iscsi_param param, char *buf) 29308c2ecf20Sopenharmony_ci{ 29318c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 29328c2ecf20Sopenharmony_ci struct qla_conn *qla_conn; 29338c2ecf20Sopenharmony_ci struct sockaddr *dst_addr; 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 29368c2ecf20Sopenharmony_ci qla_conn = conn->dd_data; 29378c2ecf20Sopenharmony_ci dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr; 29388c2ecf20Sopenharmony_ci 29398c2ecf20Sopenharmony_ci switch (param) { 29408c2ecf20Sopenharmony_ci case ISCSI_PARAM_CONN_PORT: 29418c2ecf20Sopenharmony_ci case ISCSI_PARAM_CONN_ADDRESS: 29428c2ecf20Sopenharmony_ci return iscsi_conn_get_addr_param((struct sockaddr_storage *) 29438c2ecf20Sopenharmony_ci dst_addr, param, buf); 29448c2ecf20Sopenharmony_ci default: 29458c2ecf20Sopenharmony_ci return iscsi_conn_get_param(cls_conn, param, buf); 29468c2ecf20Sopenharmony_ci } 29478c2ecf20Sopenharmony_ci} 29488c2ecf20Sopenharmony_ci 29498c2ecf20Sopenharmony_ciint qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index) 29508c2ecf20Sopenharmony_ci{ 29518c2ecf20Sopenharmony_ci uint32_t mbx_sts = 0; 29528c2ecf20Sopenharmony_ci uint16_t tmp_ddb_index; 29538c2ecf20Sopenharmony_ci int ret; 29548c2ecf20Sopenharmony_ci 29558c2ecf20Sopenharmony_ciget_ddb_index: 29568c2ecf20Sopenharmony_ci tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES); 29578c2ecf20Sopenharmony_ci 29588c2ecf20Sopenharmony_ci if (tmp_ddb_index >= MAX_DDB_ENTRIES) { 29598c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 29608c2ecf20Sopenharmony_ci "Free DDB index not available\n")); 29618c2ecf20Sopenharmony_ci ret = QLA_ERROR; 29628c2ecf20Sopenharmony_ci goto exit_get_ddb_index; 29638c2ecf20Sopenharmony_ci } 29648c2ecf20Sopenharmony_ci 29658c2ecf20Sopenharmony_ci if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map)) 29668c2ecf20Sopenharmony_ci goto get_ddb_index; 29678c2ecf20Sopenharmony_ci 29688c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 29698c2ecf20Sopenharmony_ci "Found a free DDB index at %d\n", tmp_ddb_index)); 29708c2ecf20Sopenharmony_ci ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts); 29718c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) { 29728c2ecf20Sopenharmony_ci if (mbx_sts == MBOX_STS_COMMAND_ERROR) { 29738c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 29748c2ecf20Sopenharmony_ci "DDB index = %d not available trying next\n", 29758c2ecf20Sopenharmony_ci tmp_ddb_index); 29768c2ecf20Sopenharmony_ci goto get_ddb_index; 29778c2ecf20Sopenharmony_ci } 29788c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 29798c2ecf20Sopenharmony_ci "Free FW DDB not available\n")); 29808c2ecf20Sopenharmony_ci } 29818c2ecf20Sopenharmony_ci 29828c2ecf20Sopenharmony_ci *ddb_index = tmp_ddb_index; 29838c2ecf20Sopenharmony_ci 29848c2ecf20Sopenharmony_ciexit_get_ddb_index: 29858c2ecf20Sopenharmony_ci return ret; 29868c2ecf20Sopenharmony_ci} 29878c2ecf20Sopenharmony_ci 29888c2ecf20Sopenharmony_cistatic int qla4xxx_match_ipaddress(struct scsi_qla_host *ha, 29898c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry, 29908c2ecf20Sopenharmony_ci char *existing_ipaddr, 29918c2ecf20Sopenharmony_ci char *user_ipaddr) 29928c2ecf20Sopenharmony_ci{ 29938c2ecf20Sopenharmony_ci uint8_t dst_ipaddr[IPv6_ADDR_LEN]; 29948c2ecf20Sopenharmony_ci char formatted_ipaddr[DDB_IPADDR_LEN]; 29958c2ecf20Sopenharmony_ci int status = QLA_SUCCESS, ret = 0; 29968c2ecf20Sopenharmony_ci 29978c2ecf20Sopenharmony_ci if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) { 29988c2ecf20Sopenharmony_ci ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr, 29998c2ecf20Sopenharmony_ci '\0', NULL); 30008c2ecf20Sopenharmony_ci if (ret == 0) { 30018c2ecf20Sopenharmony_ci status = QLA_ERROR; 30028c2ecf20Sopenharmony_ci goto out_match; 30038c2ecf20Sopenharmony_ci } 30048c2ecf20Sopenharmony_ci ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr); 30058c2ecf20Sopenharmony_ci } else { 30068c2ecf20Sopenharmony_ci ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr, 30078c2ecf20Sopenharmony_ci '\0', NULL); 30088c2ecf20Sopenharmony_ci if (ret == 0) { 30098c2ecf20Sopenharmony_ci status = QLA_ERROR; 30108c2ecf20Sopenharmony_ci goto out_match; 30118c2ecf20Sopenharmony_ci } 30128c2ecf20Sopenharmony_ci ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr); 30138c2ecf20Sopenharmony_ci } 30148c2ecf20Sopenharmony_ci 30158c2ecf20Sopenharmony_ci if (strcmp(existing_ipaddr, formatted_ipaddr)) 30168c2ecf20Sopenharmony_ci status = QLA_ERROR; 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ciout_match: 30198c2ecf20Sopenharmony_ci return status; 30208c2ecf20Sopenharmony_ci} 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_cistatic int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha, 30238c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn) 30248c2ecf20Sopenharmony_ci{ 30258c2ecf20Sopenharmony_ci int idx = 0, max_ddbs, rval; 30268c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn); 30278c2ecf20Sopenharmony_ci struct iscsi_session *sess, *existing_sess; 30288c2ecf20Sopenharmony_ci struct iscsi_conn *conn, *existing_conn; 30298c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 30308c2ecf20Sopenharmony_ci 30318c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 30328c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 30338c2ecf20Sopenharmony_ci 30348c2ecf20Sopenharmony_ci if (sess->targetname == NULL || 30358c2ecf20Sopenharmony_ci conn->persistent_address == NULL || 30368c2ecf20Sopenharmony_ci conn->persistent_port == 0) 30378c2ecf20Sopenharmony_ci return QLA_ERROR; 30388c2ecf20Sopenharmony_ci 30398c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 30408c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 30418c2ecf20Sopenharmony_ci 30428c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx++) { 30438c2ecf20Sopenharmony_ci ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); 30448c2ecf20Sopenharmony_ci if (ddb_entry == NULL) 30458c2ecf20Sopenharmony_ci continue; 30468c2ecf20Sopenharmony_ci 30478c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type != FLASH_DDB) 30488c2ecf20Sopenharmony_ci continue; 30498c2ecf20Sopenharmony_ci 30508c2ecf20Sopenharmony_ci existing_sess = ddb_entry->sess->dd_data; 30518c2ecf20Sopenharmony_ci existing_conn = ddb_entry->conn->dd_data; 30528c2ecf20Sopenharmony_ci 30538c2ecf20Sopenharmony_ci if (existing_sess->targetname == NULL || 30548c2ecf20Sopenharmony_ci existing_conn->persistent_address == NULL || 30558c2ecf20Sopenharmony_ci existing_conn->persistent_port == 0) 30568c2ecf20Sopenharmony_ci continue; 30578c2ecf20Sopenharmony_ci 30588c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 30598c2ecf20Sopenharmony_ci "IQN = %s User IQN = %s\n", 30608c2ecf20Sopenharmony_ci existing_sess->targetname, 30618c2ecf20Sopenharmony_ci sess->targetname)); 30628c2ecf20Sopenharmony_ci 30638c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 30648c2ecf20Sopenharmony_ci "IP = %s User IP = %s\n", 30658c2ecf20Sopenharmony_ci existing_conn->persistent_address, 30668c2ecf20Sopenharmony_ci conn->persistent_address)); 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 30698c2ecf20Sopenharmony_ci "Port = %d User Port = %d\n", 30708c2ecf20Sopenharmony_ci existing_conn->persistent_port, 30718c2ecf20Sopenharmony_ci conn->persistent_port)); 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci if (strcmp(existing_sess->targetname, sess->targetname)) 30748c2ecf20Sopenharmony_ci continue; 30758c2ecf20Sopenharmony_ci rval = qla4xxx_match_ipaddress(ha, ddb_entry, 30768c2ecf20Sopenharmony_ci existing_conn->persistent_address, 30778c2ecf20Sopenharmony_ci conn->persistent_address); 30788c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) 30798c2ecf20Sopenharmony_ci continue; 30808c2ecf20Sopenharmony_ci if (existing_conn->persistent_port != conn->persistent_port) 30818c2ecf20Sopenharmony_ci continue; 30828c2ecf20Sopenharmony_ci break; 30838c2ecf20Sopenharmony_ci } 30848c2ecf20Sopenharmony_ci 30858c2ecf20Sopenharmony_ci if (idx == max_ddbs) 30868c2ecf20Sopenharmony_ci return QLA_ERROR; 30878c2ecf20Sopenharmony_ci 30888c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 30898c2ecf20Sopenharmony_ci "Match found in fwdb sessions\n")); 30908c2ecf20Sopenharmony_ci return QLA_SUCCESS; 30918c2ecf20Sopenharmony_ci} 30928c2ecf20Sopenharmony_ci 30938c2ecf20Sopenharmony_cistatic struct iscsi_cls_session * 30948c2ecf20Sopenharmony_ciqla4xxx_session_create(struct iscsi_endpoint *ep, 30958c2ecf20Sopenharmony_ci uint16_t cmds_max, uint16_t qdepth, 30968c2ecf20Sopenharmony_ci uint32_t initial_cmdsn) 30978c2ecf20Sopenharmony_ci{ 30988c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 30998c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 31008c2ecf20Sopenharmony_ci struct qla_endpoint *qla_ep; 31018c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 31028c2ecf20Sopenharmony_ci uint16_t ddb_index; 31038c2ecf20Sopenharmony_ci struct iscsi_session *sess; 31048c2ecf20Sopenharmony_ci int ret; 31058c2ecf20Sopenharmony_ci 31068c2ecf20Sopenharmony_ci if (!ep) { 31078c2ecf20Sopenharmony_ci printk(KERN_ERR "qla4xxx: missing ep.\n"); 31088c2ecf20Sopenharmony_ci return NULL; 31098c2ecf20Sopenharmony_ci } 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci qla_ep = ep->dd_data; 31128c2ecf20Sopenharmony_ci ha = to_qla_host(qla_ep->host); 31138c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__, 31148c2ecf20Sopenharmony_ci ha->host_no)); 31158c2ecf20Sopenharmony_ci 31168c2ecf20Sopenharmony_ci ret = qla4xxx_get_ddb_index(ha, &ddb_index); 31178c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 31188c2ecf20Sopenharmony_ci return NULL; 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host, 31218c2ecf20Sopenharmony_ci cmds_max, sizeof(struct ddb_entry), 31228c2ecf20Sopenharmony_ci sizeof(struct ql4_task_data), 31238c2ecf20Sopenharmony_ci initial_cmdsn, ddb_index); 31248c2ecf20Sopenharmony_ci if (!cls_sess) 31258c2ecf20Sopenharmony_ci return NULL; 31268c2ecf20Sopenharmony_ci 31278c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 31288c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 31298c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index = ddb_index; 31308c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; 31318c2ecf20Sopenharmony_ci ddb_entry->ha = ha; 31328c2ecf20Sopenharmony_ci ddb_entry->sess = cls_sess; 31338c2ecf20Sopenharmony_ci ddb_entry->unblock_sess = qla4xxx_unblock_ddb; 31348c2ecf20Sopenharmony_ci ddb_entry->ddb_change = qla4xxx_ddb_change; 31358c2ecf20Sopenharmony_ci clear_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags); 31368c2ecf20Sopenharmony_ci cls_sess->recovery_tmo = ql4xsess_recovery_tmo; 31378c2ecf20Sopenharmony_ci ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry; 31388c2ecf20Sopenharmony_ci ha->tot_ddbs++; 31398c2ecf20Sopenharmony_ci 31408c2ecf20Sopenharmony_ci return cls_sess; 31418c2ecf20Sopenharmony_ci} 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_cistatic void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess) 31448c2ecf20Sopenharmony_ci{ 31458c2ecf20Sopenharmony_ci struct iscsi_session *sess; 31468c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 31478c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 31488c2ecf20Sopenharmony_ci unsigned long flags, wtime; 31498c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 31508c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 31518c2ecf20Sopenharmony_ci uint32_t ddb_state; 31528c2ecf20Sopenharmony_ci int ret; 31538c2ecf20Sopenharmony_ci 31548c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 31558c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 31568c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 31578c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__, 31588c2ecf20Sopenharmony_ci ha->host_no)); 31598c2ecf20Sopenharmony_ci 31608c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 31618c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 31628c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 31638c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 31648c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 31658c2ecf20Sopenharmony_ci goto destroy_session; 31668c2ecf20Sopenharmony_ci } 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * LOGOUT_TOV); 31698c2ecf20Sopenharmony_ci do { 31708c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, 31718c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma, 31728c2ecf20Sopenharmony_ci NULL, NULL, &ddb_state, NULL, 31738c2ecf20Sopenharmony_ci NULL, NULL); 31748c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 31758c2ecf20Sopenharmony_ci goto destroy_session; 31768c2ecf20Sopenharmony_ci 31778c2ecf20Sopenharmony_ci if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || 31788c2ecf20Sopenharmony_ci (ddb_state == DDB_DS_SESSION_FAILED)) 31798c2ecf20Sopenharmony_ci goto destroy_session; 31808c2ecf20Sopenharmony_ci 31818c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ); 31828c2ecf20Sopenharmony_ci } while ((time_after(wtime, jiffies))); 31838c2ecf20Sopenharmony_ci 31848c2ecf20Sopenharmony_cidestroy_session: 31858c2ecf20Sopenharmony_ci qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); 31868c2ecf20Sopenharmony_ci if (test_and_clear_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags)) 31878c2ecf20Sopenharmony_ci clear_bit(ddb_entry->fw_ddb_index, ha->ddb_idx_map); 31888c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 31898c2ecf20Sopenharmony_ci qla4xxx_free_ddb(ha, ddb_entry); 31908c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci iscsi_session_teardown(cls_sess); 31938c2ecf20Sopenharmony_ci 31948c2ecf20Sopenharmony_ci if (fw_ddb_entry) 31958c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 31968c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 31978c2ecf20Sopenharmony_ci} 31988c2ecf20Sopenharmony_ci 31998c2ecf20Sopenharmony_cistatic struct iscsi_cls_conn * 32008c2ecf20Sopenharmony_ciqla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx) 32018c2ecf20Sopenharmony_ci{ 32028c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn; 32038c2ecf20Sopenharmony_ci struct iscsi_session *sess; 32048c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 32058c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), 32088c2ecf20Sopenharmony_ci conn_idx); 32098c2ecf20Sopenharmony_ci if (!cls_conn) { 32108c2ecf20Sopenharmony_ci pr_info("%s: Can not create connection for conn_idx = %u\n", 32118c2ecf20Sopenharmony_ci __func__, conn_idx); 32128c2ecf20Sopenharmony_ci return NULL; 32138c2ecf20Sopenharmony_ci } 32148c2ecf20Sopenharmony_ci 32158c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 32168c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 32178c2ecf20Sopenharmony_ci ddb_entry->conn = cls_conn; 32188c2ecf20Sopenharmony_ci 32198c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 32208c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: conn_idx = %u\n", __func__, 32218c2ecf20Sopenharmony_ci conn_idx)); 32228c2ecf20Sopenharmony_ci return cls_conn; 32238c2ecf20Sopenharmony_ci} 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_cistatic int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session, 32268c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn, 32278c2ecf20Sopenharmony_ci uint64_t transport_fd, int is_leading) 32288c2ecf20Sopenharmony_ci{ 32298c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 32308c2ecf20Sopenharmony_ci struct qla_conn *qla_conn; 32318c2ecf20Sopenharmony_ci struct iscsi_endpoint *ep; 32328c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 32338c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 32348c2ecf20Sopenharmony_ci struct iscsi_session *sess; 32358c2ecf20Sopenharmony_ci 32368c2ecf20Sopenharmony_ci sess = cls_session->dd_data; 32378c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 32388c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 32398c2ecf20Sopenharmony_ci 32408c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: sid = %d, cid = %d\n", __func__, 32418c2ecf20Sopenharmony_ci cls_session->sid, cls_conn->cid)); 32428c2ecf20Sopenharmony_ci 32438c2ecf20Sopenharmony_ci if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) 32448c2ecf20Sopenharmony_ci return -EINVAL; 32458c2ecf20Sopenharmony_ci ep = iscsi_lookup_endpoint(transport_fd); 32468c2ecf20Sopenharmony_ci if (!ep) 32478c2ecf20Sopenharmony_ci return -EINVAL; 32488c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 32498c2ecf20Sopenharmony_ci qla_conn = conn->dd_data; 32508c2ecf20Sopenharmony_ci qla_conn->qla_ep = ep->dd_data; 32518c2ecf20Sopenharmony_ci iscsi_put_endpoint(ep); 32528c2ecf20Sopenharmony_ci return 0; 32538c2ecf20Sopenharmony_ci} 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_cistatic int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) 32568c2ecf20Sopenharmony_ci{ 32578c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn); 32588c2ecf20Sopenharmony_ci struct iscsi_session *sess; 32598c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 32608c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 32618c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 32628c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 32638c2ecf20Sopenharmony_ci uint32_t mbx_sts = 0; 32648c2ecf20Sopenharmony_ci int ret = 0; 32658c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 32668c2ecf20Sopenharmony_ci 32678c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 32688c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 32698c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 32708c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: sid = %d, cid = %d\n", __func__, 32718c2ecf20Sopenharmony_ci cls_sess->sid, cls_conn->cid)); 32728c2ecf20Sopenharmony_ci 32738c2ecf20Sopenharmony_ci /* Check if we have matching FW DDB, if yes then do not 32748c2ecf20Sopenharmony_ci * login to this target. This could cause target to logout previous 32758c2ecf20Sopenharmony_ci * connection 32768c2ecf20Sopenharmony_ci */ 32778c2ecf20Sopenharmony_ci ret = qla4xxx_match_fwdb_session(ha, cls_conn); 32788c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS) { 32798c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 32808c2ecf20Sopenharmony_ci "Session already exist in FW.\n"); 32818c2ecf20Sopenharmony_ci ret = -EEXIST; 32828c2ecf20Sopenharmony_ci goto exit_conn_start; 32838c2ecf20Sopenharmony_ci } 32848c2ecf20Sopenharmony_ci 32858c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 32868c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 32878c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 32888c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 32898c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 32908c2ecf20Sopenharmony_ci ret = -ENOMEM; 32918c2ecf20Sopenharmony_ci goto exit_conn_start; 32928c2ecf20Sopenharmony_ci } 32938c2ecf20Sopenharmony_ci 32948c2ecf20Sopenharmony_ci ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts); 32958c2ecf20Sopenharmony_ci if (ret) { 32968c2ecf20Sopenharmony_ci /* If iscsid is stopped and started then no need to do 32978c2ecf20Sopenharmony_ci * set param again since ddb state will be already 32988c2ecf20Sopenharmony_ci * active and FW does not allow set ddb to an 32998c2ecf20Sopenharmony_ci * active session. 33008c2ecf20Sopenharmony_ci */ 33018c2ecf20Sopenharmony_ci if (mbx_sts) 33028c2ecf20Sopenharmony_ci if (ddb_entry->fw_ddb_device_state == 33038c2ecf20Sopenharmony_ci DDB_DS_SESSION_ACTIVE) { 33048c2ecf20Sopenharmony_ci ddb_entry->unblock_sess(ddb_entry->sess); 33058c2ecf20Sopenharmony_ci goto exit_set_param; 33068c2ecf20Sopenharmony_ci } 33078c2ecf20Sopenharmony_ci 33088c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n", 33098c2ecf20Sopenharmony_ci __func__, ddb_entry->fw_ddb_index); 33108c2ecf20Sopenharmony_ci goto exit_conn_start; 33118c2ecf20Sopenharmony_ci } 33128c2ecf20Sopenharmony_ci 33138c2ecf20Sopenharmony_ci status = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index); 33148c2ecf20Sopenharmony_ci if (status == QLA_ERROR) { 33158c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__, 33168c2ecf20Sopenharmony_ci sess->targetname); 33178c2ecf20Sopenharmony_ci ret = -EINVAL; 33188c2ecf20Sopenharmony_ci goto exit_conn_start; 33198c2ecf20Sopenharmony_ci } 33208c2ecf20Sopenharmony_ci 33218c2ecf20Sopenharmony_ci if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE) 33228c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS; 33238c2ecf20Sopenharmony_ci 33248c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__, 33258c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_device_state)); 33268c2ecf20Sopenharmony_ci 33278c2ecf20Sopenharmony_ciexit_set_param: 33288c2ecf20Sopenharmony_ci ret = 0; 33298c2ecf20Sopenharmony_ci 33308c2ecf20Sopenharmony_ciexit_conn_start: 33318c2ecf20Sopenharmony_ci if (fw_ddb_entry) 33328c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 33338c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 33348c2ecf20Sopenharmony_ci return ret; 33358c2ecf20Sopenharmony_ci} 33368c2ecf20Sopenharmony_ci 33378c2ecf20Sopenharmony_cistatic void qla4xxx_conn_destroy(struct iscsi_cls_conn *cls_conn) 33388c2ecf20Sopenharmony_ci{ 33398c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn); 33408c2ecf20Sopenharmony_ci struct iscsi_session *sess; 33418c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 33428c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 33438c2ecf20Sopenharmony_ci int options; 33448c2ecf20Sopenharmony_ci 33458c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 33468c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 33478c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 33488c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: cid = %d\n", __func__, 33498c2ecf20Sopenharmony_ci cls_conn->cid)); 33508c2ecf20Sopenharmony_ci 33518c2ecf20Sopenharmony_ci options = LOGOUT_OPTION_CLOSE_SESSION; 33528c2ecf20Sopenharmony_ci if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR) 33538c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__); 33548c2ecf20Sopenharmony_ci} 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_cistatic void qla4xxx_task_work(struct work_struct *wdata) 33578c2ecf20Sopenharmony_ci{ 33588c2ecf20Sopenharmony_ci struct ql4_task_data *task_data; 33598c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 33608c2ecf20Sopenharmony_ci struct passthru_status *sts; 33618c2ecf20Sopenharmony_ci struct iscsi_task *task; 33628c2ecf20Sopenharmony_ci struct iscsi_hdr *hdr; 33638c2ecf20Sopenharmony_ci uint8_t *data; 33648c2ecf20Sopenharmony_ci uint32_t data_len; 33658c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 33668c2ecf20Sopenharmony_ci int hdr_len; 33678c2ecf20Sopenharmony_ci itt_t itt; 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci task_data = container_of(wdata, struct ql4_task_data, task_work); 33708c2ecf20Sopenharmony_ci ha = task_data->ha; 33718c2ecf20Sopenharmony_ci task = task_data->task; 33728c2ecf20Sopenharmony_ci sts = &task_data->sts; 33738c2ecf20Sopenharmony_ci hdr_len = sizeof(struct iscsi_hdr); 33748c2ecf20Sopenharmony_ci 33758c2ecf20Sopenharmony_ci DEBUG3(printk(KERN_INFO "Status returned\n")); 33768c2ecf20Sopenharmony_ci DEBUG3(qla4xxx_dump_buffer(sts, 64)); 33778c2ecf20Sopenharmony_ci DEBUG3(printk(KERN_INFO "Response buffer")); 33788c2ecf20Sopenharmony_ci DEBUG3(qla4xxx_dump_buffer(task_data->resp_buffer, 64)); 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci conn = task->conn; 33818c2ecf20Sopenharmony_ci 33828c2ecf20Sopenharmony_ci switch (sts->completionStatus) { 33838c2ecf20Sopenharmony_ci case PASSTHRU_STATUS_COMPLETE: 33848c2ecf20Sopenharmony_ci hdr = (struct iscsi_hdr *)task_data->resp_buffer; 33858c2ecf20Sopenharmony_ci /* Assign back the itt in hdr, until we use the PREASSIGN_TAG */ 33868c2ecf20Sopenharmony_ci itt = sts->handle; 33878c2ecf20Sopenharmony_ci hdr->itt = itt; 33888c2ecf20Sopenharmony_ci data = task_data->resp_buffer + hdr_len; 33898c2ecf20Sopenharmony_ci data_len = task_data->resp_len - hdr_len; 33908c2ecf20Sopenharmony_ci iscsi_complete_pdu(conn, hdr, data, data_len); 33918c2ecf20Sopenharmony_ci break; 33928c2ecf20Sopenharmony_ci default: 33938c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Passthru failed status = 0x%x\n", 33948c2ecf20Sopenharmony_ci sts->completionStatus); 33958c2ecf20Sopenharmony_ci break; 33968c2ecf20Sopenharmony_ci } 33978c2ecf20Sopenharmony_ci return; 33988c2ecf20Sopenharmony_ci} 33998c2ecf20Sopenharmony_ci 34008c2ecf20Sopenharmony_cistatic int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode) 34018c2ecf20Sopenharmony_ci{ 34028c2ecf20Sopenharmony_ci struct ql4_task_data *task_data; 34038c2ecf20Sopenharmony_ci struct iscsi_session *sess; 34048c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 34058c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 34068c2ecf20Sopenharmony_ci int hdr_len; 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_ci sess = task->conn->session; 34098c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 34108c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 34118c2ecf20Sopenharmony_ci task_data = task->dd_data; 34128c2ecf20Sopenharmony_ci memset(task_data, 0, sizeof(struct ql4_task_data)); 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_ci if (task->sc) { 34158c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 34168c2ecf20Sopenharmony_ci "%s: SCSI Commands not implemented\n", __func__); 34178c2ecf20Sopenharmony_ci return -EINVAL; 34188c2ecf20Sopenharmony_ci } 34198c2ecf20Sopenharmony_ci 34208c2ecf20Sopenharmony_ci hdr_len = sizeof(struct iscsi_hdr); 34218c2ecf20Sopenharmony_ci task_data->ha = ha; 34228c2ecf20Sopenharmony_ci task_data->task = task; 34238c2ecf20Sopenharmony_ci 34248c2ecf20Sopenharmony_ci if (task->data_count) { 34258c2ecf20Sopenharmony_ci task_data->data_dma = dma_map_single(&ha->pdev->dev, task->data, 34268c2ecf20Sopenharmony_ci task->data_count, 34278c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 34288c2ecf20Sopenharmony_ci } 34298c2ecf20Sopenharmony_ci 34308c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n", 34318c2ecf20Sopenharmony_ci __func__, task->conn->max_recv_dlength, hdr_len)); 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci task_data->resp_len = task->conn->max_recv_dlength + hdr_len; 34348c2ecf20Sopenharmony_ci task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev, 34358c2ecf20Sopenharmony_ci task_data->resp_len, 34368c2ecf20Sopenharmony_ci &task_data->resp_dma, 34378c2ecf20Sopenharmony_ci GFP_ATOMIC); 34388c2ecf20Sopenharmony_ci if (!task_data->resp_buffer) 34398c2ecf20Sopenharmony_ci goto exit_alloc_pdu; 34408c2ecf20Sopenharmony_ci 34418c2ecf20Sopenharmony_ci task_data->req_len = task->data_count + hdr_len; 34428c2ecf20Sopenharmony_ci task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev, 34438c2ecf20Sopenharmony_ci task_data->req_len, 34448c2ecf20Sopenharmony_ci &task_data->req_dma, 34458c2ecf20Sopenharmony_ci GFP_ATOMIC); 34468c2ecf20Sopenharmony_ci if (!task_data->req_buffer) 34478c2ecf20Sopenharmony_ci goto exit_alloc_pdu; 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ci task->hdr = task_data->req_buffer; 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ci INIT_WORK(&task_data->task_work, qla4xxx_task_work); 34528c2ecf20Sopenharmony_ci 34538c2ecf20Sopenharmony_ci return 0; 34548c2ecf20Sopenharmony_ci 34558c2ecf20Sopenharmony_ciexit_alloc_pdu: 34568c2ecf20Sopenharmony_ci if (task_data->resp_buffer) 34578c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, task_data->resp_len, 34588c2ecf20Sopenharmony_ci task_data->resp_buffer, task_data->resp_dma); 34598c2ecf20Sopenharmony_ci 34608c2ecf20Sopenharmony_ci if (task_data->req_buffer) 34618c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, task_data->req_len, 34628c2ecf20Sopenharmony_ci task_data->req_buffer, task_data->req_dma); 34638c2ecf20Sopenharmony_ci return -ENOMEM; 34648c2ecf20Sopenharmony_ci} 34658c2ecf20Sopenharmony_ci 34668c2ecf20Sopenharmony_cistatic void qla4xxx_task_cleanup(struct iscsi_task *task) 34678c2ecf20Sopenharmony_ci{ 34688c2ecf20Sopenharmony_ci struct ql4_task_data *task_data; 34698c2ecf20Sopenharmony_ci struct iscsi_session *sess; 34708c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 34718c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 34728c2ecf20Sopenharmony_ci int hdr_len; 34738c2ecf20Sopenharmony_ci 34748c2ecf20Sopenharmony_ci hdr_len = sizeof(struct iscsi_hdr); 34758c2ecf20Sopenharmony_ci sess = task->conn->session; 34768c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 34778c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 34788c2ecf20Sopenharmony_ci task_data = task->dd_data; 34798c2ecf20Sopenharmony_ci 34808c2ecf20Sopenharmony_ci if (task->data_count) { 34818c2ecf20Sopenharmony_ci dma_unmap_single(&ha->pdev->dev, task_data->data_dma, 34828c2ecf20Sopenharmony_ci task->data_count, DMA_TO_DEVICE); 34838c2ecf20Sopenharmony_ci } 34848c2ecf20Sopenharmony_ci 34858c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n", 34868c2ecf20Sopenharmony_ci __func__, task->conn->max_recv_dlength, hdr_len)); 34878c2ecf20Sopenharmony_ci 34888c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, task_data->resp_len, 34898c2ecf20Sopenharmony_ci task_data->resp_buffer, task_data->resp_dma); 34908c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, task_data->req_len, 34918c2ecf20Sopenharmony_ci task_data->req_buffer, task_data->req_dma); 34928c2ecf20Sopenharmony_ci return; 34938c2ecf20Sopenharmony_ci} 34948c2ecf20Sopenharmony_ci 34958c2ecf20Sopenharmony_cistatic int qla4xxx_task_xmit(struct iscsi_task *task) 34968c2ecf20Sopenharmony_ci{ 34978c2ecf20Sopenharmony_ci struct scsi_cmnd *sc = task->sc; 34988c2ecf20Sopenharmony_ci struct iscsi_session *sess = task->conn->session; 34998c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = sess->dd_data; 35008c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = ddb_entry->ha; 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci if (!sc) 35038c2ecf20Sopenharmony_ci return qla4xxx_send_passthru0(task); 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: scsi cmd xmit not implemented\n", 35068c2ecf20Sopenharmony_ci __func__); 35078c2ecf20Sopenharmony_ci return -ENOSYS; 35088c2ecf20Sopenharmony_ci} 35098c2ecf20Sopenharmony_ci 35108c2ecf20Sopenharmony_cistatic int qla4xxx_copy_from_fwddb_param(struct iscsi_bus_flash_session *sess, 35118c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *conn, 35128c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 35138c2ecf20Sopenharmony_ci{ 35148c2ecf20Sopenharmony_ci unsigned long options = 0; 35158c2ecf20Sopenharmony_ci int rc = 0; 35168c2ecf20Sopenharmony_ci 35178c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 35188c2ecf20Sopenharmony_ci conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options); 35198c2ecf20Sopenharmony_ci if (test_bit(OPT_IPV6_DEVICE, &options)) { 35208c2ecf20Sopenharmony_ci rc = iscsi_switch_str_param(&sess->portal_type, 35218c2ecf20Sopenharmony_ci PORTAL_TYPE_IPV6); 35228c2ecf20Sopenharmony_ci if (rc) 35238c2ecf20Sopenharmony_ci goto exit_copy; 35248c2ecf20Sopenharmony_ci } else { 35258c2ecf20Sopenharmony_ci rc = iscsi_switch_str_param(&sess->portal_type, 35268c2ecf20Sopenharmony_ci PORTAL_TYPE_IPV4); 35278c2ecf20Sopenharmony_ci if (rc) 35288c2ecf20Sopenharmony_ci goto exit_copy; 35298c2ecf20Sopenharmony_ci } 35308c2ecf20Sopenharmony_ci 35318c2ecf20Sopenharmony_ci sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE, 35328c2ecf20Sopenharmony_ci &options); 35338c2ecf20Sopenharmony_ci sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options); 35348c2ecf20Sopenharmony_ci sess->entry_state = test_bit(OPT_ENTRY_STATE, &options); 35358c2ecf20Sopenharmony_ci 35368c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->iscsi_options); 35378c2ecf20Sopenharmony_ci conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options); 35388c2ecf20Sopenharmony_ci conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options); 35398c2ecf20Sopenharmony_ci sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options); 35408c2ecf20Sopenharmony_ci sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options); 35418c2ecf20Sopenharmony_ci sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER, 35428c2ecf20Sopenharmony_ci &options); 35438c2ecf20Sopenharmony_ci sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options); 35448c2ecf20Sopenharmony_ci sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options); 35458c2ecf20Sopenharmony_ci conn->snack_req_en = test_bit(ISCSIOPT_SNACK_REQ_EN, &options); 35468c2ecf20Sopenharmony_ci sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN, 35478c2ecf20Sopenharmony_ci &options); 35488c2ecf20Sopenharmony_ci sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options); 35498c2ecf20Sopenharmony_ci sess->discovery_auth_optional = 35508c2ecf20Sopenharmony_ci test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options); 35518c2ecf20Sopenharmony_ci if (test_bit(ISCSIOPT_ERL1, &options)) 35528c2ecf20Sopenharmony_ci sess->erl |= BIT_1; 35538c2ecf20Sopenharmony_ci if (test_bit(ISCSIOPT_ERL0, &options)) 35548c2ecf20Sopenharmony_ci sess->erl |= BIT_0; 35558c2ecf20Sopenharmony_ci 35568c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->tcp_options); 35578c2ecf20Sopenharmony_ci conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options); 35588c2ecf20Sopenharmony_ci conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options); 35598c2ecf20Sopenharmony_ci conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options); 35608c2ecf20Sopenharmony_ci if (test_bit(TCPOPT_TIMER_SCALE3, &options)) 35618c2ecf20Sopenharmony_ci conn->tcp_timer_scale |= BIT_3; 35628c2ecf20Sopenharmony_ci if (test_bit(TCPOPT_TIMER_SCALE2, &options)) 35638c2ecf20Sopenharmony_ci conn->tcp_timer_scale |= BIT_2; 35648c2ecf20Sopenharmony_ci if (test_bit(TCPOPT_TIMER_SCALE1, &options)) 35658c2ecf20Sopenharmony_ci conn->tcp_timer_scale |= BIT_1; 35668c2ecf20Sopenharmony_ci 35678c2ecf20Sopenharmony_ci conn->tcp_timer_scale >>= 1; 35688c2ecf20Sopenharmony_ci conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options); 35698c2ecf20Sopenharmony_ci 35708c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->ip_options); 35718c2ecf20Sopenharmony_ci conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options); 35728c2ecf20Sopenharmony_ci 35738c2ecf20Sopenharmony_ci conn->max_recv_dlength = BYTE_UNITS * 35748c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); 35758c2ecf20Sopenharmony_ci conn->max_xmit_dlength = BYTE_UNITS * 35768c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len); 35778c2ecf20Sopenharmony_ci sess->first_burst = BYTE_UNITS * 35788c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len); 35798c2ecf20Sopenharmony_ci sess->max_burst = BYTE_UNITS * 35808c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len); 35818c2ecf20Sopenharmony_ci sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t); 35828c2ecf20Sopenharmony_ci sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); 35838c2ecf20Sopenharmony_ci sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain); 35848c2ecf20Sopenharmony_ci sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); 35858c2ecf20Sopenharmony_ci conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss); 35868c2ecf20Sopenharmony_ci conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf; 35878c2ecf20Sopenharmony_ci conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf; 35888c2ecf20Sopenharmony_ci conn->ipv6_flow_label = le16_to_cpu(fw_ddb_entry->ipv6_flow_lbl); 35898c2ecf20Sopenharmony_ci conn->keepalive_timeout = le16_to_cpu(fw_ddb_entry->ka_timeout); 35908c2ecf20Sopenharmony_ci conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port); 35918c2ecf20Sopenharmony_ci conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn); 35928c2ecf20Sopenharmony_ci conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn); 35938c2ecf20Sopenharmony_ci sess->discovery_parent_idx = le16_to_cpu(fw_ddb_entry->ddb_link); 35948c2ecf20Sopenharmony_ci sess->discovery_parent_type = le16_to_cpu(fw_ddb_entry->ddb_link); 35958c2ecf20Sopenharmony_ci sess->chap_out_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); 35968c2ecf20Sopenharmony_ci sess->tsid = le16_to_cpu(fw_ddb_entry->tsid); 35978c2ecf20Sopenharmony_ci 35988c2ecf20Sopenharmony_ci sess->default_taskmgmt_timeout = 35998c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->def_timeout); 36008c2ecf20Sopenharmony_ci conn->port = le16_to_cpu(fw_ddb_entry->port); 36018c2ecf20Sopenharmony_ci 36028c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 36038c2ecf20Sopenharmony_ci conn->ipaddress = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); 36048c2ecf20Sopenharmony_ci if (!conn->ipaddress) { 36058c2ecf20Sopenharmony_ci rc = -ENOMEM; 36068c2ecf20Sopenharmony_ci goto exit_copy; 36078c2ecf20Sopenharmony_ci } 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_ci conn->redirect_ipaddr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); 36108c2ecf20Sopenharmony_ci if (!conn->redirect_ipaddr) { 36118c2ecf20Sopenharmony_ci rc = -ENOMEM; 36128c2ecf20Sopenharmony_ci goto exit_copy; 36138c2ecf20Sopenharmony_ci } 36148c2ecf20Sopenharmony_ci 36158c2ecf20Sopenharmony_ci memcpy(conn->ipaddress, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN); 36168c2ecf20Sopenharmony_ci memcpy(conn->redirect_ipaddr, fw_ddb_entry->tgt_addr, IPv6_ADDR_LEN); 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci if (test_bit(OPT_IPV6_DEVICE, &options)) { 36198c2ecf20Sopenharmony_ci conn->ipv6_traffic_class = fw_ddb_entry->ipv4_tos; 36208c2ecf20Sopenharmony_ci 36218c2ecf20Sopenharmony_ci conn->link_local_ipv6_addr = kmemdup( 36228c2ecf20Sopenharmony_ci fw_ddb_entry->link_local_ipv6_addr, 36238c2ecf20Sopenharmony_ci IPv6_ADDR_LEN, GFP_KERNEL); 36248c2ecf20Sopenharmony_ci if (!conn->link_local_ipv6_addr) { 36258c2ecf20Sopenharmony_ci rc = -ENOMEM; 36268c2ecf20Sopenharmony_ci goto exit_copy; 36278c2ecf20Sopenharmony_ci } 36288c2ecf20Sopenharmony_ci } else { 36298c2ecf20Sopenharmony_ci conn->ipv4_tos = fw_ddb_entry->ipv4_tos; 36308c2ecf20Sopenharmony_ci } 36318c2ecf20Sopenharmony_ci 36328c2ecf20Sopenharmony_ci if (fw_ddb_entry->iscsi_name[0]) { 36338c2ecf20Sopenharmony_ci rc = iscsi_switch_str_param(&sess->targetname, 36348c2ecf20Sopenharmony_ci (char *)fw_ddb_entry->iscsi_name); 36358c2ecf20Sopenharmony_ci if (rc) 36368c2ecf20Sopenharmony_ci goto exit_copy; 36378c2ecf20Sopenharmony_ci } 36388c2ecf20Sopenharmony_ci 36398c2ecf20Sopenharmony_ci if (fw_ddb_entry->iscsi_alias[0]) { 36408c2ecf20Sopenharmony_ci rc = iscsi_switch_str_param(&sess->targetalias, 36418c2ecf20Sopenharmony_ci (char *)fw_ddb_entry->iscsi_alias); 36428c2ecf20Sopenharmony_ci if (rc) 36438c2ecf20Sopenharmony_ci goto exit_copy; 36448c2ecf20Sopenharmony_ci } 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci COPY_ISID(sess->isid, fw_ddb_entry->isid); 36478c2ecf20Sopenharmony_ci 36488c2ecf20Sopenharmony_ciexit_copy: 36498c2ecf20Sopenharmony_ci return rc; 36508c2ecf20Sopenharmony_ci} 36518c2ecf20Sopenharmony_ci 36528c2ecf20Sopenharmony_cistatic int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess, 36538c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *conn, 36548c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 36558c2ecf20Sopenharmony_ci{ 36568c2ecf20Sopenharmony_ci uint16_t options; 36578c2ecf20Sopenharmony_ci int rc = 0; 36588c2ecf20Sopenharmony_ci 36598c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 36608c2ecf20Sopenharmony_ci SET_BITVAL(conn->is_fw_assigned_ipv6, options, BIT_11); 36618c2ecf20Sopenharmony_ci if (!strncmp(sess->portal_type, PORTAL_TYPE_IPV6, 4)) 36628c2ecf20Sopenharmony_ci options |= BIT_8; 36638c2ecf20Sopenharmony_ci else 36648c2ecf20Sopenharmony_ci options &= ~BIT_8; 36658c2ecf20Sopenharmony_ci 36668c2ecf20Sopenharmony_ci SET_BITVAL(sess->auto_snd_tgt_disable, options, BIT_6); 36678c2ecf20Sopenharmony_ci SET_BITVAL(sess->discovery_sess, options, BIT_4); 36688c2ecf20Sopenharmony_ci SET_BITVAL(sess->entry_state, options, BIT_3); 36698c2ecf20Sopenharmony_ci fw_ddb_entry->options = cpu_to_le16(options); 36708c2ecf20Sopenharmony_ci 36718c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->iscsi_options); 36728c2ecf20Sopenharmony_ci SET_BITVAL(conn->hdrdgst_en, options, BIT_13); 36738c2ecf20Sopenharmony_ci SET_BITVAL(conn->datadgst_en, options, BIT_12); 36748c2ecf20Sopenharmony_ci SET_BITVAL(sess->imm_data_en, options, BIT_11); 36758c2ecf20Sopenharmony_ci SET_BITVAL(sess->initial_r2t_en, options, BIT_10); 36768c2ecf20Sopenharmony_ci SET_BITVAL(sess->dataseq_inorder_en, options, BIT_9); 36778c2ecf20Sopenharmony_ci SET_BITVAL(sess->pdu_inorder_en, options, BIT_8); 36788c2ecf20Sopenharmony_ci SET_BITVAL(sess->chap_auth_en, options, BIT_7); 36798c2ecf20Sopenharmony_ci SET_BITVAL(conn->snack_req_en, options, BIT_6); 36808c2ecf20Sopenharmony_ci SET_BITVAL(sess->discovery_logout_en, options, BIT_5); 36818c2ecf20Sopenharmony_ci SET_BITVAL(sess->bidi_chap_en, options, BIT_4); 36828c2ecf20Sopenharmony_ci SET_BITVAL(sess->discovery_auth_optional, options, BIT_3); 36838c2ecf20Sopenharmony_ci SET_BITVAL(sess->erl & BIT_1, options, BIT_1); 36848c2ecf20Sopenharmony_ci SET_BITVAL(sess->erl & BIT_0, options, BIT_0); 36858c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_options = cpu_to_le16(options); 36868c2ecf20Sopenharmony_ci 36878c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->tcp_options); 36888c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_timestamp_stat, options, BIT_6); 36898c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_nagle_disable, options, BIT_5); 36908c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_wsf_disable, options, BIT_4); 36918c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_timer_scale & BIT_2, options, BIT_3); 36928c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_timer_scale & BIT_1, options, BIT_2); 36938c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_timer_scale & BIT_0, options, BIT_1); 36948c2ecf20Sopenharmony_ci SET_BITVAL(conn->tcp_timestamp_en, options, BIT_0); 36958c2ecf20Sopenharmony_ci fw_ddb_entry->tcp_options = cpu_to_le16(options); 36968c2ecf20Sopenharmony_ci 36978c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->ip_options); 36988c2ecf20Sopenharmony_ci SET_BITVAL(conn->fragment_disable, options, BIT_4); 36998c2ecf20Sopenharmony_ci fw_ddb_entry->ip_options = cpu_to_le16(options); 37008c2ecf20Sopenharmony_ci 37018c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t); 37028c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_rcv_data_seg_len = 37038c2ecf20Sopenharmony_ci cpu_to_le16(conn->max_recv_dlength / BYTE_UNITS); 37048c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_snd_data_seg_len = 37058c2ecf20Sopenharmony_ci cpu_to_le16(conn->max_xmit_dlength / BYTE_UNITS); 37068c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_first_burst_len = 37078c2ecf20Sopenharmony_ci cpu_to_le16(sess->first_burst / BYTE_UNITS); 37088c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_max_burst_len = cpu_to_le16(sess->max_burst / 37098c2ecf20Sopenharmony_ci BYTE_UNITS); 37108c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_def_time2wait = cpu_to_le16(sess->time2wait); 37118c2ecf20Sopenharmony_ci fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain); 37128c2ecf20Sopenharmony_ci fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt); 37138c2ecf20Sopenharmony_ci fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size); 37148c2ecf20Sopenharmony_ci fw_ddb_entry->tcp_xmt_wsf = (uint8_t) cpu_to_le32(conn->tcp_xmit_wsf); 37158c2ecf20Sopenharmony_ci fw_ddb_entry->tcp_rcv_wsf = (uint8_t) cpu_to_le32(conn->tcp_recv_wsf); 37168c2ecf20Sopenharmony_ci fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label); 37178c2ecf20Sopenharmony_ci fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout); 37188c2ecf20Sopenharmony_ci fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port); 37198c2ecf20Sopenharmony_ci fw_ddb_entry->stat_sn = cpu_to_le32(conn->statsn); 37208c2ecf20Sopenharmony_ci fw_ddb_entry->exp_stat_sn = cpu_to_le32(conn->exp_statsn); 37218c2ecf20Sopenharmony_ci fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_idx); 37228c2ecf20Sopenharmony_ci fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx); 37238c2ecf20Sopenharmony_ci fw_ddb_entry->tsid = cpu_to_le16(sess->tsid); 37248c2ecf20Sopenharmony_ci fw_ddb_entry->port = cpu_to_le16(conn->port); 37258c2ecf20Sopenharmony_ci fw_ddb_entry->def_timeout = 37268c2ecf20Sopenharmony_ci cpu_to_le16(sess->default_taskmgmt_timeout); 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci if (!strncmp(sess->portal_type, PORTAL_TYPE_IPV6, 4)) 37298c2ecf20Sopenharmony_ci fw_ddb_entry->ipv4_tos = conn->ipv6_traffic_class; 37308c2ecf20Sopenharmony_ci else 37318c2ecf20Sopenharmony_ci fw_ddb_entry->ipv4_tos = conn->ipv4_tos; 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_ci if (conn->ipaddress) 37348c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->ip_addr, conn->ipaddress, 37358c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->ip_addr)); 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci if (conn->redirect_ipaddr) 37388c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->tgt_addr, conn->redirect_ipaddr, 37398c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->tgt_addr)); 37408c2ecf20Sopenharmony_ci 37418c2ecf20Sopenharmony_ci if (conn->link_local_ipv6_addr) 37428c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->link_local_ipv6_addr, 37438c2ecf20Sopenharmony_ci conn->link_local_ipv6_addr, 37448c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->link_local_ipv6_addr)); 37458c2ecf20Sopenharmony_ci 37468c2ecf20Sopenharmony_ci if (sess->targetname) 37478c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->iscsi_name, sess->targetname, 37488c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->iscsi_name)); 37498c2ecf20Sopenharmony_ci 37508c2ecf20Sopenharmony_ci if (sess->targetalias) 37518c2ecf20Sopenharmony_ci memcpy(fw_ddb_entry->iscsi_alias, sess->targetalias, 37528c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->iscsi_alias)); 37538c2ecf20Sopenharmony_ci 37548c2ecf20Sopenharmony_ci COPY_ISID(fw_ddb_entry->isid, sess->isid); 37558c2ecf20Sopenharmony_ci 37568c2ecf20Sopenharmony_ci return rc; 37578c2ecf20Sopenharmony_ci} 37588c2ecf20Sopenharmony_ci 37598c2ecf20Sopenharmony_cistatic void qla4xxx_copy_to_sess_conn_params(struct iscsi_conn *conn, 37608c2ecf20Sopenharmony_ci struct iscsi_session *sess, 37618c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 37628c2ecf20Sopenharmony_ci{ 37638c2ecf20Sopenharmony_ci unsigned long options = 0; 37648c2ecf20Sopenharmony_ci uint16_t ddb_link; 37658c2ecf20Sopenharmony_ci uint16_t disc_parent; 37668c2ecf20Sopenharmony_ci char ip_addr[DDB_IPADDR_LEN]; 37678c2ecf20Sopenharmony_ci 37688c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 37698c2ecf20Sopenharmony_ci conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options); 37708c2ecf20Sopenharmony_ci sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE, 37718c2ecf20Sopenharmony_ci &options); 37728c2ecf20Sopenharmony_ci sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options); 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->iscsi_options); 37758c2ecf20Sopenharmony_ci conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options); 37768c2ecf20Sopenharmony_ci conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options); 37778c2ecf20Sopenharmony_ci sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options); 37788c2ecf20Sopenharmony_ci sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options); 37798c2ecf20Sopenharmony_ci sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER, 37808c2ecf20Sopenharmony_ci &options); 37818c2ecf20Sopenharmony_ci sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options); 37828c2ecf20Sopenharmony_ci sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options); 37838c2ecf20Sopenharmony_ci sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN, 37848c2ecf20Sopenharmony_ci &options); 37858c2ecf20Sopenharmony_ci sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options); 37868c2ecf20Sopenharmony_ci sess->discovery_auth_optional = 37878c2ecf20Sopenharmony_ci test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options); 37888c2ecf20Sopenharmony_ci if (test_bit(ISCSIOPT_ERL1, &options)) 37898c2ecf20Sopenharmony_ci sess->erl |= BIT_1; 37908c2ecf20Sopenharmony_ci if (test_bit(ISCSIOPT_ERL0, &options)) 37918c2ecf20Sopenharmony_ci sess->erl |= BIT_0; 37928c2ecf20Sopenharmony_ci 37938c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->tcp_options); 37948c2ecf20Sopenharmony_ci conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options); 37958c2ecf20Sopenharmony_ci conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options); 37968c2ecf20Sopenharmony_ci conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options); 37978c2ecf20Sopenharmony_ci if (test_bit(TCPOPT_TIMER_SCALE3, &options)) 37988c2ecf20Sopenharmony_ci conn->tcp_timer_scale |= BIT_3; 37998c2ecf20Sopenharmony_ci if (test_bit(TCPOPT_TIMER_SCALE2, &options)) 38008c2ecf20Sopenharmony_ci conn->tcp_timer_scale |= BIT_2; 38018c2ecf20Sopenharmony_ci if (test_bit(TCPOPT_TIMER_SCALE1, &options)) 38028c2ecf20Sopenharmony_ci conn->tcp_timer_scale |= BIT_1; 38038c2ecf20Sopenharmony_ci 38048c2ecf20Sopenharmony_ci conn->tcp_timer_scale >>= 1; 38058c2ecf20Sopenharmony_ci conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options); 38068c2ecf20Sopenharmony_ci 38078c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->ip_options); 38088c2ecf20Sopenharmony_ci conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options); 38098c2ecf20Sopenharmony_ci 38108c2ecf20Sopenharmony_ci conn->max_recv_dlength = BYTE_UNITS * 38118c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); 38128c2ecf20Sopenharmony_ci conn->max_xmit_dlength = BYTE_UNITS * 38138c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len); 38148c2ecf20Sopenharmony_ci sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t); 38158c2ecf20Sopenharmony_ci sess->first_burst = BYTE_UNITS * 38168c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len); 38178c2ecf20Sopenharmony_ci sess->max_burst = BYTE_UNITS * 38188c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len); 38198c2ecf20Sopenharmony_ci sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); 38208c2ecf20Sopenharmony_ci sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain); 38218c2ecf20Sopenharmony_ci sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); 38228c2ecf20Sopenharmony_ci conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss); 38238c2ecf20Sopenharmony_ci conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf; 38248c2ecf20Sopenharmony_ci conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf; 38258c2ecf20Sopenharmony_ci conn->ipv4_tos = fw_ddb_entry->ipv4_tos; 38268c2ecf20Sopenharmony_ci conn->keepalive_tmo = le16_to_cpu(fw_ddb_entry->ka_timeout); 38278c2ecf20Sopenharmony_ci conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port); 38288c2ecf20Sopenharmony_ci conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn); 38298c2ecf20Sopenharmony_ci conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn); 38308c2ecf20Sopenharmony_ci sess->tsid = le16_to_cpu(fw_ddb_entry->tsid); 38318c2ecf20Sopenharmony_ci COPY_ISID(sess->isid, fw_ddb_entry->isid); 38328c2ecf20Sopenharmony_ci 38338c2ecf20Sopenharmony_ci ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); 38348c2ecf20Sopenharmony_ci if (ddb_link == DDB_ISNS) 38358c2ecf20Sopenharmony_ci disc_parent = ISCSI_DISC_PARENT_ISNS; 38368c2ecf20Sopenharmony_ci else if (ddb_link == DDB_NO_LINK) 38378c2ecf20Sopenharmony_ci disc_parent = ISCSI_DISC_PARENT_UNKNOWN; 38388c2ecf20Sopenharmony_ci else if (ddb_link < MAX_DDB_ENTRIES) 38398c2ecf20Sopenharmony_ci disc_parent = ISCSI_DISC_PARENT_SENDTGT; 38408c2ecf20Sopenharmony_ci else 38418c2ecf20Sopenharmony_ci disc_parent = ISCSI_DISC_PARENT_UNKNOWN; 38428c2ecf20Sopenharmony_ci 38438c2ecf20Sopenharmony_ci iscsi_set_param(conn->cls_conn, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 38448c2ecf20Sopenharmony_ci iscsi_get_discovery_parent_name(disc_parent), 0); 38458c2ecf20Sopenharmony_ci 38468c2ecf20Sopenharmony_ci iscsi_set_param(conn->cls_conn, ISCSI_PARAM_TARGET_ALIAS, 38478c2ecf20Sopenharmony_ci (char *)fw_ddb_entry->iscsi_alias, 0); 38488c2ecf20Sopenharmony_ci 38498c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 38508c2ecf20Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) { 38518c2ecf20Sopenharmony_ci memset(ip_addr, 0, sizeof(ip_addr)); 38528c2ecf20Sopenharmony_ci sprintf(ip_addr, "%pI6", fw_ddb_entry->link_local_ipv6_addr); 38538c2ecf20Sopenharmony_ci iscsi_set_param(conn->cls_conn, ISCSI_PARAM_LOCAL_IPADDR, 38548c2ecf20Sopenharmony_ci (char *)ip_addr, 0); 38558c2ecf20Sopenharmony_ci } 38568c2ecf20Sopenharmony_ci} 38578c2ecf20Sopenharmony_ci 38588c2ecf20Sopenharmony_cistatic void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, 38598c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 38608c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess, 38618c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn) 38628c2ecf20Sopenharmony_ci{ 38638c2ecf20Sopenharmony_ci int buflen = 0; 38648c2ecf20Sopenharmony_ci struct iscsi_session *sess; 38658c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 38668c2ecf20Sopenharmony_ci struct ql4_chap_table chap_tbl; 38678c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 38688c2ecf20Sopenharmony_ci char ip_addr[DDB_IPADDR_LEN]; 38698c2ecf20Sopenharmony_ci uint16_t options = 0; 38708c2ecf20Sopenharmony_ci 38718c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 38728c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 38738c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 38748c2ecf20Sopenharmony_ci memset(&chap_tbl, 0, sizeof(chap_tbl)); 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); 38778c2ecf20Sopenharmony_ci 38788c2ecf20Sopenharmony_ci qla4xxx_copy_to_sess_conn_params(conn, sess, fw_ddb_entry); 38798c2ecf20Sopenharmony_ci 38808c2ecf20Sopenharmony_ci sess->def_taskmgmt_tmo = le16_to_cpu(fw_ddb_entry->def_timeout); 38818c2ecf20Sopenharmony_ci conn->persistent_port = le16_to_cpu(fw_ddb_entry->port); 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_ci memset(ip_addr, 0, sizeof(ip_addr)); 38848c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 38858c2ecf20Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) { 38868c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_PORTAL_TYPE, "ipv6", 4); 38878c2ecf20Sopenharmony_ci 38888c2ecf20Sopenharmony_ci memset(ip_addr, 0, sizeof(ip_addr)); 38898c2ecf20Sopenharmony_ci sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr); 38908c2ecf20Sopenharmony_ci } else { 38918c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_PORTAL_TYPE, "ipv4", 4); 38928c2ecf20Sopenharmony_ci sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr); 38938c2ecf20Sopenharmony_ci } 38948c2ecf20Sopenharmony_ci 38958c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS, 38968c2ecf20Sopenharmony_ci (char *)ip_addr, buflen); 38978c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME, 38988c2ecf20Sopenharmony_ci (char *)fw_ddb_entry->iscsi_name, buflen); 38998c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, 39008c2ecf20Sopenharmony_ci (char *)ha->name_string, buflen); 39018c2ecf20Sopenharmony_ci 39028c2ecf20Sopenharmony_ci if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) { 39038c2ecf20Sopenharmony_ci if (!qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name, 39048c2ecf20Sopenharmony_ci chap_tbl.secret, 39058c2ecf20Sopenharmony_ci ddb_entry->chap_tbl_idx)) { 39068c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME, 39078c2ecf20Sopenharmony_ci (char *)chap_tbl.name, 39088c2ecf20Sopenharmony_ci strlen((char *)chap_tbl.name)); 39098c2ecf20Sopenharmony_ci iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD, 39108c2ecf20Sopenharmony_ci (char *)chap_tbl.secret, 39118c2ecf20Sopenharmony_ci chap_tbl.secret_len); 39128c2ecf20Sopenharmony_ci } 39138c2ecf20Sopenharmony_ci } 39148c2ecf20Sopenharmony_ci} 39158c2ecf20Sopenharmony_ci 39168c2ecf20Sopenharmony_civoid qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, 39178c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry) 39188c2ecf20Sopenharmony_ci{ 39198c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 39208c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn; 39218c2ecf20Sopenharmony_ci uint32_t ddb_state; 39228c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 39238c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 39248c2ecf20Sopenharmony_ci 39258c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 39268c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 39278c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 39288c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 39298c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 39308c2ecf20Sopenharmony_ci goto exit_session_conn_fwddb_param; 39318c2ecf20Sopenharmony_ci } 39328c2ecf20Sopenharmony_ci 39338c2ecf20Sopenharmony_ci if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, 39348c2ecf20Sopenharmony_ci fw_ddb_entry_dma, NULL, NULL, &ddb_state, 39358c2ecf20Sopenharmony_ci NULL, NULL, NULL) == QLA_ERROR) { 39368c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 39378c2ecf20Sopenharmony_ci "get_ddb_entry for fw_ddb_index %d\n", 39388c2ecf20Sopenharmony_ci ha->host_no, __func__, 39398c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index)); 39408c2ecf20Sopenharmony_ci goto exit_session_conn_fwddb_param; 39418c2ecf20Sopenharmony_ci } 39428c2ecf20Sopenharmony_ci 39438c2ecf20Sopenharmony_ci cls_sess = ddb_entry->sess; 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_ci cls_conn = ddb_entry->conn; 39468c2ecf20Sopenharmony_ci 39478c2ecf20Sopenharmony_ci /* Update params */ 39488c2ecf20Sopenharmony_ci qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); 39498c2ecf20Sopenharmony_ci 39508c2ecf20Sopenharmony_ciexit_session_conn_fwddb_param: 39518c2ecf20Sopenharmony_ci if (fw_ddb_entry) 39528c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 39538c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 39548c2ecf20Sopenharmony_ci} 39558c2ecf20Sopenharmony_ci 39568c2ecf20Sopenharmony_civoid qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, 39578c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry) 39588c2ecf20Sopenharmony_ci{ 39598c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 39608c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn; 39618c2ecf20Sopenharmony_ci struct iscsi_session *sess; 39628c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 39638c2ecf20Sopenharmony_ci uint32_t ddb_state; 39648c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 39658c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 39668c2ecf20Sopenharmony_ci 39678c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 39688c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 39698c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 39708c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 39718c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 39728c2ecf20Sopenharmony_ci goto exit_session_conn_param; 39738c2ecf20Sopenharmony_ci } 39748c2ecf20Sopenharmony_ci 39758c2ecf20Sopenharmony_ci if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, 39768c2ecf20Sopenharmony_ci fw_ddb_entry_dma, NULL, NULL, &ddb_state, 39778c2ecf20Sopenharmony_ci NULL, NULL, NULL) == QLA_ERROR) { 39788c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " 39798c2ecf20Sopenharmony_ci "get_ddb_entry for fw_ddb_index %d\n", 39808c2ecf20Sopenharmony_ci ha->host_no, __func__, 39818c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index)); 39828c2ecf20Sopenharmony_ci goto exit_session_conn_param; 39838c2ecf20Sopenharmony_ci } 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_ci cls_sess = ddb_entry->sess; 39868c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 39878c2ecf20Sopenharmony_ci 39888c2ecf20Sopenharmony_ci cls_conn = ddb_entry->conn; 39898c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 39908c2ecf20Sopenharmony_ci 39918c2ecf20Sopenharmony_ci /* Update timers after login */ 39928c2ecf20Sopenharmony_ci ddb_entry->default_relogin_timeout = 39938c2ecf20Sopenharmony_ci (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) && 39948c2ecf20Sopenharmony_ci (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ? 39958c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV; 39968c2ecf20Sopenharmony_ci ddb_entry->default_time2wait = 39978c2ecf20Sopenharmony_ci le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); 39988c2ecf20Sopenharmony_ci 39998c2ecf20Sopenharmony_ci /* Update params */ 40008c2ecf20Sopenharmony_ci ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); 40018c2ecf20Sopenharmony_ci qla4xxx_copy_to_sess_conn_params(conn, sess, fw_ddb_entry); 40028c2ecf20Sopenharmony_ci 40038c2ecf20Sopenharmony_ci memcpy(sess->initiatorname, ha->name_string, 40048c2ecf20Sopenharmony_ci min(sizeof(ha->name_string), sizeof(sess->initiatorname))); 40058c2ecf20Sopenharmony_ci 40068c2ecf20Sopenharmony_ciexit_session_conn_param: 40078c2ecf20Sopenharmony_ci if (fw_ddb_entry) 40088c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 40098c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 40108c2ecf20Sopenharmony_ci} 40118c2ecf20Sopenharmony_ci 40128c2ecf20Sopenharmony_ci/* 40138c2ecf20Sopenharmony_ci * Timer routines 40148c2ecf20Sopenharmony_ci */ 40158c2ecf20Sopenharmony_cistatic void qla4xxx_timer(struct timer_list *t); 40168c2ecf20Sopenharmony_ci 40178c2ecf20Sopenharmony_cistatic void qla4xxx_start_timer(struct scsi_qla_host *ha, 40188c2ecf20Sopenharmony_ci unsigned long interval) 40198c2ecf20Sopenharmony_ci{ 40208c2ecf20Sopenharmony_ci DEBUG(printk("scsi: %s: Starting timer thread for adapter %d\n", 40218c2ecf20Sopenharmony_ci __func__, ha->host->host_no)); 40228c2ecf20Sopenharmony_ci timer_setup(&ha->timer, qla4xxx_timer, 0); 40238c2ecf20Sopenharmony_ci ha->timer.expires = jiffies + interval * HZ; 40248c2ecf20Sopenharmony_ci add_timer(&ha->timer); 40258c2ecf20Sopenharmony_ci ha->timer_active = 1; 40268c2ecf20Sopenharmony_ci} 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_cistatic void qla4xxx_stop_timer(struct scsi_qla_host *ha) 40298c2ecf20Sopenharmony_ci{ 40308c2ecf20Sopenharmony_ci del_timer_sync(&ha->timer); 40318c2ecf20Sopenharmony_ci ha->timer_active = 0; 40328c2ecf20Sopenharmony_ci} 40338c2ecf20Sopenharmony_ci 40348c2ecf20Sopenharmony_ci/*** 40358c2ecf20Sopenharmony_ci * qla4xxx_mark_device_missing - blocks the session 40368c2ecf20Sopenharmony_ci * @cls_session: Pointer to the session to be blocked 40378c2ecf20Sopenharmony_ci * @ddb_entry: Pointer to device database entry 40388c2ecf20Sopenharmony_ci * 40398c2ecf20Sopenharmony_ci * This routine marks a device missing and close connection. 40408c2ecf20Sopenharmony_ci **/ 40418c2ecf20Sopenharmony_civoid qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session) 40428c2ecf20Sopenharmony_ci{ 40438c2ecf20Sopenharmony_ci iscsi_block_session(cls_session); 40448c2ecf20Sopenharmony_ci} 40458c2ecf20Sopenharmony_ci 40468c2ecf20Sopenharmony_ci/** 40478c2ecf20Sopenharmony_ci * qla4xxx_mark_all_devices_missing - mark all devices as missing. 40488c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 40498c2ecf20Sopenharmony_ci * 40508c2ecf20Sopenharmony_ci * This routine marks a device missing and resets the relogin retry count. 40518c2ecf20Sopenharmony_ci **/ 40528c2ecf20Sopenharmony_civoid qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha) 40538c2ecf20Sopenharmony_ci{ 40548c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_mark_device_missing); 40558c2ecf20Sopenharmony_ci} 40568c2ecf20Sopenharmony_ci 40578c2ecf20Sopenharmony_cistatic struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, 40588c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry, 40598c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd) 40608c2ecf20Sopenharmony_ci{ 40618c2ecf20Sopenharmony_ci struct srb *srb; 40628c2ecf20Sopenharmony_ci 40638c2ecf20Sopenharmony_ci srb = mempool_alloc(ha->srb_mempool, GFP_ATOMIC); 40648c2ecf20Sopenharmony_ci if (!srb) 40658c2ecf20Sopenharmony_ci return srb; 40668c2ecf20Sopenharmony_ci 40678c2ecf20Sopenharmony_ci kref_init(&srb->srb_ref); 40688c2ecf20Sopenharmony_ci srb->ha = ha; 40698c2ecf20Sopenharmony_ci srb->ddb = ddb_entry; 40708c2ecf20Sopenharmony_ci srb->cmd = cmd; 40718c2ecf20Sopenharmony_ci srb->flags = 0; 40728c2ecf20Sopenharmony_ci CMD_SP(cmd) = (void *)srb; 40738c2ecf20Sopenharmony_ci 40748c2ecf20Sopenharmony_ci return srb; 40758c2ecf20Sopenharmony_ci} 40768c2ecf20Sopenharmony_ci 40778c2ecf20Sopenharmony_cistatic void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb) 40788c2ecf20Sopenharmony_ci{ 40798c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = srb->cmd; 40808c2ecf20Sopenharmony_ci 40818c2ecf20Sopenharmony_ci if (srb->flags & SRB_DMA_VALID) { 40828c2ecf20Sopenharmony_ci scsi_dma_unmap(cmd); 40838c2ecf20Sopenharmony_ci srb->flags &= ~SRB_DMA_VALID; 40848c2ecf20Sopenharmony_ci } 40858c2ecf20Sopenharmony_ci CMD_SP(cmd) = NULL; 40868c2ecf20Sopenharmony_ci} 40878c2ecf20Sopenharmony_ci 40888c2ecf20Sopenharmony_civoid qla4xxx_srb_compl(struct kref *ref) 40898c2ecf20Sopenharmony_ci{ 40908c2ecf20Sopenharmony_ci struct srb *srb = container_of(ref, struct srb, srb_ref); 40918c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = srb->cmd; 40928c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = srb->ha; 40938c2ecf20Sopenharmony_ci 40948c2ecf20Sopenharmony_ci qla4xxx_srb_free_dma(ha, srb); 40958c2ecf20Sopenharmony_ci 40968c2ecf20Sopenharmony_ci mempool_free(srb, ha->srb_mempool); 40978c2ecf20Sopenharmony_ci 40988c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 40998c2ecf20Sopenharmony_ci} 41008c2ecf20Sopenharmony_ci 41018c2ecf20Sopenharmony_ci/** 41028c2ecf20Sopenharmony_ci * qla4xxx_queuecommand - scsi layer issues scsi command to driver. 41038c2ecf20Sopenharmony_ci * @host: scsi host 41048c2ecf20Sopenharmony_ci * @cmd: Pointer to Linux's SCSI command structure 41058c2ecf20Sopenharmony_ci * 41068c2ecf20Sopenharmony_ci * Remarks: 41078c2ecf20Sopenharmony_ci * This routine is invoked by Linux to send a SCSI command to the driver. 41088c2ecf20Sopenharmony_ci * The mid-level driver tries to ensure that queuecommand never gets 41098c2ecf20Sopenharmony_ci * invoked concurrently with itself or the interrupt handler (although 41108c2ecf20Sopenharmony_ci * the interrupt handler may call this routine as part of request- 41118c2ecf20Sopenharmony_ci * completion handling). Unfortunely, it sometimes calls the scheduler 41128c2ecf20Sopenharmony_ci * in interrupt context which is a big NO! NO!. 41138c2ecf20Sopenharmony_ci **/ 41148c2ecf20Sopenharmony_cistatic int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) 41158c2ecf20Sopenharmony_ci{ 41168c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(host); 41178c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = cmd->device->hostdata; 41188c2ecf20Sopenharmony_ci struct iscsi_cls_session *sess = ddb_entry->sess; 41198c2ecf20Sopenharmony_ci struct srb *srb; 41208c2ecf20Sopenharmony_ci int rval; 41218c2ecf20Sopenharmony_ci 41228c2ecf20Sopenharmony_ci if (test_bit(AF_EEH_BUSY, &ha->flags)) { 41238c2ecf20Sopenharmony_ci if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) 41248c2ecf20Sopenharmony_ci cmd->result = DID_NO_CONNECT << 16; 41258c2ecf20Sopenharmony_ci else 41268c2ecf20Sopenharmony_ci cmd->result = DID_REQUEUE << 16; 41278c2ecf20Sopenharmony_ci goto qc_fail_command; 41288c2ecf20Sopenharmony_ci } 41298c2ecf20Sopenharmony_ci 41308c2ecf20Sopenharmony_ci if (!sess) { 41318c2ecf20Sopenharmony_ci cmd->result = DID_IMM_RETRY << 16; 41328c2ecf20Sopenharmony_ci goto qc_fail_command; 41338c2ecf20Sopenharmony_ci } 41348c2ecf20Sopenharmony_ci 41358c2ecf20Sopenharmony_ci rval = iscsi_session_chkready(sess); 41368c2ecf20Sopenharmony_ci if (rval) { 41378c2ecf20Sopenharmony_ci cmd->result = rval; 41388c2ecf20Sopenharmony_ci goto qc_fail_command; 41398c2ecf20Sopenharmony_ci } 41408c2ecf20Sopenharmony_ci 41418c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || 41428c2ecf20Sopenharmony_ci test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || 41438c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA, &ha->dpc_flags) || 41448c2ecf20Sopenharmony_ci test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || 41458c2ecf20Sopenharmony_ci test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || 41468c2ecf20Sopenharmony_ci !test_bit(AF_ONLINE, &ha->flags) || 41478c2ecf20Sopenharmony_ci !test_bit(AF_LINK_UP, &ha->flags) || 41488c2ecf20Sopenharmony_ci test_bit(AF_LOOPBACK, &ha->flags) || 41498c2ecf20Sopenharmony_ci test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) || 41508c2ecf20Sopenharmony_ci test_bit(DPC_RESTORE_ACB, &ha->dpc_flags) || 41518c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) 41528c2ecf20Sopenharmony_ci goto qc_host_busy; 41538c2ecf20Sopenharmony_ci 41548c2ecf20Sopenharmony_ci srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd); 41558c2ecf20Sopenharmony_ci if (!srb) 41568c2ecf20Sopenharmony_ci goto qc_host_busy; 41578c2ecf20Sopenharmony_ci 41588c2ecf20Sopenharmony_ci rval = qla4xxx_send_command_to_isp(ha, srb); 41598c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) 41608c2ecf20Sopenharmony_ci goto qc_host_busy_free_sp; 41618c2ecf20Sopenharmony_ci 41628c2ecf20Sopenharmony_ci return 0; 41638c2ecf20Sopenharmony_ci 41648c2ecf20Sopenharmony_ciqc_host_busy_free_sp: 41658c2ecf20Sopenharmony_ci qla4xxx_srb_free_dma(ha, srb); 41668c2ecf20Sopenharmony_ci mempool_free(srb, ha->srb_mempool); 41678c2ecf20Sopenharmony_ci 41688c2ecf20Sopenharmony_ciqc_host_busy: 41698c2ecf20Sopenharmony_ci return SCSI_MLQUEUE_HOST_BUSY; 41708c2ecf20Sopenharmony_ci 41718c2ecf20Sopenharmony_ciqc_fail_command: 41728c2ecf20Sopenharmony_ci cmd->scsi_done(cmd); 41738c2ecf20Sopenharmony_ci 41748c2ecf20Sopenharmony_ci return 0; 41758c2ecf20Sopenharmony_ci} 41768c2ecf20Sopenharmony_ci 41778c2ecf20Sopenharmony_ci/** 41788c2ecf20Sopenharmony_ci * qla4xxx_mem_free - frees memory allocated to adapter 41798c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 41808c2ecf20Sopenharmony_ci * 41818c2ecf20Sopenharmony_ci * Frees memory previously allocated by qla4xxx_mem_alloc 41828c2ecf20Sopenharmony_ci **/ 41838c2ecf20Sopenharmony_cistatic void qla4xxx_mem_free(struct scsi_qla_host *ha) 41848c2ecf20Sopenharmony_ci{ 41858c2ecf20Sopenharmony_ci if (ha->queues) 41868c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues, 41878c2ecf20Sopenharmony_ci ha->queues_dma); 41888c2ecf20Sopenharmony_ci 41898c2ecf20Sopenharmony_ci if (ha->fw_dump) 41908c2ecf20Sopenharmony_ci vfree(ha->fw_dump); 41918c2ecf20Sopenharmony_ci 41928c2ecf20Sopenharmony_ci ha->queues_len = 0; 41938c2ecf20Sopenharmony_ci ha->queues = NULL; 41948c2ecf20Sopenharmony_ci ha->queues_dma = 0; 41958c2ecf20Sopenharmony_ci ha->request_ring = NULL; 41968c2ecf20Sopenharmony_ci ha->request_dma = 0; 41978c2ecf20Sopenharmony_ci ha->response_ring = NULL; 41988c2ecf20Sopenharmony_ci ha->response_dma = 0; 41998c2ecf20Sopenharmony_ci ha->shadow_regs = NULL; 42008c2ecf20Sopenharmony_ci ha->shadow_regs_dma = 0; 42018c2ecf20Sopenharmony_ci ha->fw_dump = NULL; 42028c2ecf20Sopenharmony_ci ha->fw_dump_size = 0; 42038c2ecf20Sopenharmony_ci 42048c2ecf20Sopenharmony_ci /* Free srb pool. */ 42058c2ecf20Sopenharmony_ci mempool_destroy(ha->srb_mempool); 42068c2ecf20Sopenharmony_ci ha->srb_mempool = NULL; 42078c2ecf20Sopenharmony_ci 42088c2ecf20Sopenharmony_ci dma_pool_destroy(ha->chap_dma_pool); 42098c2ecf20Sopenharmony_ci 42108c2ecf20Sopenharmony_ci if (ha->chap_list) 42118c2ecf20Sopenharmony_ci vfree(ha->chap_list); 42128c2ecf20Sopenharmony_ci ha->chap_list = NULL; 42138c2ecf20Sopenharmony_ci 42148c2ecf20Sopenharmony_ci dma_pool_destroy(ha->fw_ddb_dma_pool); 42158c2ecf20Sopenharmony_ci 42168c2ecf20Sopenharmony_ci /* release io space registers */ 42178c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 42188c2ecf20Sopenharmony_ci if (ha->nx_pcibase) 42198c2ecf20Sopenharmony_ci iounmap( 42208c2ecf20Sopenharmony_ci (struct device_reg_82xx __iomem *)ha->nx_pcibase); 42218c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 42228c2ecf20Sopenharmony_ci if (ha->nx_pcibase) 42238c2ecf20Sopenharmony_ci iounmap( 42248c2ecf20Sopenharmony_ci (struct device_reg_83xx __iomem *)ha->nx_pcibase); 42258c2ecf20Sopenharmony_ci } else if (ha->reg) { 42268c2ecf20Sopenharmony_ci iounmap(ha->reg); 42278c2ecf20Sopenharmony_ci } 42288c2ecf20Sopenharmony_ci 42298c2ecf20Sopenharmony_ci if (ha->reset_tmplt.buff) 42308c2ecf20Sopenharmony_ci vfree(ha->reset_tmplt.buff); 42318c2ecf20Sopenharmony_ci 42328c2ecf20Sopenharmony_ci pci_release_regions(ha->pdev); 42338c2ecf20Sopenharmony_ci} 42348c2ecf20Sopenharmony_ci 42358c2ecf20Sopenharmony_ci/** 42368c2ecf20Sopenharmony_ci * qla4xxx_mem_alloc - allocates memory for use by adapter. 42378c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure 42388c2ecf20Sopenharmony_ci * 42398c2ecf20Sopenharmony_ci * Allocates DMA memory for request and response queues. Also allocates memory 42408c2ecf20Sopenharmony_ci * for srbs. 42418c2ecf20Sopenharmony_ci **/ 42428c2ecf20Sopenharmony_cistatic int qla4xxx_mem_alloc(struct scsi_qla_host *ha) 42438c2ecf20Sopenharmony_ci{ 42448c2ecf20Sopenharmony_ci unsigned long align; 42458c2ecf20Sopenharmony_ci 42468c2ecf20Sopenharmony_ci /* Allocate contiguous block of DMA memory for queues. */ 42478c2ecf20Sopenharmony_ci ha->queues_len = ((REQUEST_QUEUE_DEPTH * QUEUE_SIZE) + 42488c2ecf20Sopenharmony_ci (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE) + 42498c2ecf20Sopenharmony_ci sizeof(struct shadow_regs) + 42508c2ecf20Sopenharmony_ci MEM_ALIGN_VALUE + 42518c2ecf20Sopenharmony_ci (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); 42528c2ecf20Sopenharmony_ci ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len, 42538c2ecf20Sopenharmony_ci &ha->queues_dma, GFP_KERNEL); 42548c2ecf20Sopenharmony_ci if (ha->queues == NULL) { 42558c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 42568c2ecf20Sopenharmony_ci "Memory Allocation failed - queues.\n"); 42578c2ecf20Sopenharmony_ci 42588c2ecf20Sopenharmony_ci goto mem_alloc_error_exit; 42598c2ecf20Sopenharmony_ci } 42608c2ecf20Sopenharmony_ci 42618c2ecf20Sopenharmony_ci /* 42628c2ecf20Sopenharmony_ci * As per RISC alignment requirements -- the bus-address must be a 42638c2ecf20Sopenharmony_ci * multiple of the request-ring size (in bytes). 42648c2ecf20Sopenharmony_ci */ 42658c2ecf20Sopenharmony_ci align = 0; 42668c2ecf20Sopenharmony_ci if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1)) 42678c2ecf20Sopenharmony_ci align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma & 42688c2ecf20Sopenharmony_ci (MEM_ALIGN_VALUE - 1)); 42698c2ecf20Sopenharmony_ci 42708c2ecf20Sopenharmony_ci /* Update request and response queue pointers. */ 42718c2ecf20Sopenharmony_ci ha->request_dma = ha->queues_dma + align; 42728c2ecf20Sopenharmony_ci ha->request_ring = (struct queue_entry *) (ha->queues + align); 42738c2ecf20Sopenharmony_ci ha->response_dma = ha->queues_dma + align + 42748c2ecf20Sopenharmony_ci (REQUEST_QUEUE_DEPTH * QUEUE_SIZE); 42758c2ecf20Sopenharmony_ci ha->response_ring = (struct queue_entry *) (ha->queues + align + 42768c2ecf20Sopenharmony_ci (REQUEST_QUEUE_DEPTH * 42778c2ecf20Sopenharmony_ci QUEUE_SIZE)); 42788c2ecf20Sopenharmony_ci ha->shadow_regs_dma = ha->queues_dma + align + 42798c2ecf20Sopenharmony_ci (REQUEST_QUEUE_DEPTH * QUEUE_SIZE) + 42808c2ecf20Sopenharmony_ci (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE); 42818c2ecf20Sopenharmony_ci ha->shadow_regs = (struct shadow_regs *) (ha->queues + align + 42828c2ecf20Sopenharmony_ci (REQUEST_QUEUE_DEPTH * 42838c2ecf20Sopenharmony_ci QUEUE_SIZE) + 42848c2ecf20Sopenharmony_ci (RESPONSE_QUEUE_DEPTH * 42858c2ecf20Sopenharmony_ci QUEUE_SIZE)); 42868c2ecf20Sopenharmony_ci 42878c2ecf20Sopenharmony_ci /* Allocate memory for srb pool. */ 42888c2ecf20Sopenharmony_ci ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab, 42898c2ecf20Sopenharmony_ci mempool_free_slab, srb_cachep); 42908c2ecf20Sopenharmony_ci if (ha->srb_mempool == NULL) { 42918c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 42928c2ecf20Sopenharmony_ci "Memory Allocation failed - SRB Pool.\n"); 42938c2ecf20Sopenharmony_ci 42948c2ecf20Sopenharmony_ci goto mem_alloc_error_exit; 42958c2ecf20Sopenharmony_ci } 42968c2ecf20Sopenharmony_ci 42978c2ecf20Sopenharmony_ci ha->chap_dma_pool = dma_pool_create("ql4_chap", &ha->pdev->dev, 42988c2ecf20Sopenharmony_ci CHAP_DMA_BLOCK_SIZE, 8, 0); 42998c2ecf20Sopenharmony_ci 43008c2ecf20Sopenharmony_ci if (ha->chap_dma_pool == NULL) { 43018c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 43028c2ecf20Sopenharmony_ci "%s: chap_dma_pool allocation failed..\n", __func__); 43038c2ecf20Sopenharmony_ci goto mem_alloc_error_exit; 43048c2ecf20Sopenharmony_ci } 43058c2ecf20Sopenharmony_ci 43068c2ecf20Sopenharmony_ci ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev, 43078c2ecf20Sopenharmony_ci DDB_DMA_BLOCK_SIZE, 8, 0); 43088c2ecf20Sopenharmony_ci 43098c2ecf20Sopenharmony_ci if (ha->fw_ddb_dma_pool == NULL) { 43108c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 43118c2ecf20Sopenharmony_ci "%s: fw_ddb_dma_pool allocation failed..\n", 43128c2ecf20Sopenharmony_ci __func__); 43138c2ecf20Sopenharmony_ci goto mem_alloc_error_exit; 43148c2ecf20Sopenharmony_ci } 43158c2ecf20Sopenharmony_ci 43168c2ecf20Sopenharmony_ci return QLA_SUCCESS; 43178c2ecf20Sopenharmony_ci 43188c2ecf20Sopenharmony_cimem_alloc_error_exit: 43198c2ecf20Sopenharmony_ci return QLA_ERROR; 43208c2ecf20Sopenharmony_ci} 43218c2ecf20Sopenharmony_ci 43228c2ecf20Sopenharmony_ci/** 43238c2ecf20Sopenharmony_ci * qla4_8xxx_check_temp - Check the ISP82XX temperature. 43248c2ecf20Sopenharmony_ci * @ha: adapter block pointer. 43258c2ecf20Sopenharmony_ci * 43268c2ecf20Sopenharmony_ci * Note: The caller should not hold the idc lock. 43278c2ecf20Sopenharmony_ci **/ 43288c2ecf20Sopenharmony_cistatic int qla4_8xxx_check_temp(struct scsi_qla_host *ha) 43298c2ecf20Sopenharmony_ci{ 43308c2ecf20Sopenharmony_ci uint32_t temp, temp_state, temp_val; 43318c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 43328c2ecf20Sopenharmony_ci 43338c2ecf20Sopenharmony_ci temp = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_TEMP_STATE); 43348c2ecf20Sopenharmony_ci 43358c2ecf20Sopenharmony_ci temp_state = qla82xx_get_temp_state(temp); 43368c2ecf20Sopenharmony_ci temp_val = qla82xx_get_temp_val(temp); 43378c2ecf20Sopenharmony_ci 43388c2ecf20Sopenharmony_ci if (temp_state == QLA82XX_TEMP_PANIC) { 43398c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C" 43408c2ecf20Sopenharmony_ci " exceeds maximum allowed. Hardware has been shut" 43418c2ecf20Sopenharmony_ci " down.\n", temp_val); 43428c2ecf20Sopenharmony_ci status = QLA_ERROR; 43438c2ecf20Sopenharmony_ci } else if (temp_state == QLA82XX_TEMP_WARN) { 43448c2ecf20Sopenharmony_ci if (ha->temperature == QLA82XX_TEMP_NORMAL) 43458c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "Device temperature %d" 43468c2ecf20Sopenharmony_ci " degrees C exceeds operating range." 43478c2ecf20Sopenharmony_ci " Immediate action needed.\n", temp_val); 43488c2ecf20Sopenharmony_ci } else { 43498c2ecf20Sopenharmony_ci if (ha->temperature == QLA82XX_TEMP_WARN) 43508c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Device temperature is" 43518c2ecf20Sopenharmony_ci " now %d degrees C in normal range.\n", 43528c2ecf20Sopenharmony_ci temp_val); 43538c2ecf20Sopenharmony_ci } 43548c2ecf20Sopenharmony_ci ha->temperature = temp_state; 43558c2ecf20Sopenharmony_ci return status; 43568c2ecf20Sopenharmony_ci} 43578c2ecf20Sopenharmony_ci 43588c2ecf20Sopenharmony_ci/** 43598c2ecf20Sopenharmony_ci * qla4_8xxx_check_fw_alive - Check firmware health 43608c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 43618c2ecf20Sopenharmony_ci * 43628c2ecf20Sopenharmony_ci * Context: Interrupt 43638c2ecf20Sopenharmony_ci **/ 43648c2ecf20Sopenharmony_cistatic int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) 43658c2ecf20Sopenharmony_ci{ 43668c2ecf20Sopenharmony_ci uint32_t fw_heartbeat_counter; 43678c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 43688c2ecf20Sopenharmony_ci 43698c2ecf20Sopenharmony_ci fw_heartbeat_counter = qla4_8xxx_rd_direct(ha, 43708c2ecf20Sopenharmony_ci QLA8XXX_PEG_ALIVE_COUNTER); 43718c2ecf20Sopenharmony_ci /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ 43728c2ecf20Sopenharmony_ci if (fw_heartbeat_counter == 0xffffffff) { 43738c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " 43748c2ecf20Sopenharmony_ci "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", 43758c2ecf20Sopenharmony_ci ha->host_no, __func__)); 43768c2ecf20Sopenharmony_ci return status; 43778c2ecf20Sopenharmony_ci } 43788c2ecf20Sopenharmony_ci 43798c2ecf20Sopenharmony_ci if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { 43808c2ecf20Sopenharmony_ci ha->seconds_since_last_heartbeat++; 43818c2ecf20Sopenharmony_ci /* FW not alive after 2 seconds */ 43828c2ecf20Sopenharmony_ci if (ha->seconds_since_last_heartbeat == 2) { 43838c2ecf20Sopenharmony_ci ha->seconds_since_last_heartbeat = 0; 43848c2ecf20Sopenharmony_ci qla4_8xxx_dump_peg_reg(ha); 43858c2ecf20Sopenharmony_ci status = QLA_ERROR; 43868c2ecf20Sopenharmony_ci } 43878c2ecf20Sopenharmony_ci } else 43888c2ecf20Sopenharmony_ci ha->seconds_since_last_heartbeat = 0; 43898c2ecf20Sopenharmony_ci 43908c2ecf20Sopenharmony_ci ha->fw_heartbeat_counter = fw_heartbeat_counter; 43918c2ecf20Sopenharmony_ci return status; 43928c2ecf20Sopenharmony_ci} 43938c2ecf20Sopenharmony_ci 43948c2ecf20Sopenharmony_cistatic void qla4_8xxx_process_fw_error(struct scsi_qla_host *ha) 43958c2ecf20Sopenharmony_ci{ 43968c2ecf20Sopenharmony_ci uint32_t halt_status; 43978c2ecf20Sopenharmony_ci int halt_status_unrecoverable = 0; 43988c2ecf20Sopenharmony_ci 43998c2ecf20Sopenharmony_ci halt_status = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_HALT_STATUS1); 44008c2ecf20Sopenharmony_ci 44018c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 44028c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n", 44038c2ecf20Sopenharmony_ci __func__); 44048c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, 44058c2ecf20Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P0 | 44068c2ecf20Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P1); 44078c2ecf20Sopenharmony_ci 44088c2ecf20Sopenharmony_ci if (QLA82XX_FWERROR_CODE(halt_status) == 0x67) 44098c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Firmware aborted with error code 0x00006700. Device is being reset\n", 44108c2ecf20Sopenharmony_ci __func__); 44118c2ecf20Sopenharmony_ci if (halt_status & HALT_STATUS_UNRECOVERABLE) 44128c2ecf20Sopenharmony_ci halt_status_unrecoverable = 1; 44138c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 44148c2ecf20Sopenharmony_ci if (halt_status & QLA83XX_HALT_STATUS_FW_RESET) 44158c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Firmware error detected device is being reset\n", 44168c2ecf20Sopenharmony_ci __func__); 44178c2ecf20Sopenharmony_ci else if (halt_status & QLA83XX_HALT_STATUS_UNRECOVERABLE) 44188c2ecf20Sopenharmony_ci halt_status_unrecoverable = 1; 44198c2ecf20Sopenharmony_ci } 44208c2ecf20Sopenharmony_ci 44218c2ecf20Sopenharmony_ci /* 44228c2ecf20Sopenharmony_ci * Since we cannot change dev_state in interrupt context, 44238c2ecf20Sopenharmony_ci * set appropriate DPC flag then wakeup DPC 44248c2ecf20Sopenharmony_ci */ 44258c2ecf20Sopenharmony_ci if (halt_status_unrecoverable) { 44268c2ecf20Sopenharmony_ci set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); 44278c2ecf20Sopenharmony_ci } else { 44288c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: detect abort needed!\n", 44298c2ecf20Sopenharmony_ci __func__); 44308c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 44318c2ecf20Sopenharmony_ci } 44328c2ecf20Sopenharmony_ci qla4xxx_mailbox_premature_completion(ha); 44338c2ecf20Sopenharmony_ci qla4xxx_wake_dpc(ha); 44348c2ecf20Sopenharmony_ci} 44358c2ecf20Sopenharmony_ci 44368c2ecf20Sopenharmony_ci/** 44378c2ecf20Sopenharmony_ci * qla4_8xxx_watchdog - Poll dev state 44388c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 44398c2ecf20Sopenharmony_ci * 44408c2ecf20Sopenharmony_ci * Context: Interrupt 44418c2ecf20Sopenharmony_ci **/ 44428c2ecf20Sopenharmony_civoid qla4_8xxx_watchdog(struct scsi_qla_host *ha) 44438c2ecf20Sopenharmony_ci{ 44448c2ecf20Sopenharmony_ci uint32_t dev_state; 44458c2ecf20Sopenharmony_ci uint32_t idc_ctrl; 44468c2ecf20Sopenharmony_ci 44478c2ecf20Sopenharmony_ci if (is_qla8032(ha) && 44488c2ecf20Sopenharmony_ci (qla4_83xx_is_detached(ha) == QLA_SUCCESS)) 44498c2ecf20Sopenharmony_ci WARN_ONCE(1, "%s: iSCSI function %d marked invisible\n", 44508c2ecf20Sopenharmony_ci __func__, ha->func_num); 44518c2ecf20Sopenharmony_ci 44528c2ecf20Sopenharmony_ci /* don't poll if reset is going on */ 44538c2ecf20Sopenharmony_ci if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || 44548c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA, &ha->dpc_flags) || 44558c2ecf20Sopenharmony_ci test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) { 44568c2ecf20Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE); 44578c2ecf20Sopenharmony_ci 44588c2ecf20Sopenharmony_ci if (qla4_8xxx_check_temp(ha)) { 44598c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 44608c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "disabling pause transmit on port 0 & 1.\n"); 44618c2ecf20Sopenharmony_ci qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, 44628c2ecf20Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P0 | 44638c2ecf20Sopenharmony_ci CRB_NIU_XG_PAUSE_CTL_P1); 44648c2ecf20Sopenharmony_ci } 44658c2ecf20Sopenharmony_ci set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags); 44668c2ecf20Sopenharmony_ci qla4xxx_wake_dpc(ha); 44678c2ecf20Sopenharmony_ci } else if (dev_state == QLA8XXX_DEV_NEED_RESET && 44688c2ecf20Sopenharmony_ci !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { 44698c2ecf20Sopenharmony_ci 44708c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: HW State: NEED RESET!\n", 44718c2ecf20Sopenharmony_ci __func__); 44728c2ecf20Sopenharmony_ci 44738c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 44748c2ecf20Sopenharmony_ci idc_ctrl = qla4_83xx_rd_reg(ha, 44758c2ecf20Sopenharmony_ci QLA83XX_IDC_DRV_CTRL); 44768c2ecf20Sopenharmony_ci if (!(idc_ctrl & GRACEFUL_RESET_BIT1)) { 44778c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Graceful reset bit is not set\n", 44788c2ecf20Sopenharmony_ci __func__); 44798c2ecf20Sopenharmony_ci qla4xxx_mailbox_premature_completion( 44808c2ecf20Sopenharmony_ci ha); 44818c2ecf20Sopenharmony_ci } 44828c2ecf20Sopenharmony_ci } 44838c2ecf20Sopenharmony_ci 44848c2ecf20Sopenharmony_ci if ((is_qla8032(ha) || is_qla8042(ha)) || 44858c2ecf20Sopenharmony_ci (is_qla8022(ha) && !ql4xdontresethba)) { 44868c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 44878c2ecf20Sopenharmony_ci qla4xxx_wake_dpc(ha); 44888c2ecf20Sopenharmony_ci } 44898c2ecf20Sopenharmony_ci } else if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT && 44908c2ecf20Sopenharmony_ci !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { 44918c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n", 44928c2ecf20Sopenharmony_ci __func__); 44938c2ecf20Sopenharmony_ci set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags); 44948c2ecf20Sopenharmony_ci qla4xxx_wake_dpc(ha); 44958c2ecf20Sopenharmony_ci } else { 44968c2ecf20Sopenharmony_ci /* Check firmware health */ 44978c2ecf20Sopenharmony_ci if (qla4_8xxx_check_fw_alive(ha)) 44988c2ecf20Sopenharmony_ci qla4_8xxx_process_fw_error(ha); 44998c2ecf20Sopenharmony_ci } 45008c2ecf20Sopenharmony_ci } 45018c2ecf20Sopenharmony_ci} 45028c2ecf20Sopenharmony_ci 45038c2ecf20Sopenharmony_cistatic void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) 45048c2ecf20Sopenharmony_ci{ 45058c2ecf20Sopenharmony_ci struct iscsi_session *sess; 45068c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 45078c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 45088c2ecf20Sopenharmony_ci 45098c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 45108c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 45118c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 45128c2ecf20Sopenharmony_ci 45138c2ecf20Sopenharmony_ci if (!(ddb_entry->ddb_type == FLASH_DDB)) 45148c2ecf20Sopenharmony_ci return; 45158c2ecf20Sopenharmony_ci 45168c2ecf20Sopenharmony_ci if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) && 45178c2ecf20Sopenharmony_ci !iscsi_is_session_online(cls_sess)) { 45188c2ecf20Sopenharmony_ci if (atomic_read(&ddb_entry->retry_relogin_timer) != 45198c2ecf20Sopenharmony_ci INVALID_ENTRY) { 45208c2ecf20Sopenharmony_ci if (atomic_read(&ddb_entry->retry_relogin_timer) == 45218c2ecf20Sopenharmony_ci 0) { 45228c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->retry_relogin_timer, 45238c2ecf20Sopenharmony_ci INVALID_ENTRY); 45248c2ecf20Sopenharmony_ci set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); 45258c2ecf20Sopenharmony_ci set_bit(DF_RELOGIN, &ddb_entry->flags); 45268c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 45278c2ecf20Sopenharmony_ci "%s: index [%d] login device\n", 45288c2ecf20Sopenharmony_ci __func__, ddb_entry->fw_ddb_index)); 45298c2ecf20Sopenharmony_ci } else 45308c2ecf20Sopenharmony_ci atomic_dec(&ddb_entry->retry_relogin_timer); 45318c2ecf20Sopenharmony_ci } 45328c2ecf20Sopenharmony_ci } 45338c2ecf20Sopenharmony_ci 45348c2ecf20Sopenharmony_ci /* Wait for relogin to timeout */ 45358c2ecf20Sopenharmony_ci if (atomic_read(&ddb_entry->relogin_timer) && 45368c2ecf20Sopenharmony_ci (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { 45378c2ecf20Sopenharmony_ci /* 45388c2ecf20Sopenharmony_ci * If the relogin times out and the device is 45398c2ecf20Sopenharmony_ci * still NOT ONLINE then try and relogin again. 45408c2ecf20Sopenharmony_ci */ 45418c2ecf20Sopenharmony_ci if (!iscsi_is_session_online(cls_sess)) { 45428c2ecf20Sopenharmony_ci /* Reset retry relogin timer */ 45438c2ecf20Sopenharmony_ci atomic_inc(&ddb_entry->relogin_retry_count); 45448c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 45458c2ecf20Sopenharmony_ci "%s: index[%d] relogin timed out-retrying" 45468c2ecf20Sopenharmony_ci " relogin (%d), retry (%d)\n", __func__, 45478c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index, 45488c2ecf20Sopenharmony_ci atomic_read(&ddb_entry->relogin_retry_count), 45498c2ecf20Sopenharmony_ci ddb_entry->default_time2wait + 4)); 45508c2ecf20Sopenharmony_ci set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); 45518c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->retry_relogin_timer, 45528c2ecf20Sopenharmony_ci ddb_entry->default_time2wait + 4); 45538c2ecf20Sopenharmony_ci } 45548c2ecf20Sopenharmony_ci } 45558c2ecf20Sopenharmony_ci} 45568c2ecf20Sopenharmony_ci 45578c2ecf20Sopenharmony_ci/** 45588c2ecf20Sopenharmony_ci * qla4xxx_timer - checks every second for work to do. 45598c2ecf20Sopenharmony_ci * @t: Context to obtain pointer to host adapter structure. 45608c2ecf20Sopenharmony_ci **/ 45618c2ecf20Sopenharmony_cistatic void qla4xxx_timer(struct timer_list *t) 45628c2ecf20Sopenharmony_ci{ 45638c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = from_timer(ha, t, timer); 45648c2ecf20Sopenharmony_ci int start_dpc = 0; 45658c2ecf20Sopenharmony_ci uint16_t w; 45668c2ecf20Sopenharmony_ci 45678c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb); 45688c2ecf20Sopenharmony_ci 45698c2ecf20Sopenharmony_ci /* If we are in the middle of AER/EEH processing 45708c2ecf20Sopenharmony_ci * skip any processing and reschedule the timer 45718c2ecf20Sopenharmony_ci */ 45728c2ecf20Sopenharmony_ci if (test_bit(AF_EEH_BUSY, &ha->flags)) { 45738c2ecf20Sopenharmony_ci mod_timer(&ha->timer, jiffies + HZ); 45748c2ecf20Sopenharmony_ci return; 45758c2ecf20Sopenharmony_ci } 45768c2ecf20Sopenharmony_ci 45778c2ecf20Sopenharmony_ci /* Hardware read to trigger an EEH error during mailbox waits. */ 45788c2ecf20Sopenharmony_ci if (!pci_channel_offline(ha->pdev)) 45798c2ecf20Sopenharmony_ci pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); 45808c2ecf20Sopenharmony_ci 45818c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 45828c2ecf20Sopenharmony_ci qla4_8xxx_watchdog(ha); 45838c2ecf20Sopenharmony_ci 45848c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 45858c2ecf20Sopenharmony_ci /* Check for heartbeat interval. */ 45868c2ecf20Sopenharmony_ci if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE && 45878c2ecf20Sopenharmony_ci ha->heartbeat_interval != 0) { 45888c2ecf20Sopenharmony_ci ha->seconds_since_last_heartbeat++; 45898c2ecf20Sopenharmony_ci if (ha->seconds_since_last_heartbeat > 45908c2ecf20Sopenharmony_ci ha->heartbeat_interval + 2) 45918c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 45928c2ecf20Sopenharmony_ci } 45938c2ecf20Sopenharmony_ci } 45948c2ecf20Sopenharmony_ci 45958c2ecf20Sopenharmony_ci /* Process any deferred work. */ 45968c2ecf20Sopenharmony_ci if (!list_empty(&ha->work_list)) 45978c2ecf20Sopenharmony_ci start_dpc++; 45988c2ecf20Sopenharmony_ci 45998c2ecf20Sopenharmony_ci /* Wakeup the dpc routine for this adapter, if needed. */ 46008c2ecf20Sopenharmony_ci if (start_dpc || 46018c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA, &ha->dpc_flags) || 46028c2ecf20Sopenharmony_ci test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) || 46038c2ecf20Sopenharmony_ci test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) || 46048c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || 46058c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || 46068c2ecf20Sopenharmony_ci test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || 46078c2ecf20Sopenharmony_ci test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) || 46088c2ecf20Sopenharmony_ci test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) || 46098c2ecf20Sopenharmony_ci test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) || 46108c2ecf20Sopenharmony_ci test_bit(DPC_SYSFS_DDB_EXPORT, &ha->dpc_flags) || 46118c2ecf20Sopenharmony_ci test_bit(DPC_AEN, &ha->dpc_flags)) { 46128c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" 46138c2ecf20Sopenharmony_ci " - dpc flags = 0x%lx\n", 46148c2ecf20Sopenharmony_ci ha->host_no, __func__, ha->dpc_flags)); 46158c2ecf20Sopenharmony_ci qla4xxx_wake_dpc(ha); 46168c2ecf20Sopenharmony_ci } 46178c2ecf20Sopenharmony_ci 46188c2ecf20Sopenharmony_ci /* Reschedule timer thread to call us back in one second */ 46198c2ecf20Sopenharmony_ci mod_timer(&ha->timer, jiffies + HZ); 46208c2ecf20Sopenharmony_ci 46218c2ecf20Sopenharmony_ci DEBUG2(ha->seconds_since_last_intr++); 46228c2ecf20Sopenharmony_ci} 46238c2ecf20Sopenharmony_ci 46248c2ecf20Sopenharmony_ci/** 46258c2ecf20Sopenharmony_ci * qla4xxx_cmd_wait - waits for all outstanding commands to complete 46268c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 46278c2ecf20Sopenharmony_ci * 46288c2ecf20Sopenharmony_ci * This routine stalls the driver until all outstanding commands are returned. 46298c2ecf20Sopenharmony_ci * Caller must release the Hardware Lock prior to calling this routine. 46308c2ecf20Sopenharmony_ci **/ 46318c2ecf20Sopenharmony_cistatic int qla4xxx_cmd_wait(struct scsi_qla_host *ha) 46328c2ecf20Sopenharmony_ci{ 46338c2ecf20Sopenharmony_ci uint32_t index = 0; 46348c2ecf20Sopenharmony_ci unsigned long flags; 46358c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd; 46368c2ecf20Sopenharmony_ci unsigned long wtime; 46378c2ecf20Sopenharmony_ci uint32_t wtmo; 46388c2ecf20Sopenharmony_ci 46398c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) 46408c2ecf20Sopenharmony_ci wtmo = WAIT_CMD_TOV; 46418c2ecf20Sopenharmony_ci else 46428c2ecf20Sopenharmony_ci wtmo = ha->nx_reset_timeout / 2; 46438c2ecf20Sopenharmony_ci 46448c2ecf20Sopenharmony_ci wtime = jiffies + (wtmo * HZ); 46458c2ecf20Sopenharmony_ci 46468c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 46478c2ecf20Sopenharmony_ci "Wait up to %u seconds for cmds to complete\n", 46488c2ecf20Sopenharmony_ci wtmo)); 46498c2ecf20Sopenharmony_ci 46508c2ecf20Sopenharmony_ci while (!time_after_eq(jiffies, wtime)) { 46518c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 46528c2ecf20Sopenharmony_ci /* Find a command that hasn't completed. */ 46538c2ecf20Sopenharmony_ci for (index = 0; index < ha->host->can_queue; index++) { 46548c2ecf20Sopenharmony_ci cmd = scsi_host_find_tag(ha->host, index); 46558c2ecf20Sopenharmony_ci /* 46568c2ecf20Sopenharmony_ci * We cannot just check if the index is valid, 46578c2ecf20Sopenharmony_ci * becase if we are run from the scsi eh, then 46588c2ecf20Sopenharmony_ci * the scsi/block layer is going to prevent 46598c2ecf20Sopenharmony_ci * the tag from being released. 46608c2ecf20Sopenharmony_ci */ 46618c2ecf20Sopenharmony_ci if (cmd != NULL && CMD_SP(cmd)) 46628c2ecf20Sopenharmony_ci break; 46638c2ecf20Sopenharmony_ci } 46648c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 46658c2ecf20Sopenharmony_ci 46668c2ecf20Sopenharmony_ci /* If No Commands are pending, wait is complete */ 46678c2ecf20Sopenharmony_ci if (index == ha->host->can_queue) 46688c2ecf20Sopenharmony_ci return QLA_SUCCESS; 46698c2ecf20Sopenharmony_ci 46708c2ecf20Sopenharmony_ci msleep(1000); 46718c2ecf20Sopenharmony_ci } 46728c2ecf20Sopenharmony_ci /* If we timed out on waiting for commands to come back 46738c2ecf20Sopenharmony_ci * return ERROR. */ 46748c2ecf20Sopenharmony_ci return QLA_ERROR; 46758c2ecf20Sopenharmony_ci} 46768c2ecf20Sopenharmony_ci 46778c2ecf20Sopenharmony_ciint qla4xxx_hw_reset(struct scsi_qla_host *ha) 46788c2ecf20Sopenharmony_ci{ 46798c2ecf20Sopenharmony_ci uint32_t ctrl_status; 46808c2ecf20Sopenharmony_ci unsigned long flags = 0; 46818c2ecf20Sopenharmony_ci 46828c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__)); 46838c2ecf20Sopenharmony_ci 46848c2ecf20Sopenharmony_ci if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) 46858c2ecf20Sopenharmony_ci return QLA_ERROR; 46868c2ecf20Sopenharmony_ci 46878c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 46888c2ecf20Sopenharmony_ci 46898c2ecf20Sopenharmony_ci /* 46908c2ecf20Sopenharmony_ci * If the SCSI Reset Interrupt bit is set, clear it. 46918c2ecf20Sopenharmony_ci * Otherwise, the Soft Reset won't work. 46928c2ecf20Sopenharmony_ci */ 46938c2ecf20Sopenharmony_ci ctrl_status = readw(&ha->reg->ctrl_status); 46948c2ecf20Sopenharmony_ci if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) 46958c2ecf20Sopenharmony_ci writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status); 46968c2ecf20Sopenharmony_ci 46978c2ecf20Sopenharmony_ci /* Issue Soft Reset */ 46988c2ecf20Sopenharmony_ci writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status); 46998c2ecf20Sopenharmony_ci readl(&ha->reg->ctrl_status); 47008c2ecf20Sopenharmony_ci 47018c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47028c2ecf20Sopenharmony_ci return QLA_SUCCESS; 47038c2ecf20Sopenharmony_ci} 47048c2ecf20Sopenharmony_ci 47058c2ecf20Sopenharmony_ci/** 47068c2ecf20Sopenharmony_ci * qla4xxx_soft_reset - performs soft reset. 47078c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 47088c2ecf20Sopenharmony_ci **/ 47098c2ecf20Sopenharmony_ciint qla4xxx_soft_reset(struct scsi_qla_host *ha) 47108c2ecf20Sopenharmony_ci{ 47118c2ecf20Sopenharmony_ci uint32_t max_wait_time; 47128c2ecf20Sopenharmony_ci unsigned long flags = 0; 47138c2ecf20Sopenharmony_ci int status; 47148c2ecf20Sopenharmony_ci uint32_t ctrl_status; 47158c2ecf20Sopenharmony_ci 47168c2ecf20Sopenharmony_ci status = qla4xxx_hw_reset(ha); 47178c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) 47188c2ecf20Sopenharmony_ci return status; 47198c2ecf20Sopenharmony_ci 47208c2ecf20Sopenharmony_ci status = QLA_ERROR; 47218c2ecf20Sopenharmony_ci /* Wait until the Network Reset Intr bit is cleared */ 47228c2ecf20Sopenharmony_ci max_wait_time = RESET_INTR_TOV; 47238c2ecf20Sopenharmony_ci do { 47248c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47258c2ecf20Sopenharmony_ci ctrl_status = readw(&ha->reg->ctrl_status); 47268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47278c2ecf20Sopenharmony_ci 47288c2ecf20Sopenharmony_ci if ((ctrl_status & CSR_NET_RESET_INTR) == 0) 47298c2ecf20Sopenharmony_ci break; 47308c2ecf20Sopenharmony_ci 47318c2ecf20Sopenharmony_ci msleep(1000); 47328c2ecf20Sopenharmony_ci } while ((--max_wait_time)); 47338c2ecf20Sopenharmony_ci 47348c2ecf20Sopenharmony_ci if ((ctrl_status & CSR_NET_RESET_INTR) != 0) { 47358c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_WARNING 47368c2ecf20Sopenharmony_ci "scsi%ld: Network Reset Intr not cleared by " 47378c2ecf20Sopenharmony_ci "Network function, clearing it now!\n", 47388c2ecf20Sopenharmony_ci ha->host_no)); 47398c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47408c2ecf20Sopenharmony_ci writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status); 47418c2ecf20Sopenharmony_ci readl(&ha->reg->ctrl_status); 47428c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47438c2ecf20Sopenharmony_ci } 47448c2ecf20Sopenharmony_ci 47458c2ecf20Sopenharmony_ci /* Wait until the firmware tells us the Soft Reset is done */ 47468c2ecf20Sopenharmony_ci max_wait_time = SOFT_RESET_TOV; 47478c2ecf20Sopenharmony_ci do { 47488c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47498c2ecf20Sopenharmony_ci ctrl_status = readw(&ha->reg->ctrl_status); 47508c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47518c2ecf20Sopenharmony_ci 47528c2ecf20Sopenharmony_ci if ((ctrl_status & CSR_SOFT_RESET) == 0) { 47538c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 47548c2ecf20Sopenharmony_ci break; 47558c2ecf20Sopenharmony_ci } 47568c2ecf20Sopenharmony_ci 47578c2ecf20Sopenharmony_ci msleep(1000); 47588c2ecf20Sopenharmony_ci } while ((--max_wait_time)); 47598c2ecf20Sopenharmony_ci 47608c2ecf20Sopenharmony_ci /* 47618c2ecf20Sopenharmony_ci * Also, make sure that the SCSI Reset Interrupt bit has been cleared 47628c2ecf20Sopenharmony_ci * after the soft reset has taken place. 47638c2ecf20Sopenharmony_ci */ 47648c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47658c2ecf20Sopenharmony_ci ctrl_status = readw(&ha->reg->ctrl_status); 47668c2ecf20Sopenharmony_ci if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) { 47678c2ecf20Sopenharmony_ci writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status); 47688c2ecf20Sopenharmony_ci readl(&ha->reg->ctrl_status); 47698c2ecf20Sopenharmony_ci } 47708c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47718c2ecf20Sopenharmony_ci 47728c2ecf20Sopenharmony_ci /* If soft reset fails then most probably the bios on other 47738c2ecf20Sopenharmony_ci * function is also enabled. 47748c2ecf20Sopenharmony_ci * Since the initialization is sequential the other fn 47758c2ecf20Sopenharmony_ci * wont be able to acknowledge the soft reset. 47768c2ecf20Sopenharmony_ci * Issue a force soft reset to workaround this scenario. 47778c2ecf20Sopenharmony_ci */ 47788c2ecf20Sopenharmony_ci if (max_wait_time == 0) { 47798c2ecf20Sopenharmony_ci /* Issue Force Soft Reset */ 47808c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47818c2ecf20Sopenharmony_ci writel(set_rmask(CSR_FORCE_SOFT_RESET), &ha->reg->ctrl_status); 47828c2ecf20Sopenharmony_ci readl(&ha->reg->ctrl_status); 47838c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47848c2ecf20Sopenharmony_ci /* Wait until the firmware tells us the Soft Reset is done */ 47858c2ecf20Sopenharmony_ci max_wait_time = SOFT_RESET_TOV; 47868c2ecf20Sopenharmony_ci do { 47878c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 47888c2ecf20Sopenharmony_ci ctrl_status = readw(&ha->reg->ctrl_status); 47898c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 47908c2ecf20Sopenharmony_ci 47918c2ecf20Sopenharmony_ci if ((ctrl_status & CSR_FORCE_SOFT_RESET) == 0) { 47928c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 47938c2ecf20Sopenharmony_ci break; 47948c2ecf20Sopenharmony_ci } 47958c2ecf20Sopenharmony_ci 47968c2ecf20Sopenharmony_ci msleep(1000); 47978c2ecf20Sopenharmony_ci } while ((--max_wait_time)); 47988c2ecf20Sopenharmony_ci } 47998c2ecf20Sopenharmony_ci 48008c2ecf20Sopenharmony_ci return status; 48018c2ecf20Sopenharmony_ci} 48028c2ecf20Sopenharmony_ci 48038c2ecf20Sopenharmony_ci/** 48048c2ecf20Sopenharmony_ci * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S. 48058c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 48068c2ecf20Sopenharmony_ci * @res: returned scsi status 48078c2ecf20Sopenharmony_ci * 48088c2ecf20Sopenharmony_ci * This routine is called just prior to a HARD RESET to return all 48098c2ecf20Sopenharmony_ci * outstanding commands back to the Operating System. 48108c2ecf20Sopenharmony_ci * Caller should make sure that the following locks are released 48118c2ecf20Sopenharmony_ci * before this calling routine: Hardware lock, and io_request_lock. 48128c2ecf20Sopenharmony_ci **/ 48138c2ecf20Sopenharmony_cistatic void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res) 48148c2ecf20Sopenharmony_ci{ 48158c2ecf20Sopenharmony_ci struct srb *srb; 48168c2ecf20Sopenharmony_ci int i; 48178c2ecf20Sopenharmony_ci unsigned long flags; 48188c2ecf20Sopenharmony_ci 48198c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 48208c2ecf20Sopenharmony_ci for (i = 0; i < ha->host->can_queue; i++) { 48218c2ecf20Sopenharmony_ci srb = qla4xxx_del_from_active_array(ha, i); 48228c2ecf20Sopenharmony_ci if (srb != NULL) { 48238c2ecf20Sopenharmony_ci srb->cmd->result = res; 48248c2ecf20Sopenharmony_ci kref_put(&srb->srb_ref, qla4xxx_srb_compl); 48258c2ecf20Sopenharmony_ci } 48268c2ecf20Sopenharmony_ci } 48278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 48288c2ecf20Sopenharmony_ci} 48298c2ecf20Sopenharmony_ci 48308c2ecf20Sopenharmony_civoid qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha) 48318c2ecf20Sopenharmony_ci{ 48328c2ecf20Sopenharmony_ci clear_bit(AF_ONLINE, &ha->flags); 48338c2ecf20Sopenharmony_ci 48348c2ecf20Sopenharmony_ci /* Disable the board */ 48358c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Disabling the board\n"); 48368c2ecf20Sopenharmony_ci 48378c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); 48388c2ecf20Sopenharmony_ci qla4xxx_mark_all_devices_missing(ha); 48398c2ecf20Sopenharmony_ci clear_bit(AF_INIT_DONE, &ha->flags); 48408c2ecf20Sopenharmony_ci} 48418c2ecf20Sopenharmony_ci 48428c2ecf20Sopenharmony_cistatic void qla4xxx_fail_session(struct iscsi_cls_session *cls_session) 48438c2ecf20Sopenharmony_ci{ 48448c2ecf20Sopenharmony_ci struct iscsi_session *sess; 48458c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 48468c2ecf20Sopenharmony_ci 48478c2ecf20Sopenharmony_ci sess = cls_session->dd_data; 48488c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 48498c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED; 48508c2ecf20Sopenharmony_ci 48518c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type == FLASH_DDB) 48528c2ecf20Sopenharmony_ci iscsi_block_session(ddb_entry->sess); 48538c2ecf20Sopenharmony_ci else 48548c2ecf20Sopenharmony_ci iscsi_session_failure(cls_session->dd_data, 48558c2ecf20Sopenharmony_ci ISCSI_ERR_CONN_FAILED); 48568c2ecf20Sopenharmony_ci} 48578c2ecf20Sopenharmony_ci 48588c2ecf20Sopenharmony_ci/** 48598c2ecf20Sopenharmony_ci * qla4xxx_recover_adapter - recovers adapter after a fatal error 48608c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 48618c2ecf20Sopenharmony_ci **/ 48628c2ecf20Sopenharmony_cistatic int qla4xxx_recover_adapter(struct scsi_qla_host *ha) 48638c2ecf20Sopenharmony_ci{ 48648c2ecf20Sopenharmony_ci int status = QLA_ERROR; 48658c2ecf20Sopenharmony_ci uint8_t reset_chip = 0; 48668c2ecf20Sopenharmony_ci uint32_t dev_state; 48678c2ecf20Sopenharmony_ci unsigned long wait; 48688c2ecf20Sopenharmony_ci 48698c2ecf20Sopenharmony_ci /* Stall incoming I/O until we are done */ 48708c2ecf20Sopenharmony_ci scsi_block_requests(ha->host); 48718c2ecf20Sopenharmony_ci clear_bit(AF_ONLINE, &ha->flags); 48728c2ecf20Sopenharmony_ci clear_bit(AF_LINK_UP, &ha->flags); 48738c2ecf20Sopenharmony_ci 48748c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__)); 48758c2ecf20Sopenharmony_ci 48768c2ecf20Sopenharmony_ci set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); 48778c2ecf20Sopenharmony_ci 48788c2ecf20Sopenharmony_ci if ((is_qla8032(ha) || is_qla8042(ha)) && 48798c2ecf20Sopenharmony_ci !test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) { 48808c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n", 48818c2ecf20Sopenharmony_ci __func__); 48828c2ecf20Sopenharmony_ci /* disable pause frame for ISP83xx */ 48838c2ecf20Sopenharmony_ci qla4_83xx_disable_pause(ha); 48848c2ecf20Sopenharmony_ci } 48858c2ecf20Sopenharmony_ci 48868c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_fail_session); 48878c2ecf20Sopenharmony_ci 48888c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) 48898c2ecf20Sopenharmony_ci reset_chip = 1; 48908c2ecf20Sopenharmony_ci 48918c2ecf20Sopenharmony_ci /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific) 48928c2ecf20Sopenharmony_ci * do not reset adapter, jump to initialize_adapter */ 48938c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { 48948c2ecf20Sopenharmony_ci status = QLA_SUCCESS; 48958c2ecf20Sopenharmony_ci goto recover_ha_init_adapter; 48968c2ecf20Sopenharmony_ci } 48978c2ecf20Sopenharmony_ci 48988c2ecf20Sopenharmony_ci /* For the ISP-8xxx adapter, issue a stop_firmware if invoked 48998c2ecf20Sopenharmony_ci * from eh_host_reset or ioctl module */ 49008c2ecf20Sopenharmony_ci if (is_qla80XX(ha) && !reset_chip && 49018c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) { 49028c2ecf20Sopenharmony_ci 49038c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 49048c2ecf20Sopenharmony_ci "scsi%ld: %s - Performing stop_firmware...\n", 49058c2ecf20Sopenharmony_ci ha->host_no, __func__)); 49068c2ecf20Sopenharmony_ci status = ha->isp_ops->reset_firmware(ha); 49078c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 49088c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 49098c2ecf20Sopenharmony_ci qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); 49108c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_RESET << 16); 49118c2ecf20Sopenharmony_ci } else { 49128c2ecf20Sopenharmony_ci /* If the stop_firmware fails then 49138c2ecf20Sopenharmony_ci * reset the entire chip */ 49148c2ecf20Sopenharmony_ci reset_chip = 1; 49158c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); 49168c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 49178c2ecf20Sopenharmony_ci } 49188c2ecf20Sopenharmony_ci } 49198c2ecf20Sopenharmony_ci 49208c2ecf20Sopenharmony_ci /* Issue full chip reset if recovering from a catastrophic error, 49218c2ecf20Sopenharmony_ci * or if stop_firmware fails for ISP-8xxx. 49228c2ecf20Sopenharmony_ci * This is the default case for ISP-4xxx */ 49238c2ecf20Sopenharmony_ci if (is_qla40XX(ha) || reset_chip) { 49248c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) 49258c2ecf20Sopenharmony_ci goto chip_reset; 49268c2ecf20Sopenharmony_ci 49278c2ecf20Sopenharmony_ci /* Check if 8XXX firmware is alive or not 49288c2ecf20Sopenharmony_ci * We may have arrived here from NEED_RESET 49298c2ecf20Sopenharmony_ci * detection only */ 49308c2ecf20Sopenharmony_ci if (test_bit(AF_FW_RECOVERY, &ha->flags)) 49318c2ecf20Sopenharmony_ci goto chip_reset; 49328c2ecf20Sopenharmony_ci 49338c2ecf20Sopenharmony_ci wait = jiffies + (FW_ALIVE_WAIT_TOV * HZ); 49348c2ecf20Sopenharmony_ci while (time_before(jiffies, wait)) { 49358c2ecf20Sopenharmony_ci if (qla4_8xxx_check_fw_alive(ha)) { 49368c2ecf20Sopenharmony_ci qla4xxx_mailbox_premature_completion(ha); 49378c2ecf20Sopenharmony_ci break; 49388c2ecf20Sopenharmony_ci } 49398c2ecf20Sopenharmony_ci 49408c2ecf20Sopenharmony_ci set_current_state(TASK_UNINTERRUPTIBLE); 49418c2ecf20Sopenharmony_ci schedule_timeout(HZ); 49428c2ecf20Sopenharmony_ci } 49438c2ecf20Sopenharmony_cichip_reset: 49448c2ecf20Sopenharmony_ci if (!test_bit(AF_FW_RECOVERY, &ha->flags)) 49458c2ecf20Sopenharmony_ci qla4xxx_cmd_wait(ha); 49468c2ecf20Sopenharmony_ci 49478c2ecf20Sopenharmony_ci qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); 49488c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 49498c2ecf20Sopenharmony_ci "scsi%ld: %s - Performing chip reset..\n", 49508c2ecf20Sopenharmony_ci ha->host_no, __func__)); 49518c2ecf20Sopenharmony_ci status = ha->isp_ops->reset_chip(ha); 49528c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_RESET << 16); 49538c2ecf20Sopenharmony_ci } 49548c2ecf20Sopenharmony_ci 49558c2ecf20Sopenharmony_ci /* Flush any pending ddb changed AENs */ 49568c2ecf20Sopenharmony_ci qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); 49578c2ecf20Sopenharmony_ci 49588c2ecf20Sopenharmony_cirecover_ha_init_adapter: 49598c2ecf20Sopenharmony_ci /* Upon successful firmware/chip reset, re-initialize the adapter */ 49608c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 49618c2ecf20Sopenharmony_ci /* For ISP-4xxx, force function 1 to always initialize 49628c2ecf20Sopenharmony_ci * before function 3 to prevent both funcions from 49638c2ecf20Sopenharmony_ci * stepping on top of the other */ 49648c2ecf20Sopenharmony_ci if (is_qla40XX(ha) && (ha->mac_index == 3)) 49658c2ecf20Sopenharmony_ci ssleep(6); 49668c2ecf20Sopenharmony_ci 49678c2ecf20Sopenharmony_ci /* NOTE: AF_ONLINE flag set upon successful completion of 49688c2ecf20Sopenharmony_ci * qla4xxx_initialize_adapter */ 49698c2ecf20Sopenharmony_ci status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); 49708c2ecf20Sopenharmony_ci if (is_qla80XX(ha) && (status == QLA_ERROR)) { 49718c2ecf20Sopenharmony_ci status = qla4_8xxx_check_init_adapter_retry(ha); 49728c2ecf20Sopenharmony_ci if (status == QLA_ERROR) { 49738c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Don't retry recover adapter\n", 49748c2ecf20Sopenharmony_ci ha->host_no, __func__); 49758c2ecf20Sopenharmony_ci qla4xxx_dead_adapter_cleanup(ha); 49768c2ecf20Sopenharmony_ci clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); 49778c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA, &ha->dpc_flags); 49788c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_FW_CONTEXT, 49798c2ecf20Sopenharmony_ci &ha->dpc_flags); 49808c2ecf20Sopenharmony_ci goto exit_recover; 49818c2ecf20Sopenharmony_ci } 49828c2ecf20Sopenharmony_ci } 49838c2ecf20Sopenharmony_ci } 49848c2ecf20Sopenharmony_ci 49858c2ecf20Sopenharmony_ci /* Retry failed adapter initialization, if necessary 49868c2ecf20Sopenharmony_ci * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific) 49878c2ecf20Sopenharmony_ci * case to prevent ping-pong resets between functions */ 49888c2ecf20Sopenharmony_ci if (!test_bit(AF_ONLINE, &ha->flags) && 49898c2ecf20Sopenharmony_ci !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { 49908c2ecf20Sopenharmony_ci /* Adapter initialization failed, see if we can retry 49918c2ecf20Sopenharmony_ci * resetting the ha. 49928c2ecf20Sopenharmony_ci * Since we don't want to block the DPC for too long 49938c2ecf20Sopenharmony_ci * with multiple resets in the same thread, 49948c2ecf20Sopenharmony_ci * utilize DPC to retry */ 49958c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 49968c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 49978c2ecf20Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, 49988c2ecf20Sopenharmony_ci QLA8XXX_CRB_DEV_STATE); 49998c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 50008c2ecf20Sopenharmony_ci if (dev_state == QLA8XXX_DEV_FAILED) { 50018c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: don't retry " 50028c2ecf20Sopenharmony_ci "recover adapter. H/W is in Failed " 50038c2ecf20Sopenharmony_ci "state\n", __func__); 50048c2ecf20Sopenharmony_ci qla4xxx_dead_adapter_cleanup(ha); 50058c2ecf20Sopenharmony_ci clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); 50068c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA, &ha->dpc_flags); 50078c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_FW_CONTEXT, 50088c2ecf20Sopenharmony_ci &ha->dpc_flags); 50098c2ecf20Sopenharmony_ci status = QLA_ERROR; 50108c2ecf20Sopenharmony_ci 50118c2ecf20Sopenharmony_ci goto exit_recover; 50128c2ecf20Sopenharmony_ci } 50138c2ecf20Sopenharmony_ci } 50148c2ecf20Sopenharmony_ci 50158c2ecf20Sopenharmony_ci if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) { 50168c2ecf20Sopenharmony_ci ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES; 50178c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: recover adapter - retrying " 50188c2ecf20Sopenharmony_ci "(%d) more times\n", ha->host_no, 50198c2ecf20Sopenharmony_ci ha->retry_reset_ha_cnt)); 50208c2ecf20Sopenharmony_ci set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); 50218c2ecf20Sopenharmony_ci status = QLA_ERROR; 50228c2ecf20Sopenharmony_ci } else { 50238c2ecf20Sopenharmony_ci if (ha->retry_reset_ha_cnt > 0) { 50248c2ecf20Sopenharmony_ci /* Schedule another Reset HA--DPC will retry */ 50258c2ecf20Sopenharmony_ci ha->retry_reset_ha_cnt--; 50268c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: recover adapter - " 50278c2ecf20Sopenharmony_ci "retry remaining %d\n", 50288c2ecf20Sopenharmony_ci ha->host_no, 50298c2ecf20Sopenharmony_ci ha->retry_reset_ha_cnt)); 50308c2ecf20Sopenharmony_ci status = QLA_ERROR; 50318c2ecf20Sopenharmony_ci } 50328c2ecf20Sopenharmony_ci 50338c2ecf20Sopenharmony_ci if (ha->retry_reset_ha_cnt == 0) { 50348c2ecf20Sopenharmony_ci /* Recover adapter retries have been exhausted. 50358c2ecf20Sopenharmony_ci * Adapter DEAD */ 50368c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: recover adapter " 50378c2ecf20Sopenharmony_ci "failed - board disabled\n", 50388c2ecf20Sopenharmony_ci ha->host_no)); 50398c2ecf20Sopenharmony_ci qla4xxx_dead_adapter_cleanup(ha); 50408c2ecf20Sopenharmony_ci clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); 50418c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA, &ha->dpc_flags); 50428c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_FW_CONTEXT, 50438c2ecf20Sopenharmony_ci &ha->dpc_flags); 50448c2ecf20Sopenharmony_ci status = QLA_ERROR; 50458c2ecf20Sopenharmony_ci } 50468c2ecf20Sopenharmony_ci } 50478c2ecf20Sopenharmony_ci } else { 50488c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA, &ha->dpc_flags); 50498c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); 50508c2ecf20Sopenharmony_ci clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags); 50518c2ecf20Sopenharmony_ci } 50528c2ecf20Sopenharmony_ci 50538c2ecf20Sopenharmony_ciexit_recover: 50548c2ecf20Sopenharmony_ci ha->adapter_error_count++; 50558c2ecf20Sopenharmony_ci 50568c2ecf20Sopenharmony_ci if (test_bit(AF_ONLINE, &ha->flags)) 50578c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 50588c2ecf20Sopenharmony_ci 50598c2ecf20Sopenharmony_ci scsi_unblock_requests(ha->host); 50608c2ecf20Sopenharmony_ci 50618c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); 50628c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no, 50638c2ecf20Sopenharmony_ci status == QLA_ERROR ? "FAILED" : "SUCCEEDED")); 50648c2ecf20Sopenharmony_ci 50658c2ecf20Sopenharmony_ci return status; 50668c2ecf20Sopenharmony_ci} 50678c2ecf20Sopenharmony_ci 50688c2ecf20Sopenharmony_cistatic void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session) 50698c2ecf20Sopenharmony_ci{ 50708c2ecf20Sopenharmony_ci struct iscsi_session *sess; 50718c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 50728c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 50738c2ecf20Sopenharmony_ci 50748c2ecf20Sopenharmony_ci sess = cls_session->dd_data; 50758c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 50768c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 50778c2ecf20Sopenharmony_ci if (!iscsi_is_session_online(cls_session)) { 50788c2ecf20Sopenharmony_ci if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { 50798c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" 50808c2ecf20Sopenharmony_ci " unblock session\n", ha->host_no, __func__, 50818c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index); 50828c2ecf20Sopenharmony_ci iscsi_unblock_session(ddb_entry->sess); 50838c2ecf20Sopenharmony_ci } else { 50848c2ecf20Sopenharmony_ci /* Trigger relogin */ 50858c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type == FLASH_DDB) { 50868c2ecf20Sopenharmony_ci if (!(test_bit(DF_RELOGIN, &ddb_entry->flags) || 50878c2ecf20Sopenharmony_ci test_bit(DF_DISABLE_RELOGIN, 50888c2ecf20Sopenharmony_ci &ddb_entry->flags))) 50898c2ecf20Sopenharmony_ci qla4xxx_arm_relogin_timer(ddb_entry); 50908c2ecf20Sopenharmony_ci } else 50918c2ecf20Sopenharmony_ci iscsi_session_failure(cls_session->dd_data, 50928c2ecf20Sopenharmony_ci ISCSI_ERR_CONN_FAILED); 50938c2ecf20Sopenharmony_ci } 50948c2ecf20Sopenharmony_ci } 50958c2ecf20Sopenharmony_ci} 50968c2ecf20Sopenharmony_ci 50978c2ecf20Sopenharmony_ciint qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session) 50988c2ecf20Sopenharmony_ci{ 50998c2ecf20Sopenharmony_ci struct iscsi_session *sess; 51008c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 51018c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 51028c2ecf20Sopenharmony_ci 51038c2ecf20Sopenharmony_ci sess = cls_session->dd_data; 51048c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 51058c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 51068c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" 51078c2ecf20Sopenharmony_ci " unblock session\n", ha->host_no, __func__, 51088c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index); 51098c2ecf20Sopenharmony_ci 51108c2ecf20Sopenharmony_ci iscsi_unblock_session(ddb_entry->sess); 51118c2ecf20Sopenharmony_ci 51128c2ecf20Sopenharmony_ci /* Start scan target */ 51138c2ecf20Sopenharmony_ci if (test_bit(AF_ONLINE, &ha->flags)) { 51148c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" 51158c2ecf20Sopenharmony_ci " start scan\n", ha->host_no, __func__, 51168c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index); 51178c2ecf20Sopenharmony_ci scsi_queue_work(ha->host, &ddb_entry->sess->scan_work); 51188c2ecf20Sopenharmony_ci } 51198c2ecf20Sopenharmony_ci return QLA_SUCCESS; 51208c2ecf20Sopenharmony_ci} 51218c2ecf20Sopenharmony_ci 51228c2ecf20Sopenharmony_ciint qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session) 51238c2ecf20Sopenharmony_ci{ 51248c2ecf20Sopenharmony_ci struct iscsi_session *sess; 51258c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 51268c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 51278c2ecf20Sopenharmony_ci int status = QLA_SUCCESS; 51288c2ecf20Sopenharmony_ci 51298c2ecf20Sopenharmony_ci sess = cls_session->dd_data; 51308c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 51318c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 51328c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" 51338c2ecf20Sopenharmony_ci " unblock user space session\n", ha->host_no, __func__, 51348c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index); 51358c2ecf20Sopenharmony_ci 51368c2ecf20Sopenharmony_ci if (!iscsi_is_session_online(cls_session)) { 51378c2ecf20Sopenharmony_ci iscsi_conn_start(ddb_entry->conn); 51388c2ecf20Sopenharmony_ci iscsi_conn_login_event(ddb_entry->conn, 51398c2ecf20Sopenharmony_ci ISCSI_CONN_STATE_LOGGED_IN); 51408c2ecf20Sopenharmony_ci } else { 51418c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 51428c2ecf20Sopenharmony_ci "scsi%ld: %s: ddb[%d] session [%d] already logged in\n", 51438c2ecf20Sopenharmony_ci ha->host_no, __func__, ddb_entry->fw_ddb_index, 51448c2ecf20Sopenharmony_ci cls_session->sid); 51458c2ecf20Sopenharmony_ci status = QLA_ERROR; 51468c2ecf20Sopenharmony_ci } 51478c2ecf20Sopenharmony_ci 51488c2ecf20Sopenharmony_ci return status; 51498c2ecf20Sopenharmony_ci} 51508c2ecf20Sopenharmony_ci 51518c2ecf20Sopenharmony_cistatic void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha) 51528c2ecf20Sopenharmony_ci{ 51538c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices); 51548c2ecf20Sopenharmony_ci} 51558c2ecf20Sopenharmony_ci 51568c2ecf20Sopenharmony_cistatic void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) 51578c2ecf20Sopenharmony_ci{ 51588c2ecf20Sopenharmony_ci uint16_t relogin_timer; 51598c2ecf20Sopenharmony_ci struct iscsi_session *sess; 51608c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 51618c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 51628c2ecf20Sopenharmony_ci 51638c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 51648c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 51658c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 51668c2ecf20Sopenharmony_ci 51678c2ecf20Sopenharmony_ci relogin_timer = max(ddb_entry->default_relogin_timeout, 51688c2ecf20Sopenharmony_ci (uint16_t)RELOGIN_TOV); 51698c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->relogin_timer, relogin_timer); 51708c2ecf20Sopenharmony_ci 51718c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 51728c2ecf20Sopenharmony_ci "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no, 51738c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index, relogin_timer)); 51748c2ecf20Sopenharmony_ci 51758c2ecf20Sopenharmony_ci qla4xxx_login_flash_ddb(cls_sess); 51768c2ecf20Sopenharmony_ci} 51778c2ecf20Sopenharmony_ci 51788c2ecf20Sopenharmony_cistatic void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess) 51798c2ecf20Sopenharmony_ci{ 51808c2ecf20Sopenharmony_ci struct iscsi_session *sess; 51818c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 51828c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 51838c2ecf20Sopenharmony_ci 51848c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 51858c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 51868c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 51878c2ecf20Sopenharmony_ci 51888c2ecf20Sopenharmony_ci if (!(ddb_entry->ddb_type == FLASH_DDB)) 51898c2ecf20Sopenharmony_ci return; 51908c2ecf20Sopenharmony_ci 51918c2ecf20Sopenharmony_ci if (test_bit(DF_DISABLE_RELOGIN, &ddb_entry->flags)) 51928c2ecf20Sopenharmony_ci return; 51938c2ecf20Sopenharmony_ci 51948c2ecf20Sopenharmony_ci if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) && 51958c2ecf20Sopenharmony_ci !iscsi_is_session_online(cls_sess)) { 51968c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 51978c2ecf20Sopenharmony_ci "relogin issued\n")); 51988c2ecf20Sopenharmony_ci qla4xxx_relogin_flash_ddb(cls_sess); 51998c2ecf20Sopenharmony_ci } 52008c2ecf20Sopenharmony_ci} 52018c2ecf20Sopenharmony_ci 52028c2ecf20Sopenharmony_civoid qla4xxx_wake_dpc(struct scsi_qla_host *ha) 52038c2ecf20Sopenharmony_ci{ 52048c2ecf20Sopenharmony_ci if (ha->dpc_thread) 52058c2ecf20Sopenharmony_ci queue_work(ha->dpc_thread, &ha->dpc_work); 52068c2ecf20Sopenharmony_ci} 52078c2ecf20Sopenharmony_ci 52088c2ecf20Sopenharmony_cistatic struct qla4_work_evt * 52098c2ecf20Sopenharmony_ciqla4xxx_alloc_work(struct scsi_qla_host *ha, uint32_t data_size, 52108c2ecf20Sopenharmony_ci enum qla4_work_type type) 52118c2ecf20Sopenharmony_ci{ 52128c2ecf20Sopenharmony_ci struct qla4_work_evt *e; 52138c2ecf20Sopenharmony_ci uint32_t size = sizeof(struct qla4_work_evt) + data_size; 52148c2ecf20Sopenharmony_ci 52158c2ecf20Sopenharmony_ci e = kzalloc(size, GFP_ATOMIC); 52168c2ecf20Sopenharmony_ci if (!e) 52178c2ecf20Sopenharmony_ci return NULL; 52188c2ecf20Sopenharmony_ci 52198c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&e->list); 52208c2ecf20Sopenharmony_ci e->type = type; 52218c2ecf20Sopenharmony_ci return e; 52228c2ecf20Sopenharmony_ci} 52238c2ecf20Sopenharmony_ci 52248c2ecf20Sopenharmony_cistatic void qla4xxx_post_work(struct scsi_qla_host *ha, 52258c2ecf20Sopenharmony_ci struct qla4_work_evt *e) 52268c2ecf20Sopenharmony_ci{ 52278c2ecf20Sopenharmony_ci unsigned long flags; 52288c2ecf20Sopenharmony_ci 52298c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->work_lock, flags); 52308c2ecf20Sopenharmony_ci list_add_tail(&e->list, &ha->work_list); 52318c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->work_lock, flags); 52328c2ecf20Sopenharmony_ci qla4xxx_wake_dpc(ha); 52338c2ecf20Sopenharmony_ci} 52348c2ecf20Sopenharmony_ci 52358c2ecf20Sopenharmony_ciint qla4xxx_post_aen_work(struct scsi_qla_host *ha, 52368c2ecf20Sopenharmony_ci enum iscsi_host_event_code aen_code, 52378c2ecf20Sopenharmony_ci uint32_t data_size, uint8_t *data) 52388c2ecf20Sopenharmony_ci{ 52398c2ecf20Sopenharmony_ci struct qla4_work_evt *e; 52408c2ecf20Sopenharmony_ci 52418c2ecf20Sopenharmony_ci e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_AEN); 52428c2ecf20Sopenharmony_ci if (!e) 52438c2ecf20Sopenharmony_ci return QLA_ERROR; 52448c2ecf20Sopenharmony_ci 52458c2ecf20Sopenharmony_ci e->u.aen.code = aen_code; 52468c2ecf20Sopenharmony_ci e->u.aen.data_size = data_size; 52478c2ecf20Sopenharmony_ci memcpy(e->u.aen.data, data, data_size); 52488c2ecf20Sopenharmony_ci 52498c2ecf20Sopenharmony_ci qla4xxx_post_work(ha, e); 52508c2ecf20Sopenharmony_ci 52518c2ecf20Sopenharmony_ci return QLA_SUCCESS; 52528c2ecf20Sopenharmony_ci} 52538c2ecf20Sopenharmony_ci 52548c2ecf20Sopenharmony_ciint qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha, 52558c2ecf20Sopenharmony_ci uint32_t status, uint32_t pid, 52568c2ecf20Sopenharmony_ci uint32_t data_size, uint8_t *data) 52578c2ecf20Sopenharmony_ci{ 52588c2ecf20Sopenharmony_ci struct qla4_work_evt *e; 52598c2ecf20Sopenharmony_ci 52608c2ecf20Sopenharmony_ci e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_PING_STATUS); 52618c2ecf20Sopenharmony_ci if (!e) 52628c2ecf20Sopenharmony_ci return QLA_ERROR; 52638c2ecf20Sopenharmony_ci 52648c2ecf20Sopenharmony_ci e->u.ping.status = status; 52658c2ecf20Sopenharmony_ci e->u.ping.pid = pid; 52668c2ecf20Sopenharmony_ci e->u.ping.data_size = data_size; 52678c2ecf20Sopenharmony_ci memcpy(e->u.ping.data, data, data_size); 52688c2ecf20Sopenharmony_ci 52698c2ecf20Sopenharmony_ci qla4xxx_post_work(ha, e); 52708c2ecf20Sopenharmony_ci 52718c2ecf20Sopenharmony_ci return QLA_SUCCESS; 52728c2ecf20Sopenharmony_ci} 52738c2ecf20Sopenharmony_ci 52748c2ecf20Sopenharmony_cistatic void qla4xxx_do_work(struct scsi_qla_host *ha) 52758c2ecf20Sopenharmony_ci{ 52768c2ecf20Sopenharmony_ci struct qla4_work_evt *e, *tmp; 52778c2ecf20Sopenharmony_ci unsigned long flags; 52788c2ecf20Sopenharmony_ci LIST_HEAD(work); 52798c2ecf20Sopenharmony_ci 52808c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->work_lock, flags); 52818c2ecf20Sopenharmony_ci list_splice_init(&ha->work_list, &work); 52828c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->work_lock, flags); 52838c2ecf20Sopenharmony_ci 52848c2ecf20Sopenharmony_ci list_for_each_entry_safe(e, tmp, &work, list) { 52858c2ecf20Sopenharmony_ci list_del_init(&e->list); 52868c2ecf20Sopenharmony_ci 52878c2ecf20Sopenharmony_ci switch (e->type) { 52888c2ecf20Sopenharmony_ci case QLA4_EVENT_AEN: 52898c2ecf20Sopenharmony_ci iscsi_post_host_event(ha->host_no, 52908c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 52918c2ecf20Sopenharmony_ci e->u.aen.code, 52928c2ecf20Sopenharmony_ci e->u.aen.data_size, 52938c2ecf20Sopenharmony_ci e->u.aen.data); 52948c2ecf20Sopenharmony_ci break; 52958c2ecf20Sopenharmony_ci case QLA4_EVENT_PING_STATUS: 52968c2ecf20Sopenharmony_ci iscsi_ping_comp_event(ha->host_no, 52978c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 52988c2ecf20Sopenharmony_ci e->u.ping.status, 52998c2ecf20Sopenharmony_ci e->u.ping.pid, 53008c2ecf20Sopenharmony_ci e->u.ping.data_size, 53018c2ecf20Sopenharmony_ci e->u.ping.data); 53028c2ecf20Sopenharmony_ci break; 53038c2ecf20Sopenharmony_ci default: 53048c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "event type: 0x%x not " 53058c2ecf20Sopenharmony_ci "supported", e->type); 53068c2ecf20Sopenharmony_ci } 53078c2ecf20Sopenharmony_ci kfree(e); 53088c2ecf20Sopenharmony_ci } 53098c2ecf20Sopenharmony_ci} 53108c2ecf20Sopenharmony_ci 53118c2ecf20Sopenharmony_ci/** 53128c2ecf20Sopenharmony_ci * qla4xxx_do_dpc - dpc routine 53138c2ecf20Sopenharmony_ci * @work: Context to obtain pointer to host adapter structure. 53148c2ecf20Sopenharmony_ci * 53158c2ecf20Sopenharmony_ci * This routine is a task that is schedule by the interrupt handler 53168c2ecf20Sopenharmony_ci * to perform the background processing for interrupts. We put it 53178c2ecf20Sopenharmony_ci * on a task queue that is consumed whenever the scheduler runs; that's 53188c2ecf20Sopenharmony_ci * so you can do anything (i.e. put the process to sleep etc). In fact, 53198c2ecf20Sopenharmony_ci * the mid-level tries to sleep when it reaches the driver threshold 53208c2ecf20Sopenharmony_ci * "host->can_queue". This can cause a panic if we were in our interrupt code. 53218c2ecf20Sopenharmony_ci **/ 53228c2ecf20Sopenharmony_cistatic void qla4xxx_do_dpc(struct work_struct *work) 53238c2ecf20Sopenharmony_ci{ 53248c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = 53258c2ecf20Sopenharmony_ci container_of(work, struct scsi_qla_host, dpc_work); 53268c2ecf20Sopenharmony_ci int status = QLA_ERROR; 53278c2ecf20Sopenharmony_ci 53288c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 53298c2ecf20Sopenharmony_ci "scsi%ld: %s: DPC handler waking up. flags = 0x%08lx, dpc_flags = 0x%08lx\n", 53308c2ecf20Sopenharmony_ci ha->host_no, __func__, ha->flags, ha->dpc_flags)); 53318c2ecf20Sopenharmony_ci 53328c2ecf20Sopenharmony_ci /* Initialization not yet finished. Don't do anything yet. */ 53338c2ecf20Sopenharmony_ci if (!test_bit(AF_INIT_DONE, &ha->flags)) 53348c2ecf20Sopenharmony_ci return; 53358c2ecf20Sopenharmony_ci 53368c2ecf20Sopenharmony_ci if (test_bit(AF_EEH_BUSY, &ha->flags)) { 53378c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", 53388c2ecf20Sopenharmony_ci ha->host_no, __func__, ha->flags)); 53398c2ecf20Sopenharmony_ci return; 53408c2ecf20Sopenharmony_ci } 53418c2ecf20Sopenharmony_ci 53428c2ecf20Sopenharmony_ci /* post events to application */ 53438c2ecf20Sopenharmony_ci qla4xxx_do_work(ha); 53448c2ecf20Sopenharmony_ci 53458c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 53468c2ecf20Sopenharmony_ci if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { 53478c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 53488c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n", 53498c2ecf20Sopenharmony_ci __func__); 53508c2ecf20Sopenharmony_ci /* disable pause frame for ISP83xx */ 53518c2ecf20Sopenharmony_ci qla4_83xx_disable_pause(ha); 53528c2ecf20Sopenharmony_ci } 53538c2ecf20Sopenharmony_ci 53548c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 53558c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 53568c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 53578c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 53588c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HW State: FAILED\n"); 53598c2ecf20Sopenharmony_ci qla4_8xxx_device_state_handler(ha); 53608c2ecf20Sopenharmony_ci } 53618c2ecf20Sopenharmony_ci 53628c2ecf20Sopenharmony_ci if (test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags)) { 53638c2ecf20Sopenharmony_ci if (is_qla8042(ha)) { 53648c2ecf20Sopenharmony_ci if (ha->idc_info.info2 & 53658c2ecf20Sopenharmony_ci ENABLE_INTERNAL_LOOPBACK) { 53668c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Disabling ACB\n", 53678c2ecf20Sopenharmony_ci __func__); 53688c2ecf20Sopenharmony_ci status = qla4_84xx_config_acb(ha, 53698c2ecf20Sopenharmony_ci ACB_CONFIG_DISABLE); 53708c2ecf20Sopenharmony_ci if (status != QLA_SUCCESS) { 53718c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: ACB config failed\n", 53728c2ecf20Sopenharmony_ci __func__); 53738c2ecf20Sopenharmony_ci } 53748c2ecf20Sopenharmony_ci } 53758c2ecf20Sopenharmony_ci } 53768c2ecf20Sopenharmony_ci qla4_83xx_post_idc_ack(ha); 53778c2ecf20Sopenharmony_ci clear_bit(DPC_POST_IDC_ACK, &ha->dpc_flags); 53788c2ecf20Sopenharmony_ci } 53798c2ecf20Sopenharmony_ci 53808c2ecf20Sopenharmony_ci if (is_qla8042(ha) && 53818c2ecf20Sopenharmony_ci test_bit(DPC_RESTORE_ACB, &ha->dpc_flags)) { 53828c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Restoring ACB\n", 53838c2ecf20Sopenharmony_ci __func__); 53848c2ecf20Sopenharmony_ci if (qla4_84xx_config_acb(ha, ACB_CONFIG_SET) != 53858c2ecf20Sopenharmony_ci QLA_SUCCESS) { 53868c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: ACB config failed ", 53878c2ecf20Sopenharmony_ci __func__); 53888c2ecf20Sopenharmony_ci } 53898c2ecf20Sopenharmony_ci clear_bit(DPC_RESTORE_ACB, &ha->dpc_flags); 53908c2ecf20Sopenharmony_ci } 53918c2ecf20Sopenharmony_ci 53928c2ecf20Sopenharmony_ci if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { 53938c2ecf20Sopenharmony_ci qla4_8xxx_need_qsnt_handler(ha); 53948c2ecf20Sopenharmony_ci } 53958c2ecf20Sopenharmony_ci } 53968c2ecf20Sopenharmony_ci 53978c2ecf20Sopenharmony_ci if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) && 53988c2ecf20Sopenharmony_ci (test_bit(DPC_RESET_HA, &ha->dpc_flags) || 53998c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || 54008c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) { 54018c2ecf20Sopenharmony_ci if ((is_qla8022(ha) && ql4xdontresethba) || 54028c2ecf20Sopenharmony_ci ((is_qla8032(ha) || is_qla8042(ha)) && 54038c2ecf20Sopenharmony_ci qla4_83xx_idc_dontreset(ha))) { 54048c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", 54058c2ecf20Sopenharmony_ci ha->host_no, __func__)); 54068c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA, &ha->dpc_flags); 54078c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); 54088c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); 54098c2ecf20Sopenharmony_ci goto dpc_post_reset_ha; 54108c2ecf20Sopenharmony_ci } 54118c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) || 54128c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA, &ha->dpc_flags)) 54138c2ecf20Sopenharmony_ci qla4xxx_recover_adapter(ha); 54148c2ecf20Sopenharmony_ci 54158c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { 54168c2ecf20Sopenharmony_ci uint8_t wait_time = RESET_INTR_TOV; 54178c2ecf20Sopenharmony_ci 54188c2ecf20Sopenharmony_ci while ((readw(&ha->reg->ctrl_status) & 54198c2ecf20Sopenharmony_ci (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) { 54208c2ecf20Sopenharmony_ci if (--wait_time == 0) 54218c2ecf20Sopenharmony_ci break; 54228c2ecf20Sopenharmony_ci msleep(1000); 54238c2ecf20Sopenharmony_ci } 54248c2ecf20Sopenharmony_ci if (wait_time == 0) 54258c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: SR|FSR " 54268c2ecf20Sopenharmony_ci "bit not cleared-- resetting\n", 54278c2ecf20Sopenharmony_ci ha->host_no, __func__)); 54288c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_RESET << 16); 54298c2ecf20Sopenharmony_ci if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) { 54308c2ecf20Sopenharmony_ci qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); 54318c2ecf20Sopenharmony_ci status = qla4xxx_recover_adapter(ha); 54328c2ecf20Sopenharmony_ci } 54338c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags); 54348c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) 54358c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 54368c2ecf20Sopenharmony_ci } 54378c2ecf20Sopenharmony_ci } 54388c2ecf20Sopenharmony_ci 54398c2ecf20Sopenharmony_cidpc_post_reset_ha: 54408c2ecf20Sopenharmony_ci /* ---- process AEN? --- */ 54418c2ecf20Sopenharmony_ci if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) 54428c2ecf20Sopenharmony_ci qla4xxx_process_aen(ha, PROCESS_ALL_AENS); 54438c2ecf20Sopenharmony_ci 54448c2ecf20Sopenharmony_ci /* ---- Get DHCP IP Address? --- */ 54458c2ecf20Sopenharmony_ci if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) 54468c2ecf20Sopenharmony_ci qla4xxx_get_dhcp_ip_address(ha); 54478c2ecf20Sopenharmony_ci 54488c2ecf20Sopenharmony_ci /* ---- relogin device? --- */ 54498c2ecf20Sopenharmony_ci if (adapter_up(ha) && 54508c2ecf20Sopenharmony_ci test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { 54518c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin); 54528c2ecf20Sopenharmony_ci } 54538c2ecf20Sopenharmony_ci 54548c2ecf20Sopenharmony_ci /* ---- link change? --- */ 54558c2ecf20Sopenharmony_ci if (!test_bit(AF_LOOPBACK, &ha->flags) && 54568c2ecf20Sopenharmony_ci test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) { 54578c2ecf20Sopenharmony_ci if (!test_bit(AF_LINK_UP, &ha->flags)) { 54588c2ecf20Sopenharmony_ci /* ---- link down? --- */ 54598c2ecf20Sopenharmony_ci qla4xxx_mark_all_devices_missing(ha); 54608c2ecf20Sopenharmony_ci } else { 54618c2ecf20Sopenharmony_ci /* ---- link up? --- * 54628c2ecf20Sopenharmony_ci * F/W will auto login to all devices ONLY ONCE after 54638c2ecf20Sopenharmony_ci * link up during driver initialization and runtime 54648c2ecf20Sopenharmony_ci * fatal error recovery. Therefore, the driver must 54658c2ecf20Sopenharmony_ci * manually relogin to devices when recovering from 54668c2ecf20Sopenharmony_ci * connection failures, logouts, expired KATO, etc. */ 54678c2ecf20Sopenharmony_ci if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) { 54688c2ecf20Sopenharmony_ci qla4xxx_build_ddb_list(ha, ha->is_reset); 54698c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, 54708c2ecf20Sopenharmony_ci qla4xxx_login_flash_ddb); 54718c2ecf20Sopenharmony_ci } else 54728c2ecf20Sopenharmony_ci qla4xxx_relogin_all_devices(ha); 54738c2ecf20Sopenharmony_ci } 54748c2ecf20Sopenharmony_ci } 54758c2ecf20Sopenharmony_ci if (test_and_clear_bit(DPC_SYSFS_DDB_EXPORT, &ha->dpc_flags)) { 54768c2ecf20Sopenharmony_ci if (qla4xxx_sysfs_ddb_export(ha)) 54778c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Error exporting ddb to sysfs\n", 54788c2ecf20Sopenharmony_ci __func__); 54798c2ecf20Sopenharmony_ci } 54808c2ecf20Sopenharmony_ci} 54818c2ecf20Sopenharmony_ci 54828c2ecf20Sopenharmony_ci/** 54838c2ecf20Sopenharmony_ci * qla4xxx_free_adapter - release the adapter 54848c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 54858c2ecf20Sopenharmony_ci **/ 54868c2ecf20Sopenharmony_cistatic void qla4xxx_free_adapter(struct scsi_qla_host *ha) 54878c2ecf20Sopenharmony_ci{ 54888c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); 54898c2ecf20Sopenharmony_ci 54908c2ecf20Sopenharmony_ci /* Turn-off interrupts on the card. */ 54918c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 54928c2ecf20Sopenharmony_ci 54938c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 54948c2ecf20Sopenharmony_ci writel(set_rmask(CSR_SCSI_PROCESSOR_INTR), 54958c2ecf20Sopenharmony_ci &ha->reg->ctrl_status); 54968c2ecf20Sopenharmony_ci readl(&ha->reg->ctrl_status); 54978c2ecf20Sopenharmony_ci } else if (is_qla8022(ha)) { 54988c2ecf20Sopenharmony_ci writel(0, &ha->qla4_82xx_reg->host_int); 54998c2ecf20Sopenharmony_ci readl(&ha->qla4_82xx_reg->host_int); 55008c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 55018c2ecf20Sopenharmony_ci writel(0, &ha->qla4_83xx_reg->risc_intr); 55028c2ecf20Sopenharmony_ci readl(&ha->qla4_83xx_reg->risc_intr); 55038c2ecf20Sopenharmony_ci } 55048c2ecf20Sopenharmony_ci 55058c2ecf20Sopenharmony_ci /* Remove timer thread, if present */ 55068c2ecf20Sopenharmony_ci if (ha->timer_active) 55078c2ecf20Sopenharmony_ci qla4xxx_stop_timer(ha); 55088c2ecf20Sopenharmony_ci 55098c2ecf20Sopenharmony_ci /* Kill the kernel thread for this host */ 55108c2ecf20Sopenharmony_ci if (ha->dpc_thread) 55118c2ecf20Sopenharmony_ci destroy_workqueue(ha->dpc_thread); 55128c2ecf20Sopenharmony_ci 55138c2ecf20Sopenharmony_ci /* Kill the kernel thread for this host */ 55148c2ecf20Sopenharmony_ci if (ha->task_wq) 55158c2ecf20Sopenharmony_ci destroy_workqueue(ha->task_wq); 55168c2ecf20Sopenharmony_ci 55178c2ecf20Sopenharmony_ci /* Put firmware in known state */ 55188c2ecf20Sopenharmony_ci ha->isp_ops->reset_firmware(ha); 55198c2ecf20Sopenharmony_ci 55208c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 55218c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 55228c2ecf20Sopenharmony_ci qla4_8xxx_clear_drv_active(ha); 55238c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 55248c2ecf20Sopenharmony_ci } 55258c2ecf20Sopenharmony_ci 55268c2ecf20Sopenharmony_ci /* Detach interrupts */ 55278c2ecf20Sopenharmony_ci qla4xxx_free_irqs(ha); 55288c2ecf20Sopenharmony_ci 55298c2ecf20Sopenharmony_ci /* free extra memory */ 55308c2ecf20Sopenharmony_ci qla4xxx_mem_free(ha); 55318c2ecf20Sopenharmony_ci} 55328c2ecf20Sopenharmony_ci 55338c2ecf20Sopenharmony_ciint qla4_8xxx_iospace_config(struct scsi_qla_host *ha) 55348c2ecf20Sopenharmony_ci{ 55358c2ecf20Sopenharmony_ci int status = 0; 55368c2ecf20Sopenharmony_ci unsigned long mem_base, mem_len; 55378c2ecf20Sopenharmony_ci struct pci_dev *pdev = ha->pdev; 55388c2ecf20Sopenharmony_ci 55398c2ecf20Sopenharmony_ci status = pci_request_regions(pdev, DRIVER_NAME); 55408c2ecf20Sopenharmony_ci if (status) { 55418c2ecf20Sopenharmony_ci printk(KERN_WARNING 55428c2ecf20Sopenharmony_ci "scsi(%ld) Failed to reserve PIO regions (%s) " 55438c2ecf20Sopenharmony_ci "status=%d\n", ha->host_no, pci_name(pdev), status); 55448c2ecf20Sopenharmony_ci goto iospace_error_exit; 55458c2ecf20Sopenharmony_ci } 55468c2ecf20Sopenharmony_ci 55478c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n", 55488c2ecf20Sopenharmony_ci __func__, pdev->revision)); 55498c2ecf20Sopenharmony_ci ha->revision_id = pdev->revision; 55508c2ecf20Sopenharmony_ci 55518c2ecf20Sopenharmony_ci /* remap phys address */ 55528c2ecf20Sopenharmony_ci mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ 55538c2ecf20Sopenharmony_ci mem_len = pci_resource_len(pdev, 0); 55548c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n", 55558c2ecf20Sopenharmony_ci __func__, mem_base, mem_len)); 55568c2ecf20Sopenharmony_ci 55578c2ecf20Sopenharmony_ci /* mapping of pcibase pointer */ 55588c2ecf20Sopenharmony_ci ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len); 55598c2ecf20Sopenharmony_ci if (!ha->nx_pcibase) { 55608c2ecf20Sopenharmony_ci printk(KERN_ERR 55618c2ecf20Sopenharmony_ci "cannot remap MMIO (%s), aborting\n", pci_name(pdev)); 55628c2ecf20Sopenharmony_ci pci_release_regions(ha->pdev); 55638c2ecf20Sopenharmony_ci goto iospace_error_exit; 55648c2ecf20Sopenharmony_ci } 55658c2ecf20Sopenharmony_ci 55668c2ecf20Sopenharmony_ci /* Mapping of IO base pointer, door bell read and write pointer */ 55678c2ecf20Sopenharmony_ci 55688c2ecf20Sopenharmony_ci /* mapping of IO base pointer */ 55698c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 55708c2ecf20Sopenharmony_ci ha->qla4_82xx_reg = (struct device_reg_82xx __iomem *) 55718c2ecf20Sopenharmony_ci ((uint8_t *)ha->nx_pcibase + 0xbc000 + 55728c2ecf20Sopenharmony_ci (ha->pdev->devfn << 11)); 55738c2ecf20Sopenharmony_ci ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 : 55748c2ecf20Sopenharmony_ci QLA82XX_CAM_RAM_DB2); 55758c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 55768c2ecf20Sopenharmony_ci ha->qla4_83xx_reg = (struct device_reg_83xx __iomem *) 55778c2ecf20Sopenharmony_ci ((uint8_t *)ha->nx_pcibase); 55788c2ecf20Sopenharmony_ci } 55798c2ecf20Sopenharmony_ci 55808c2ecf20Sopenharmony_ci return 0; 55818c2ecf20Sopenharmony_ciiospace_error_exit: 55828c2ecf20Sopenharmony_ci return -ENOMEM; 55838c2ecf20Sopenharmony_ci} 55848c2ecf20Sopenharmony_ci 55858c2ecf20Sopenharmony_ci/*** 55868c2ecf20Sopenharmony_ci * qla4xxx_iospace_config - maps registers 55878c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 55888c2ecf20Sopenharmony_ci * 55898c2ecf20Sopenharmony_ci * This routines maps HBA's registers from the pci address space 55908c2ecf20Sopenharmony_ci * into the kernel virtual address space for memory mapped i/o. 55918c2ecf20Sopenharmony_ci **/ 55928c2ecf20Sopenharmony_ciint qla4xxx_iospace_config(struct scsi_qla_host *ha) 55938c2ecf20Sopenharmony_ci{ 55948c2ecf20Sopenharmony_ci unsigned long pio, pio_len, pio_flags; 55958c2ecf20Sopenharmony_ci unsigned long mmio, mmio_len, mmio_flags; 55968c2ecf20Sopenharmony_ci 55978c2ecf20Sopenharmony_ci pio = pci_resource_start(ha->pdev, 0); 55988c2ecf20Sopenharmony_ci pio_len = pci_resource_len(ha->pdev, 0); 55998c2ecf20Sopenharmony_ci pio_flags = pci_resource_flags(ha->pdev, 0); 56008c2ecf20Sopenharmony_ci if (pio_flags & IORESOURCE_IO) { 56018c2ecf20Sopenharmony_ci if (pio_len < MIN_IOBASE_LEN) { 56028c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 56038c2ecf20Sopenharmony_ci "Invalid PCI I/O region size\n"); 56048c2ecf20Sopenharmony_ci pio = 0; 56058c2ecf20Sopenharmony_ci } 56068c2ecf20Sopenharmony_ci } else { 56078c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n"); 56088c2ecf20Sopenharmony_ci pio = 0; 56098c2ecf20Sopenharmony_ci } 56108c2ecf20Sopenharmony_ci 56118c2ecf20Sopenharmony_ci /* Use MMIO operations for all accesses. */ 56128c2ecf20Sopenharmony_ci mmio = pci_resource_start(ha->pdev, 1); 56138c2ecf20Sopenharmony_ci mmio_len = pci_resource_len(ha->pdev, 1); 56148c2ecf20Sopenharmony_ci mmio_flags = pci_resource_flags(ha->pdev, 1); 56158c2ecf20Sopenharmony_ci 56168c2ecf20Sopenharmony_ci if (!(mmio_flags & IORESOURCE_MEM)) { 56178c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 56188c2ecf20Sopenharmony_ci "region #0 not an MMIO resource, aborting\n"); 56198c2ecf20Sopenharmony_ci 56208c2ecf20Sopenharmony_ci goto iospace_error_exit; 56218c2ecf20Sopenharmony_ci } 56228c2ecf20Sopenharmony_ci 56238c2ecf20Sopenharmony_ci if (mmio_len < MIN_IOBASE_LEN) { 56248c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 56258c2ecf20Sopenharmony_ci "Invalid PCI mem region size, aborting\n"); 56268c2ecf20Sopenharmony_ci goto iospace_error_exit; 56278c2ecf20Sopenharmony_ci } 56288c2ecf20Sopenharmony_ci 56298c2ecf20Sopenharmony_ci if (pci_request_regions(ha->pdev, DRIVER_NAME)) { 56308c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 56318c2ecf20Sopenharmony_ci "Failed to reserve PIO/MMIO regions\n"); 56328c2ecf20Sopenharmony_ci 56338c2ecf20Sopenharmony_ci goto iospace_error_exit; 56348c2ecf20Sopenharmony_ci } 56358c2ecf20Sopenharmony_ci 56368c2ecf20Sopenharmony_ci ha->pio_address = pio; 56378c2ecf20Sopenharmony_ci ha->pio_length = pio_len; 56388c2ecf20Sopenharmony_ci ha->reg = ioremap(mmio, MIN_IOBASE_LEN); 56398c2ecf20Sopenharmony_ci if (!ha->reg) { 56408c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 56418c2ecf20Sopenharmony_ci "cannot remap MMIO, aborting\n"); 56428c2ecf20Sopenharmony_ci 56438c2ecf20Sopenharmony_ci goto iospace_error_exit; 56448c2ecf20Sopenharmony_ci } 56458c2ecf20Sopenharmony_ci 56468c2ecf20Sopenharmony_ci return 0; 56478c2ecf20Sopenharmony_ci 56488c2ecf20Sopenharmony_ciiospace_error_exit: 56498c2ecf20Sopenharmony_ci return -ENOMEM; 56508c2ecf20Sopenharmony_ci} 56518c2ecf20Sopenharmony_ci 56528c2ecf20Sopenharmony_cistatic struct isp_operations qla4xxx_isp_ops = { 56538c2ecf20Sopenharmony_ci .iospace_config = qla4xxx_iospace_config, 56548c2ecf20Sopenharmony_ci .pci_config = qla4xxx_pci_config, 56558c2ecf20Sopenharmony_ci .disable_intrs = qla4xxx_disable_intrs, 56568c2ecf20Sopenharmony_ci .enable_intrs = qla4xxx_enable_intrs, 56578c2ecf20Sopenharmony_ci .start_firmware = qla4xxx_start_firmware, 56588c2ecf20Sopenharmony_ci .intr_handler = qla4xxx_intr_handler, 56598c2ecf20Sopenharmony_ci .interrupt_service_routine = qla4xxx_interrupt_service_routine, 56608c2ecf20Sopenharmony_ci .reset_chip = qla4xxx_soft_reset, 56618c2ecf20Sopenharmony_ci .reset_firmware = qla4xxx_hw_reset, 56628c2ecf20Sopenharmony_ci .queue_iocb = qla4xxx_queue_iocb, 56638c2ecf20Sopenharmony_ci .complete_iocb = qla4xxx_complete_iocb, 56648c2ecf20Sopenharmony_ci .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, 56658c2ecf20Sopenharmony_ci .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, 56668c2ecf20Sopenharmony_ci .get_sys_info = qla4xxx_get_sys_info, 56678c2ecf20Sopenharmony_ci .queue_mailbox_command = qla4xxx_queue_mbox_cmd, 56688c2ecf20Sopenharmony_ci .process_mailbox_interrupt = qla4xxx_process_mbox_intr, 56698c2ecf20Sopenharmony_ci}; 56708c2ecf20Sopenharmony_ci 56718c2ecf20Sopenharmony_cistatic struct isp_operations qla4_82xx_isp_ops = { 56728c2ecf20Sopenharmony_ci .iospace_config = qla4_8xxx_iospace_config, 56738c2ecf20Sopenharmony_ci .pci_config = qla4_8xxx_pci_config, 56748c2ecf20Sopenharmony_ci .disable_intrs = qla4_82xx_disable_intrs, 56758c2ecf20Sopenharmony_ci .enable_intrs = qla4_82xx_enable_intrs, 56768c2ecf20Sopenharmony_ci .start_firmware = qla4_8xxx_load_risc, 56778c2ecf20Sopenharmony_ci .restart_firmware = qla4_82xx_try_start_fw, 56788c2ecf20Sopenharmony_ci .intr_handler = qla4_82xx_intr_handler, 56798c2ecf20Sopenharmony_ci .interrupt_service_routine = qla4_82xx_interrupt_service_routine, 56808c2ecf20Sopenharmony_ci .need_reset = qla4_8xxx_need_reset, 56818c2ecf20Sopenharmony_ci .reset_chip = qla4_82xx_isp_reset, 56828c2ecf20Sopenharmony_ci .reset_firmware = qla4_8xxx_stop_firmware, 56838c2ecf20Sopenharmony_ci .queue_iocb = qla4_82xx_queue_iocb, 56848c2ecf20Sopenharmony_ci .complete_iocb = qla4_82xx_complete_iocb, 56858c2ecf20Sopenharmony_ci .rd_shdw_req_q_out = qla4_82xx_rd_shdw_req_q_out, 56868c2ecf20Sopenharmony_ci .rd_shdw_rsp_q_in = qla4_82xx_rd_shdw_rsp_q_in, 56878c2ecf20Sopenharmony_ci .get_sys_info = qla4_8xxx_get_sys_info, 56888c2ecf20Sopenharmony_ci .rd_reg_direct = qla4_82xx_rd_32, 56898c2ecf20Sopenharmony_ci .wr_reg_direct = qla4_82xx_wr_32, 56908c2ecf20Sopenharmony_ci .rd_reg_indirect = qla4_82xx_md_rd_32, 56918c2ecf20Sopenharmony_ci .wr_reg_indirect = qla4_82xx_md_wr_32, 56928c2ecf20Sopenharmony_ci .idc_lock = qla4_82xx_idc_lock, 56938c2ecf20Sopenharmony_ci .idc_unlock = qla4_82xx_idc_unlock, 56948c2ecf20Sopenharmony_ci .rom_lock_recovery = qla4_82xx_rom_lock_recovery, 56958c2ecf20Sopenharmony_ci .queue_mailbox_command = qla4_82xx_queue_mbox_cmd, 56968c2ecf20Sopenharmony_ci .process_mailbox_interrupt = qla4_82xx_process_mbox_intr, 56978c2ecf20Sopenharmony_ci}; 56988c2ecf20Sopenharmony_ci 56998c2ecf20Sopenharmony_cistatic struct isp_operations qla4_83xx_isp_ops = { 57008c2ecf20Sopenharmony_ci .iospace_config = qla4_8xxx_iospace_config, 57018c2ecf20Sopenharmony_ci .pci_config = qla4_8xxx_pci_config, 57028c2ecf20Sopenharmony_ci .disable_intrs = qla4_83xx_disable_intrs, 57038c2ecf20Sopenharmony_ci .enable_intrs = qla4_83xx_enable_intrs, 57048c2ecf20Sopenharmony_ci .start_firmware = qla4_8xxx_load_risc, 57058c2ecf20Sopenharmony_ci .restart_firmware = qla4_83xx_start_firmware, 57068c2ecf20Sopenharmony_ci .intr_handler = qla4_83xx_intr_handler, 57078c2ecf20Sopenharmony_ci .interrupt_service_routine = qla4_83xx_interrupt_service_routine, 57088c2ecf20Sopenharmony_ci .need_reset = qla4_8xxx_need_reset, 57098c2ecf20Sopenharmony_ci .reset_chip = qla4_83xx_isp_reset, 57108c2ecf20Sopenharmony_ci .reset_firmware = qla4_8xxx_stop_firmware, 57118c2ecf20Sopenharmony_ci .queue_iocb = qla4_83xx_queue_iocb, 57128c2ecf20Sopenharmony_ci .complete_iocb = qla4_83xx_complete_iocb, 57138c2ecf20Sopenharmony_ci .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, 57148c2ecf20Sopenharmony_ci .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, 57158c2ecf20Sopenharmony_ci .get_sys_info = qla4_8xxx_get_sys_info, 57168c2ecf20Sopenharmony_ci .rd_reg_direct = qla4_83xx_rd_reg, 57178c2ecf20Sopenharmony_ci .wr_reg_direct = qla4_83xx_wr_reg, 57188c2ecf20Sopenharmony_ci .rd_reg_indirect = qla4_83xx_rd_reg_indirect, 57198c2ecf20Sopenharmony_ci .wr_reg_indirect = qla4_83xx_wr_reg_indirect, 57208c2ecf20Sopenharmony_ci .idc_lock = qla4_83xx_drv_lock, 57218c2ecf20Sopenharmony_ci .idc_unlock = qla4_83xx_drv_unlock, 57228c2ecf20Sopenharmony_ci .rom_lock_recovery = qla4_83xx_rom_lock_recovery, 57238c2ecf20Sopenharmony_ci .queue_mailbox_command = qla4_83xx_queue_mbox_cmd, 57248c2ecf20Sopenharmony_ci .process_mailbox_interrupt = qla4_83xx_process_mbox_intr, 57258c2ecf20Sopenharmony_ci}; 57268c2ecf20Sopenharmony_ci 57278c2ecf20Sopenharmony_ciuint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha) 57288c2ecf20Sopenharmony_ci{ 57298c2ecf20Sopenharmony_ci return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out); 57308c2ecf20Sopenharmony_ci} 57318c2ecf20Sopenharmony_ci 57328c2ecf20Sopenharmony_ciuint16_t qla4_82xx_rd_shdw_req_q_out(struct scsi_qla_host *ha) 57338c2ecf20Sopenharmony_ci{ 57348c2ecf20Sopenharmony_ci return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out)); 57358c2ecf20Sopenharmony_ci} 57368c2ecf20Sopenharmony_ci 57378c2ecf20Sopenharmony_ciuint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) 57388c2ecf20Sopenharmony_ci{ 57398c2ecf20Sopenharmony_ci return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); 57408c2ecf20Sopenharmony_ci} 57418c2ecf20Sopenharmony_ci 57428c2ecf20Sopenharmony_ciuint16_t qla4_82xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) 57438c2ecf20Sopenharmony_ci{ 57448c2ecf20Sopenharmony_ci return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in)); 57458c2ecf20Sopenharmony_ci} 57468c2ecf20Sopenharmony_ci 57478c2ecf20Sopenharmony_cistatic ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf) 57488c2ecf20Sopenharmony_ci{ 57498c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = data; 57508c2ecf20Sopenharmony_ci char *str = buf; 57518c2ecf20Sopenharmony_ci int rc; 57528c2ecf20Sopenharmony_ci 57538c2ecf20Sopenharmony_ci switch (type) { 57548c2ecf20Sopenharmony_ci case ISCSI_BOOT_ETH_FLAGS: 57558c2ecf20Sopenharmony_ci rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT); 57568c2ecf20Sopenharmony_ci break; 57578c2ecf20Sopenharmony_ci case ISCSI_BOOT_ETH_INDEX: 57588c2ecf20Sopenharmony_ci rc = sprintf(str, "0\n"); 57598c2ecf20Sopenharmony_ci break; 57608c2ecf20Sopenharmony_ci case ISCSI_BOOT_ETH_MAC: 57618c2ecf20Sopenharmony_ci rc = sysfs_format_mac(str, ha->my_mac, 57628c2ecf20Sopenharmony_ci MAC_ADDR_LEN); 57638c2ecf20Sopenharmony_ci break; 57648c2ecf20Sopenharmony_ci default: 57658c2ecf20Sopenharmony_ci rc = -ENOSYS; 57668c2ecf20Sopenharmony_ci break; 57678c2ecf20Sopenharmony_ci } 57688c2ecf20Sopenharmony_ci return rc; 57698c2ecf20Sopenharmony_ci} 57708c2ecf20Sopenharmony_ci 57718c2ecf20Sopenharmony_cistatic umode_t qla4xxx_eth_get_attr_visibility(void *data, int type) 57728c2ecf20Sopenharmony_ci{ 57738c2ecf20Sopenharmony_ci int rc; 57748c2ecf20Sopenharmony_ci 57758c2ecf20Sopenharmony_ci switch (type) { 57768c2ecf20Sopenharmony_ci case ISCSI_BOOT_ETH_FLAGS: 57778c2ecf20Sopenharmony_ci case ISCSI_BOOT_ETH_MAC: 57788c2ecf20Sopenharmony_ci case ISCSI_BOOT_ETH_INDEX: 57798c2ecf20Sopenharmony_ci rc = S_IRUGO; 57808c2ecf20Sopenharmony_ci break; 57818c2ecf20Sopenharmony_ci default: 57828c2ecf20Sopenharmony_ci rc = 0; 57838c2ecf20Sopenharmony_ci break; 57848c2ecf20Sopenharmony_ci } 57858c2ecf20Sopenharmony_ci return rc; 57868c2ecf20Sopenharmony_ci} 57878c2ecf20Sopenharmony_ci 57888c2ecf20Sopenharmony_cistatic ssize_t qla4xxx_show_boot_ini_info(void *data, int type, char *buf) 57898c2ecf20Sopenharmony_ci{ 57908c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = data; 57918c2ecf20Sopenharmony_ci char *str = buf; 57928c2ecf20Sopenharmony_ci int rc; 57938c2ecf20Sopenharmony_ci 57948c2ecf20Sopenharmony_ci switch (type) { 57958c2ecf20Sopenharmony_ci case ISCSI_BOOT_INI_INITIATOR_NAME: 57968c2ecf20Sopenharmony_ci rc = sprintf(str, "%s\n", ha->name_string); 57978c2ecf20Sopenharmony_ci break; 57988c2ecf20Sopenharmony_ci default: 57998c2ecf20Sopenharmony_ci rc = -ENOSYS; 58008c2ecf20Sopenharmony_ci break; 58018c2ecf20Sopenharmony_ci } 58028c2ecf20Sopenharmony_ci return rc; 58038c2ecf20Sopenharmony_ci} 58048c2ecf20Sopenharmony_ci 58058c2ecf20Sopenharmony_cistatic umode_t qla4xxx_ini_get_attr_visibility(void *data, int type) 58068c2ecf20Sopenharmony_ci{ 58078c2ecf20Sopenharmony_ci int rc; 58088c2ecf20Sopenharmony_ci 58098c2ecf20Sopenharmony_ci switch (type) { 58108c2ecf20Sopenharmony_ci case ISCSI_BOOT_INI_INITIATOR_NAME: 58118c2ecf20Sopenharmony_ci rc = S_IRUGO; 58128c2ecf20Sopenharmony_ci break; 58138c2ecf20Sopenharmony_ci default: 58148c2ecf20Sopenharmony_ci rc = 0; 58158c2ecf20Sopenharmony_ci break; 58168c2ecf20Sopenharmony_ci } 58178c2ecf20Sopenharmony_ci return rc; 58188c2ecf20Sopenharmony_ci} 58198c2ecf20Sopenharmony_ci 58208c2ecf20Sopenharmony_cistatic ssize_t 58218c2ecf20Sopenharmony_ciqla4xxx_show_boot_tgt_info(struct ql4_boot_session_info *boot_sess, int type, 58228c2ecf20Sopenharmony_ci char *buf) 58238c2ecf20Sopenharmony_ci{ 58248c2ecf20Sopenharmony_ci struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0]; 58258c2ecf20Sopenharmony_ci char *str = buf; 58268c2ecf20Sopenharmony_ci int rc; 58278c2ecf20Sopenharmony_ci 58288c2ecf20Sopenharmony_ci switch (type) { 58298c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_NAME: 58308c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", (char *)&boot_sess->target_name); 58318c2ecf20Sopenharmony_ci break; 58328c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_IP_ADDR: 58338c2ecf20Sopenharmony_ci if (boot_sess->conn_list[0].dest_ipaddr.ip_type == 0x1) 58348c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pI4\n", 58358c2ecf20Sopenharmony_ci &boot_conn->dest_ipaddr.ip_address); 58368c2ecf20Sopenharmony_ci else 58378c2ecf20Sopenharmony_ci rc = sprintf(str, "%pI6\n", 58388c2ecf20Sopenharmony_ci &boot_conn->dest_ipaddr.ip_address); 58398c2ecf20Sopenharmony_ci break; 58408c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_PORT: 58418c2ecf20Sopenharmony_ci rc = sprintf(str, "%d\n", boot_conn->dest_port); 58428c2ecf20Sopenharmony_ci break; 58438c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_CHAP_NAME: 58448c2ecf20Sopenharmony_ci rc = sprintf(str, "%.*s\n", 58458c2ecf20Sopenharmony_ci boot_conn->chap.target_chap_name_length, 58468c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.target_chap_name); 58478c2ecf20Sopenharmony_ci break; 58488c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_CHAP_SECRET: 58498c2ecf20Sopenharmony_ci rc = sprintf(str, "%.*s\n", 58508c2ecf20Sopenharmony_ci boot_conn->chap.target_secret_length, 58518c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.target_secret); 58528c2ecf20Sopenharmony_ci break; 58538c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_REV_CHAP_NAME: 58548c2ecf20Sopenharmony_ci rc = sprintf(str, "%.*s\n", 58558c2ecf20Sopenharmony_ci boot_conn->chap.intr_chap_name_length, 58568c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.intr_chap_name); 58578c2ecf20Sopenharmony_ci break; 58588c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_REV_CHAP_SECRET: 58598c2ecf20Sopenharmony_ci rc = sprintf(str, "%.*s\n", 58608c2ecf20Sopenharmony_ci boot_conn->chap.intr_secret_length, 58618c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.intr_secret); 58628c2ecf20Sopenharmony_ci break; 58638c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_FLAGS: 58648c2ecf20Sopenharmony_ci rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT); 58658c2ecf20Sopenharmony_ci break; 58668c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_NIC_ASSOC: 58678c2ecf20Sopenharmony_ci rc = sprintf(str, "0\n"); 58688c2ecf20Sopenharmony_ci break; 58698c2ecf20Sopenharmony_ci default: 58708c2ecf20Sopenharmony_ci rc = -ENOSYS; 58718c2ecf20Sopenharmony_ci break; 58728c2ecf20Sopenharmony_ci } 58738c2ecf20Sopenharmony_ci return rc; 58748c2ecf20Sopenharmony_ci} 58758c2ecf20Sopenharmony_ci 58768c2ecf20Sopenharmony_cistatic ssize_t qla4xxx_show_boot_tgt_pri_info(void *data, int type, char *buf) 58778c2ecf20Sopenharmony_ci{ 58788c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = data; 58798c2ecf20Sopenharmony_ci struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_pri_sess); 58808c2ecf20Sopenharmony_ci 58818c2ecf20Sopenharmony_ci return qla4xxx_show_boot_tgt_info(boot_sess, type, buf); 58828c2ecf20Sopenharmony_ci} 58838c2ecf20Sopenharmony_ci 58848c2ecf20Sopenharmony_cistatic ssize_t qla4xxx_show_boot_tgt_sec_info(void *data, int type, char *buf) 58858c2ecf20Sopenharmony_ci{ 58868c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = data; 58878c2ecf20Sopenharmony_ci struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_sec_sess); 58888c2ecf20Sopenharmony_ci 58898c2ecf20Sopenharmony_ci return qla4xxx_show_boot_tgt_info(boot_sess, type, buf); 58908c2ecf20Sopenharmony_ci} 58918c2ecf20Sopenharmony_ci 58928c2ecf20Sopenharmony_cistatic umode_t qla4xxx_tgt_get_attr_visibility(void *data, int type) 58938c2ecf20Sopenharmony_ci{ 58948c2ecf20Sopenharmony_ci int rc; 58958c2ecf20Sopenharmony_ci 58968c2ecf20Sopenharmony_ci switch (type) { 58978c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_NAME: 58988c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_IP_ADDR: 58998c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_PORT: 59008c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_CHAP_NAME: 59018c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_CHAP_SECRET: 59028c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_REV_CHAP_NAME: 59038c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_REV_CHAP_SECRET: 59048c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_NIC_ASSOC: 59058c2ecf20Sopenharmony_ci case ISCSI_BOOT_TGT_FLAGS: 59068c2ecf20Sopenharmony_ci rc = S_IRUGO; 59078c2ecf20Sopenharmony_ci break; 59088c2ecf20Sopenharmony_ci default: 59098c2ecf20Sopenharmony_ci rc = 0; 59108c2ecf20Sopenharmony_ci break; 59118c2ecf20Sopenharmony_ci } 59128c2ecf20Sopenharmony_ci return rc; 59138c2ecf20Sopenharmony_ci} 59148c2ecf20Sopenharmony_ci 59158c2ecf20Sopenharmony_cistatic void qla4xxx_boot_release(void *data) 59168c2ecf20Sopenharmony_ci{ 59178c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = data; 59188c2ecf20Sopenharmony_ci 59198c2ecf20Sopenharmony_ci scsi_host_put(ha->host); 59208c2ecf20Sopenharmony_ci} 59218c2ecf20Sopenharmony_ci 59228c2ecf20Sopenharmony_cistatic int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[]) 59238c2ecf20Sopenharmony_ci{ 59248c2ecf20Sopenharmony_ci dma_addr_t buf_dma; 59258c2ecf20Sopenharmony_ci uint32_t addr, pri_addr, sec_addr; 59268c2ecf20Sopenharmony_ci uint32_t offset; 59278c2ecf20Sopenharmony_ci uint16_t func_num; 59288c2ecf20Sopenharmony_ci uint8_t val; 59298c2ecf20Sopenharmony_ci uint8_t *buf = NULL; 59308c2ecf20Sopenharmony_ci size_t size = 13 * sizeof(uint8_t); 59318c2ecf20Sopenharmony_ci int ret = QLA_SUCCESS; 59328c2ecf20Sopenharmony_ci 59338c2ecf20Sopenharmony_ci func_num = PCI_FUNC(ha->pdev->devfn); 59348c2ecf20Sopenharmony_ci 59358c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n", 59368c2ecf20Sopenharmony_ci __func__, ha->pdev->device, func_num); 59378c2ecf20Sopenharmony_ci 59388c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 59398c2ecf20Sopenharmony_ci if (func_num == 1) { 59408c2ecf20Sopenharmony_ci addr = NVRAM_PORT0_BOOT_MODE; 59418c2ecf20Sopenharmony_ci pri_addr = NVRAM_PORT0_BOOT_PRI_TGT; 59428c2ecf20Sopenharmony_ci sec_addr = NVRAM_PORT0_BOOT_SEC_TGT; 59438c2ecf20Sopenharmony_ci } else if (func_num == 3) { 59448c2ecf20Sopenharmony_ci addr = NVRAM_PORT1_BOOT_MODE; 59458c2ecf20Sopenharmony_ci pri_addr = NVRAM_PORT1_BOOT_PRI_TGT; 59468c2ecf20Sopenharmony_ci sec_addr = NVRAM_PORT1_BOOT_SEC_TGT; 59478c2ecf20Sopenharmony_ci } else { 59488c2ecf20Sopenharmony_ci ret = QLA_ERROR; 59498c2ecf20Sopenharmony_ci goto exit_boot_info; 59508c2ecf20Sopenharmony_ci } 59518c2ecf20Sopenharmony_ci 59528c2ecf20Sopenharmony_ci /* Check Boot Mode */ 59538c2ecf20Sopenharmony_ci val = rd_nvram_byte(ha, addr); 59548c2ecf20Sopenharmony_ci if (!(val & 0x07)) { 59558c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Adapter boot " 59568c2ecf20Sopenharmony_ci "options : 0x%x\n", __func__, val)); 59578c2ecf20Sopenharmony_ci ret = QLA_ERROR; 59588c2ecf20Sopenharmony_ci goto exit_boot_info; 59598c2ecf20Sopenharmony_ci } 59608c2ecf20Sopenharmony_ci 59618c2ecf20Sopenharmony_ci /* get primary valid target index */ 59628c2ecf20Sopenharmony_ci val = rd_nvram_byte(ha, pri_addr); 59638c2ecf20Sopenharmony_ci if (val & BIT_7) 59648c2ecf20Sopenharmony_ci ddb_index[0] = (val & 0x7f); 59658c2ecf20Sopenharmony_ci 59668c2ecf20Sopenharmony_ci /* get secondary valid target index */ 59678c2ecf20Sopenharmony_ci val = rd_nvram_byte(ha, sec_addr); 59688c2ecf20Sopenharmony_ci if (val & BIT_7) 59698c2ecf20Sopenharmony_ci ddb_index[1] = (val & 0x7f); 59708c2ecf20Sopenharmony_ci goto exit_boot_info; 59718c2ecf20Sopenharmony_ci } else if (is_qla80XX(ha)) { 59728c2ecf20Sopenharmony_ci buf = dma_alloc_coherent(&ha->pdev->dev, size, 59738c2ecf20Sopenharmony_ci &buf_dma, GFP_KERNEL); 59748c2ecf20Sopenharmony_ci if (!buf) { 59758c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 59768c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 59778c2ecf20Sopenharmony_ci __func__)); 59788c2ecf20Sopenharmony_ci ret = QLA_ERROR; 59798c2ecf20Sopenharmony_ci goto exit_boot_info; 59808c2ecf20Sopenharmony_ci } 59818c2ecf20Sopenharmony_ci 59828c2ecf20Sopenharmony_ci if (ha->port_num == 0) 59838c2ecf20Sopenharmony_ci offset = BOOT_PARAM_OFFSET_PORT0; 59848c2ecf20Sopenharmony_ci else if (ha->port_num == 1) 59858c2ecf20Sopenharmony_ci offset = BOOT_PARAM_OFFSET_PORT1; 59868c2ecf20Sopenharmony_ci else { 59878c2ecf20Sopenharmony_ci ret = QLA_ERROR; 59888c2ecf20Sopenharmony_ci goto exit_boot_info_free; 59898c2ecf20Sopenharmony_ci } 59908c2ecf20Sopenharmony_ci addr = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_iscsi_param * 4) + 59918c2ecf20Sopenharmony_ci offset; 59928c2ecf20Sopenharmony_ci if (qla4xxx_get_flash(ha, buf_dma, addr, 59938c2ecf20Sopenharmony_ci 13 * sizeof(uint8_t)) != QLA_SUCCESS) { 59948c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash" 59958c2ecf20Sopenharmony_ci " failed\n", ha->host_no, __func__)); 59968c2ecf20Sopenharmony_ci ret = QLA_ERROR; 59978c2ecf20Sopenharmony_ci goto exit_boot_info_free; 59988c2ecf20Sopenharmony_ci } 59998c2ecf20Sopenharmony_ci /* Check Boot Mode */ 60008c2ecf20Sopenharmony_ci if (!(buf[1] & 0x07)) { 60018c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Firmware boot options" 60028c2ecf20Sopenharmony_ci " : 0x%x\n", buf[1])); 60038c2ecf20Sopenharmony_ci ret = QLA_ERROR; 60048c2ecf20Sopenharmony_ci goto exit_boot_info_free; 60058c2ecf20Sopenharmony_ci } 60068c2ecf20Sopenharmony_ci 60078c2ecf20Sopenharmony_ci /* get primary valid target index */ 60088c2ecf20Sopenharmony_ci if (buf[2] & BIT_7) 60098c2ecf20Sopenharmony_ci ddb_index[0] = buf[2] & 0x7f; 60108c2ecf20Sopenharmony_ci 60118c2ecf20Sopenharmony_ci /* get secondary valid target index */ 60128c2ecf20Sopenharmony_ci if (buf[11] & BIT_7) 60138c2ecf20Sopenharmony_ci ddb_index[1] = buf[11] & 0x7f; 60148c2ecf20Sopenharmony_ci } else { 60158c2ecf20Sopenharmony_ci ret = QLA_ERROR; 60168c2ecf20Sopenharmony_ci goto exit_boot_info; 60178c2ecf20Sopenharmony_ci } 60188c2ecf20Sopenharmony_ci 60198c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary target ID %d, Secondary" 60208c2ecf20Sopenharmony_ci " target ID %d\n", __func__, ddb_index[0], 60218c2ecf20Sopenharmony_ci ddb_index[1])); 60228c2ecf20Sopenharmony_ci 60238c2ecf20Sopenharmony_ciexit_boot_info_free: 60248c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma); 60258c2ecf20Sopenharmony_ciexit_boot_info: 60268c2ecf20Sopenharmony_ci ha->pri_ddb_idx = ddb_index[0]; 60278c2ecf20Sopenharmony_ci ha->sec_ddb_idx = ddb_index[1]; 60288c2ecf20Sopenharmony_ci return ret; 60298c2ecf20Sopenharmony_ci} 60308c2ecf20Sopenharmony_ci 60318c2ecf20Sopenharmony_ci/** 60328c2ecf20Sopenharmony_ci * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password 60338c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 60348c2ecf20Sopenharmony_ci * @username: CHAP username to be returned 60358c2ecf20Sopenharmony_ci * @password: CHAP password to be returned 60368c2ecf20Sopenharmony_ci * 60378c2ecf20Sopenharmony_ci * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP 60388c2ecf20Sopenharmony_ci * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/. 60398c2ecf20Sopenharmony_ci * So from the CHAP cache find the first BIDI CHAP entry and set it 60408c2ecf20Sopenharmony_ci * to the boot record in sysfs. 60418c2ecf20Sopenharmony_ci **/ 60428c2ecf20Sopenharmony_cistatic int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username, 60438c2ecf20Sopenharmony_ci char *password) 60448c2ecf20Sopenharmony_ci{ 60458c2ecf20Sopenharmony_ci int i, ret = -EINVAL; 60468c2ecf20Sopenharmony_ci int max_chap_entries = 0; 60478c2ecf20Sopenharmony_ci struct ql4_chap_table *chap_table; 60488c2ecf20Sopenharmony_ci 60498c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 60508c2ecf20Sopenharmony_ci max_chap_entries = (ha->hw.flt_chap_size / 2) / 60518c2ecf20Sopenharmony_ci sizeof(struct ql4_chap_table); 60528c2ecf20Sopenharmony_ci else 60538c2ecf20Sopenharmony_ci max_chap_entries = MAX_CHAP_ENTRIES_40XX; 60548c2ecf20Sopenharmony_ci 60558c2ecf20Sopenharmony_ci if (!ha->chap_list) { 60568c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); 60578c2ecf20Sopenharmony_ci return ret; 60588c2ecf20Sopenharmony_ci } 60598c2ecf20Sopenharmony_ci 60608c2ecf20Sopenharmony_ci mutex_lock(&ha->chap_sem); 60618c2ecf20Sopenharmony_ci for (i = 0; i < max_chap_entries; i++) { 60628c2ecf20Sopenharmony_ci chap_table = (struct ql4_chap_table *)ha->chap_list + i; 60638c2ecf20Sopenharmony_ci if (chap_table->cookie != 60648c2ecf20Sopenharmony_ci __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { 60658c2ecf20Sopenharmony_ci continue; 60668c2ecf20Sopenharmony_ci } 60678c2ecf20Sopenharmony_ci 60688c2ecf20Sopenharmony_ci if (chap_table->flags & BIT_7) /* local */ 60698c2ecf20Sopenharmony_ci continue; 60708c2ecf20Sopenharmony_ci 60718c2ecf20Sopenharmony_ci if (!(chap_table->flags & BIT_6)) /* Not BIDI */ 60728c2ecf20Sopenharmony_ci continue; 60738c2ecf20Sopenharmony_ci 60748c2ecf20Sopenharmony_ci strlcpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN); 60758c2ecf20Sopenharmony_ci strlcpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN); 60768c2ecf20Sopenharmony_ci ret = 0; 60778c2ecf20Sopenharmony_ci break; 60788c2ecf20Sopenharmony_ci } 60798c2ecf20Sopenharmony_ci mutex_unlock(&ha->chap_sem); 60808c2ecf20Sopenharmony_ci 60818c2ecf20Sopenharmony_ci return ret; 60828c2ecf20Sopenharmony_ci} 60838c2ecf20Sopenharmony_ci 60848c2ecf20Sopenharmony_ci 60858c2ecf20Sopenharmony_cistatic int qla4xxx_get_boot_target(struct scsi_qla_host *ha, 60868c2ecf20Sopenharmony_ci struct ql4_boot_session_info *boot_sess, 60878c2ecf20Sopenharmony_ci uint16_t ddb_index) 60888c2ecf20Sopenharmony_ci{ 60898c2ecf20Sopenharmony_ci struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0]; 60908c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 60918c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 60928c2ecf20Sopenharmony_ci uint16_t idx; 60938c2ecf20Sopenharmony_ci uint16_t options; 60948c2ecf20Sopenharmony_ci int ret = QLA_SUCCESS; 60958c2ecf20Sopenharmony_ci 60968c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 60978c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 60988c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 60998c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 61008c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer.\n", 61018c2ecf20Sopenharmony_ci __func__)); 61028c2ecf20Sopenharmony_ci ret = QLA_ERROR; 61038c2ecf20Sopenharmony_ci return ret; 61048c2ecf20Sopenharmony_ci } 61058c2ecf20Sopenharmony_ci 61068c2ecf20Sopenharmony_ci if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry, 61078c2ecf20Sopenharmony_ci fw_ddb_entry_dma, ddb_index)) { 61088c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: No Flash DDB found at " 61098c2ecf20Sopenharmony_ci "index [%d]\n", __func__, ddb_index)); 61108c2ecf20Sopenharmony_ci ret = QLA_ERROR; 61118c2ecf20Sopenharmony_ci goto exit_boot_target; 61128c2ecf20Sopenharmony_ci } 61138c2ecf20Sopenharmony_ci 61148c2ecf20Sopenharmony_ci /* Update target name and IP from DDB */ 61158c2ecf20Sopenharmony_ci memcpy(boot_sess->target_name, fw_ddb_entry->iscsi_name, 61168c2ecf20Sopenharmony_ci min(sizeof(boot_sess->target_name), 61178c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->iscsi_name))); 61188c2ecf20Sopenharmony_ci 61198c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 61208c2ecf20Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) { 61218c2ecf20Sopenharmony_ci memcpy(&boot_conn->dest_ipaddr.ip_address, 61228c2ecf20Sopenharmony_ci &fw_ddb_entry->ip_addr[0], IPv6_ADDR_LEN); 61238c2ecf20Sopenharmony_ci } else { 61248c2ecf20Sopenharmony_ci boot_conn->dest_ipaddr.ip_type = 0x1; 61258c2ecf20Sopenharmony_ci memcpy(&boot_conn->dest_ipaddr.ip_address, 61268c2ecf20Sopenharmony_ci &fw_ddb_entry->ip_addr[0], IP_ADDR_LEN); 61278c2ecf20Sopenharmony_ci } 61288c2ecf20Sopenharmony_ci 61298c2ecf20Sopenharmony_ci boot_conn->dest_port = le16_to_cpu(fw_ddb_entry->port); 61308c2ecf20Sopenharmony_ci 61318c2ecf20Sopenharmony_ci /* update chap information */ 61328c2ecf20Sopenharmony_ci idx = __le16_to_cpu(fw_ddb_entry->chap_tbl_idx); 61338c2ecf20Sopenharmony_ci 61348c2ecf20Sopenharmony_ci if (BIT_7 & le16_to_cpu(fw_ddb_entry->iscsi_options)) { 61358c2ecf20Sopenharmony_ci 61368c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Setting chap\n")); 61378c2ecf20Sopenharmony_ci 61388c2ecf20Sopenharmony_ci ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap. 61398c2ecf20Sopenharmony_ci target_chap_name, 61408c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.target_secret, 61418c2ecf20Sopenharmony_ci idx); 61428c2ecf20Sopenharmony_ci if (ret) { 61438c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Failed to set chap\n"); 61448c2ecf20Sopenharmony_ci ret = QLA_ERROR; 61458c2ecf20Sopenharmony_ci goto exit_boot_target; 61468c2ecf20Sopenharmony_ci } 61478c2ecf20Sopenharmony_ci 61488c2ecf20Sopenharmony_ci boot_conn->chap.target_chap_name_length = QL4_CHAP_MAX_NAME_LEN; 61498c2ecf20Sopenharmony_ci boot_conn->chap.target_secret_length = QL4_CHAP_MAX_SECRET_LEN; 61508c2ecf20Sopenharmony_ci } 61518c2ecf20Sopenharmony_ci 61528c2ecf20Sopenharmony_ci if (BIT_4 & le16_to_cpu(fw_ddb_entry->iscsi_options)) { 61538c2ecf20Sopenharmony_ci 61548c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n")); 61558c2ecf20Sopenharmony_ci 61568c2ecf20Sopenharmony_ci ret = qla4xxx_get_bidi_chap(ha, 61578c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.intr_chap_name, 61588c2ecf20Sopenharmony_ci (char *)&boot_conn->chap.intr_secret); 61598c2ecf20Sopenharmony_ci 61608c2ecf20Sopenharmony_ci if (ret) { 61618c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n"); 61628c2ecf20Sopenharmony_ci ret = QLA_ERROR; 61638c2ecf20Sopenharmony_ci goto exit_boot_target; 61648c2ecf20Sopenharmony_ci } 61658c2ecf20Sopenharmony_ci 61668c2ecf20Sopenharmony_ci boot_conn->chap.intr_chap_name_length = QL4_CHAP_MAX_NAME_LEN; 61678c2ecf20Sopenharmony_ci boot_conn->chap.intr_secret_length = QL4_CHAP_MAX_SECRET_LEN; 61688c2ecf20Sopenharmony_ci } 61698c2ecf20Sopenharmony_ci 61708c2ecf20Sopenharmony_ciexit_boot_target: 61718c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 61728c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 61738c2ecf20Sopenharmony_ci return ret; 61748c2ecf20Sopenharmony_ci} 61758c2ecf20Sopenharmony_ci 61768c2ecf20Sopenharmony_cistatic int qla4xxx_get_boot_info(struct scsi_qla_host *ha) 61778c2ecf20Sopenharmony_ci{ 61788c2ecf20Sopenharmony_ci uint16_t ddb_index[2]; 61798c2ecf20Sopenharmony_ci int ret = QLA_ERROR; 61808c2ecf20Sopenharmony_ci int rval; 61818c2ecf20Sopenharmony_ci 61828c2ecf20Sopenharmony_ci memset(ddb_index, 0, sizeof(ddb_index)); 61838c2ecf20Sopenharmony_ci ddb_index[0] = 0xffff; 61848c2ecf20Sopenharmony_ci ddb_index[1] = 0xffff; 61858c2ecf20Sopenharmony_ci ret = get_fw_boot_info(ha, ddb_index); 61868c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 61878c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 61888c2ecf20Sopenharmony_ci "%s: No boot target configured.\n", __func__)); 61898c2ecf20Sopenharmony_ci return ret; 61908c2ecf20Sopenharmony_ci } 61918c2ecf20Sopenharmony_ci 61928c2ecf20Sopenharmony_ci if (ql4xdisablesysfsboot) 61938c2ecf20Sopenharmony_ci return QLA_SUCCESS; 61948c2ecf20Sopenharmony_ci 61958c2ecf20Sopenharmony_ci if (ddb_index[0] == 0xffff) 61968c2ecf20Sopenharmony_ci goto sec_target; 61978c2ecf20Sopenharmony_ci 61988c2ecf20Sopenharmony_ci rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess), 61998c2ecf20Sopenharmony_ci ddb_index[0]); 62008c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 62018c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary boot target not " 62028c2ecf20Sopenharmony_ci "configured\n", __func__)); 62038c2ecf20Sopenharmony_ci } else 62048c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 62058c2ecf20Sopenharmony_ci 62068c2ecf20Sopenharmony_cisec_target: 62078c2ecf20Sopenharmony_ci if (ddb_index[1] == 0xffff) 62088c2ecf20Sopenharmony_ci goto exit_get_boot_info; 62098c2ecf20Sopenharmony_ci 62108c2ecf20Sopenharmony_ci rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess), 62118c2ecf20Sopenharmony_ci ddb_index[1]); 62128c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 62138c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Secondary boot target not" 62148c2ecf20Sopenharmony_ci " configured\n", __func__)); 62158c2ecf20Sopenharmony_ci } else 62168c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 62178c2ecf20Sopenharmony_ci 62188c2ecf20Sopenharmony_ciexit_get_boot_info: 62198c2ecf20Sopenharmony_ci return ret; 62208c2ecf20Sopenharmony_ci} 62218c2ecf20Sopenharmony_ci 62228c2ecf20Sopenharmony_cistatic int qla4xxx_setup_boot_info(struct scsi_qla_host *ha) 62238c2ecf20Sopenharmony_ci{ 62248c2ecf20Sopenharmony_ci struct iscsi_boot_kobj *boot_kobj; 62258c2ecf20Sopenharmony_ci 62268c2ecf20Sopenharmony_ci if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS) 62278c2ecf20Sopenharmony_ci return QLA_ERROR; 62288c2ecf20Sopenharmony_ci 62298c2ecf20Sopenharmony_ci if (ql4xdisablesysfsboot) { 62308c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 62318c2ecf20Sopenharmony_ci "%s: syfsboot disabled - driver will trigger login " 62328c2ecf20Sopenharmony_ci "and publish session for discovery .\n", __func__); 62338c2ecf20Sopenharmony_ci return QLA_SUCCESS; 62348c2ecf20Sopenharmony_ci } 62358c2ecf20Sopenharmony_ci 62368c2ecf20Sopenharmony_ci 62378c2ecf20Sopenharmony_ci ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no); 62388c2ecf20Sopenharmony_ci if (!ha->boot_kset) 62398c2ecf20Sopenharmony_ci goto kset_free; 62408c2ecf20Sopenharmony_ci 62418c2ecf20Sopenharmony_ci if (!scsi_host_get(ha->host)) 62428c2ecf20Sopenharmony_ci goto kset_free; 62438c2ecf20Sopenharmony_ci boot_kobj = iscsi_boot_create_target(ha->boot_kset, 0, ha, 62448c2ecf20Sopenharmony_ci qla4xxx_show_boot_tgt_pri_info, 62458c2ecf20Sopenharmony_ci qla4xxx_tgt_get_attr_visibility, 62468c2ecf20Sopenharmony_ci qla4xxx_boot_release); 62478c2ecf20Sopenharmony_ci if (!boot_kobj) 62488c2ecf20Sopenharmony_ci goto put_host; 62498c2ecf20Sopenharmony_ci 62508c2ecf20Sopenharmony_ci if (!scsi_host_get(ha->host)) 62518c2ecf20Sopenharmony_ci goto kset_free; 62528c2ecf20Sopenharmony_ci boot_kobj = iscsi_boot_create_target(ha->boot_kset, 1, ha, 62538c2ecf20Sopenharmony_ci qla4xxx_show_boot_tgt_sec_info, 62548c2ecf20Sopenharmony_ci qla4xxx_tgt_get_attr_visibility, 62558c2ecf20Sopenharmony_ci qla4xxx_boot_release); 62568c2ecf20Sopenharmony_ci if (!boot_kobj) 62578c2ecf20Sopenharmony_ci goto put_host; 62588c2ecf20Sopenharmony_ci 62598c2ecf20Sopenharmony_ci if (!scsi_host_get(ha->host)) 62608c2ecf20Sopenharmony_ci goto kset_free; 62618c2ecf20Sopenharmony_ci boot_kobj = iscsi_boot_create_initiator(ha->boot_kset, 0, ha, 62628c2ecf20Sopenharmony_ci qla4xxx_show_boot_ini_info, 62638c2ecf20Sopenharmony_ci qla4xxx_ini_get_attr_visibility, 62648c2ecf20Sopenharmony_ci qla4xxx_boot_release); 62658c2ecf20Sopenharmony_ci if (!boot_kobj) 62668c2ecf20Sopenharmony_ci goto put_host; 62678c2ecf20Sopenharmony_ci 62688c2ecf20Sopenharmony_ci if (!scsi_host_get(ha->host)) 62698c2ecf20Sopenharmony_ci goto kset_free; 62708c2ecf20Sopenharmony_ci boot_kobj = iscsi_boot_create_ethernet(ha->boot_kset, 0, ha, 62718c2ecf20Sopenharmony_ci qla4xxx_show_boot_eth_info, 62728c2ecf20Sopenharmony_ci qla4xxx_eth_get_attr_visibility, 62738c2ecf20Sopenharmony_ci qla4xxx_boot_release); 62748c2ecf20Sopenharmony_ci if (!boot_kobj) 62758c2ecf20Sopenharmony_ci goto put_host; 62768c2ecf20Sopenharmony_ci 62778c2ecf20Sopenharmony_ci return QLA_SUCCESS; 62788c2ecf20Sopenharmony_ci 62798c2ecf20Sopenharmony_ciput_host: 62808c2ecf20Sopenharmony_ci scsi_host_put(ha->host); 62818c2ecf20Sopenharmony_cikset_free: 62828c2ecf20Sopenharmony_ci iscsi_boot_destroy_kset(ha->boot_kset); 62838c2ecf20Sopenharmony_ci return -ENOMEM; 62848c2ecf20Sopenharmony_ci} 62858c2ecf20Sopenharmony_ci 62868c2ecf20Sopenharmony_ci 62878c2ecf20Sopenharmony_cistatic void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, 62888c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *tddb) 62898c2ecf20Sopenharmony_ci{ 62908c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 62918c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn; 62928c2ecf20Sopenharmony_ci struct iscsi_session *sess; 62938c2ecf20Sopenharmony_ci struct iscsi_conn *conn; 62948c2ecf20Sopenharmony_ci 62958c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); 62968c2ecf20Sopenharmony_ci cls_sess = ddb_entry->sess; 62978c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 62988c2ecf20Sopenharmony_ci cls_conn = ddb_entry->conn; 62998c2ecf20Sopenharmony_ci conn = cls_conn->dd_data; 63008c2ecf20Sopenharmony_ci 63018c2ecf20Sopenharmony_ci tddb->tpgt = sess->tpgt; 63028c2ecf20Sopenharmony_ci tddb->port = conn->persistent_port; 63038c2ecf20Sopenharmony_ci strlcpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); 63048c2ecf20Sopenharmony_ci strlcpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); 63058c2ecf20Sopenharmony_ci} 63068c2ecf20Sopenharmony_ci 63078c2ecf20Sopenharmony_cistatic void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, 63088c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *tddb, 63098c2ecf20Sopenharmony_ci uint8_t *flash_isid) 63108c2ecf20Sopenharmony_ci{ 63118c2ecf20Sopenharmony_ci uint16_t options = 0; 63128c2ecf20Sopenharmony_ci 63138c2ecf20Sopenharmony_ci tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); 63148c2ecf20Sopenharmony_ci memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], 63158c2ecf20Sopenharmony_ci min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name))); 63168c2ecf20Sopenharmony_ci 63178c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 63188c2ecf20Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) 63198c2ecf20Sopenharmony_ci sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr); 63208c2ecf20Sopenharmony_ci else 63218c2ecf20Sopenharmony_ci sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr); 63228c2ecf20Sopenharmony_ci 63238c2ecf20Sopenharmony_ci tddb->port = le16_to_cpu(fw_ddb_entry->port); 63248c2ecf20Sopenharmony_ci 63258c2ecf20Sopenharmony_ci if (flash_isid == NULL) 63268c2ecf20Sopenharmony_ci memcpy(&tddb->isid[0], &fw_ddb_entry->isid[0], 63278c2ecf20Sopenharmony_ci sizeof(tddb->isid)); 63288c2ecf20Sopenharmony_ci else 63298c2ecf20Sopenharmony_ci memcpy(&tddb->isid[0], &flash_isid[0], sizeof(tddb->isid)); 63308c2ecf20Sopenharmony_ci} 63318c2ecf20Sopenharmony_ci 63328c2ecf20Sopenharmony_cistatic int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, 63338c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *old_tddb, 63348c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *new_tddb, 63358c2ecf20Sopenharmony_ci uint8_t is_isid_compare) 63368c2ecf20Sopenharmony_ci{ 63378c2ecf20Sopenharmony_ci if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name)) 63388c2ecf20Sopenharmony_ci return QLA_ERROR; 63398c2ecf20Sopenharmony_ci 63408c2ecf20Sopenharmony_ci if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr)) 63418c2ecf20Sopenharmony_ci return QLA_ERROR; 63428c2ecf20Sopenharmony_ci 63438c2ecf20Sopenharmony_ci if (old_tddb->port != new_tddb->port) 63448c2ecf20Sopenharmony_ci return QLA_ERROR; 63458c2ecf20Sopenharmony_ci 63468c2ecf20Sopenharmony_ci /* For multi sessions, driver generates the ISID, so do not compare 63478c2ecf20Sopenharmony_ci * ISID in reset path since it would be a comparison between the 63488c2ecf20Sopenharmony_ci * driver generated ISID and firmware generated ISID. This could 63498c2ecf20Sopenharmony_ci * lead to adding duplicated DDBs in the list as driver generated 63508c2ecf20Sopenharmony_ci * ISID would not match firmware generated ISID. 63518c2ecf20Sopenharmony_ci */ 63528c2ecf20Sopenharmony_ci if (is_isid_compare) { 63538c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 63548c2ecf20Sopenharmony_ci "%s: old ISID [%pmR] New ISID [%pmR]\n", 63558c2ecf20Sopenharmony_ci __func__, old_tddb->isid, new_tddb->isid)); 63568c2ecf20Sopenharmony_ci 63578c2ecf20Sopenharmony_ci if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0], 63588c2ecf20Sopenharmony_ci sizeof(old_tddb->isid))) 63598c2ecf20Sopenharmony_ci return QLA_ERROR; 63608c2ecf20Sopenharmony_ci } 63618c2ecf20Sopenharmony_ci 63628c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 63638c2ecf20Sopenharmony_ci "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]", 63648c2ecf20Sopenharmony_ci old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr, 63658c2ecf20Sopenharmony_ci old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt, 63668c2ecf20Sopenharmony_ci new_tddb->ip_addr, new_tddb->iscsi_name)); 63678c2ecf20Sopenharmony_ci 63688c2ecf20Sopenharmony_ci return QLA_SUCCESS; 63698c2ecf20Sopenharmony_ci} 63708c2ecf20Sopenharmony_ci 63718c2ecf20Sopenharmony_cistatic int qla4xxx_is_session_exists(struct scsi_qla_host *ha, 63728c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 63738c2ecf20Sopenharmony_ci uint32_t *index) 63748c2ecf20Sopenharmony_ci{ 63758c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 63768c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *fw_tddb = NULL; 63778c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *tmp_tddb = NULL; 63788c2ecf20Sopenharmony_ci int idx; 63798c2ecf20Sopenharmony_ci int ret = QLA_ERROR; 63808c2ecf20Sopenharmony_ci 63818c2ecf20Sopenharmony_ci fw_tddb = vzalloc(sizeof(*fw_tddb)); 63828c2ecf20Sopenharmony_ci if (!fw_tddb) { 63838c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 63848c2ecf20Sopenharmony_ci "Memory Allocation failed.\n")); 63858c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 63868c2ecf20Sopenharmony_ci goto exit_check; 63878c2ecf20Sopenharmony_ci } 63888c2ecf20Sopenharmony_ci 63898c2ecf20Sopenharmony_ci tmp_tddb = vzalloc(sizeof(*tmp_tddb)); 63908c2ecf20Sopenharmony_ci if (!tmp_tddb) { 63918c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 63928c2ecf20Sopenharmony_ci "Memory Allocation failed.\n")); 63938c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 63948c2ecf20Sopenharmony_ci goto exit_check; 63958c2ecf20Sopenharmony_ci } 63968c2ecf20Sopenharmony_ci 63978c2ecf20Sopenharmony_ci qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb, NULL); 63988c2ecf20Sopenharmony_ci 63998c2ecf20Sopenharmony_ci for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { 64008c2ecf20Sopenharmony_ci ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); 64018c2ecf20Sopenharmony_ci if (ddb_entry == NULL) 64028c2ecf20Sopenharmony_ci continue; 64038c2ecf20Sopenharmony_ci 64048c2ecf20Sopenharmony_ci qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); 64058c2ecf20Sopenharmony_ci if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) { 64068c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; /* found */ 64078c2ecf20Sopenharmony_ci if (index != NULL) 64088c2ecf20Sopenharmony_ci *index = idx; 64098c2ecf20Sopenharmony_ci goto exit_check; 64108c2ecf20Sopenharmony_ci } 64118c2ecf20Sopenharmony_ci } 64128c2ecf20Sopenharmony_ci 64138c2ecf20Sopenharmony_ciexit_check: 64148c2ecf20Sopenharmony_ci if (fw_tddb) 64158c2ecf20Sopenharmony_ci vfree(fw_tddb); 64168c2ecf20Sopenharmony_ci if (tmp_tddb) 64178c2ecf20Sopenharmony_ci vfree(tmp_tddb); 64188c2ecf20Sopenharmony_ci return ret; 64198c2ecf20Sopenharmony_ci} 64208c2ecf20Sopenharmony_ci 64218c2ecf20Sopenharmony_ci/** 64228c2ecf20Sopenharmony_ci * qla4xxx_check_existing_isid - check if target with same isid exist 64238c2ecf20Sopenharmony_ci * in target list 64248c2ecf20Sopenharmony_ci * @list_nt: list of target 64258c2ecf20Sopenharmony_ci * @isid: isid to check 64268c2ecf20Sopenharmony_ci * 64278c2ecf20Sopenharmony_ci * This routine return QLA_SUCCESS if target with same isid exist 64288c2ecf20Sopenharmony_ci **/ 64298c2ecf20Sopenharmony_cistatic int qla4xxx_check_existing_isid(struct list_head *list_nt, uint8_t *isid) 64308c2ecf20Sopenharmony_ci{ 64318c2ecf20Sopenharmony_ci struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; 64328c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 64338c2ecf20Sopenharmony_ci 64348c2ecf20Sopenharmony_ci list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { 64358c2ecf20Sopenharmony_ci fw_ddb_entry = &nt_ddb_idx->fw_ddb; 64368c2ecf20Sopenharmony_ci 64378c2ecf20Sopenharmony_ci if (memcmp(&fw_ddb_entry->isid[0], &isid[0], 64388c2ecf20Sopenharmony_ci sizeof(nt_ddb_idx->fw_ddb.isid)) == 0) { 64398c2ecf20Sopenharmony_ci return QLA_SUCCESS; 64408c2ecf20Sopenharmony_ci } 64418c2ecf20Sopenharmony_ci } 64428c2ecf20Sopenharmony_ci return QLA_ERROR; 64438c2ecf20Sopenharmony_ci} 64448c2ecf20Sopenharmony_ci 64458c2ecf20Sopenharmony_ci/** 64468c2ecf20Sopenharmony_ci * qla4xxx_update_isid - compare ddbs and updated isid 64478c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 64488c2ecf20Sopenharmony_ci * @list_nt: list of nt target 64498c2ecf20Sopenharmony_ci * @fw_ddb_entry: firmware ddb entry 64508c2ecf20Sopenharmony_ci * 64518c2ecf20Sopenharmony_ci * This routine update isid if ddbs have same iqn, same isid and 64528c2ecf20Sopenharmony_ci * different IP addr. 64538c2ecf20Sopenharmony_ci * Return QLA_SUCCESS if isid is updated. 64548c2ecf20Sopenharmony_ci **/ 64558c2ecf20Sopenharmony_cistatic int qla4xxx_update_isid(struct scsi_qla_host *ha, 64568c2ecf20Sopenharmony_ci struct list_head *list_nt, 64578c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 64588c2ecf20Sopenharmony_ci{ 64598c2ecf20Sopenharmony_ci uint8_t base_value, i; 64608c2ecf20Sopenharmony_ci 64618c2ecf20Sopenharmony_ci base_value = fw_ddb_entry->isid[1] & 0x1f; 64628c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 64638c2ecf20Sopenharmony_ci fw_ddb_entry->isid[1] = (base_value | (i << 5)); 64648c2ecf20Sopenharmony_ci if (qla4xxx_check_existing_isid(list_nt, fw_ddb_entry->isid)) 64658c2ecf20Sopenharmony_ci break; 64668c2ecf20Sopenharmony_ci } 64678c2ecf20Sopenharmony_ci 64688c2ecf20Sopenharmony_ci if (!qla4xxx_check_existing_isid(list_nt, fw_ddb_entry->isid)) 64698c2ecf20Sopenharmony_ci return QLA_ERROR; 64708c2ecf20Sopenharmony_ci 64718c2ecf20Sopenharmony_ci return QLA_SUCCESS; 64728c2ecf20Sopenharmony_ci} 64738c2ecf20Sopenharmony_ci 64748c2ecf20Sopenharmony_ci/** 64758c2ecf20Sopenharmony_ci * qla4xxx_should_update_isid - check if isid need to update 64768c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 64778c2ecf20Sopenharmony_ci * @old_tddb: ddb tuple 64788c2ecf20Sopenharmony_ci * @new_tddb: ddb tuple 64798c2ecf20Sopenharmony_ci * 64808c2ecf20Sopenharmony_ci * Return QLA_SUCCESS if different IP, different PORT, same iqn, 64818c2ecf20Sopenharmony_ci * same isid 64828c2ecf20Sopenharmony_ci **/ 64838c2ecf20Sopenharmony_cistatic int qla4xxx_should_update_isid(struct scsi_qla_host *ha, 64848c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *old_tddb, 64858c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *new_tddb) 64868c2ecf20Sopenharmony_ci{ 64878c2ecf20Sopenharmony_ci if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr) == 0) { 64888c2ecf20Sopenharmony_ci /* Same ip */ 64898c2ecf20Sopenharmony_ci if (old_tddb->port == new_tddb->port) 64908c2ecf20Sopenharmony_ci return QLA_ERROR; 64918c2ecf20Sopenharmony_ci } 64928c2ecf20Sopenharmony_ci 64938c2ecf20Sopenharmony_ci if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name)) 64948c2ecf20Sopenharmony_ci /* different iqn */ 64958c2ecf20Sopenharmony_ci return QLA_ERROR; 64968c2ecf20Sopenharmony_ci 64978c2ecf20Sopenharmony_ci if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0], 64988c2ecf20Sopenharmony_ci sizeof(old_tddb->isid))) 64998c2ecf20Sopenharmony_ci /* different isid */ 65008c2ecf20Sopenharmony_ci return QLA_ERROR; 65018c2ecf20Sopenharmony_ci 65028c2ecf20Sopenharmony_ci return QLA_SUCCESS; 65038c2ecf20Sopenharmony_ci} 65048c2ecf20Sopenharmony_ci 65058c2ecf20Sopenharmony_ci/** 65068c2ecf20Sopenharmony_ci * qla4xxx_is_flash_ddb_exists - check if fw_ddb_entry already exists in list_nt 65078c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 65088c2ecf20Sopenharmony_ci * @list_nt: list of nt target. 65098c2ecf20Sopenharmony_ci * @fw_ddb_entry: firmware ddb entry. 65108c2ecf20Sopenharmony_ci * 65118c2ecf20Sopenharmony_ci * This routine check if fw_ddb_entry already exists in list_nt to avoid 65128c2ecf20Sopenharmony_ci * duplicate ddb in list_nt. 65138c2ecf20Sopenharmony_ci * Return QLA_SUCCESS if duplicate ddb exit in list_nl. 65148c2ecf20Sopenharmony_ci * Note: This function also update isid of DDB if required. 65158c2ecf20Sopenharmony_ci **/ 65168c2ecf20Sopenharmony_ci 65178c2ecf20Sopenharmony_cistatic int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha, 65188c2ecf20Sopenharmony_ci struct list_head *list_nt, 65198c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 65208c2ecf20Sopenharmony_ci{ 65218c2ecf20Sopenharmony_ci struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; 65228c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *fw_tddb = NULL; 65238c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *tmp_tddb = NULL; 65248c2ecf20Sopenharmony_ci int rval, ret = QLA_ERROR; 65258c2ecf20Sopenharmony_ci 65268c2ecf20Sopenharmony_ci fw_tddb = vzalloc(sizeof(*fw_tddb)); 65278c2ecf20Sopenharmony_ci if (!fw_tddb) { 65288c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 65298c2ecf20Sopenharmony_ci "Memory Allocation failed.\n")); 65308c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 65318c2ecf20Sopenharmony_ci goto exit_check; 65328c2ecf20Sopenharmony_ci } 65338c2ecf20Sopenharmony_ci 65348c2ecf20Sopenharmony_ci tmp_tddb = vzalloc(sizeof(*tmp_tddb)); 65358c2ecf20Sopenharmony_ci if (!tmp_tddb) { 65368c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_WARNING, ha, 65378c2ecf20Sopenharmony_ci "Memory Allocation failed.\n")); 65388c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 65398c2ecf20Sopenharmony_ci goto exit_check; 65408c2ecf20Sopenharmony_ci } 65418c2ecf20Sopenharmony_ci 65428c2ecf20Sopenharmony_ci qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb, NULL); 65438c2ecf20Sopenharmony_ci 65448c2ecf20Sopenharmony_ci list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { 65458c2ecf20Sopenharmony_ci qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb, 65468c2ecf20Sopenharmony_ci nt_ddb_idx->flash_isid); 65478c2ecf20Sopenharmony_ci ret = qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, true); 65488c2ecf20Sopenharmony_ci /* found duplicate ddb */ 65498c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS) 65508c2ecf20Sopenharmony_ci goto exit_check; 65518c2ecf20Sopenharmony_ci } 65528c2ecf20Sopenharmony_ci 65538c2ecf20Sopenharmony_ci list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { 65548c2ecf20Sopenharmony_ci qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb, NULL); 65558c2ecf20Sopenharmony_ci 65568c2ecf20Sopenharmony_ci ret = qla4xxx_should_update_isid(ha, tmp_tddb, fw_tddb); 65578c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS) { 65588c2ecf20Sopenharmony_ci rval = qla4xxx_update_isid(ha, list_nt, fw_ddb_entry); 65598c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) 65608c2ecf20Sopenharmony_ci ret = QLA_ERROR; 65618c2ecf20Sopenharmony_ci else 65628c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 65638c2ecf20Sopenharmony_ci 65648c2ecf20Sopenharmony_ci goto exit_check; 65658c2ecf20Sopenharmony_ci } 65668c2ecf20Sopenharmony_ci } 65678c2ecf20Sopenharmony_ci 65688c2ecf20Sopenharmony_ciexit_check: 65698c2ecf20Sopenharmony_ci if (fw_tddb) 65708c2ecf20Sopenharmony_ci vfree(fw_tddb); 65718c2ecf20Sopenharmony_ci if (tmp_tddb) 65728c2ecf20Sopenharmony_ci vfree(tmp_tddb); 65738c2ecf20Sopenharmony_ci return ret; 65748c2ecf20Sopenharmony_ci} 65758c2ecf20Sopenharmony_ci 65768c2ecf20Sopenharmony_cistatic void qla4xxx_free_ddb_list(struct list_head *list_ddb) 65778c2ecf20Sopenharmony_ci{ 65788c2ecf20Sopenharmony_ci struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; 65798c2ecf20Sopenharmony_ci 65808c2ecf20Sopenharmony_ci list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { 65818c2ecf20Sopenharmony_ci list_del_init(&ddb_idx->list); 65828c2ecf20Sopenharmony_ci vfree(ddb_idx); 65838c2ecf20Sopenharmony_ci } 65848c2ecf20Sopenharmony_ci} 65858c2ecf20Sopenharmony_ci 65868c2ecf20Sopenharmony_cistatic struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha, 65878c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 65888c2ecf20Sopenharmony_ci{ 65898c2ecf20Sopenharmony_ci struct iscsi_endpoint *ep; 65908c2ecf20Sopenharmony_ci struct sockaddr_in *addr; 65918c2ecf20Sopenharmony_ci struct sockaddr_in6 *addr6; 65928c2ecf20Sopenharmony_ci struct sockaddr *t_addr; 65938c2ecf20Sopenharmony_ci struct sockaddr_storage *dst_addr; 65948c2ecf20Sopenharmony_ci char *ip; 65958c2ecf20Sopenharmony_ci 65968c2ecf20Sopenharmony_ci /* TODO: need to destroy on unload iscsi_endpoint*/ 65978c2ecf20Sopenharmony_ci dst_addr = vmalloc(sizeof(*dst_addr)); 65988c2ecf20Sopenharmony_ci if (!dst_addr) 65998c2ecf20Sopenharmony_ci return NULL; 66008c2ecf20Sopenharmony_ci 66018c2ecf20Sopenharmony_ci if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) { 66028c2ecf20Sopenharmony_ci t_addr = (struct sockaddr *)dst_addr; 66038c2ecf20Sopenharmony_ci t_addr->sa_family = AF_INET6; 66048c2ecf20Sopenharmony_ci addr6 = (struct sockaddr_in6 *)dst_addr; 66058c2ecf20Sopenharmony_ci ip = (char *)&addr6->sin6_addr; 66068c2ecf20Sopenharmony_ci memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN); 66078c2ecf20Sopenharmony_ci addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port)); 66088c2ecf20Sopenharmony_ci 66098c2ecf20Sopenharmony_ci } else { 66108c2ecf20Sopenharmony_ci t_addr = (struct sockaddr *)dst_addr; 66118c2ecf20Sopenharmony_ci t_addr->sa_family = AF_INET; 66128c2ecf20Sopenharmony_ci addr = (struct sockaddr_in *)dst_addr; 66138c2ecf20Sopenharmony_ci ip = (char *)&addr->sin_addr; 66148c2ecf20Sopenharmony_ci memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN); 66158c2ecf20Sopenharmony_ci addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port)); 66168c2ecf20Sopenharmony_ci } 66178c2ecf20Sopenharmony_ci 66188c2ecf20Sopenharmony_ci ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0); 66198c2ecf20Sopenharmony_ci vfree(dst_addr); 66208c2ecf20Sopenharmony_ci return ep; 66218c2ecf20Sopenharmony_ci} 66228c2ecf20Sopenharmony_ci 66238c2ecf20Sopenharmony_cistatic int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx) 66248c2ecf20Sopenharmony_ci{ 66258c2ecf20Sopenharmony_ci if (ql4xdisablesysfsboot) 66268c2ecf20Sopenharmony_ci return QLA_SUCCESS; 66278c2ecf20Sopenharmony_ci if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx) 66288c2ecf20Sopenharmony_ci return QLA_ERROR; 66298c2ecf20Sopenharmony_ci return QLA_SUCCESS; 66308c2ecf20Sopenharmony_ci} 66318c2ecf20Sopenharmony_ci 66328c2ecf20Sopenharmony_cistatic void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, 66338c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry, 66348c2ecf20Sopenharmony_ci uint16_t idx) 66358c2ecf20Sopenharmony_ci{ 66368c2ecf20Sopenharmony_ci uint16_t def_timeout; 66378c2ecf20Sopenharmony_ci 66388c2ecf20Sopenharmony_ci ddb_entry->ddb_type = FLASH_DDB; 66398c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index = INVALID_ENTRY; 66408c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; 66418c2ecf20Sopenharmony_ci ddb_entry->ha = ha; 66428c2ecf20Sopenharmony_ci ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; 66438c2ecf20Sopenharmony_ci ddb_entry->ddb_change = qla4xxx_flash_ddb_change; 66448c2ecf20Sopenharmony_ci ddb_entry->chap_tbl_idx = INVALID_ENTRY; 66458c2ecf20Sopenharmony_ci 66468c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); 66478c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->relogin_timer, 0); 66488c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->relogin_retry_count, 0); 66498c2ecf20Sopenharmony_ci def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout); 66508c2ecf20Sopenharmony_ci ddb_entry->default_relogin_timeout = 66518c2ecf20Sopenharmony_ci (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ? 66528c2ecf20Sopenharmony_ci def_timeout : LOGIN_TOV; 66538c2ecf20Sopenharmony_ci ddb_entry->default_time2wait = 66548c2ecf20Sopenharmony_ci le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait); 66558c2ecf20Sopenharmony_ci 66568c2ecf20Sopenharmony_ci if (ql4xdisablesysfsboot && 66578c2ecf20Sopenharmony_ci (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx)) 66588c2ecf20Sopenharmony_ci set_bit(DF_BOOT_TGT, &ddb_entry->flags); 66598c2ecf20Sopenharmony_ci} 66608c2ecf20Sopenharmony_ci 66618c2ecf20Sopenharmony_cistatic void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) 66628c2ecf20Sopenharmony_ci{ 66638c2ecf20Sopenharmony_ci uint32_t idx = 0; 66648c2ecf20Sopenharmony_ci uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */ 66658c2ecf20Sopenharmony_ci uint32_t sts[MBOX_REG_COUNT]; 66668c2ecf20Sopenharmony_ci uint32_t ip_state; 66678c2ecf20Sopenharmony_ci unsigned long wtime; 66688c2ecf20Sopenharmony_ci int ret; 66698c2ecf20Sopenharmony_ci 66708c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * IP_CONFIG_TOV); 66718c2ecf20Sopenharmony_ci do { 66728c2ecf20Sopenharmony_ci for (idx = 0; idx < IP_ADDR_COUNT; idx++) { 66738c2ecf20Sopenharmony_ci if (ip_idx[idx] == -1) 66748c2ecf20Sopenharmony_ci continue; 66758c2ecf20Sopenharmony_ci 66768c2ecf20Sopenharmony_ci ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts); 66778c2ecf20Sopenharmony_ci 66788c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) { 66798c2ecf20Sopenharmony_ci ip_idx[idx] = -1; 66808c2ecf20Sopenharmony_ci continue; 66818c2ecf20Sopenharmony_ci } 66828c2ecf20Sopenharmony_ci 66838c2ecf20Sopenharmony_ci ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT; 66848c2ecf20Sopenharmony_ci 66858c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 66868c2ecf20Sopenharmony_ci "Waiting for IP state for idx = %d, state = 0x%x\n", 66878c2ecf20Sopenharmony_ci ip_idx[idx], ip_state)); 66888c2ecf20Sopenharmony_ci if (ip_state == IP_ADDRSTATE_UNCONFIGURED || 66898c2ecf20Sopenharmony_ci ip_state == IP_ADDRSTATE_INVALID || 66908c2ecf20Sopenharmony_ci ip_state == IP_ADDRSTATE_PREFERRED || 66918c2ecf20Sopenharmony_ci ip_state == IP_ADDRSTATE_DEPRICATED || 66928c2ecf20Sopenharmony_ci ip_state == IP_ADDRSTATE_DISABLING) 66938c2ecf20Sopenharmony_ci ip_idx[idx] = -1; 66948c2ecf20Sopenharmony_ci } 66958c2ecf20Sopenharmony_ci 66968c2ecf20Sopenharmony_ci /* Break if all IP states checked */ 66978c2ecf20Sopenharmony_ci if ((ip_idx[0] == -1) && 66988c2ecf20Sopenharmony_ci (ip_idx[1] == -1) && 66998c2ecf20Sopenharmony_ci (ip_idx[2] == -1) && 67008c2ecf20Sopenharmony_ci (ip_idx[3] == -1)) 67018c2ecf20Sopenharmony_ci break; 67028c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ); 67038c2ecf20Sopenharmony_ci } while (time_after(wtime, jiffies)); 67048c2ecf20Sopenharmony_ci} 67058c2ecf20Sopenharmony_ci 67068c2ecf20Sopenharmony_cistatic int qla4xxx_cmp_fw_stentry(struct dev_db_entry *fw_ddb_entry, 67078c2ecf20Sopenharmony_ci struct dev_db_entry *flash_ddb_entry) 67088c2ecf20Sopenharmony_ci{ 67098c2ecf20Sopenharmony_ci uint16_t options = 0; 67108c2ecf20Sopenharmony_ci size_t ip_len = IP_ADDR_LEN; 67118c2ecf20Sopenharmony_ci 67128c2ecf20Sopenharmony_ci options = le16_to_cpu(fw_ddb_entry->options); 67138c2ecf20Sopenharmony_ci if (options & DDB_OPT_IPV6_DEVICE) 67148c2ecf20Sopenharmony_ci ip_len = IPv6_ADDR_LEN; 67158c2ecf20Sopenharmony_ci 67168c2ecf20Sopenharmony_ci if (memcmp(fw_ddb_entry->ip_addr, flash_ddb_entry->ip_addr, ip_len)) 67178c2ecf20Sopenharmony_ci return QLA_ERROR; 67188c2ecf20Sopenharmony_ci 67198c2ecf20Sopenharmony_ci if (memcmp(&fw_ddb_entry->isid[0], &flash_ddb_entry->isid[0], 67208c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->isid))) 67218c2ecf20Sopenharmony_ci return QLA_ERROR; 67228c2ecf20Sopenharmony_ci 67238c2ecf20Sopenharmony_ci if (memcmp(&fw_ddb_entry->port, &flash_ddb_entry->port, 67248c2ecf20Sopenharmony_ci sizeof(fw_ddb_entry->port))) 67258c2ecf20Sopenharmony_ci return QLA_ERROR; 67268c2ecf20Sopenharmony_ci 67278c2ecf20Sopenharmony_ci return QLA_SUCCESS; 67288c2ecf20Sopenharmony_ci} 67298c2ecf20Sopenharmony_ci 67308c2ecf20Sopenharmony_cistatic int qla4xxx_find_flash_st_idx(struct scsi_qla_host *ha, 67318c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 67328c2ecf20Sopenharmony_ci uint32_t fw_idx, uint32_t *flash_index) 67338c2ecf20Sopenharmony_ci{ 67348c2ecf20Sopenharmony_ci struct dev_db_entry *flash_ddb_entry; 67358c2ecf20Sopenharmony_ci dma_addr_t flash_ddb_entry_dma; 67368c2ecf20Sopenharmony_ci uint32_t idx = 0; 67378c2ecf20Sopenharmony_ci int max_ddbs; 67388c2ecf20Sopenharmony_ci int ret = QLA_ERROR, status; 67398c2ecf20Sopenharmony_ci 67408c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 67418c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 67428c2ecf20Sopenharmony_ci 67438c2ecf20Sopenharmony_ci flash_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, 67448c2ecf20Sopenharmony_ci &flash_ddb_entry_dma); 67458c2ecf20Sopenharmony_ci if (flash_ddb_entry == NULL || fw_ddb_entry == NULL) { 67468c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Out of memory\n"); 67478c2ecf20Sopenharmony_ci goto exit_find_st_idx; 67488c2ecf20Sopenharmony_ci } 67498c2ecf20Sopenharmony_ci 67508c2ecf20Sopenharmony_ci status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry, 67518c2ecf20Sopenharmony_ci flash_ddb_entry_dma, fw_idx); 67528c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 67538c2ecf20Sopenharmony_ci status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry); 67548c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 67558c2ecf20Sopenharmony_ci *flash_index = fw_idx; 67568c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 67578c2ecf20Sopenharmony_ci goto exit_find_st_idx; 67588c2ecf20Sopenharmony_ci } 67598c2ecf20Sopenharmony_ci } 67608c2ecf20Sopenharmony_ci 67618c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx++) { 67628c2ecf20Sopenharmony_ci status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry, 67638c2ecf20Sopenharmony_ci flash_ddb_entry_dma, idx); 67648c2ecf20Sopenharmony_ci if (status == QLA_ERROR) 67658c2ecf20Sopenharmony_ci continue; 67668c2ecf20Sopenharmony_ci 67678c2ecf20Sopenharmony_ci status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry); 67688c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 67698c2ecf20Sopenharmony_ci *flash_index = idx; 67708c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 67718c2ecf20Sopenharmony_ci goto exit_find_st_idx; 67728c2ecf20Sopenharmony_ci } 67738c2ecf20Sopenharmony_ci } 67748c2ecf20Sopenharmony_ci 67758c2ecf20Sopenharmony_ci if (idx == max_ddbs) 67768c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "Failed to find ST [%d] in flash\n", 67778c2ecf20Sopenharmony_ci fw_idx); 67788c2ecf20Sopenharmony_ci 67798c2ecf20Sopenharmony_ciexit_find_st_idx: 67808c2ecf20Sopenharmony_ci if (flash_ddb_entry) 67818c2ecf20Sopenharmony_ci dma_pool_free(ha->fw_ddb_dma_pool, flash_ddb_entry, 67828c2ecf20Sopenharmony_ci flash_ddb_entry_dma); 67838c2ecf20Sopenharmony_ci 67848c2ecf20Sopenharmony_ci return ret; 67858c2ecf20Sopenharmony_ci} 67868c2ecf20Sopenharmony_ci 67878c2ecf20Sopenharmony_cistatic void qla4xxx_build_st_list(struct scsi_qla_host *ha, 67888c2ecf20Sopenharmony_ci struct list_head *list_st) 67898c2ecf20Sopenharmony_ci{ 67908c2ecf20Sopenharmony_ci struct qla_ddb_index *st_ddb_idx; 67918c2ecf20Sopenharmony_ci int max_ddbs; 67928c2ecf20Sopenharmony_ci int fw_idx_size; 67938c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 67948c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_dma; 67958c2ecf20Sopenharmony_ci int ret; 67968c2ecf20Sopenharmony_ci uint32_t idx = 0, next_idx = 0; 67978c2ecf20Sopenharmony_ci uint32_t state = 0, conn_err = 0; 67988c2ecf20Sopenharmony_ci uint32_t flash_index = -1; 67998c2ecf20Sopenharmony_ci uint16_t conn_id = 0; 68008c2ecf20Sopenharmony_ci 68018c2ecf20Sopenharmony_ci fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, 68028c2ecf20Sopenharmony_ci &fw_ddb_dma); 68038c2ecf20Sopenharmony_ci if (fw_ddb_entry == NULL) { 68048c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); 68058c2ecf20Sopenharmony_ci goto exit_st_list; 68068c2ecf20Sopenharmony_ci } 68078c2ecf20Sopenharmony_ci 68088c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 68098c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 68108c2ecf20Sopenharmony_ci fw_idx_size = sizeof(struct qla_ddb_index); 68118c2ecf20Sopenharmony_ci 68128c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx = next_idx) { 68138c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, 68148c2ecf20Sopenharmony_ci NULL, &next_idx, &state, 68158c2ecf20Sopenharmony_ci &conn_err, NULL, &conn_id); 68168c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 68178c2ecf20Sopenharmony_ci break; 68188c2ecf20Sopenharmony_ci 68198c2ecf20Sopenharmony_ci /* Ignore DDB if invalid state (unassigned) */ 68208c2ecf20Sopenharmony_ci if (state == DDB_DS_UNASSIGNED) 68218c2ecf20Sopenharmony_ci goto continue_next_st; 68228c2ecf20Sopenharmony_ci 68238c2ecf20Sopenharmony_ci /* Check if ST, add to the list_st */ 68248c2ecf20Sopenharmony_ci if (strlen((char *) fw_ddb_entry->iscsi_name) != 0) 68258c2ecf20Sopenharmony_ci goto continue_next_st; 68268c2ecf20Sopenharmony_ci 68278c2ecf20Sopenharmony_ci st_ddb_idx = vzalloc(fw_idx_size); 68288c2ecf20Sopenharmony_ci if (!st_ddb_idx) 68298c2ecf20Sopenharmony_ci break; 68308c2ecf20Sopenharmony_ci 68318c2ecf20Sopenharmony_ci ret = qla4xxx_find_flash_st_idx(ha, fw_ddb_entry, idx, 68328c2ecf20Sopenharmony_ci &flash_index); 68338c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) { 68348c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 68358c2ecf20Sopenharmony_ci "No flash entry for ST at idx [%d]\n", idx); 68368c2ecf20Sopenharmony_ci st_ddb_idx->flash_ddb_idx = idx; 68378c2ecf20Sopenharmony_ci } else { 68388c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 68398c2ecf20Sopenharmony_ci "ST at idx [%d] is stored at flash [%d]\n", 68408c2ecf20Sopenharmony_ci idx, flash_index); 68418c2ecf20Sopenharmony_ci st_ddb_idx->flash_ddb_idx = flash_index; 68428c2ecf20Sopenharmony_ci } 68438c2ecf20Sopenharmony_ci 68448c2ecf20Sopenharmony_ci st_ddb_idx->fw_ddb_idx = idx; 68458c2ecf20Sopenharmony_ci 68468c2ecf20Sopenharmony_ci list_add_tail(&st_ddb_idx->list, list_st); 68478c2ecf20Sopenharmony_cicontinue_next_st: 68488c2ecf20Sopenharmony_ci if (next_idx == 0) 68498c2ecf20Sopenharmony_ci break; 68508c2ecf20Sopenharmony_ci } 68518c2ecf20Sopenharmony_ci 68528c2ecf20Sopenharmony_ciexit_st_list: 68538c2ecf20Sopenharmony_ci if (fw_ddb_entry) 68548c2ecf20Sopenharmony_ci dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); 68558c2ecf20Sopenharmony_ci} 68568c2ecf20Sopenharmony_ci 68578c2ecf20Sopenharmony_ci/** 68588c2ecf20Sopenharmony_ci * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list 68598c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 68608c2ecf20Sopenharmony_ci * @list_ddb: List from which failed ddb to be removed 68618c2ecf20Sopenharmony_ci * 68628c2ecf20Sopenharmony_ci * Iterate over the list of DDBs and find and remove DDBs that are either in 68638c2ecf20Sopenharmony_ci * no connection active state or failed state 68648c2ecf20Sopenharmony_ci **/ 68658c2ecf20Sopenharmony_cistatic void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha, 68668c2ecf20Sopenharmony_ci struct list_head *list_ddb) 68678c2ecf20Sopenharmony_ci{ 68688c2ecf20Sopenharmony_ci struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; 68698c2ecf20Sopenharmony_ci uint32_t next_idx = 0; 68708c2ecf20Sopenharmony_ci uint32_t state = 0, conn_err = 0; 68718c2ecf20Sopenharmony_ci int ret; 68728c2ecf20Sopenharmony_ci 68738c2ecf20Sopenharmony_ci list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { 68748c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx, 68758c2ecf20Sopenharmony_ci NULL, 0, NULL, &next_idx, &state, 68768c2ecf20Sopenharmony_ci &conn_err, NULL, NULL); 68778c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 68788c2ecf20Sopenharmony_ci continue; 68798c2ecf20Sopenharmony_ci 68808c2ecf20Sopenharmony_ci if (state == DDB_DS_NO_CONNECTION_ACTIVE || 68818c2ecf20Sopenharmony_ci state == DDB_DS_SESSION_FAILED) { 68828c2ecf20Sopenharmony_ci list_del_init(&ddb_idx->list); 68838c2ecf20Sopenharmony_ci vfree(ddb_idx); 68848c2ecf20Sopenharmony_ci } 68858c2ecf20Sopenharmony_ci } 68868c2ecf20Sopenharmony_ci} 68878c2ecf20Sopenharmony_ci 68888c2ecf20Sopenharmony_cistatic void qla4xxx_update_sess_disc_idx(struct scsi_qla_host *ha, 68898c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry, 68908c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 68918c2ecf20Sopenharmony_ci{ 68928c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 68938c2ecf20Sopenharmony_ci struct iscsi_session *sess; 68948c2ecf20Sopenharmony_ci uint32_t max_ddbs = 0; 68958c2ecf20Sopenharmony_ci uint16_t ddb_link = -1; 68968c2ecf20Sopenharmony_ci 68978c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 68988c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 68998c2ecf20Sopenharmony_ci 69008c2ecf20Sopenharmony_ci cls_sess = ddb_entry->sess; 69018c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 69028c2ecf20Sopenharmony_ci 69038c2ecf20Sopenharmony_ci ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); 69048c2ecf20Sopenharmony_ci if (ddb_link < max_ddbs) 69058c2ecf20Sopenharmony_ci sess->discovery_parent_idx = ddb_link; 69068c2ecf20Sopenharmony_ci else 69078c2ecf20Sopenharmony_ci sess->discovery_parent_idx = DDB_NO_LINK; 69088c2ecf20Sopenharmony_ci} 69098c2ecf20Sopenharmony_ci 69108c2ecf20Sopenharmony_cistatic int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, 69118c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 69128c2ecf20Sopenharmony_ci int is_reset, uint16_t idx) 69138c2ecf20Sopenharmony_ci{ 69148c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 69158c2ecf20Sopenharmony_ci struct iscsi_session *sess; 69168c2ecf20Sopenharmony_ci struct iscsi_cls_conn *cls_conn; 69178c2ecf20Sopenharmony_ci struct iscsi_endpoint *ep; 69188c2ecf20Sopenharmony_ci uint16_t cmds_max = 32; 69198c2ecf20Sopenharmony_ci uint16_t conn_id = 0; 69208c2ecf20Sopenharmony_ci uint32_t initial_cmdsn = 0; 69218c2ecf20Sopenharmony_ci int ret = QLA_SUCCESS; 69228c2ecf20Sopenharmony_ci 69238c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = NULL; 69248c2ecf20Sopenharmony_ci 69258c2ecf20Sopenharmony_ci /* Create session object, with INVALID_ENTRY, 69268c2ecf20Sopenharmony_ci * the targer_id would get set when we issue the login 69278c2ecf20Sopenharmony_ci */ 69288c2ecf20Sopenharmony_ci cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host, 69298c2ecf20Sopenharmony_ci cmds_max, sizeof(struct ddb_entry), 69308c2ecf20Sopenharmony_ci sizeof(struct ql4_task_data), 69318c2ecf20Sopenharmony_ci initial_cmdsn, INVALID_ENTRY); 69328c2ecf20Sopenharmony_ci if (!cls_sess) { 69338c2ecf20Sopenharmony_ci ret = QLA_ERROR; 69348c2ecf20Sopenharmony_ci goto exit_setup; 69358c2ecf20Sopenharmony_ci } 69368c2ecf20Sopenharmony_ci 69378c2ecf20Sopenharmony_ci /* 69388c2ecf20Sopenharmony_ci * so calling module_put function to decrement the 69398c2ecf20Sopenharmony_ci * reference count. 69408c2ecf20Sopenharmony_ci **/ 69418c2ecf20Sopenharmony_ci module_put(qla4xxx_iscsi_transport.owner); 69428c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 69438c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 69448c2ecf20Sopenharmony_ci ddb_entry->sess = cls_sess; 69458c2ecf20Sopenharmony_ci 69468c2ecf20Sopenharmony_ci cls_sess->recovery_tmo = ql4xsess_recovery_tmo; 69478c2ecf20Sopenharmony_ci memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry, 69488c2ecf20Sopenharmony_ci sizeof(struct dev_db_entry)); 69498c2ecf20Sopenharmony_ci 69508c2ecf20Sopenharmony_ci qla4xxx_setup_flash_ddb_entry(ha, ddb_entry, idx); 69518c2ecf20Sopenharmony_ci 69528c2ecf20Sopenharmony_ci cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id); 69538c2ecf20Sopenharmony_ci 69548c2ecf20Sopenharmony_ci if (!cls_conn) { 69558c2ecf20Sopenharmony_ci ret = QLA_ERROR; 69568c2ecf20Sopenharmony_ci goto exit_setup; 69578c2ecf20Sopenharmony_ci } 69588c2ecf20Sopenharmony_ci 69598c2ecf20Sopenharmony_ci ddb_entry->conn = cls_conn; 69608c2ecf20Sopenharmony_ci 69618c2ecf20Sopenharmony_ci /* Setup ep, for displaying attributes in sysfs */ 69628c2ecf20Sopenharmony_ci ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry); 69638c2ecf20Sopenharmony_ci if (ep) { 69648c2ecf20Sopenharmony_ci ep->conn = cls_conn; 69658c2ecf20Sopenharmony_ci cls_conn->ep = ep; 69668c2ecf20Sopenharmony_ci } else { 69678c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n")); 69688c2ecf20Sopenharmony_ci ret = QLA_ERROR; 69698c2ecf20Sopenharmony_ci goto exit_setup; 69708c2ecf20Sopenharmony_ci } 69718c2ecf20Sopenharmony_ci 69728c2ecf20Sopenharmony_ci /* Update sess/conn params */ 69738c2ecf20Sopenharmony_ci qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); 69748c2ecf20Sopenharmony_ci qla4xxx_update_sess_disc_idx(ha, ddb_entry, fw_ddb_entry); 69758c2ecf20Sopenharmony_ci 69768c2ecf20Sopenharmony_ci if (is_reset == RESET_ADAPTER) { 69778c2ecf20Sopenharmony_ci iscsi_block_session(cls_sess); 69788c2ecf20Sopenharmony_ci /* Use the relogin path to discover new devices 69798c2ecf20Sopenharmony_ci * by short-circuting the logic of setting 69808c2ecf20Sopenharmony_ci * timer to relogin - instead set the flags 69818c2ecf20Sopenharmony_ci * to initiate login right away. 69828c2ecf20Sopenharmony_ci */ 69838c2ecf20Sopenharmony_ci set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); 69848c2ecf20Sopenharmony_ci set_bit(DF_RELOGIN, &ddb_entry->flags); 69858c2ecf20Sopenharmony_ci } 69868c2ecf20Sopenharmony_ci 69878c2ecf20Sopenharmony_ciexit_setup: 69888c2ecf20Sopenharmony_ci return ret; 69898c2ecf20Sopenharmony_ci} 69908c2ecf20Sopenharmony_ci 69918c2ecf20Sopenharmony_cistatic void qla4xxx_update_fw_ddb_link(struct scsi_qla_host *ha, 69928c2ecf20Sopenharmony_ci struct list_head *list_ddb, 69938c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry) 69948c2ecf20Sopenharmony_ci{ 69958c2ecf20Sopenharmony_ci struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; 69968c2ecf20Sopenharmony_ci uint16_t ddb_link; 69978c2ecf20Sopenharmony_ci 69988c2ecf20Sopenharmony_ci ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); 69998c2ecf20Sopenharmony_ci 70008c2ecf20Sopenharmony_ci list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) { 70018c2ecf20Sopenharmony_ci if (ddb_idx->fw_ddb_idx == ddb_link) { 70028c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 70038c2ecf20Sopenharmony_ci "Updating NT parent idx from [%d] to [%d]\n", 70048c2ecf20Sopenharmony_ci ddb_link, ddb_idx->flash_ddb_idx)); 70058c2ecf20Sopenharmony_ci fw_ddb_entry->ddb_link = 70068c2ecf20Sopenharmony_ci cpu_to_le16(ddb_idx->flash_ddb_idx); 70078c2ecf20Sopenharmony_ci return; 70088c2ecf20Sopenharmony_ci } 70098c2ecf20Sopenharmony_ci } 70108c2ecf20Sopenharmony_ci} 70118c2ecf20Sopenharmony_ci 70128c2ecf20Sopenharmony_cistatic void qla4xxx_build_nt_list(struct scsi_qla_host *ha, 70138c2ecf20Sopenharmony_ci struct list_head *list_nt, 70148c2ecf20Sopenharmony_ci struct list_head *list_st, 70158c2ecf20Sopenharmony_ci int is_reset) 70168c2ecf20Sopenharmony_ci{ 70178c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 70188c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = NULL; 70198c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_dma; 70208c2ecf20Sopenharmony_ci int max_ddbs; 70218c2ecf20Sopenharmony_ci int fw_idx_size; 70228c2ecf20Sopenharmony_ci int ret; 70238c2ecf20Sopenharmony_ci uint32_t idx = 0, next_idx = 0; 70248c2ecf20Sopenharmony_ci uint32_t state = 0, conn_err = 0; 70258c2ecf20Sopenharmony_ci uint32_t ddb_idx = -1; 70268c2ecf20Sopenharmony_ci uint16_t conn_id = 0; 70278c2ecf20Sopenharmony_ci uint16_t ddb_link = -1; 70288c2ecf20Sopenharmony_ci struct qla_ddb_index *nt_ddb_idx; 70298c2ecf20Sopenharmony_ci 70308c2ecf20Sopenharmony_ci fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, 70318c2ecf20Sopenharmony_ci &fw_ddb_dma); 70328c2ecf20Sopenharmony_ci if (fw_ddb_entry == NULL) { 70338c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); 70348c2ecf20Sopenharmony_ci goto exit_nt_list; 70358c2ecf20Sopenharmony_ci } 70368c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 70378c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 70388c2ecf20Sopenharmony_ci fw_idx_size = sizeof(struct qla_ddb_index); 70398c2ecf20Sopenharmony_ci 70408c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx = next_idx) { 70418c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, 70428c2ecf20Sopenharmony_ci NULL, &next_idx, &state, 70438c2ecf20Sopenharmony_ci &conn_err, NULL, &conn_id); 70448c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 70458c2ecf20Sopenharmony_ci break; 70468c2ecf20Sopenharmony_ci 70478c2ecf20Sopenharmony_ci if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS) 70488c2ecf20Sopenharmony_ci goto continue_next_nt; 70498c2ecf20Sopenharmony_ci 70508c2ecf20Sopenharmony_ci /* Check if NT, then add to list it */ 70518c2ecf20Sopenharmony_ci if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) 70528c2ecf20Sopenharmony_ci goto continue_next_nt; 70538c2ecf20Sopenharmony_ci 70548c2ecf20Sopenharmony_ci ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link); 70558c2ecf20Sopenharmony_ci if (ddb_link < max_ddbs) 70568c2ecf20Sopenharmony_ci qla4xxx_update_fw_ddb_link(ha, list_st, fw_ddb_entry); 70578c2ecf20Sopenharmony_ci 70588c2ecf20Sopenharmony_ci if (!(state == DDB_DS_NO_CONNECTION_ACTIVE || 70598c2ecf20Sopenharmony_ci state == DDB_DS_SESSION_FAILED) && 70608c2ecf20Sopenharmony_ci (is_reset == INIT_ADAPTER)) 70618c2ecf20Sopenharmony_ci goto continue_next_nt; 70628c2ecf20Sopenharmony_ci 70638c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 70648c2ecf20Sopenharmony_ci "Adding DDB to session = 0x%x\n", idx)); 70658c2ecf20Sopenharmony_ci 70668c2ecf20Sopenharmony_ci if (is_reset == INIT_ADAPTER) { 70678c2ecf20Sopenharmony_ci nt_ddb_idx = vmalloc(fw_idx_size); 70688c2ecf20Sopenharmony_ci if (!nt_ddb_idx) 70698c2ecf20Sopenharmony_ci break; 70708c2ecf20Sopenharmony_ci 70718c2ecf20Sopenharmony_ci nt_ddb_idx->fw_ddb_idx = idx; 70728c2ecf20Sopenharmony_ci 70738c2ecf20Sopenharmony_ci /* Copy original isid as it may get updated in function 70748c2ecf20Sopenharmony_ci * qla4xxx_update_isid(). We need original isid in 70758c2ecf20Sopenharmony_ci * function qla4xxx_compare_tuple_ddb to find duplicate 70768c2ecf20Sopenharmony_ci * target */ 70778c2ecf20Sopenharmony_ci memcpy(&nt_ddb_idx->flash_isid[0], 70788c2ecf20Sopenharmony_ci &fw_ddb_entry->isid[0], 70798c2ecf20Sopenharmony_ci sizeof(nt_ddb_idx->flash_isid)); 70808c2ecf20Sopenharmony_ci 70818c2ecf20Sopenharmony_ci ret = qla4xxx_is_flash_ddb_exists(ha, list_nt, 70828c2ecf20Sopenharmony_ci fw_ddb_entry); 70838c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS) { 70848c2ecf20Sopenharmony_ci /* free nt_ddb_idx and do not add to list_nt */ 70858c2ecf20Sopenharmony_ci vfree(nt_ddb_idx); 70868c2ecf20Sopenharmony_ci goto continue_next_nt; 70878c2ecf20Sopenharmony_ci } 70888c2ecf20Sopenharmony_ci 70898c2ecf20Sopenharmony_ci /* Copy updated isid */ 70908c2ecf20Sopenharmony_ci memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry, 70918c2ecf20Sopenharmony_ci sizeof(struct dev_db_entry)); 70928c2ecf20Sopenharmony_ci 70938c2ecf20Sopenharmony_ci list_add_tail(&nt_ddb_idx->list, list_nt); 70948c2ecf20Sopenharmony_ci } else if (is_reset == RESET_ADAPTER) { 70958c2ecf20Sopenharmony_ci ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, 70968c2ecf20Sopenharmony_ci &ddb_idx); 70978c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS) { 70988c2ecf20Sopenharmony_ci ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, 70998c2ecf20Sopenharmony_ci ddb_idx); 71008c2ecf20Sopenharmony_ci if (ddb_entry != NULL) 71018c2ecf20Sopenharmony_ci qla4xxx_update_sess_disc_idx(ha, 71028c2ecf20Sopenharmony_ci ddb_entry, 71038c2ecf20Sopenharmony_ci fw_ddb_entry); 71048c2ecf20Sopenharmony_ci goto continue_next_nt; 71058c2ecf20Sopenharmony_ci } 71068c2ecf20Sopenharmony_ci } 71078c2ecf20Sopenharmony_ci 71088c2ecf20Sopenharmony_ci ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx); 71098c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 71108c2ecf20Sopenharmony_ci goto exit_nt_list; 71118c2ecf20Sopenharmony_ci 71128c2ecf20Sopenharmony_cicontinue_next_nt: 71138c2ecf20Sopenharmony_ci if (next_idx == 0) 71148c2ecf20Sopenharmony_ci break; 71158c2ecf20Sopenharmony_ci } 71168c2ecf20Sopenharmony_ci 71178c2ecf20Sopenharmony_ciexit_nt_list: 71188c2ecf20Sopenharmony_ci if (fw_ddb_entry) 71198c2ecf20Sopenharmony_ci dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); 71208c2ecf20Sopenharmony_ci} 71218c2ecf20Sopenharmony_ci 71228c2ecf20Sopenharmony_cistatic void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, 71238c2ecf20Sopenharmony_ci struct list_head *list_nt, 71248c2ecf20Sopenharmony_ci uint16_t target_id) 71258c2ecf20Sopenharmony_ci{ 71268c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry; 71278c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_dma; 71288c2ecf20Sopenharmony_ci int max_ddbs; 71298c2ecf20Sopenharmony_ci int fw_idx_size; 71308c2ecf20Sopenharmony_ci int ret; 71318c2ecf20Sopenharmony_ci uint32_t idx = 0, next_idx = 0; 71328c2ecf20Sopenharmony_ci uint32_t state = 0, conn_err = 0; 71338c2ecf20Sopenharmony_ci uint16_t conn_id = 0; 71348c2ecf20Sopenharmony_ci struct qla_ddb_index *nt_ddb_idx; 71358c2ecf20Sopenharmony_ci 71368c2ecf20Sopenharmony_ci fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, 71378c2ecf20Sopenharmony_ci &fw_ddb_dma); 71388c2ecf20Sopenharmony_ci if (fw_ddb_entry == NULL) { 71398c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); 71408c2ecf20Sopenharmony_ci goto exit_new_nt_list; 71418c2ecf20Sopenharmony_ci } 71428c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 71438c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 71448c2ecf20Sopenharmony_ci fw_idx_size = sizeof(struct qla_ddb_index); 71458c2ecf20Sopenharmony_ci 71468c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx = next_idx) { 71478c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, 71488c2ecf20Sopenharmony_ci NULL, &next_idx, &state, 71498c2ecf20Sopenharmony_ci &conn_err, NULL, &conn_id); 71508c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 71518c2ecf20Sopenharmony_ci break; 71528c2ecf20Sopenharmony_ci 71538c2ecf20Sopenharmony_ci /* Check if NT, then add it to list */ 71548c2ecf20Sopenharmony_ci if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) 71558c2ecf20Sopenharmony_ci goto continue_next_new_nt; 71568c2ecf20Sopenharmony_ci 71578c2ecf20Sopenharmony_ci if (!(state == DDB_DS_NO_CONNECTION_ACTIVE)) 71588c2ecf20Sopenharmony_ci goto continue_next_new_nt; 71598c2ecf20Sopenharmony_ci 71608c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 71618c2ecf20Sopenharmony_ci "Adding DDB to session = 0x%x\n", idx)); 71628c2ecf20Sopenharmony_ci 71638c2ecf20Sopenharmony_ci nt_ddb_idx = vmalloc(fw_idx_size); 71648c2ecf20Sopenharmony_ci if (!nt_ddb_idx) 71658c2ecf20Sopenharmony_ci break; 71668c2ecf20Sopenharmony_ci 71678c2ecf20Sopenharmony_ci nt_ddb_idx->fw_ddb_idx = idx; 71688c2ecf20Sopenharmony_ci 71698c2ecf20Sopenharmony_ci ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL); 71708c2ecf20Sopenharmony_ci if (ret == QLA_SUCCESS) { 71718c2ecf20Sopenharmony_ci /* free nt_ddb_idx and do not add to list_nt */ 71728c2ecf20Sopenharmony_ci vfree(nt_ddb_idx); 71738c2ecf20Sopenharmony_ci goto continue_next_new_nt; 71748c2ecf20Sopenharmony_ci } 71758c2ecf20Sopenharmony_ci 71768c2ecf20Sopenharmony_ci if (target_id < max_ddbs) 71778c2ecf20Sopenharmony_ci fw_ddb_entry->ddb_link = cpu_to_le16(target_id); 71788c2ecf20Sopenharmony_ci 71798c2ecf20Sopenharmony_ci list_add_tail(&nt_ddb_idx->list, list_nt); 71808c2ecf20Sopenharmony_ci 71818c2ecf20Sopenharmony_ci ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, 71828c2ecf20Sopenharmony_ci idx); 71838c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 71848c2ecf20Sopenharmony_ci goto exit_new_nt_list; 71858c2ecf20Sopenharmony_ci 71868c2ecf20Sopenharmony_cicontinue_next_new_nt: 71878c2ecf20Sopenharmony_ci if (next_idx == 0) 71888c2ecf20Sopenharmony_ci break; 71898c2ecf20Sopenharmony_ci } 71908c2ecf20Sopenharmony_ci 71918c2ecf20Sopenharmony_ciexit_new_nt_list: 71928c2ecf20Sopenharmony_ci if (fw_ddb_entry) 71938c2ecf20Sopenharmony_ci dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); 71948c2ecf20Sopenharmony_ci} 71958c2ecf20Sopenharmony_ci 71968c2ecf20Sopenharmony_ci/** 71978c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_is_non_persistent - check for non-persistence of ddb entry 71988c2ecf20Sopenharmony_ci * @dev: dev associated with the sysfs entry 71998c2ecf20Sopenharmony_ci * @data: pointer to flashnode session object 72008c2ecf20Sopenharmony_ci * 72018c2ecf20Sopenharmony_ci * Returns: 72028c2ecf20Sopenharmony_ci * 1: if flashnode entry is non-persistent 72038c2ecf20Sopenharmony_ci * 0: if flashnode entry is persistent 72048c2ecf20Sopenharmony_ci **/ 72058c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data) 72068c2ecf20Sopenharmony_ci{ 72078c2ecf20Sopenharmony_ci struct iscsi_bus_flash_session *fnode_sess; 72088c2ecf20Sopenharmony_ci 72098c2ecf20Sopenharmony_ci if (!iscsi_flashnode_bus_match(dev, NULL)) 72108c2ecf20Sopenharmony_ci return 0; 72118c2ecf20Sopenharmony_ci 72128c2ecf20Sopenharmony_ci fnode_sess = iscsi_dev_to_flash_session(dev); 72138c2ecf20Sopenharmony_ci 72148c2ecf20Sopenharmony_ci return (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT); 72158c2ecf20Sopenharmony_ci} 72168c2ecf20Sopenharmony_ci 72178c2ecf20Sopenharmony_ci/** 72188c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_tgt_create - Create sysfs entry for target 72198c2ecf20Sopenharmony_ci * @ha: pointer to host 72208c2ecf20Sopenharmony_ci * @fw_ddb_entry: flash ddb data 72218c2ecf20Sopenharmony_ci * @idx: target index 72228c2ecf20Sopenharmony_ci * @user: if set then this call is made from userland else from kernel 72238c2ecf20Sopenharmony_ci * 72248c2ecf20Sopenharmony_ci * Returns: 72258c2ecf20Sopenharmony_ci * On sucess: QLA_SUCCESS 72268c2ecf20Sopenharmony_ci * On failure: QLA_ERROR 72278c2ecf20Sopenharmony_ci * 72288c2ecf20Sopenharmony_ci * This create separate sysfs entries for session and connection attributes of 72298c2ecf20Sopenharmony_ci * the given fw ddb entry. 72308c2ecf20Sopenharmony_ci * If this is invoked as a result of a userspace call then the entry is marked 72318c2ecf20Sopenharmony_ci * as nonpersistent using flash_state field. 72328c2ecf20Sopenharmony_ci **/ 72338c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, 72348c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 72358c2ecf20Sopenharmony_ci uint16_t *idx, int user) 72368c2ecf20Sopenharmony_ci{ 72378c2ecf20Sopenharmony_ci struct iscsi_bus_flash_session *fnode_sess = NULL; 72388c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn = NULL; 72398c2ecf20Sopenharmony_ci int rc = QLA_ERROR; 72408c2ecf20Sopenharmony_ci 72418c2ecf20Sopenharmony_ci fnode_sess = iscsi_create_flashnode_sess(ha->host, *idx, 72428c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 0); 72438c2ecf20Sopenharmony_ci if (!fnode_sess) { 72448c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 72458c2ecf20Sopenharmony_ci "%s: Unable to create session sysfs entry for flashnode %d of host%lu\n", 72468c2ecf20Sopenharmony_ci __func__, *idx, ha->host_no); 72478c2ecf20Sopenharmony_ci goto exit_tgt_create; 72488c2ecf20Sopenharmony_ci } 72498c2ecf20Sopenharmony_ci 72508c2ecf20Sopenharmony_ci fnode_conn = iscsi_create_flashnode_conn(ha->host, fnode_sess, 72518c2ecf20Sopenharmony_ci &qla4xxx_iscsi_transport, 0); 72528c2ecf20Sopenharmony_ci if (!fnode_conn) { 72538c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 72548c2ecf20Sopenharmony_ci "%s: Unable to create conn sysfs entry for flashnode %d of host%lu\n", 72558c2ecf20Sopenharmony_ci __func__, *idx, ha->host_no); 72568c2ecf20Sopenharmony_ci goto free_sess; 72578c2ecf20Sopenharmony_ci } 72588c2ecf20Sopenharmony_ci 72598c2ecf20Sopenharmony_ci if (user) { 72608c2ecf20Sopenharmony_ci fnode_sess->flash_state = DEV_DB_NON_PERSISTENT; 72618c2ecf20Sopenharmony_ci } else { 72628c2ecf20Sopenharmony_ci fnode_sess->flash_state = DEV_DB_PERSISTENT; 72638c2ecf20Sopenharmony_ci 72648c2ecf20Sopenharmony_ci if (*idx == ha->pri_ddb_idx || *idx == ha->sec_ddb_idx) 72658c2ecf20Sopenharmony_ci fnode_sess->is_boot_target = 1; 72668c2ecf20Sopenharmony_ci else 72678c2ecf20Sopenharmony_ci fnode_sess->is_boot_target = 0; 72688c2ecf20Sopenharmony_ci } 72698c2ecf20Sopenharmony_ci 72708c2ecf20Sopenharmony_ci rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn, 72718c2ecf20Sopenharmony_ci fw_ddb_entry); 72728c2ecf20Sopenharmony_ci if (rc) 72738c2ecf20Sopenharmony_ci goto free_sess; 72748c2ecf20Sopenharmony_ci 72758c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", 72768c2ecf20Sopenharmony_ci __func__, fnode_sess->dev.kobj.name); 72778c2ecf20Sopenharmony_ci 72788c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", 72798c2ecf20Sopenharmony_ci __func__, fnode_conn->dev.kobj.name); 72808c2ecf20Sopenharmony_ci 72818c2ecf20Sopenharmony_ci return QLA_SUCCESS; 72828c2ecf20Sopenharmony_ci 72838c2ecf20Sopenharmony_cifree_sess: 72848c2ecf20Sopenharmony_ci iscsi_destroy_flashnode_sess(fnode_sess); 72858c2ecf20Sopenharmony_ci 72868c2ecf20Sopenharmony_ciexit_tgt_create: 72878c2ecf20Sopenharmony_ci return QLA_ERROR; 72888c2ecf20Sopenharmony_ci} 72898c2ecf20Sopenharmony_ci 72908c2ecf20Sopenharmony_ci/** 72918c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_add - Add new ddb entry in flash 72928c2ecf20Sopenharmony_ci * @shost: pointer to host 72938c2ecf20Sopenharmony_ci * @buf: type of ddb entry (ipv4/ipv6) 72948c2ecf20Sopenharmony_ci * @len: length of buf 72958c2ecf20Sopenharmony_ci * 72968c2ecf20Sopenharmony_ci * This creates new ddb entry in the flash by finding first free index and 72978c2ecf20Sopenharmony_ci * storing default ddb there. And then create sysfs entry for the new ddb entry. 72988c2ecf20Sopenharmony_ci **/ 72998c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, 73008c2ecf20Sopenharmony_ci int len) 73018c2ecf20Sopenharmony_ci{ 73028c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 73038c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 73048c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 73058c2ecf20Sopenharmony_ci struct device *dev; 73068c2ecf20Sopenharmony_ci uint16_t idx = 0; 73078c2ecf20Sopenharmony_ci uint16_t max_ddbs = 0; 73088c2ecf20Sopenharmony_ci uint32_t options = 0; 73098c2ecf20Sopenharmony_ci uint32_t rval = QLA_ERROR; 73108c2ecf20Sopenharmony_ci 73118c2ecf20Sopenharmony_ci if (strncasecmp(PORTAL_TYPE_IPV4, buf, 4) && 73128c2ecf20Sopenharmony_ci strncasecmp(PORTAL_TYPE_IPV6, buf, 4)) { 73138c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Invalid portal type\n", 73148c2ecf20Sopenharmony_ci __func__)); 73158c2ecf20Sopenharmony_ci goto exit_ddb_add; 73168c2ecf20Sopenharmony_ci } 73178c2ecf20Sopenharmony_ci 73188c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : 73198c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 73208c2ecf20Sopenharmony_ci 73218c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 73228c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 73238c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 73248c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 73258c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 73268c2ecf20Sopenharmony_ci __func__)); 73278c2ecf20Sopenharmony_ci goto exit_ddb_add; 73288c2ecf20Sopenharmony_ci } 73298c2ecf20Sopenharmony_ci 73308c2ecf20Sopenharmony_ci dev = iscsi_find_flashnode_sess(ha->host, NULL, 73318c2ecf20Sopenharmony_ci qla4xxx_sysfs_ddb_is_non_persistent); 73328c2ecf20Sopenharmony_ci if (dev) { 73338c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 73348c2ecf20Sopenharmony_ci "%s: A non-persistent entry %s found\n", 73358c2ecf20Sopenharmony_ci __func__, dev->kobj.name); 73368c2ecf20Sopenharmony_ci put_device(dev); 73378c2ecf20Sopenharmony_ci goto exit_ddb_add; 73388c2ecf20Sopenharmony_ci } 73398c2ecf20Sopenharmony_ci 73408c2ecf20Sopenharmony_ci /* Index 0 and 1 are reserved for boot target entries */ 73418c2ecf20Sopenharmony_ci for (idx = 2; idx < max_ddbs; idx++) { 73428c2ecf20Sopenharmony_ci if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, 73438c2ecf20Sopenharmony_ci fw_ddb_entry_dma, idx)) 73448c2ecf20Sopenharmony_ci break; 73458c2ecf20Sopenharmony_ci } 73468c2ecf20Sopenharmony_ci 73478c2ecf20Sopenharmony_ci if (idx == max_ddbs) 73488c2ecf20Sopenharmony_ci goto exit_ddb_add; 73498c2ecf20Sopenharmony_ci 73508c2ecf20Sopenharmony_ci if (!strncasecmp("ipv6", buf, 4)) 73518c2ecf20Sopenharmony_ci options |= IPV6_DEFAULT_DDB_ENTRY; 73528c2ecf20Sopenharmony_ci 73538c2ecf20Sopenharmony_ci rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); 73548c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) 73558c2ecf20Sopenharmony_ci goto exit_ddb_add; 73568c2ecf20Sopenharmony_ci 73578c2ecf20Sopenharmony_ci rval = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 1); 73588c2ecf20Sopenharmony_ci 73598c2ecf20Sopenharmony_ciexit_ddb_add: 73608c2ecf20Sopenharmony_ci if (fw_ddb_entry) 73618c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 73628c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 73638c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) 73648c2ecf20Sopenharmony_ci return idx; 73658c2ecf20Sopenharmony_ci else 73668c2ecf20Sopenharmony_ci return -EIO; 73678c2ecf20Sopenharmony_ci} 73688c2ecf20Sopenharmony_ci 73698c2ecf20Sopenharmony_ci/** 73708c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_apply - write the target ddb contents to Flash 73718c2ecf20Sopenharmony_ci * @fnode_sess: pointer to session attrs of flash ddb entry 73728c2ecf20Sopenharmony_ci * @fnode_conn: pointer to connection attrs of flash ddb entry 73738c2ecf20Sopenharmony_ci * 73748c2ecf20Sopenharmony_ci * This writes the contents of target ddb buffer to Flash with a valid cookie 73758c2ecf20Sopenharmony_ci * value in order to make the ddb entry persistent. 73768c2ecf20Sopenharmony_ci **/ 73778c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_apply(struct iscsi_bus_flash_session *fnode_sess, 73788c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn) 73798c2ecf20Sopenharmony_ci{ 73808c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); 73818c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 73828c2ecf20Sopenharmony_ci uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO; 73838c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 73848c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 73858c2ecf20Sopenharmony_ci uint32_t options = 0; 73868c2ecf20Sopenharmony_ci int rval = 0; 73878c2ecf20Sopenharmony_ci 73888c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 73898c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 73908c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 73918c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 73928c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 73938c2ecf20Sopenharmony_ci __func__)); 73948c2ecf20Sopenharmony_ci rval = -ENOMEM; 73958c2ecf20Sopenharmony_ci goto exit_ddb_apply; 73968c2ecf20Sopenharmony_ci } 73978c2ecf20Sopenharmony_ci 73988c2ecf20Sopenharmony_ci if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 73998c2ecf20Sopenharmony_ci options |= IPV6_DEFAULT_DDB_ENTRY; 74008c2ecf20Sopenharmony_ci 74018c2ecf20Sopenharmony_ci rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); 74028c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) 74038c2ecf20Sopenharmony_ci goto exit_ddb_apply; 74048c2ecf20Sopenharmony_ci 74058c2ecf20Sopenharmony_ci dev_db_start_offset += (fnode_sess->target_id * 74068c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry)); 74078c2ecf20Sopenharmony_ci 74088c2ecf20Sopenharmony_ci qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); 74098c2ecf20Sopenharmony_ci fw_ddb_entry->cookie = DDB_VALID_COOKIE; 74108c2ecf20Sopenharmony_ci 74118c2ecf20Sopenharmony_ci rval = qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 74128c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry), FLASH_OPT_RMW_COMMIT); 74138c2ecf20Sopenharmony_ci 74148c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) { 74158c2ecf20Sopenharmony_ci fnode_sess->flash_state = DEV_DB_PERSISTENT; 74168c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 74178c2ecf20Sopenharmony_ci "%s: flash node %u of host %lu written to flash\n", 74188c2ecf20Sopenharmony_ci __func__, fnode_sess->target_id, ha->host_no); 74198c2ecf20Sopenharmony_ci } else { 74208c2ecf20Sopenharmony_ci rval = -EIO; 74218c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 74228c2ecf20Sopenharmony_ci "%s: Error while writing flash node %u of host %lu to flash\n", 74238c2ecf20Sopenharmony_ci __func__, fnode_sess->target_id, ha->host_no); 74248c2ecf20Sopenharmony_ci } 74258c2ecf20Sopenharmony_ci 74268c2ecf20Sopenharmony_ciexit_ddb_apply: 74278c2ecf20Sopenharmony_ci if (fw_ddb_entry) 74288c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 74298c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 74308c2ecf20Sopenharmony_ci return rval; 74318c2ecf20Sopenharmony_ci} 74328c2ecf20Sopenharmony_ci 74338c2ecf20Sopenharmony_cistatic ssize_t qla4xxx_sysfs_ddb_conn_open(struct scsi_qla_host *ha, 74348c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 74358c2ecf20Sopenharmony_ci uint16_t idx) 74368c2ecf20Sopenharmony_ci{ 74378c2ecf20Sopenharmony_ci struct dev_db_entry *ddb_entry = NULL; 74388c2ecf20Sopenharmony_ci dma_addr_t ddb_entry_dma; 74398c2ecf20Sopenharmony_ci unsigned long wtime; 74408c2ecf20Sopenharmony_ci uint32_t mbx_sts = 0; 74418c2ecf20Sopenharmony_ci uint32_t state = 0, conn_err = 0; 74428c2ecf20Sopenharmony_ci uint16_t tmo = 0; 74438c2ecf20Sopenharmony_ci int ret = 0; 74448c2ecf20Sopenharmony_ci 74458c2ecf20Sopenharmony_ci ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*ddb_entry), 74468c2ecf20Sopenharmony_ci &ddb_entry_dma, GFP_KERNEL); 74478c2ecf20Sopenharmony_ci if (!ddb_entry) { 74488c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 74498c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 74508c2ecf20Sopenharmony_ci __func__)); 74518c2ecf20Sopenharmony_ci return QLA_ERROR; 74528c2ecf20Sopenharmony_ci } 74538c2ecf20Sopenharmony_ci 74548c2ecf20Sopenharmony_ci memcpy(ddb_entry, fw_ddb_entry, sizeof(*ddb_entry)); 74558c2ecf20Sopenharmony_ci 74568c2ecf20Sopenharmony_ci ret = qla4xxx_set_ddb_entry(ha, idx, ddb_entry_dma, &mbx_sts); 74578c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 74588c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 74598c2ecf20Sopenharmony_ci "%s: Unable to set ddb entry for index %d\n", 74608c2ecf20Sopenharmony_ci __func__, idx)); 74618c2ecf20Sopenharmony_ci goto exit_ddb_conn_open; 74628c2ecf20Sopenharmony_ci } 74638c2ecf20Sopenharmony_ci 74648c2ecf20Sopenharmony_ci qla4xxx_conn_open(ha, idx); 74658c2ecf20Sopenharmony_ci 74668c2ecf20Sopenharmony_ci /* To ensure that sendtargets is done, wait for at least 12 secs */ 74678c2ecf20Sopenharmony_ci tmo = ((ha->def_timeout > LOGIN_TOV) && 74688c2ecf20Sopenharmony_ci (ha->def_timeout < LOGIN_TOV * 10) ? 74698c2ecf20Sopenharmony_ci ha->def_timeout : LOGIN_TOV); 74708c2ecf20Sopenharmony_ci 74718c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 74728c2ecf20Sopenharmony_ci "Default time to wait for login to ddb %d\n", tmo)); 74738c2ecf20Sopenharmony_ci 74748c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * tmo); 74758c2ecf20Sopenharmony_ci do { 74768c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, 74778c2ecf20Sopenharmony_ci NULL, &state, &conn_err, NULL, 74788c2ecf20Sopenharmony_ci NULL); 74798c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 74808c2ecf20Sopenharmony_ci continue; 74818c2ecf20Sopenharmony_ci 74828c2ecf20Sopenharmony_ci if (state == DDB_DS_NO_CONNECTION_ACTIVE || 74838c2ecf20Sopenharmony_ci state == DDB_DS_SESSION_FAILED) 74848c2ecf20Sopenharmony_ci break; 74858c2ecf20Sopenharmony_ci 74868c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ / 10); 74878c2ecf20Sopenharmony_ci } while (time_after(wtime, jiffies)); 74888c2ecf20Sopenharmony_ci 74898c2ecf20Sopenharmony_ciexit_ddb_conn_open: 74908c2ecf20Sopenharmony_ci if (ddb_entry) 74918c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*ddb_entry), 74928c2ecf20Sopenharmony_ci ddb_entry, ddb_entry_dma); 74938c2ecf20Sopenharmony_ci return ret; 74948c2ecf20Sopenharmony_ci} 74958c2ecf20Sopenharmony_ci 74968c2ecf20Sopenharmony_cistatic int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, 74978c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 74988c2ecf20Sopenharmony_ci uint16_t target_id) 74998c2ecf20Sopenharmony_ci{ 75008c2ecf20Sopenharmony_ci struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; 75018c2ecf20Sopenharmony_ci struct list_head list_nt; 75028c2ecf20Sopenharmony_ci uint16_t ddb_index; 75038c2ecf20Sopenharmony_ci int ret = 0; 75048c2ecf20Sopenharmony_ci 75058c2ecf20Sopenharmony_ci if (test_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags)) { 75068c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 75078c2ecf20Sopenharmony_ci "%s: A discovery already in progress!\n", __func__); 75088c2ecf20Sopenharmony_ci return QLA_ERROR; 75098c2ecf20Sopenharmony_ci } 75108c2ecf20Sopenharmony_ci 75118c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&list_nt); 75128c2ecf20Sopenharmony_ci 75138c2ecf20Sopenharmony_ci set_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags); 75148c2ecf20Sopenharmony_ci 75158c2ecf20Sopenharmony_ci ret = qla4xxx_get_ddb_index(ha, &ddb_index); 75168c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 75178c2ecf20Sopenharmony_ci goto exit_login_st_clr_bit; 75188c2ecf20Sopenharmony_ci 75198c2ecf20Sopenharmony_ci ret = qla4xxx_sysfs_ddb_conn_open(ha, fw_ddb_entry, ddb_index); 75208c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 75218c2ecf20Sopenharmony_ci goto exit_login_st; 75228c2ecf20Sopenharmony_ci 75238c2ecf20Sopenharmony_ci qla4xxx_build_new_nt_list(ha, &list_nt, target_id); 75248c2ecf20Sopenharmony_ci 75258c2ecf20Sopenharmony_ci list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { 75268c2ecf20Sopenharmony_ci list_del_init(&ddb_idx->list); 75278c2ecf20Sopenharmony_ci qla4xxx_clear_ddb_entry(ha, ddb_idx->fw_ddb_idx); 75288c2ecf20Sopenharmony_ci vfree(ddb_idx); 75298c2ecf20Sopenharmony_ci } 75308c2ecf20Sopenharmony_ci 75318c2ecf20Sopenharmony_ciexit_login_st: 75328c2ecf20Sopenharmony_ci if (qla4xxx_clear_ddb_entry(ha, ddb_index) == QLA_ERROR) { 75338c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 75348c2ecf20Sopenharmony_ci "Unable to clear DDB index = 0x%x\n", ddb_index); 75358c2ecf20Sopenharmony_ci } 75368c2ecf20Sopenharmony_ci 75378c2ecf20Sopenharmony_ci clear_bit(ddb_index, ha->ddb_idx_map); 75388c2ecf20Sopenharmony_ci 75398c2ecf20Sopenharmony_ciexit_login_st_clr_bit: 75408c2ecf20Sopenharmony_ci clear_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags); 75418c2ecf20Sopenharmony_ci return ret; 75428c2ecf20Sopenharmony_ci} 75438c2ecf20Sopenharmony_ci 75448c2ecf20Sopenharmony_cistatic int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha, 75458c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry, 75468c2ecf20Sopenharmony_ci uint16_t idx) 75478c2ecf20Sopenharmony_ci{ 75488c2ecf20Sopenharmony_ci int ret = QLA_ERROR; 75498c2ecf20Sopenharmony_ci 75508c2ecf20Sopenharmony_ci ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL); 75518c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) 75528c2ecf20Sopenharmony_ci ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, 75538c2ecf20Sopenharmony_ci idx); 75548c2ecf20Sopenharmony_ci else 75558c2ecf20Sopenharmony_ci ret = -EPERM; 75568c2ecf20Sopenharmony_ci 75578c2ecf20Sopenharmony_ci return ret; 75588c2ecf20Sopenharmony_ci} 75598c2ecf20Sopenharmony_ci 75608c2ecf20Sopenharmony_ci/** 75618c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_login - Login to the specified target 75628c2ecf20Sopenharmony_ci * @fnode_sess: pointer to session attrs of flash ddb entry 75638c2ecf20Sopenharmony_ci * @fnode_conn: pointer to connection attrs of flash ddb entry 75648c2ecf20Sopenharmony_ci * 75658c2ecf20Sopenharmony_ci * This logs in to the specified target 75668c2ecf20Sopenharmony_ci **/ 75678c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, 75688c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn) 75698c2ecf20Sopenharmony_ci{ 75708c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); 75718c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 75728c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 75738c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 75748c2ecf20Sopenharmony_ci uint32_t options = 0; 75758c2ecf20Sopenharmony_ci int ret = 0; 75768c2ecf20Sopenharmony_ci 75778c2ecf20Sopenharmony_ci if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) { 75788c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 75798c2ecf20Sopenharmony_ci "%s: Target info is not persistent\n", __func__); 75808c2ecf20Sopenharmony_ci ret = -EIO; 75818c2ecf20Sopenharmony_ci goto exit_ddb_login; 75828c2ecf20Sopenharmony_ci } 75838c2ecf20Sopenharmony_ci 75848c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 75858c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 75868c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 75878c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 75888c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 75898c2ecf20Sopenharmony_ci __func__)); 75908c2ecf20Sopenharmony_ci ret = -ENOMEM; 75918c2ecf20Sopenharmony_ci goto exit_ddb_login; 75928c2ecf20Sopenharmony_ci } 75938c2ecf20Sopenharmony_ci 75948c2ecf20Sopenharmony_ci if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 75958c2ecf20Sopenharmony_ci options |= IPV6_DEFAULT_DDB_ENTRY; 75968c2ecf20Sopenharmony_ci 75978c2ecf20Sopenharmony_ci ret = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); 75988c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 75998c2ecf20Sopenharmony_ci goto exit_ddb_login; 76008c2ecf20Sopenharmony_ci 76018c2ecf20Sopenharmony_ci qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); 76028c2ecf20Sopenharmony_ci fw_ddb_entry->cookie = DDB_VALID_COOKIE; 76038c2ecf20Sopenharmony_ci 76048c2ecf20Sopenharmony_ci if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) 76058c2ecf20Sopenharmony_ci ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry, 76068c2ecf20Sopenharmony_ci fnode_sess->target_id); 76078c2ecf20Sopenharmony_ci else 76088c2ecf20Sopenharmony_ci ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, 76098c2ecf20Sopenharmony_ci fnode_sess->target_id); 76108c2ecf20Sopenharmony_ci 76118c2ecf20Sopenharmony_ci if (ret > 0) 76128c2ecf20Sopenharmony_ci ret = -EIO; 76138c2ecf20Sopenharmony_ci 76148c2ecf20Sopenharmony_ciexit_ddb_login: 76158c2ecf20Sopenharmony_ci if (fw_ddb_entry) 76168c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 76178c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 76188c2ecf20Sopenharmony_ci return ret; 76198c2ecf20Sopenharmony_ci} 76208c2ecf20Sopenharmony_ci 76218c2ecf20Sopenharmony_ci/** 76228c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_logout_sid - Logout session for the specified target 76238c2ecf20Sopenharmony_ci * @cls_sess: pointer to session to be logged out 76248c2ecf20Sopenharmony_ci * 76258c2ecf20Sopenharmony_ci * This performs session log out from the specified target 76268c2ecf20Sopenharmony_ci **/ 76278c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess) 76288c2ecf20Sopenharmony_ci{ 76298c2ecf20Sopenharmony_ci struct iscsi_session *sess; 76308c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = NULL; 76318c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 76328c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 76338c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 76348c2ecf20Sopenharmony_ci unsigned long flags; 76358c2ecf20Sopenharmony_ci unsigned long wtime; 76368c2ecf20Sopenharmony_ci uint32_t ddb_state; 76378c2ecf20Sopenharmony_ci int options; 76388c2ecf20Sopenharmony_ci int ret = 0; 76398c2ecf20Sopenharmony_ci 76408c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 76418c2ecf20Sopenharmony_ci ddb_entry = sess->dd_data; 76428c2ecf20Sopenharmony_ci ha = ddb_entry->ha; 76438c2ecf20Sopenharmony_ci 76448c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type != FLASH_DDB) { 76458c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Not a flash node session\n", 76468c2ecf20Sopenharmony_ci __func__); 76478c2ecf20Sopenharmony_ci ret = -ENXIO; 76488c2ecf20Sopenharmony_ci goto exit_ddb_logout; 76498c2ecf20Sopenharmony_ci } 76508c2ecf20Sopenharmony_ci 76518c2ecf20Sopenharmony_ci if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) { 76528c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 76538c2ecf20Sopenharmony_ci "%s: Logout from boot target entry is not permitted.\n", 76548c2ecf20Sopenharmony_ci __func__); 76558c2ecf20Sopenharmony_ci ret = -EPERM; 76568c2ecf20Sopenharmony_ci goto exit_ddb_logout; 76578c2ecf20Sopenharmony_ci } 76588c2ecf20Sopenharmony_ci 76598c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 76608c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 76618c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 76628c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 76638c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 76648c2ecf20Sopenharmony_ci ret = -ENOMEM; 76658c2ecf20Sopenharmony_ci goto exit_ddb_logout; 76668c2ecf20Sopenharmony_ci } 76678c2ecf20Sopenharmony_ci 76688c2ecf20Sopenharmony_ci if (test_and_set_bit(DF_DISABLE_RELOGIN, &ddb_entry->flags)) 76698c2ecf20Sopenharmony_ci goto ddb_logout_init; 76708c2ecf20Sopenharmony_ci 76718c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, 76728c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma, 76738c2ecf20Sopenharmony_ci NULL, NULL, &ddb_state, NULL, 76748c2ecf20Sopenharmony_ci NULL, NULL); 76758c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 76768c2ecf20Sopenharmony_ci goto ddb_logout_init; 76778c2ecf20Sopenharmony_ci 76788c2ecf20Sopenharmony_ci if (ddb_state == DDB_DS_SESSION_ACTIVE) 76798c2ecf20Sopenharmony_ci goto ddb_logout_init; 76808c2ecf20Sopenharmony_ci 76818c2ecf20Sopenharmony_ci /* wait until next relogin is triggered using DF_RELOGIN and 76828c2ecf20Sopenharmony_ci * clear DF_RELOGIN to avoid invocation of further relogin 76838c2ecf20Sopenharmony_ci */ 76848c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * RELOGIN_TOV); 76858c2ecf20Sopenharmony_ci do { 76868c2ecf20Sopenharmony_ci if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags)) 76878c2ecf20Sopenharmony_ci goto ddb_logout_init; 76888c2ecf20Sopenharmony_ci 76898c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ); 76908c2ecf20Sopenharmony_ci } while ((time_after(wtime, jiffies))); 76918c2ecf20Sopenharmony_ci 76928c2ecf20Sopenharmony_ciddb_logout_init: 76938c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); 76948c2ecf20Sopenharmony_ci atomic_set(&ddb_entry->relogin_timer, 0); 76958c2ecf20Sopenharmony_ci 76968c2ecf20Sopenharmony_ci options = LOGOUT_OPTION_CLOSE_SESSION; 76978c2ecf20Sopenharmony_ci qla4xxx_session_logout_ddb(ha, ddb_entry, options); 76988c2ecf20Sopenharmony_ci 76998c2ecf20Sopenharmony_ci memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); 77008c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * LOGOUT_TOV); 77018c2ecf20Sopenharmony_ci do { 77028c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, 77038c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma, 77048c2ecf20Sopenharmony_ci NULL, NULL, &ddb_state, NULL, 77058c2ecf20Sopenharmony_ci NULL, NULL); 77068c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 77078c2ecf20Sopenharmony_ci goto ddb_logout_clr_sess; 77088c2ecf20Sopenharmony_ci 77098c2ecf20Sopenharmony_ci if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || 77108c2ecf20Sopenharmony_ci (ddb_state == DDB_DS_SESSION_FAILED)) 77118c2ecf20Sopenharmony_ci goto ddb_logout_clr_sess; 77128c2ecf20Sopenharmony_ci 77138c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ); 77148c2ecf20Sopenharmony_ci } while ((time_after(wtime, jiffies))); 77158c2ecf20Sopenharmony_ci 77168c2ecf20Sopenharmony_ciddb_logout_clr_sess: 77178c2ecf20Sopenharmony_ci qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); 77188c2ecf20Sopenharmony_ci /* 77198c2ecf20Sopenharmony_ci * we have decremented the reference count of the driver 77208c2ecf20Sopenharmony_ci * when we setup the session to have the driver unload 77218c2ecf20Sopenharmony_ci * to be seamless without actually destroying the 77228c2ecf20Sopenharmony_ci * session 77238c2ecf20Sopenharmony_ci **/ 77248c2ecf20Sopenharmony_ci try_module_get(qla4xxx_iscsi_transport.owner); 77258c2ecf20Sopenharmony_ci iscsi_destroy_endpoint(ddb_entry->conn->ep); 77268c2ecf20Sopenharmony_ci 77278c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 77288c2ecf20Sopenharmony_ci qla4xxx_free_ddb(ha, ddb_entry); 77298c2ecf20Sopenharmony_ci clear_bit(ddb_entry->fw_ddb_index, ha->ddb_idx_map); 77308c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 77318c2ecf20Sopenharmony_ci 77328c2ecf20Sopenharmony_ci iscsi_session_teardown(ddb_entry->sess); 77338c2ecf20Sopenharmony_ci 77348c2ecf20Sopenharmony_ci clear_bit(DF_DISABLE_RELOGIN, &ddb_entry->flags); 77358c2ecf20Sopenharmony_ci ret = QLA_SUCCESS; 77368c2ecf20Sopenharmony_ci 77378c2ecf20Sopenharmony_ciexit_ddb_logout: 77388c2ecf20Sopenharmony_ci if (fw_ddb_entry) 77398c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 77408c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 77418c2ecf20Sopenharmony_ci return ret; 77428c2ecf20Sopenharmony_ci} 77438c2ecf20Sopenharmony_ci 77448c2ecf20Sopenharmony_ci/** 77458c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_logout - Logout from the specified target 77468c2ecf20Sopenharmony_ci * @fnode_sess: pointer to session attrs of flash ddb entry 77478c2ecf20Sopenharmony_ci * @fnode_conn: pointer to connection attrs of flash ddb entry 77488c2ecf20Sopenharmony_ci * 77498c2ecf20Sopenharmony_ci * This performs log out from the specified target 77508c2ecf20Sopenharmony_ci **/ 77518c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, 77528c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn) 77538c2ecf20Sopenharmony_ci{ 77548c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); 77558c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 77568c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *flash_tddb = NULL; 77578c2ecf20Sopenharmony_ci struct ql4_tuple_ddb *tmp_tddb = NULL; 77588c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 77598c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = NULL; 77608c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_dma; 77618c2ecf20Sopenharmony_ci uint32_t next_idx = 0; 77628c2ecf20Sopenharmony_ci uint32_t state = 0, conn_err = 0; 77638c2ecf20Sopenharmony_ci uint16_t conn_id = 0; 77648c2ecf20Sopenharmony_ci int idx, index; 77658c2ecf20Sopenharmony_ci int status, ret = 0; 77668c2ecf20Sopenharmony_ci 77678c2ecf20Sopenharmony_ci fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, 77688c2ecf20Sopenharmony_ci &fw_ddb_dma); 77698c2ecf20Sopenharmony_ci if (fw_ddb_entry == NULL) { 77708c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s:Out of memory\n", __func__); 77718c2ecf20Sopenharmony_ci ret = -ENOMEM; 77728c2ecf20Sopenharmony_ci goto exit_ddb_logout; 77738c2ecf20Sopenharmony_ci } 77748c2ecf20Sopenharmony_ci 77758c2ecf20Sopenharmony_ci flash_tddb = vzalloc(sizeof(*flash_tddb)); 77768c2ecf20Sopenharmony_ci if (!flash_tddb) { 77778c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 77788c2ecf20Sopenharmony_ci "%s:Memory Allocation failed.\n", __func__); 77798c2ecf20Sopenharmony_ci ret = -ENOMEM; 77808c2ecf20Sopenharmony_ci goto exit_ddb_logout; 77818c2ecf20Sopenharmony_ci } 77828c2ecf20Sopenharmony_ci 77838c2ecf20Sopenharmony_ci tmp_tddb = vzalloc(sizeof(*tmp_tddb)); 77848c2ecf20Sopenharmony_ci if (!tmp_tddb) { 77858c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 77868c2ecf20Sopenharmony_ci "%s:Memory Allocation failed.\n", __func__); 77878c2ecf20Sopenharmony_ci ret = -ENOMEM; 77888c2ecf20Sopenharmony_ci goto exit_ddb_logout; 77898c2ecf20Sopenharmony_ci } 77908c2ecf20Sopenharmony_ci 77918c2ecf20Sopenharmony_ci if (!fnode_sess->targetname) { 77928c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 77938c2ecf20Sopenharmony_ci "%s:Cannot logout from SendTarget entry\n", 77948c2ecf20Sopenharmony_ci __func__); 77958c2ecf20Sopenharmony_ci ret = -EPERM; 77968c2ecf20Sopenharmony_ci goto exit_ddb_logout; 77978c2ecf20Sopenharmony_ci } 77988c2ecf20Sopenharmony_ci 77998c2ecf20Sopenharmony_ci if (fnode_sess->is_boot_target) { 78008c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 78018c2ecf20Sopenharmony_ci "%s: Logout from boot target entry is not permitted.\n", 78028c2ecf20Sopenharmony_ci __func__); 78038c2ecf20Sopenharmony_ci ret = -EPERM; 78048c2ecf20Sopenharmony_ci goto exit_ddb_logout; 78058c2ecf20Sopenharmony_ci } 78068c2ecf20Sopenharmony_ci 78078c2ecf20Sopenharmony_ci strlcpy(flash_tddb->iscsi_name, fnode_sess->targetname, 78088c2ecf20Sopenharmony_ci ISCSI_NAME_SIZE); 78098c2ecf20Sopenharmony_ci 78108c2ecf20Sopenharmony_ci if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 78118c2ecf20Sopenharmony_ci sprintf(flash_tddb->ip_addr, "%pI6", fnode_conn->ipaddress); 78128c2ecf20Sopenharmony_ci else 78138c2ecf20Sopenharmony_ci sprintf(flash_tddb->ip_addr, "%pI4", fnode_conn->ipaddress); 78148c2ecf20Sopenharmony_ci 78158c2ecf20Sopenharmony_ci flash_tddb->tpgt = fnode_sess->tpgt; 78168c2ecf20Sopenharmony_ci flash_tddb->port = fnode_conn->port; 78178c2ecf20Sopenharmony_ci 78188c2ecf20Sopenharmony_ci COPY_ISID(flash_tddb->isid, fnode_sess->isid); 78198c2ecf20Sopenharmony_ci 78208c2ecf20Sopenharmony_ci for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { 78218c2ecf20Sopenharmony_ci ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); 78228c2ecf20Sopenharmony_ci if (ddb_entry == NULL) 78238c2ecf20Sopenharmony_ci continue; 78248c2ecf20Sopenharmony_ci 78258c2ecf20Sopenharmony_ci if (ddb_entry->ddb_type != FLASH_DDB) 78268c2ecf20Sopenharmony_ci continue; 78278c2ecf20Sopenharmony_ci 78288c2ecf20Sopenharmony_ci index = ddb_entry->sess->target_id; 78298c2ecf20Sopenharmony_ci status = qla4xxx_get_fwddb_entry(ha, index, fw_ddb_entry, 78308c2ecf20Sopenharmony_ci fw_ddb_dma, NULL, &next_idx, 78318c2ecf20Sopenharmony_ci &state, &conn_err, NULL, 78328c2ecf20Sopenharmony_ci &conn_id); 78338c2ecf20Sopenharmony_ci if (status == QLA_ERROR) { 78348c2ecf20Sopenharmony_ci ret = -ENOMEM; 78358c2ecf20Sopenharmony_ci break; 78368c2ecf20Sopenharmony_ci } 78378c2ecf20Sopenharmony_ci 78388c2ecf20Sopenharmony_ci qla4xxx_convert_param_ddb(fw_ddb_entry, tmp_tddb, NULL); 78398c2ecf20Sopenharmony_ci 78408c2ecf20Sopenharmony_ci status = qla4xxx_compare_tuple_ddb(ha, flash_tddb, tmp_tddb, 78418c2ecf20Sopenharmony_ci true); 78428c2ecf20Sopenharmony_ci if (status == QLA_SUCCESS) { 78438c2ecf20Sopenharmony_ci ret = qla4xxx_sysfs_ddb_logout_sid(ddb_entry->sess); 78448c2ecf20Sopenharmony_ci break; 78458c2ecf20Sopenharmony_ci } 78468c2ecf20Sopenharmony_ci } 78478c2ecf20Sopenharmony_ci 78488c2ecf20Sopenharmony_ci if (idx == MAX_DDB_ENTRIES) 78498c2ecf20Sopenharmony_ci ret = -ESRCH; 78508c2ecf20Sopenharmony_ci 78518c2ecf20Sopenharmony_ciexit_ddb_logout: 78528c2ecf20Sopenharmony_ci if (flash_tddb) 78538c2ecf20Sopenharmony_ci vfree(flash_tddb); 78548c2ecf20Sopenharmony_ci if (tmp_tddb) 78558c2ecf20Sopenharmony_ci vfree(tmp_tddb); 78568c2ecf20Sopenharmony_ci if (fw_ddb_entry) 78578c2ecf20Sopenharmony_ci dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); 78588c2ecf20Sopenharmony_ci 78598c2ecf20Sopenharmony_ci return ret; 78608c2ecf20Sopenharmony_ci} 78618c2ecf20Sopenharmony_ci 78628c2ecf20Sopenharmony_cistatic int 78638c2ecf20Sopenharmony_ciqla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, 78648c2ecf20Sopenharmony_ci int param, char *buf) 78658c2ecf20Sopenharmony_ci{ 78668c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); 78678c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 78688c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn; 78698c2ecf20Sopenharmony_ci struct ql4_chap_table chap_tbl; 78708c2ecf20Sopenharmony_ci struct device *dev; 78718c2ecf20Sopenharmony_ci int parent_type; 78728c2ecf20Sopenharmony_ci int rc = 0; 78738c2ecf20Sopenharmony_ci 78748c2ecf20Sopenharmony_ci dev = iscsi_find_flashnode_conn(fnode_sess); 78758c2ecf20Sopenharmony_ci if (!dev) 78768c2ecf20Sopenharmony_ci return -EIO; 78778c2ecf20Sopenharmony_ci 78788c2ecf20Sopenharmony_ci fnode_conn = iscsi_dev_to_flash_conn(dev); 78798c2ecf20Sopenharmony_ci 78808c2ecf20Sopenharmony_ci switch (param) { 78818c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: 78828c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->is_fw_assigned_ipv6); 78838c2ecf20Sopenharmony_ci break; 78848c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PORTAL_TYPE: 78858c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", fnode_sess->portal_type); 78868c2ecf20Sopenharmony_ci break; 78878c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: 78888c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->auto_snd_tgt_disable); 78898c2ecf20Sopenharmony_ci break; 78908c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_SESS: 78918c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->discovery_sess); 78928c2ecf20Sopenharmony_ci break; 78938c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ENTRY_EN: 78948c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->entry_state); 78958c2ecf20Sopenharmony_ci break; 78968c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_HDR_DGST_EN: 78978c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->hdrdgst_en); 78988c2ecf20Sopenharmony_ci break; 78998c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DATA_DGST_EN: 79008c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->datadgst_en); 79018c2ecf20Sopenharmony_ci break; 79028c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IMM_DATA_EN: 79038c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->imm_data_en); 79048c2ecf20Sopenharmony_ci break; 79058c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_INITIAL_R2T_EN: 79068c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->initial_r2t_en); 79078c2ecf20Sopenharmony_ci break; 79088c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DATASEQ_INORDER: 79098c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->dataseq_inorder_en); 79108c2ecf20Sopenharmony_ci break; 79118c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PDU_INORDER: 79128c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->pdu_inorder_en); 79138c2ecf20Sopenharmony_ci break; 79148c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_CHAP_AUTH_EN: 79158c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->chap_auth_en); 79168c2ecf20Sopenharmony_ci break; 79178c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_SNACK_REQ_EN: 79188c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->snack_req_en); 79198c2ecf20Sopenharmony_ci break; 79208c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: 79218c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->discovery_logout_en); 79228c2ecf20Sopenharmony_ci break; 79238c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_BIDI_CHAP_EN: 79248c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->bidi_chap_en); 79258c2ecf20Sopenharmony_ci break; 79268c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: 79278c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->discovery_auth_optional); 79288c2ecf20Sopenharmony_ci break; 79298c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ERL: 79308c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->erl); 79318c2ecf20Sopenharmony_ci break; 79328c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: 79338c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_stat); 79348c2ecf20Sopenharmony_ci break; 79358c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: 79368c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_nagle_disable); 79378c2ecf20Sopenharmony_ci break; 79388c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_WSF_DISABLE: 79398c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_wsf_disable); 79408c2ecf20Sopenharmony_ci break; 79418c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMER_SCALE: 79428c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_timer_scale); 79438c2ecf20Sopenharmony_ci break; 79448c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: 79458c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_en); 79468c2ecf20Sopenharmony_ci break; 79478c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IP_FRAG_DISABLE: 79488c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->fragment_disable); 79498c2ecf20Sopenharmony_ci break; 79508c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: 79518c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->max_recv_dlength); 79528c2ecf20Sopenharmony_ci break; 79538c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: 79548c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->max_xmit_dlength); 79558c2ecf20Sopenharmony_ci break; 79568c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_FIRST_BURST: 79578c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->first_burst); 79588c2ecf20Sopenharmony_ci break; 79598c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TIME2WAIT: 79608c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->time2wait); 79618c2ecf20Sopenharmony_ci break; 79628c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TIME2RETAIN: 79638c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->time2retain); 79648c2ecf20Sopenharmony_ci break; 79658c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_R2T: 79668c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->max_r2t); 79678c2ecf20Sopenharmony_ci break; 79688c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_KEEPALIVE_TMO: 79698c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->keepalive_timeout); 79708c2ecf20Sopenharmony_ci break; 79718c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ISID: 79728c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pm\n", fnode_sess->isid); 79738c2ecf20Sopenharmony_ci break; 79748c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TSID: 79758c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->tsid); 79768c2ecf20Sopenharmony_ci break; 79778c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PORT: 79788c2ecf20Sopenharmony_ci rc = sprintf(buf, "%d\n", fnode_conn->port); 79798c2ecf20Sopenharmony_ci break; 79808c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_BURST: 79818c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->max_burst); 79828c2ecf20Sopenharmony_ci break; 79838c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: 79848c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", 79858c2ecf20Sopenharmony_ci fnode_sess->default_taskmgmt_timeout); 79868c2ecf20Sopenharmony_ci break; 79878c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPADDR: 79888c2ecf20Sopenharmony_ci if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 79898c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pI6\n", fnode_conn->ipaddress); 79908c2ecf20Sopenharmony_ci else 79918c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pI4\n", fnode_conn->ipaddress); 79928c2ecf20Sopenharmony_ci break; 79938c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ALIAS: 79948c2ecf20Sopenharmony_ci if (fnode_sess->targetalias) 79958c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", fnode_sess->targetalias); 79968c2ecf20Sopenharmony_ci else 79978c2ecf20Sopenharmony_ci rc = sprintf(buf, "\n"); 79988c2ecf20Sopenharmony_ci break; 79998c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_REDIRECT_IPADDR: 80008c2ecf20Sopenharmony_ci if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 80018c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pI6\n", 80028c2ecf20Sopenharmony_ci fnode_conn->redirect_ipaddr); 80038c2ecf20Sopenharmony_ci else 80048c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pI4\n", 80058c2ecf20Sopenharmony_ci fnode_conn->redirect_ipaddr); 80068c2ecf20Sopenharmony_ci break; 80078c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: 80088c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->max_segment_size); 80098c2ecf20Sopenharmony_ci break; 80108c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_LOCAL_PORT: 80118c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->local_port); 80128c2ecf20Sopenharmony_ci break; 80138c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV4_TOS: 80148c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->ipv4_tos); 80158c2ecf20Sopenharmony_ci break; 80168c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV6_TC: 80178c2ecf20Sopenharmony_ci if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 80188c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", 80198c2ecf20Sopenharmony_ci fnode_conn->ipv6_traffic_class); 80208c2ecf20Sopenharmony_ci else 80218c2ecf20Sopenharmony_ci rc = sprintf(buf, "\n"); 80228c2ecf20Sopenharmony_ci break; 80238c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: 80248c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->ipv6_flow_label); 80258c2ecf20Sopenharmony_ci break; 80268c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: 80278c2ecf20Sopenharmony_ci if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) 80288c2ecf20Sopenharmony_ci rc = sprintf(buf, "%pI6\n", 80298c2ecf20Sopenharmony_ci fnode_conn->link_local_ipv6_addr); 80308c2ecf20Sopenharmony_ci else 80318c2ecf20Sopenharmony_ci rc = sprintf(buf, "\n"); 80328c2ecf20Sopenharmony_ci break; 80338c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: 80348c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->discovery_parent_idx); 80358c2ecf20Sopenharmony_ci break; 80368c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: 80378c2ecf20Sopenharmony_ci if (fnode_sess->discovery_parent_type == DDB_ISNS) 80388c2ecf20Sopenharmony_ci parent_type = ISCSI_DISC_PARENT_ISNS; 80398c2ecf20Sopenharmony_ci else if (fnode_sess->discovery_parent_type == DDB_NO_LINK) 80408c2ecf20Sopenharmony_ci parent_type = ISCSI_DISC_PARENT_UNKNOWN; 80418c2ecf20Sopenharmony_ci else if (fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES) 80428c2ecf20Sopenharmony_ci parent_type = ISCSI_DISC_PARENT_SENDTGT; 80438c2ecf20Sopenharmony_ci else 80448c2ecf20Sopenharmony_ci parent_type = ISCSI_DISC_PARENT_UNKNOWN; 80458c2ecf20Sopenharmony_ci 80468c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", 80478c2ecf20Sopenharmony_ci iscsi_get_discovery_parent_name(parent_type)); 80488c2ecf20Sopenharmony_ci break; 80498c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_NAME: 80508c2ecf20Sopenharmony_ci if (fnode_sess->targetname) 80518c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", fnode_sess->targetname); 80528c2ecf20Sopenharmony_ci else 80538c2ecf20Sopenharmony_ci rc = sprintf(buf, "\n"); 80548c2ecf20Sopenharmony_ci break; 80558c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TPGT: 80568c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->tpgt); 80578c2ecf20Sopenharmony_ci break; 80588c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_XMIT_WSF: 80598c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_xmit_wsf); 80608c2ecf20Sopenharmony_ci break; 80618c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_RECV_WSF: 80628c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->tcp_recv_wsf); 80638c2ecf20Sopenharmony_ci break; 80648c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_CHAP_OUT_IDX: 80658c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->chap_out_idx); 80668c2ecf20Sopenharmony_ci break; 80678c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_USERNAME: 80688c2ecf20Sopenharmony_ci if (fnode_sess->chap_auth_en) { 80698c2ecf20Sopenharmony_ci qla4xxx_get_uni_chap_at_index(ha, 80708c2ecf20Sopenharmony_ci chap_tbl.name, 80718c2ecf20Sopenharmony_ci chap_tbl.secret, 80728c2ecf20Sopenharmony_ci fnode_sess->chap_out_idx); 80738c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", chap_tbl.name); 80748c2ecf20Sopenharmony_ci } else { 80758c2ecf20Sopenharmony_ci rc = sprintf(buf, "\n"); 80768c2ecf20Sopenharmony_ci } 80778c2ecf20Sopenharmony_ci break; 80788c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PASSWORD: 80798c2ecf20Sopenharmony_ci if (fnode_sess->chap_auth_en) { 80808c2ecf20Sopenharmony_ci qla4xxx_get_uni_chap_at_index(ha, 80818c2ecf20Sopenharmony_ci chap_tbl.name, 80828c2ecf20Sopenharmony_ci chap_tbl.secret, 80838c2ecf20Sopenharmony_ci fnode_sess->chap_out_idx); 80848c2ecf20Sopenharmony_ci rc = sprintf(buf, "%s\n", chap_tbl.secret); 80858c2ecf20Sopenharmony_ci } else { 80868c2ecf20Sopenharmony_ci rc = sprintf(buf, "\n"); 80878c2ecf20Sopenharmony_ci } 80888c2ecf20Sopenharmony_ci break; 80898c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_STATSN: 80908c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->statsn); 80918c2ecf20Sopenharmony_ci break; 80928c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_EXP_STATSN: 80938c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_conn->exp_statsn); 80948c2ecf20Sopenharmony_ci break; 80958c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IS_BOOT_TGT: 80968c2ecf20Sopenharmony_ci rc = sprintf(buf, "%u\n", fnode_sess->is_boot_target); 80978c2ecf20Sopenharmony_ci break; 80988c2ecf20Sopenharmony_ci default: 80998c2ecf20Sopenharmony_ci rc = -ENOSYS; 81008c2ecf20Sopenharmony_ci break; 81018c2ecf20Sopenharmony_ci } 81028c2ecf20Sopenharmony_ci 81038c2ecf20Sopenharmony_ci put_device(dev); 81048c2ecf20Sopenharmony_ci return rc; 81058c2ecf20Sopenharmony_ci} 81068c2ecf20Sopenharmony_ci 81078c2ecf20Sopenharmony_ci/** 81088c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_set_param - Set parameter for firmware DDB entry 81098c2ecf20Sopenharmony_ci * @fnode_sess: pointer to session attrs of flash ddb entry 81108c2ecf20Sopenharmony_ci * @fnode_conn: pointer to connection attrs of flash ddb entry 81118c2ecf20Sopenharmony_ci * @data: Parameters and their values to update 81128c2ecf20Sopenharmony_ci * @len: len of data 81138c2ecf20Sopenharmony_ci * 81148c2ecf20Sopenharmony_ci * This sets the parameter of flash ddb entry and writes them to flash 81158c2ecf20Sopenharmony_ci **/ 81168c2ecf20Sopenharmony_cistatic int 81178c2ecf20Sopenharmony_ciqla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, 81188c2ecf20Sopenharmony_ci struct iscsi_bus_flash_conn *fnode_conn, 81198c2ecf20Sopenharmony_ci void *data, int len) 81208c2ecf20Sopenharmony_ci{ 81218c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); 81228c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 81238c2ecf20Sopenharmony_ci struct iscsi_flashnode_param_info *fnode_param; 81248c2ecf20Sopenharmony_ci struct ql4_chap_table chap_tbl; 81258c2ecf20Sopenharmony_ci struct nlattr *attr; 81268c2ecf20Sopenharmony_ci uint16_t chap_out_idx = INVALID_ENTRY; 81278c2ecf20Sopenharmony_ci int rc = QLA_ERROR; 81288c2ecf20Sopenharmony_ci uint32_t rem = len; 81298c2ecf20Sopenharmony_ci 81308c2ecf20Sopenharmony_ci memset((void *)&chap_tbl, 0, sizeof(chap_tbl)); 81318c2ecf20Sopenharmony_ci nla_for_each_attr(attr, data, len, rem) { 81328c2ecf20Sopenharmony_ci if (nla_len(attr) < sizeof(*fnode_param)) { 81338c2ecf20Sopenharmony_ci rc = -EINVAL; 81348c2ecf20Sopenharmony_ci goto exit_set_param; 81358c2ecf20Sopenharmony_ci } 81368c2ecf20Sopenharmony_ci 81378c2ecf20Sopenharmony_ci fnode_param = nla_data(attr); 81388c2ecf20Sopenharmony_ci 81398c2ecf20Sopenharmony_ci switch (fnode_param->param) { 81408c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: 81418c2ecf20Sopenharmony_ci fnode_conn->is_fw_assigned_ipv6 = fnode_param->value[0]; 81428c2ecf20Sopenharmony_ci break; 81438c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PORTAL_TYPE: 81448c2ecf20Sopenharmony_ci memcpy(fnode_sess->portal_type, fnode_param->value, 81458c2ecf20Sopenharmony_ci strlen(fnode_sess->portal_type)); 81468c2ecf20Sopenharmony_ci break; 81478c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: 81488c2ecf20Sopenharmony_ci fnode_sess->auto_snd_tgt_disable = 81498c2ecf20Sopenharmony_ci fnode_param->value[0]; 81508c2ecf20Sopenharmony_ci break; 81518c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_SESS: 81528c2ecf20Sopenharmony_ci fnode_sess->discovery_sess = fnode_param->value[0]; 81538c2ecf20Sopenharmony_ci break; 81548c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ENTRY_EN: 81558c2ecf20Sopenharmony_ci fnode_sess->entry_state = fnode_param->value[0]; 81568c2ecf20Sopenharmony_ci break; 81578c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_HDR_DGST_EN: 81588c2ecf20Sopenharmony_ci fnode_conn->hdrdgst_en = fnode_param->value[0]; 81598c2ecf20Sopenharmony_ci break; 81608c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DATA_DGST_EN: 81618c2ecf20Sopenharmony_ci fnode_conn->datadgst_en = fnode_param->value[0]; 81628c2ecf20Sopenharmony_ci break; 81638c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IMM_DATA_EN: 81648c2ecf20Sopenharmony_ci fnode_sess->imm_data_en = fnode_param->value[0]; 81658c2ecf20Sopenharmony_ci break; 81668c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_INITIAL_R2T_EN: 81678c2ecf20Sopenharmony_ci fnode_sess->initial_r2t_en = fnode_param->value[0]; 81688c2ecf20Sopenharmony_ci break; 81698c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DATASEQ_INORDER: 81708c2ecf20Sopenharmony_ci fnode_sess->dataseq_inorder_en = fnode_param->value[0]; 81718c2ecf20Sopenharmony_ci break; 81728c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PDU_INORDER: 81738c2ecf20Sopenharmony_ci fnode_sess->pdu_inorder_en = fnode_param->value[0]; 81748c2ecf20Sopenharmony_ci break; 81758c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_CHAP_AUTH_EN: 81768c2ecf20Sopenharmony_ci fnode_sess->chap_auth_en = fnode_param->value[0]; 81778c2ecf20Sopenharmony_ci /* Invalidate chap index if chap auth is disabled */ 81788c2ecf20Sopenharmony_ci if (!fnode_sess->chap_auth_en) 81798c2ecf20Sopenharmony_ci fnode_sess->chap_out_idx = INVALID_ENTRY; 81808c2ecf20Sopenharmony_ci 81818c2ecf20Sopenharmony_ci break; 81828c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_SNACK_REQ_EN: 81838c2ecf20Sopenharmony_ci fnode_conn->snack_req_en = fnode_param->value[0]; 81848c2ecf20Sopenharmony_ci break; 81858c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: 81868c2ecf20Sopenharmony_ci fnode_sess->discovery_logout_en = fnode_param->value[0]; 81878c2ecf20Sopenharmony_ci break; 81888c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_BIDI_CHAP_EN: 81898c2ecf20Sopenharmony_ci fnode_sess->bidi_chap_en = fnode_param->value[0]; 81908c2ecf20Sopenharmony_ci break; 81918c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: 81928c2ecf20Sopenharmony_ci fnode_sess->discovery_auth_optional = 81938c2ecf20Sopenharmony_ci fnode_param->value[0]; 81948c2ecf20Sopenharmony_ci break; 81958c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ERL: 81968c2ecf20Sopenharmony_ci fnode_sess->erl = fnode_param->value[0]; 81978c2ecf20Sopenharmony_ci break; 81988c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: 81998c2ecf20Sopenharmony_ci fnode_conn->tcp_timestamp_stat = fnode_param->value[0]; 82008c2ecf20Sopenharmony_ci break; 82018c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: 82028c2ecf20Sopenharmony_ci fnode_conn->tcp_nagle_disable = fnode_param->value[0]; 82038c2ecf20Sopenharmony_ci break; 82048c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_WSF_DISABLE: 82058c2ecf20Sopenharmony_ci fnode_conn->tcp_wsf_disable = fnode_param->value[0]; 82068c2ecf20Sopenharmony_ci break; 82078c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMER_SCALE: 82088c2ecf20Sopenharmony_ci fnode_conn->tcp_timer_scale = fnode_param->value[0]; 82098c2ecf20Sopenharmony_ci break; 82108c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: 82118c2ecf20Sopenharmony_ci fnode_conn->tcp_timestamp_en = fnode_param->value[0]; 82128c2ecf20Sopenharmony_ci break; 82138c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IP_FRAG_DISABLE: 82148c2ecf20Sopenharmony_ci fnode_conn->fragment_disable = fnode_param->value[0]; 82158c2ecf20Sopenharmony_ci break; 82168c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: 82178c2ecf20Sopenharmony_ci fnode_conn->max_recv_dlength = 82188c2ecf20Sopenharmony_ci *(unsigned *)fnode_param->value; 82198c2ecf20Sopenharmony_ci break; 82208c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: 82218c2ecf20Sopenharmony_ci fnode_conn->max_xmit_dlength = 82228c2ecf20Sopenharmony_ci *(unsigned *)fnode_param->value; 82238c2ecf20Sopenharmony_ci break; 82248c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_FIRST_BURST: 82258c2ecf20Sopenharmony_ci fnode_sess->first_burst = 82268c2ecf20Sopenharmony_ci *(unsigned *)fnode_param->value; 82278c2ecf20Sopenharmony_ci break; 82288c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TIME2WAIT: 82298c2ecf20Sopenharmony_ci fnode_sess->time2wait = *(uint16_t *)fnode_param->value; 82308c2ecf20Sopenharmony_ci break; 82318c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TIME2RETAIN: 82328c2ecf20Sopenharmony_ci fnode_sess->time2retain = 82338c2ecf20Sopenharmony_ci *(uint16_t *)fnode_param->value; 82348c2ecf20Sopenharmony_ci break; 82358c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_R2T: 82368c2ecf20Sopenharmony_ci fnode_sess->max_r2t = 82378c2ecf20Sopenharmony_ci *(uint16_t *)fnode_param->value; 82388c2ecf20Sopenharmony_ci break; 82398c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_KEEPALIVE_TMO: 82408c2ecf20Sopenharmony_ci fnode_conn->keepalive_timeout = 82418c2ecf20Sopenharmony_ci *(uint16_t *)fnode_param->value; 82428c2ecf20Sopenharmony_ci break; 82438c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ISID: 82448c2ecf20Sopenharmony_ci memcpy(fnode_sess->isid, fnode_param->value, 82458c2ecf20Sopenharmony_ci sizeof(fnode_sess->isid)); 82468c2ecf20Sopenharmony_ci break; 82478c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TSID: 82488c2ecf20Sopenharmony_ci fnode_sess->tsid = *(uint16_t *)fnode_param->value; 82498c2ecf20Sopenharmony_ci break; 82508c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_PORT: 82518c2ecf20Sopenharmony_ci fnode_conn->port = *(uint16_t *)fnode_param->value; 82528c2ecf20Sopenharmony_ci break; 82538c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_BURST: 82548c2ecf20Sopenharmony_ci fnode_sess->max_burst = *(unsigned *)fnode_param->value; 82558c2ecf20Sopenharmony_ci break; 82568c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: 82578c2ecf20Sopenharmony_ci fnode_sess->default_taskmgmt_timeout = 82588c2ecf20Sopenharmony_ci *(uint16_t *)fnode_param->value; 82598c2ecf20Sopenharmony_ci break; 82608c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPADDR: 82618c2ecf20Sopenharmony_ci memcpy(fnode_conn->ipaddress, fnode_param->value, 82628c2ecf20Sopenharmony_ci IPv6_ADDR_LEN); 82638c2ecf20Sopenharmony_ci break; 82648c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_ALIAS: 82658c2ecf20Sopenharmony_ci rc = iscsi_switch_str_param(&fnode_sess->targetalias, 82668c2ecf20Sopenharmony_ci (char *)fnode_param->value); 82678c2ecf20Sopenharmony_ci break; 82688c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_REDIRECT_IPADDR: 82698c2ecf20Sopenharmony_ci memcpy(fnode_conn->redirect_ipaddr, fnode_param->value, 82708c2ecf20Sopenharmony_ci IPv6_ADDR_LEN); 82718c2ecf20Sopenharmony_ci break; 82728c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: 82738c2ecf20Sopenharmony_ci fnode_conn->max_segment_size = 82748c2ecf20Sopenharmony_ci *(unsigned *)fnode_param->value; 82758c2ecf20Sopenharmony_ci break; 82768c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_LOCAL_PORT: 82778c2ecf20Sopenharmony_ci fnode_conn->local_port = 82788c2ecf20Sopenharmony_ci *(uint16_t *)fnode_param->value; 82798c2ecf20Sopenharmony_ci break; 82808c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV4_TOS: 82818c2ecf20Sopenharmony_ci fnode_conn->ipv4_tos = fnode_param->value[0]; 82828c2ecf20Sopenharmony_ci break; 82838c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV6_TC: 82848c2ecf20Sopenharmony_ci fnode_conn->ipv6_traffic_class = fnode_param->value[0]; 82858c2ecf20Sopenharmony_ci break; 82868c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: 82878c2ecf20Sopenharmony_ci fnode_conn->ipv6_flow_label = fnode_param->value[0]; 82888c2ecf20Sopenharmony_ci break; 82898c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_NAME: 82908c2ecf20Sopenharmony_ci rc = iscsi_switch_str_param(&fnode_sess->targetname, 82918c2ecf20Sopenharmony_ci (char *)fnode_param->value); 82928c2ecf20Sopenharmony_ci break; 82938c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TPGT: 82948c2ecf20Sopenharmony_ci fnode_sess->tpgt = *(uint16_t *)fnode_param->value; 82958c2ecf20Sopenharmony_ci break; 82968c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: 82978c2ecf20Sopenharmony_ci memcpy(fnode_conn->link_local_ipv6_addr, 82988c2ecf20Sopenharmony_ci fnode_param->value, IPv6_ADDR_LEN); 82998c2ecf20Sopenharmony_ci break; 83008c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: 83018c2ecf20Sopenharmony_ci fnode_sess->discovery_parent_idx = 83028c2ecf20Sopenharmony_ci *(uint16_t *)fnode_param->value; 83038c2ecf20Sopenharmony_ci break; 83048c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_XMIT_WSF: 83058c2ecf20Sopenharmony_ci fnode_conn->tcp_xmit_wsf = 83068c2ecf20Sopenharmony_ci *(uint8_t *)fnode_param->value; 83078c2ecf20Sopenharmony_ci break; 83088c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_TCP_RECV_WSF: 83098c2ecf20Sopenharmony_ci fnode_conn->tcp_recv_wsf = 83108c2ecf20Sopenharmony_ci *(uint8_t *)fnode_param->value; 83118c2ecf20Sopenharmony_ci break; 83128c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_STATSN: 83138c2ecf20Sopenharmony_ci fnode_conn->statsn = *(uint32_t *)fnode_param->value; 83148c2ecf20Sopenharmony_ci break; 83158c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_EXP_STATSN: 83168c2ecf20Sopenharmony_ci fnode_conn->exp_statsn = 83178c2ecf20Sopenharmony_ci *(uint32_t *)fnode_param->value; 83188c2ecf20Sopenharmony_ci break; 83198c2ecf20Sopenharmony_ci case ISCSI_FLASHNODE_CHAP_OUT_IDX: 83208c2ecf20Sopenharmony_ci chap_out_idx = *(uint16_t *)fnode_param->value; 83218c2ecf20Sopenharmony_ci if (!qla4xxx_get_uni_chap_at_index(ha, 83228c2ecf20Sopenharmony_ci chap_tbl.name, 83238c2ecf20Sopenharmony_ci chap_tbl.secret, 83248c2ecf20Sopenharmony_ci chap_out_idx)) { 83258c2ecf20Sopenharmony_ci fnode_sess->chap_out_idx = chap_out_idx; 83268c2ecf20Sopenharmony_ci /* Enable chap auth if chap index is valid */ 83278c2ecf20Sopenharmony_ci fnode_sess->chap_auth_en = QL4_PARAM_ENABLE; 83288c2ecf20Sopenharmony_ci } 83298c2ecf20Sopenharmony_ci break; 83308c2ecf20Sopenharmony_ci default: 83318c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 83328c2ecf20Sopenharmony_ci "%s: No such sysfs attribute\n", __func__); 83338c2ecf20Sopenharmony_ci rc = -ENOSYS; 83348c2ecf20Sopenharmony_ci goto exit_set_param; 83358c2ecf20Sopenharmony_ci } 83368c2ecf20Sopenharmony_ci } 83378c2ecf20Sopenharmony_ci 83388c2ecf20Sopenharmony_ci rc = qla4xxx_sysfs_ddb_apply(fnode_sess, fnode_conn); 83398c2ecf20Sopenharmony_ci 83408c2ecf20Sopenharmony_ciexit_set_param: 83418c2ecf20Sopenharmony_ci return rc; 83428c2ecf20Sopenharmony_ci} 83438c2ecf20Sopenharmony_ci 83448c2ecf20Sopenharmony_ci/** 83458c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_delete - Delete firmware DDB entry 83468c2ecf20Sopenharmony_ci * @fnode_sess: pointer to session attrs of flash ddb entry 83478c2ecf20Sopenharmony_ci * 83488c2ecf20Sopenharmony_ci * This invalidates the flash ddb entry at the given index 83498c2ecf20Sopenharmony_ci **/ 83508c2ecf20Sopenharmony_cistatic int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess) 83518c2ecf20Sopenharmony_ci{ 83528c2ecf20Sopenharmony_ci struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); 83538c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 83548c2ecf20Sopenharmony_ci uint32_t dev_db_start_offset; 83558c2ecf20Sopenharmony_ci uint32_t dev_db_end_offset; 83568c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 83578c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 83588c2ecf20Sopenharmony_ci uint16_t *ddb_cookie = NULL; 83598c2ecf20Sopenharmony_ci size_t ddb_size = 0; 83608c2ecf20Sopenharmony_ci void *pddb = NULL; 83618c2ecf20Sopenharmony_ci int target_id; 83628c2ecf20Sopenharmony_ci int rc = 0; 83638c2ecf20Sopenharmony_ci 83648c2ecf20Sopenharmony_ci if (fnode_sess->is_boot_target) { 83658c2ecf20Sopenharmony_ci rc = -EPERM; 83668c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 83678c2ecf20Sopenharmony_ci "%s: Deletion of boot target entry is not permitted.\n", 83688c2ecf20Sopenharmony_ci __func__)); 83698c2ecf20Sopenharmony_ci goto exit_ddb_del; 83708c2ecf20Sopenharmony_ci } 83718c2ecf20Sopenharmony_ci 83728c2ecf20Sopenharmony_ci if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) 83738c2ecf20Sopenharmony_ci goto sysfs_ddb_del; 83748c2ecf20Sopenharmony_ci 83758c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 83768c2ecf20Sopenharmony_ci dev_db_start_offset = FLASH_OFFSET_DB_INFO; 83778c2ecf20Sopenharmony_ci dev_db_end_offset = FLASH_OFFSET_DB_END; 83788c2ecf20Sopenharmony_ci dev_db_start_offset += (fnode_sess->target_id * 83798c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry)); 83808c2ecf20Sopenharmony_ci ddb_size = sizeof(*fw_ddb_entry); 83818c2ecf20Sopenharmony_ci } else { 83828c2ecf20Sopenharmony_ci dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + 83838c2ecf20Sopenharmony_ci (ha->hw.flt_region_ddb << 2); 83848c2ecf20Sopenharmony_ci /* flt_ddb_size is DDB table size for both ports 83858c2ecf20Sopenharmony_ci * so divide it by 2 to calculate the offset for second port 83868c2ecf20Sopenharmony_ci */ 83878c2ecf20Sopenharmony_ci if (ha->port_num == 1) 83888c2ecf20Sopenharmony_ci dev_db_start_offset += (ha->hw.flt_ddb_size / 2); 83898c2ecf20Sopenharmony_ci 83908c2ecf20Sopenharmony_ci dev_db_end_offset = dev_db_start_offset + 83918c2ecf20Sopenharmony_ci (ha->hw.flt_ddb_size / 2); 83928c2ecf20Sopenharmony_ci 83938c2ecf20Sopenharmony_ci dev_db_start_offset += (fnode_sess->target_id * 83948c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry)); 83958c2ecf20Sopenharmony_ci dev_db_start_offset += offsetof(struct dev_db_entry, cookie); 83968c2ecf20Sopenharmony_ci 83978c2ecf20Sopenharmony_ci ddb_size = sizeof(*ddb_cookie); 83988c2ecf20Sopenharmony_ci } 83998c2ecf20Sopenharmony_ci 84008c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s: start offset=%u, end offset=%u\n", 84018c2ecf20Sopenharmony_ci __func__, dev_db_start_offset, dev_db_end_offset)); 84028c2ecf20Sopenharmony_ci 84038c2ecf20Sopenharmony_ci if (dev_db_start_offset > dev_db_end_offset) { 84048c2ecf20Sopenharmony_ci rc = -EIO; 84058c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, "%s:Invalid DDB index %u\n", 84068c2ecf20Sopenharmony_ci __func__, fnode_sess->target_id)); 84078c2ecf20Sopenharmony_ci goto exit_ddb_del; 84088c2ecf20Sopenharmony_ci } 84098c2ecf20Sopenharmony_ci 84108c2ecf20Sopenharmony_ci pddb = dma_alloc_coherent(&ha->pdev->dev, ddb_size, 84118c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 84128c2ecf20Sopenharmony_ci if (!pddb) { 84138c2ecf20Sopenharmony_ci rc = -ENOMEM; 84148c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 84158c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 84168c2ecf20Sopenharmony_ci __func__)); 84178c2ecf20Sopenharmony_ci goto exit_ddb_del; 84188c2ecf20Sopenharmony_ci } 84198c2ecf20Sopenharmony_ci 84208c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 84218c2ecf20Sopenharmony_ci fw_ddb_entry = pddb; 84228c2ecf20Sopenharmony_ci memset(fw_ddb_entry, 0, ddb_size); 84238c2ecf20Sopenharmony_ci ddb_cookie = &fw_ddb_entry->cookie; 84248c2ecf20Sopenharmony_ci } else { 84258c2ecf20Sopenharmony_ci ddb_cookie = pddb; 84268c2ecf20Sopenharmony_ci } 84278c2ecf20Sopenharmony_ci 84288c2ecf20Sopenharmony_ci /* invalidate the cookie */ 84298c2ecf20Sopenharmony_ci *ddb_cookie = 0xFFEE; 84308c2ecf20Sopenharmony_ci qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, 84318c2ecf20Sopenharmony_ci ddb_size, FLASH_OPT_RMW_COMMIT); 84328c2ecf20Sopenharmony_ci 84338c2ecf20Sopenharmony_cisysfs_ddb_del: 84348c2ecf20Sopenharmony_ci target_id = fnode_sess->target_id; 84358c2ecf20Sopenharmony_ci iscsi_destroy_flashnode_sess(fnode_sess); 84368c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 84378c2ecf20Sopenharmony_ci "%s: session and conn entries for flashnode %u of host %lu deleted\n", 84388c2ecf20Sopenharmony_ci __func__, target_id, ha->host_no); 84398c2ecf20Sopenharmony_ciexit_ddb_del: 84408c2ecf20Sopenharmony_ci if (pddb) 84418c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, ddb_size, pddb, 84428c2ecf20Sopenharmony_ci fw_ddb_entry_dma); 84438c2ecf20Sopenharmony_ci return rc; 84448c2ecf20Sopenharmony_ci} 84458c2ecf20Sopenharmony_ci 84468c2ecf20Sopenharmony_ci/** 84478c2ecf20Sopenharmony_ci * qla4xxx_sysfs_ddb_export - Create sysfs entries for firmware DDBs 84488c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 84498c2ecf20Sopenharmony_ci * 84508c2ecf20Sopenharmony_ci * Export the firmware DDB for all send targets and normal targets to sysfs. 84518c2ecf20Sopenharmony_ci **/ 84528c2ecf20Sopenharmony_ciint qla4xxx_sysfs_ddb_export(struct scsi_qla_host *ha) 84538c2ecf20Sopenharmony_ci{ 84548c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 84558c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 84568c2ecf20Sopenharmony_ci uint16_t max_ddbs; 84578c2ecf20Sopenharmony_ci uint16_t idx = 0; 84588c2ecf20Sopenharmony_ci int ret = QLA_SUCCESS; 84598c2ecf20Sopenharmony_ci 84608c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, 84618c2ecf20Sopenharmony_ci sizeof(*fw_ddb_entry), 84628c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 84638c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 84648c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_ERR, ha, 84658c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", 84668c2ecf20Sopenharmony_ci __func__)); 84678c2ecf20Sopenharmony_ci return -ENOMEM; 84688c2ecf20Sopenharmony_ci } 84698c2ecf20Sopenharmony_ci 84708c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : 84718c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 84728c2ecf20Sopenharmony_ci 84738c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx++) { 84748c2ecf20Sopenharmony_ci if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, fw_ddb_entry_dma, 84758c2ecf20Sopenharmony_ci idx)) 84768c2ecf20Sopenharmony_ci continue; 84778c2ecf20Sopenharmony_ci 84788c2ecf20Sopenharmony_ci ret = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 0); 84798c2ecf20Sopenharmony_ci if (ret) { 84808c2ecf20Sopenharmony_ci ret = -EIO; 84818c2ecf20Sopenharmony_ci break; 84828c2ecf20Sopenharmony_ci } 84838c2ecf20Sopenharmony_ci } 84848c2ecf20Sopenharmony_ci 84858c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, 84868c2ecf20Sopenharmony_ci fw_ddb_entry_dma); 84878c2ecf20Sopenharmony_ci 84888c2ecf20Sopenharmony_ci return ret; 84898c2ecf20Sopenharmony_ci} 84908c2ecf20Sopenharmony_ci 84918c2ecf20Sopenharmony_cistatic void qla4xxx_sysfs_ddb_remove(struct scsi_qla_host *ha) 84928c2ecf20Sopenharmony_ci{ 84938c2ecf20Sopenharmony_ci iscsi_destroy_all_flashnode(ha->host); 84948c2ecf20Sopenharmony_ci} 84958c2ecf20Sopenharmony_ci 84968c2ecf20Sopenharmony_ci/** 84978c2ecf20Sopenharmony_ci * qla4xxx_build_ddb_list - Build ddb list and setup sessions 84988c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 84998c2ecf20Sopenharmony_ci * @is_reset: Is this init path or reset path 85008c2ecf20Sopenharmony_ci * 85018c2ecf20Sopenharmony_ci * Create a list of sendtargets (st) from firmware DDBs, issue send targets 85028c2ecf20Sopenharmony_ci * using connection open, then create the list of normal targets (nt) 85038c2ecf20Sopenharmony_ci * from firmware DDBs. Based on the list of nt setup session and connection 85048c2ecf20Sopenharmony_ci * objects. 85058c2ecf20Sopenharmony_ci **/ 85068c2ecf20Sopenharmony_civoid qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) 85078c2ecf20Sopenharmony_ci{ 85088c2ecf20Sopenharmony_ci uint16_t tmo = 0; 85098c2ecf20Sopenharmony_ci struct list_head list_st, list_nt; 85108c2ecf20Sopenharmony_ci struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp; 85118c2ecf20Sopenharmony_ci unsigned long wtime; 85128c2ecf20Sopenharmony_ci 85138c2ecf20Sopenharmony_ci if (!test_bit(AF_LINK_UP, &ha->flags)) { 85148c2ecf20Sopenharmony_ci set_bit(AF_BUILD_DDB_LIST, &ha->flags); 85158c2ecf20Sopenharmony_ci ha->is_reset = is_reset; 85168c2ecf20Sopenharmony_ci return; 85178c2ecf20Sopenharmony_ci } 85188c2ecf20Sopenharmony_ci 85198c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&list_st); 85208c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&list_nt); 85218c2ecf20Sopenharmony_ci 85228c2ecf20Sopenharmony_ci qla4xxx_build_st_list(ha, &list_st); 85238c2ecf20Sopenharmony_ci 85248c2ecf20Sopenharmony_ci /* Before issuing conn open mbox, ensure all IPs states are configured 85258c2ecf20Sopenharmony_ci * Note, conn open fails if IPs are not configured 85268c2ecf20Sopenharmony_ci */ 85278c2ecf20Sopenharmony_ci qla4xxx_wait_for_ip_configuration(ha); 85288c2ecf20Sopenharmony_ci 85298c2ecf20Sopenharmony_ci /* Go thru the STs and fire the sendtargets by issuing conn open mbx */ 85308c2ecf20Sopenharmony_ci list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { 85318c2ecf20Sopenharmony_ci qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx); 85328c2ecf20Sopenharmony_ci } 85338c2ecf20Sopenharmony_ci 85348c2ecf20Sopenharmony_ci /* Wait to ensure all sendtargets are done for min 12 sec wait */ 85358c2ecf20Sopenharmony_ci tmo = ((ha->def_timeout > LOGIN_TOV) && 85368c2ecf20Sopenharmony_ci (ha->def_timeout < LOGIN_TOV * 10) ? 85378c2ecf20Sopenharmony_ci ha->def_timeout : LOGIN_TOV); 85388c2ecf20Sopenharmony_ci 85398c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 85408c2ecf20Sopenharmony_ci "Default time to wait for build ddb %d\n", tmo)); 85418c2ecf20Sopenharmony_ci 85428c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * tmo); 85438c2ecf20Sopenharmony_ci do { 85448c2ecf20Sopenharmony_ci if (list_empty(&list_st)) 85458c2ecf20Sopenharmony_ci break; 85468c2ecf20Sopenharmony_ci 85478c2ecf20Sopenharmony_ci qla4xxx_remove_failed_ddb(ha, &list_st); 85488c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ / 10); 85498c2ecf20Sopenharmony_ci } while (time_after(wtime, jiffies)); 85508c2ecf20Sopenharmony_ci 85518c2ecf20Sopenharmony_ci 85528c2ecf20Sopenharmony_ci qla4xxx_build_nt_list(ha, &list_nt, &list_st, is_reset); 85538c2ecf20Sopenharmony_ci 85548c2ecf20Sopenharmony_ci qla4xxx_free_ddb_list(&list_st); 85558c2ecf20Sopenharmony_ci qla4xxx_free_ddb_list(&list_nt); 85568c2ecf20Sopenharmony_ci 85578c2ecf20Sopenharmony_ci qla4xxx_free_ddb_index(ha); 85588c2ecf20Sopenharmony_ci} 85598c2ecf20Sopenharmony_ci 85608c2ecf20Sopenharmony_ci/** 85618c2ecf20Sopenharmony_ci * qla4xxx_wait_login_resp_boot_tgt - Wait for iSCSI boot target login 85628c2ecf20Sopenharmony_ci * response. 85638c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 85648c2ecf20Sopenharmony_ci * 85658c2ecf20Sopenharmony_ci * When the boot entry is normal iSCSI target then DF_BOOT_TGT flag will be 85668c2ecf20Sopenharmony_ci * set in DDB and we will wait for login response of boot targets during 85678c2ecf20Sopenharmony_ci * probe. 85688c2ecf20Sopenharmony_ci **/ 85698c2ecf20Sopenharmony_cistatic void qla4xxx_wait_login_resp_boot_tgt(struct scsi_qla_host *ha) 85708c2ecf20Sopenharmony_ci{ 85718c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 85728c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 85738c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 85748c2ecf20Sopenharmony_ci unsigned long wtime; 85758c2ecf20Sopenharmony_ci uint32_t ddb_state; 85768c2ecf20Sopenharmony_ci int max_ddbs, idx, ret; 85778c2ecf20Sopenharmony_ci 85788c2ecf20Sopenharmony_ci max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : 85798c2ecf20Sopenharmony_ci MAX_DEV_DB_ENTRIES; 85808c2ecf20Sopenharmony_ci 85818c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 85828c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 85838c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 85848c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 85858c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 85868c2ecf20Sopenharmony_ci goto exit_login_resp; 85878c2ecf20Sopenharmony_ci } 85888c2ecf20Sopenharmony_ci 85898c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * BOOT_LOGIN_RESP_TOV); 85908c2ecf20Sopenharmony_ci 85918c2ecf20Sopenharmony_ci for (idx = 0; idx < max_ddbs; idx++) { 85928c2ecf20Sopenharmony_ci ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); 85938c2ecf20Sopenharmony_ci if (ddb_entry == NULL) 85948c2ecf20Sopenharmony_ci continue; 85958c2ecf20Sopenharmony_ci 85968c2ecf20Sopenharmony_ci if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) { 85978c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 85988c2ecf20Sopenharmony_ci "%s: DDB index [%d]\n", __func__, 85998c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index)); 86008c2ecf20Sopenharmony_ci do { 86018c2ecf20Sopenharmony_ci ret = qla4xxx_get_fwddb_entry(ha, 86028c2ecf20Sopenharmony_ci ddb_entry->fw_ddb_index, 86038c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma, 86048c2ecf20Sopenharmony_ci NULL, NULL, &ddb_state, NULL, 86058c2ecf20Sopenharmony_ci NULL, NULL); 86068c2ecf20Sopenharmony_ci if (ret == QLA_ERROR) 86078c2ecf20Sopenharmony_ci goto exit_login_resp; 86088c2ecf20Sopenharmony_ci 86098c2ecf20Sopenharmony_ci if ((ddb_state == DDB_DS_SESSION_ACTIVE) || 86108c2ecf20Sopenharmony_ci (ddb_state == DDB_DS_SESSION_FAILED)) 86118c2ecf20Sopenharmony_ci break; 86128c2ecf20Sopenharmony_ci 86138c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ); 86148c2ecf20Sopenharmony_ci 86158c2ecf20Sopenharmony_ci } while ((time_after(wtime, jiffies))); 86168c2ecf20Sopenharmony_ci 86178c2ecf20Sopenharmony_ci if (!time_after(wtime, jiffies)) { 86188c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, 86198c2ecf20Sopenharmony_ci "%s: Login response wait timer expired\n", 86208c2ecf20Sopenharmony_ci __func__)); 86218c2ecf20Sopenharmony_ci goto exit_login_resp; 86228c2ecf20Sopenharmony_ci } 86238c2ecf20Sopenharmony_ci } 86248c2ecf20Sopenharmony_ci } 86258c2ecf20Sopenharmony_ci 86268c2ecf20Sopenharmony_ciexit_login_resp: 86278c2ecf20Sopenharmony_ci if (fw_ddb_entry) 86288c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 86298c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 86308c2ecf20Sopenharmony_ci} 86318c2ecf20Sopenharmony_ci 86328c2ecf20Sopenharmony_ci/** 86338c2ecf20Sopenharmony_ci * qla4xxx_probe_adapter - callback function to probe HBA 86348c2ecf20Sopenharmony_ci * @pdev: pointer to pci_dev structure 86358c2ecf20Sopenharmony_ci * @ent: pointer to pci_device entry 86368c2ecf20Sopenharmony_ci * 86378c2ecf20Sopenharmony_ci * This routine will probe for Qlogic 4xxx iSCSI host adapters. 86388c2ecf20Sopenharmony_ci * It returns zero if successful. It also initializes all data necessary for 86398c2ecf20Sopenharmony_ci * the driver. 86408c2ecf20Sopenharmony_ci **/ 86418c2ecf20Sopenharmony_cistatic int qla4xxx_probe_adapter(struct pci_dev *pdev, 86428c2ecf20Sopenharmony_ci const struct pci_device_id *ent) 86438c2ecf20Sopenharmony_ci{ 86448c2ecf20Sopenharmony_ci int ret = -ENODEV, status; 86458c2ecf20Sopenharmony_ci struct Scsi_Host *host; 86468c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 86478c2ecf20Sopenharmony_ci uint8_t init_retry_count = 0; 86488c2ecf20Sopenharmony_ci char buf[34]; 86498c2ecf20Sopenharmony_ci struct qla4_8xxx_legacy_intr_set *nx_legacy_intr; 86508c2ecf20Sopenharmony_ci uint32_t dev_state; 86518c2ecf20Sopenharmony_ci 86528c2ecf20Sopenharmony_ci if (pci_enable_device(pdev)) 86538c2ecf20Sopenharmony_ci return -1; 86548c2ecf20Sopenharmony_ci 86558c2ecf20Sopenharmony_ci host = iscsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha), 0); 86568c2ecf20Sopenharmony_ci if (host == NULL) { 86578c2ecf20Sopenharmony_ci printk(KERN_WARNING 86588c2ecf20Sopenharmony_ci "qla4xxx: Couldn't allocate host from scsi layer!\n"); 86598c2ecf20Sopenharmony_ci goto probe_disable_device; 86608c2ecf20Sopenharmony_ci } 86618c2ecf20Sopenharmony_ci 86628c2ecf20Sopenharmony_ci /* Clear our data area */ 86638c2ecf20Sopenharmony_ci ha = to_qla_host(host); 86648c2ecf20Sopenharmony_ci memset(ha, 0, sizeof(*ha)); 86658c2ecf20Sopenharmony_ci 86668c2ecf20Sopenharmony_ci /* Save the information from PCI BIOS. */ 86678c2ecf20Sopenharmony_ci ha->pdev = pdev; 86688c2ecf20Sopenharmony_ci ha->host = host; 86698c2ecf20Sopenharmony_ci ha->host_no = host->host_no; 86708c2ecf20Sopenharmony_ci ha->func_num = PCI_FUNC(ha->pdev->devfn); 86718c2ecf20Sopenharmony_ci 86728c2ecf20Sopenharmony_ci pci_enable_pcie_error_reporting(pdev); 86738c2ecf20Sopenharmony_ci 86748c2ecf20Sopenharmony_ci /* Setup Runtime configurable options */ 86758c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 86768c2ecf20Sopenharmony_ci ha->isp_ops = &qla4_82xx_isp_ops; 86778c2ecf20Sopenharmony_ci ha->reg_tbl = (uint32_t *) qla4_82xx_reg_tbl; 86788c2ecf20Sopenharmony_ci ha->qdr_sn_window = -1; 86798c2ecf20Sopenharmony_ci ha->ddr_mn_window = -1; 86808c2ecf20Sopenharmony_ci ha->curr_window = 255; 86818c2ecf20Sopenharmony_ci nx_legacy_intr = &legacy_intr[ha->func_num]; 86828c2ecf20Sopenharmony_ci ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit; 86838c2ecf20Sopenharmony_ci ha->nx_legacy_intr.tgt_status_reg = 86848c2ecf20Sopenharmony_ci nx_legacy_intr->tgt_status_reg; 86858c2ecf20Sopenharmony_ci ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg; 86868c2ecf20Sopenharmony_ci ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; 86878c2ecf20Sopenharmony_ci } else if (is_qla8032(ha) || is_qla8042(ha)) { 86888c2ecf20Sopenharmony_ci ha->isp_ops = &qla4_83xx_isp_ops; 86898c2ecf20Sopenharmony_ci ha->reg_tbl = (uint32_t *)qla4_83xx_reg_tbl; 86908c2ecf20Sopenharmony_ci } else { 86918c2ecf20Sopenharmony_ci ha->isp_ops = &qla4xxx_isp_ops; 86928c2ecf20Sopenharmony_ci } 86938c2ecf20Sopenharmony_ci 86948c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 86958c2ecf20Sopenharmony_ci rwlock_init(&ha->hw_lock); 86968c2ecf20Sopenharmony_ci ha->pf_bit = ha->func_num << 16; 86978c2ecf20Sopenharmony_ci /* Set EEH reset type to fundamental if required by hba */ 86988c2ecf20Sopenharmony_ci pdev->needs_freset = 1; 86998c2ecf20Sopenharmony_ci } 87008c2ecf20Sopenharmony_ci 87018c2ecf20Sopenharmony_ci /* Configure PCI I/O space. */ 87028c2ecf20Sopenharmony_ci ret = ha->isp_ops->iospace_config(ha); 87038c2ecf20Sopenharmony_ci if (ret) 87048c2ecf20Sopenharmony_ci goto probe_failed_ioconfig; 87058c2ecf20Sopenharmony_ci 87068c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n", 87078c2ecf20Sopenharmony_ci pdev->device, pdev->irq, ha->reg); 87088c2ecf20Sopenharmony_ci 87098c2ecf20Sopenharmony_ci qla4xxx_config_dma_addressing(ha); 87108c2ecf20Sopenharmony_ci 87118c2ecf20Sopenharmony_ci /* Initialize lists and spinlocks. */ 87128c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->free_srb_q); 87138c2ecf20Sopenharmony_ci 87148c2ecf20Sopenharmony_ci mutex_init(&ha->mbox_sem); 87158c2ecf20Sopenharmony_ci mutex_init(&ha->chap_sem); 87168c2ecf20Sopenharmony_ci init_completion(&ha->mbx_intr_comp); 87178c2ecf20Sopenharmony_ci init_completion(&ha->disable_acb_comp); 87188c2ecf20Sopenharmony_ci init_completion(&ha->idc_comp); 87198c2ecf20Sopenharmony_ci init_completion(&ha->link_up_comp); 87208c2ecf20Sopenharmony_ci 87218c2ecf20Sopenharmony_ci spin_lock_init(&ha->hardware_lock); 87228c2ecf20Sopenharmony_ci spin_lock_init(&ha->work_lock); 87238c2ecf20Sopenharmony_ci 87248c2ecf20Sopenharmony_ci /* Initialize work list */ 87258c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ha->work_list); 87268c2ecf20Sopenharmony_ci 87278c2ecf20Sopenharmony_ci /* Allocate dma buffers */ 87288c2ecf20Sopenharmony_ci if (qla4xxx_mem_alloc(ha)) { 87298c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, 87308c2ecf20Sopenharmony_ci "[ERROR] Failed to allocate memory for adapter\n"); 87318c2ecf20Sopenharmony_ci 87328c2ecf20Sopenharmony_ci ret = -ENOMEM; 87338c2ecf20Sopenharmony_ci goto probe_failed; 87348c2ecf20Sopenharmony_ci } 87358c2ecf20Sopenharmony_ci 87368c2ecf20Sopenharmony_ci host->cmd_per_lun = 3; 87378c2ecf20Sopenharmony_ci host->max_channel = 0; 87388c2ecf20Sopenharmony_ci host->max_lun = MAX_LUNS - 1; 87398c2ecf20Sopenharmony_ci host->max_id = MAX_TARGETS; 87408c2ecf20Sopenharmony_ci host->max_cmd_len = IOCB_MAX_CDB_LEN; 87418c2ecf20Sopenharmony_ci host->can_queue = MAX_SRBS ; 87428c2ecf20Sopenharmony_ci host->transportt = qla4xxx_scsi_transport; 87438c2ecf20Sopenharmony_ci 87448c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, ha); 87458c2ecf20Sopenharmony_ci 87468c2ecf20Sopenharmony_ci ret = scsi_add_host(host, &pdev->dev); 87478c2ecf20Sopenharmony_ci if (ret) 87488c2ecf20Sopenharmony_ci goto probe_failed; 87498c2ecf20Sopenharmony_ci 87508c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 87518c2ecf20Sopenharmony_ci qla4_8xxx_get_flash_info(ha); 87528c2ecf20Sopenharmony_ci 87538c2ecf20Sopenharmony_ci if (is_qla8032(ha) || is_qla8042(ha)) { 87548c2ecf20Sopenharmony_ci qla4_83xx_read_reset_template(ha); 87558c2ecf20Sopenharmony_ci /* 87568c2ecf20Sopenharmony_ci * NOTE: If ql4dontresethba==1, set IDC_CTRL DONTRESET_BIT0. 87578c2ecf20Sopenharmony_ci * If DONRESET_BIT0 is set, drivers should not set dev_state 87588c2ecf20Sopenharmony_ci * to NEED_RESET. But if NEED_RESET is set, drivers should 87598c2ecf20Sopenharmony_ci * should honor the reset. 87608c2ecf20Sopenharmony_ci */ 87618c2ecf20Sopenharmony_ci if (ql4xdontresethba == 1) 87628c2ecf20Sopenharmony_ci qla4_83xx_set_idc_dontreset(ha); 87638c2ecf20Sopenharmony_ci } 87648c2ecf20Sopenharmony_ci 87658c2ecf20Sopenharmony_ci /* 87668c2ecf20Sopenharmony_ci * Initialize the Host adapter request/response queues and 87678c2ecf20Sopenharmony_ci * firmware 87688c2ecf20Sopenharmony_ci * NOTE: interrupts enabled upon successful completion 87698c2ecf20Sopenharmony_ci */ 87708c2ecf20Sopenharmony_ci status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); 87718c2ecf20Sopenharmony_ci 87728c2ecf20Sopenharmony_ci /* Dont retry adapter initialization if IRQ allocation failed */ 87738c2ecf20Sopenharmony_ci if (is_qla80XX(ha) && (status == QLA_ERROR)) 87748c2ecf20Sopenharmony_ci goto skip_retry_init; 87758c2ecf20Sopenharmony_ci 87768c2ecf20Sopenharmony_ci while ((!test_bit(AF_ONLINE, &ha->flags)) && 87778c2ecf20Sopenharmony_ci init_retry_count++ < MAX_INIT_RETRIES) { 87788c2ecf20Sopenharmony_ci 87798c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 87808c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 87818c2ecf20Sopenharmony_ci dev_state = qla4_8xxx_rd_direct(ha, 87828c2ecf20Sopenharmony_ci QLA8XXX_CRB_DEV_STATE); 87838c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 87848c2ecf20Sopenharmony_ci if (dev_state == QLA8XXX_DEV_FAILED) { 87858c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "%s: don't retry " 87868c2ecf20Sopenharmony_ci "initialize adapter. H/W is in failed state\n", 87878c2ecf20Sopenharmony_ci __func__); 87888c2ecf20Sopenharmony_ci break; 87898c2ecf20Sopenharmony_ci } 87908c2ecf20Sopenharmony_ci } 87918c2ecf20Sopenharmony_ci DEBUG2(printk("scsi: %s: retrying adapter initialization " 87928c2ecf20Sopenharmony_ci "(%d)\n", __func__, init_retry_count)); 87938c2ecf20Sopenharmony_ci 87948c2ecf20Sopenharmony_ci if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) 87958c2ecf20Sopenharmony_ci continue; 87968c2ecf20Sopenharmony_ci 87978c2ecf20Sopenharmony_ci status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); 87988c2ecf20Sopenharmony_ci if (is_qla80XX(ha) && (status == QLA_ERROR)) { 87998c2ecf20Sopenharmony_ci if (qla4_8xxx_check_init_adapter_retry(ha) == QLA_ERROR) 88008c2ecf20Sopenharmony_ci goto skip_retry_init; 88018c2ecf20Sopenharmony_ci } 88028c2ecf20Sopenharmony_ci } 88038c2ecf20Sopenharmony_ci 88048c2ecf20Sopenharmony_ciskip_retry_init: 88058c2ecf20Sopenharmony_ci if (!test_bit(AF_ONLINE, &ha->flags)) { 88068c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n"); 88078c2ecf20Sopenharmony_ci 88088c2ecf20Sopenharmony_ci if ((is_qla8022(ha) && ql4xdontresethba) || 88098c2ecf20Sopenharmony_ci ((is_qla8032(ha) || is_qla8042(ha)) && 88108c2ecf20Sopenharmony_ci qla4_83xx_idc_dontreset(ha))) { 88118c2ecf20Sopenharmony_ci /* Put the device in failed state. */ 88128c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n")); 88138c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 88148c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 88158c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 88168c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 88178c2ecf20Sopenharmony_ci } 88188c2ecf20Sopenharmony_ci ret = -ENODEV; 88198c2ecf20Sopenharmony_ci goto remove_host; 88208c2ecf20Sopenharmony_ci } 88218c2ecf20Sopenharmony_ci 88228c2ecf20Sopenharmony_ci /* Startup the kernel thread for this host adapter. */ 88238c2ecf20Sopenharmony_ci DEBUG2(printk("scsi: %s: Starting kernel thread for " 88248c2ecf20Sopenharmony_ci "qla4xxx_dpc\n", __func__)); 88258c2ecf20Sopenharmony_ci sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no); 88268c2ecf20Sopenharmony_ci ha->dpc_thread = create_singlethread_workqueue(buf); 88278c2ecf20Sopenharmony_ci if (!ha->dpc_thread) { 88288c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n"); 88298c2ecf20Sopenharmony_ci ret = -ENODEV; 88308c2ecf20Sopenharmony_ci goto remove_host; 88318c2ecf20Sopenharmony_ci } 88328c2ecf20Sopenharmony_ci INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc); 88338c2ecf20Sopenharmony_ci 88348c2ecf20Sopenharmony_ci ha->task_wq = alloc_workqueue("qla4xxx_%lu_task", WQ_MEM_RECLAIM, 1, 88358c2ecf20Sopenharmony_ci ha->host_no); 88368c2ecf20Sopenharmony_ci if (!ha->task_wq) { 88378c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n"); 88388c2ecf20Sopenharmony_ci ret = -ENODEV; 88398c2ecf20Sopenharmony_ci goto remove_host; 88408c2ecf20Sopenharmony_ci } 88418c2ecf20Sopenharmony_ci 88428c2ecf20Sopenharmony_ci /* 88438c2ecf20Sopenharmony_ci * For ISP-8XXX, request_irqs is called in qla4_8xxx_load_risc 88448c2ecf20Sopenharmony_ci * (which is called indirectly by qla4xxx_initialize_adapter), 88458c2ecf20Sopenharmony_ci * so that irqs will be registered after crbinit but before 88468c2ecf20Sopenharmony_ci * mbx_intr_enable. 88478c2ecf20Sopenharmony_ci */ 88488c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) { 88498c2ecf20Sopenharmony_ci ret = qla4xxx_request_irqs(ha); 88508c2ecf20Sopenharmony_ci if (ret) { 88518c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "Failed to reserve " 88528c2ecf20Sopenharmony_ci "interrupt %d already in use.\n", pdev->irq); 88538c2ecf20Sopenharmony_ci goto remove_host; 88548c2ecf20Sopenharmony_ci } 88558c2ecf20Sopenharmony_ci } 88568c2ecf20Sopenharmony_ci 88578c2ecf20Sopenharmony_ci pci_save_state(ha->pdev); 88588c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 88598c2ecf20Sopenharmony_ci 88608c2ecf20Sopenharmony_ci /* Start timer thread. */ 88618c2ecf20Sopenharmony_ci qla4xxx_start_timer(ha, 1); 88628c2ecf20Sopenharmony_ci 88638c2ecf20Sopenharmony_ci set_bit(AF_INIT_DONE, &ha->flags); 88648c2ecf20Sopenharmony_ci 88658c2ecf20Sopenharmony_ci qla4_8xxx_alloc_sysfs_attr(ha); 88668c2ecf20Sopenharmony_ci 88678c2ecf20Sopenharmony_ci printk(KERN_INFO 88688c2ecf20Sopenharmony_ci " QLogic iSCSI HBA Driver version: %s\n" 88698c2ecf20Sopenharmony_ci " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", 88708c2ecf20Sopenharmony_ci qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev), 88718c2ecf20Sopenharmony_ci ha->host_no, ha->fw_info.fw_major, ha->fw_info.fw_minor, 88728c2ecf20Sopenharmony_ci ha->fw_info.fw_patch, ha->fw_info.fw_build); 88738c2ecf20Sopenharmony_ci 88748c2ecf20Sopenharmony_ci /* Set the driver version */ 88758c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 88768c2ecf20Sopenharmony_ci qla4_8xxx_set_param(ha, SET_DRVR_VERSION); 88778c2ecf20Sopenharmony_ci 88788c2ecf20Sopenharmony_ci if (qla4xxx_setup_boot_info(ha)) 88798c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 88808c2ecf20Sopenharmony_ci "%s: No iSCSI boot target configured\n", __func__); 88818c2ecf20Sopenharmony_ci 88828c2ecf20Sopenharmony_ci set_bit(DPC_SYSFS_DDB_EXPORT, &ha->dpc_flags); 88838c2ecf20Sopenharmony_ci /* Perform the build ddb list and login to each */ 88848c2ecf20Sopenharmony_ci qla4xxx_build_ddb_list(ha, INIT_ADAPTER); 88858c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); 88868c2ecf20Sopenharmony_ci qla4xxx_wait_login_resp_boot_tgt(ha); 88878c2ecf20Sopenharmony_ci 88888c2ecf20Sopenharmony_ci qla4xxx_create_chap_list(ha); 88898c2ecf20Sopenharmony_ci 88908c2ecf20Sopenharmony_ci qla4xxx_create_ifaces(ha); 88918c2ecf20Sopenharmony_ci return 0; 88928c2ecf20Sopenharmony_ci 88938c2ecf20Sopenharmony_ciremove_host: 88948c2ecf20Sopenharmony_ci scsi_remove_host(ha->host); 88958c2ecf20Sopenharmony_ci 88968c2ecf20Sopenharmony_ciprobe_failed: 88978c2ecf20Sopenharmony_ci qla4xxx_free_adapter(ha); 88988c2ecf20Sopenharmony_ci 88998c2ecf20Sopenharmony_ciprobe_failed_ioconfig: 89008c2ecf20Sopenharmony_ci pci_disable_pcie_error_reporting(pdev); 89018c2ecf20Sopenharmony_ci scsi_host_put(ha->host); 89028c2ecf20Sopenharmony_ci 89038c2ecf20Sopenharmony_ciprobe_disable_device: 89048c2ecf20Sopenharmony_ci pci_disable_device(pdev); 89058c2ecf20Sopenharmony_ci 89068c2ecf20Sopenharmony_ci return ret; 89078c2ecf20Sopenharmony_ci} 89088c2ecf20Sopenharmony_ci 89098c2ecf20Sopenharmony_ci/** 89108c2ecf20Sopenharmony_ci * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize 89118c2ecf20Sopenharmony_ci * @ha: pointer to adapter structure 89128c2ecf20Sopenharmony_ci * 89138c2ecf20Sopenharmony_ci * Mark the other ISP-4xxx port to indicate that the driver is being removed, 89148c2ecf20Sopenharmony_ci * so that the other port will not re-initialize while in the process of 89158c2ecf20Sopenharmony_ci * removing the ha due to driver unload or hba hotplug. 89168c2ecf20Sopenharmony_ci **/ 89178c2ecf20Sopenharmony_cistatic void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha) 89188c2ecf20Sopenharmony_ci{ 89198c2ecf20Sopenharmony_ci struct scsi_qla_host *other_ha = NULL; 89208c2ecf20Sopenharmony_ci struct pci_dev *other_pdev = NULL; 89218c2ecf20Sopenharmony_ci int fn = ISP4XXX_PCI_FN_2; 89228c2ecf20Sopenharmony_ci 89238c2ecf20Sopenharmony_ci /*iscsi function numbers for ISP4xxx is 1 and 3*/ 89248c2ecf20Sopenharmony_ci if (PCI_FUNC(ha->pdev->devfn) & BIT_1) 89258c2ecf20Sopenharmony_ci fn = ISP4XXX_PCI_FN_1; 89268c2ecf20Sopenharmony_ci 89278c2ecf20Sopenharmony_ci other_pdev = 89288c2ecf20Sopenharmony_ci pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus), 89298c2ecf20Sopenharmony_ci ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), 89308c2ecf20Sopenharmony_ci fn)); 89318c2ecf20Sopenharmony_ci 89328c2ecf20Sopenharmony_ci /* Get other_ha if other_pdev is valid and state is enable*/ 89338c2ecf20Sopenharmony_ci if (other_pdev) { 89348c2ecf20Sopenharmony_ci if (atomic_read(&other_pdev->enable_cnt)) { 89358c2ecf20Sopenharmony_ci other_ha = pci_get_drvdata(other_pdev); 89368c2ecf20Sopenharmony_ci if (other_ha) { 89378c2ecf20Sopenharmony_ci set_bit(AF_HA_REMOVAL, &other_ha->flags); 89388c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: " 89398c2ecf20Sopenharmony_ci "Prevent %s reinit\n", __func__, 89408c2ecf20Sopenharmony_ci dev_name(&other_ha->pdev->dev))); 89418c2ecf20Sopenharmony_ci } 89428c2ecf20Sopenharmony_ci } 89438c2ecf20Sopenharmony_ci pci_dev_put(other_pdev); 89448c2ecf20Sopenharmony_ci } 89458c2ecf20Sopenharmony_ci} 89468c2ecf20Sopenharmony_ci 89478c2ecf20Sopenharmony_cistatic void qla4xxx_destroy_ddb(struct scsi_qla_host *ha, 89488c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry) 89498c2ecf20Sopenharmony_ci{ 89508c2ecf20Sopenharmony_ci struct dev_db_entry *fw_ddb_entry = NULL; 89518c2ecf20Sopenharmony_ci dma_addr_t fw_ddb_entry_dma; 89528c2ecf20Sopenharmony_ci unsigned long wtime; 89538c2ecf20Sopenharmony_ci uint32_t ddb_state; 89548c2ecf20Sopenharmony_ci int options; 89558c2ecf20Sopenharmony_ci int status; 89568c2ecf20Sopenharmony_ci 89578c2ecf20Sopenharmony_ci options = LOGOUT_OPTION_CLOSE_SESSION; 89588c2ecf20Sopenharmony_ci if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR) { 89598c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__); 89608c2ecf20Sopenharmony_ci goto clear_ddb; 89618c2ecf20Sopenharmony_ci } 89628c2ecf20Sopenharmony_ci 89638c2ecf20Sopenharmony_ci fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 89648c2ecf20Sopenharmony_ci &fw_ddb_entry_dma, GFP_KERNEL); 89658c2ecf20Sopenharmony_ci if (!fw_ddb_entry) { 89668c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, 89678c2ecf20Sopenharmony_ci "%s: Unable to allocate dma buffer\n", __func__); 89688c2ecf20Sopenharmony_ci goto clear_ddb; 89698c2ecf20Sopenharmony_ci } 89708c2ecf20Sopenharmony_ci 89718c2ecf20Sopenharmony_ci wtime = jiffies + (HZ * LOGOUT_TOV); 89728c2ecf20Sopenharmony_ci do { 89738c2ecf20Sopenharmony_ci status = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, 89748c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma, 89758c2ecf20Sopenharmony_ci NULL, NULL, &ddb_state, NULL, 89768c2ecf20Sopenharmony_ci NULL, NULL); 89778c2ecf20Sopenharmony_ci if (status == QLA_ERROR) 89788c2ecf20Sopenharmony_ci goto free_ddb; 89798c2ecf20Sopenharmony_ci 89808c2ecf20Sopenharmony_ci if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || 89818c2ecf20Sopenharmony_ci (ddb_state == DDB_DS_SESSION_FAILED)) 89828c2ecf20Sopenharmony_ci goto free_ddb; 89838c2ecf20Sopenharmony_ci 89848c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(HZ); 89858c2ecf20Sopenharmony_ci } while ((time_after(wtime, jiffies))); 89868c2ecf20Sopenharmony_ci 89878c2ecf20Sopenharmony_cifree_ddb: 89888c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 89898c2ecf20Sopenharmony_ci fw_ddb_entry, fw_ddb_entry_dma); 89908c2ecf20Sopenharmony_ciclear_ddb: 89918c2ecf20Sopenharmony_ci qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); 89928c2ecf20Sopenharmony_ci} 89938c2ecf20Sopenharmony_ci 89948c2ecf20Sopenharmony_cistatic void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha) 89958c2ecf20Sopenharmony_ci{ 89968c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry; 89978c2ecf20Sopenharmony_ci int idx; 89988c2ecf20Sopenharmony_ci 89998c2ecf20Sopenharmony_ci for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { 90008c2ecf20Sopenharmony_ci 90018c2ecf20Sopenharmony_ci ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); 90028c2ecf20Sopenharmony_ci if ((ddb_entry != NULL) && 90038c2ecf20Sopenharmony_ci (ddb_entry->ddb_type == FLASH_DDB)) { 90048c2ecf20Sopenharmony_ci 90058c2ecf20Sopenharmony_ci qla4xxx_destroy_ddb(ha, ddb_entry); 90068c2ecf20Sopenharmony_ci /* 90078c2ecf20Sopenharmony_ci * we have decremented the reference count of the driver 90088c2ecf20Sopenharmony_ci * when we setup the session to have the driver unload 90098c2ecf20Sopenharmony_ci * to be seamless without actually destroying the 90108c2ecf20Sopenharmony_ci * session 90118c2ecf20Sopenharmony_ci **/ 90128c2ecf20Sopenharmony_ci try_module_get(qla4xxx_iscsi_transport.owner); 90138c2ecf20Sopenharmony_ci iscsi_destroy_endpoint(ddb_entry->conn->ep); 90148c2ecf20Sopenharmony_ci qla4xxx_free_ddb(ha, ddb_entry); 90158c2ecf20Sopenharmony_ci iscsi_session_teardown(ddb_entry->sess); 90168c2ecf20Sopenharmony_ci } 90178c2ecf20Sopenharmony_ci } 90188c2ecf20Sopenharmony_ci} 90198c2ecf20Sopenharmony_ci/** 90208c2ecf20Sopenharmony_ci * qla4xxx_remove_adapter - callback function to remove adapter. 90218c2ecf20Sopenharmony_ci * @pdev: PCI device pointer 90228c2ecf20Sopenharmony_ci **/ 90238c2ecf20Sopenharmony_cistatic void qla4xxx_remove_adapter(struct pci_dev *pdev) 90248c2ecf20Sopenharmony_ci{ 90258c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 90268c2ecf20Sopenharmony_ci 90278c2ecf20Sopenharmony_ci /* 90288c2ecf20Sopenharmony_ci * If the PCI device is disabled then it means probe_adapter had 90298c2ecf20Sopenharmony_ci * failed and resources already cleaned up on probe_adapter exit. 90308c2ecf20Sopenharmony_ci */ 90318c2ecf20Sopenharmony_ci if (!pci_is_enabled(pdev)) 90328c2ecf20Sopenharmony_ci return; 90338c2ecf20Sopenharmony_ci 90348c2ecf20Sopenharmony_ci ha = pci_get_drvdata(pdev); 90358c2ecf20Sopenharmony_ci 90368c2ecf20Sopenharmony_ci if (is_qla40XX(ha)) 90378c2ecf20Sopenharmony_ci qla4xxx_prevent_other_port_reinit(ha); 90388c2ecf20Sopenharmony_ci 90398c2ecf20Sopenharmony_ci /* destroy iface from sysfs */ 90408c2ecf20Sopenharmony_ci qla4xxx_destroy_ifaces(ha); 90418c2ecf20Sopenharmony_ci 90428c2ecf20Sopenharmony_ci if ((!ql4xdisablesysfsboot) && ha->boot_kset) 90438c2ecf20Sopenharmony_ci iscsi_boot_destroy_kset(ha->boot_kset); 90448c2ecf20Sopenharmony_ci 90458c2ecf20Sopenharmony_ci qla4xxx_destroy_fw_ddb_session(ha); 90468c2ecf20Sopenharmony_ci qla4_8xxx_free_sysfs_attr(ha); 90478c2ecf20Sopenharmony_ci 90488c2ecf20Sopenharmony_ci qla4xxx_sysfs_ddb_remove(ha); 90498c2ecf20Sopenharmony_ci scsi_remove_host(ha->host); 90508c2ecf20Sopenharmony_ci 90518c2ecf20Sopenharmony_ci qla4xxx_free_adapter(ha); 90528c2ecf20Sopenharmony_ci 90538c2ecf20Sopenharmony_ci scsi_host_put(ha->host); 90548c2ecf20Sopenharmony_ci 90558c2ecf20Sopenharmony_ci pci_disable_pcie_error_reporting(pdev); 90568c2ecf20Sopenharmony_ci pci_disable_device(pdev); 90578c2ecf20Sopenharmony_ci} 90588c2ecf20Sopenharmony_ci 90598c2ecf20Sopenharmony_ci/** 90608c2ecf20Sopenharmony_ci * qla4xxx_config_dma_addressing() - Configure OS DMA addressing method. 90618c2ecf20Sopenharmony_ci * @ha: HA context 90628c2ecf20Sopenharmony_ci */ 90638c2ecf20Sopenharmony_cistatic void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) 90648c2ecf20Sopenharmony_ci{ 90658c2ecf20Sopenharmony_ci /* Update our PCI device dma_mask for full 64 bit mask */ 90668c2ecf20Sopenharmony_ci if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) { 90678c2ecf20Sopenharmony_ci dev_dbg(&ha->pdev->dev, 90688c2ecf20Sopenharmony_ci "Failed to set 64 bit PCI consistent mask; " 90698c2ecf20Sopenharmony_ci "using 32 bit.\n"); 90708c2ecf20Sopenharmony_ci dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(32)); 90718c2ecf20Sopenharmony_ci } 90728c2ecf20Sopenharmony_ci} 90738c2ecf20Sopenharmony_ci 90748c2ecf20Sopenharmony_cistatic int qla4xxx_slave_alloc(struct scsi_device *sdev) 90758c2ecf20Sopenharmony_ci{ 90768c2ecf20Sopenharmony_ci struct iscsi_cls_session *cls_sess; 90778c2ecf20Sopenharmony_ci struct iscsi_session *sess; 90788c2ecf20Sopenharmony_ci struct ddb_entry *ddb; 90798c2ecf20Sopenharmony_ci int queue_depth = QL4_DEF_QDEPTH; 90808c2ecf20Sopenharmony_ci 90818c2ecf20Sopenharmony_ci cls_sess = starget_to_session(sdev->sdev_target); 90828c2ecf20Sopenharmony_ci sess = cls_sess->dd_data; 90838c2ecf20Sopenharmony_ci ddb = sess->dd_data; 90848c2ecf20Sopenharmony_ci 90858c2ecf20Sopenharmony_ci sdev->hostdata = ddb; 90868c2ecf20Sopenharmony_ci 90878c2ecf20Sopenharmony_ci if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU) 90888c2ecf20Sopenharmony_ci queue_depth = ql4xmaxqdepth; 90898c2ecf20Sopenharmony_ci 90908c2ecf20Sopenharmony_ci scsi_change_queue_depth(sdev, queue_depth); 90918c2ecf20Sopenharmony_ci return 0; 90928c2ecf20Sopenharmony_ci} 90938c2ecf20Sopenharmony_ci 90948c2ecf20Sopenharmony_ci/** 90958c2ecf20Sopenharmony_ci * qla4xxx_del_from_active_array - returns an active srb 90968c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 90978c2ecf20Sopenharmony_ci * @index: index into the active_array 90988c2ecf20Sopenharmony_ci * 90998c2ecf20Sopenharmony_ci * This routine removes and returns the srb at the specified index 91008c2ecf20Sopenharmony_ci **/ 91018c2ecf20Sopenharmony_cistruct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, 91028c2ecf20Sopenharmony_ci uint32_t index) 91038c2ecf20Sopenharmony_ci{ 91048c2ecf20Sopenharmony_ci struct srb *srb = NULL; 91058c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd = NULL; 91068c2ecf20Sopenharmony_ci 91078c2ecf20Sopenharmony_ci cmd = scsi_host_find_tag(ha->host, index); 91088c2ecf20Sopenharmony_ci if (!cmd) 91098c2ecf20Sopenharmony_ci return srb; 91108c2ecf20Sopenharmony_ci 91118c2ecf20Sopenharmony_ci srb = (struct srb *)CMD_SP(cmd); 91128c2ecf20Sopenharmony_ci if (!srb) 91138c2ecf20Sopenharmony_ci return srb; 91148c2ecf20Sopenharmony_ci 91158c2ecf20Sopenharmony_ci /* update counters */ 91168c2ecf20Sopenharmony_ci if (srb->flags & SRB_DMA_VALID) { 91178c2ecf20Sopenharmony_ci ha->iocb_cnt -= srb->iocb_cnt; 91188c2ecf20Sopenharmony_ci if (srb->cmd) 91198c2ecf20Sopenharmony_ci srb->cmd->host_scribble = 91208c2ecf20Sopenharmony_ci (unsigned char *)(unsigned long) MAX_SRBS; 91218c2ecf20Sopenharmony_ci } 91228c2ecf20Sopenharmony_ci return srb; 91238c2ecf20Sopenharmony_ci} 91248c2ecf20Sopenharmony_ci 91258c2ecf20Sopenharmony_ci/** 91268c2ecf20Sopenharmony_ci * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware 91278c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure. 91288c2ecf20Sopenharmony_ci * @cmd: Scsi Command to wait on. 91298c2ecf20Sopenharmony_ci * 91308c2ecf20Sopenharmony_ci * This routine waits for the command to be returned by the Firmware 91318c2ecf20Sopenharmony_ci * for some max time. 91328c2ecf20Sopenharmony_ci **/ 91338c2ecf20Sopenharmony_cistatic int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, 91348c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd) 91358c2ecf20Sopenharmony_ci{ 91368c2ecf20Sopenharmony_ci int done = 0; 91378c2ecf20Sopenharmony_ci struct srb *rp; 91388c2ecf20Sopenharmony_ci uint32_t max_wait_time = EH_WAIT_CMD_TOV; 91398c2ecf20Sopenharmony_ci int ret = SUCCESS; 91408c2ecf20Sopenharmony_ci 91418c2ecf20Sopenharmony_ci /* Dont wait on command if PCI error is being handled 91428c2ecf20Sopenharmony_ci * by PCI AER driver 91438c2ecf20Sopenharmony_ci */ 91448c2ecf20Sopenharmony_ci if (unlikely(pci_channel_offline(ha->pdev)) || 91458c2ecf20Sopenharmony_ci (test_bit(AF_EEH_BUSY, &ha->flags))) { 91468c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n", 91478c2ecf20Sopenharmony_ci ha->host_no, __func__); 91488c2ecf20Sopenharmony_ci return ret; 91498c2ecf20Sopenharmony_ci } 91508c2ecf20Sopenharmony_ci 91518c2ecf20Sopenharmony_ci do { 91528c2ecf20Sopenharmony_ci /* Checking to see if its returned to OS */ 91538c2ecf20Sopenharmony_ci rp = (struct srb *) CMD_SP(cmd); 91548c2ecf20Sopenharmony_ci if (rp == NULL) { 91558c2ecf20Sopenharmony_ci done++; 91568c2ecf20Sopenharmony_ci break; 91578c2ecf20Sopenharmony_ci } 91588c2ecf20Sopenharmony_ci 91598c2ecf20Sopenharmony_ci msleep(2000); 91608c2ecf20Sopenharmony_ci } while (max_wait_time--); 91618c2ecf20Sopenharmony_ci 91628c2ecf20Sopenharmony_ci return done; 91638c2ecf20Sopenharmony_ci} 91648c2ecf20Sopenharmony_ci 91658c2ecf20Sopenharmony_ci/** 91668c2ecf20Sopenharmony_ci * qla4xxx_wait_for_hba_online - waits for HBA to come online 91678c2ecf20Sopenharmony_ci * @ha: Pointer to host adapter structure 91688c2ecf20Sopenharmony_ci **/ 91698c2ecf20Sopenharmony_cistatic int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha) 91708c2ecf20Sopenharmony_ci{ 91718c2ecf20Sopenharmony_ci unsigned long wait_online; 91728c2ecf20Sopenharmony_ci 91738c2ecf20Sopenharmony_ci wait_online = jiffies + (HBA_ONLINE_TOV * HZ); 91748c2ecf20Sopenharmony_ci while (time_before(jiffies, wait_online)) { 91758c2ecf20Sopenharmony_ci 91768c2ecf20Sopenharmony_ci if (adapter_up(ha)) 91778c2ecf20Sopenharmony_ci return QLA_SUCCESS; 91788c2ecf20Sopenharmony_ci 91798c2ecf20Sopenharmony_ci msleep(2000); 91808c2ecf20Sopenharmony_ci } 91818c2ecf20Sopenharmony_ci 91828c2ecf20Sopenharmony_ci return QLA_ERROR; 91838c2ecf20Sopenharmony_ci} 91848c2ecf20Sopenharmony_ci 91858c2ecf20Sopenharmony_ci/** 91868c2ecf20Sopenharmony_ci * qla4xxx_eh_wait_for_commands - wait for active cmds to finish. 91878c2ecf20Sopenharmony_ci * @ha: pointer to HBA 91888c2ecf20Sopenharmony_ci * @stgt: pointer to SCSI target 91898c2ecf20Sopenharmony_ci * @sdev: pointer to SCSI device 91908c2ecf20Sopenharmony_ci * 91918c2ecf20Sopenharmony_ci * This function waits for all outstanding commands to a lun to complete. It 91928c2ecf20Sopenharmony_ci * returns 0 if all pending commands are returned and 1 otherwise. 91938c2ecf20Sopenharmony_ci **/ 91948c2ecf20Sopenharmony_cistatic int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha, 91958c2ecf20Sopenharmony_ci struct scsi_target *stgt, 91968c2ecf20Sopenharmony_ci struct scsi_device *sdev) 91978c2ecf20Sopenharmony_ci{ 91988c2ecf20Sopenharmony_ci int cnt; 91998c2ecf20Sopenharmony_ci int status = 0; 92008c2ecf20Sopenharmony_ci struct scsi_cmnd *cmd; 92018c2ecf20Sopenharmony_ci 92028c2ecf20Sopenharmony_ci /* 92038c2ecf20Sopenharmony_ci * Waiting for all commands for the designated target or dev 92048c2ecf20Sopenharmony_ci * in the active array 92058c2ecf20Sopenharmony_ci */ 92068c2ecf20Sopenharmony_ci for (cnt = 0; cnt < ha->host->can_queue; cnt++) { 92078c2ecf20Sopenharmony_ci cmd = scsi_host_find_tag(ha->host, cnt); 92088c2ecf20Sopenharmony_ci if (cmd && stgt == scsi_target(cmd->device) && 92098c2ecf20Sopenharmony_ci (!sdev || sdev == cmd->device)) { 92108c2ecf20Sopenharmony_ci if (!qla4xxx_eh_wait_on_command(ha, cmd)) { 92118c2ecf20Sopenharmony_ci status++; 92128c2ecf20Sopenharmony_ci break; 92138c2ecf20Sopenharmony_ci } 92148c2ecf20Sopenharmony_ci } 92158c2ecf20Sopenharmony_ci } 92168c2ecf20Sopenharmony_ci return status; 92178c2ecf20Sopenharmony_ci} 92188c2ecf20Sopenharmony_ci 92198c2ecf20Sopenharmony_ci/** 92208c2ecf20Sopenharmony_ci * qla4xxx_eh_abort - callback for abort task. 92218c2ecf20Sopenharmony_ci * @cmd: Pointer to Linux's SCSI command structure 92228c2ecf20Sopenharmony_ci * 92238c2ecf20Sopenharmony_ci * This routine is called by the Linux OS to abort the specified 92248c2ecf20Sopenharmony_ci * command. 92258c2ecf20Sopenharmony_ci **/ 92268c2ecf20Sopenharmony_cistatic int qla4xxx_eh_abort(struct scsi_cmnd *cmd) 92278c2ecf20Sopenharmony_ci{ 92288c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(cmd->device->host); 92298c2ecf20Sopenharmony_ci unsigned int id = cmd->device->id; 92308c2ecf20Sopenharmony_ci uint64_t lun = cmd->device->lun; 92318c2ecf20Sopenharmony_ci unsigned long flags; 92328c2ecf20Sopenharmony_ci struct srb *srb = NULL; 92338c2ecf20Sopenharmony_ci int ret = SUCCESS; 92348c2ecf20Sopenharmony_ci int wait = 0; 92358c2ecf20Sopenharmony_ci int rval; 92368c2ecf20Sopenharmony_ci 92378c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n", 92388c2ecf20Sopenharmony_ci ha->host_no, id, lun, cmd, cmd->cmnd[0]); 92398c2ecf20Sopenharmony_ci 92408c2ecf20Sopenharmony_ci rval = qla4xxx_isp_check_reg(ha); 92418c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 92428c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); 92438c2ecf20Sopenharmony_ci return FAILED; 92448c2ecf20Sopenharmony_ci } 92458c2ecf20Sopenharmony_ci 92468c2ecf20Sopenharmony_ci spin_lock_irqsave(&ha->hardware_lock, flags); 92478c2ecf20Sopenharmony_ci srb = (struct srb *) CMD_SP(cmd); 92488c2ecf20Sopenharmony_ci if (!srb) { 92498c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 92508c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Specified command has already completed.\n", 92518c2ecf20Sopenharmony_ci ha->host_no, id, lun); 92528c2ecf20Sopenharmony_ci return SUCCESS; 92538c2ecf20Sopenharmony_ci } 92548c2ecf20Sopenharmony_ci kref_get(&srb->srb_ref); 92558c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ha->hardware_lock, flags); 92568c2ecf20Sopenharmony_ci 92578c2ecf20Sopenharmony_ci if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) { 92588c2ecf20Sopenharmony_ci DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx failed.\n", 92598c2ecf20Sopenharmony_ci ha->host_no, id, lun)); 92608c2ecf20Sopenharmony_ci ret = FAILED; 92618c2ecf20Sopenharmony_ci } else { 92628c2ecf20Sopenharmony_ci DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx success.\n", 92638c2ecf20Sopenharmony_ci ha->host_no, id, lun)); 92648c2ecf20Sopenharmony_ci wait = 1; 92658c2ecf20Sopenharmony_ci } 92668c2ecf20Sopenharmony_ci 92678c2ecf20Sopenharmony_ci kref_put(&srb->srb_ref, qla4xxx_srb_compl); 92688c2ecf20Sopenharmony_ci 92698c2ecf20Sopenharmony_ci /* Wait for command to complete */ 92708c2ecf20Sopenharmony_ci if (wait) { 92718c2ecf20Sopenharmony_ci if (!qla4xxx_eh_wait_on_command(ha, cmd)) { 92728c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld:%d:%llu: Abort handler timed out\n", 92738c2ecf20Sopenharmony_ci ha->host_no, id, lun)); 92748c2ecf20Sopenharmony_ci ret = FAILED; 92758c2ecf20Sopenharmony_ci } 92768c2ecf20Sopenharmony_ci } 92778c2ecf20Sopenharmony_ci 92788c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 92798c2ecf20Sopenharmony_ci "scsi%ld:%d:%llu: Abort command - %s\n", 92808c2ecf20Sopenharmony_ci ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed"); 92818c2ecf20Sopenharmony_ci 92828c2ecf20Sopenharmony_ci return ret; 92838c2ecf20Sopenharmony_ci} 92848c2ecf20Sopenharmony_ci 92858c2ecf20Sopenharmony_ci/** 92868c2ecf20Sopenharmony_ci * qla4xxx_eh_device_reset - callback for target reset. 92878c2ecf20Sopenharmony_ci * @cmd: Pointer to Linux's SCSI command structure 92888c2ecf20Sopenharmony_ci * 92898c2ecf20Sopenharmony_ci * This routine is called by the Linux OS to reset all luns on the 92908c2ecf20Sopenharmony_ci * specified target. 92918c2ecf20Sopenharmony_ci **/ 92928c2ecf20Sopenharmony_cistatic int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) 92938c2ecf20Sopenharmony_ci{ 92948c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(cmd->device->host); 92958c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = cmd->device->hostdata; 92968c2ecf20Sopenharmony_ci int ret = FAILED, stat; 92978c2ecf20Sopenharmony_ci int rval; 92988c2ecf20Sopenharmony_ci 92998c2ecf20Sopenharmony_ci if (!ddb_entry) 93008c2ecf20Sopenharmony_ci return ret; 93018c2ecf20Sopenharmony_ci 93028c2ecf20Sopenharmony_ci ret = iscsi_block_scsi_eh(cmd); 93038c2ecf20Sopenharmony_ci if (ret) 93048c2ecf20Sopenharmony_ci return ret; 93058c2ecf20Sopenharmony_ci ret = FAILED; 93068c2ecf20Sopenharmony_ci 93078c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 93088c2ecf20Sopenharmony_ci "scsi%ld:%d:%d:%llu: DEVICE RESET ISSUED.\n", ha->host_no, 93098c2ecf20Sopenharmony_ci cmd->device->channel, cmd->device->id, cmd->device->lun); 93108c2ecf20Sopenharmony_ci 93118c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO 93128c2ecf20Sopenharmony_ci "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x," 93138c2ecf20Sopenharmony_ci "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no, 93148c2ecf20Sopenharmony_ci cmd, jiffies, cmd->request->timeout / HZ, 93158c2ecf20Sopenharmony_ci ha->dpc_flags, cmd->result, cmd->allowed)); 93168c2ecf20Sopenharmony_ci 93178c2ecf20Sopenharmony_ci rval = qla4xxx_isp_check_reg(ha); 93188c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 93198c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); 93208c2ecf20Sopenharmony_ci return FAILED; 93218c2ecf20Sopenharmony_ci } 93228c2ecf20Sopenharmony_ci 93238c2ecf20Sopenharmony_ci /* FIXME: wait for hba to go online */ 93248c2ecf20Sopenharmony_ci stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun); 93258c2ecf20Sopenharmony_ci if (stat != QLA_SUCCESS) { 93268c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat); 93278c2ecf20Sopenharmony_ci goto eh_dev_reset_done; 93288c2ecf20Sopenharmony_ci } 93298c2ecf20Sopenharmony_ci 93308c2ecf20Sopenharmony_ci if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), 93318c2ecf20Sopenharmony_ci cmd->device)) { 93328c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 93338c2ecf20Sopenharmony_ci "DEVICE RESET FAILED - waiting for " 93348c2ecf20Sopenharmony_ci "commands.\n"); 93358c2ecf20Sopenharmony_ci goto eh_dev_reset_done; 93368c2ecf20Sopenharmony_ci } 93378c2ecf20Sopenharmony_ci 93388c2ecf20Sopenharmony_ci /* Send marker. */ 93398c2ecf20Sopenharmony_ci if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun, 93408c2ecf20Sopenharmony_ci MM_LUN_RESET) != QLA_SUCCESS) 93418c2ecf20Sopenharmony_ci goto eh_dev_reset_done; 93428c2ecf20Sopenharmony_ci 93438c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 93448c2ecf20Sopenharmony_ci "scsi(%ld:%d:%d:%llu): DEVICE RESET SUCCEEDED.\n", 93458c2ecf20Sopenharmony_ci ha->host_no, cmd->device->channel, cmd->device->id, 93468c2ecf20Sopenharmony_ci cmd->device->lun); 93478c2ecf20Sopenharmony_ci 93488c2ecf20Sopenharmony_ci ret = SUCCESS; 93498c2ecf20Sopenharmony_ci 93508c2ecf20Sopenharmony_cieh_dev_reset_done: 93518c2ecf20Sopenharmony_ci 93528c2ecf20Sopenharmony_ci return ret; 93538c2ecf20Sopenharmony_ci} 93548c2ecf20Sopenharmony_ci 93558c2ecf20Sopenharmony_ci/** 93568c2ecf20Sopenharmony_ci * qla4xxx_eh_target_reset - callback for target reset. 93578c2ecf20Sopenharmony_ci * @cmd: Pointer to Linux's SCSI command structure 93588c2ecf20Sopenharmony_ci * 93598c2ecf20Sopenharmony_ci * This routine is called by the Linux OS to reset the target. 93608c2ecf20Sopenharmony_ci **/ 93618c2ecf20Sopenharmony_cistatic int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd) 93628c2ecf20Sopenharmony_ci{ 93638c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(cmd->device->host); 93648c2ecf20Sopenharmony_ci struct ddb_entry *ddb_entry = cmd->device->hostdata; 93658c2ecf20Sopenharmony_ci int stat, ret; 93668c2ecf20Sopenharmony_ci int rval; 93678c2ecf20Sopenharmony_ci 93688c2ecf20Sopenharmony_ci if (!ddb_entry) 93698c2ecf20Sopenharmony_ci return FAILED; 93708c2ecf20Sopenharmony_ci 93718c2ecf20Sopenharmony_ci ret = iscsi_block_scsi_eh(cmd); 93728c2ecf20Sopenharmony_ci if (ret) 93738c2ecf20Sopenharmony_ci return ret; 93748c2ecf20Sopenharmony_ci 93758c2ecf20Sopenharmony_ci starget_printk(KERN_INFO, scsi_target(cmd->device), 93768c2ecf20Sopenharmony_ci "WARM TARGET RESET ISSUED.\n"); 93778c2ecf20Sopenharmony_ci 93788c2ecf20Sopenharmony_ci DEBUG2(printk(KERN_INFO 93798c2ecf20Sopenharmony_ci "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, " 93808c2ecf20Sopenharmony_ci "to=%x,dpc_flags=%lx, status=%x allowed=%d\n", 93818c2ecf20Sopenharmony_ci ha->host_no, cmd, jiffies, cmd->request->timeout / HZ, 93828c2ecf20Sopenharmony_ci ha->dpc_flags, cmd->result, cmd->allowed)); 93838c2ecf20Sopenharmony_ci 93848c2ecf20Sopenharmony_ci rval = qla4xxx_isp_check_reg(ha); 93858c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 93868c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); 93878c2ecf20Sopenharmony_ci return FAILED; 93888c2ecf20Sopenharmony_ci } 93898c2ecf20Sopenharmony_ci 93908c2ecf20Sopenharmony_ci stat = qla4xxx_reset_target(ha, ddb_entry); 93918c2ecf20Sopenharmony_ci if (stat != QLA_SUCCESS) { 93928c2ecf20Sopenharmony_ci starget_printk(KERN_INFO, scsi_target(cmd->device), 93938c2ecf20Sopenharmony_ci "WARM TARGET RESET FAILED.\n"); 93948c2ecf20Sopenharmony_ci return FAILED; 93958c2ecf20Sopenharmony_ci } 93968c2ecf20Sopenharmony_ci 93978c2ecf20Sopenharmony_ci if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device), 93988c2ecf20Sopenharmony_ci NULL)) { 93998c2ecf20Sopenharmony_ci starget_printk(KERN_INFO, scsi_target(cmd->device), 94008c2ecf20Sopenharmony_ci "WARM TARGET DEVICE RESET FAILED - " 94018c2ecf20Sopenharmony_ci "waiting for commands.\n"); 94028c2ecf20Sopenharmony_ci return FAILED; 94038c2ecf20Sopenharmony_ci } 94048c2ecf20Sopenharmony_ci 94058c2ecf20Sopenharmony_ci /* Send marker. */ 94068c2ecf20Sopenharmony_ci if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun, 94078c2ecf20Sopenharmony_ci MM_TGT_WARM_RESET) != QLA_SUCCESS) { 94088c2ecf20Sopenharmony_ci starget_printk(KERN_INFO, scsi_target(cmd->device), 94098c2ecf20Sopenharmony_ci "WARM TARGET DEVICE RESET FAILED - " 94108c2ecf20Sopenharmony_ci "marker iocb failed.\n"); 94118c2ecf20Sopenharmony_ci return FAILED; 94128c2ecf20Sopenharmony_ci } 94138c2ecf20Sopenharmony_ci 94148c2ecf20Sopenharmony_ci starget_printk(KERN_INFO, scsi_target(cmd->device), 94158c2ecf20Sopenharmony_ci "WARM TARGET RESET SUCCEEDED.\n"); 94168c2ecf20Sopenharmony_ci return SUCCESS; 94178c2ecf20Sopenharmony_ci} 94188c2ecf20Sopenharmony_ci 94198c2ecf20Sopenharmony_ci/** 94208c2ecf20Sopenharmony_ci * qla4xxx_is_eh_active - check if error handler is running 94218c2ecf20Sopenharmony_ci * @shost: Pointer to SCSI Host struct 94228c2ecf20Sopenharmony_ci * 94238c2ecf20Sopenharmony_ci * This routine finds that if reset host is called in EH 94248c2ecf20Sopenharmony_ci * scenario or from some application like sg_reset 94258c2ecf20Sopenharmony_ci **/ 94268c2ecf20Sopenharmony_cistatic int qla4xxx_is_eh_active(struct Scsi_Host *shost) 94278c2ecf20Sopenharmony_ci{ 94288c2ecf20Sopenharmony_ci if (shost->shost_state == SHOST_RECOVERY) 94298c2ecf20Sopenharmony_ci return 1; 94308c2ecf20Sopenharmony_ci return 0; 94318c2ecf20Sopenharmony_ci} 94328c2ecf20Sopenharmony_ci 94338c2ecf20Sopenharmony_ci/** 94348c2ecf20Sopenharmony_ci * qla4xxx_eh_host_reset - kernel callback 94358c2ecf20Sopenharmony_ci * @cmd: Pointer to Linux's SCSI command structure 94368c2ecf20Sopenharmony_ci * 94378c2ecf20Sopenharmony_ci * This routine is invoked by the Linux kernel to perform fatal error 94388c2ecf20Sopenharmony_ci * recovery on the specified adapter. 94398c2ecf20Sopenharmony_ci **/ 94408c2ecf20Sopenharmony_cistatic int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) 94418c2ecf20Sopenharmony_ci{ 94428c2ecf20Sopenharmony_ci int return_status = FAILED; 94438c2ecf20Sopenharmony_ci struct scsi_qla_host *ha; 94448c2ecf20Sopenharmony_ci int rval; 94458c2ecf20Sopenharmony_ci 94468c2ecf20Sopenharmony_ci ha = to_qla_host(cmd->device->host); 94478c2ecf20Sopenharmony_ci 94488c2ecf20Sopenharmony_ci rval = qla4xxx_isp_check_reg(ha); 94498c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 94508c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n"); 94518c2ecf20Sopenharmony_ci return FAILED; 94528c2ecf20Sopenharmony_ci } 94538c2ecf20Sopenharmony_ci 94548c2ecf20Sopenharmony_ci if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba) 94558c2ecf20Sopenharmony_ci qla4_83xx_set_idc_dontreset(ha); 94568c2ecf20Sopenharmony_ci 94578c2ecf20Sopenharmony_ci /* 94588c2ecf20Sopenharmony_ci * For ISP8324 and ISP8042, if IDC_CTRL DONTRESET_BIT0 is set by other 94598c2ecf20Sopenharmony_ci * protocol drivers, we should not set device_state to NEED_RESET 94608c2ecf20Sopenharmony_ci */ 94618c2ecf20Sopenharmony_ci if (ql4xdontresethba || 94628c2ecf20Sopenharmony_ci ((is_qla8032(ha) || is_qla8042(ha)) && 94638c2ecf20Sopenharmony_ci qla4_83xx_idc_dontreset(ha))) { 94648c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n", 94658c2ecf20Sopenharmony_ci ha->host_no, __func__)); 94668c2ecf20Sopenharmony_ci 94678c2ecf20Sopenharmony_ci /* Clear outstanding srb in queues */ 94688c2ecf20Sopenharmony_ci if (qla4xxx_is_eh_active(cmd->device->host)) 94698c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_ABORT << 16); 94708c2ecf20Sopenharmony_ci 94718c2ecf20Sopenharmony_ci return FAILED; 94728c2ecf20Sopenharmony_ci } 94738c2ecf20Sopenharmony_ci 94748c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, 94758c2ecf20Sopenharmony_ci "scsi(%ld:%d:%d:%llu): HOST RESET ISSUED.\n", ha->host_no, 94768c2ecf20Sopenharmony_ci cmd->device->channel, cmd->device->id, cmd->device->lun); 94778c2ecf20Sopenharmony_ci 94788c2ecf20Sopenharmony_ci if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { 94798c2ecf20Sopenharmony_ci DEBUG2(printk("scsi%ld:%d: %s: Unable to reset host. Adapter " 94808c2ecf20Sopenharmony_ci "DEAD.\n", ha->host_no, cmd->device->channel, 94818c2ecf20Sopenharmony_ci __func__)); 94828c2ecf20Sopenharmony_ci 94838c2ecf20Sopenharmony_ci return FAILED; 94848c2ecf20Sopenharmony_ci } 94858c2ecf20Sopenharmony_ci 94868c2ecf20Sopenharmony_ci if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) { 94878c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 94888c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags); 94898c2ecf20Sopenharmony_ci else 94908c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 94918c2ecf20Sopenharmony_ci } 94928c2ecf20Sopenharmony_ci 94938c2ecf20Sopenharmony_ci if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS) 94948c2ecf20Sopenharmony_ci return_status = SUCCESS; 94958c2ecf20Sopenharmony_ci 94968c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n", 94978c2ecf20Sopenharmony_ci return_status == FAILED ? "FAILED" : "SUCCEEDED"); 94988c2ecf20Sopenharmony_ci 94998c2ecf20Sopenharmony_ci return return_status; 95008c2ecf20Sopenharmony_ci} 95018c2ecf20Sopenharmony_ci 95028c2ecf20Sopenharmony_cistatic int qla4xxx_context_reset(struct scsi_qla_host *ha) 95038c2ecf20Sopenharmony_ci{ 95048c2ecf20Sopenharmony_ci uint32_t mbox_cmd[MBOX_REG_COUNT]; 95058c2ecf20Sopenharmony_ci uint32_t mbox_sts[MBOX_REG_COUNT]; 95068c2ecf20Sopenharmony_ci struct addr_ctrl_blk_def *acb = NULL; 95078c2ecf20Sopenharmony_ci uint32_t acb_len = sizeof(struct addr_ctrl_blk_def); 95088c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 95098c2ecf20Sopenharmony_ci dma_addr_t acb_dma; 95108c2ecf20Sopenharmony_ci 95118c2ecf20Sopenharmony_ci acb = dma_alloc_coherent(&ha->pdev->dev, 95128c2ecf20Sopenharmony_ci sizeof(struct addr_ctrl_blk_def), 95138c2ecf20Sopenharmony_ci &acb_dma, GFP_KERNEL); 95148c2ecf20Sopenharmony_ci if (!acb) { 95158c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n", 95168c2ecf20Sopenharmony_ci __func__); 95178c2ecf20Sopenharmony_ci rval = -ENOMEM; 95188c2ecf20Sopenharmony_ci goto exit_port_reset; 95198c2ecf20Sopenharmony_ci } 95208c2ecf20Sopenharmony_ci 95218c2ecf20Sopenharmony_ci memset(acb, 0, acb_len); 95228c2ecf20Sopenharmony_ci 95238c2ecf20Sopenharmony_ci rval = qla4xxx_get_acb(ha, acb_dma, PRIMARI_ACB, acb_len); 95248c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 95258c2ecf20Sopenharmony_ci rval = -EIO; 95268c2ecf20Sopenharmony_ci goto exit_free_acb; 95278c2ecf20Sopenharmony_ci } 95288c2ecf20Sopenharmony_ci 95298c2ecf20Sopenharmony_ci rval = qla4xxx_disable_acb(ha); 95308c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 95318c2ecf20Sopenharmony_ci rval = -EIO; 95328c2ecf20Sopenharmony_ci goto exit_free_acb; 95338c2ecf20Sopenharmony_ci } 95348c2ecf20Sopenharmony_ci 95358c2ecf20Sopenharmony_ci wait_for_completion_timeout(&ha->disable_acb_comp, 95368c2ecf20Sopenharmony_ci DISABLE_ACB_TOV * HZ); 95378c2ecf20Sopenharmony_ci 95388c2ecf20Sopenharmony_ci rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma); 95398c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 95408c2ecf20Sopenharmony_ci rval = -EIO; 95418c2ecf20Sopenharmony_ci goto exit_free_acb; 95428c2ecf20Sopenharmony_ci } 95438c2ecf20Sopenharmony_ci 95448c2ecf20Sopenharmony_ciexit_free_acb: 95458c2ecf20Sopenharmony_ci dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk_def), 95468c2ecf20Sopenharmony_ci acb, acb_dma); 95478c2ecf20Sopenharmony_ciexit_port_reset: 95488c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s %s\n", __func__, 95498c2ecf20Sopenharmony_ci rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED")); 95508c2ecf20Sopenharmony_ci return rval; 95518c2ecf20Sopenharmony_ci} 95528c2ecf20Sopenharmony_ci 95538c2ecf20Sopenharmony_cistatic int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type) 95548c2ecf20Sopenharmony_ci{ 95558c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = to_qla_host(shost); 95568c2ecf20Sopenharmony_ci int rval = QLA_SUCCESS; 95578c2ecf20Sopenharmony_ci uint32_t idc_ctrl; 95588c2ecf20Sopenharmony_ci 95598c2ecf20Sopenharmony_ci if (ql4xdontresethba) { 95608c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n", 95618c2ecf20Sopenharmony_ci __func__)); 95628c2ecf20Sopenharmony_ci rval = -EPERM; 95638c2ecf20Sopenharmony_ci goto exit_host_reset; 95648c2ecf20Sopenharmony_ci } 95658c2ecf20Sopenharmony_ci 95668c2ecf20Sopenharmony_ci if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) 95678c2ecf20Sopenharmony_ci goto recover_adapter; 95688c2ecf20Sopenharmony_ci 95698c2ecf20Sopenharmony_ci switch (reset_type) { 95708c2ecf20Sopenharmony_ci case SCSI_ADAPTER_RESET: 95718c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA, &ha->dpc_flags); 95728c2ecf20Sopenharmony_ci break; 95738c2ecf20Sopenharmony_ci case SCSI_FIRMWARE_RESET: 95748c2ecf20Sopenharmony_ci if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) { 95758c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) 95768c2ecf20Sopenharmony_ci /* set firmware context reset */ 95778c2ecf20Sopenharmony_ci set_bit(DPC_RESET_HA_FW_CONTEXT, 95788c2ecf20Sopenharmony_ci &ha->dpc_flags); 95798c2ecf20Sopenharmony_ci else { 95808c2ecf20Sopenharmony_ci rval = qla4xxx_context_reset(ha); 95818c2ecf20Sopenharmony_ci goto exit_host_reset; 95828c2ecf20Sopenharmony_ci } 95838c2ecf20Sopenharmony_ci } 95848c2ecf20Sopenharmony_ci break; 95858c2ecf20Sopenharmony_ci } 95868c2ecf20Sopenharmony_ci 95878c2ecf20Sopenharmony_cirecover_adapter: 95888c2ecf20Sopenharmony_ci /* For ISP8324 and ISP8042 set graceful reset bit in IDC_DRV_CTRL if 95898c2ecf20Sopenharmony_ci * reset is issued by application */ 95908c2ecf20Sopenharmony_ci if ((is_qla8032(ha) || is_qla8042(ha)) && 95918c2ecf20Sopenharmony_ci test_bit(DPC_RESET_HA, &ha->dpc_flags)) { 95928c2ecf20Sopenharmony_ci idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL); 95938c2ecf20Sopenharmony_ci qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL, 95948c2ecf20Sopenharmony_ci (idc_ctrl | GRACEFUL_RESET_BIT1)); 95958c2ecf20Sopenharmony_ci } 95968c2ecf20Sopenharmony_ci 95978c2ecf20Sopenharmony_ci rval = qla4xxx_recover_adapter(ha); 95988c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 95998c2ecf20Sopenharmony_ci DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n", 96008c2ecf20Sopenharmony_ci __func__)); 96018c2ecf20Sopenharmony_ci rval = -EIO; 96028c2ecf20Sopenharmony_ci } 96038c2ecf20Sopenharmony_ci 96048c2ecf20Sopenharmony_ciexit_host_reset: 96058c2ecf20Sopenharmony_ci return rval; 96068c2ecf20Sopenharmony_ci} 96078c2ecf20Sopenharmony_ci 96088c2ecf20Sopenharmony_ci/* PCI AER driver recovers from all correctable errors w/o 96098c2ecf20Sopenharmony_ci * driver intervention. For uncorrectable errors PCI AER 96108c2ecf20Sopenharmony_ci * driver calls the following device driver's callbacks 96118c2ecf20Sopenharmony_ci * 96128c2ecf20Sopenharmony_ci * - Fatal Errors - link_reset 96138c2ecf20Sopenharmony_ci * - Non-Fatal Errors - driver's error_detected() which 96148c2ecf20Sopenharmony_ci * returns CAN_RECOVER, NEED_RESET or DISCONNECT. 96158c2ecf20Sopenharmony_ci * 96168c2ecf20Sopenharmony_ci * PCI AER driver calls 96178c2ecf20Sopenharmony_ci * CAN_RECOVER - driver's mmio_enabled(), mmio_enabled() 96188c2ecf20Sopenharmony_ci * returns RECOVERED or NEED_RESET if fw_hung 96198c2ecf20Sopenharmony_ci * NEED_RESET - driver's slot_reset() 96208c2ecf20Sopenharmony_ci * DISCONNECT - device is dead & cannot recover 96218c2ecf20Sopenharmony_ci * RECOVERED - driver's resume() 96228c2ecf20Sopenharmony_ci */ 96238c2ecf20Sopenharmony_cistatic pci_ers_result_t 96248c2ecf20Sopenharmony_ciqla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) 96258c2ecf20Sopenharmony_ci{ 96268c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = pci_get_drvdata(pdev); 96278c2ecf20Sopenharmony_ci 96288c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n", 96298c2ecf20Sopenharmony_ci ha->host_no, __func__, state); 96308c2ecf20Sopenharmony_ci 96318c2ecf20Sopenharmony_ci if (!is_aer_supported(ha)) 96328c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NONE; 96338c2ecf20Sopenharmony_ci 96348c2ecf20Sopenharmony_ci switch (state) { 96358c2ecf20Sopenharmony_ci case pci_channel_io_normal: 96368c2ecf20Sopenharmony_ci clear_bit(AF_EEH_BUSY, &ha->flags); 96378c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_CAN_RECOVER; 96388c2ecf20Sopenharmony_ci case pci_channel_io_frozen: 96398c2ecf20Sopenharmony_ci set_bit(AF_EEH_BUSY, &ha->flags); 96408c2ecf20Sopenharmony_ci qla4xxx_mailbox_premature_completion(ha); 96418c2ecf20Sopenharmony_ci qla4xxx_free_irqs(ha); 96428c2ecf20Sopenharmony_ci pci_disable_device(pdev); 96438c2ecf20Sopenharmony_ci /* Return back all IOs */ 96448c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_RESET << 16); 96458c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NEED_RESET; 96468c2ecf20Sopenharmony_ci case pci_channel_io_perm_failure: 96478c2ecf20Sopenharmony_ci set_bit(AF_EEH_BUSY, &ha->flags); 96488c2ecf20Sopenharmony_ci set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags); 96498c2ecf20Sopenharmony_ci qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); 96508c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 96518c2ecf20Sopenharmony_ci } 96528c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NEED_RESET; 96538c2ecf20Sopenharmony_ci} 96548c2ecf20Sopenharmony_ci 96558c2ecf20Sopenharmony_ci/** 96568c2ecf20Sopenharmony_ci * qla4xxx_pci_mmio_enabled() gets called if 96578c2ecf20Sopenharmony_ci * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER 96588c2ecf20Sopenharmony_ci * and read/write to the device still works. 96598c2ecf20Sopenharmony_ci * @pdev: PCI device pointer 96608c2ecf20Sopenharmony_ci **/ 96618c2ecf20Sopenharmony_cistatic pci_ers_result_t 96628c2ecf20Sopenharmony_ciqla4xxx_pci_mmio_enabled(struct pci_dev *pdev) 96638c2ecf20Sopenharmony_ci{ 96648c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = pci_get_drvdata(pdev); 96658c2ecf20Sopenharmony_ci 96668c2ecf20Sopenharmony_ci if (!is_aer_supported(ha)) 96678c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NONE; 96688c2ecf20Sopenharmony_ci 96698c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_RECOVERED; 96708c2ecf20Sopenharmony_ci} 96718c2ecf20Sopenharmony_ci 96728c2ecf20Sopenharmony_cistatic uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) 96738c2ecf20Sopenharmony_ci{ 96748c2ecf20Sopenharmony_ci uint32_t rval = QLA_ERROR; 96758c2ecf20Sopenharmony_ci int fn; 96768c2ecf20Sopenharmony_ci struct pci_dev *other_pdev = NULL; 96778c2ecf20Sopenharmony_ci 96788c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__); 96798c2ecf20Sopenharmony_ci 96808c2ecf20Sopenharmony_ci set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); 96818c2ecf20Sopenharmony_ci 96828c2ecf20Sopenharmony_ci if (test_bit(AF_ONLINE, &ha->flags)) { 96838c2ecf20Sopenharmony_ci clear_bit(AF_ONLINE, &ha->flags); 96848c2ecf20Sopenharmony_ci clear_bit(AF_LINK_UP, &ha->flags); 96858c2ecf20Sopenharmony_ci iscsi_host_for_each_session(ha->host, qla4xxx_fail_session); 96868c2ecf20Sopenharmony_ci qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); 96878c2ecf20Sopenharmony_ci } 96888c2ecf20Sopenharmony_ci 96898c2ecf20Sopenharmony_ci fn = PCI_FUNC(ha->pdev->devfn); 96908c2ecf20Sopenharmony_ci if (is_qla8022(ha)) { 96918c2ecf20Sopenharmony_ci while (fn > 0) { 96928c2ecf20Sopenharmony_ci fn--; 96938c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at func %x\n", 96948c2ecf20Sopenharmony_ci ha->host_no, __func__, fn); 96958c2ecf20Sopenharmony_ci /* Get the pci device given the domain, bus, 96968c2ecf20Sopenharmony_ci * slot/function number */ 96978c2ecf20Sopenharmony_ci other_pdev = pci_get_domain_bus_and_slot( 96988c2ecf20Sopenharmony_ci pci_domain_nr(ha->pdev->bus), 96998c2ecf20Sopenharmony_ci ha->pdev->bus->number, 97008c2ecf20Sopenharmony_ci PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), 97018c2ecf20Sopenharmony_ci fn)); 97028c2ecf20Sopenharmony_ci 97038c2ecf20Sopenharmony_ci if (!other_pdev) 97048c2ecf20Sopenharmony_ci continue; 97058c2ecf20Sopenharmony_ci 97068c2ecf20Sopenharmony_ci if (atomic_read(&other_pdev->enable_cnt)) { 97078c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI func in enabled state%x\n", 97088c2ecf20Sopenharmony_ci ha->host_no, __func__, fn); 97098c2ecf20Sopenharmony_ci pci_dev_put(other_pdev); 97108c2ecf20Sopenharmony_ci break; 97118c2ecf20Sopenharmony_ci } 97128c2ecf20Sopenharmony_ci pci_dev_put(other_pdev); 97138c2ecf20Sopenharmony_ci } 97148c2ecf20Sopenharmony_ci } else { 97158c2ecf20Sopenharmony_ci /* this case is meant for ISP83xx/ISP84xx only */ 97168c2ecf20Sopenharmony_ci if (qla4_83xx_can_perform_reset(ha)) { 97178c2ecf20Sopenharmony_ci /* reset fn as iSCSI is going to perform the reset */ 97188c2ecf20Sopenharmony_ci fn = 0; 97198c2ecf20Sopenharmony_ci } 97208c2ecf20Sopenharmony_ci } 97218c2ecf20Sopenharmony_ci 97228c2ecf20Sopenharmony_ci /* The first function on the card, the reset owner will 97238c2ecf20Sopenharmony_ci * start & initialize the firmware. The other functions 97248c2ecf20Sopenharmony_ci * on the card will reset the firmware context 97258c2ecf20Sopenharmony_ci */ 97268c2ecf20Sopenharmony_ci if (!fn) { 97278c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset " 97288c2ecf20Sopenharmony_ci "0x%x is the owner\n", ha->host_no, __func__, 97298c2ecf20Sopenharmony_ci ha->pdev->devfn); 97308c2ecf20Sopenharmony_ci 97318c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 97328c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 97338c2ecf20Sopenharmony_ci QLA8XXX_DEV_COLD); 97348c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 97358c2ecf20Sopenharmony_ci 97368c2ecf20Sopenharmony_ci rval = qla4_8xxx_update_idc_reg(ha); 97378c2ecf20Sopenharmony_ci if (rval == QLA_ERROR) { 97388c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: FAILED\n", 97398c2ecf20Sopenharmony_ci ha->host_no, __func__); 97408c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 97418c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 97428c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 97438c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 97448c2ecf20Sopenharmony_ci goto exit_error_recovery; 97458c2ecf20Sopenharmony_ci } 97468c2ecf20Sopenharmony_ci 97478c2ecf20Sopenharmony_ci clear_bit(AF_FW_RECOVERY, &ha->flags); 97488c2ecf20Sopenharmony_ci rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); 97498c2ecf20Sopenharmony_ci 97508c2ecf20Sopenharmony_ci if (rval != QLA_SUCCESS) { 97518c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " 97528c2ecf20Sopenharmony_ci "FAILED\n", ha->host_no, __func__); 97538c2ecf20Sopenharmony_ci qla4xxx_free_irqs(ha); 97548c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 97558c2ecf20Sopenharmony_ci qla4_8xxx_clear_drv_active(ha); 97568c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 97578c2ecf20Sopenharmony_ci QLA8XXX_DEV_FAILED); 97588c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 97598c2ecf20Sopenharmony_ci } else { 97608c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " 97618c2ecf20Sopenharmony_ci "READY\n", ha->host_no, __func__); 97628c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 97638c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE, 97648c2ecf20Sopenharmony_ci QLA8XXX_DEV_READY); 97658c2ecf20Sopenharmony_ci /* Clear driver state register */ 97668c2ecf20Sopenharmony_ci qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, 0); 97678c2ecf20Sopenharmony_ci qla4_8xxx_set_drv_active(ha); 97688c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 97698c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 97708c2ecf20Sopenharmony_ci } 97718c2ecf20Sopenharmony_ci } else { 97728c2ecf20Sopenharmony_ci ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not " 97738c2ecf20Sopenharmony_ci "the reset owner\n", ha->host_no, __func__, 97748c2ecf20Sopenharmony_ci ha->pdev->devfn); 97758c2ecf20Sopenharmony_ci if ((qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE) == 97768c2ecf20Sopenharmony_ci QLA8XXX_DEV_READY)) { 97778c2ecf20Sopenharmony_ci clear_bit(AF_FW_RECOVERY, &ha->flags); 97788c2ecf20Sopenharmony_ci rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); 97798c2ecf20Sopenharmony_ci if (rval == QLA_SUCCESS) 97808c2ecf20Sopenharmony_ci ha->isp_ops->enable_intrs(ha); 97818c2ecf20Sopenharmony_ci else 97828c2ecf20Sopenharmony_ci qla4xxx_free_irqs(ha); 97838c2ecf20Sopenharmony_ci 97848c2ecf20Sopenharmony_ci ha->isp_ops->idc_lock(ha); 97858c2ecf20Sopenharmony_ci qla4_8xxx_set_drv_active(ha); 97868c2ecf20Sopenharmony_ci ha->isp_ops->idc_unlock(ha); 97878c2ecf20Sopenharmony_ci } 97888c2ecf20Sopenharmony_ci } 97898c2ecf20Sopenharmony_ciexit_error_recovery: 97908c2ecf20Sopenharmony_ci clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); 97918c2ecf20Sopenharmony_ci return rval; 97928c2ecf20Sopenharmony_ci} 97938c2ecf20Sopenharmony_ci 97948c2ecf20Sopenharmony_cistatic pci_ers_result_t 97958c2ecf20Sopenharmony_ciqla4xxx_pci_slot_reset(struct pci_dev *pdev) 97968c2ecf20Sopenharmony_ci{ 97978c2ecf20Sopenharmony_ci pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; 97988c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = pci_get_drvdata(pdev); 97998c2ecf20Sopenharmony_ci int rc; 98008c2ecf20Sopenharmony_ci 98018c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n", 98028c2ecf20Sopenharmony_ci ha->host_no, __func__); 98038c2ecf20Sopenharmony_ci 98048c2ecf20Sopenharmony_ci if (!is_aer_supported(ha)) 98058c2ecf20Sopenharmony_ci return PCI_ERS_RESULT_NONE; 98068c2ecf20Sopenharmony_ci 98078c2ecf20Sopenharmony_ci /* Restore the saved state of PCIe device - 98088c2ecf20Sopenharmony_ci * BAR registers, PCI Config space, PCIX, MSI, 98098c2ecf20Sopenharmony_ci * IOV states 98108c2ecf20Sopenharmony_ci */ 98118c2ecf20Sopenharmony_ci pci_restore_state(pdev); 98128c2ecf20Sopenharmony_ci 98138c2ecf20Sopenharmony_ci /* pci_restore_state() clears the saved_state flag of the device 98148c2ecf20Sopenharmony_ci * save restored state which resets saved_state flag 98158c2ecf20Sopenharmony_ci */ 98168c2ecf20Sopenharmony_ci pci_save_state(pdev); 98178c2ecf20Sopenharmony_ci 98188c2ecf20Sopenharmony_ci /* Initialize device or resume if in suspended state */ 98198c2ecf20Sopenharmony_ci rc = pci_enable_device(pdev); 98208c2ecf20Sopenharmony_ci if (rc) { 98218c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Can't re-enable " 98228c2ecf20Sopenharmony_ci "device after reset\n", ha->host_no, __func__); 98238c2ecf20Sopenharmony_ci goto exit_slot_reset; 98248c2ecf20Sopenharmony_ci } 98258c2ecf20Sopenharmony_ci 98268c2ecf20Sopenharmony_ci ha->isp_ops->disable_intrs(ha); 98278c2ecf20Sopenharmony_ci 98288c2ecf20Sopenharmony_ci if (is_qla80XX(ha)) { 98298c2ecf20Sopenharmony_ci if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) { 98308c2ecf20Sopenharmony_ci ret = PCI_ERS_RESULT_RECOVERED; 98318c2ecf20Sopenharmony_ci goto exit_slot_reset; 98328c2ecf20Sopenharmony_ci } else 98338c2ecf20Sopenharmony_ci goto exit_slot_reset; 98348c2ecf20Sopenharmony_ci } 98358c2ecf20Sopenharmony_ci 98368c2ecf20Sopenharmony_ciexit_slot_reset: 98378c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n" 98388c2ecf20Sopenharmony_ci "device after reset\n", ha->host_no, __func__, ret); 98398c2ecf20Sopenharmony_ci return ret; 98408c2ecf20Sopenharmony_ci} 98418c2ecf20Sopenharmony_ci 98428c2ecf20Sopenharmony_cistatic void 98438c2ecf20Sopenharmony_ciqla4xxx_pci_resume(struct pci_dev *pdev) 98448c2ecf20Sopenharmony_ci{ 98458c2ecf20Sopenharmony_ci struct scsi_qla_host *ha = pci_get_drvdata(pdev); 98468c2ecf20Sopenharmony_ci int ret; 98478c2ecf20Sopenharmony_ci 98488c2ecf20Sopenharmony_ci ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n", 98498c2ecf20Sopenharmony_ci ha->host_no, __func__); 98508c2ecf20Sopenharmony_ci 98518c2ecf20Sopenharmony_ci ret = qla4xxx_wait_for_hba_online(ha); 98528c2ecf20Sopenharmony_ci if (ret != QLA_SUCCESS) { 98538c2ecf20Sopenharmony_ci ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to " 98548c2ecf20Sopenharmony_ci "resume I/O from slot/link_reset\n", ha->host_no, 98558c2ecf20Sopenharmony_ci __func__); 98568c2ecf20Sopenharmony_ci } 98578c2ecf20Sopenharmony_ci 98588c2ecf20Sopenharmony_ci clear_bit(AF_EEH_BUSY, &ha->flags); 98598c2ecf20Sopenharmony_ci} 98608c2ecf20Sopenharmony_ci 98618c2ecf20Sopenharmony_cistatic const struct pci_error_handlers qla4xxx_err_handler = { 98628c2ecf20Sopenharmony_ci .error_detected = qla4xxx_pci_error_detected, 98638c2ecf20Sopenharmony_ci .mmio_enabled = qla4xxx_pci_mmio_enabled, 98648c2ecf20Sopenharmony_ci .slot_reset = qla4xxx_pci_slot_reset, 98658c2ecf20Sopenharmony_ci .resume = qla4xxx_pci_resume, 98668c2ecf20Sopenharmony_ci}; 98678c2ecf20Sopenharmony_ci 98688c2ecf20Sopenharmony_cistatic struct pci_device_id qla4xxx_pci_tbl[] = { 98698c2ecf20Sopenharmony_ci { 98708c2ecf20Sopenharmony_ci .vendor = PCI_VENDOR_ID_QLOGIC, 98718c2ecf20Sopenharmony_ci .device = PCI_DEVICE_ID_QLOGIC_ISP4010, 98728c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 98738c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 98748c2ecf20Sopenharmony_ci }, 98758c2ecf20Sopenharmony_ci { 98768c2ecf20Sopenharmony_ci .vendor = PCI_VENDOR_ID_QLOGIC, 98778c2ecf20Sopenharmony_ci .device = PCI_DEVICE_ID_QLOGIC_ISP4022, 98788c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 98798c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 98808c2ecf20Sopenharmony_ci }, 98818c2ecf20Sopenharmony_ci { 98828c2ecf20Sopenharmony_ci .vendor = PCI_VENDOR_ID_QLOGIC, 98838c2ecf20Sopenharmony_ci .device = PCI_DEVICE_ID_QLOGIC_ISP4032, 98848c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 98858c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 98868c2ecf20Sopenharmony_ci }, 98878c2ecf20Sopenharmony_ci { 98888c2ecf20Sopenharmony_ci .vendor = PCI_VENDOR_ID_QLOGIC, 98898c2ecf20Sopenharmony_ci .device = PCI_DEVICE_ID_QLOGIC_ISP8022, 98908c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 98918c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 98928c2ecf20Sopenharmony_ci }, 98938c2ecf20Sopenharmony_ci { 98948c2ecf20Sopenharmony_ci .vendor = PCI_VENDOR_ID_QLOGIC, 98958c2ecf20Sopenharmony_ci .device = PCI_DEVICE_ID_QLOGIC_ISP8324, 98968c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 98978c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 98988c2ecf20Sopenharmony_ci }, 98998c2ecf20Sopenharmony_ci { 99008c2ecf20Sopenharmony_ci .vendor = PCI_VENDOR_ID_QLOGIC, 99018c2ecf20Sopenharmony_ci .device = PCI_DEVICE_ID_QLOGIC_ISP8042, 99028c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 99038c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 99048c2ecf20Sopenharmony_ci }, 99058c2ecf20Sopenharmony_ci {0, 0}, 99068c2ecf20Sopenharmony_ci}; 99078c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); 99088c2ecf20Sopenharmony_ci 99098c2ecf20Sopenharmony_cistatic struct pci_driver qla4xxx_pci_driver = { 99108c2ecf20Sopenharmony_ci .name = DRIVER_NAME, 99118c2ecf20Sopenharmony_ci .id_table = qla4xxx_pci_tbl, 99128c2ecf20Sopenharmony_ci .probe = qla4xxx_probe_adapter, 99138c2ecf20Sopenharmony_ci .remove = qla4xxx_remove_adapter, 99148c2ecf20Sopenharmony_ci .err_handler = &qla4xxx_err_handler, 99158c2ecf20Sopenharmony_ci}; 99168c2ecf20Sopenharmony_ci 99178c2ecf20Sopenharmony_cistatic int __init qla4xxx_module_init(void) 99188c2ecf20Sopenharmony_ci{ 99198c2ecf20Sopenharmony_ci int ret; 99208c2ecf20Sopenharmony_ci 99218c2ecf20Sopenharmony_ci if (ql4xqfulltracking) 99228c2ecf20Sopenharmony_ci qla4xxx_driver_template.track_queue_depth = 1; 99238c2ecf20Sopenharmony_ci 99248c2ecf20Sopenharmony_ci /* Allocate cache for SRBs. */ 99258c2ecf20Sopenharmony_ci srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0, 99268c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL); 99278c2ecf20Sopenharmony_ci if (srb_cachep == NULL) { 99288c2ecf20Sopenharmony_ci printk(KERN_ERR 99298c2ecf20Sopenharmony_ci "%s: Unable to allocate SRB cache..." 99308c2ecf20Sopenharmony_ci "Failing load!\n", DRIVER_NAME); 99318c2ecf20Sopenharmony_ci ret = -ENOMEM; 99328c2ecf20Sopenharmony_ci goto no_srp_cache; 99338c2ecf20Sopenharmony_ci } 99348c2ecf20Sopenharmony_ci 99358c2ecf20Sopenharmony_ci /* Derive version string. */ 99368c2ecf20Sopenharmony_ci strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION); 99378c2ecf20Sopenharmony_ci if (ql4xextended_error_logging) 99388c2ecf20Sopenharmony_ci strcat(qla4xxx_version_str, "-debug"); 99398c2ecf20Sopenharmony_ci 99408c2ecf20Sopenharmony_ci qla4xxx_scsi_transport = 99418c2ecf20Sopenharmony_ci iscsi_register_transport(&qla4xxx_iscsi_transport); 99428c2ecf20Sopenharmony_ci if (!qla4xxx_scsi_transport){ 99438c2ecf20Sopenharmony_ci ret = -ENODEV; 99448c2ecf20Sopenharmony_ci goto release_srb_cache; 99458c2ecf20Sopenharmony_ci } 99468c2ecf20Sopenharmony_ci 99478c2ecf20Sopenharmony_ci ret = pci_register_driver(&qla4xxx_pci_driver); 99488c2ecf20Sopenharmony_ci if (ret) 99498c2ecf20Sopenharmony_ci goto unregister_transport; 99508c2ecf20Sopenharmony_ci 99518c2ecf20Sopenharmony_ci printk(KERN_INFO "QLogic iSCSI HBA Driver\n"); 99528c2ecf20Sopenharmony_ci return 0; 99538c2ecf20Sopenharmony_ci 99548c2ecf20Sopenharmony_ciunregister_transport: 99558c2ecf20Sopenharmony_ci iscsi_unregister_transport(&qla4xxx_iscsi_transport); 99568c2ecf20Sopenharmony_cirelease_srb_cache: 99578c2ecf20Sopenharmony_ci kmem_cache_destroy(srb_cachep); 99588c2ecf20Sopenharmony_cino_srp_cache: 99598c2ecf20Sopenharmony_ci return ret; 99608c2ecf20Sopenharmony_ci} 99618c2ecf20Sopenharmony_ci 99628c2ecf20Sopenharmony_cistatic void __exit qla4xxx_module_exit(void) 99638c2ecf20Sopenharmony_ci{ 99648c2ecf20Sopenharmony_ci pci_unregister_driver(&qla4xxx_pci_driver); 99658c2ecf20Sopenharmony_ci iscsi_unregister_transport(&qla4xxx_iscsi_transport); 99668c2ecf20Sopenharmony_ci kmem_cache_destroy(srb_cachep); 99678c2ecf20Sopenharmony_ci} 99688c2ecf20Sopenharmony_ci 99698c2ecf20Sopenharmony_cimodule_init(qla4xxx_module_init); 99708c2ecf20Sopenharmony_cimodule_exit(qla4xxx_module_exit); 99718c2ecf20Sopenharmony_ci 99728c2ecf20Sopenharmony_ciMODULE_AUTHOR("QLogic Corporation"); 99738c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("QLogic iSCSI HBA Driver"); 99748c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 99758c2ecf20Sopenharmony_ciMODULE_VERSION(QLA4XXX_DRIVER_VERSION); 9976