9957 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QLogic iSCSI HBA Driver4 * Copyright (c) 2003-2013 QLogic Corporation5 */6#include <linux/moduleparam.h>7#include <linux/slab.h>8#include <linux/blkdev.h>9#include <linux/iscsi_boot_sysfs.h>10#include <linux/inet.h>11 12#include <scsi/scsi_tcq.h>13#include <scsi/scsicam.h>14 15#include "ql4_def.h"16#include "ql4_version.h"17#include "ql4_glbl.h"18#include "ql4_dbg.h"19#include "ql4_inline.h"20#include "ql4_83xx.h"21 22/*23 * Driver version24 */25static char qla4xxx_version_str[40];26 27/*28 * SRB allocation cache29 */30static struct kmem_cache *srb_cachep;31 32/*33 * Module parameter information and variables34 */35static int ql4xdisablesysfsboot = 1;36module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);37MODULE_PARM_DESC(ql4xdisablesysfsboot,38 " Set to disable exporting boot targets to sysfs.\n"39 "\t\t 0 - Export boot targets\n"40 "\t\t 1 - Do not export boot targets (Default)");41 42int ql4xdontresethba;43module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);44MODULE_PARM_DESC(ql4xdontresethba,45 " Don't reset the HBA for driver recovery.\n"46 "\t\t 0 - It will reset HBA (Default)\n"47 "\t\t 1 - It will NOT reset HBA");48 49int ql4xextended_error_logging;50module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);51MODULE_PARM_DESC(ql4xextended_error_logging,52 " Option to enable extended error logging.\n"53 "\t\t 0 - no logging (Default)\n"54 "\t\t 2 - debug logging");55 56int ql4xenablemsix = 1;57module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);58MODULE_PARM_DESC(ql4xenablemsix,59 " Set to enable MSI or MSI-X interrupt mechanism.\n"60 "\t\t 0 = enable INTx interrupt mechanism.\n"61 "\t\t 1 = enable MSI-X interrupt mechanism (Default).\n"62 "\t\t 2 = enable MSI interrupt mechanism.");63 64#define QL4_DEF_QDEPTH 3265static int ql4xmaxqdepth = QL4_DEF_QDEPTH;66module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);67MODULE_PARM_DESC(ql4xmaxqdepth,68 " Maximum queue depth to report for target devices.\n"69 "\t\t Default: 32.");70 71static int ql4xqfulltracking = 1;72module_param(ql4xqfulltracking, int, S_IRUGO | S_IWUSR);73MODULE_PARM_DESC(ql4xqfulltracking,74 " Enable or disable dynamic tracking and adjustment of\n"75 "\t\t scsi device queue depth.\n"76 "\t\t 0 - Disable.\n"77 "\t\t 1 - Enable. (Default)");78 79static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;80module_param(ql4xsess_recovery_tmo, int, S_IRUGO);81MODULE_PARM_DESC(ql4xsess_recovery_tmo,82 " Target Session Recovery Timeout.\n"83 "\t\t Default: 120 sec.");84 85int ql4xmdcapmask = 0;86module_param(ql4xmdcapmask, int, S_IRUGO);87MODULE_PARM_DESC(ql4xmdcapmask,88 " Set the Minidump driver capture mask level.\n"89 "\t\t Default is 0 (firmware default capture mask)\n"90 "\t\t Can be set to 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF");91 92int ql4xenablemd = 1;93module_param(ql4xenablemd, int, S_IRUGO | S_IWUSR);94MODULE_PARM_DESC(ql4xenablemd,95 " Set to enable minidump.\n"96 "\t\t 0 - disable minidump\n"97 "\t\t 1 - enable minidump (Default)");98 99static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);100/*101 * SCSI host template entry points102 */103static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);104 105/*106 * iSCSI template entry points107 */108static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,109 enum iscsi_param param, char *buf);110static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,111 enum iscsi_param param, char *buf);112static int qla4xxx_host_get_param(struct Scsi_Host *shost,113 enum iscsi_host_param param, char *buf);114static int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data,115 uint32_t len);116static int qla4xxx_get_iface_param(struct iscsi_iface *iface,117 enum iscsi_param_type param_type,118 int param, char *buf);119static enum scsi_timeout_action qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);120static struct iscsi_endpoint *qla4xxx_ep_connect(struct Scsi_Host *shost,121 struct sockaddr *dst_addr,122 int non_blocking);123static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms);124static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep);125static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,126 enum iscsi_param param, char *buf);127static int qla4xxx_conn_start(struct iscsi_cls_conn *conn);128static struct iscsi_cls_conn *129qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx);130static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,131 struct iscsi_cls_conn *cls_conn,132 uint64_t transport_fd, int is_leading);133static void qla4xxx_conn_destroy(struct iscsi_cls_conn *conn);134static struct iscsi_cls_session *135qla4xxx_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,136 uint16_t qdepth, uint32_t initial_cmdsn);137static void qla4xxx_session_destroy(struct iscsi_cls_session *sess);138static void qla4xxx_task_work(struct work_struct *wdata);139static int qla4xxx_alloc_pdu(struct iscsi_task *, uint8_t);140static int qla4xxx_task_xmit(struct iscsi_task *);141static void qla4xxx_task_cleanup(struct iscsi_task *);142static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session);143static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,144 struct iscsi_stats *stats);145static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,146 uint32_t iface_type, uint32_t payload_size,147 uint32_t pid, struct sockaddr *dst_addr);148static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,149 uint32_t *num_entries, char *buf);150static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx);151static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data,152 int len);153static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len);154 155/*156 * SCSI host template entry points157 */158static int qla4xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);159static int qla4xxx_eh_abort(struct scsi_cmnd *cmd);160static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);161static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);162static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);163static int qla4xxx_slave_alloc(struct scsi_device *device);164static umode_t qla4_attr_is_visible(int param_type, int param);165static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type);166 167/*168 * iSCSI Flash DDB sysfs entry points169 */170static int171qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess,172 struct iscsi_bus_flash_conn *fnode_conn,173 void *data, int len);174static int175qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,176 int param, char *buf);177static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,178 int len);179static int180qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess);181static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess,182 struct iscsi_bus_flash_conn *fnode_conn);183static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess,184 struct iscsi_bus_flash_conn *fnode_conn);185static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess);186 187static struct qla4_8xxx_legacy_intr_set legacy_intr[] =188 QLA82XX_LEGACY_INTR_CONFIG;189 190static const uint32_t qla4_82xx_reg_tbl[] = {191 QLA82XX_PEG_HALT_STATUS1,192 QLA82XX_PEG_HALT_STATUS2,193 QLA82XX_PEG_ALIVE_COUNTER,194 QLA82XX_CRB_DRV_ACTIVE,195 QLA82XX_CRB_DEV_STATE,196 QLA82XX_CRB_DRV_STATE,197 QLA82XX_CRB_DRV_SCRATCH,198 QLA82XX_CRB_DEV_PART_INFO,199 QLA82XX_CRB_DRV_IDC_VERSION,200 QLA82XX_FW_VERSION_MAJOR,201 QLA82XX_FW_VERSION_MINOR,202 QLA82XX_FW_VERSION_SUB,203 CRB_CMDPEG_STATE,204 CRB_TEMP_STATE,205};206 207static const uint32_t qla4_83xx_reg_tbl[] = {208 QLA83XX_PEG_HALT_STATUS1,209 QLA83XX_PEG_HALT_STATUS2,210 QLA83XX_PEG_ALIVE_COUNTER,211 QLA83XX_CRB_DRV_ACTIVE,212 QLA83XX_CRB_DEV_STATE,213 QLA83XX_CRB_DRV_STATE,214 QLA83XX_CRB_DRV_SCRATCH,215 QLA83XX_CRB_DEV_PART_INFO1,216 QLA83XX_CRB_IDC_VER_MAJOR,217 QLA83XX_FW_VER_MAJOR,218 QLA83XX_FW_VER_MINOR,219 QLA83XX_FW_VER_SUB,220 QLA83XX_CMDPEG_STATE,221 QLA83XX_ASIC_TEMP,222};223 224static struct scsi_host_template qla4xxx_driver_template = {225 .module = THIS_MODULE,226 .name = DRIVER_NAME,227 .proc_name = DRIVER_NAME,228 .queuecommand = qla4xxx_queuecommand,229 .cmd_size = sizeof(struct qla4xxx_cmd_priv),230 231 .eh_abort_handler = qla4xxx_eh_abort,232 .eh_device_reset_handler = qla4xxx_eh_device_reset,233 .eh_target_reset_handler = qla4xxx_eh_target_reset,234 .eh_host_reset_handler = qla4xxx_eh_host_reset,235 .eh_timed_out = qla4xxx_eh_cmd_timed_out,236 237 .slave_alloc = qla4xxx_slave_alloc,238 .change_queue_depth = scsi_change_queue_depth,239 240 .this_id = -1,241 .cmd_per_lun = 3,242 .sg_tablesize = SG_ALL,243 244 .max_sectors = 0xFFFF,245 .shost_groups = qla4xxx_host_groups,246 .host_reset = qla4xxx_host_reset,247 .vendor_id = SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC,248};249 250static struct iscsi_transport qla4xxx_iscsi_transport = {251 .owner = THIS_MODULE,252 .name = DRIVER_NAME,253 .caps = CAP_TEXT_NEGO |254 CAP_DATA_PATH_OFFLOAD | CAP_HDRDGST |255 CAP_DATADGST | CAP_LOGIN_OFFLOAD |256 CAP_MULTI_R2T,257 .attr_is_visible = qla4_attr_is_visible,258 .create_session = qla4xxx_session_create,259 .destroy_session = qla4xxx_session_destroy,260 .start_conn = qla4xxx_conn_start,261 .create_conn = qla4xxx_conn_create,262 .bind_conn = qla4xxx_conn_bind,263 .unbind_conn = iscsi_conn_unbind,264 .stop_conn = iscsi_conn_stop,265 .destroy_conn = qla4xxx_conn_destroy,266 .set_param = iscsi_set_param,267 .get_conn_param = qla4xxx_conn_get_param,268 .get_session_param = qla4xxx_session_get_param,269 .get_ep_param = qla4xxx_get_ep_param,270 .ep_connect = qla4xxx_ep_connect,271 .ep_poll = qla4xxx_ep_poll,272 .ep_disconnect = qla4xxx_ep_disconnect,273 .get_stats = qla4xxx_conn_get_stats,274 .send_pdu = iscsi_conn_send_pdu,275 .xmit_task = qla4xxx_task_xmit,276 .cleanup_task = qla4xxx_task_cleanup,277 .alloc_pdu = qla4xxx_alloc_pdu,278 279 .get_host_param = qla4xxx_host_get_param,280 .set_iface_param = qla4xxx_iface_set_param,281 .get_iface_param = qla4xxx_get_iface_param,282 .bsg_request = qla4xxx_bsg_request,283 .send_ping = qla4xxx_send_ping,284 .get_chap = qla4xxx_get_chap_list,285 .delete_chap = qla4xxx_delete_chap,286 .set_chap = qla4xxx_set_chap_entry,287 .get_flashnode_param = qla4xxx_sysfs_ddb_get_param,288 .set_flashnode_param = qla4xxx_sysfs_ddb_set_param,289 .new_flashnode = qla4xxx_sysfs_ddb_add,290 .del_flashnode = qla4xxx_sysfs_ddb_delete,291 .login_flashnode = qla4xxx_sysfs_ddb_login,292 .logout_flashnode = qla4xxx_sysfs_ddb_logout,293 .logout_flashnode_sid = qla4xxx_sysfs_ddb_logout_sid,294 .get_host_stats = qla4xxx_get_host_stats,295};296 297static struct scsi_transport_template *qla4xxx_scsi_transport;298 299static int qla4xxx_isp_check_reg(struct scsi_qla_host *ha)300{301 u32 reg_val = 0;302 int rval = QLA_SUCCESS;303 304 if (is_qla8022(ha))305 reg_val = readl(&ha->qla4_82xx_reg->host_status);306 else if (is_qla8032(ha) || is_qla8042(ha))307 reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER);308 else309 reg_val = readw(&ha->reg->ctrl_status);310 311 if (reg_val == QL4_ISP_REG_DISCONNECT)312 rval = QLA_ERROR;313 314 return rval;315}316 317static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,318 uint32_t iface_type, uint32_t payload_size,319 uint32_t pid, struct sockaddr *dst_addr)320{321 struct scsi_qla_host *ha = to_qla_host(shost);322 struct sockaddr_in *addr;323 struct sockaddr_in6 *addr6;324 uint32_t options = 0;325 uint8_t ipaddr[IPv6_ADDR_LEN];326 int rval;327 328 memset(ipaddr, 0, IPv6_ADDR_LEN);329 /* IPv4 to IPv4 */330 if ((iface_type == ISCSI_IFACE_TYPE_IPV4) &&331 (dst_addr->sa_family == AF_INET)) {332 addr = (struct sockaddr_in *)dst_addr;333 memcpy(ipaddr, &addr->sin_addr.s_addr, IP_ADDR_LEN);334 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv4 Ping src: %pI4 "335 "dest: %pI4\n", __func__,336 &ha->ip_config.ip_address, ipaddr));337 rval = qla4xxx_ping_iocb(ha, options, payload_size, pid,338 ipaddr);339 if (rval)340 rval = -EINVAL;341 } else if ((iface_type == ISCSI_IFACE_TYPE_IPV6) &&342 (dst_addr->sa_family == AF_INET6)) {343 /* IPv6 to IPv6 */344 addr6 = (struct sockaddr_in6 *)dst_addr;345 memcpy(ipaddr, &addr6->sin6_addr.in6_u.u6_addr8, IPv6_ADDR_LEN);346 347 options |= PING_IPV6_PROTOCOL_ENABLE;348 349 /* Ping using LinkLocal address */350 if ((iface_num == 0) || (iface_num == 1)) {351 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: LinkLocal Ping "352 "src: %pI6 dest: %pI6\n", __func__,353 &ha->ip_config.ipv6_link_local_addr,354 ipaddr));355 options |= PING_IPV6_LINKLOCAL_ADDR;356 rval = qla4xxx_ping_iocb(ha, options, payload_size,357 pid, ipaddr);358 } else {359 ql4_printk(KERN_WARNING, ha, "%s: iface num = %d "360 "not supported\n", __func__, iface_num);361 rval = -ENOSYS;362 goto exit_send_ping;363 }364 365 /*366 * If ping using LinkLocal address fails, try ping using367 * IPv6 address368 */369 if (rval != QLA_SUCCESS) {370 options &= ~PING_IPV6_LINKLOCAL_ADDR;371 if (iface_num == 0) {372 options |= PING_IPV6_ADDR0;373 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 "374 "Ping src: %pI6 "375 "dest: %pI6\n", __func__,376 &ha->ip_config.ipv6_addr0,377 ipaddr));378 } else if (iface_num == 1) {379 options |= PING_IPV6_ADDR1;380 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 "381 "Ping src: %pI6 "382 "dest: %pI6\n", __func__,383 &ha->ip_config.ipv6_addr1,384 ipaddr));385 }386 rval = qla4xxx_ping_iocb(ha, options, payload_size,387 pid, ipaddr);388 if (rval)389 rval = -EINVAL;390 }391 } else392 rval = -ENOSYS;393exit_send_ping:394 return rval;395}396 397static umode_t qla4_attr_is_visible(int param_type, int param)398{399 switch (param_type) {400 case ISCSI_HOST_PARAM:401 switch (param) {402 case ISCSI_HOST_PARAM_HWADDRESS:403 case ISCSI_HOST_PARAM_IPADDRESS:404 case ISCSI_HOST_PARAM_INITIATOR_NAME:405 case ISCSI_HOST_PARAM_PORT_STATE:406 case ISCSI_HOST_PARAM_PORT_SPEED:407 return S_IRUGO;408 default:409 return 0;410 }411 case ISCSI_PARAM:412 switch (param) {413 case ISCSI_PARAM_PERSISTENT_ADDRESS:414 case ISCSI_PARAM_PERSISTENT_PORT:415 case ISCSI_PARAM_CONN_ADDRESS:416 case ISCSI_PARAM_CONN_PORT:417 case ISCSI_PARAM_TARGET_NAME:418 case ISCSI_PARAM_TPGT:419 case ISCSI_PARAM_TARGET_ALIAS:420 case ISCSI_PARAM_MAX_BURST:421 case ISCSI_PARAM_MAX_R2T:422 case ISCSI_PARAM_FIRST_BURST:423 case ISCSI_PARAM_MAX_RECV_DLENGTH:424 case ISCSI_PARAM_MAX_XMIT_DLENGTH:425 case ISCSI_PARAM_IFACE_NAME:426 case ISCSI_PARAM_CHAP_OUT_IDX:427 case ISCSI_PARAM_CHAP_IN_IDX:428 case ISCSI_PARAM_USERNAME:429 case ISCSI_PARAM_PASSWORD:430 case ISCSI_PARAM_USERNAME_IN:431 case ISCSI_PARAM_PASSWORD_IN:432 case ISCSI_PARAM_AUTO_SND_TGT_DISABLE:433 case ISCSI_PARAM_DISCOVERY_SESS:434 case ISCSI_PARAM_PORTAL_TYPE:435 case ISCSI_PARAM_CHAP_AUTH_EN:436 case ISCSI_PARAM_DISCOVERY_LOGOUT_EN:437 case ISCSI_PARAM_BIDI_CHAP_EN:438 case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL:439 case ISCSI_PARAM_DEF_TIME2WAIT:440 case ISCSI_PARAM_DEF_TIME2RETAIN:441 case ISCSI_PARAM_HDRDGST_EN:442 case ISCSI_PARAM_DATADGST_EN:443 case ISCSI_PARAM_INITIAL_R2T_EN:444 case ISCSI_PARAM_IMM_DATA_EN:445 case ISCSI_PARAM_PDU_INORDER_EN:446 case ISCSI_PARAM_DATASEQ_INORDER_EN:447 case ISCSI_PARAM_MAX_SEGMENT_SIZE:448 case ISCSI_PARAM_TCP_TIMESTAMP_STAT:449 case ISCSI_PARAM_TCP_WSF_DISABLE:450 case ISCSI_PARAM_TCP_NAGLE_DISABLE:451 case ISCSI_PARAM_TCP_TIMER_SCALE:452 case ISCSI_PARAM_TCP_TIMESTAMP_EN:453 case ISCSI_PARAM_TCP_XMIT_WSF:454 case ISCSI_PARAM_TCP_RECV_WSF:455 case ISCSI_PARAM_IP_FRAGMENT_DISABLE:456 case ISCSI_PARAM_IPV4_TOS:457 case ISCSI_PARAM_IPV6_TC:458 case ISCSI_PARAM_IPV6_FLOW_LABEL:459 case ISCSI_PARAM_IS_FW_ASSIGNED_IPV6:460 case ISCSI_PARAM_KEEPALIVE_TMO:461 case ISCSI_PARAM_LOCAL_PORT:462 case ISCSI_PARAM_ISID:463 case ISCSI_PARAM_TSID:464 case ISCSI_PARAM_DEF_TASKMGMT_TMO:465 case ISCSI_PARAM_ERL:466 case ISCSI_PARAM_STATSN:467 case ISCSI_PARAM_EXP_STATSN:468 case ISCSI_PARAM_DISCOVERY_PARENT_IDX:469 case ISCSI_PARAM_DISCOVERY_PARENT_TYPE:470 case ISCSI_PARAM_LOCAL_IPADDR:471 return S_IRUGO;472 default:473 return 0;474 }475 case ISCSI_NET_PARAM:476 switch (param) {477 case ISCSI_NET_PARAM_IPV4_ADDR:478 case ISCSI_NET_PARAM_IPV4_SUBNET:479 case ISCSI_NET_PARAM_IPV4_GW:480 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:481 case ISCSI_NET_PARAM_IFACE_ENABLE:482 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:483 case ISCSI_NET_PARAM_IPV6_ADDR:484 case ISCSI_NET_PARAM_IPV6_ROUTER:485 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:486 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:487 case ISCSI_NET_PARAM_VLAN_ID:488 case ISCSI_NET_PARAM_VLAN_PRIORITY:489 case ISCSI_NET_PARAM_VLAN_ENABLED:490 case ISCSI_NET_PARAM_MTU:491 case ISCSI_NET_PARAM_PORT:492 case ISCSI_NET_PARAM_IPADDR_STATE:493 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE:494 case ISCSI_NET_PARAM_IPV6_ROUTER_STATE:495 case ISCSI_NET_PARAM_DELAYED_ACK_EN:496 case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE:497 case ISCSI_NET_PARAM_TCP_WSF_DISABLE:498 case ISCSI_NET_PARAM_TCP_WSF:499 case ISCSI_NET_PARAM_TCP_TIMER_SCALE:500 case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN:501 case ISCSI_NET_PARAM_CACHE_ID:502 case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN:503 case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN:504 case ISCSI_NET_PARAM_IPV4_TOS_EN:505 case ISCSI_NET_PARAM_IPV4_TOS:506 case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN:507 case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN:508 case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID:509 case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN:510 case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN:511 case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID:512 case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN:513 case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE:514 case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN:515 case ISCSI_NET_PARAM_REDIRECT_EN:516 case ISCSI_NET_PARAM_IPV4_TTL:517 case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN:518 case ISCSI_NET_PARAM_IPV6_MLD_EN:519 case ISCSI_NET_PARAM_IPV6_FLOW_LABEL:520 case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS:521 case ISCSI_NET_PARAM_IPV6_HOP_LIMIT:522 case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO:523 case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME:524 case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO:525 case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT:526 case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU:527 return S_IRUGO;528 default:529 return 0;530 }531 case ISCSI_IFACE_PARAM:532 switch (param) {533 case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO:534 case ISCSI_IFACE_PARAM_HDRDGST_EN:535 case ISCSI_IFACE_PARAM_DATADGST_EN:536 case ISCSI_IFACE_PARAM_IMM_DATA_EN:537 case ISCSI_IFACE_PARAM_INITIAL_R2T_EN:538 case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN:539 case ISCSI_IFACE_PARAM_PDU_INORDER_EN:540 case ISCSI_IFACE_PARAM_ERL:541 case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH:542 case ISCSI_IFACE_PARAM_FIRST_BURST:543 case ISCSI_IFACE_PARAM_MAX_R2T:544 case ISCSI_IFACE_PARAM_MAX_BURST:545 case ISCSI_IFACE_PARAM_CHAP_AUTH_EN:546 case ISCSI_IFACE_PARAM_BIDI_CHAP_EN:547 case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL:548 case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN:549 case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN:550 case ISCSI_IFACE_PARAM_INITIATOR_NAME:551 return S_IRUGO;552 default:553 return 0;554 }555 case ISCSI_FLASHNODE_PARAM:556 switch (param) {557 case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6:558 case ISCSI_FLASHNODE_PORTAL_TYPE:559 case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE:560 case ISCSI_FLASHNODE_DISCOVERY_SESS:561 case ISCSI_FLASHNODE_ENTRY_EN:562 case ISCSI_FLASHNODE_HDR_DGST_EN:563 case ISCSI_FLASHNODE_DATA_DGST_EN:564 case ISCSI_FLASHNODE_IMM_DATA_EN:565 case ISCSI_FLASHNODE_INITIAL_R2T_EN:566 case ISCSI_FLASHNODE_DATASEQ_INORDER:567 case ISCSI_FLASHNODE_PDU_INORDER:568 case ISCSI_FLASHNODE_CHAP_AUTH_EN:569 case ISCSI_FLASHNODE_SNACK_REQ_EN:570 case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN:571 case ISCSI_FLASHNODE_BIDI_CHAP_EN:572 case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL:573 case ISCSI_FLASHNODE_ERL:574 case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT:575 case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE:576 case ISCSI_FLASHNODE_TCP_WSF_DISABLE:577 case ISCSI_FLASHNODE_TCP_TIMER_SCALE:578 case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN:579 case ISCSI_FLASHNODE_IP_FRAG_DISABLE:580 case ISCSI_FLASHNODE_MAX_RECV_DLENGTH:581 case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH:582 case ISCSI_FLASHNODE_FIRST_BURST:583 case ISCSI_FLASHNODE_DEF_TIME2WAIT:584 case ISCSI_FLASHNODE_DEF_TIME2RETAIN:585 case ISCSI_FLASHNODE_MAX_R2T:586 case ISCSI_FLASHNODE_KEEPALIVE_TMO:587 case ISCSI_FLASHNODE_ISID:588 case ISCSI_FLASHNODE_TSID:589 case ISCSI_FLASHNODE_PORT:590 case ISCSI_FLASHNODE_MAX_BURST:591 case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO:592 case ISCSI_FLASHNODE_IPADDR:593 case ISCSI_FLASHNODE_ALIAS:594 case ISCSI_FLASHNODE_REDIRECT_IPADDR:595 case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE:596 case ISCSI_FLASHNODE_LOCAL_PORT:597 case ISCSI_FLASHNODE_IPV4_TOS:598 case ISCSI_FLASHNODE_IPV6_TC:599 case ISCSI_FLASHNODE_IPV6_FLOW_LABEL:600 case ISCSI_FLASHNODE_NAME:601 case ISCSI_FLASHNODE_TPGT:602 case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:603 case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX:604 case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE:605 case ISCSI_FLASHNODE_TCP_XMIT_WSF:606 case ISCSI_FLASHNODE_TCP_RECV_WSF:607 case ISCSI_FLASHNODE_CHAP_OUT_IDX:608 case ISCSI_FLASHNODE_USERNAME:609 case ISCSI_FLASHNODE_PASSWORD:610 case ISCSI_FLASHNODE_STATSN:611 case ISCSI_FLASHNODE_EXP_STATSN:612 case ISCSI_FLASHNODE_IS_BOOT_TGT:613 return S_IRUGO;614 default:615 return 0;616 }617 }618 619 return 0;620}621 622/**623 * qla4xxx_create_chap_list - Create CHAP list from FLASH624 * @ha: pointer to adapter structure625 *626 * Read flash and make a list of CHAP entries, during login when a CHAP entry627 * is received, it will be checked in this list. If entry exist then the CHAP628 * entry index is set in the DDB. If CHAP entry does not exist in this list629 * then a new entry is added in FLASH in CHAP table and the index obtained is630 * used in the DDB.631 **/632static void qla4xxx_create_chap_list(struct scsi_qla_host *ha)633{634 int rval = 0;635 uint8_t *chap_flash_data = NULL;636 uint32_t offset;637 dma_addr_t chap_dma;638 uint32_t chap_size = 0;639 640 if (is_qla40XX(ha))641 chap_size = MAX_CHAP_ENTRIES_40XX *642 sizeof(struct ql4_chap_table);643 else /* Single region contains CHAP info for both644 * ports which is divided into half for each port.645 */646 chap_size = ha->hw.flt_chap_size / 2;647 648 chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size,649 &chap_dma, GFP_KERNEL);650 if (!chap_flash_data) {651 ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n");652 return;653 }654 655 if (is_qla40XX(ha)) {656 offset = FLASH_CHAP_OFFSET;657 } else {658 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);659 if (ha->port_num == 1)660 offset += chap_size;661 }662 663 rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);664 if (rval != QLA_SUCCESS)665 goto exit_chap_list;666 667 if (ha->chap_list == NULL)668 ha->chap_list = vmalloc(chap_size);669 if (ha->chap_list == NULL) {670 ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n");671 goto exit_chap_list;672 }673 674 memcpy(ha->chap_list, chap_flash_data, chap_size);675 676exit_chap_list:677 dma_free_coherent(&ha->pdev->dev, chap_size, chap_flash_data, chap_dma);678}679 680static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha,681 int16_t chap_index,682 struct ql4_chap_table **chap_entry)683{684 int rval = QLA_ERROR;685 int max_chap_entries;686 687 if (!ha->chap_list) {688 ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n");689 goto exit_get_chap;690 }691 692 if (is_qla80XX(ha))693 max_chap_entries = (ha->hw.flt_chap_size / 2) /694 sizeof(struct ql4_chap_table);695 else696 max_chap_entries = MAX_CHAP_ENTRIES_40XX;697 698 if (chap_index > max_chap_entries) {699 ql4_printk(KERN_ERR, ha, "Invalid Chap index\n");700 goto exit_get_chap;701 }702 703 *chap_entry = (struct ql4_chap_table *)ha->chap_list + chap_index;704 if ((*chap_entry)->cookie !=705 cpu_to_le16(CHAP_VALID_COOKIE)) {706 *chap_entry = NULL;707 } else {708 rval = QLA_SUCCESS;709 }710 711exit_get_chap:712 return rval;713}714 715/**716 * qla4xxx_find_free_chap_index - Find the first free chap index717 * @ha: pointer to adapter structure718 * @chap_index: CHAP index to be returned719 *720 * Find the first free chap index available in the chap table721 *722 * Note: Caller should acquire the chap lock before getting here.723 **/724static int qla4xxx_find_free_chap_index(struct scsi_qla_host *ha,725 uint16_t *chap_index)726{727 int i, rval;728 int free_index = -1;729 int max_chap_entries = 0;730 struct ql4_chap_table *chap_table;731 732 if (is_qla80XX(ha))733 max_chap_entries = (ha->hw.flt_chap_size / 2) /734 sizeof(struct ql4_chap_table);735 else736 max_chap_entries = MAX_CHAP_ENTRIES_40XX;737 738 if (!ha->chap_list) {739 ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n");740 rval = QLA_ERROR;741 goto exit_find_chap;742 }743 744 for (i = 0; i < max_chap_entries; i++) {745 chap_table = (struct ql4_chap_table *)ha->chap_list + i;746 747 if ((chap_table->cookie !=748 cpu_to_le16(CHAP_VALID_COOKIE)) &&749 (i > MAX_RESRV_CHAP_IDX)) {750 free_index = i;751 break;752 }753 }754 755 if (free_index != -1) {756 *chap_index = free_index;757 rval = QLA_SUCCESS;758 } else {759 rval = QLA_ERROR;760 }761 762exit_find_chap:763 return rval;764}765 766static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,767 uint32_t *num_entries, char *buf)768{769 struct scsi_qla_host *ha = to_qla_host(shost);770 struct ql4_chap_table *chap_table;771 struct iscsi_chap_rec *chap_rec;772 int max_chap_entries = 0;773 int valid_chap_entries = 0;774 int ret = 0, i;775 776 if (is_qla80XX(ha))777 max_chap_entries = (ha->hw.flt_chap_size / 2) /778 sizeof(struct ql4_chap_table);779 else780 max_chap_entries = MAX_CHAP_ENTRIES_40XX;781 782 ql4_printk(KERN_INFO, ha, "%s: num_entries = %d, CHAP idx = %d\n",783 __func__, *num_entries, chap_tbl_idx);784 785 if (!buf) {786 ret = -ENOMEM;787 goto exit_get_chap_list;788 }789 790 qla4xxx_create_chap_list(ha);791 792 chap_rec = (struct iscsi_chap_rec *) buf;793 mutex_lock(&ha->chap_sem);794 for (i = chap_tbl_idx; i < max_chap_entries; i++) {795 chap_table = (struct ql4_chap_table *)ha->chap_list + i;796 if (chap_table->cookie !=797 cpu_to_le16(CHAP_VALID_COOKIE))798 continue;799 800 chap_rec->chap_tbl_idx = i;801 strscpy(chap_rec->username, chap_table->name,802 sizeof(chap_rec->username));803 chap_rec->password_length = strscpy(chap_rec->password,804 chap_table->secret,805 sizeof(chap_rec->password));806 807 if (chap_table->flags & BIT_7) /* local */808 chap_rec->chap_type = CHAP_TYPE_OUT;809 810 if (chap_table->flags & BIT_6) /* peer */811 chap_rec->chap_type = CHAP_TYPE_IN;812 813 chap_rec++;814 815 valid_chap_entries++;816 if (valid_chap_entries == *num_entries)817 break;818 }819 mutex_unlock(&ha->chap_sem);820 821exit_get_chap_list:822 ql4_printk(KERN_INFO, ha, "%s: Valid CHAP Entries = %d\n",823 __func__, valid_chap_entries);824 *num_entries = valid_chap_entries;825 return ret;826}827 828static int __qla4xxx_is_chap_active(struct device *dev, void *data)829{830 int ret = 0;831 uint16_t *chap_tbl_idx = (uint16_t *) data;832 struct iscsi_cls_session *cls_session;833 struct iscsi_session *sess;834 struct ddb_entry *ddb_entry;835 836 if (!iscsi_is_session_dev(dev))837 goto exit_is_chap_active;838 839 cls_session = iscsi_dev_to_session(dev);840 sess = cls_session->dd_data;841 ddb_entry = sess->dd_data;842 843 if (iscsi_is_session_online(cls_session))844 goto exit_is_chap_active;845 846 if (ddb_entry->chap_tbl_idx == *chap_tbl_idx)847 ret = 1;848 849exit_is_chap_active:850 return ret;851}852 853static int qla4xxx_is_chap_active(struct Scsi_Host *shost,854 uint16_t chap_tbl_idx)855{856 int ret = 0;857 858 ret = device_for_each_child(&shost->shost_gendev, &chap_tbl_idx,859 __qla4xxx_is_chap_active);860 861 return ret;862}863 864static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx)865{866 struct scsi_qla_host *ha = to_qla_host(shost);867 struct ql4_chap_table *chap_table;868 dma_addr_t chap_dma;869 int max_chap_entries = 0;870 uint32_t offset = 0;871 uint32_t chap_size;872 int ret = 0;873 874 chap_table = dma_pool_zalloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);875 if (chap_table == NULL)876 return -ENOMEM;877 878 if (is_qla80XX(ha))879 max_chap_entries = (ha->hw.flt_chap_size / 2) /880 sizeof(struct ql4_chap_table);881 else882 max_chap_entries = MAX_CHAP_ENTRIES_40XX;883 884 if (chap_tbl_idx > max_chap_entries) {885 ret = -EINVAL;886 goto exit_delete_chap;887 }888 889 /* Check if chap index is in use.890 * If chap is in use don't delet chap entry */891 ret = qla4xxx_is_chap_active(shost, chap_tbl_idx);892 if (ret) {893 ql4_printk(KERN_INFO, ha, "CHAP entry %d is in use, cannot "894 "delete from flash\n", chap_tbl_idx);895 ret = -EBUSY;896 goto exit_delete_chap;897 }898 899 chap_size = sizeof(struct ql4_chap_table);900 if (is_qla40XX(ha))901 offset = FLASH_CHAP_OFFSET | (chap_tbl_idx * chap_size);902 else {903 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);904 /* flt_chap_size is CHAP table size for both ports905 * so divide it by 2 to calculate the offset for second port906 */907 if (ha->port_num == 1)908 offset += (ha->hw.flt_chap_size / 2);909 offset += (chap_tbl_idx * chap_size);910 }911 912 ret = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);913 if (ret != QLA_SUCCESS) {914 ret = -EINVAL;915 goto exit_delete_chap;916 }917 918 DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",919 __le16_to_cpu(chap_table->cookie)));920 921 if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {922 ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");923 goto exit_delete_chap;924 }925 926 chap_table->cookie = cpu_to_le16(0xFFFF);927 928 offset = FLASH_CHAP_OFFSET |929 (chap_tbl_idx * sizeof(struct ql4_chap_table));930 ret = qla4xxx_set_flash(ha, chap_dma, offset, chap_size,931 FLASH_OPT_RMW_COMMIT);932 if (ret == QLA_SUCCESS && ha->chap_list) {933 mutex_lock(&ha->chap_sem);934 /* Update ha chap_list cache */935 memcpy((struct ql4_chap_table *)ha->chap_list + chap_tbl_idx,936 chap_table, sizeof(struct ql4_chap_table));937 mutex_unlock(&ha->chap_sem);938 }939 if (ret != QLA_SUCCESS)940 ret = -EINVAL;941 942exit_delete_chap:943 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);944 return ret;945}946 947/**948 * qla4xxx_set_chap_entry - Make chap entry with given information949 * @shost: pointer to host950 * @data: chap info - credentials, index and type to make chap entry951 * @len: length of data952 *953 * Add or update chap entry with the given information954 **/955static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len)956{957 struct scsi_qla_host *ha = to_qla_host(shost);958 struct iscsi_chap_rec chap_rec;959 struct ql4_chap_table *chap_entry = NULL;960 struct iscsi_param_info *param_info;961 struct nlattr *attr;962 int max_chap_entries = 0;963 int type;964 int rem = len;965 int rc = 0;966 int size;967 968 memset(&chap_rec, 0, sizeof(chap_rec));969 970 nla_for_each_attr(attr, data, len, rem) {971 if (nla_len(attr) < sizeof(*param_info)) {972 rc = -EINVAL;973 goto exit_set_chap;974 }975 976 param_info = nla_data(attr);977 978 switch (param_info->param) {979 case ISCSI_CHAP_PARAM_INDEX:980 chap_rec.chap_tbl_idx = *(uint16_t *)param_info->value;981 break;982 case ISCSI_CHAP_PARAM_CHAP_TYPE:983 chap_rec.chap_type = param_info->value[0];984 break;985 case ISCSI_CHAP_PARAM_USERNAME:986 size = min_t(size_t, sizeof(chap_rec.username),987 param_info->len);988 memcpy(chap_rec.username, param_info->value, size);989 break;990 case ISCSI_CHAP_PARAM_PASSWORD:991 size = min_t(size_t, sizeof(chap_rec.password),992 param_info->len);993 memcpy(chap_rec.password, param_info->value, size);994 break;995 case ISCSI_CHAP_PARAM_PASSWORD_LEN:996 chap_rec.password_length = param_info->value[0];997 break;998 default:999 ql4_printk(KERN_ERR, ha,1000 "%s: No such sysfs attribute\n", __func__);1001 rc = -ENOSYS;1002 goto exit_set_chap;1003 }1004 }1005 1006 if (chap_rec.chap_type == CHAP_TYPE_IN)1007 type = BIDI_CHAP;1008 else1009 type = LOCAL_CHAP;1010 1011 if (is_qla80XX(ha))1012 max_chap_entries = (ha->hw.flt_chap_size / 2) /1013 sizeof(struct ql4_chap_table);1014 else1015 max_chap_entries = MAX_CHAP_ENTRIES_40XX;1016 1017 mutex_lock(&ha->chap_sem);1018 if (chap_rec.chap_tbl_idx < max_chap_entries) {1019 rc = qla4xxx_get_chap_by_index(ha, chap_rec.chap_tbl_idx,1020 &chap_entry);1021 if (!rc) {1022 if (!(type == qla4xxx_get_chap_type(chap_entry))) {1023 ql4_printk(KERN_INFO, ha,1024 "Type mismatch for CHAP entry %d\n",1025 chap_rec.chap_tbl_idx);1026 rc = -EINVAL;1027 goto exit_unlock_chap;1028 }1029 1030 /* If chap index is in use then don't modify it */1031 rc = qla4xxx_is_chap_active(shost,1032 chap_rec.chap_tbl_idx);1033 if (rc) {1034 ql4_printk(KERN_INFO, ha,1035 "CHAP entry %d is in use\n",1036 chap_rec.chap_tbl_idx);1037 rc = -EBUSY;1038 goto exit_unlock_chap;1039 }1040 }1041 } else {1042 rc = qla4xxx_find_free_chap_index(ha, &chap_rec.chap_tbl_idx);1043 if (rc) {1044 ql4_printk(KERN_INFO, ha, "CHAP entry not available\n");1045 rc = -EBUSY;1046 goto exit_unlock_chap;1047 }1048 }1049 1050 rc = qla4xxx_set_chap(ha, chap_rec.username, chap_rec.password,1051 chap_rec.chap_tbl_idx, type);1052 1053exit_unlock_chap:1054 mutex_unlock(&ha->chap_sem);1055 1056exit_set_chap:1057 return rc;1058}1059 1060 1061static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len)1062{1063 struct scsi_qla_host *ha = to_qla_host(shost);1064 struct iscsi_offload_host_stats *host_stats = NULL;1065 int host_stats_size;1066 int ret = 0;1067 int ddb_idx = 0;1068 struct ql_iscsi_stats *ql_iscsi_stats = NULL;1069 int stats_size;1070 dma_addr_t iscsi_stats_dma;1071 1072 DEBUG2(ql4_printk(KERN_INFO, ha, "Func: %s\n", __func__));1073 1074 host_stats_size = sizeof(struct iscsi_offload_host_stats);1075 1076 if (host_stats_size != len) {1077 ql4_printk(KERN_INFO, ha, "%s: host_stats size mismatch expected = %d, is = %d\n",1078 __func__, len, host_stats_size);1079 ret = -EINVAL;1080 goto exit_host_stats;1081 }1082 host_stats = (struct iscsi_offload_host_stats *)buf;1083 1084 if (!buf) {1085 ret = -ENOMEM;1086 goto exit_host_stats;1087 }1088 1089 stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats));1090 1091 ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size,1092 &iscsi_stats_dma, GFP_KERNEL);1093 if (!ql_iscsi_stats) {1094 ql4_printk(KERN_ERR, ha,1095 "Unable to allocate memory for iscsi stats\n");1096 ret = -ENOMEM;1097 goto exit_host_stats;1098 }1099 1100 ret = qla4xxx_get_mgmt_data(ha, ddb_idx, stats_size,1101 iscsi_stats_dma);1102 if (ret != QLA_SUCCESS) {1103 ql4_printk(KERN_ERR, ha,1104 "Unable to retrieve iscsi stats\n");1105 ret = -EIO;1106 goto exit_host_stats;1107 }1108 host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames);1109 host_stats->mactx_bytes = le64_to_cpu(ql_iscsi_stats->mac_tx_bytes);1110 host_stats->mactx_multicast_frames =1111 le64_to_cpu(ql_iscsi_stats->mac_tx_multicast_frames);1112 host_stats->mactx_broadcast_frames =1113 le64_to_cpu(ql_iscsi_stats->mac_tx_broadcast_frames);1114 host_stats->mactx_pause_frames =1115 le64_to_cpu(ql_iscsi_stats->mac_tx_pause_frames);1116 host_stats->mactx_control_frames =1117 le64_to_cpu(ql_iscsi_stats->mac_tx_control_frames);1118 host_stats->mactx_deferral =1119 le64_to_cpu(ql_iscsi_stats->mac_tx_deferral);1120 host_stats->mactx_excess_deferral =1121 le64_to_cpu(ql_iscsi_stats->mac_tx_excess_deferral);1122 host_stats->mactx_late_collision =1123 le64_to_cpu(ql_iscsi_stats->mac_tx_late_collision);1124 host_stats->mactx_abort = le64_to_cpu(ql_iscsi_stats->mac_tx_abort);1125 host_stats->mactx_single_collision =1126 le64_to_cpu(ql_iscsi_stats->mac_tx_single_collision);1127 host_stats->mactx_multiple_collision =1128 le64_to_cpu(ql_iscsi_stats->mac_tx_multiple_collision);1129 host_stats->mactx_collision =1130 le64_to_cpu(ql_iscsi_stats->mac_tx_collision);1131 host_stats->mactx_frames_dropped =1132 le64_to_cpu(ql_iscsi_stats->mac_tx_frames_dropped);1133 host_stats->mactx_jumbo_frames =1134 le64_to_cpu(ql_iscsi_stats->mac_tx_jumbo_frames);1135 host_stats->macrx_frames = le64_to_cpu(ql_iscsi_stats->mac_rx_frames);1136 host_stats->macrx_bytes = le64_to_cpu(ql_iscsi_stats->mac_rx_bytes);1137 host_stats->macrx_unknown_control_frames =1138 le64_to_cpu(ql_iscsi_stats->mac_rx_unknown_control_frames);1139 host_stats->macrx_pause_frames =1140 le64_to_cpu(ql_iscsi_stats->mac_rx_pause_frames);1141 host_stats->macrx_control_frames =1142 le64_to_cpu(ql_iscsi_stats->mac_rx_control_frames);1143 host_stats->macrx_dribble =1144 le64_to_cpu(ql_iscsi_stats->mac_rx_dribble);1145 host_stats->macrx_frame_length_error =1146 le64_to_cpu(ql_iscsi_stats->mac_rx_frame_length_error);1147 host_stats->macrx_jabber = le64_to_cpu(ql_iscsi_stats->mac_rx_jabber);1148 host_stats->macrx_carrier_sense_error =1149 le64_to_cpu(ql_iscsi_stats->mac_rx_carrier_sense_error);1150 host_stats->macrx_frame_discarded =1151 le64_to_cpu(ql_iscsi_stats->mac_rx_frame_discarded);1152 host_stats->macrx_frames_dropped =1153 le64_to_cpu(ql_iscsi_stats->mac_rx_frames_dropped);1154 host_stats->mac_crc_error = le64_to_cpu(ql_iscsi_stats->mac_crc_error);1155 host_stats->mac_encoding_error =1156 le64_to_cpu(ql_iscsi_stats->mac_encoding_error);1157 host_stats->macrx_length_error_large =1158 le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_large);1159 host_stats->macrx_length_error_small =1160 le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_small);1161 host_stats->macrx_multicast_frames =1162 le64_to_cpu(ql_iscsi_stats->mac_rx_multicast_frames);1163 host_stats->macrx_broadcast_frames =1164 le64_to_cpu(ql_iscsi_stats->mac_rx_broadcast_frames);1165 host_stats->iptx_packets = le64_to_cpu(ql_iscsi_stats->ip_tx_packets);1166 host_stats->iptx_bytes = le64_to_cpu(ql_iscsi_stats->ip_tx_bytes);1167 host_stats->iptx_fragments =1168 le64_to_cpu(ql_iscsi_stats->ip_tx_fragments);1169 host_stats->iprx_packets = le64_to_cpu(ql_iscsi_stats->ip_rx_packets);1170 host_stats->iprx_bytes = le64_to_cpu(ql_iscsi_stats->ip_rx_bytes);1171 host_stats->iprx_fragments =1172 le64_to_cpu(ql_iscsi_stats->ip_rx_fragments);1173 host_stats->ip_datagram_reassembly =1174 le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly);1175 host_stats->ip_invalid_address_error =1176 le64_to_cpu(ql_iscsi_stats->ip_invalid_address_error);1177 host_stats->ip_error_packets =1178 le64_to_cpu(ql_iscsi_stats->ip_error_packets);1179 host_stats->ip_fragrx_overlap =1180 le64_to_cpu(ql_iscsi_stats->ip_fragrx_overlap);1181 host_stats->ip_fragrx_outoforder =1182 le64_to_cpu(ql_iscsi_stats->ip_fragrx_outoforder);1183 host_stats->ip_datagram_reassembly_timeout =1184 le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly_timeout);1185 host_stats->ipv6tx_packets =1186 le64_to_cpu(ql_iscsi_stats->ipv6_tx_packets);1187 host_stats->ipv6tx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_tx_bytes);1188 host_stats->ipv6tx_fragments =1189 le64_to_cpu(ql_iscsi_stats->ipv6_tx_fragments);1190 host_stats->ipv6rx_packets =1191 le64_to_cpu(ql_iscsi_stats->ipv6_rx_packets);1192 host_stats->ipv6rx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_rx_bytes);1193 host_stats->ipv6rx_fragments =1194 le64_to_cpu(ql_iscsi_stats->ipv6_rx_fragments);1195 host_stats->ipv6_datagram_reassembly =1196 le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly);1197 host_stats->ipv6_invalid_address_error =1198 le64_to_cpu(ql_iscsi_stats->ipv6_invalid_address_error);1199 host_stats->ipv6_error_packets =1200 le64_to_cpu(ql_iscsi_stats->ipv6_error_packets);1201 host_stats->ipv6_fragrx_overlap =1202 le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_overlap);1203 host_stats->ipv6_fragrx_outoforder =1204 le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_outoforder);1205 host_stats->ipv6_datagram_reassembly_timeout =1206 le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly_timeout);1207 host_stats->tcptx_segments =1208 le64_to_cpu(ql_iscsi_stats->tcp_tx_segments);1209 host_stats->tcptx_bytes = le64_to_cpu(ql_iscsi_stats->tcp_tx_bytes);1210 host_stats->tcprx_segments =1211 le64_to_cpu(ql_iscsi_stats->tcp_rx_segments);1212 host_stats->tcprx_byte = le64_to_cpu(ql_iscsi_stats->tcp_rx_byte);1213 host_stats->tcp_duplicate_ack_retx =1214 le64_to_cpu(ql_iscsi_stats->tcp_duplicate_ack_retx);1215 host_stats->tcp_retx_timer_expired =1216 le64_to_cpu(ql_iscsi_stats->tcp_retx_timer_expired);1217 host_stats->tcprx_duplicate_ack =1218 le64_to_cpu(ql_iscsi_stats->tcp_rx_duplicate_ack);1219 host_stats->tcprx_pure_ackr =1220 le64_to_cpu(ql_iscsi_stats->tcp_rx_pure_ackr);1221 host_stats->tcptx_delayed_ack =1222 le64_to_cpu(ql_iscsi_stats->tcp_tx_delayed_ack);1223 host_stats->tcptx_pure_ack =1224 le64_to_cpu(ql_iscsi_stats->tcp_tx_pure_ack);1225 host_stats->tcprx_segment_error =1226 le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_error);1227 host_stats->tcprx_segment_outoforder =1228 le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_outoforder);1229 host_stats->tcprx_window_probe =1230 le64_to_cpu(ql_iscsi_stats->tcp_rx_window_probe);1231 host_stats->tcprx_window_update =1232 le64_to_cpu(ql_iscsi_stats->tcp_rx_window_update);1233 host_stats->tcptx_window_probe_persist =1234 le64_to_cpu(ql_iscsi_stats->tcp_tx_window_probe_persist);1235 host_stats->ecc_error_correction =1236 le64_to_cpu(ql_iscsi_stats->ecc_error_correction);1237 host_stats->iscsi_pdu_tx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_tx);1238 host_stats->iscsi_data_bytes_tx =1239 le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_tx);1240 host_stats->iscsi_pdu_rx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_rx);1241 host_stats->iscsi_data_bytes_rx =1242 le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_rx);1243 host_stats->iscsi_io_completed =1244 le64_to_cpu(ql_iscsi_stats->iscsi_io_completed);1245 host_stats->iscsi_unexpected_io_rx =1246 le64_to_cpu(ql_iscsi_stats->iscsi_unexpected_io_rx);1247 host_stats->iscsi_format_error =1248 le64_to_cpu(ql_iscsi_stats->iscsi_format_error);1249 host_stats->iscsi_hdr_digest_error =1250 le64_to_cpu(ql_iscsi_stats->iscsi_hdr_digest_error);1251 host_stats->iscsi_data_digest_error =1252 le64_to_cpu(ql_iscsi_stats->iscsi_data_digest_error);1253 host_stats->iscsi_sequence_error =1254 le64_to_cpu(ql_iscsi_stats->iscsi_sequence_error);1255exit_host_stats:1256 if (ql_iscsi_stats)1257 dma_free_coherent(&ha->pdev->dev, stats_size,1258 ql_iscsi_stats, iscsi_stats_dma);1259 1260 ql4_printk(KERN_INFO, ha, "%s: Get host stats done\n",1261 __func__);1262 return ret;1263}1264 1265static int qla4xxx_get_iface_param(struct iscsi_iface *iface,1266 enum iscsi_param_type param_type,1267 int param, char *buf)1268{1269 struct Scsi_Host *shost = iscsi_iface_to_shost(iface);1270 struct scsi_qla_host *ha = to_qla_host(shost);1271 int ival;1272 char *pval = NULL;1273 int len = -ENOSYS;1274 1275 if (param_type == ISCSI_NET_PARAM) {1276 switch (param) {1277 case ISCSI_NET_PARAM_IPV4_ADDR:1278 len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);1279 break;1280 case ISCSI_NET_PARAM_IPV4_SUBNET:1281 len = sprintf(buf, "%pI4\n",1282 &ha->ip_config.subnet_mask);1283 break;1284 case ISCSI_NET_PARAM_IPV4_GW:1285 len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway);1286 break;1287 case ISCSI_NET_PARAM_IFACE_ENABLE:1288 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1289 OP_STATE(ha->ip_config.ipv4_options,1290 IPOPT_IPV4_PROTOCOL_ENABLE, pval);1291 } else {1292 OP_STATE(ha->ip_config.ipv6_options,1293 IPV6_OPT_IPV6_PROTOCOL_ENABLE, pval);1294 }1295 1296 len = sprintf(buf, "%s\n", pval);1297 break;1298 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:1299 len = sprintf(buf, "%s\n",1300 (ha->ip_config.tcp_options &1301 TCPOPT_DHCP_ENABLE) ?1302 "dhcp" : "static");1303 break;1304 case ISCSI_NET_PARAM_IPV6_ADDR:1305 if (iface->iface_num == 0)1306 len = sprintf(buf, "%pI6\n",1307 &ha->ip_config.ipv6_addr0);1308 if (iface->iface_num == 1)1309 len = sprintf(buf, "%pI6\n",1310 &ha->ip_config.ipv6_addr1);1311 break;1312 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:1313 len = sprintf(buf, "%pI6\n",1314 &ha->ip_config.ipv6_link_local_addr);1315 break;1316 case ISCSI_NET_PARAM_IPV6_ROUTER:1317 len = sprintf(buf, "%pI6\n",1318 &ha->ip_config.ipv6_default_router_addr);1319 break;1320 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:1321 pval = (ha->ip_config.ipv6_addl_options &1322 IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ?1323 "nd" : "static";1324 1325 len = sprintf(buf, "%s\n", pval);1326 break;1327 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:1328 pval = (ha->ip_config.ipv6_addl_options &1329 IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ?1330 "auto" : "static";1331 1332 len = sprintf(buf, "%s\n", pval);1333 break;1334 case ISCSI_NET_PARAM_VLAN_ID:1335 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)1336 ival = ha->ip_config.ipv4_vlan_tag &1337 ISCSI_MAX_VLAN_ID;1338 else1339 ival = ha->ip_config.ipv6_vlan_tag &1340 ISCSI_MAX_VLAN_ID;1341 1342 len = sprintf(buf, "%d\n", ival);1343 break;1344 case ISCSI_NET_PARAM_VLAN_PRIORITY:1345 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)1346 ival = (ha->ip_config.ipv4_vlan_tag >> 13) &1347 ISCSI_MAX_VLAN_PRIORITY;1348 else1349 ival = (ha->ip_config.ipv6_vlan_tag >> 13) &1350 ISCSI_MAX_VLAN_PRIORITY;1351 1352 len = sprintf(buf, "%d\n", ival);1353 break;1354 case ISCSI_NET_PARAM_VLAN_ENABLED:1355 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1356 OP_STATE(ha->ip_config.ipv4_options,1357 IPOPT_VLAN_TAGGING_ENABLE, pval);1358 } else {1359 OP_STATE(ha->ip_config.ipv6_options,1360 IPV6_OPT_VLAN_TAGGING_ENABLE, pval);1361 }1362 len = sprintf(buf, "%s\n", pval);1363 break;1364 case ISCSI_NET_PARAM_MTU:1365 len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size);1366 break;1367 case ISCSI_NET_PARAM_PORT:1368 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)1369 len = sprintf(buf, "%d\n",1370 ha->ip_config.ipv4_port);1371 else1372 len = sprintf(buf, "%d\n",1373 ha->ip_config.ipv6_port);1374 break;1375 case ISCSI_NET_PARAM_IPADDR_STATE:1376 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1377 pval = iscsi_get_ipaddress_state_name(1378 ha->ip_config.ipv4_addr_state);1379 } else {1380 if (iface->iface_num == 0)1381 pval = iscsi_get_ipaddress_state_name(1382 ha->ip_config.ipv6_addr0_state);1383 else if (iface->iface_num == 1)1384 pval = iscsi_get_ipaddress_state_name(1385 ha->ip_config.ipv6_addr1_state);1386 }1387 1388 len = sprintf(buf, "%s\n", pval);1389 break;1390 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE:1391 pval = iscsi_get_ipaddress_state_name(1392 ha->ip_config.ipv6_link_local_state);1393 len = sprintf(buf, "%s\n", pval);1394 break;1395 case ISCSI_NET_PARAM_IPV6_ROUTER_STATE:1396 pval = iscsi_get_router_state_name(1397 ha->ip_config.ipv6_default_router_state);1398 len = sprintf(buf, "%s\n", pval);1399 break;1400 case ISCSI_NET_PARAM_DELAYED_ACK_EN:1401 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1402 OP_STATE(~ha->ip_config.tcp_options,1403 TCPOPT_DELAYED_ACK_DISABLE, pval);1404 } else {1405 OP_STATE(~ha->ip_config.ipv6_tcp_options,1406 IPV6_TCPOPT_DELAYED_ACK_DISABLE, pval);1407 }1408 len = sprintf(buf, "%s\n", pval);1409 break;1410 case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE:1411 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1412 OP_STATE(~ha->ip_config.tcp_options,1413 TCPOPT_NAGLE_ALGO_DISABLE, pval);1414 } else {1415 OP_STATE(~ha->ip_config.ipv6_tcp_options,1416 IPV6_TCPOPT_NAGLE_ALGO_DISABLE, pval);1417 }1418 len = sprintf(buf, "%s\n", pval);1419 break;1420 case ISCSI_NET_PARAM_TCP_WSF_DISABLE:1421 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1422 OP_STATE(~ha->ip_config.tcp_options,1423 TCPOPT_WINDOW_SCALE_DISABLE, pval);1424 } else {1425 OP_STATE(~ha->ip_config.ipv6_tcp_options,1426 IPV6_TCPOPT_WINDOW_SCALE_DISABLE,1427 pval);1428 }1429 len = sprintf(buf, "%s\n", pval);1430 break;1431 case ISCSI_NET_PARAM_TCP_WSF:1432 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)1433 len = sprintf(buf, "%d\n",1434 ha->ip_config.tcp_wsf);1435 else1436 len = sprintf(buf, "%d\n",1437 ha->ip_config.ipv6_tcp_wsf);1438 break;1439 case ISCSI_NET_PARAM_TCP_TIMER_SCALE:1440 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)1441 ival = (ha->ip_config.tcp_options &1442 TCPOPT_TIMER_SCALE) >> 1;1443 else1444 ival = (ha->ip_config.ipv6_tcp_options &1445 IPV6_TCPOPT_TIMER_SCALE) >> 1;1446 1447 len = sprintf(buf, "%d\n", ival);1448 break;1449 case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN:1450 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1451 OP_STATE(ha->ip_config.tcp_options,1452 TCPOPT_TIMESTAMP_ENABLE, pval);1453 } else {1454 OP_STATE(ha->ip_config.ipv6_tcp_options,1455 IPV6_TCPOPT_TIMESTAMP_EN, pval);1456 }1457 len = sprintf(buf, "%s\n", pval);1458 break;1459 case ISCSI_NET_PARAM_CACHE_ID:1460 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)1461 len = sprintf(buf, "%d\n",1462 ha->ip_config.ipv4_cache_id);1463 else1464 len = sprintf(buf, "%d\n",1465 ha->ip_config.ipv6_cache_id);1466 break;1467 case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN:1468 OP_STATE(ha->ip_config.tcp_options,1469 TCPOPT_DNS_SERVER_IP_EN, pval);1470 1471 len = sprintf(buf, "%s\n", pval);1472 break;1473 case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN:1474 OP_STATE(ha->ip_config.tcp_options,1475 TCPOPT_SLP_DA_INFO_EN, pval);1476 1477 len = sprintf(buf, "%s\n", pval);1478 break;1479 case ISCSI_NET_PARAM_IPV4_TOS_EN:1480 OP_STATE(ha->ip_config.ipv4_options,1481 IPOPT_IPV4_TOS_EN, pval);1482 1483 len = sprintf(buf, "%s\n", pval);1484 break;1485 case ISCSI_NET_PARAM_IPV4_TOS:1486 len = sprintf(buf, "%d\n", ha->ip_config.ipv4_tos);1487 break;1488 case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN:1489 OP_STATE(ha->ip_config.ipv4_options,1490 IPOPT_GRAT_ARP_EN, pval);1491 1492 len = sprintf(buf, "%s\n", pval);1493 break;1494 case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN:1495 OP_STATE(ha->ip_config.ipv4_options, IPOPT_ALT_CID_EN,1496 pval);1497 1498 len = sprintf(buf, "%s\n", pval);1499 break;1500 case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID:1501 pval = (ha->ip_config.ipv4_alt_cid_len) ?1502 (char *)ha->ip_config.ipv4_alt_cid : "";1503 1504 len = sprintf(buf, "%s\n", pval);1505 break;1506 case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN:1507 OP_STATE(ha->ip_config.ipv4_options,1508 IPOPT_REQ_VID_EN, pval);1509 1510 len = sprintf(buf, "%s\n", pval);1511 break;1512 case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN:1513 OP_STATE(ha->ip_config.ipv4_options,1514 IPOPT_USE_VID_EN, pval);1515 1516 len = sprintf(buf, "%s\n", pval);1517 break;1518 case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID:1519 pval = (ha->ip_config.ipv4_vid_len) ?1520 (char *)ha->ip_config.ipv4_vid : "";1521 1522 len = sprintf(buf, "%s\n", pval);1523 break;1524 case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN:1525 OP_STATE(ha->ip_config.ipv4_options,1526 IPOPT_LEARN_IQN_EN, pval);1527 1528 len = sprintf(buf, "%s\n", pval);1529 break;1530 case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE:1531 OP_STATE(~ha->ip_config.ipv4_options,1532 IPOPT_FRAGMENTATION_DISABLE, pval);1533 1534 len = sprintf(buf, "%s\n", pval);1535 break;1536 case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN:1537 OP_STATE(ha->ip_config.ipv4_options,1538 IPOPT_IN_FORWARD_EN, pval);1539 1540 len = sprintf(buf, "%s\n", pval);1541 break;1542 case ISCSI_NET_PARAM_REDIRECT_EN:1543 if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {1544 OP_STATE(ha->ip_config.ipv4_options,1545 IPOPT_ARP_REDIRECT_EN, pval);1546 } else {1547 OP_STATE(ha->ip_config.ipv6_options,1548 IPV6_OPT_REDIRECT_EN, pval);1549 }1550 len = sprintf(buf, "%s\n", pval);1551 break;1552 case ISCSI_NET_PARAM_IPV4_TTL:1553 len = sprintf(buf, "%d\n", ha->ip_config.ipv4_ttl);1554 break;1555 case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN:1556 OP_STATE(ha->ip_config.ipv6_options,1557 IPV6_OPT_GRAT_NEIGHBOR_ADV_EN, pval);1558 1559 len = sprintf(buf, "%s\n", pval);1560 break;1561 case ISCSI_NET_PARAM_IPV6_MLD_EN:1562 OP_STATE(ha->ip_config.ipv6_addl_options,1563 IPV6_ADDOPT_MLD_EN, pval);1564 1565 len = sprintf(buf, "%s\n", pval);1566 break;1567 case ISCSI_NET_PARAM_IPV6_FLOW_LABEL:1568 len = sprintf(buf, "%u\n", ha->ip_config.ipv6_flow_lbl);1569 break;1570 case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS:1571 len = sprintf(buf, "%d\n",1572 ha->ip_config.ipv6_traffic_class);1573 break;1574 case ISCSI_NET_PARAM_IPV6_HOP_LIMIT:1575 len = sprintf(buf, "%d\n",1576 ha->ip_config.ipv6_hop_limit);1577 break;1578 case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO:1579 len = sprintf(buf, "%d\n",1580 ha->ip_config.ipv6_nd_reach_time);1581 break;1582 case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME:1583 len = sprintf(buf, "%d\n",1584 ha->ip_config.ipv6_nd_rexmit_timer);1585 break;1586 case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO:1587 len = sprintf(buf, "%d\n",1588 ha->ip_config.ipv6_nd_stale_timeout);1589 break;1590 case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT:1591 len = sprintf(buf, "%d\n",1592 ha->ip_config.ipv6_dup_addr_detect_count);1593 break;1594 case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU:1595 len = sprintf(buf, "%d\n",1596 ha->ip_config.ipv6_gw_advrt_mtu);1597 break;1598 default:1599 len = -ENOSYS;1600 }1601 } else if (param_type == ISCSI_IFACE_PARAM) {1602 switch (param) {1603 case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO:1604 len = sprintf(buf, "%d\n", ha->ip_config.def_timeout);1605 break;1606 case ISCSI_IFACE_PARAM_HDRDGST_EN:1607 OP_STATE(ha->ip_config.iscsi_options,1608 ISCSIOPTS_HEADER_DIGEST_EN, pval);1609 1610 len = sprintf(buf, "%s\n", pval);1611 break;1612 case ISCSI_IFACE_PARAM_DATADGST_EN:1613 OP_STATE(ha->ip_config.iscsi_options,1614 ISCSIOPTS_DATA_DIGEST_EN, pval);1615 1616 len = sprintf(buf, "%s\n", pval);1617 break;1618 case ISCSI_IFACE_PARAM_IMM_DATA_EN:1619 OP_STATE(ha->ip_config.iscsi_options,1620 ISCSIOPTS_IMMEDIATE_DATA_EN, pval);1621 1622 len = sprintf(buf, "%s\n", pval);1623 break;1624 case ISCSI_IFACE_PARAM_INITIAL_R2T_EN:1625 OP_STATE(ha->ip_config.iscsi_options,1626 ISCSIOPTS_INITIAL_R2T_EN, pval);1627 1628 len = sprintf(buf, "%s\n", pval);1629 break;1630 case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN:1631 OP_STATE(ha->ip_config.iscsi_options,1632 ISCSIOPTS_DATA_SEQ_INORDER_EN, pval);1633 1634 len = sprintf(buf, "%s\n", pval);1635 break;1636 case ISCSI_IFACE_PARAM_PDU_INORDER_EN:1637 OP_STATE(ha->ip_config.iscsi_options,1638 ISCSIOPTS_DATA_PDU_INORDER_EN, pval);1639 1640 len = sprintf(buf, "%s\n", pval);1641 break;1642 case ISCSI_IFACE_PARAM_ERL:1643 len = sprintf(buf, "%d\n",1644 (ha->ip_config.iscsi_options &1645 ISCSIOPTS_ERL));1646 break;1647 case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH:1648 len = sprintf(buf, "%u\n",1649 ha->ip_config.iscsi_max_pdu_size *1650 BYTE_UNITS);1651 break;1652 case ISCSI_IFACE_PARAM_FIRST_BURST:1653 len = sprintf(buf, "%u\n",1654 ha->ip_config.iscsi_first_burst_len *1655 BYTE_UNITS);1656 break;1657 case ISCSI_IFACE_PARAM_MAX_R2T:1658 len = sprintf(buf, "%d\n",1659 ha->ip_config.iscsi_max_outstnd_r2t);1660 break;1661 case ISCSI_IFACE_PARAM_MAX_BURST:1662 len = sprintf(buf, "%u\n",1663 ha->ip_config.iscsi_max_burst_len *1664 BYTE_UNITS);1665 break;1666 case ISCSI_IFACE_PARAM_CHAP_AUTH_EN:1667 OP_STATE(ha->ip_config.iscsi_options,1668 ISCSIOPTS_CHAP_AUTH_EN, pval);1669 1670 len = sprintf(buf, "%s\n", pval);1671 break;1672 case ISCSI_IFACE_PARAM_BIDI_CHAP_EN:1673 OP_STATE(ha->ip_config.iscsi_options,1674 ISCSIOPTS_BIDI_CHAP_EN, pval);1675 1676 len = sprintf(buf, "%s\n", pval);1677 break;1678 case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL:1679 OP_STATE(ha->ip_config.iscsi_options,1680 ISCSIOPTS_DISCOVERY_AUTH_EN, pval);1681 1682 len = sprintf(buf, "%s\n", pval);1683 break;1684 case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN:1685 OP_STATE(ha->ip_config.iscsi_options,1686 ISCSIOPTS_DISCOVERY_LOGOUT_EN, pval);1687 1688 len = sprintf(buf, "%s\n", pval);1689 break;1690 case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN:1691 OP_STATE(ha->ip_config.iscsi_options,1692 ISCSIOPTS_STRICT_LOGIN_COMP_EN, pval);1693 1694 len = sprintf(buf, "%s\n", pval);1695 break;1696 case ISCSI_IFACE_PARAM_INITIATOR_NAME:1697 len = sprintf(buf, "%s\n", ha->ip_config.iscsi_name);1698 break;1699 default:1700 len = -ENOSYS;1701 }1702 }1703 1704 return len;1705}1706 1707static struct iscsi_endpoint *1708qla4xxx_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,1709 int non_blocking)1710{1711 int ret;1712 struct iscsi_endpoint *ep;1713 struct qla_endpoint *qla_ep;1714 struct scsi_qla_host *ha;1715 struct sockaddr_in *addr;1716 struct sockaddr_in6 *addr6;1717 1718 if (!shost) {1719 ret = -ENXIO;1720 pr_err("%s: shost is NULL\n", __func__);1721 return ERR_PTR(ret);1722 }1723 1724 ha = iscsi_host_priv(shost);1725 ep = iscsi_create_endpoint(sizeof(struct qla_endpoint));1726 if (!ep) {1727 ret = -ENOMEM;1728 return ERR_PTR(ret);1729 }1730 1731 qla_ep = ep->dd_data;1732 memset(qla_ep, 0, sizeof(struct qla_endpoint));1733 if (dst_addr->sa_family == AF_INET) {1734 memcpy(&qla_ep->dst_addr, dst_addr, sizeof(struct sockaddr_in));1735 addr = (struct sockaddr_in *)&qla_ep->dst_addr;1736 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI4\n", __func__,1737 (char *)&addr->sin_addr));1738 } else if (dst_addr->sa_family == AF_INET6) {1739 memcpy(&qla_ep->dst_addr, dst_addr,1740 sizeof(struct sockaddr_in6));1741 addr6 = (struct sockaddr_in6 *)&qla_ep->dst_addr;1742 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: %pI6\n", __func__,1743 (char *)&addr6->sin6_addr));1744 } else {1745 ql4_printk(KERN_WARNING, ha, "%s: Invalid endpoint\n",1746 __func__);1747 }1748 1749 qla_ep->host = shost;1750 1751 return ep;1752}1753 1754static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)1755{1756 struct qla_endpoint *qla_ep;1757 struct scsi_qla_host *ha;1758 int ret = 0;1759 1760 qla_ep = ep->dd_data;1761 ha = to_qla_host(qla_ep->host);1762 DEBUG2(pr_info_ratelimited("%s: host: %ld\n", __func__, ha->host_no));1763 1764 if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags))1765 ret = 1;1766 1767 return ret;1768}1769 1770static void qla4xxx_ep_disconnect(struct iscsi_endpoint *ep)1771{1772 struct qla_endpoint *qla_ep;1773 struct scsi_qla_host *ha;1774 1775 qla_ep = ep->dd_data;1776 ha = to_qla_host(qla_ep->host);1777 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__,1778 ha->host_no));1779 iscsi_destroy_endpoint(ep);1780}1781 1782static int qla4xxx_get_ep_param(struct iscsi_endpoint *ep,1783 enum iscsi_param param,1784 char *buf)1785{1786 struct qla_endpoint *qla_ep = ep->dd_data;1787 struct sockaddr *dst_addr;1788 struct scsi_qla_host *ha;1789 1790 if (!qla_ep)1791 return -ENOTCONN;1792 1793 ha = to_qla_host(qla_ep->host);1794 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__,1795 ha->host_no));1796 1797 switch (param) {1798 case ISCSI_PARAM_CONN_PORT:1799 case ISCSI_PARAM_CONN_ADDRESS:1800 dst_addr = (struct sockaddr *)&qla_ep->dst_addr;1801 if (!dst_addr)1802 return -ENOTCONN;1803 1804 return iscsi_conn_get_addr_param((struct sockaddr_storage *)1805 &qla_ep->dst_addr, param, buf);1806 default:1807 return -ENOSYS;1808 }1809}1810 1811static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,1812 struct iscsi_stats *stats)1813{1814 struct iscsi_session *sess;1815 struct iscsi_cls_session *cls_sess;1816 struct ddb_entry *ddb_entry;1817 struct scsi_qla_host *ha;1818 struct ql_iscsi_stats *ql_iscsi_stats;1819 int stats_size;1820 int ret;1821 dma_addr_t iscsi_stats_dma;1822 1823 cls_sess = iscsi_conn_to_session(cls_conn);1824 sess = cls_sess->dd_data;1825 ddb_entry = sess->dd_data;1826 ha = ddb_entry->ha;1827 1828 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__,1829 ha->host_no));1830 stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats));1831 /* Allocate memory */1832 ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size,1833 &iscsi_stats_dma, GFP_KERNEL);1834 if (!ql_iscsi_stats) {1835 ql4_printk(KERN_ERR, ha,1836 "Unable to allocate memory for iscsi stats\n");1837 goto exit_get_stats;1838 }1839 1840 ret = qla4xxx_get_mgmt_data(ha, ddb_entry->fw_ddb_index, stats_size,1841 iscsi_stats_dma);1842 if (ret != QLA_SUCCESS) {1843 ql4_printk(KERN_ERR, ha,1844 "Unable to retrieve iscsi stats\n");1845 goto free_stats;1846 }1847 1848 /* octets */1849 stats->txdata_octets = le64_to_cpu(ql_iscsi_stats->tx_data_octets);1850 stats->rxdata_octets = le64_to_cpu(ql_iscsi_stats->rx_data_octets);1851 /* xmit pdus */1852 stats->noptx_pdus = le32_to_cpu(ql_iscsi_stats->tx_nopout_pdus);1853 stats->scsicmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_cmd_pdus);1854 stats->tmfcmd_pdus = le32_to_cpu(ql_iscsi_stats->tx_tmf_cmd_pdus);1855 stats->login_pdus = le32_to_cpu(ql_iscsi_stats->tx_login_cmd_pdus);1856 stats->text_pdus = le32_to_cpu(ql_iscsi_stats->tx_text_cmd_pdus);1857 stats->dataout_pdus = le32_to_cpu(ql_iscsi_stats->tx_scsi_write_pdus);1858 stats->logout_pdus = le32_to_cpu(ql_iscsi_stats->tx_logout_cmd_pdus);1859 stats->snack_pdus = le32_to_cpu(ql_iscsi_stats->tx_snack_req_pdus);1860 /* recv pdus */1861 stats->noprx_pdus = le32_to_cpu(ql_iscsi_stats->rx_nopin_pdus);1862 stats->scsirsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_resp_pdus);1863 stats->tmfrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_tmf_resp_pdus);1864 stats->textrsp_pdus = le32_to_cpu(ql_iscsi_stats->rx_text_resp_pdus);1865 stats->datain_pdus = le32_to_cpu(ql_iscsi_stats->rx_scsi_read_pdus);1866 stats->logoutrsp_pdus =1867 le32_to_cpu(ql_iscsi_stats->rx_logout_resp_pdus);1868 stats->r2t_pdus = le32_to_cpu(ql_iscsi_stats->rx_r2t_pdus);1869 stats->async_pdus = le32_to_cpu(ql_iscsi_stats->rx_async_pdus);1870 stats->rjt_pdus = le32_to_cpu(ql_iscsi_stats->rx_reject_pdus);1871 1872free_stats:1873 dma_free_coherent(&ha->pdev->dev, stats_size, ql_iscsi_stats,1874 iscsi_stats_dma);1875exit_get_stats:1876 return;1877}1878 1879static enum scsi_timeout_action qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)1880{1881 struct iscsi_cls_session *session;1882 unsigned long flags;1883 enum scsi_timeout_action ret = SCSI_EH_NOT_HANDLED;1884 1885 session = starget_to_session(scsi_target(sc->device));1886 1887 spin_lock_irqsave(&session->lock, flags);1888 if (session->state == ISCSI_SESSION_FAILED)1889 ret = SCSI_EH_RESET_TIMER;1890 spin_unlock_irqrestore(&session->lock, flags);1891 1892 return ret;1893}1894 1895static void qla4xxx_set_port_speed(struct Scsi_Host *shost)1896{1897 struct scsi_qla_host *ha = to_qla_host(shost);1898 struct iscsi_cls_host *ihost = shost->shost_data;1899 uint32_t speed = ISCSI_PORT_SPEED_UNKNOWN;1900 1901 qla4xxx_get_firmware_state(ha);1902 1903 switch (ha->addl_fw_state & 0x0F00) {1904 case FW_ADDSTATE_LINK_SPEED_10MBPS:1905 speed = ISCSI_PORT_SPEED_10MBPS;1906 break;1907 case FW_ADDSTATE_LINK_SPEED_100MBPS:1908 speed = ISCSI_PORT_SPEED_100MBPS;1909 break;1910 case FW_ADDSTATE_LINK_SPEED_1GBPS:1911 speed = ISCSI_PORT_SPEED_1GBPS;1912 break;1913 case FW_ADDSTATE_LINK_SPEED_10GBPS:1914 speed = ISCSI_PORT_SPEED_10GBPS;1915 break;1916 }1917 ihost->port_speed = speed;1918}1919 1920static void qla4xxx_set_port_state(struct Scsi_Host *shost)1921{1922 struct scsi_qla_host *ha = to_qla_host(shost);1923 struct iscsi_cls_host *ihost = shost->shost_data;1924 uint32_t state = ISCSI_PORT_STATE_DOWN;1925 1926 if (test_bit(AF_LINK_UP, &ha->flags))1927 state = ISCSI_PORT_STATE_UP;1928 1929 ihost->port_state = state;1930}1931 1932static int qla4xxx_host_get_param(struct Scsi_Host *shost,1933 enum iscsi_host_param param, char *buf)1934{1935 struct scsi_qla_host *ha = to_qla_host(shost);1936 int len;1937 1938 switch (param) {1939 case ISCSI_HOST_PARAM_HWADDRESS:1940 len = sysfs_format_mac(buf, ha->my_mac, MAC_ADDR_LEN);1941 break;1942 case ISCSI_HOST_PARAM_IPADDRESS:1943 len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address);1944 break;1945 case ISCSI_HOST_PARAM_INITIATOR_NAME:1946 len = sprintf(buf, "%s\n", ha->name_string);1947 break;1948 case ISCSI_HOST_PARAM_PORT_STATE:1949 qla4xxx_set_port_state(shost);1950 len = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));1951 break;1952 case ISCSI_HOST_PARAM_PORT_SPEED:1953 qla4xxx_set_port_speed(shost);1954 len = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));1955 break;1956 default:1957 return -ENOSYS;1958 }1959 1960 return len;1961}1962 1963static void qla4xxx_create_ipv4_iface(struct scsi_qla_host *ha)1964{1965 if (ha->iface_ipv4)1966 return;1967 1968 /* IPv4 */1969 ha->iface_ipv4 = iscsi_create_iface(ha->host,1970 &qla4xxx_iscsi_transport,1971 ISCSI_IFACE_TYPE_IPV4, 0, 0);1972 if (!ha->iface_ipv4)1973 ql4_printk(KERN_ERR, ha, "Could not create IPv4 iSCSI "1974 "iface0.\n");1975}1976 1977static void qla4xxx_create_ipv6_iface(struct scsi_qla_host *ha)1978{1979 if (!ha->iface_ipv6_0)1980 /* IPv6 iface-0 */1981 ha->iface_ipv6_0 = iscsi_create_iface(ha->host,1982 &qla4xxx_iscsi_transport,1983 ISCSI_IFACE_TYPE_IPV6, 0,1984 0);1985 if (!ha->iface_ipv6_0)1986 ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "1987 "iface0.\n");1988 1989 if (!ha->iface_ipv6_1)1990 /* IPv6 iface-1 */1991 ha->iface_ipv6_1 = iscsi_create_iface(ha->host,1992 &qla4xxx_iscsi_transport,1993 ISCSI_IFACE_TYPE_IPV6, 1,1994 0);1995 if (!ha->iface_ipv6_1)1996 ql4_printk(KERN_ERR, ha, "Could not create IPv6 iSCSI "1997 "iface1.\n");1998}1999 2000static void qla4xxx_create_ifaces(struct scsi_qla_host *ha)2001{2002 if (ha->ip_config.ipv4_options & IPOPT_IPV4_PROTOCOL_ENABLE)2003 qla4xxx_create_ipv4_iface(ha);2004 2005 if (ha->ip_config.ipv6_options & IPV6_OPT_IPV6_PROTOCOL_ENABLE)2006 qla4xxx_create_ipv6_iface(ha);2007}2008 2009static void qla4xxx_destroy_ipv4_iface(struct scsi_qla_host *ha)2010{2011 if (ha->iface_ipv4) {2012 iscsi_destroy_iface(ha->iface_ipv4);2013 ha->iface_ipv4 = NULL;2014 }2015}2016 2017static void qla4xxx_destroy_ipv6_iface(struct scsi_qla_host *ha)2018{2019 if (ha->iface_ipv6_0) {2020 iscsi_destroy_iface(ha->iface_ipv6_0);2021 ha->iface_ipv6_0 = NULL;2022 }2023 if (ha->iface_ipv6_1) {2024 iscsi_destroy_iface(ha->iface_ipv6_1);2025 ha->iface_ipv6_1 = NULL;2026 }2027}2028 2029static void qla4xxx_destroy_ifaces(struct scsi_qla_host *ha)2030{2031 qla4xxx_destroy_ipv4_iface(ha);2032 qla4xxx_destroy_ipv6_iface(ha);2033}2034 2035static void qla4xxx_set_ipv6(struct scsi_qla_host *ha,2036 struct iscsi_iface_param_info *iface_param,2037 struct addr_ctrl_blk *init_fw_cb)2038{2039 /*2040 * iface_num 0 is valid for IPv6 Addr, linklocal, router, autocfg.2041 * iface_num 1 is valid only for IPv6 Addr.2042 */2043 switch (iface_param->param) {2044 case ISCSI_NET_PARAM_IPV6_ADDR:2045 if (iface_param->iface_num & 0x1)2046 /* IPv6 Addr 1 */2047 memcpy(init_fw_cb->ipv6_addr1, iface_param->value,2048 sizeof(init_fw_cb->ipv6_addr1));2049 else2050 /* IPv6 Addr 0 */2051 memcpy(init_fw_cb->ipv6_addr0, iface_param->value,2052 sizeof(init_fw_cb->ipv6_addr0));2053 break;2054 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:2055 if (iface_param->iface_num & 0x1)2056 break;2057 memcpy(init_fw_cb->ipv6_if_id, &iface_param->value[8],2058 sizeof(init_fw_cb->ipv6_if_id));2059 break;2060 case ISCSI_NET_PARAM_IPV6_ROUTER:2061 if (iface_param->iface_num & 0x1)2062 break;2063 memcpy(init_fw_cb->ipv6_dflt_rtr_addr, iface_param->value,2064 sizeof(init_fw_cb->ipv6_dflt_rtr_addr));2065 break;2066 case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG:2067 /* Autocfg applies to even interface */2068 if (iface_param->iface_num & 0x1)2069 break;2070 2071 if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_DISABLE)2072 init_fw_cb->ipv6_addtl_opts &=2073 cpu_to_le16(2074 ~IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);2075 else if (iface_param->value[0] == ISCSI_IPV6_AUTOCFG_ND_ENABLE)2076 init_fw_cb->ipv6_addtl_opts |=2077 cpu_to_le16(2078 IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE);2079 else2080 ql4_printk(KERN_ERR, ha,2081 "Invalid autocfg setting for IPv6 addr\n");2082 break;2083 case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG:2084 /* Autocfg applies to even interface */2085 if (iface_param->iface_num & 0x1)2086 break;2087 2088 if (iface_param->value[0] ==2089 ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE)2090 init_fw_cb->ipv6_addtl_opts |= cpu_to_le16(2091 IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);2092 else if (iface_param->value[0] ==2093 ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE)2094 init_fw_cb->ipv6_addtl_opts &= cpu_to_le16(2095 ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR);2096 else2097 ql4_printk(KERN_ERR, ha,2098 "Invalid autocfg setting for IPv6 linklocal addr\n");2099 break;2100 case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG:2101 /* Autocfg applies to even interface */2102 if (iface_param->iface_num & 0x1)2103 break;2104 2105 if (iface_param->value[0] == ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE)2106 memset(init_fw_cb->ipv6_dflt_rtr_addr, 0,2107 sizeof(init_fw_cb->ipv6_dflt_rtr_addr));2108 break;2109 case ISCSI_NET_PARAM_IFACE_ENABLE:2110 if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {2111 init_fw_cb->ipv6_opts |=2112 cpu_to_le16(IPV6_OPT_IPV6_PROTOCOL_ENABLE);2113 qla4xxx_create_ipv6_iface(ha);2114 } else {2115 init_fw_cb->ipv6_opts &=2116 cpu_to_le16(~IPV6_OPT_IPV6_PROTOCOL_ENABLE &2117 0xFFFF);2118 qla4xxx_destroy_ipv6_iface(ha);2119 }2120 break;2121 case ISCSI_NET_PARAM_VLAN_TAG:2122 if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))2123 break;2124 init_fw_cb->ipv6_vlan_tag =2125 cpu_to_be16(*(uint16_t *)iface_param->value);2126 break;2127 case ISCSI_NET_PARAM_VLAN_ENABLED:2128 if (iface_param->value[0] == ISCSI_VLAN_ENABLE)2129 init_fw_cb->ipv6_opts |=2130 cpu_to_le16(IPV6_OPT_VLAN_TAGGING_ENABLE);2131 else2132 init_fw_cb->ipv6_opts &=2133 cpu_to_le16(~IPV6_OPT_VLAN_TAGGING_ENABLE);2134 break;2135 case ISCSI_NET_PARAM_MTU:2136 init_fw_cb->eth_mtu_size =2137 cpu_to_le16(*(uint16_t *)iface_param->value);2138 break;2139 case ISCSI_NET_PARAM_PORT:2140 /* Autocfg applies to even interface */2141 if (iface_param->iface_num & 0x1)2142 break;2143 2144 init_fw_cb->ipv6_port =2145 cpu_to_le16(*(uint16_t *)iface_param->value);2146 break;2147 case ISCSI_NET_PARAM_DELAYED_ACK_EN:2148 if (iface_param->iface_num & 0x1)2149 break;2150 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2151 init_fw_cb->ipv6_tcp_opts |=2152 cpu_to_le16(IPV6_TCPOPT_DELAYED_ACK_DISABLE);2153 else2154 init_fw_cb->ipv6_tcp_opts &=2155 cpu_to_le16(~IPV6_TCPOPT_DELAYED_ACK_DISABLE &2156 0xFFFF);2157 break;2158 case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE:2159 if (iface_param->iface_num & 0x1)2160 break;2161 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2162 init_fw_cb->ipv6_tcp_opts |=2163 cpu_to_le16(IPV6_TCPOPT_NAGLE_ALGO_DISABLE);2164 else2165 init_fw_cb->ipv6_tcp_opts &=2166 cpu_to_le16(~IPV6_TCPOPT_NAGLE_ALGO_DISABLE);2167 break;2168 case ISCSI_NET_PARAM_TCP_WSF_DISABLE:2169 if (iface_param->iface_num & 0x1)2170 break;2171 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2172 init_fw_cb->ipv6_tcp_opts |=2173 cpu_to_le16(IPV6_TCPOPT_WINDOW_SCALE_DISABLE);2174 else2175 init_fw_cb->ipv6_tcp_opts &=2176 cpu_to_le16(~IPV6_TCPOPT_WINDOW_SCALE_DISABLE);2177 break;2178 case ISCSI_NET_PARAM_TCP_WSF:2179 if (iface_param->iface_num & 0x1)2180 break;2181 init_fw_cb->ipv6_tcp_wsf = iface_param->value[0];2182 break;2183 case ISCSI_NET_PARAM_TCP_TIMER_SCALE:2184 if (iface_param->iface_num & 0x1)2185 break;2186 init_fw_cb->ipv6_tcp_opts &=2187 cpu_to_le16(~IPV6_TCPOPT_TIMER_SCALE);2188 init_fw_cb->ipv6_tcp_opts |=2189 cpu_to_le16((iface_param->value[0] << 1) &2190 IPV6_TCPOPT_TIMER_SCALE);2191 break;2192 case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN:2193 if (iface_param->iface_num & 0x1)2194 break;2195 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2196 init_fw_cb->ipv6_tcp_opts |=2197 cpu_to_le16(IPV6_TCPOPT_TIMESTAMP_EN);2198 else2199 init_fw_cb->ipv6_tcp_opts &=2200 cpu_to_le16(~IPV6_TCPOPT_TIMESTAMP_EN);2201 break;2202 case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN:2203 if (iface_param->iface_num & 0x1)2204 break;2205 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2206 init_fw_cb->ipv6_opts |=2207 cpu_to_le16(IPV6_OPT_GRAT_NEIGHBOR_ADV_EN);2208 else2209 init_fw_cb->ipv6_opts &=2210 cpu_to_le16(~IPV6_OPT_GRAT_NEIGHBOR_ADV_EN);2211 break;2212 case ISCSI_NET_PARAM_REDIRECT_EN:2213 if (iface_param->iface_num & 0x1)2214 break;2215 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2216 init_fw_cb->ipv6_opts |=2217 cpu_to_le16(IPV6_OPT_REDIRECT_EN);2218 else2219 init_fw_cb->ipv6_opts &=2220 cpu_to_le16(~IPV6_OPT_REDIRECT_EN);2221 break;2222 case ISCSI_NET_PARAM_IPV6_MLD_EN:2223 if (iface_param->iface_num & 0x1)2224 break;2225 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2226 init_fw_cb->ipv6_addtl_opts |=2227 cpu_to_le16(IPV6_ADDOPT_MLD_EN);2228 else2229 init_fw_cb->ipv6_addtl_opts &=2230 cpu_to_le16(~IPV6_ADDOPT_MLD_EN);2231 break;2232 case ISCSI_NET_PARAM_IPV6_FLOW_LABEL:2233 if (iface_param->iface_num & 0x1)2234 break;2235 init_fw_cb->ipv6_flow_lbl =2236 cpu_to_le16(*(uint16_t *)iface_param->value);2237 break;2238 case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS:2239 if (iface_param->iface_num & 0x1)2240 break;2241 init_fw_cb->ipv6_traffic_class = iface_param->value[0];2242 break;2243 case ISCSI_NET_PARAM_IPV6_HOP_LIMIT:2244 if (iface_param->iface_num & 0x1)2245 break;2246 init_fw_cb->ipv6_hop_limit = iface_param->value[0];2247 break;2248 case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO:2249 if (iface_param->iface_num & 0x1)2250 break;2251 init_fw_cb->ipv6_nd_reach_time =2252 cpu_to_le32(*(uint32_t *)iface_param->value);2253 break;2254 case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME:2255 if (iface_param->iface_num & 0x1)2256 break;2257 init_fw_cb->ipv6_nd_rexmit_timer =2258 cpu_to_le32(*(uint32_t *)iface_param->value);2259 break;2260 case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO:2261 if (iface_param->iface_num & 0x1)2262 break;2263 init_fw_cb->ipv6_nd_stale_timeout =2264 cpu_to_le32(*(uint32_t *)iface_param->value);2265 break;2266 case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT:2267 if (iface_param->iface_num & 0x1)2268 break;2269 init_fw_cb->ipv6_dup_addr_detect_count = iface_param->value[0];2270 break;2271 case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU:2272 if (iface_param->iface_num & 0x1)2273 break;2274 init_fw_cb->ipv6_gw_advrt_mtu =2275 cpu_to_le32(*(uint32_t *)iface_param->value);2276 break;2277 default:2278 ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n",2279 iface_param->param);2280 break;2281 }2282}2283 2284static void qla4xxx_set_ipv4(struct scsi_qla_host *ha,2285 struct iscsi_iface_param_info *iface_param,2286 struct addr_ctrl_blk *init_fw_cb)2287{2288 switch (iface_param->param) {2289 case ISCSI_NET_PARAM_IPV4_ADDR:2290 memcpy(init_fw_cb->ipv4_addr, iface_param->value,2291 sizeof(init_fw_cb->ipv4_addr));2292 break;2293 case ISCSI_NET_PARAM_IPV4_SUBNET:2294 memcpy(init_fw_cb->ipv4_subnet, iface_param->value,2295 sizeof(init_fw_cb->ipv4_subnet));2296 break;2297 case ISCSI_NET_PARAM_IPV4_GW:2298 memcpy(init_fw_cb->ipv4_gw_addr, iface_param->value,2299 sizeof(init_fw_cb->ipv4_gw_addr));2300 break;2301 case ISCSI_NET_PARAM_IPV4_BOOTPROTO:2302 if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)2303 init_fw_cb->ipv4_tcp_opts |=2304 cpu_to_le16(TCPOPT_DHCP_ENABLE);2305 else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)2306 init_fw_cb->ipv4_tcp_opts &=2307 cpu_to_le16(~TCPOPT_DHCP_ENABLE);2308 else2309 ql4_printk(KERN_ERR, ha, "Invalid IPv4 bootproto\n");2310 break;2311 case ISCSI_NET_PARAM_IFACE_ENABLE:2312 if (iface_param->value[0] == ISCSI_IFACE_ENABLE) {2313 init_fw_cb->ipv4_ip_opts |=2314 cpu_to_le16(IPOPT_IPV4_PROTOCOL_ENABLE);2315 qla4xxx_create_ipv4_iface(ha);2316 } else {2317 init_fw_cb->ipv4_ip_opts &=2318 cpu_to_le16(~IPOPT_IPV4_PROTOCOL_ENABLE &2319 0xFFFF);2320 qla4xxx_destroy_ipv4_iface(ha);2321 }2322 break;2323 case ISCSI_NET_PARAM_VLAN_TAG:2324 if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))2325 break;2326 init_fw_cb->ipv4_vlan_tag =2327 cpu_to_be16(*(uint16_t *)iface_param->value);2328 break;2329 case ISCSI_NET_PARAM_VLAN_ENABLED:2330 if (iface_param->value[0] == ISCSI_VLAN_ENABLE)2331 init_fw_cb->ipv4_ip_opts |=2332 cpu_to_le16(IPOPT_VLAN_TAGGING_ENABLE);2333 else2334 init_fw_cb->ipv4_ip_opts &=2335 cpu_to_le16(~IPOPT_VLAN_TAGGING_ENABLE);2336 break;2337 case ISCSI_NET_PARAM_MTU:2338 init_fw_cb->eth_mtu_size =2339 cpu_to_le16(*(uint16_t *)iface_param->value);2340 break;2341 case ISCSI_NET_PARAM_PORT:2342 init_fw_cb->ipv4_port =2343 cpu_to_le16(*(uint16_t *)iface_param->value);2344 break;2345 case ISCSI_NET_PARAM_DELAYED_ACK_EN:2346 if (iface_param->iface_num & 0x1)2347 break;2348 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2349 init_fw_cb->ipv4_tcp_opts |=2350 cpu_to_le16(TCPOPT_DELAYED_ACK_DISABLE);2351 else2352 init_fw_cb->ipv4_tcp_opts &=2353 cpu_to_le16(~TCPOPT_DELAYED_ACK_DISABLE &2354 0xFFFF);2355 break;2356 case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE:2357 if (iface_param->iface_num & 0x1)2358 break;2359 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2360 init_fw_cb->ipv4_tcp_opts |=2361 cpu_to_le16(TCPOPT_NAGLE_ALGO_DISABLE);2362 else2363 init_fw_cb->ipv4_tcp_opts &=2364 cpu_to_le16(~TCPOPT_NAGLE_ALGO_DISABLE);2365 break;2366 case ISCSI_NET_PARAM_TCP_WSF_DISABLE:2367 if (iface_param->iface_num & 0x1)2368 break;2369 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2370 init_fw_cb->ipv4_tcp_opts |=2371 cpu_to_le16(TCPOPT_WINDOW_SCALE_DISABLE);2372 else2373 init_fw_cb->ipv4_tcp_opts &=2374 cpu_to_le16(~TCPOPT_WINDOW_SCALE_DISABLE);2375 break;2376 case ISCSI_NET_PARAM_TCP_WSF:2377 if (iface_param->iface_num & 0x1)2378 break;2379 init_fw_cb->ipv4_tcp_wsf = iface_param->value[0];2380 break;2381 case ISCSI_NET_PARAM_TCP_TIMER_SCALE:2382 if (iface_param->iface_num & 0x1)2383 break;2384 init_fw_cb->ipv4_tcp_opts &= cpu_to_le16(~TCPOPT_TIMER_SCALE);2385 init_fw_cb->ipv4_tcp_opts |=2386 cpu_to_le16((iface_param->value[0] << 1) &2387 TCPOPT_TIMER_SCALE);2388 break;2389 case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN:2390 if (iface_param->iface_num & 0x1)2391 break;2392 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2393 init_fw_cb->ipv4_tcp_opts |=2394 cpu_to_le16(TCPOPT_TIMESTAMP_ENABLE);2395 else2396 init_fw_cb->ipv4_tcp_opts &=2397 cpu_to_le16(~TCPOPT_TIMESTAMP_ENABLE);2398 break;2399 case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN:2400 if (iface_param->iface_num & 0x1)2401 break;2402 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2403 init_fw_cb->ipv4_tcp_opts |=2404 cpu_to_le16(TCPOPT_DNS_SERVER_IP_EN);2405 else2406 init_fw_cb->ipv4_tcp_opts &=2407 cpu_to_le16(~TCPOPT_DNS_SERVER_IP_EN);2408 break;2409 case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN:2410 if (iface_param->iface_num & 0x1)2411 break;2412 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2413 init_fw_cb->ipv4_tcp_opts |=2414 cpu_to_le16(TCPOPT_SLP_DA_INFO_EN);2415 else2416 init_fw_cb->ipv4_tcp_opts &=2417 cpu_to_le16(~TCPOPT_SLP_DA_INFO_EN);2418 break;2419 case ISCSI_NET_PARAM_IPV4_TOS_EN:2420 if (iface_param->iface_num & 0x1)2421 break;2422 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2423 init_fw_cb->ipv4_ip_opts |=2424 cpu_to_le16(IPOPT_IPV4_TOS_EN);2425 else2426 init_fw_cb->ipv4_ip_opts &=2427 cpu_to_le16(~IPOPT_IPV4_TOS_EN);2428 break;2429 case ISCSI_NET_PARAM_IPV4_TOS:2430 if (iface_param->iface_num & 0x1)2431 break;2432 init_fw_cb->ipv4_tos = iface_param->value[0];2433 break;2434 case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN:2435 if (iface_param->iface_num & 0x1)2436 break;2437 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2438 init_fw_cb->ipv4_ip_opts |=2439 cpu_to_le16(IPOPT_GRAT_ARP_EN);2440 else2441 init_fw_cb->ipv4_ip_opts &=2442 cpu_to_le16(~IPOPT_GRAT_ARP_EN);2443 break;2444 case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN:2445 if (iface_param->iface_num & 0x1)2446 break;2447 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2448 init_fw_cb->ipv4_ip_opts |=2449 cpu_to_le16(IPOPT_ALT_CID_EN);2450 else2451 init_fw_cb->ipv4_ip_opts &=2452 cpu_to_le16(~IPOPT_ALT_CID_EN);2453 break;2454 case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID:2455 if (iface_param->iface_num & 0x1)2456 break;2457 memcpy(init_fw_cb->ipv4_dhcp_alt_cid, iface_param->value,2458 (sizeof(init_fw_cb->ipv4_dhcp_alt_cid) - 1));2459 init_fw_cb->ipv4_dhcp_alt_cid_len =2460 strlen(init_fw_cb->ipv4_dhcp_alt_cid);2461 break;2462 case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN:2463 if (iface_param->iface_num & 0x1)2464 break;2465 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2466 init_fw_cb->ipv4_ip_opts |=2467 cpu_to_le16(IPOPT_REQ_VID_EN);2468 else2469 init_fw_cb->ipv4_ip_opts &=2470 cpu_to_le16(~IPOPT_REQ_VID_EN);2471 break;2472 case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN:2473 if (iface_param->iface_num & 0x1)2474 break;2475 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2476 init_fw_cb->ipv4_ip_opts |=2477 cpu_to_le16(IPOPT_USE_VID_EN);2478 else2479 init_fw_cb->ipv4_ip_opts &=2480 cpu_to_le16(~IPOPT_USE_VID_EN);2481 break;2482 case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID:2483 if (iface_param->iface_num & 0x1)2484 break;2485 memcpy(init_fw_cb->ipv4_dhcp_vid, iface_param->value,2486 (sizeof(init_fw_cb->ipv4_dhcp_vid) - 1));2487 init_fw_cb->ipv4_dhcp_vid_len =2488 strlen(init_fw_cb->ipv4_dhcp_vid);2489 break;2490 case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN:2491 if (iface_param->iface_num & 0x1)2492 break;2493 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2494 init_fw_cb->ipv4_ip_opts |=2495 cpu_to_le16(IPOPT_LEARN_IQN_EN);2496 else2497 init_fw_cb->ipv4_ip_opts &=2498 cpu_to_le16(~IPOPT_LEARN_IQN_EN);2499 break;2500 case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE:2501 if (iface_param->iface_num & 0x1)2502 break;2503 if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE)2504 init_fw_cb->ipv4_ip_opts |=2505 cpu_to_le16(IPOPT_FRAGMENTATION_DISABLE);2506 else2507 init_fw_cb->ipv4_ip_opts &=2508 cpu_to_le16(~IPOPT_FRAGMENTATION_DISABLE);2509 break;2510 case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN:2511 if (iface_param->iface_num & 0x1)2512 break;2513 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2514 init_fw_cb->ipv4_ip_opts |=2515 cpu_to_le16(IPOPT_IN_FORWARD_EN);2516 else2517 init_fw_cb->ipv4_ip_opts &=2518 cpu_to_le16(~IPOPT_IN_FORWARD_EN);2519 break;2520 case ISCSI_NET_PARAM_REDIRECT_EN:2521 if (iface_param->iface_num & 0x1)2522 break;2523 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2524 init_fw_cb->ipv4_ip_opts |=2525 cpu_to_le16(IPOPT_ARP_REDIRECT_EN);2526 else2527 init_fw_cb->ipv4_ip_opts &=2528 cpu_to_le16(~IPOPT_ARP_REDIRECT_EN);2529 break;2530 case ISCSI_NET_PARAM_IPV4_TTL:2531 if (iface_param->iface_num & 0x1)2532 break;2533 init_fw_cb->ipv4_ttl = iface_param->value[0];2534 break;2535 default:2536 ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n",2537 iface_param->param);2538 break;2539 }2540}2541 2542static void qla4xxx_set_iscsi_param(struct scsi_qla_host *ha,2543 struct iscsi_iface_param_info *iface_param,2544 struct addr_ctrl_blk *init_fw_cb)2545{2546 switch (iface_param->param) {2547 case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO:2548 if (iface_param->iface_num & 0x1)2549 break;2550 init_fw_cb->def_timeout =2551 cpu_to_le16(*(uint16_t *)iface_param->value);2552 break;2553 case ISCSI_IFACE_PARAM_HDRDGST_EN:2554 if (iface_param->iface_num & 0x1)2555 break;2556 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2557 init_fw_cb->iscsi_opts |=2558 cpu_to_le16(ISCSIOPTS_HEADER_DIGEST_EN);2559 else2560 init_fw_cb->iscsi_opts &=2561 cpu_to_le16(~ISCSIOPTS_HEADER_DIGEST_EN);2562 break;2563 case ISCSI_IFACE_PARAM_DATADGST_EN:2564 if (iface_param->iface_num & 0x1)2565 break;2566 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2567 init_fw_cb->iscsi_opts |=2568 cpu_to_le16(ISCSIOPTS_DATA_DIGEST_EN);2569 else2570 init_fw_cb->iscsi_opts &=2571 cpu_to_le16(~ISCSIOPTS_DATA_DIGEST_EN);2572 break;2573 case ISCSI_IFACE_PARAM_IMM_DATA_EN:2574 if (iface_param->iface_num & 0x1)2575 break;2576 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2577 init_fw_cb->iscsi_opts |=2578 cpu_to_le16(ISCSIOPTS_IMMEDIATE_DATA_EN);2579 else2580 init_fw_cb->iscsi_opts &=2581 cpu_to_le16(~ISCSIOPTS_IMMEDIATE_DATA_EN);2582 break;2583 case ISCSI_IFACE_PARAM_INITIAL_R2T_EN:2584 if (iface_param->iface_num & 0x1)2585 break;2586 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2587 init_fw_cb->iscsi_opts |=2588 cpu_to_le16(ISCSIOPTS_INITIAL_R2T_EN);2589 else2590 init_fw_cb->iscsi_opts &=2591 cpu_to_le16(~ISCSIOPTS_INITIAL_R2T_EN);2592 break;2593 case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN:2594 if (iface_param->iface_num & 0x1)2595 break;2596 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2597 init_fw_cb->iscsi_opts |=2598 cpu_to_le16(ISCSIOPTS_DATA_SEQ_INORDER_EN);2599 else2600 init_fw_cb->iscsi_opts &=2601 cpu_to_le16(~ISCSIOPTS_DATA_SEQ_INORDER_EN);2602 break;2603 case ISCSI_IFACE_PARAM_PDU_INORDER_EN:2604 if (iface_param->iface_num & 0x1)2605 break;2606 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2607 init_fw_cb->iscsi_opts |=2608 cpu_to_le16(ISCSIOPTS_DATA_PDU_INORDER_EN);2609 else2610 init_fw_cb->iscsi_opts &=2611 cpu_to_le16(~ISCSIOPTS_DATA_PDU_INORDER_EN);2612 break;2613 case ISCSI_IFACE_PARAM_ERL:2614 if (iface_param->iface_num & 0x1)2615 break;2616 init_fw_cb->iscsi_opts &= cpu_to_le16(~ISCSIOPTS_ERL);2617 init_fw_cb->iscsi_opts |= cpu_to_le16(iface_param->value[0] &2618 ISCSIOPTS_ERL);2619 break;2620 case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH:2621 if (iface_param->iface_num & 0x1)2622 break;2623 init_fw_cb->iscsi_max_pdu_size =2624 cpu_to_le32(*(uint32_t *)iface_param->value) /2625 BYTE_UNITS;2626 break;2627 case ISCSI_IFACE_PARAM_FIRST_BURST:2628 if (iface_param->iface_num & 0x1)2629 break;2630 init_fw_cb->iscsi_fburst_len =2631 cpu_to_le32(*(uint32_t *)iface_param->value) /2632 BYTE_UNITS;2633 break;2634 case ISCSI_IFACE_PARAM_MAX_R2T:2635 if (iface_param->iface_num & 0x1)2636 break;2637 init_fw_cb->iscsi_max_outstnd_r2t =2638 cpu_to_le16(*(uint16_t *)iface_param->value);2639 break;2640 case ISCSI_IFACE_PARAM_MAX_BURST:2641 if (iface_param->iface_num & 0x1)2642 break;2643 init_fw_cb->iscsi_max_burst_len =2644 cpu_to_le32(*(uint32_t *)iface_param->value) /2645 BYTE_UNITS;2646 break;2647 case ISCSI_IFACE_PARAM_CHAP_AUTH_EN:2648 if (iface_param->iface_num & 0x1)2649 break;2650 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2651 init_fw_cb->iscsi_opts |=2652 cpu_to_le16(ISCSIOPTS_CHAP_AUTH_EN);2653 else2654 init_fw_cb->iscsi_opts &=2655 cpu_to_le16(~ISCSIOPTS_CHAP_AUTH_EN);2656 break;2657 case ISCSI_IFACE_PARAM_BIDI_CHAP_EN:2658 if (iface_param->iface_num & 0x1)2659 break;2660 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2661 init_fw_cb->iscsi_opts |=2662 cpu_to_le16(ISCSIOPTS_BIDI_CHAP_EN);2663 else2664 init_fw_cb->iscsi_opts &=2665 cpu_to_le16(~ISCSIOPTS_BIDI_CHAP_EN);2666 break;2667 case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL:2668 if (iface_param->iface_num & 0x1)2669 break;2670 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2671 init_fw_cb->iscsi_opts |=2672 cpu_to_le16(ISCSIOPTS_DISCOVERY_AUTH_EN);2673 else2674 init_fw_cb->iscsi_opts &=2675 cpu_to_le16(~ISCSIOPTS_DISCOVERY_AUTH_EN);2676 break;2677 case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN:2678 if (iface_param->iface_num & 0x1)2679 break;2680 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2681 init_fw_cb->iscsi_opts |=2682 cpu_to_le16(ISCSIOPTS_DISCOVERY_LOGOUT_EN);2683 else2684 init_fw_cb->iscsi_opts &=2685 cpu_to_le16(~ISCSIOPTS_DISCOVERY_LOGOUT_EN);2686 break;2687 case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN:2688 if (iface_param->iface_num & 0x1)2689 break;2690 if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE)2691 init_fw_cb->iscsi_opts |=2692 cpu_to_le16(ISCSIOPTS_STRICT_LOGIN_COMP_EN);2693 else2694 init_fw_cb->iscsi_opts &=2695 cpu_to_le16(~ISCSIOPTS_STRICT_LOGIN_COMP_EN);2696 break;2697 default:2698 ql4_printk(KERN_ERR, ha, "Unknown iscsi param = %d\n",2699 iface_param->param);2700 break;2701 }2702}2703 2704static void2705qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb)2706{2707 struct addr_ctrl_blk_def *acb;2708 acb = (struct addr_ctrl_blk_def *)init_fw_cb;2709 memset(acb->reserved1, 0, sizeof(acb->reserved1));2710 memset(acb->reserved2, 0, sizeof(acb->reserved2));2711 memset(acb->reserved3, 0, sizeof(acb->reserved3));2712 memset(acb->reserved4, 0, sizeof(acb->reserved4));2713 memset(acb->reserved5, 0, sizeof(acb->reserved5));2714 memset(acb->reserved6, 0, sizeof(acb->reserved6));2715 memset(acb->reserved7, 0, sizeof(acb->reserved7));2716 memset(acb->reserved8, 0, sizeof(acb->reserved8));2717 memset(acb->reserved9, 0, sizeof(acb->reserved9));2718 memset(acb->reserved10, 0, sizeof(acb->reserved10));2719 memset(acb->reserved11, 0, sizeof(acb->reserved11));2720 memset(acb->reserved12, 0, sizeof(acb->reserved12));2721 memset(acb->reserved13, 0, sizeof(acb->reserved13));2722 memset(acb->reserved14, 0, sizeof(acb->reserved14));2723 memset(acb->reserved15, 0, sizeof(acb->reserved15));2724}2725 2726static int2727qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)2728{2729 struct scsi_qla_host *ha = to_qla_host(shost);2730 int rval = 0;2731 struct iscsi_iface_param_info *iface_param = NULL;2732 struct addr_ctrl_blk *init_fw_cb = NULL;2733 dma_addr_t init_fw_cb_dma;2734 uint32_t mbox_cmd[MBOX_REG_COUNT];2735 uint32_t mbox_sts[MBOX_REG_COUNT];2736 uint32_t rem = len;2737 struct nlattr *attr;2738 2739 init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,2740 sizeof(struct addr_ctrl_blk),2741 &init_fw_cb_dma, GFP_KERNEL);2742 if (!init_fw_cb) {2743 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",2744 __func__);2745 return -ENOMEM;2746 }2747 2748 memset(&mbox_cmd, 0, sizeof(mbox_cmd));2749 memset(&mbox_sts, 0, sizeof(mbox_sts));2750 2751 if (qla4xxx_get_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)) {2752 ql4_printk(KERN_ERR, ha, "%s: get ifcb failed\n", __func__);2753 rval = -EIO;2754 goto exit_init_fw_cb;2755 }2756 2757 nla_for_each_attr(attr, data, len, rem) {2758 if (nla_len(attr) < sizeof(*iface_param)) {2759 rval = -EINVAL;2760 goto exit_init_fw_cb;2761 }2762 2763 iface_param = nla_data(attr);2764 2765 if (iface_param->param_type == ISCSI_NET_PARAM) {2766 switch (iface_param->iface_type) {2767 case ISCSI_IFACE_TYPE_IPV4:2768 switch (iface_param->iface_num) {2769 case 0:2770 qla4xxx_set_ipv4(ha, iface_param,2771 init_fw_cb);2772 break;2773 default:2774 /* Cannot have more than one IPv4 interface */2775 ql4_printk(KERN_ERR, ha,2776 "Invalid IPv4 iface number = %d\n",2777 iface_param->iface_num);2778 break;2779 }2780 break;2781 case ISCSI_IFACE_TYPE_IPV6:2782 switch (iface_param->iface_num) {2783 case 0:2784 case 1:2785 qla4xxx_set_ipv6(ha, iface_param,2786 init_fw_cb);2787 break;2788 default:2789 /* Cannot have more than two IPv6 interface */2790 ql4_printk(KERN_ERR, ha,2791 "Invalid IPv6 iface number = %d\n",2792 iface_param->iface_num);2793 break;2794 }2795 break;2796 default:2797 ql4_printk(KERN_ERR, ha,2798 "Invalid iface type\n");2799 break;2800 }2801 } else if (iface_param->param_type == ISCSI_IFACE_PARAM) {2802 qla4xxx_set_iscsi_param(ha, iface_param,2803 init_fw_cb);2804 } else {2805 continue;2806 }2807 }2808 2809 init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);2810 2811 rval = qla4xxx_set_flash(ha, init_fw_cb_dma, FLASH_SEGMENT_IFCB,2812 sizeof(struct addr_ctrl_blk),2813 FLASH_OPT_RMW_COMMIT);2814 if (rval != QLA_SUCCESS) {2815 ql4_printk(KERN_ERR, ha, "%s: set flash mbx failed\n",2816 __func__);2817 rval = -EIO;2818 goto exit_init_fw_cb;2819 }2820 2821 rval = qla4xxx_disable_acb(ha);2822 if (rval != QLA_SUCCESS) {2823 ql4_printk(KERN_ERR, ha, "%s: disable acb mbx failed\n",2824 __func__);2825 rval = -EIO;2826 goto exit_init_fw_cb;2827 }2828 2829 wait_for_completion_timeout(&ha->disable_acb_comp,2830 DISABLE_ACB_TOV * HZ);2831 2832 qla4xxx_initcb_to_acb(init_fw_cb);2833 2834 rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma);2835 if (rval != QLA_SUCCESS) {2836 ql4_printk(KERN_ERR, ha, "%s: set acb mbx failed\n",2837 __func__);2838 rval = -EIO;2839 goto exit_init_fw_cb;2840 }2841 2842 memset(init_fw_cb, 0, sizeof(struct addr_ctrl_blk));2843 qla4xxx_update_local_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb,2844 init_fw_cb_dma);2845 2846exit_init_fw_cb:2847 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk),2848 init_fw_cb, init_fw_cb_dma);2849 2850 return rval;2851}2852 2853static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,2854 enum iscsi_param param, char *buf)2855{2856 struct iscsi_session *sess = cls_sess->dd_data;2857 struct ddb_entry *ddb_entry = sess->dd_data;2858 struct scsi_qla_host *ha = ddb_entry->ha;2859 struct iscsi_cls_conn *cls_conn = ddb_entry->conn;2860 struct ql4_chap_table chap_tbl;2861 int rval, len;2862 uint16_t idx;2863 2864 memset(&chap_tbl, 0, sizeof(chap_tbl));2865 switch (param) {2866 case ISCSI_PARAM_CHAP_IN_IDX:2867 rval = qla4xxx_get_chap_index(ha, sess->username_in,2868 sess->password_in, BIDI_CHAP,2869 &idx);2870 if (rval)2871 len = sprintf(buf, "\n");2872 else2873 len = sprintf(buf, "%hu\n", idx);2874 break;2875 case ISCSI_PARAM_CHAP_OUT_IDX:2876 if (ddb_entry->ddb_type == FLASH_DDB) {2877 if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) {2878 idx = ddb_entry->chap_tbl_idx;2879 rval = QLA_SUCCESS;2880 } else {2881 rval = QLA_ERROR;2882 }2883 } else {2884 rval = qla4xxx_get_chap_index(ha, sess->username,2885 sess->password,2886 LOCAL_CHAP, &idx);2887 }2888 if (rval)2889 len = sprintf(buf, "\n");2890 else2891 len = sprintf(buf, "%hu\n", idx);2892 break;2893 case ISCSI_PARAM_USERNAME:2894 case ISCSI_PARAM_PASSWORD:2895 /* First, populate session username and password for FLASH DDB,2896 * if not already done. This happens when session login fails2897 * for a FLASH DDB.2898 */2899 if (ddb_entry->ddb_type == FLASH_DDB &&2900 ddb_entry->chap_tbl_idx != INVALID_ENTRY &&2901 !sess->username && !sess->password) {2902 idx = ddb_entry->chap_tbl_idx;2903 rval = qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name,2904 chap_tbl.secret,2905 idx);2906 if (!rval) {2907 iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME,2908 (char *)chap_tbl.name,2909 strlen((char *)chap_tbl.name));2910 iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD,2911 (char *)chap_tbl.secret,2912 chap_tbl.secret_len);2913 }2914 }2915 fallthrough;2916 default:2917 return iscsi_session_get_param(cls_sess, param, buf);2918 }2919 2920 return len;2921}2922 2923static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,2924 enum iscsi_param param, char *buf)2925{2926 struct iscsi_conn *conn;2927 struct qla_conn *qla_conn;2928 struct sockaddr *dst_addr;2929 2930 conn = cls_conn->dd_data;2931 qla_conn = conn->dd_data;2932 dst_addr = (struct sockaddr *)&qla_conn->qla_ep->dst_addr;2933 2934 switch (param) {2935 case ISCSI_PARAM_CONN_PORT:2936 case ISCSI_PARAM_CONN_ADDRESS:2937 return iscsi_conn_get_addr_param((struct sockaddr_storage *)2938 dst_addr, param, buf);2939 default:2940 return iscsi_conn_get_param(cls_conn, param, buf);2941 }2942}2943 2944int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index)2945{2946 uint32_t mbx_sts = 0;2947 uint16_t tmp_ddb_index;2948 int ret;2949 2950get_ddb_index:2951 tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);2952 2953 if (tmp_ddb_index >= MAX_DDB_ENTRIES) {2954 DEBUG2(ql4_printk(KERN_INFO, ha,2955 "Free DDB index not available\n"));2956 ret = QLA_ERROR;2957 goto exit_get_ddb_index;2958 }2959 2960 if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map))2961 goto get_ddb_index;2962 2963 DEBUG2(ql4_printk(KERN_INFO, ha,2964 "Found a free DDB index at %d\n", tmp_ddb_index));2965 ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts);2966 if (ret == QLA_ERROR) {2967 if (mbx_sts == MBOX_STS_COMMAND_ERROR) {2968 ql4_printk(KERN_INFO, ha,2969 "DDB index = %d not available trying next\n",2970 tmp_ddb_index);2971 goto get_ddb_index;2972 }2973 DEBUG2(ql4_printk(KERN_INFO, ha,2974 "Free FW DDB not available\n"));2975 }2976 2977 *ddb_index = tmp_ddb_index;2978 2979exit_get_ddb_index:2980 return ret;2981}2982 2983static int qla4xxx_match_ipaddress(struct scsi_qla_host *ha,2984 struct ddb_entry *ddb_entry,2985 char *existing_ipaddr,2986 char *user_ipaddr)2987{2988 uint8_t dst_ipaddr[IPv6_ADDR_LEN];2989 char formatted_ipaddr[DDB_IPADDR_LEN];2990 int status = QLA_SUCCESS, ret = 0;2991 2992 if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) {2993 ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,2994 '\0', NULL);2995 if (ret == 0) {2996 status = QLA_ERROR;2997 goto out_match;2998 }2999 ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr);3000 } else {3001 ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr,3002 '\0', NULL);3003 if (ret == 0) {3004 status = QLA_ERROR;3005 goto out_match;3006 }3007 ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr);3008 }3009 3010 if (strcmp(existing_ipaddr, formatted_ipaddr))3011 status = QLA_ERROR;3012 3013out_match:3014 return status;3015}3016 3017static int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha,3018 struct iscsi_cls_conn *cls_conn)3019{3020 int idx = 0, max_ddbs, rval;3021 struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);3022 struct iscsi_session *sess, *existing_sess;3023 struct iscsi_conn *conn, *existing_conn;3024 struct ddb_entry *ddb_entry;3025 3026 sess = cls_sess->dd_data;3027 conn = cls_conn->dd_data;3028 3029 if (sess->targetname == NULL ||3030 conn->persistent_address == NULL ||3031 conn->persistent_port == 0)3032 return QLA_ERROR;3033 3034 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :3035 MAX_DEV_DB_ENTRIES;3036 3037 for (idx = 0; idx < max_ddbs; idx++) {3038 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);3039 if (ddb_entry == NULL)3040 continue;3041 3042 if (ddb_entry->ddb_type != FLASH_DDB)3043 continue;3044 3045 existing_sess = ddb_entry->sess->dd_data;3046 existing_conn = ddb_entry->conn->dd_data;3047 3048 if (existing_sess->targetname == NULL ||3049 existing_conn->persistent_address == NULL ||3050 existing_conn->persistent_port == 0)3051 continue;3052 3053 DEBUG2(ql4_printk(KERN_INFO, ha,3054 "IQN = %s User IQN = %s\n",3055 existing_sess->targetname,3056 sess->targetname));3057 3058 DEBUG2(ql4_printk(KERN_INFO, ha,3059 "IP = %s User IP = %s\n",3060 existing_conn->persistent_address,3061 conn->persistent_address));3062 3063 DEBUG2(ql4_printk(KERN_INFO, ha,3064 "Port = %d User Port = %d\n",3065 existing_conn->persistent_port,3066 conn->persistent_port));3067 3068 if (strcmp(existing_sess->targetname, sess->targetname))3069 continue;3070 rval = qla4xxx_match_ipaddress(ha, ddb_entry,3071 existing_conn->persistent_address,3072 conn->persistent_address);3073 if (rval == QLA_ERROR)3074 continue;3075 if (existing_conn->persistent_port != conn->persistent_port)3076 continue;3077 break;3078 }3079 3080 if (idx == max_ddbs)3081 return QLA_ERROR;3082 3083 DEBUG2(ql4_printk(KERN_INFO, ha,3084 "Match found in fwdb sessions\n"));3085 return QLA_SUCCESS;3086}3087 3088static struct iscsi_cls_session *3089qla4xxx_session_create(struct iscsi_endpoint *ep,3090 uint16_t cmds_max, uint16_t qdepth,3091 uint32_t initial_cmdsn)3092{3093 struct iscsi_cls_session *cls_sess;3094 struct scsi_qla_host *ha;3095 struct qla_endpoint *qla_ep;3096 struct ddb_entry *ddb_entry;3097 uint16_t ddb_index;3098 struct iscsi_session *sess;3099 int ret;3100 3101 if (!ep) {3102 printk(KERN_ERR "qla4xxx: missing ep.\n");3103 return NULL;3104 }3105 3106 qla_ep = ep->dd_data;3107 ha = to_qla_host(qla_ep->host);3108 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__,3109 ha->host_no));3110 3111 ret = qla4xxx_get_ddb_index(ha, &ddb_index);3112 if (ret == QLA_ERROR)3113 return NULL;3114 3115 cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host,3116 cmds_max, sizeof(struct ddb_entry),3117 sizeof(struct ql4_task_data),3118 initial_cmdsn, ddb_index);3119 if (!cls_sess)3120 return NULL;3121 3122 sess = cls_sess->dd_data;3123 ddb_entry = sess->dd_data;3124 ddb_entry->fw_ddb_index = ddb_index;3125 ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;3126 ddb_entry->ha = ha;3127 ddb_entry->sess = cls_sess;3128 ddb_entry->unblock_sess = qla4xxx_unblock_ddb;3129 ddb_entry->ddb_change = qla4xxx_ddb_change;3130 clear_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags);3131 cls_sess->recovery_tmo = ql4xsess_recovery_tmo;3132 ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;3133 ha->tot_ddbs++;3134 3135 return cls_sess;3136}3137 3138static void qla4xxx_session_destroy(struct iscsi_cls_session *cls_sess)3139{3140 struct iscsi_session *sess;3141 struct ddb_entry *ddb_entry;3142 struct scsi_qla_host *ha;3143 unsigned long flags, wtime;3144 struct dev_db_entry *fw_ddb_entry = NULL;3145 dma_addr_t fw_ddb_entry_dma;3146 uint32_t ddb_state;3147 int ret;3148 3149 sess = cls_sess->dd_data;3150 ddb_entry = sess->dd_data;3151 ha = ddb_entry->ha;3152 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: host: %ld\n", __func__,3153 ha->host_no));3154 3155 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3156 &fw_ddb_entry_dma, GFP_KERNEL);3157 if (!fw_ddb_entry) {3158 ql4_printk(KERN_ERR, ha,3159 "%s: Unable to allocate dma buffer\n", __func__);3160 goto destroy_session;3161 }3162 3163 wtime = jiffies + (HZ * LOGOUT_TOV);3164 do {3165 ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index,3166 fw_ddb_entry, fw_ddb_entry_dma,3167 NULL, NULL, &ddb_state, NULL,3168 NULL, NULL);3169 if (ret == QLA_ERROR)3170 goto destroy_session;3171 3172 if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) ||3173 (ddb_state == DDB_DS_SESSION_FAILED))3174 goto destroy_session;3175 3176 schedule_timeout_uninterruptible(HZ);3177 } while ((time_after(wtime, jiffies)));3178 3179destroy_session:3180 qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);3181 if (test_and_clear_bit(DDB_CONN_CLOSE_FAILURE, &ddb_entry->flags))3182 clear_bit(ddb_entry->fw_ddb_index, ha->ddb_idx_map);3183 spin_lock_irqsave(&ha->hardware_lock, flags);3184 qla4xxx_free_ddb(ha, ddb_entry);3185 spin_unlock_irqrestore(&ha->hardware_lock, flags);3186 3187 iscsi_session_teardown(cls_sess);3188 3189 if (fw_ddb_entry)3190 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3191 fw_ddb_entry, fw_ddb_entry_dma);3192}3193 3194static struct iscsi_cls_conn *3195qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx)3196{3197 struct iscsi_cls_conn *cls_conn;3198 struct iscsi_session *sess;3199 struct ddb_entry *ddb_entry;3200 struct scsi_qla_host *ha;3201 3202 cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn),3203 conn_idx);3204 if (!cls_conn) {3205 pr_info("%s: Can not create connection for conn_idx = %u\n",3206 __func__, conn_idx);3207 return NULL;3208 }3209 3210 sess = cls_sess->dd_data;3211 ddb_entry = sess->dd_data;3212 ddb_entry->conn = cls_conn;3213 3214 ha = ddb_entry->ha;3215 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: conn_idx = %u\n", __func__,3216 conn_idx));3217 return cls_conn;3218}3219 3220static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,3221 struct iscsi_cls_conn *cls_conn,3222 uint64_t transport_fd, int is_leading)3223{3224 struct iscsi_conn *conn;3225 struct qla_conn *qla_conn;3226 struct iscsi_endpoint *ep;3227 struct ddb_entry *ddb_entry;3228 struct scsi_qla_host *ha;3229 struct iscsi_session *sess;3230 3231 sess = cls_session->dd_data;3232 ddb_entry = sess->dd_data;3233 ha = ddb_entry->ha;3234 3235 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: sid = %d, cid = %d\n", __func__,3236 cls_session->sid, cls_conn->cid));3237 3238 if (iscsi_conn_bind(cls_session, cls_conn, is_leading))3239 return -EINVAL;3240 ep = iscsi_lookup_endpoint(transport_fd);3241 if (!ep)3242 return -EINVAL;3243 conn = cls_conn->dd_data;3244 qla_conn = conn->dd_data;3245 qla_conn->qla_ep = ep->dd_data;3246 iscsi_put_endpoint(ep);3247 return 0;3248}3249 3250static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn)3251{3252 struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);3253 struct iscsi_session *sess;3254 struct ddb_entry *ddb_entry;3255 struct scsi_qla_host *ha;3256 struct dev_db_entry *fw_ddb_entry = NULL;3257 dma_addr_t fw_ddb_entry_dma;3258 uint32_t mbx_sts = 0;3259 int ret = 0;3260 int status = QLA_SUCCESS;3261 3262 sess = cls_sess->dd_data;3263 ddb_entry = sess->dd_data;3264 ha = ddb_entry->ha;3265 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: sid = %d, cid = %d\n", __func__,3266 cls_sess->sid, cls_conn->cid));3267 3268 /* Check if we have matching FW DDB, if yes then do not3269 * login to this target. This could cause target to logout previous3270 * connection3271 */3272 ret = qla4xxx_match_fwdb_session(ha, cls_conn);3273 if (ret == QLA_SUCCESS) {3274 ql4_printk(KERN_INFO, ha,3275 "Session already exist in FW.\n");3276 ret = -EEXIST;3277 goto exit_conn_start;3278 }3279 3280 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3281 &fw_ddb_entry_dma, GFP_KERNEL);3282 if (!fw_ddb_entry) {3283 ql4_printk(KERN_ERR, ha,3284 "%s: Unable to allocate dma buffer\n", __func__);3285 ret = -ENOMEM;3286 goto exit_conn_start;3287 }3288 3289 ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts);3290 if (ret) {3291 /* If iscsid is stopped and started then no need to do3292 * set param again since ddb state will be already3293 * active and FW does not allow set ddb to an3294 * active session.3295 */3296 if (mbx_sts)3297 if (ddb_entry->fw_ddb_device_state ==3298 DDB_DS_SESSION_ACTIVE) {3299 ddb_entry->unblock_sess(ddb_entry->sess);3300 goto exit_set_param;3301 }3302 3303 ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n",3304 __func__, ddb_entry->fw_ddb_index);3305 goto exit_conn_start;3306 }3307 3308 status = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);3309 if (status == QLA_ERROR) {3310 ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,3311 sess->targetname);3312 ret = -EINVAL;3313 goto exit_conn_start;3314 }3315 3316 if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE)3317 ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;3318 3319 DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__,3320 ddb_entry->fw_ddb_device_state));3321 3322exit_set_param:3323 ret = 0;3324 3325exit_conn_start:3326 if (fw_ddb_entry)3327 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3328 fw_ddb_entry, fw_ddb_entry_dma);3329 return ret;3330}3331 3332static void qla4xxx_conn_destroy(struct iscsi_cls_conn *cls_conn)3333{3334 struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn);3335 struct iscsi_session *sess;3336 struct scsi_qla_host *ha;3337 struct ddb_entry *ddb_entry;3338 int options;3339 3340 sess = cls_sess->dd_data;3341 ddb_entry = sess->dd_data;3342 ha = ddb_entry->ha;3343 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: cid = %d\n", __func__,3344 cls_conn->cid));3345 3346 options = LOGOUT_OPTION_CLOSE_SESSION;3347 if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR)3348 ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);3349}3350 3351static void qla4xxx_task_work(struct work_struct *wdata)3352{3353 struct ql4_task_data *task_data;3354 struct scsi_qla_host *ha;3355 struct passthru_status *sts;3356 struct iscsi_task *task;3357 struct iscsi_hdr *hdr;3358 uint8_t *data;3359 uint32_t data_len;3360 struct iscsi_conn *conn;3361 int hdr_len;3362 itt_t itt;3363 3364 task_data = container_of(wdata, struct ql4_task_data, task_work);3365 ha = task_data->ha;3366 task = task_data->task;3367 sts = &task_data->sts;3368 hdr_len = sizeof(struct iscsi_hdr);3369 3370 DEBUG3(printk(KERN_INFO "Status returned\n"));3371 DEBUG3(qla4xxx_dump_buffer(sts, 64));3372 DEBUG3(printk(KERN_INFO "Response buffer"));3373 DEBUG3(qla4xxx_dump_buffer(task_data->resp_buffer, 64));3374 3375 conn = task->conn;3376 3377 switch (sts->completionStatus) {3378 case PASSTHRU_STATUS_COMPLETE:3379 hdr = (struct iscsi_hdr *)task_data->resp_buffer;3380 /* Assign back the itt in hdr, until we use the PREASSIGN_TAG */3381 itt = sts->handle;3382 hdr->itt = itt;3383 data = task_data->resp_buffer + hdr_len;3384 data_len = task_data->resp_len - hdr_len;3385 iscsi_complete_pdu(conn, hdr, data, data_len);3386 break;3387 default:3388 ql4_printk(KERN_ERR, ha, "Passthru failed status = 0x%x\n",3389 sts->completionStatus);3390 break;3391 }3392 return;3393}3394 3395static int qla4xxx_alloc_pdu(struct iscsi_task *task, uint8_t opcode)3396{3397 struct ql4_task_data *task_data;3398 struct iscsi_session *sess;3399 struct ddb_entry *ddb_entry;3400 struct scsi_qla_host *ha;3401 int hdr_len;3402 3403 sess = task->conn->session;3404 ddb_entry = sess->dd_data;3405 ha = ddb_entry->ha;3406 task_data = task->dd_data;3407 memset(task_data, 0, sizeof(struct ql4_task_data));3408 3409 if (task->sc) {3410 ql4_printk(KERN_INFO, ha,3411 "%s: SCSI Commands not implemented\n", __func__);3412 return -EINVAL;3413 }3414 3415 hdr_len = sizeof(struct iscsi_hdr);3416 task_data->ha = ha;3417 task_data->task = task;3418 3419 if (task->data_count) {3420 task_data->data_dma = dma_map_single(&ha->pdev->dev, task->data,3421 task->data_count,3422 DMA_TO_DEVICE);3423 }3424 3425 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",3426 __func__, task->conn->max_recv_dlength, hdr_len));3427 3428 task_data->resp_len = task->conn->max_recv_dlength + hdr_len;3429 task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev,3430 task_data->resp_len,3431 &task_data->resp_dma,3432 GFP_ATOMIC);3433 if (!task_data->resp_buffer)3434 goto exit_alloc_pdu;3435 3436 task_data->req_len = task->data_count + hdr_len;3437 task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev,3438 task_data->req_len,3439 &task_data->req_dma,3440 GFP_ATOMIC);3441 if (!task_data->req_buffer)3442 goto exit_alloc_pdu;3443 3444 task->hdr = task_data->req_buffer;3445 3446 INIT_WORK(&task_data->task_work, qla4xxx_task_work);3447 3448 return 0;3449 3450exit_alloc_pdu:3451 if (task_data->resp_buffer)3452 dma_free_coherent(&ha->pdev->dev, task_data->resp_len,3453 task_data->resp_buffer, task_data->resp_dma);3454 3455 if (task_data->req_buffer)3456 dma_free_coherent(&ha->pdev->dev, task_data->req_len,3457 task_data->req_buffer, task_data->req_dma);3458 return -ENOMEM;3459}3460 3461static void qla4xxx_task_cleanup(struct iscsi_task *task)3462{3463 struct ql4_task_data *task_data;3464 struct iscsi_session *sess;3465 struct ddb_entry *ddb_entry;3466 struct scsi_qla_host *ha;3467 int hdr_len;3468 3469 hdr_len = sizeof(struct iscsi_hdr);3470 sess = task->conn->session;3471 ddb_entry = sess->dd_data;3472 ha = ddb_entry->ha;3473 task_data = task->dd_data;3474 3475 if (task->data_count) {3476 dma_unmap_single(&ha->pdev->dev, task_data->data_dma,3477 task->data_count, DMA_TO_DEVICE);3478 }3479 3480 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",3481 __func__, task->conn->max_recv_dlength, hdr_len));3482 3483 dma_free_coherent(&ha->pdev->dev, task_data->resp_len,3484 task_data->resp_buffer, task_data->resp_dma);3485 dma_free_coherent(&ha->pdev->dev, task_data->req_len,3486 task_data->req_buffer, task_data->req_dma);3487 return;3488}3489 3490static int qla4xxx_task_xmit(struct iscsi_task *task)3491{3492 struct scsi_cmnd *sc = task->sc;3493 struct iscsi_session *sess = task->conn->session;3494 struct ddb_entry *ddb_entry = sess->dd_data;3495 struct scsi_qla_host *ha = ddb_entry->ha;3496 3497 if (!sc)3498 return qla4xxx_send_passthru0(task);3499 3500 ql4_printk(KERN_INFO, ha, "%s: scsi cmd xmit not implemented\n",3501 __func__);3502 return -ENOSYS;3503}3504 3505static int qla4xxx_copy_from_fwddb_param(struct iscsi_bus_flash_session *sess,3506 struct iscsi_bus_flash_conn *conn,3507 struct dev_db_entry *fw_ddb_entry)3508{3509 unsigned long options = 0;3510 int rc = 0;3511 3512 options = le16_to_cpu(fw_ddb_entry->options);3513 conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options);3514 if (test_bit(OPT_IPV6_DEVICE, &options)) {3515 rc = iscsi_switch_str_param(&sess->portal_type,3516 PORTAL_TYPE_IPV6);3517 if (rc)3518 goto exit_copy;3519 } else {3520 rc = iscsi_switch_str_param(&sess->portal_type,3521 PORTAL_TYPE_IPV4);3522 if (rc)3523 goto exit_copy;3524 }3525 3526 sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE,3527 &options);3528 sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options);3529 sess->entry_state = test_bit(OPT_ENTRY_STATE, &options);3530 3531 options = le16_to_cpu(fw_ddb_entry->iscsi_options);3532 conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options);3533 conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options);3534 sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options);3535 sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options);3536 sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER,3537 &options);3538 sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options);3539 sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options);3540 conn->snack_req_en = test_bit(ISCSIOPT_SNACK_REQ_EN, &options);3541 sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN,3542 &options);3543 sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options);3544 sess->discovery_auth_optional =3545 test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options);3546 if (test_bit(ISCSIOPT_ERL1, &options))3547 sess->erl |= BIT_1;3548 if (test_bit(ISCSIOPT_ERL0, &options))3549 sess->erl |= BIT_0;3550 3551 options = le16_to_cpu(fw_ddb_entry->tcp_options);3552 conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options);3553 conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options);3554 conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options);3555 if (test_bit(TCPOPT_TIMER_SCALE3, &options))3556 conn->tcp_timer_scale |= BIT_3;3557 if (test_bit(TCPOPT_TIMER_SCALE2, &options))3558 conn->tcp_timer_scale |= BIT_2;3559 if (test_bit(TCPOPT_TIMER_SCALE1, &options))3560 conn->tcp_timer_scale |= BIT_1;3561 3562 conn->tcp_timer_scale >>= 1;3563 conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options);3564 3565 options = le16_to_cpu(fw_ddb_entry->ip_options);3566 conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options);3567 3568 conn->max_recv_dlength = BYTE_UNITS *3569 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);3570 conn->max_xmit_dlength = BYTE_UNITS *3571 le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);3572 sess->first_burst = BYTE_UNITS *3573 le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);3574 sess->max_burst = BYTE_UNITS *3575 le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);3576 sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);3577 sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);3578 sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);3579 sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);3580 conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss);3581 conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf;3582 conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf;3583 conn->ipv6_flow_label = le16_to_cpu(fw_ddb_entry->ipv6_flow_lbl);3584 conn->keepalive_timeout = le16_to_cpu(fw_ddb_entry->ka_timeout);3585 conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port);3586 conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn);3587 conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn);3588 sess->discovery_parent_idx = le16_to_cpu(fw_ddb_entry->ddb_link);3589 sess->discovery_parent_type = le16_to_cpu(fw_ddb_entry->ddb_link);3590 sess->chap_out_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);3591 sess->tsid = le16_to_cpu(fw_ddb_entry->tsid);3592 3593 sess->default_taskmgmt_timeout =3594 le16_to_cpu(fw_ddb_entry->def_timeout);3595 conn->port = le16_to_cpu(fw_ddb_entry->port);3596 3597 options = le16_to_cpu(fw_ddb_entry->options);3598 conn->ipaddress = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL);3599 if (!conn->ipaddress) {3600 rc = -ENOMEM;3601 goto exit_copy;3602 }3603 3604 conn->redirect_ipaddr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL);3605 if (!conn->redirect_ipaddr) {3606 rc = -ENOMEM;3607 goto exit_copy;3608 }3609 3610 memcpy(conn->ipaddress, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);3611 memcpy(conn->redirect_ipaddr, fw_ddb_entry->tgt_addr, IPv6_ADDR_LEN);3612 3613 if (test_bit(OPT_IPV6_DEVICE, &options)) {3614 conn->ipv6_traffic_class = fw_ddb_entry->ipv4_tos;3615 3616 conn->link_local_ipv6_addr = kmemdup(3617 fw_ddb_entry->link_local_ipv6_addr,3618 IPv6_ADDR_LEN, GFP_KERNEL);3619 if (!conn->link_local_ipv6_addr) {3620 rc = -ENOMEM;3621 goto exit_copy;3622 }3623 } else {3624 conn->ipv4_tos = fw_ddb_entry->ipv4_tos;3625 }3626 3627 if (fw_ddb_entry->iscsi_name[0]) {3628 rc = iscsi_switch_str_param(&sess->targetname,3629 (char *)fw_ddb_entry->iscsi_name);3630 if (rc)3631 goto exit_copy;3632 }3633 3634 if (fw_ddb_entry->iscsi_alias[0]) {3635 rc = iscsi_switch_str_param(&sess->targetalias,3636 (char *)fw_ddb_entry->iscsi_alias);3637 if (rc)3638 goto exit_copy;3639 }3640 3641 COPY_ISID(sess->isid, fw_ddb_entry->isid);3642 3643exit_copy:3644 return rc;3645}3646 3647static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess,3648 struct iscsi_bus_flash_conn *conn,3649 struct dev_db_entry *fw_ddb_entry)3650{3651 uint16_t options;3652 3653 options = le16_to_cpu(fw_ddb_entry->options);3654 SET_BITVAL(conn->is_fw_assigned_ipv6, options, BIT_11);3655 if (!strncmp(sess->portal_type, PORTAL_TYPE_IPV6, 4))3656 options |= BIT_8;3657 else3658 options &= ~BIT_8;3659 3660 SET_BITVAL(sess->auto_snd_tgt_disable, options, BIT_6);3661 SET_BITVAL(sess->discovery_sess, options, BIT_4);3662 SET_BITVAL(sess->entry_state, options, BIT_3);3663 fw_ddb_entry->options = cpu_to_le16(options);3664 3665 options = le16_to_cpu(fw_ddb_entry->iscsi_options);3666 SET_BITVAL(conn->hdrdgst_en, options, BIT_13);3667 SET_BITVAL(conn->datadgst_en, options, BIT_12);3668 SET_BITVAL(sess->imm_data_en, options, BIT_11);3669 SET_BITVAL(sess->initial_r2t_en, options, BIT_10);3670 SET_BITVAL(sess->dataseq_inorder_en, options, BIT_9);3671 SET_BITVAL(sess->pdu_inorder_en, options, BIT_8);3672 SET_BITVAL(sess->chap_auth_en, options, BIT_7);3673 SET_BITVAL(conn->snack_req_en, options, BIT_6);3674 SET_BITVAL(sess->discovery_logout_en, options, BIT_5);3675 SET_BITVAL(sess->bidi_chap_en, options, BIT_4);3676 SET_BITVAL(sess->discovery_auth_optional, options, BIT_3);3677 SET_BITVAL(sess->erl & BIT_1, options, BIT_1);3678 SET_BITVAL(sess->erl & BIT_0, options, BIT_0);3679 fw_ddb_entry->iscsi_options = cpu_to_le16(options);3680 3681 options = le16_to_cpu(fw_ddb_entry->tcp_options);3682 SET_BITVAL(conn->tcp_timestamp_stat, options, BIT_6);3683 SET_BITVAL(conn->tcp_nagle_disable, options, BIT_5);3684 SET_BITVAL(conn->tcp_wsf_disable, options, BIT_4);3685 SET_BITVAL(conn->tcp_timer_scale & BIT_2, options, BIT_3);3686 SET_BITVAL(conn->tcp_timer_scale & BIT_1, options, BIT_2);3687 SET_BITVAL(conn->tcp_timer_scale & BIT_0, options, BIT_1);3688 SET_BITVAL(conn->tcp_timestamp_en, options, BIT_0);3689 fw_ddb_entry->tcp_options = cpu_to_le16(options);3690 3691 options = le16_to_cpu(fw_ddb_entry->ip_options);3692 SET_BITVAL(conn->fragment_disable, options, BIT_4);3693 fw_ddb_entry->ip_options = cpu_to_le16(options);3694 3695 fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t);3696 fw_ddb_entry->iscsi_max_rcv_data_seg_len =3697 cpu_to_le16(conn->max_recv_dlength / BYTE_UNITS);3698 fw_ddb_entry->iscsi_max_snd_data_seg_len =3699 cpu_to_le16(conn->max_xmit_dlength / BYTE_UNITS);3700 fw_ddb_entry->iscsi_first_burst_len =3701 cpu_to_le16(sess->first_burst / BYTE_UNITS);3702 fw_ddb_entry->iscsi_max_burst_len = cpu_to_le16(sess->max_burst /3703 BYTE_UNITS);3704 fw_ddb_entry->iscsi_def_time2wait = cpu_to_le16(sess->time2wait);3705 fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain);3706 fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt);3707 fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size);3708 fw_ddb_entry->tcp_xmt_wsf = (uint8_t) cpu_to_le32(conn->tcp_xmit_wsf);3709 fw_ddb_entry->tcp_rcv_wsf = (uint8_t) cpu_to_le32(conn->tcp_recv_wsf);3710 fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label);3711 fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout);3712 fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port);3713 fw_ddb_entry->stat_sn = cpu_to_le32(conn->statsn);3714 fw_ddb_entry->exp_stat_sn = cpu_to_le32(conn->exp_statsn);3715 fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_idx);3716 fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx);3717 fw_ddb_entry->tsid = cpu_to_le16(sess->tsid);3718 fw_ddb_entry->port = cpu_to_le16(conn->port);3719 fw_ddb_entry->def_timeout =3720 cpu_to_le16(sess->default_taskmgmt_timeout);3721 3722 if (!strncmp(sess->portal_type, PORTAL_TYPE_IPV6, 4))3723 fw_ddb_entry->ipv4_tos = conn->ipv6_traffic_class;3724 else3725 fw_ddb_entry->ipv4_tos = conn->ipv4_tos;3726 3727 if (conn->ipaddress)3728 memcpy(fw_ddb_entry->ip_addr, conn->ipaddress,3729 sizeof(fw_ddb_entry->ip_addr));3730 3731 if (conn->redirect_ipaddr)3732 memcpy(fw_ddb_entry->tgt_addr, conn->redirect_ipaddr,3733 sizeof(fw_ddb_entry->tgt_addr));3734 3735 if (conn->link_local_ipv6_addr)3736 memcpy(fw_ddb_entry->link_local_ipv6_addr,3737 conn->link_local_ipv6_addr,3738 sizeof(fw_ddb_entry->link_local_ipv6_addr));3739 3740 if (sess->targetname)3741 memcpy(fw_ddb_entry->iscsi_name, sess->targetname,3742 sizeof(fw_ddb_entry->iscsi_name));3743 3744 if (sess->targetalias)3745 memcpy(fw_ddb_entry->iscsi_alias, sess->targetalias,3746 sizeof(fw_ddb_entry->iscsi_alias));3747 3748 COPY_ISID(fw_ddb_entry->isid, sess->isid);3749 3750 return 0;3751}3752 3753static void qla4xxx_copy_to_sess_conn_params(struct iscsi_conn *conn,3754 struct iscsi_session *sess,3755 struct dev_db_entry *fw_ddb_entry)3756{3757 unsigned long options = 0;3758 uint16_t ddb_link;3759 uint16_t disc_parent;3760 char ip_addr[DDB_IPADDR_LEN];3761 3762 options = le16_to_cpu(fw_ddb_entry->options);3763 conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options);3764 sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE,3765 &options);3766 sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options);3767 3768 options = le16_to_cpu(fw_ddb_entry->iscsi_options);3769 conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options);3770 conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options);3771 sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options);3772 sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options);3773 sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER,3774 &options);3775 sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options);3776 sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options);3777 sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN,3778 &options);3779 sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options);3780 sess->discovery_auth_optional =3781 test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options);3782 if (test_bit(ISCSIOPT_ERL1, &options))3783 sess->erl |= BIT_1;3784 if (test_bit(ISCSIOPT_ERL0, &options))3785 sess->erl |= BIT_0;3786 3787 options = le16_to_cpu(fw_ddb_entry->tcp_options);3788 conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options);3789 conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options);3790 conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options);3791 if (test_bit(TCPOPT_TIMER_SCALE3, &options))3792 conn->tcp_timer_scale |= BIT_3;3793 if (test_bit(TCPOPT_TIMER_SCALE2, &options))3794 conn->tcp_timer_scale |= BIT_2;3795 if (test_bit(TCPOPT_TIMER_SCALE1, &options))3796 conn->tcp_timer_scale |= BIT_1;3797 3798 conn->tcp_timer_scale >>= 1;3799 conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options);3800 3801 options = le16_to_cpu(fw_ddb_entry->ip_options);3802 conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options);3803 3804 conn->max_recv_dlength = BYTE_UNITS *3805 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);3806 conn->max_xmit_dlength = BYTE_UNITS *3807 le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len);3808 sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t);3809 sess->first_burst = BYTE_UNITS *3810 le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len);3811 sess->max_burst = BYTE_UNITS *3812 le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len);3813 sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);3814 sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain);3815 sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);3816 conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss);3817 conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf;3818 conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf;3819 conn->ipv4_tos = fw_ddb_entry->ipv4_tos;3820 conn->keepalive_tmo = le16_to_cpu(fw_ddb_entry->ka_timeout);3821 conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port);3822 conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn);3823 conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn);3824 sess->tsid = le16_to_cpu(fw_ddb_entry->tsid);3825 COPY_ISID(sess->isid, fw_ddb_entry->isid);3826 3827 ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link);3828 if (ddb_link == DDB_ISNS)3829 disc_parent = ISCSI_DISC_PARENT_ISNS;3830 else if (ddb_link == DDB_NO_LINK)3831 disc_parent = ISCSI_DISC_PARENT_UNKNOWN;3832 else if (ddb_link < MAX_DDB_ENTRIES)3833 disc_parent = ISCSI_DISC_PARENT_SENDTGT;3834 else3835 disc_parent = ISCSI_DISC_PARENT_UNKNOWN;3836 3837 iscsi_set_param(conn->cls_conn, ISCSI_PARAM_DISCOVERY_PARENT_TYPE,3838 iscsi_get_discovery_parent_name(disc_parent), 0);3839 3840 iscsi_set_param(conn->cls_conn, ISCSI_PARAM_TARGET_ALIAS,3841 (char *)fw_ddb_entry->iscsi_alias, 0);3842 3843 options = le16_to_cpu(fw_ddb_entry->options);3844 if (options & DDB_OPT_IPV6_DEVICE) {3845 memset(ip_addr, 0, sizeof(ip_addr));3846 sprintf(ip_addr, "%pI6", fw_ddb_entry->link_local_ipv6_addr);3847 iscsi_set_param(conn->cls_conn, ISCSI_PARAM_LOCAL_IPADDR,3848 (char *)ip_addr, 0);3849 }3850}3851 3852static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,3853 struct dev_db_entry *fw_ddb_entry,3854 struct iscsi_cls_session *cls_sess,3855 struct iscsi_cls_conn *cls_conn)3856{3857 int buflen = 0;3858 struct iscsi_session *sess;3859 struct ddb_entry *ddb_entry;3860 struct ql4_chap_table chap_tbl;3861 struct iscsi_conn *conn;3862 char ip_addr[DDB_IPADDR_LEN];3863 uint16_t options = 0;3864 3865 sess = cls_sess->dd_data;3866 ddb_entry = sess->dd_data;3867 conn = cls_conn->dd_data;3868 memset(&chap_tbl, 0, sizeof(chap_tbl));3869 3870 ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);3871 3872 qla4xxx_copy_to_sess_conn_params(conn, sess, fw_ddb_entry);3873 3874 sess->def_taskmgmt_tmo = le16_to_cpu(fw_ddb_entry->def_timeout);3875 conn->persistent_port = le16_to_cpu(fw_ddb_entry->port);3876 3877 memset(ip_addr, 0, sizeof(ip_addr));3878 options = le16_to_cpu(fw_ddb_entry->options);3879 if (options & DDB_OPT_IPV6_DEVICE) {3880 iscsi_set_param(cls_conn, ISCSI_PARAM_PORTAL_TYPE, "ipv6", 4);3881 3882 memset(ip_addr, 0, sizeof(ip_addr));3883 sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr);3884 } else {3885 iscsi_set_param(cls_conn, ISCSI_PARAM_PORTAL_TYPE, "ipv4", 4);3886 sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr);3887 }3888 3889 iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS,3890 (char *)ip_addr, buflen);3891 iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME,3892 (char *)fw_ddb_entry->iscsi_name, buflen);3893 iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME,3894 (char *)ha->name_string, buflen);3895 3896 if (ddb_entry->chap_tbl_idx != INVALID_ENTRY) {3897 if (!qla4xxx_get_uni_chap_at_index(ha, chap_tbl.name,3898 chap_tbl.secret,3899 ddb_entry->chap_tbl_idx)) {3900 iscsi_set_param(cls_conn, ISCSI_PARAM_USERNAME,3901 (char *)chap_tbl.name,3902 strlen((char *)chap_tbl.name));3903 iscsi_set_param(cls_conn, ISCSI_PARAM_PASSWORD,3904 (char *)chap_tbl.secret,3905 chap_tbl.secret_len);3906 }3907 }3908}3909 3910void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,3911 struct ddb_entry *ddb_entry)3912{3913 struct iscsi_cls_session *cls_sess;3914 struct iscsi_cls_conn *cls_conn;3915 uint32_t ddb_state;3916 dma_addr_t fw_ddb_entry_dma;3917 struct dev_db_entry *fw_ddb_entry;3918 3919 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3920 &fw_ddb_entry_dma, GFP_KERNEL);3921 if (!fw_ddb_entry) {3922 ql4_printk(KERN_ERR, ha,3923 "%s: Unable to allocate dma buffer\n", __func__);3924 goto exit_session_conn_fwddb_param;3925 }3926 3927 if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,3928 fw_ddb_entry_dma, NULL, NULL, &ddb_state,3929 NULL, NULL, NULL) == QLA_ERROR) {3930 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "3931 "get_ddb_entry for fw_ddb_index %d\n",3932 ha->host_no, __func__,3933 ddb_entry->fw_ddb_index));3934 goto exit_session_conn_fwddb_param;3935 }3936 3937 cls_sess = ddb_entry->sess;3938 3939 cls_conn = ddb_entry->conn;3940 3941 /* Update params */3942 qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);3943 3944exit_session_conn_fwddb_param:3945 if (fw_ddb_entry)3946 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3947 fw_ddb_entry, fw_ddb_entry_dma);3948}3949 3950void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,3951 struct ddb_entry *ddb_entry)3952{3953 struct iscsi_cls_session *cls_sess;3954 struct iscsi_cls_conn *cls_conn;3955 struct iscsi_session *sess;3956 struct iscsi_conn *conn;3957 uint32_t ddb_state;3958 dma_addr_t fw_ddb_entry_dma;3959 struct dev_db_entry *fw_ddb_entry;3960 3961 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),3962 &fw_ddb_entry_dma, GFP_KERNEL);3963 if (!fw_ddb_entry) {3964 ql4_printk(KERN_ERR, ha,3965 "%s: Unable to allocate dma buffer\n", __func__);3966 goto exit_session_conn_param;3967 }3968 3969 if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry,3970 fw_ddb_entry_dma, NULL, NULL, &ddb_state,3971 NULL, NULL, NULL) == QLA_ERROR) {3972 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed "3973 "get_ddb_entry for fw_ddb_index %d\n",3974 ha->host_no, __func__,3975 ddb_entry->fw_ddb_index));3976 goto exit_session_conn_param;3977 }3978 3979 cls_sess = ddb_entry->sess;3980 sess = cls_sess->dd_data;3981 3982 cls_conn = ddb_entry->conn;3983 conn = cls_conn->dd_data;3984 3985 /* Update timers after login */3986 ddb_entry->default_relogin_timeout =3987 (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) &&3988 (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ?3989 le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV;3990 ddb_entry->default_time2wait =3991 le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);3992 3993 /* Update params */3994 ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);3995 qla4xxx_copy_to_sess_conn_params(conn, sess, fw_ddb_entry);3996 3997 memcpy(sess->initiatorname, ha->name_string,3998 min(sizeof(ha->name_string), sizeof(sess->initiatorname)));3999 4000exit_session_conn_param:4001 if (fw_ddb_entry)4002 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),4003 fw_ddb_entry, fw_ddb_entry_dma);4004}4005 4006/*4007 * Timer routines4008 */4009static void qla4xxx_timer(struct timer_list *t);4010 4011static void qla4xxx_start_timer(struct scsi_qla_host *ha,4012 unsigned long interval)4013{4014 DEBUG(printk("scsi: %s: Starting timer thread for adapter %d\n",4015 __func__, ha->host->host_no));4016 timer_setup(&ha->timer, qla4xxx_timer, 0);4017 ha->timer.expires = jiffies + interval * HZ;4018 add_timer(&ha->timer);4019 ha->timer_active = 1;4020}4021 4022static void qla4xxx_stop_timer(struct scsi_qla_host *ha)4023{4024 del_timer_sync(&ha->timer);4025 ha->timer_active = 0;4026}4027 4028/***4029 * qla4xxx_mark_device_missing - blocks the session4030 * @cls_session: Pointer to the session to be blocked4031 * @ddb_entry: Pointer to device database entry4032 *4033 * This routine marks a device missing and close connection.4034 **/4035void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session)4036{4037 iscsi_block_session(cls_session);4038}4039 4040/**4041 * qla4xxx_mark_all_devices_missing - mark all devices as missing.4042 * @ha: Pointer to host adapter structure.4043 *4044 * This routine marks a device missing and resets the relogin retry count.4045 **/4046void qla4xxx_mark_all_devices_missing(struct scsi_qla_host *ha)4047{4048 iscsi_host_for_each_session(ha->host, qla4xxx_mark_device_missing);4049}4050 4051static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha,4052 struct ddb_entry *ddb_entry,4053 struct scsi_cmnd *cmd)4054{4055 struct srb *srb;4056 4057 srb = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);4058 if (!srb)4059 return srb;4060 4061 kref_init(&srb->srb_ref);4062 srb->ha = ha;4063 srb->ddb = ddb_entry;4064 srb->cmd = cmd;4065 srb->flags = 0;4066 qla4xxx_cmd_priv(cmd)->srb = srb;4067 4068 return srb;4069}4070 4071static void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, struct srb *srb)4072{4073 struct scsi_cmnd *cmd = srb->cmd;4074 4075 if (srb->flags & SRB_DMA_VALID) {4076 scsi_dma_unmap(cmd);4077 srb->flags &= ~SRB_DMA_VALID;4078 }4079 qla4xxx_cmd_priv(cmd)->srb = NULL;4080}4081 4082void qla4xxx_srb_compl(struct kref *ref)4083{4084 struct srb *srb = container_of(ref, struct srb, srb_ref);4085 struct scsi_cmnd *cmd = srb->cmd;4086 struct scsi_qla_host *ha = srb->ha;4087 4088 qla4xxx_srb_free_dma(ha, srb);4089 4090 mempool_free(srb, ha->srb_mempool);4091 4092 scsi_done(cmd);4093}4094 4095/**4096 * qla4xxx_queuecommand - scsi layer issues scsi command to driver.4097 * @host: scsi host4098 * @cmd: Pointer to Linux's SCSI command structure4099 *4100 * Remarks:4101 * This routine is invoked by Linux to send a SCSI command to the driver.4102 * The mid-level driver tries to ensure that queuecommand never gets4103 * invoked concurrently with itself or the interrupt handler (although4104 * the interrupt handler may call this routine as part of request-4105 * completion handling). Unfortunely, it sometimes calls the scheduler4106 * in interrupt context which is a big NO! NO!.4107 **/4108static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)4109{4110 struct scsi_qla_host *ha = to_qla_host(host);4111 struct ddb_entry *ddb_entry = cmd->device->hostdata;4112 struct iscsi_cls_session *sess = ddb_entry->sess;4113 struct srb *srb;4114 int rval;4115 4116 if (test_bit(AF_EEH_BUSY, &ha->flags)) {4117 if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))4118 cmd->result = DID_NO_CONNECT << 16;4119 else4120 cmd->result = DID_REQUEUE << 16;4121 goto qc_fail_command;4122 }4123 4124 if (!sess) {4125 cmd->result = DID_IMM_RETRY << 16;4126 goto qc_fail_command;4127 }4128 4129 rval = iscsi_session_chkready(sess);4130 if (rval) {4131 cmd->result = rval;4132 goto qc_fail_command;4133 }4134 4135 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||4136 test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||4137 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||4138 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||4139 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||4140 !test_bit(AF_ONLINE, &ha->flags) ||4141 !test_bit(AF_LINK_UP, &ha->flags) ||4142 test_bit(AF_LOOPBACK, &ha->flags) ||4143 test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags) ||4144 test_bit(DPC_RESTORE_ACB, &ha->dpc_flags) ||4145 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))4146 goto qc_host_busy;4147 4148 srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd);4149 if (!srb)4150 goto qc_host_busy;4151 4152 rval = qla4xxx_send_command_to_isp(ha, srb);4153 if (rval != QLA_SUCCESS)4154 goto qc_host_busy_free_sp;4155 4156 return 0;4157 4158qc_host_busy_free_sp:4159 qla4xxx_srb_free_dma(ha, srb);4160 mempool_free(srb, ha->srb_mempool);4161 4162qc_host_busy:4163 return SCSI_MLQUEUE_HOST_BUSY;4164 4165qc_fail_command:4166 scsi_done(cmd);4167 4168 return 0;4169}4170 4171/**4172 * qla4xxx_mem_free - frees memory allocated to adapter4173 * @ha: Pointer to host adapter structure.4174 *4175 * Frees memory previously allocated by qla4xxx_mem_alloc4176 **/4177static void qla4xxx_mem_free(struct scsi_qla_host *ha)4178{4179 if (ha->queues)4180 dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,4181 ha->queues_dma);4182 4183 vfree(ha->fw_dump);4184 4185 ha->queues_len = 0;4186 ha->queues = NULL;4187 ha->queues_dma = 0;4188 ha->request_ring = NULL;4189 ha->request_dma = 0;4190 ha->response_ring = NULL;4191 ha->response_dma = 0;4192 ha->shadow_regs = NULL;4193 ha->shadow_regs_dma = 0;4194 ha->fw_dump = NULL;4195 ha->fw_dump_size = 0;4196 4197 /* Free srb pool. */4198 mempool_destroy(ha->srb_mempool);4199 ha->srb_mempool = NULL;4200 4201 dma_pool_destroy(ha->chap_dma_pool);4202 4203 vfree(ha->chap_list);4204 ha->chap_list = NULL;4205 4206 dma_pool_destroy(ha->fw_ddb_dma_pool);4207 4208 /* release io space registers */4209 if (is_qla8022(ha)) {4210 if (ha->nx_pcibase)4211 iounmap(4212 (struct device_reg_82xx __iomem *)ha->nx_pcibase);4213 } else if (is_qla8032(ha) || is_qla8042(ha)) {4214 if (ha->nx_pcibase)4215 iounmap(4216 (struct device_reg_83xx __iomem *)ha->nx_pcibase);4217 } else if (ha->reg) {4218 iounmap(ha->reg);4219 }4220 4221 vfree(ha->reset_tmplt.buff);4222 4223 pci_release_regions(ha->pdev);4224}4225 4226/**4227 * qla4xxx_mem_alloc - allocates memory for use by adapter.4228 * @ha: Pointer to host adapter structure4229 *4230 * Allocates DMA memory for request and response queues. Also allocates memory4231 * for srbs.4232 **/4233static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)4234{4235 unsigned long align;4236 4237 /* Allocate contiguous block of DMA memory for queues. */4238 ha->queues_len = ((REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +4239 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE) +4240 sizeof(struct shadow_regs) +4241 MEM_ALIGN_VALUE +4242 (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);4243 ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,4244 &ha->queues_dma, GFP_KERNEL);4245 if (ha->queues == NULL) {4246 ql4_printk(KERN_WARNING, ha,4247 "Memory Allocation failed - queues.\n");4248 4249 goto mem_alloc_error_exit;4250 }4251 4252 /*4253 * As per RISC alignment requirements -- the bus-address must be a4254 * multiple of the request-ring size (in bytes).4255 */4256 align = 0;4257 if ((unsigned long)ha->queues_dma & (MEM_ALIGN_VALUE - 1))4258 align = MEM_ALIGN_VALUE - ((unsigned long)ha->queues_dma &4259 (MEM_ALIGN_VALUE - 1));4260 4261 /* Update request and response queue pointers. */4262 ha->request_dma = ha->queues_dma + align;4263 ha->request_ring = (struct queue_entry *) (ha->queues + align);4264 ha->response_dma = ha->queues_dma + align +4265 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE);4266 ha->response_ring = (struct queue_entry *) (ha->queues + align +4267 (REQUEST_QUEUE_DEPTH *4268 QUEUE_SIZE));4269 ha->shadow_regs_dma = ha->queues_dma + align +4270 (REQUEST_QUEUE_DEPTH * QUEUE_SIZE) +4271 (RESPONSE_QUEUE_DEPTH * QUEUE_SIZE);4272 ha->shadow_regs = (struct shadow_regs *) (ha->queues + align +4273 (REQUEST_QUEUE_DEPTH *4274 QUEUE_SIZE) +4275 (RESPONSE_QUEUE_DEPTH *4276 QUEUE_SIZE));4277 4278 /* Allocate memory for srb pool. */4279 ha->srb_mempool = mempool_create(SRB_MIN_REQ, mempool_alloc_slab,4280 mempool_free_slab, srb_cachep);4281 if (ha->srb_mempool == NULL) {4282 ql4_printk(KERN_WARNING, ha,4283 "Memory Allocation failed - SRB Pool.\n");4284 4285 goto mem_alloc_error_exit;4286 }4287 4288 ha->chap_dma_pool = dma_pool_create("ql4_chap", &ha->pdev->dev,4289 CHAP_DMA_BLOCK_SIZE, 8, 0);4290 4291 if (ha->chap_dma_pool == NULL) {4292 ql4_printk(KERN_WARNING, ha,4293 "%s: chap_dma_pool allocation failed..\n", __func__);4294 goto mem_alloc_error_exit;4295 }4296 4297 ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev,4298 DDB_DMA_BLOCK_SIZE, 8, 0);4299 4300 if (ha->fw_ddb_dma_pool == NULL) {4301 ql4_printk(KERN_WARNING, ha,4302 "%s: fw_ddb_dma_pool allocation failed..\n",4303 __func__);4304 goto mem_alloc_error_exit;4305 }4306 4307 return QLA_SUCCESS;4308 4309mem_alloc_error_exit:4310 return QLA_ERROR;4311}4312 4313/**4314 * qla4_8xxx_check_temp - Check the ISP82XX temperature.4315 * @ha: adapter block pointer.4316 *4317 * Note: The caller should not hold the idc lock.4318 **/4319static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)4320{4321 uint32_t temp, temp_state, temp_val;4322 int status = QLA_SUCCESS;4323 4324 temp = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_TEMP_STATE);4325 4326 temp_state = qla82xx_get_temp_state(temp);4327 temp_val = qla82xx_get_temp_val(temp);4328 4329 if (temp_state == QLA82XX_TEMP_PANIC) {4330 ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C"4331 " exceeds maximum allowed. Hardware has been shut"4332 " down.\n", temp_val);4333 status = QLA_ERROR;4334 } else if (temp_state == QLA82XX_TEMP_WARN) {4335 if (ha->temperature == QLA82XX_TEMP_NORMAL)4336 ql4_printk(KERN_WARNING, ha, "Device temperature %d"4337 " degrees C exceeds operating range."4338 " Immediate action needed.\n", temp_val);4339 } else {4340 if (ha->temperature == QLA82XX_TEMP_WARN)4341 ql4_printk(KERN_INFO, ha, "Device temperature is"4342 " now %d degrees C in normal range.\n",4343 temp_val);4344 }4345 ha->temperature = temp_state;4346 return status;4347}4348 4349/**4350 * qla4_8xxx_check_fw_alive - Check firmware health4351 * @ha: Pointer to host adapter structure.4352 *4353 * Context: Interrupt4354 **/4355static int qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha)4356{4357 uint32_t fw_heartbeat_counter;4358 int status = QLA_SUCCESS;4359 4360 fw_heartbeat_counter = qla4_8xxx_rd_direct(ha,4361 QLA8XXX_PEG_ALIVE_COUNTER);4362 /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */4363 if (fw_heartbeat_counter == 0xffffffff) {4364 DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen "4365 "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n",4366 ha->host_no, __func__));4367 return status;4368 }4369 4370 if (ha->fw_heartbeat_counter == fw_heartbeat_counter) {4371 ha->seconds_since_last_heartbeat++;4372 /* FW not alive after 2 seconds */4373 if (ha->seconds_since_last_heartbeat == 2) {4374 ha->seconds_since_last_heartbeat = 0;4375 qla4_8xxx_dump_peg_reg(ha);4376 status = QLA_ERROR;4377 }4378 } else4379 ha->seconds_since_last_heartbeat = 0;4380 4381 ha->fw_heartbeat_counter = fw_heartbeat_counter;4382 return status;4383}4384 4385static void qla4_8xxx_process_fw_error(struct scsi_qla_host *ha)4386{4387 uint32_t halt_status;4388 int halt_status_unrecoverable = 0;4389 4390 halt_status = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_HALT_STATUS1);4391 4392 if (is_qla8022(ha)) {4393 ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n",4394 __func__);4395 qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,4396 CRB_NIU_XG_PAUSE_CTL_P0 |4397 CRB_NIU_XG_PAUSE_CTL_P1);4398 4399 if (QLA82XX_FWERROR_CODE(halt_status) == 0x67)4400 ql4_printk(KERN_ERR, ha, "%s: Firmware aborted with error code 0x00006700. Device is being reset\n",4401 __func__);4402 if (halt_status & HALT_STATUS_UNRECOVERABLE)4403 halt_status_unrecoverable = 1;4404 } else if (is_qla8032(ha) || is_qla8042(ha)) {4405 if (halt_status & QLA83XX_HALT_STATUS_FW_RESET)4406 ql4_printk(KERN_ERR, ha, "%s: Firmware error detected device is being reset\n",4407 __func__);4408 else if (halt_status & QLA83XX_HALT_STATUS_UNRECOVERABLE)4409 halt_status_unrecoverable = 1;4410 }4411 4412 /*4413 * Since we cannot change dev_state in interrupt context,4414 * set appropriate DPC flag then wakeup DPC4415 */4416 if (halt_status_unrecoverable) {4417 set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);4418 } else {4419 ql4_printk(KERN_INFO, ha, "%s: detect abort needed!\n",4420 __func__);4421 set_bit(DPC_RESET_HA, &ha->dpc_flags);4422 }4423 qla4xxx_mailbox_premature_completion(ha);4424 qla4xxx_wake_dpc(ha);4425}4426 4427/**4428 * qla4_8xxx_watchdog - Poll dev state4429 * @ha: Pointer to host adapter structure.4430 *4431 * Context: Interrupt4432 **/4433void qla4_8xxx_watchdog(struct scsi_qla_host *ha)4434{4435 uint32_t dev_state;4436 uint32_t idc_ctrl;4437 4438 if (is_qla8032(ha) &&4439 (qla4_83xx_is_detached(ha) == QLA_SUCCESS))4440 WARN_ONCE(1, "%s: iSCSI function %d marked invisible\n",4441 __func__, ha->func_num);4442 4443 /* don't poll if reset is going on */4444 if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) ||4445 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||4446 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {4447 dev_state = qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE);4448 4449 if (qla4_8xxx_check_temp(ha)) {4450 if (is_qla8022(ha)) {4451 ql4_printk(KERN_INFO, ha, "disabling pause transmit on port 0 & 1.\n");4452 qla4_82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,4453 CRB_NIU_XG_PAUSE_CTL_P0 |4454 CRB_NIU_XG_PAUSE_CTL_P1);4455 }4456 set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);4457 qla4xxx_wake_dpc(ha);4458 } else if (dev_state == QLA8XXX_DEV_NEED_RESET &&4459 !test_bit(DPC_RESET_HA, &ha->dpc_flags)) {4460 4461 ql4_printk(KERN_INFO, ha, "%s: HW State: NEED RESET!\n",4462 __func__);4463 4464 if (is_qla8032(ha) || is_qla8042(ha)) {4465 idc_ctrl = qla4_83xx_rd_reg(ha,4466 QLA83XX_IDC_DRV_CTRL);4467 if (!(idc_ctrl & GRACEFUL_RESET_BIT1)) {4468 ql4_printk(KERN_INFO, ha, "%s: Graceful reset bit is not set\n",4469 __func__);4470 qla4xxx_mailbox_premature_completion(4471 ha);4472 }4473 }4474 4475 if ((is_qla8032(ha) || is_qla8042(ha)) ||4476 (is_qla8022(ha) && !ql4xdontresethba)) {4477 set_bit(DPC_RESET_HA, &ha->dpc_flags);4478 qla4xxx_wake_dpc(ha);4479 }4480 } else if (dev_state == QLA8XXX_DEV_NEED_QUIESCENT &&4481 !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {4482 ql4_printk(KERN_INFO, ha, "%s: HW State: NEED QUIES!\n",4483 __func__);4484 set_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags);4485 qla4xxx_wake_dpc(ha);4486 } else {4487 /* Check firmware health */4488 if (qla4_8xxx_check_fw_alive(ha))4489 qla4_8xxx_process_fw_error(ha);4490 }4491 }4492}4493 4494static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)4495{4496 struct iscsi_session *sess;4497 struct ddb_entry *ddb_entry;4498 struct scsi_qla_host *ha;4499 4500 sess = cls_sess->dd_data;4501 ddb_entry = sess->dd_data;4502 ha = ddb_entry->ha;4503 4504 if (!(ddb_entry->ddb_type == FLASH_DDB))4505 return;4506 4507 if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) &&4508 !iscsi_is_session_online(cls_sess)) {4509 if (atomic_read(&ddb_entry->retry_relogin_timer) !=4510 INVALID_ENTRY) {4511 if (atomic_read(&ddb_entry->retry_relogin_timer) ==4512 0) {4513 atomic_set(&ddb_entry->retry_relogin_timer,4514 INVALID_ENTRY);4515 set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);4516 set_bit(DF_RELOGIN, &ddb_entry->flags);4517 DEBUG2(ql4_printk(KERN_INFO, ha,4518 "%s: index [%d] login device\n",4519 __func__, ddb_entry->fw_ddb_index));4520 } else4521 atomic_dec(&ddb_entry->retry_relogin_timer);4522 }4523 }4524 4525 /* Wait for relogin to timeout */4526 if (atomic_read(&ddb_entry->relogin_timer) &&4527 (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) {4528 /*4529 * If the relogin times out and the device is4530 * still NOT ONLINE then try and relogin again.4531 */4532 if (!iscsi_is_session_online(cls_sess)) {4533 /* Reset retry relogin timer */4534 atomic_inc(&ddb_entry->relogin_retry_count);4535 DEBUG2(ql4_printk(KERN_INFO, ha,4536 "%s: index[%d] relogin timed out-retrying"4537 " relogin (%d), retry (%d)\n", __func__,4538 ddb_entry->fw_ddb_index,4539 atomic_read(&ddb_entry->relogin_retry_count),4540 ddb_entry->default_time2wait + 4));4541 set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);4542 atomic_set(&ddb_entry->retry_relogin_timer,4543 ddb_entry->default_time2wait + 4);4544 }4545 }4546}4547 4548/**4549 * qla4xxx_timer - checks every second for work to do.4550 * @t: Context to obtain pointer to host adapter structure.4551 **/4552static void qla4xxx_timer(struct timer_list *t)4553{4554 struct scsi_qla_host *ha = from_timer(ha, t, timer);4555 int start_dpc = 0;4556 uint16_t w;4557 4558 iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb);4559 4560 /* If we are in the middle of AER/EEH processing4561 * skip any processing and reschedule the timer4562 */4563 if (test_bit(AF_EEH_BUSY, &ha->flags)) {4564 mod_timer(&ha->timer, jiffies + HZ);4565 return;4566 }4567 4568 /* Hardware read to trigger an EEH error during mailbox waits. */4569 if (!pci_channel_offline(ha->pdev))4570 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);4571 4572 if (is_qla80XX(ha))4573 qla4_8xxx_watchdog(ha);4574 4575 if (is_qla40XX(ha)) {4576 /* Check for heartbeat interval. */4577 if (ha->firmware_options & FWOPT_HEARTBEAT_ENABLE &&4578 ha->heartbeat_interval != 0) {4579 ha->seconds_since_last_heartbeat++;4580 if (ha->seconds_since_last_heartbeat >4581 ha->heartbeat_interval + 2)4582 set_bit(DPC_RESET_HA, &ha->dpc_flags);4583 }4584 }4585 4586 /* Process any deferred work. */4587 if (!list_empty(&ha->work_list))4588 start_dpc++;4589 4590 /* Wakeup the dpc routine for this adapter, if needed. */4591 if (start_dpc ||4592 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||4593 test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags) ||4594 test_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags) ||4595 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||4596 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||4597 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||4598 test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||4599 test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags) ||4600 test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags) ||4601 test_bit(DPC_SYSFS_DDB_EXPORT, &ha->dpc_flags) ||4602 test_bit(DPC_AEN, &ha->dpc_flags)) {4603 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"4604 " - dpc flags = 0x%lx\n",4605 ha->host_no, __func__, ha->dpc_flags));4606 qla4xxx_wake_dpc(ha);4607 }4608 4609 /* Reschedule timer thread to call us back in one second */4610 mod_timer(&ha->timer, jiffies + HZ);4611 4612 DEBUG2(ha->seconds_since_last_intr++);4613}4614 4615/**4616 * qla4xxx_cmd_wait - waits for all outstanding commands to complete4617 * @ha: Pointer to host adapter structure.4618 *4619 * This routine stalls the driver until all outstanding commands are returned.4620 * Caller must release the Hardware Lock prior to calling this routine.4621 **/4622static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)4623{4624 uint32_t index = 0;4625 unsigned long flags;4626 struct scsi_cmnd *cmd;4627 unsigned long wtime;4628 uint32_t wtmo;4629 4630 if (is_qla40XX(ha))4631 wtmo = WAIT_CMD_TOV;4632 else4633 wtmo = ha->nx_reset_timeout / 2;4634 4635 wtime = jiffies + (wtmo * HZ);4636 4637 DEBUG2(ql4_printk(KERN_INFO, ha,4638 "Wait up to %u seconds for cmds to complete\n",4639 wtmo));4640 4641 while (!time_after_eq(jiffies, wtime)) {4642 spin_lock_irqsave(&ha->hardware_lock, flags);4643 /* Find a command that hasn't completed. */4644 for (index = 0; index < ha->host->can_queue; index++) {4645 cmd = scsi_host_find_tag(ha->host, index);4646 /*4647 * We cannot just check if the index is valid,4648 * becase if we are run from the scsi eh, then4649 * the scsi/block layer is going to prevent4650 * the tag from being released.4651 */4652 if (cmd != NULL && qla4xxx_cmd_priv(cmd)->srb)4653 break;4654 }4655 spin_unlock_irqrestore(&ha->hardware_lock, flags);4656 4657 /* If No Commands are pending, wait is complete */4658 if (index == ha->host->can_queue)4659 return QLA_SUCCESS;4660 4661 msleep(1000);4662 }4663 /* If we timed out on waiting for commands to come back4664 * return ERROR. */4665 return QLA_ERROR;4666}4667 4668int qla4xxx_hw_reset(struct scsi_qla_host *ha)4669{4670 uint32_t ctrl_status;4671 unsigned long flags = 0;4672 4673 DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));4674 4675 if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)4676 return QLA_ERROR;4677 4678 spin_lock_irqsave(&ha->hardware_lock, flags);4679 4680 /*4681 * If the SCSI Reset Interrupt bit is set, clear it.4682 * Otherwise, the Soft Reset won't work.4683 */4684 ctrl_status = readw(&ha->reg->ctrl_status);4685 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0)4686 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);4687 4688 /* Issue Soft Reset */4689 writel(set_rmask(CSR_SOFT_RESET), &ha->reg->ctrl_status);4690 readl(&ha->reg->ctrl_status);4691 4692 spin_unlock_irqrestore(&ha->hardware_lock, flags);4693 return QLA_SUCCESS;4694}4695 4696/**4697 * qla4xxx_soft_reset - performs soft reset.4698 * @ha: Pointer to host adapter structure.4699 **/4700int qla4xxx_soft_reset(struct scsi_qla_host *ha)4701{4702 uint32_t max_wait_time;4703 unsigned long flags = 0;4704 int status;4705 uint32_t ctrl_status;4706 4707 status = qla4xxx_hw_reset(ha);4708 if (status != QLA_SUCCESS)4709 return status;4710 4711 status = QLA_ERROR;4712 /* Wait until the Network Reset Intr bit is cleared */4713 max_wait_time = RESET_INTR_TOV;4714 do {4715 spin_lock_irqsave(&ha->hardware_lock, flags);4716 ctrl_status = readw(&ha->reg->ctrl_status);4717 spin_unlock_irqrestore(&ha->hardware_lock, flags);4718 4719 if ((ctrl_status & CSR_NET_RESET_INTR) == 0)4720 break;4721 4722 msleep(1000);4723 } while ((--max_wait_time));4724 4725 if ((ctrl_status & CSR_NET_RESET_INTR) != 0) {4726 DEBUG2(printk(KERN_WARNING4727 "scsi%ld: Network Reset Intr not cleared by "4728 "Network function, clearing it now!\n",4729 ha->host_no));4730 spin_lock_irqsave(&ha->hardware_lock, flags);4731 writel(set_rmask(CSR_NET_RESET_INTR), &ha->reg->ctrl_status);4732 readl(&ha->reg->ctrl_status);4733 spin_unlock_irqrestore(&ha->hardware_lock, flags);4734 }4735 4736 /* Wait until the firmware tells us the Soft Reset is done */4737 max_wait_time = SOFT_RESET_TOV;4738 do {4739 spin_lock_irqsave(&ha->hardware_lock, flags);4740 ctrl_status = readw(&ha->reg->ctrl_status);4741 spin_unlock_irqrestore(&ha->hardware_lock, flags);4742 4743 if ((ctrl_status & CSR_SOFT_RESET) == 0) {4744 status = QLA_SUCCESS;4745 break;4746 }4747 4748 msleep(1000);4749 } while ((--max_wait_time));4750 4751 /*4752 * Also, make sure that the SCSI Reset Interrupt bit has been cleared4753 * after the soft reset has taken place.4754 */4755 spin_lock_irqsave(&ha->hardware_lock, flags);4756 ctrl_status = readw(&ha->reg->ctrl_status);4757 if ((ctrl_status & CSR_SCSI_RESET_INTR) != 0) {4758 writel(set_rmask(CSR_SCSI_RESET_INTR), &ha->reg->ctrl_status);4759 readl(&ha->reg->ctrl_status);4760 }4761 spin_unlock_irqrestore(&ha->hardware_lock, flags);4762 4763 /* If soft reset fails then most probably the bios on other4764 * function is also enabled.4765 * Since the initialization is sequential the other fn4766 * wont be able to acknowledge the soft reset.4767 * Issue a force soft reset to workaround this scenario.4768 */4769 if (max_wait_time == 0) {4770 /* Issue Force Soft Reset */4771 spin_lock_irqsave(&ha->hardware_lock, flags);4772 writel(set_rmask(CSR_FORCE_SOFT_RESET), &ha->reg->ctrl_status);4773 readl(&ha->reg->ctrl_status);4774 spin_unlock_irqrestore(&ha->hardware_lock, flags);4775 /* Wait until the firmware tells us the Soft Reset is done */4776 max_wait_time = SOFT_RESET_TOV;4777 do {4778 spin_lock_irqsave(&ha->hardware_lock, flags);4779 ctrl_status = readw(&ha->reg->ctrl_status);4780 spin_unlock_irqrestore(&ha->hardware_lock, flags);4781 4782 if ((ctrl_status & CSR_FORCE_SOFT_RESET) == 0) {4783 status = QLA_SUCCESS;4784 break;4785 }4786 4787 msleep(1000);4788 } while ((--max_wait_time));4789 }4790 4791 return status;4792}4793 4794/**4795 * qla4xxx_abort_active_cmds - returns all outstanding i/o requests to O.S.4796 * @ha: Pointer to host adapter structure.4797 * @res: returned scsi status4798 *4799 * This routine is called just prior to a HARD RESET to return all4800 * outstanding commands back to the Operating System.4801 * Caller should make sure that the following locks are released4802 * before this calling routine: Hardware lock, and io_request_lock.4803 **/4804static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res)4805{4806 struct srb *srb;4807 int i;4808 unsigned long flags;4809 4810 spin_lock_irqsave(&ha->hardware_lock, flags);4811 for (i = 0; i < ha->host->can_queue; i++) {4812 srb = qla4xxx_del_from_active_array(ha, i);4813 if (srb != NULL) {4814 srb->cmd->result = res;4815 kref_put(&srb->srb_ref, qla4xxx_srb_compl);4816 }4817 }4818 spin_unlock_irqrestore(&ha->hardware_lock, flags);4819}4820 4821void qla4xxx_dead_adapter_cleanup(struct scsi_qla_host *ha)4822{4823 clear_bit(AF_ONLINE, &ha->flags);4824 4825 /* Disable the board */4826 ql4_printk(KERN_INFO, ha, "Disabling the board\n");4827 4828 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);4829 qla4xxx_mark_all_devices_missing(ha);4830 clear_bit(AF_INIT_DONE, &ha->flags);4831}4832 4833static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session)4834{4835 struct iscsi_session *sess;4836 struct ddb_entry *ddb_entry;4837 4838 sess = cls_session->dd_data;4839 ddb_entry = sess->dd_data;4840 ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED;4841 4842 if (ddb_entry->ddb_type == FLASH_DDB)4843 iscsi_block_session(ddb_entry->sess);4844 else4845 iscsi_session_failure(cls_session->dd_data,4846 ISCSI_ERR_CONN_FAILED);4847}4848 4849/**4850 * qla4xxx_recover_adapter - recovers adapter after a fatal error4851 * @ha: Pointer to host adapter structure.4852 **/4853static int qla4xxx_recover_adapter(struct scsi_qla_host *ha)4854{4855 int status = QLA_ERROR;4856 uint8_t reset_chip = 0;4857 uint32_t dev_state;4858 unsigned long wait;4859 4860 /* Stall incoming I/O until we are done */4861 scsi_block_requests(ha->host);4862 clear_bit(AF_ONLINE, &ha->flags);4863 clear_bit(AF_LINK_UP, &ha->flags);4864 4865 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: adapter OFFLINE\n", __func__));4866 4867 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);4868 4869 if ((is_qla8032(ha) || is_qla8042(ha)) &&4870 !test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {4871 ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n",4872 __func__);4873 /* disable pause frame for ISP83xx */4874 qla4_83xx_disable_pause(ha);4875 }4876 4877 iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);4878 4879 if (test_bit(DPC_RESET_HA, &ha->dpc_flags))4880 reset_chip = 1;4881 4882 /* For the DPC_RESET_HA_INTR case (ISP-4xxx specific)4883 * do not reset adapter, jump to initialize_adapter */4884 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {4885 status = QLA_SUCCESS;4886 goto recover_ha_init_adapter;4887 }4888 4889 /* For the ISP-8xxx adapter, issue a stop_firmware if invoked4890 * from eh_host_reset or ioctl module */4891 if (is_qla80XX(ha) && !reset_chip &&4892 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags)) {4893 4894 DEBUG2(ql4_printk(KERN_INFO, ha,4895 "scsi%ld: %s - Performing stop_firmware...\n",4896 ha->host_no, __func__));4897 status = ha->isp_ops->reset_firmware(ha);4898 if (status == QLA_SUCCESS) {4899 ha->isp_ops->disable_intrs(ha);4900 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);4901 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);4902 } else {4903 /* If the stop_firmware fails then4904 * reset the entire chip */4905 reset_chip = 1;4906 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);4907 set_bit(DPC_RESET_HA, &ha->dpc_flags);4908 }4909 }4910 4911 /* Issue full chip reset if recovering from a catastrophic error,4912 * or if stop_firmware fails for ISP-8xxx.4913 * This is the default case for ISP-4xxx */4914 if (is_qla40XX(ha) || reset_chip) {4915 if (is_qla40XX(ha))4916 goto chip_reset;4917 4918 /* Check if 8XXX firmware is alive or not4919 * We may have arrived here from NEED_RESET4920 * detection only */4921 if (test_bit(AF_FW_RECOVERY, &ha->flags))4922 goto chip_reset;4923 4924 wait = jiffies + (FW_ALIVE_WAIT_TOV * HZ);4925 while (time_before(jiffies, wait)) {4926 if (qla4_8xxx_check_fw_alive(ha)) {4927 qla4xxx_mailbox_premature_completion(ha);4928 break;4929 }4930 4931 set_current_state(TASK_UNINTERRUPTIBLE);4932 schedule_timeout(HZ);4933 }4934chip_reset:4935 if (!test_bit(AF_FW_RECOVERY, &ha->flags))4936 qla4xxx_cmd_wait(ha);4937 4938 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);4939 DEBUG2(ql4_printk(KERN_INFO, ha,4940 "scsi%ld: %s - Performing chip reset..\n",4941 ha->host_no, __func__));4942 status = ha->isp_ops->reset_chip(ha);4943 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);4944 }4945 4946 /* Flush any pending ddb changed AENs */4947 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);4948 4949recover_ha_init_adapter:4950 /* Upon successful firmware/chip reset, re-initialize the adapter */4951 if (status == QLA_SUCCESS) {4952 /* For ISP-4xxx, force function 1 to always initialize4953 * before function 3 to prevent both funcions from4954 * stepping on top of the other */4955 if (is_qla40XX(ha) && (ha->mac_index == 3))4956 ssleep(6);4957 4958 /* NOTE: AF_ONLINE flag set upon successful completion of4959 * qla4xxx_initialize_adapter */4960 status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);4961 if (is_qla80XX(ha) && (status == QLA_ERROR)) {4962 status = qla4_8xxx_check_init_adapter_retry(ha);4963 if (status == QLA_ERROR) {4964 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Don't retry recover adapter\n",4965 ha->host_no, __func__);4966 qla4xxx_dead_adapter_cleanup(ha);4967 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);4968 clear_bit(DPC_RESET_HA, &ha->dpc_flags);4969 clear_bit(DPC_RESET_HA_FW_CONTEXT,4970 &ha->dpc_flags);4971 goto exit_recover;4972 }4973 }4974 }4975 4976 /* Retry failed adapter initialization, if necessary4977 * Do not retry initialize_adapter for RESET_HA_INTR (ISP-4xxx specific)4978 * case to prevent ping-pong resets between functions */4979 if (!test_bit(AF_ONLINE, &ha->flags) &&4980 !test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {4981 /* Adapter initialization failed, see if we can retry4982 * resetting the ha.4983 * Since we don't want to block the DPC for too long4984 * with multiple resets in the same thread,4985 * utilize DPC to retry */4986 if (is_qla80XX(ha)) {4987 ha->isp_ops->idc_lock(ha);4988 dev_state = qla4_8xxx_rd_direct(ha,4989 QLA8XXX_CRB_DEV_STATE);4990 ha->isp_ops->idc_unlock(ha);4991 if (dev_state == QLA8XXX_DEV_FAILED) {4992 ql4_printk(KERN_INFO, ha, "%s: don't retry "4993 "recover adapter. H/W is in Failed "4994 "state\n", __func__);4995 qla4xxx_dead_adapter_cleanup(ha);4996 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);4997 clear_bit(DPC_RESET_HA, &ha->dpc_flags);4998 clear_bit(DPC_RESET_HA_FW_CONTEXT,4999 &ha->dpc_flags);5000 status = QLA_ERROR;5001 5002 goto exit_recover;5003 }5004 }5005 5006 if (!test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags)) {5007 ha->retry_reset_ha_cnt = MAX_RESET_HA_RETRIES;5008 DEBUG2(printk("scsi%ld: recover adapter - retrying "5009 "(%d) more times\n", ha->host_no,5010 ha->retry_reset_ha_cnt));5011 set_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);5012 status = QLA_ERROR;5013 } else {5014 if (ha->retry_reset_ha_cnt > 0) {5015 /* Schedule another Reset HA--DPC will retry */5016 ha->retry_reset_ha_cnt--;5017 DEBUG2(printk("scsi%ld: recover adapter - "5018 "retry remaining %d\n",5019 ha->host_no,5020 ha->retry_reset_ha_cnt));5021 status = QLA_ERROR;5022 }5023 5024 if (ha->retry_reset_ha_cnt == 0) {5025 /* Recover adapter retries have been exhausted.5026 * Adapter DEAD */5027 DEBUG2(printk("scsi%ld: recover adapter "5028 "failed - board disabled\n",5029 ha->host_no));5030 qla4xxx_dead_adapter_cleanup(ha);5031 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);5032 clear_bit(DPC_RESET_HA, &ha->dpc_flags);5033 clear_bit(DPC_RESET_HA_FW_CONTEXT,5034 &ha->dpc_flags);5035 status = QLA_ERROR;5036 }5037 }5038 } else {5039 clear_bit(DPC_RESET_HA, &ha->dpc_flags);5040 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);5041 clear_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags);5042 }5043 5044exit_recover:5045 ha->adapter_error_count++;5046 5047 if (test_bit(AF_ONLINE, &ha->flags))5048 ha->isp_ops->enable_intrs(ha);5049 5050 scsi_unblock_requests(ha->host);5051 5052 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);5053 DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no,5054 status == QLA_ERROR ? "FAILED" : "SUCCEEDED"));5055 5056 return status;5057}5058 5059static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session)5060{5061 struct iscsi_session *sess;5062 struct ddb_entry *ddb_entry;5063 struct scsi_qla_host *ha;5064 5065 sess = cls_session->dd_data;5066 ddb_entry = sess->dd_data;5067 ha = ddb_entry->ha;5068 if (!iscsi_is_session_online(cls_session)) {5069 if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {5070 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"5071 " unblock session\n", ha->host_no, __func__,5072 ddb_entry->fw_ddb_index);5073 iscsi_unblock_session(ddb_entry->sess);5074 } else {5075 /* Trigger relogin */5076 if (ddb_entry->ddb_type == FLASH_DDB) {5077 if (!(test_bit(DF_RELOGIN, &ddb_entry->flags) ||5078 test_bit(DF_DISABLE_RELOGIN,5079 &ddb_entry->flags)))5080 qla4xxx_arm_relogin_timer(ddb_entry);5081 } else5082 iscsi_session_failure(cls_session->dd_data,5083 ISCSI_ERR_CONN_FAILED);5084 }5085 }5086}5087 5088int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session)5089{5090 struct iscsi_session *sess;5091 struct ddb_entry *ddb_entry;5092 struct scsi_qla_host *ha;5093 5094 sess = cls_session->dd_data;5095 ddb_entry = sess->dd_data;5096 ha = ddb_entry->ha;5097 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"5098 " unblock session\n", ha->host_no, __func__,5099 ddb_entry->fw_ddb_index);5100 5101 iscsi_unblock_session(ddb_entry->sess);5102 5103 /* Start scan target */5104 if (test_bit(AF_ONLINE, &ha->flags)) {5105 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"5106 " start scan\n", ha->host_no, __func__,5107 ddb_entry->fw_ddb_index);5108 queue_work(ddb_entry->sess->workq, &ddb_entry->sess->scan_work);5109 }5110 return QLA_SUCCESS;5111}5112 5113int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session)5114{5115 struct iscsi_session *sess;5116 struct ddb_entry *ddb_entry;5117 struct scsi_qla_host *ha;5118 int status = QLA_SUCCESS;5119 5120 sess = cls_session->dd_data;5121 ddb_entry = sess->dd_data;5122 ha = ddb_entry->ha;5123 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"5124 " unblock user space session\n", ha->host_no, __func__,5125 ddb_entry->fw_ddb_index);5126 5127 if (!iscsi_is_session_online(cls_session)) {5128 iscsi_conn_start(ddb_entry->conn);5129 iscsi_conn_login_event(ddb_entry->conn,5130 ISCSI_CONN_STATE_LOGGED_IN);5131 } else {5132 ql4_printk(KERN_INFO, ha,5133 "scsi%ld: %s: ddb[%d] session [%d] already logged in\n",5134 ha->host_no, __func__, ddb_entry->fw_ddb_index,5135 cls_session->sid);5136 status = QLA_ERROR;5137 }5138 5139 return status;5140}5141 5142static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)5143{5144 iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices);5145}5146 5147static void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)5148{5149 uint16_t relogin_timer;5150 struct iscsi_session *sess;5151 struct ddb_entry *ddb_entry;5152 struct scsi_qla_host *ha;5153 5154 sess = cls_sess->dd_data;5155 ddb_entry = sess->dd_data;5156 ha = ddb_entry->ha;5157 5158 relogin_timer = max(ddb_entry->default_relogin_timeout,5159 (uint16_t)RELOGIN_TOV);5160 atomic_set(&ddb_entry->relogin_timer, relogin_timer);5161 5162 DEBUG2(ql4_printk(KERN_INFO, ha,5163 "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no,5164 ddb_entry->fw_ddb_index, relogin_timer));5165 5166 qla4xxx_login_flash_ddb(cls_sess);5167}5168 5169static void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess)5170{5171 struct iscsi_session *sess;5172 struct ddb_entry *ddb_entry;5173 struct scsi_qla_host *ha;5174 5175 sess = cls_sess->dd_data;5176 ddb_entry = sess->dd_data;5177 ha = ddb_entry->ha;5178 5179 if (!(ddb_entry->ddb_type == FLASH_DDB))5180 return;5181 5182 if (test_bit(DF_DISABLE_RELOGIN, &ddb_entry->flags))5183 return;5184 5185 if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) &&5186 !iscsi_is_session_online(cls_sess)) {5187 DEBUG2(ql4_printk(KERN_INFO, ha,5188 "relogin issued\n"));5189 qla4xxx_relogin_flash_ddb(cls_sess);5190 }5191}5192 5193void qla4xxx_wake_dpc(struct scsi_qla_host *ha)5194{5195 if (ha->dpc_thread)5196 queue_work(ha->dpc_thread, &ha->dpc_work);5197}5198 5199static struct qla4_work_evt *5200qla4xxx_alloc_work(struct scsi_qla_host *ha, uint32_t data_size,5201 enum qla4_work_type type)5202{5203 struct qla4_work_evt *e;5204 uint32_t size = sizeof(struct qla4_work_evt) + data_size;5205 5206 e = kzalloc(size, GFP_ATOMIC);5207 if (!e)5208 return NULL;5209 5210 INIT_LIST_HEAD(&e->list);5211 e->type = type;5212 return e;5213}5214 5215static void qla4xxx_post_work(struct scsi_qla_host *ha,5216 struct qla4_work_evt *e)5217{5218 unsigned long flags;5219 5220 spin_lock_irqsave(&ha->work_lock, flags);5221 list_add_tail(&e->list, &ha->work_list);5222 spin_unlock_irqrestore(&ha->work_lock, flags);5223 qla4xxx_wake_dpc(ha);5224}5225 5226int qla4xxx_post_aen_work(struct scsi_qla_host *ha,5227 enum iscsi_host_event_code aen_code,5228 uint32_t data_size, uint8_t *data)5229{5230 struct qla4_work_evt *e;5231 5232 e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_AEN);5233 if (!e)5234 return QLA_ERROR;5235 5236 e->u.aen.code = aen_code;5237 e->u.aen.data_size = data_size;5238 memcpy(e->u.aen.data, data, data_size);5239 5240 qla4xxx_post_work(ha, e);5241 5242 return QLA_SUCCESS;5243}5244 5245int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,5246 uint32_t status, uint32_t pid,5247 uint32_t data_size, uint8_t *data)5248{5249 struct qla4_work_evt *e;5250 5251 e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_PING_STATUS);5252 if (!e)5253 return QLA_ERROR;5254 5255 e->u.ping.status = status;5256 e->u.ping.pid = pid;5257 e->u.ping.data_size = data_size;5258 memcpy(e->u.ping.data, data, data_size);5259 5260 qla4xxx_post_work(ha, e);5261 5262 return QLA_SUCCESS;5263}5264 5265static void qla4xxx_do_work(struct scsi_qla_host *ha)5266{5267 struct qla4_work_evt *e, *tmp;5268 unsigned long flags;5269 LIST_HEAD(work);5270 5271 spin_lock_irqsave(&ha->work_lock, flags);5272 list_splice_init(&ha->work_list, &work);5273 spin_unlock_irqrestore(&ha->work_lock, flags);5274 5275 list_for_each_entry_safe(e, tmp, &work, list) {5276 list_del_init(&e->list);5277 5278 switch (e->type) {5279 case QLA4_EVENT_AEN:5280 iscsi_post_host_event(ha->host_no,5281 &qla4xxx_iscsi_transport,5282 e->u.aen.code,5283 e->u.aen.data_size,5284 e->u.aen.data);5285 break;5286 case QLA4_EVENT_PING_STATUS:5287 iscsi_ping_comp_event(ha->host_no,5288 &qla4xxx_iscsi_transport,5289 e->u.ping.status,5290 e->u.ping.pid,5291 e->u.ping.data_size,5292 e->u.ping.data);5293 break;5294 default:5295 ql4_printk(KERN_WARNING, ha, "event type: 0x%x not "5296 "supported", e->type);5297 }5298 kfree(e);5299 }5300}5301 5302/**5303 * qla4xxx_do_dpc - dpc routine5304 * @work: Context to obtain pointer to host adapter structure.5305 *5306 * This routine is a task that is schedule by the interrupt handler5307 * to perform the background processing for interrupts. We put it5308 * on a task queue that is consumed whenever the scheduler runs; that's5309 * so you can do anything (i.e. put the process to sleep etc). In fact,5310 * the mid-level tries to sleep when it reaches the driver threshold5311 * "host->can_queue". This can cause a panic if we were in our interrupt code.5312 **/5313static void qla4xxx_do_dpc(struct work_struct *work)5314{5315 struct scsi_qla_host *ha =5316 container_of(work, struct scsi_qla_host, dpc_work);5317 int status = QLA_ERROR;5318 5319 DEBUG2(ql4_printk(KERN_INFO, ha,5320 "scsi%ld: %s: DPC handler waking up. flags = 0x%08lx, dpc_flags = 0x%08lx\n",5321 ha->host_no, __func__, ha->flags, ha->dpc_flags));5322 5323 /* Initialization not yet finished. Don't do anything yet. */5324 if (!test_bit(AF_INIT_DONE, &ha->flags))5325 return;5326 5327 if (test_bit(AF_EEH_BUSY, &ha->flags)) {5328 DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n",5329 ha->host_no, __func__, ha->flags));5330 return;5331 }5332 5333 /* post events to application */5334 qla4xxx_do_work(ha);5335 5336 if (is_qla80XX(ha)) {5337 if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {5338 if (is_qla8032(ha) || is_qla8042(ha)) {5339 ql4_printk(KERN_INFO, ha, "%s: disabling pause transmit on port 0 & 1.\n",5340 __func__);5341 /* disable pause frame for ISP83xx */5342 qla4_83xx_disable_pause(ha);5343 }5344 5345 ha->isp_ops->idc_lock(ha);5346 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,5347 QLA8XXX_DEV_FAILED);5348 ha->isp_ops->idc_unlock(ha);5349 ql4_printk(KERN_INFO, ha, "HW State: FAILED\n");5350 qla4_8xxx_device_state_handler(ha);5351 }5352 5353 if (test_bit(DPC_POST_IDC_ACK, &ha->dpc_flags)) {5354 if (is_qla8042(ha)) {5355 if (ha->idc_info.info2 &5356 ENABLE_INTERNAL_LOOPBACK) {5357 ql4_printk(KERN_INFO, ha, "%s: Disabling ACB\n",5358 __func__);5359 status = qla4_84xx_config_acb(ha,5360 ACB_CONFIG_DISABLE);5361 if (status != QLA_SUCCESS) {5362 ql4_printk(KERN_INFO, ha, "%s: ACB config failed\n",5363 __func__);5364 }5365 }5366 }5367 qla4_83xx_post_idc_ack(ha);5368 clear_bit(DPC_POST_IDC_ACK, &ha->dpc_flags);5369 }5370 5371 if (is_qla8042(ha) &&5372 test_bit(DPC_RESTORE_ACB, &ha->dpc_flags)) {5373 ql4_printk(KERN_INFO, ha, "%s: Restoring ACB\n",5374 __func__);5375 if (qla4_84xx_config_acb(ha, ACB_CONFIG_SET) !=5376 QLA_SUCCESS) {5377 ql4_printk(KERN_INFO, ha, "%s: ACB config failed ",5378 __func__);5379 }5380 clear_bit(DPC_RESTORE_ACB, &ha->dpc_flags);5381 }5382 5383 if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {5384 qla4_8xxx_need_qsnt_handler(ha);5385 }5386 }5387 5388 if (!test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) &&5389 (test_bit(DPC_RESET_HA, &ha->dpc_flags) ||5390 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||5391 test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags))) {5392 if ((is_qla8022(ha) && ql4xdontresethba) ||5393 ((is_qla8032(ha) || is_qla8042(ha)) &&5394 qla4_83xx_idc_dontreset(ha))) {5395 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",5396 ha->host_no, __func__));5397 clear_bit(DPC_RESET_HA, &ha->dpc_flags);5398 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);5399 clear_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);5400 goto dpc_post_reset_ha;5401 }5402 if (test_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags) ||5403 test_bit(DPC_RESET_HA, &ha->dpc_flags))5404 qla4xxx_recover_adapter(ha);5405 5406 if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {5407 uint8_t wait_time = RESET_INTR_TOV;5408 5409 while ((readw(&ha->reg->ctrl_status) &5410 (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {5411 if (--wait_time == 0)5412 break;5413 msleep(1000);5414 }5415 if (wait_time == 0)5416 DEBUG2(printk("scsi%ld: %s: SR|FSR "5417 "bit not cleared-- resetting\n",5418 ha->host_no, __func__));5419 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);5420 if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {5421 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);5422 status = qla4xxx_recover_adapter(ha);5423 }5424 clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);5425 if (status == QLA_SUCCESS)5426 ha->isp_ops->enable_intrs(ha);5427 }5428 }5429 5430dpc_post_reset_ha:5431 /* ---- process AEN? --- */5432 if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))5433 qla4xxx_process_aen(ha, PROCESS_ALL_AENS);5434 5435 /* ---- Get DHCP IP Address? --- */5436 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))5437 qla4xxx_get_dhcp_ip_address(ha);5438 5439 /* ---- relogin device? --- */5440 if (adapter_up(ha) &&5441 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {5442 iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin);5443 }5444 5445 /* ---- link change? --- */5446 if (!test_bit(AF_LOOPBACK, &ha->flags) &&5447 test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {5448 if (!test_bit(AF_LINK_UP, &ha->flags)) {5449 /* ---- link down? --- */5450 qla4xxx_mark_all_devices_missing(ha);5451 } else {5452 /* ---- link up? --- *5453 * F/W will auto login to all devices ONLY ONCE after5454 * link up during driver initialization and runtime5455 * fatal error recovery. Therefore, the driver must5456 * manually relogin to devices when recovering from5457 * connection failures, logouts, expired KATO, etc. */5458 if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) {5459 qla4xxx_build_ddb_list(ha, ha->is_reset);5460 iscsi_host_for_each_session(ha->host,5461 qla4xxx_login_flash_ddb);5462 } else5463 qla4xxx_relogin_all_devices(ha);5464 }5465 }5466 if (test_and_clear_bit(DPC_SYSFS_DDB_EXPORT, &ha->dpc_flags)) {5467 if (qla4xxx_sysfs_ddb_export(ha))5468 ql4_printk(KERN_ERR, ha, "%s: Error exporting ddb to sysfs\n",5469 __func__);5470 }5471}5472 5473/**5474 * qla4xxx_free_adapter - release the adapter5475 * @ha: pointer to adapter structure5476 **/5477static void qla4xxx_free_adapter(struct scsi_qla_host *ha)5478{5479 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);5480 5481 /* Turn-off interrupts on the card. */5482 ha->isp_ops->disable_intrs(ha);5483 5484 if (is_qla40XX(ha)) {5485 writel(set_rmask(CSR_SCSI_PROCESSOR_INTR),5486 &ha->reg->ctrl_status);5487 readl(&ha->reg->ctrl_status);5488 } else if (is_qla8022(ha)) {5489 writel(0, &ha->qla4_82xx_reg->host_int);5490 readl(&ha->qla4_82xx_reg->host_int);5491 } else if (is_qla8032(ha) || is_qla8042(ha)) {5492 writel(0, &ha->qla4_83xx_reg->risc_intr);5493 readl(&ha->qla4_83xx_reg->risc_intr);5494 }5495 5496 /* Remove timer thread, if present */5497 if (ha->timer_active)5498 qla4xxx_stop_timer(ha);5499 5500 /* Kill the kernel thread for this host */5501 if (ha->dpc_thread)5502 destroy_workqueue(ha->dpc_thread);5503 5504 /* Kill the kernel thread for this host */5505 if (ha->task_wq)5506 destroy_workqueue(ha->task_wq);5507 5508 /* Put firmware in known state */5509 ha->isp_ops->reset_firmware(ha);5510 5511 if (is_qla80XX(ha)) {5512 ha->isp_ops->idc_lock(ha);5513 qla4_8xxx_clear_drv_active(ha);5514 ha->isp_ops->idc_unlock(ha);5515 }5516 5517 /* Detach interrupts */5518 qla4xxx_free_irqs(ha);5519 5520 /* free extra memory */5521 qla4xxx_mem_free(ha);5522}5523 5524int qla4_8xxx_iospace_config(struct scsi_qla_host *ha)5525{5526 int status = 0;5527 unsigned long mem_base, mem_len;5528 struct pci_dev *pdev = ha->pdev;5529 5530 status = pci_request_regions(pdev, DRIVER_NAME);5531 if (status) {5532 printk(KERN_WARNING5533 "scsi(%ld) Failed to reserve PIO regions (%s) "5534 "status=%d\n", ha->host_no, pci_name(pdev), status);5535 goto iospace_error_exit;5536 }5537 5538 DEBUG2(printk(KERN_INFO "%s: revision-id=%d\n",5539 __func__, pdev->revision));5540 ha->revision_id = pdev->revision;5541 5542 /* remap phys address */5543 mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */5544 mem_len = pci_resource_len(pdev, 0);5545 DEBUG2(printk(KERN_INFO "%s: ioremap from %lx a size of %lx\n",5546 __func__, mem_base, mem_len));5547 5548 /* mapping of pcibase pointer */5549 ha->nx_pcibase = (unsigned long)ioremap(mem_base, mem_len);5550 if (!ha->nx_pcibase) {5551 printk(KERN_ERR5552 "cannot remap MMIO (%s), aborting\n", pci_name(pdev));5553 pci_release_regions(ha->pdev);5554 goto iospace_error_exit;5555 }5556 5557 /* Mapping of IO base pointer, door bell read and write pointer */5558 5559 /* mapping of IO base pointer */5560 if (is_qla8022(ha)) {5561 ha->qla4_82xx_reg = (struct device_reg_82xx __iomem *)5562 ((uint8_t *)ha->nx_pcibase + 0xbc000 +5563 (ha->pdev->devfn << 11));5564 ha->nx_db_wr_ptr = (ha->pdev->devfn == 4 ? QLA82XX_CAM_RAM_DB1 :5565 QLA82XX_CAM_RAM_DB2);5566 } else if (is_qla8032(ha) || is_qla8042(ha)) {5567 ha->qla4_83xx_reg = (struct device_reg_83xx __iomem *)5568 ((uint8_t *)ha->nx_pcibase);5569 }5570 5571 return 0;5572iospace_error_exit:5573 return -ENOMEM;5574}5575 5576/***5577 * qla4xxx_iospace_config - maps registers5578 * @ha: pointer to adapter structure5579 *5580 * This routines maps HBA's registers from the pci address space5581 * into the kernel virtual address space for memory mapped i/o.5582 **/5583int qla4xxx_iospace_config(struct scsi_qla_host *ha)5584{5585 unsigned long pio, pio_len, pio_flags;5586 unsigned long mmio, mmio_len, mmio_flags;5587 5588 pio = pci_resource_start(ha->pdev, 0);5589 pio_len = pci_resource_len(ha->pdev, 0);5590 pio_flags = pci_resource_flags(ha->pdev, 0);5591 if (pio_flags & IORESOURCE_IO) {5592 if (pio_len < MIN_IOBASE_LEN) {5593 ql4_printk(KERN_WARNING, ha,5594 "Invalid PCI I/O region size\n");5595 pio = 0;5596 }5597 } else {5598 ql4_printk(KERN_WARNING, ha, "region #0 not a PIO resource\n");5599 pio = 0;5600 }5601 5602 /* Use MMIO operations for all accesses. */5603 mmio = pci_resource_start(ha->pdev, 1);5604 mmio_len = pci_resource_len(ha->pdev, 1);5605 mmio_flags = pci_resource_flags(ha->pdev, 1);5606 5607 if (!(mmio_flags & IORESOURCE_MEM)) {5608 ql4_printk(KERN_ERR, ha,5609 "region #0 not an MMIO resource, aborting\n");5610 5611 goto iospace_error_exit;5612 }5613 5614 if (mmio_len < MIN_IOBASE_LEN) {5615 ql4_printk(KERN_ERR, ha,5616 "Invalid PCI mem region size, aborting\n");5617 goto iospace_error_exit;5618 }5619 5620 if (pci_request_regions(ha->pdev, DRIVER_NAME)) {5621 ql4_printk(KERN_WARNING, ha,5622 "Failed to reserve PIO/MMIO regions\n");5623 5624 goto iospace_error_exit;5625 }5626 5627 ha->pio_address = pio;5628 ha->pio_length = pio_len;5629 ha->reg = ioremap(mmio, MIN_IOBASE_LEN);5630 if (!ha->reg) {5631 ql4_printk(KERN_ERR, ha,5632 "cannot remap MMIO, aborting\n");5633 5634 goto iospace_error_exit;5635 }5636 5637 return 0;5638 5639iospace_error_exit:5640 return -ENOMEM;5641}5642 5643static struct isp_operations qla4xxx_isp_ops = {5644 .iospace_config = qla4xxx_iospace_config,5645 .pci_config = qla4xxx_pci_config,5646 .disable_intrs = qla4xxx_disable_intrs,5647 .enable_intrs = qla4xxx_enable_intrs,5648 .start_firmware = qla4xxx_start_firmware,5649 .intr_handler = qla4xxx_intr_handler,5650 .interrupt_service_routine = qla4xxx_interrupt_service_routine,5651 .reset_chip = qla4xxx_soft_reset,5652 .reset_firmware = qla4xxx_hw_reset,5653 .queue_iocb = qla4xxx_queue_iocb,5654 .complete_iocb = qla4xxx_complete_iocb,5655 .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out,5656 .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in,5657 .get_sys_info = qla4xxx_get_sys_info,5658 .queue_mailbox_command = qla4xxx_queue_mbox_cmd,5659 .process_mailbox_interrupt = qla4xxx_process_mbox_intr,5660};5661 5662static struct isp_operations qla4_82xx_isp_ops = {5663 .iospace_config = qla4_8xxx_iospace_config,5664 .pci_config = qla4_8xxx_pci_config,5665 .disable_intrs = qla4_82xx_disable_intrs,5666 .enable_intrs = qla4_82xx_enable_intrs,5667 .start_firmware = qla4_8xxx_load_risc,5668 .restart_firmware = qla4_82xx_try_start_fw,5669 .intr_handler = qla4_82xx_intr_handler,5670 .interrupt_service_routine = qla4_82xx_interrupt_service_routine,5671 .need_reset = qla4_8xxx_need_reset,5672 .reset_chip = qla4_82xx_isp_reset,5673 .reset_firmware = qla4_8xxx_stop_firmware,5674 .queue_iocb = qla4_82xx_queue_iocb,5675 .complete_iocb = qla4_82xx_complete_iocb,5676 .rd_shdw_req_q_out = qla4_82xx_rd_shdw_req_q_out,5677 .rd_shdw_rsp_q_in = qla4_82xx_rd_shdw_rsp_q_in,5678 .get_sys_info = qla4_8xxx_get_sys_info,5679 .rd_reg_direct = qla4_82xx_rd_32,5680 .wr_reg_direct = qla4_82xx_wr_32,5681 .rd_reg_indirect = qla4_82xx_md_rd_32,5682 .wr_reg_indirect = qla4_82xx_md_wr_32,5683 .idc_lock = qla4_82xx_idc_lock,5684 .idc_unlock = qla4_82xx_idc_unlock,5685 .rom_lock_recovery = qla4_82xx_rom_lock_recovery,5686 .queue_mailbox_command = qla4_82xx_queue_mbox_cmd,5687 .process_mailbox_interrupt = qla4_82xx_process_mbox_intr,5688};5689 5690static struct isp_operations qla4_83xx_isp_ops = {5691 .iospace_config = qla4_8xxx_iospace_config,5692 .pci_config = qla4_8xxx_pci_config,5693 .disable_intrs = qla4_83xx_disable_intrs,5694 .enable_intrs = qla4_83xx_enable_intrs,5695 .start_firmware = qla4_8xxx_load_risc,5696 .restart_firmware = qla4_83xx_start_firmware,5697 .intr_handler = qla4_83xx_intr_handler,5698 .interrupt_service_routine = qla4_83xx_interrupt_service_routine,5699 .need_reset = qla4_8xxx_need_reset,5700 .reset_chip = qla4_83xx_isp_reset,5701 .reset_firmware = qla4_8xxx_stop_firmware,5702 .queue_iocb = qla4_83xx_queue_iocb,5703 .complete_iocb = qla4_83xx_complete_iocb,5704 .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out,5705 .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in,5706 .get_sys_info = qla4_8xxx_get_sys_info,5707 .rd_reg_direct = qla4_83xx_rd_reg,5708 .wr_reg_direct = qla4_83xx_wr_reg,5709 .rd_reg_indirect = qla4_83xx_rd_reg_indirect,5710 .wr_reg_indirect = qla4_83xx_wr_reg_indirect,5711 .idc_lock = qla4_83xx_drv_lock,5712 .idc_unlock = qla4_83xx_drv_unlock,5713 .rom_lock_recovery = qla4_83xx_rom_lock_recovery,5714 .queue_mailbox_command = qla4_83xx_queue_mbox_cmd,5715 .process_mailbox_interrupt = qla4_83xx_process_mbox_intr,5716};5717 5718uint16_t qla4xxx_rd_shdw_req_q_out(struct scsi_qla_host *ha)5719{5720 return (uint16_t)le32_to_cpu(ha->shadow_regs->req_q_out);5721}5722 5723uint16_t qla4_82xx_rd_shdw_req_q_out(struct scsi_qla_host *ha)5724{5725 return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out));5726}5727 5728uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)5729{5730 return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in);5731}5732 5733uint16_t qla4_82xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)5734{5735 return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in));5736}5737 5738static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)5739{5740 struct scsi_qla_host *ha = data;5741 char *str = buf;5742 int rc;5743 5744 switch (type) {5745 case ISCSI_BOOT_ETH_FLAGS:5746 rc = sprintf(str, "%d\n", (char)SYSFS_FLAG_FW_SEL_BOOT);5747 break;5748 case ISCSI_BOOT_ETH_INDEX:5749 rc = sprintf(str, "0\n");5750 break;5751 case ISCSI_BOOT_ETH_MAC:5752 rc = sysfs_format_mac(str, ha->my_mac,5753 MAC_ADDR_LEN);5754 break;5755 default:5756 rc = -ENOSYS;5757 break;5758 }5759 return rc;5760}5761 5762static umode_t qla4xxx_eth_get_attr_visibility(void *data, int type)5763{5764 int rc;5765 5766 switch (type) {5767 case ISCSI_BOOT_ETH_FLAGS:5768 case ISCSI_BOOT_ETH_MAC:5769 case ISCSI_BOOT_ETH_INDEX:5770 rc = S_IRUGO;5771 break;5772 default:5773 rc = 0;5774 break;5775 }5776 return rc;5777}5778 5779static ssize_t qla4xxx_show_boot_ini_info(void *data, int type, char *buf)5780{5781 struct scsi_qla_host *ha = data;5782 char *str = buf;5783 int rc;5784 5785 switch (type) {5786 case ISCSI_BOOT_INI_INITIATOR_NAME:5787 rc = sprintf(str, "%s\n", ha->name_string);5788 break;5789 default:5790 rc = -ENOSYS;5791 break;5792 }5793 return rc;5794}5795 5796static umode_t qla4xxx_ini_get_attr_visibility(void *data, int type)5797{5798 int rc;5799 5800 switch (type) {5801 case ISCSI_BOOT_INI_INITIATOR_NAME:5802 rc = S_IRUGO;5803 break;5804 default:5805 rc = 0;5806 break;5807 }5808 return rc;5809}5810 5811static ssize_t5812qla4xxx_show_boot_tgt_info(struct ql4_boot_session_info *boot_sess, int type,5813 char *buf)5814{5815 struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];5816 char *str = buf;5817 int rc;5818 5819 switch (type) {5820 case ISCSI_BOOT_TGT_NAME:5821 rc = sprintf(buf, "%s\n", (char *)&boot_sess->target_name);5822 break;5823 case ISCSI_BOOT_TGT_IP_ADDR:5824 if (boot_sess->conn_list[0].dest_ipaddr.ip_type == 0x1)5825 rc = sprintf(buf, "%pI4\n",5826 &boot_conn->dest_ipaddr.ip_address);5827 else5828 rc = sprintf(str, "%pI6\n",5829 &boot_conn->dest_ipaddr.ip_address);5830 break;5831 case ISCSI_BOOT_TGT_PORT:5832 rc = sprintf(str, "%d\n", boot_conn->dest_port);5833 break;5834 case ISCSI_BOOT_TGT_CHAP_NAME:5835 rc = sprintf(str, "%.*s\n",5836 boot_conn->chap.target_chap_name_length,5837 (char *)&boot_conn->chap.target_chap_name);5838 break;5839 case ISCSI_BOOT_TGT_CHAP_SECRET:5840 rc = sprintf(str, "%.*s\n",5841 boot_conn->chap.target_secret_length,5842 (char *)&boot_conn->chap.target_secret);5843 break;5844 case ISCSI_BOOT_TGT_REV_CHAP_NAME:5845 rc = sprintf(str, "%.*s\n",5846 boot_conn->chap.intr_chap_name_length,5847 (char *)&boot_conn->chap.intr_chap_name);5848 break;5849 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:5850 rc = sprintf(str, "%.*s\n",5851 boot_conn->chap.intr_secret_length,5852 (char *)&boot_conn->chap.intr_secret);5853 break;5854 case ISCSI_BOOT_TGT_FLAGS:5855 rc = sprintf(str, "%d\n", (char)SYSFS_FLAG_FW_SEL_BOOT);5856 break;5857 case ISCSI_BOOT_TGT_NIC_ASSOC:5858 rc = sprintf(str, "0\n");5859 break;5860 default:5861 rc = -ENOSYS;5862 break;5863 }5864 return rc;5865}5866 5867static ssize_t qla4xxx_show_boot_tgt_pri_info(void *data, int type, char *buf)5868{5869 struct scsi_qla_host *ha = data;5870 struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_pri_sess);5871 5872 return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);5873}5874 5875static ssize_t qla4xxx_show_boot_tgt_sec_info(void *data, int type, char *buf)5876{5877 struct scsi_qla_host *ha = data;5878 struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_sec_sess);5879 5880 return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);5881}5882 5883static umode_t qla4xxx_tgt_get_attr_visibility(void *data, int type)5884{5885 int rc;5886 5887 switch (type) {5888 case ISCSI_BOOT_TGT_NAME:5889 case ISCSI_BOOT_TGT_IP_ADDR:5890 case ISCSI_BOOT_TGT_PORT:5891 case ISCSI_BOOT_TGT_CHAP_NAME:5892 case ISCSI_BOOT_TGT_CHAP_SECRET:5893 case ISCSI_BOOT_TGT_REV_CHAP_NAME:5894 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:5895 case ISCSI_BOOT_TGT_NIC_ASSOC:5896 case ISCSI_BOOT_TGT_FLAGS:5897 rc = S_IRUGO;5898 break;5899 default:5900 rc = 0;5901 break;5902 }5903 return rc;5904}5905 5906static void qla4xxx_boot_release(void *data)5907{5908 struct scsi_qla_host *ha = data;5909 5910 scsi_host_put(ha->host);5911}5912 5913static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])5914{5915 dma_addr_t buf_dma;5916 uint32_t addr, pri_addr, sec_addr;5917 uint32_t offset;5918 uint16_t func_num;5919 uint8_t val;5920 uint8_t *buf = NULL;5921 size_t size = 13 * sizeof(uint8_t);5922 int ret = QLA_SUCCESS;5923 5924 func_num = PCI_FUNC(ha->pdev->devfn);5925 5926 ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n",5927 __func__, ha->pdev->device, func_num);5928 5929 if (is_qla40XX(ha)) {5930 if (func_num == 1) {5931 addr = NVRAM_PORT0_BOOT_MODE;5932 pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;5933 sec_addr = NVRAM_PORT0_BOOT_SEC_TGT;5934 } else if (func_num == 3) {5935 addr = NVRAM_PORT1_BOOT_MODE;5936 pri_addr = NVRAM_PORT1_BOOT_PRI_TGT;5937 sec_addr = NVRAM_PORT1_BOOT_SEC_TGT;5938 } else {5939 ret = QLA_ERROR;5940 goto exit_boot_info;5941 }5942 5943 /* Check Boot Mode */5944 val = rd_nvram_byte(ha, addr);5945 if (!(val & 0x07)) {5946 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Adapter boot "5947 "options : 0x%x\n", __func__, val));5948 ret = QLA_ERROR;5949 goto exit_boot_info;5950 }5951 5952 /* get primary valid target index */5953 val = rd_nvram_byte(ha, pri_addr);5954 if (val & BIT_7)5955 ddb_index[0] = (val & 0x7f);5956 5957 /* get secondary valid target index */5958 val = rd_nvram_byte(ha, sec_addr);5959 if (val & BIT_7)5960 ddb_index[1] = (val & 0x7f);5961 goto exit_boot_info;5962 } else if (is_qla80XX(ha)) {5963 buf = dma_alloc_coherent(&ha->pdev->dev, size,5964 &buf_dma, GFP_KERNEL);5965 if (!buf) {5966 DEBUG2(ql4_printk(KERN_ERR, ha,5967 "%s: Unable to allocate dma buffer\n",5968 __func__));5969 ret = QLA_ERROR;5970 goto exit_boot_info;5971 }5972 5973 if (ha->port_num == 0)5974 offset = BOOT_PARAM_OFFSET_PORT0;5975 else if (ha->port_num == 1)5976 offset = BOOT_PARAM_OFFSET_PORT1;5977 else {5978 ret = QLA_ERROR;5979 goto exit_boot_info_free;5980 }5981 addr = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_iscsi_param * 4) +5982 offset;5983 if (qla4xxx_get_flash(ha, buf_dma, addr,5984 13 * sizeof(uint8_t)) != QLA_SUCCESS) {5985 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"5986 " failed\n", ha->host_no, __func__));5987 ret = QLA_ERROR;5988 goto exit_boot_info_free;5989 }5990 /* Check Boot Mode */5991 if (!(buf[1] & 0x07)) {5992 DEBUG2(ql4_printk(KERN_INFO, ha, "Firmware boot options"5993 " : 0x%x\n", buf[1]));5994 ret = QLA_ERROR;5995 goto exit_boot_info_free;5996 }5997 5998 /* get primary valid target index */5999 if (buf[2] & BIT_7)6000 ddb_index[0] = buf[2] & 0x7f;6001 6002 /* get secondary valid target index */6003 if (buf[11] & BIT_7)6004 ddb_index[1] = buf[11] & 0x7f;6005 } else {6006 ret = QLA_ERROR;6007 goto exit_boot_info;6008 }6009 6010 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary target ID %d, Secondary"6011 " target ID %d\n", __func__, ddb_index[0],6012 ddb_index[1]));6013 6014exit_boot_info_free:6015 dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);6016exit_boot_info:6017 ha->pri_ddb_idx = ddb_index[0];6018 ha->sec_ddb_idx = ddb_index[1];6019 return ret;6020}6021 6022/**6023 * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password6024 * @ha: pointer to adapter structure6025 * @username: CHAP username to be returned6026 * @password: CHAP password to be returned6027 *6028 * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP6029 * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/.6030 * So from the CHAP cache find the first BIDI CHAP entry and set it6031 * to the boot record in sysfs.6032 **/6033static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,6034 char *password)6035{6036 int i, ret = -EINVAL;6037 int max_chap_entries = 0;6038 struct ql4_chap_table *chap_table;6039 6040 if (is_qla80XX(ha))6041 max_chap_entries = (ha->hw.flt_chap_size / 2) /6042 sizeof(struct ql4_chap_table);6043 else6044 max_chap_entries = MAX_CHAP_ENTRIES_40XX;6045 6046 if (!ha->chap_list) {6047 ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");6048 return ret;6049 }6050 6051 mutex_lock(&ha->chap_sem);6052 for (i = 0; i < max_chap_entries; i++) {6053 chap_table = (struct ql4_chap_table *)ha->chap_list + i;6054 if (chap_table->cookie !=6055 cpu_to_le16(CHAP_VALID_COOKIE)) {6056 continue;6057 }6058 6059 if (chap_table->flags & BIT_7) /* local */6060 continue;6061 6062 if (!(chap_table->flags & BIT_6)) /* Not BIDI */6063 continue;6064 6065 strscpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);6066 strscpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);6067 ret = 0;6068 break;6069 }6070 mutex_unlock(&ha->chap_sem);6071 6072 return ret;6073}6074 6075 6076static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,6077 struct ql4_boot_session_info *boot_sess,6078 uint16_t ddb_index)6079{6080 struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];6081 struct dev_db_entry *fw_ddb_entry;6082 dma_addr_t fw_ddb_entry_dma;6083 uint16_t idx;6084 uint16_t options;6085 int ret = QLA_SUCCESS;6086 6087 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),6088 &fw_ddb_entry_dma, GFP_KERNEL);6089 if (!fw_ddb_entry) {6090 DEBUG2(ql4_printk(KERN_ERR, ha,6091 "%s: Unable to allocate dma buffer.\n",6092 __func__));6093 ret = QLA_ERROR;6094 return ret;6095 }6096 6097 if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry,6098 fw_ddb_entry_dma, ddb_index)) {6099 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: No Flash DDB found at "6100 "index [%d]\n", __func__, ddb_index));6101 ret = QLA_ERROR;6102 goto exit_boot_target;6103 }6104 6105 /* Update target name and IP from DDB */6106 memcpy(boot_sess->target_name, fw_ddb_entry->iscsi_name,6107 min(sizeof(boot_sess->target_name),6108 sizeof(fw_ddb_entry->iscsi_name)));6109 6110 options = le16_to_cpu(fw_ddb_entry->options);6111 if (options & DDB_OPT_IPV6_DEVICE) {6112 memcpy(&boot_conn->dest_ipaddr.ip_address,6113 &fw_ddb_entry->ip_addr[0], IPv6_ADDR_LEN);6114 } else {6115 boot_conn->dest_ipaddr.ip_type = 0x1;6116 memcpy(&boot_conn->dest_ipaddr.ip_address,6117 &fw_ddb_entry->ip_addr[0], IP_ADDR_LEN);6118 }6119 6120 boot_conn->dest_port = le16_to_cpu(fw_ddb_entry->port);6121 6122 /* update chap information */6123 idx = __le16_to_cpu(fw_ddb_entry->chap_tbl_idx);6124 6125 if (BIT_7 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {6126 6127 DEBUG2(ql4_printk(KERN_INFO, ha, "Setting chap\n"));6128 6129 ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.6130 target_chap_name,6131 (char *)&boot_conn->chap.target_secret,6132 idx);6133 if (ret) {6134 ql4_printk(KERN_ERR, ha, "Failed to set chap\n");6135 ret = QLA_ERROR;6136 goto exit_boot_target;6137 }6138 6139 boot_conn->chap.target_chap_name_length = QL4_CHAP_MAX_NAME_LEN;6140 boot_conn->chap.target_secret_length = QL4_CHAP_MAX_SECRET_LEN;6141 }6142 6143 if (BIT_4 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {6144 6145 DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));6146 6147 ret = qla4xxx_get_bidi_chap(ha,6148 (char *)&boot_conn->chap.intr_chap_name,6149 (char *)&boot_conn->chap.intr_secret);6150 6151 if (ret) {6152 ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");6153 ret = QLA_ERROR;6154 goto exit_boot_target;6155 }6156 6157 boot_conn->chap.intr_chap_name_length = QL4_CHAP_MAX_NAME_LEN;6158 boot_conn->chap.intr_secret_length = QL4_CHAP_MAX_SECRET_LEN;6159 }6160 6161exit_boot_target:6162 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),6163 fw_ddb_entry, fw_ddb_entry_dma);6164 return ret;6165}6166 6167static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)6168{6169 uint16_t ddb_index[2];6170 int ret = QLA_ERROR;6171 int rval;6172 6173 memset(ddb_index, 0, sizeof(ddb_index));6174 ddb_index[0] = 0xffff;6175 ddb_index[1] = 0xffff;6176 ret = get_fw_boot_info(ha, ddb_index);6177 if (ret != QLA_SUCCESS) {6178 DEBUG2(ql4_printk(KERN_INFO, ha,6179 "%s: No boot target configured.\n", __func__));6180 return ret;6181 }6182 6183 if (ql4xdisablesysfsboot)6184 return QLA_SUCCESS;6185 6186 if (ddb_index[0] == 0xffff)6187 goto sec_target;6188 6189 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),6190 ddb_index[0]);6191 if (rval != QLA_SUCCESS) {6192 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary boot target not "6193 "configured\n", __func__));6194 } else6195 ret = QLA_SUCCESS;6196 6197sec_target:6198 if (ddb_index[1] == 0xffff)6199 goto exit_get_boot_info;6200 6201 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),6202 ddb_index[1]);6203 if (rval != QLA_SUCCESS) {6204 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Secondary boot target not"6205 " configured\n", __func__));6206 } else6207 ret = QLA_SUCCESS;6208 6209exit_get_boot_info:6210 return ret;6211}6212 6213static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)6214{6215 struct iscsi_boot_kobj *boot_kobj;6216 6217 if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS)6218 return QLA_ERROR;6219 6220 if (ql4xdisablesysfsboot) {6221 ql4_printk(KERN_INFO, ha,6222 "%s: syfsboot disabled - driver will trigger login "6223 "and publish session for discovery .\n", __func__);6224 return QLA_SUCCESS;6225 }6226 6227 6228 ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no);6229 if (!ha->boot_kset)6230 goto kset_free;6231 6232 if (!scsi_host_get(ha->host))6233 goto kset_free;6234 boot_kobj = iscsi_boot_create_target(ha->boot_kset, 0, ha,6235 qla4xxx_show_boot_tgt_pri_info,6236 qla4xxx_tgt_get_attr_visibility,6237 qla4xxx_boot_release);6238 if (!boot_kobj)6239 goto put_host;6240 6241 if (!scsi_host_get(ha->host))6242 goto kset_free;6243 boot_kobj = iscsi_boot_create_target(ha->boot_kset, 1, ha,6244 qla4xxx_show_boot_tgt_sec_info,6245 qla4xxx_tgt_get_attr_visibility,6246 qla4xxx_boot_release);6247 if (!boot_kobj)6248 goto put_host;6249 6250 if (!scsi_host_get(ha->host))6251 goto kset_free;6252 boot_kobj = iscsi_boot_create_initiator(ha->boot_kset, 0, ha,6253 qla4xxx_show_boot_ini_info,6254 qla4xxx_ini_get_attr_visibility,6255 qla4xxx_boot_release);6256 if (!boot_kobj)6257 goto put_host;6258 6259 if (!scsi_host_get(ha->host))6260 goto kset_free;6261 boot_kobj = iscsi_boot_create_ethernet(ha->boot_kset, 0, ha,6262 qla4xxx_show_boot_eth_info,6263 qla4xxx_eth_get_attr_visibility,6264 qla4xxx_boot_release);6265 if (!boot_kobj)6266 goto put_host;6267 6268 return QLA_SUCCESS;6269 6270put_host:6271 scsi_host_put(ha->host);6272kset_free:6273 iscsi_boot_destroy_kset(ha->boot_kset);6274 return -ENOMEM;6275}6276 6277 6278static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry,6279 struct ql4_tuple_ddb *tddb)6280{6281 struct iscsi_cls_session *cls_sess;6282 struct iscsi_cls_conn *cls_conn;6283 struct iscsi_session *sess;6284 struct iscsi_conn *conn;6285 6286 DEBUG2(printk(KERN_INFO "Func: %s\n", __func__));6287 cls_sess = ddb_entry->sess;6288 sess = cls_sess->dd_data;6289 cls_conn = ddb_entry->conn;6290 conn = cls_conn->dd_data;6291 6292 tddb->tpgt = sess->tpgt;6293 tddb->port = conn->persistent_port;6294 strscpy(tddb->iscsi_name, sess->targetname, sizeof(tddb->iscsi_name));6295 strscpy(tddb->ip_addr, conn->persistent_address, sizeof(tddb->ip_addr));6296}6297 6298static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,6299 struct ql4_tuple_ddb *tddb,6300 uint8_t *flash_isid)6301{6302 uint16_t options = 0;6303 6304 tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);6305 memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],6306 min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name)));6307 6308 options = le16_to_cpu(fw_ddb_entry->options);6309 if (options & DDB_OPT_IPV6_DEVICE)6310 sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr);6311 else6312 sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);6313 6314 tddb->port = le16_to_cpu(fw_ddb_entry->port);6315 6316 if (flash_isid == NULL)6317 memcpy(&tddb->isid[0], &fw_ddb_entry->isid[0],6318 sizeof(tddb->isid));6319 else6320 memcpy(&tddb->isid[0], &flash_isid[0], sizeof(tddb->isid));6321}6322 6323static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,6324 struct ql4_tuple_ddb *old_tddb,6325 struct ql4_tuple_ddb *new_tddb,6326 uint8_t is_isid_compare)6327{6328 if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))6329 return QLA_ERROR;6330 6331 if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr))6332 return QLA_ERROR;6333 6334 if (old_tddb->port != new_tddb->port)6335 return QLA_ERROR;6336 6337 /* For multi sessions, driver generates the ISID, so do not compare6338 * ISID in reset path since it would be a comparison between the6339 * driver generated ISID and firmware generated ISID. This could6340 * lead to adding duplicated DDBs in the list as driver generated6341 * ISID would not match firmware generated ISID.6342 */6343 if (is_isid_compare) {6344 DEBUG2(ql4_printk(KERN_INFO, ha,6345 "%s: old ISID [%pmR] New ISID [%pmR]\n",6346 __func__, old_tddb->isid, new_tddb->isid));6347 6348 if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0],6349 sizeof(old_tddb->isid)))6350 return QLA_ERROR;6351 }6352 6353 DEBUG2(ql4_printk(KERN_INFO, ha,6354 "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]",6355 old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr,6356 old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt,6357 new_tddb->ip_addr, new_tddb->iscsi_name));6358 6359 return QLA_SUCCESS;6360}6361 6362static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,6363 struct dev_db_entry *fw_ddb_entry,6364 uint32_t *index)6365{6366 struct ddb_entry *ddb_entry;6367 struct ql4_tuple_ddb *fw_tddb = NULL;6368 struct ql4_tuple_ddb *tmp_tddb = NULL;6369 int idx;6370 int ret = QLA_ERROR;6371 6372 fw_tddb = vzalloc(sizeof(*fw_tddb));6373 if (!fw_tddb) {6374 DEBUG2(ql4_printk(KERN_WARNING, ha,6375 "Memory Allocation failed.\n"));6376 ret = QLA_SUCCESS;6377 goto exit_check;6378 }6379 6380 tmp_tddb = vzalloc(sizeof(*tmp_tddb));6381 if (!tmp_tddb) {6382 DEBUG2(ql4_printk(KERN_WARNING, ha,6383 "Memory Allocation failed.\n"));6384 ret = QLA_SUCCESS;6385 goto exit_check;6386 }6387 6388 qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb, NULL);6389 6390 for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {6391 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);6392 if (ddb_entry == NULL)6393 continue;6394 6395 qla4xxx_get_param_ddb(ddb_entry, tmp_tddb);6396 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) {6397 ret = QLA_SUCCESS; /* found */6398 if (index != NULL)6399 *index = idx;6400 goto exit_check;6401 }6402 }6403 6404exit_check:6405 vfree(fw_tddb);6406 vfree(tmp_tddb);6407 return ret;6408}6409 6410/**6411 * qla4xxx_check_existing_isid - check if target with same isid exist6412 * in target list6413 * @list_nt: list of target6414 * @isid: isid to check6415 *6416 * This routine return QLA_SUCCESS if target with same isid exist6417 **/6418static int qla4xxx_check_existing_isid(struct list_head *list_nt, uint8_t *isid)6419{6420 struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;6421 struct dev_db_entry *fw_ddb_entry;6422 6423 list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {6424 fw_ddb_entry = &nt_ddb_idx->fw_ddb;6425 6426 if (memcmp(&fw_ddb_entry->isid[0], &isid[0],6427 sizeof(nt_ddb_idx->fw_ddb.isid)) == 0) {6428 return QLA_SUCCESS;6429 }6430 }6431 return QLA_ERROR;6432}6433 6434/**6435 * qla4xxx_update_isid - compare ddbs and updated isid6436 * @ha: Pointer to host adapter structure.6437 * @list_nt: list of nt target6438 * @fw_ddb_entry: firmware ddb entry6439 *6440 * This routine update isid if ddbs have same iqn, same isid and6441 * different IP addr.6442 * Return QLA_SUCCESS if isid is updated.6443 **/6444static int qla4xxx_update_isid(struct scsi_qla_host *ha,6445 struct list_head *list_nt,6446 struct dev_db_entry *fw_ddb_entry)6447{6448 uint8_t base_value, i;6449 6450 base_value = fw_ddb_entry->isid[1] & 0x1f;6451 for (i = 0; i < 8; i++) {6452 fw_ddb_entry->isid[1] = (base_value | (i << 5));6453 if (qla4xxx_check_existing_isid(list_nt, fw_ddb_entry->isid))6454 break;6455 }6456 6457 if (!qla4xxx_check_existing_isid(list_nt, fw_ddb_entry->isid))6458 return QLA_ERROR;6459 6460 return QLA_SUCCESS;6461}6462 6463/**6464 * qla4xxx_should_update_isid - check if isid need to update6465 * @ha: Pointer to host adapter structure.6466 * @old_tddb: ddb tuple6467 * @new_tddb: ddb tuple6468 *6469 * Return QLA_SUCCESS if different IP, different PORT, same iqn,6470 * same isid6471 **/6472static int qla4xxx_should_update_isid(struct scsi_qla_host *ha,6473 struct ql4_tuple_ddb *old_tddb,6474 struct ql4_tuple_ddb *new_tddb)6475{6476 if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr) == 0) {6477 /* Same ip */6478 if (old_tddb->port == new_tddb->port)6479 return QLA_ERROR;6480 }6481 6482 if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))6483 /* different iqn */6484 return QLA_ERROR;6485 6486 if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0],6487 sizeof(old_tddb->isid)))6488 /* different isid */6489 return QLA_ERROR;6490 6491 return QLA_SUCCESS;6492}6493 6494/**6495 * qla4xxx_is_flash_ddb_exists - check if fw_ddb_entry already exists in list_nt6496 * @ha: Pointer to host adapter structure.6497 * @list_nt: list of nt target.6498 * @fw_ddb_entry: firmware ddb entry.6499 *6500 * This routine check if fw_ddb_entry already exists in list_nt to avoid6501 * duplicate ddb in list_nt.6502 * Return QLA_SUCCESS if duplicate ddb exit in list_nl.6503 * Note: This function also update isid of DDB if required.6504 **/6505 6506static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,6507 struct list_head *list_nt,6508 struct dev_db_entry *fw_ddb_entry)6509{6510 struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;6511 struct ql4_tuple_ddb *fw_tddb = NULL;6512 struct ql4_tuple_ddb *tmp_tddb = NULL;6513 int rval, ret = QLA_ERROR;6514 6515 fw_tddb = vzalloc(sizeof(*fw_tddb));6516 if (!fw_tddb) {6517 DEBUG2(ql4_printk(KERN_WARNING, ha,6518 "Memory Allocation failed.\n"));6519 ret = QLA_SUCCESS;6520 goto exit_check;6521 }6522 6523 tmp_tddb = vzalloc(sizeof(*tmp_tddb));6524 if (!tmp_tddb) {6525 DEBUG2(ql4_printk(KERN_WARNING, ha,6526 "Memory Allocation failed.\n"));6527 ret = QLA_SUCCESS;6528 goto exit_check;6529 }6530 6531 qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb, NULL);6532 6533 list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {6534 qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb,6535 nt_ddb_idx->flash_isid);6536 ret = qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, true);6537 /* found duplicate ddb */6538 if (ret == QLA_SUCCESS)6539 goto exit_check;6540 }6541 6542 list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {6543 qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb, NULL);6544 6545 ret = qla4xxx_should_update_isid(ha, tmp_tddb, fw_tddb);6546 if (ret == QLA_SUCCESS) {6547 rval = qla4xxx_update_isid(ha, list_nt, fw_ddb_entry);6548 if (rval == QLA_SUCCESS)6549 ret = QLA_ERROR;6550 else6551 ret = QLA_SUCCESS;6552 6553 goto exit_check;6554 }6555 }6556 6557exit_check:6558 vfree(fw_tddb);6559 vfree(tmp_tddb);6560 return ret;6561}6562 6563static void qla4xxx_free_ddb_list(struct list_head *list_ddb)6564{6565 struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;6566 6567 list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {6568 list_del_init(&ddb_idx->list);6569 vfree(ddb_idx);6570 }6571}6572 6573static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,6574 struct dev_db_entry *fw_ddb_entry)6575{6576 struct iscsi_endpoint *ep;6577 struct sockaddr_in *addr;6578 struct sockaddr_in6 *addr6;6579 struct sockaddr *t_addr;6580 struct sockaddr_storage *dst_addr;6581 char *ip;6582 6583 /* TODO: need to destroy on unload iscsi_endpoint*/6584 dst_addr = vmalloc(sizeof(*dst_addr));6585 if (!dst_addr)6586 return NULL;6587 6588 if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) {6589 t_addr = (struct sockaddr *)dst_addr;6590 t_addr->sa_family = AF_INET6;6591 addr6 = (struct sockaddr_in6 *)dst_addr;6592 ip = (char *)&addr6->sin6_addr;6593 memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN);6594 addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port));6595 6596 } else {6597 t_addr = (struct sockaddr *)dst_addr;6598 t_addr->sa_family = AF_INET;6599 addr = (struct sockaddr_in *)dst_addr;6600 ip = (char *)&addr->sin_addr;6601 memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN);6602 addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port));6603 }6604 6605 ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0);6606 vfree(dst_addr);6607 return ep;6608}6609 6610static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)6611{6612 if (ql4xdisablesysfsboot)6613 return QLA_SUCCESS;6614 if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx)6615 return QLA_ERROR;6616 return QLA_SUCCESS;6617}6618 6619static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,6620 struct ddb_entry *ddb_entry,6621 uint16_t idx)6622{6623 uint16_t def_timeout;6624 6625 ddb_entry->ddb_type = FLASH_DDB;6626 ddb_entry->fw_ddb_index = INVALID_ENTRY;6627 ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;6628 ddb_entry->ha = ha;6629 ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb;6630 ddb_entry->ddb_change = qla4xxx_flash_ddb_change;6631 ddb_entry->chap_tbl_idx = INVALID_ENTRY;6632 6633 atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);6634 atomic_set(&ddb_entry->relogin_timer, 0);6635 atomic_set(&ddb_entry->relogin_retry_count, 0);6636 def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);6637 ddb_entry->default_relogin_timeout =6638 (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ?6639 def_timeout : LOGIN_TOV;6640 ddb_entry->default_time2wait =6641 le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);6642 6643 if (ql4xdisablesysfsboot &&6644 (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx))6645 set_bit(DF_BOOT_TGT, &ddb_entry->flags);6646}6647 6648static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)6649{6650 uint32_t idx = 0;6651 uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */6652 uint32_t sts[MBOX_REG_COUNT];6653 uint32_t ip_state;6654 unsigned long wtime;6655 int ret;6656 6657 wtime = jiffies + (HZ * IP_CONFIG_TOV);6658 do {6659 for (idx = 0; idx < IP_ADDR_COUNT; idx++) {6660 if (ip_idx[idx] == -1)6661 continue;6662 6663 ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts);6664 6665 if (ret == QLA_ERROR) {6666 ip_idx[idx] = -1;6667 continue;6668 }6669 6670 ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT;6671 6672 DEBUG2(ql4_printk(KERN_INFO, ha,6673 "Waiting for IP state for idx = %d, state = 0x%x\n",6674 ip_idx[idx], ip_state));6675 if (ip_state == IP_ADDRSTATE_UNCONFIGURED ||6676 ip_state == IP_ADDRSTATE_INVALID ||6677 ip_state == IP_ADDRSTATE_PREFERRED ||6678 ip_state == IP_ADDRSTATE_DEPRICATED ||6679 ip_state == IP_ADDRSTATE_DISABLING)6680 ip_idx[idx] = -1;6681 }6682 6683 /* Break if all IP states checked */6684 if ((ip_idx[0] == -1) &&6685 (ip_idx[1] == -1) &&6686 (ip_idx[2] == -1) &&6687 (ip_idx[3] == -1))6688 break;6689 schedule_timeout_uninterruptible(HZ);6690 } while (time_after(wtime, jiffies));6691}6692 6693static int qla4xxx_cmp_fw_stentry(struct dev_db_entry *fw_ddb_entry,6694 struct dev_db_entry *flash_ddb_entry)6695{6696 uint16_t options = 0;6697 size_t ip_len = IP_ADDR_LEN;6698 6699 options = le16_to_cpu(fw_ddb_entry->options);6700 if (options & DDB_OPT_IPV6_DEVICE)6701 ip_len = IPv6_ADDR_LEN;6702 6703 if (memcmp(fw_ddb_entry->ip_addr, flash_ddb_entry->ip_addr, ip_len))6704 return QLA_ERROR;6705 6706 if (memcmp(&fw_ddb_entry->isid[0], &flash_ddb_entry->isid[0],6707 sizeof(fw_ddb_entry->isid)))6708 return QLA_ERROR;6709 6710 if (memcmp(&fw_ddb_entry->port, &flash_ddb_entry->port,6711 sizeof(fw_ddb_entry->port)))6712 return QLA_ERROR;6713 6714 return QLA_SUCCESS;6715}6716 6717static int qla4xxx_find_flash_st_idx(struct scsi_qla_host *ha,6718 struct dev_db_entry *fw_ddb_entry,6719 uint32_t fw_idx, uint32_t *flash_index)6720{6721 struct dev_db_entry *flash_ddb_entry;6722 dma_addr_t flash_ddb_entry_dma;6723 uint32_t idx = 0;6724 int max_ddbs;6725 int ret = QLA_ERROR, status;6726 6727 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :6728 MAX_DEV_DB_ENTRIES;6729 6730 flash_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,6731 &flash_ddb_entry_dma);6732 if (flash_ddb_entry == NULL || fw_ddb_entry == NULL) {6733 ql4_printk(KERN_ERR, ha, "Out of memory\n");6734 goto exit_find_st_idx;6735 }6736 6737 status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry,6738 flash_ddb_entry_dma, fw_idx);6739 if (status == QLA_SUCCESS) {6740 status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry);6741 if (status == QLA_SUCCESS) {6742 *flash_index = fw_idx;6743 ret = QLA_SUCCESS;6744 goto exit_find_st_idx;6745 }6746 }6747 6748 for (idx = 0; idx < max_ddbs; idx++) {6749 status = qla4xxx_flashdb_by_index(ha, flash_ddb_entry,6750 flash_ddb_entry_dma, idx);6751 if (status == QLA_ERROR)6752 continue;6753 6754 status = qla4xxx_cmp_fw_stentry(fw_ddb_entry, flash_ddb_entry);6755 if (status == QLA_SUCCESS) {6756 *flash_index = idx;6757 ret = QLA_SUCCESS;6758 goto exit_find_st_idx;6759 }6760 }6761 6762 if (idx == max_ddbs)6763 ql4_printk(KERN_ERR, ha, "Failed to find ST [%d] in flash\n",6764 fw_idx);6765 6766exit_find_st_idx:6767 if (flash_ddb_entry)6768 dma_pool_free(ha->fw_ddb_dma_pool, flash_ddb_entry,6769 flash_ddb_entry_dma);6770 6771 return ret;6772}6773 6774static void qla4xxx_build_st_list(struct scsi_qla_host *ha,6775 struct list_head *list_st)6776{6777 struct qla_ddb_index *st_ddb_idx;6778 int max_ddbs;6779 int fw_idx_size;6780 struct dev_db_entry *fw_ddb_entry;6781 dma_addr_t fw_ddb_dma;6782 int ret;6783 uint32_t idx = 0, next_idx = 0;6784 uint32_t state = 0, conn_err = 0;6785 uint32_t flash_index = -1;6786 uint16_t conn_id = 0;6787 6788 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,6789 &fw_ddb_dma);6790 if (fw_ddb_entry == NULL) {6791 DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));6792 goto exit_st_list;6793 }6794 6795 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :6796 MAX_DEV_DB_ENTRIES;6797 fw_idx_size = sizeof(struct qla_ddb_index);6798 6799 for (idx = 0; idx < max_ddbs; idx = next_idx) {6800 ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,6801 NULL, &next_idx, &state,6802 &conn_err, NULL, &conn_id);6803 if (ret == QLA_ERROR)6804 break;6805 6806 /* Ignore DDB if invalid state (unassigned) */6807 if (state == DDB_DS_UNASSIGNED)6808 goto continue_next_st;6809 6810 /* Check if ST, add to the list_st */6811 if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)6812 goto continue_next_st;6813 6814 st_ddb_idx = vzalloc(fw_idx_size);6815 if (!st_ddb_idx)6816 break;6817 6818 ret = qla4xxx_find_flash_st_idx(ha, fw_ddb_entry, idx,6819 &flash_index);6820 if (ret == QLA_ERROR) {6821 ql4_printk(KERN_ERR, ha,6822 "No flash entry for ST at idx [%d]\n", idx);6823 st_ddb_idx->flash_ddb_idx = idx;6824 } else {6825 ql4_printk(KERN_INFO, ha,6826 "ST at idx [%d] is stored at flash [%d]\n",6827 idx, flash_index);6828 st_ddb_idx->flash_ddb_idx = flash_index;6829 }6830 6831 st_ddb_idx->fw_ddb_idx = idx;6832 6833 list_add_tail(&st_ddb_idx->list, list_st);6834continue_next_st:6835 if (next_idx == 0)6836 break;6837 }6838 6839exit_st_list:6840 if (fw_ddb_entry)6841 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);6842}6843 6844/**6845 * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list6846 * @ha: pointer to adapter structure6847 * @list_ddb: List from which failed ddb to be removed6848 *6849 * Iterate over the list of DDBs and find and remove DDBs that are either in6850 * no connection active state or failed state6851 **/6852static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,6853 struct list_head *list_ddb)6854{6855 struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;6856 uint32_t next_idx = 0;6857 uint32_t state = 0, conn_err = 0;6858 int ret;6859 6860 list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {6861 ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,6862 NULL, 0, NULL, &next_idx, &state,6863 &conn_err, NULL, NULL);6864 if (ret == QLA_ERROR)6865 continue;6866 6867 if (state == DDB_DS_NO_CONNECTION_ACTIVE ||6868 state == DDB_DS_SESSION_FAILED) {6869 list_del_init(&ddb_idx->list);6870 vfree(ddb_idx);6871 }6872 }6873}6874 6875static void qla4xxx_update_sess_disc_idx(struct scsi_qla_host *ha,6876 struct ddb_entry *ddb_entry,6877 struct dev_db_entry *fw_ddb_entry)6878{6879 struct iscsi_cls_session *cls_sess;6880 struct iscsi_session *sess;6881 uint32_t max_ddbs = 0;6882 uint16_t ddb_link = -1;6883 6884 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :6885 MAX_DEV_DB_ENTRIES;6886 6887 cls_sess = ddb_entry->sess;6888 sess = cls_sess->dd_data;6889 6890 ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link);6891 if (ddb_link < max_ddbs)6892 sess->discovery_parent_idx = ddb_link;6893 else6894 sess->discovery_parent_idx = DDB_NO_LINK;6895}6896 6897static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,6898 struct dev_db_entry *fw_ddb_entry,6899 int is_reset, uint16_t idx)6900{6901 struct iscsi_cls_session *cls_sess;6902 struct iscsi_session *sess;6903 struct iscsi_cls_conn *cls_conn;6904 struct iscsi_endpoint *ep;6905 uint16_t cmds_max = 32;6906 uint16_t conn_id = 0;6907 uint32_t initial_cmdsn = 0;6908 int ret = QLA_SUCCESS;6909 6910 struct ddb_entry *ddb_entry = NULL;6911 6912 /* Create session object, with INVALID_ENTRY,6913 * the targer_id would get set when we issue the login6914 */6915 cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,6916 cmds_max, sizeof(struct ddb_entry),6917 sizeof(struct ql4_task_data),6918 initial_cmdsn, INVALID_ENTRY);6919 if (!cls_sess) {6920 ret = QLA_ERROR;6921 goto exit_setup;6922 }6923 6924 /*6925 * so calling module_put function to decrement the6926 * reference count.6927 **/6928 module_put(qla4xxx_iscsi_transport.owner);6929 sess = cls_sess->dd_data;6930 ddb_entry = sess->dd_data;6931 ddb_entry->sess = cls_sess;6932 6933 cls_sess->recovery_tmo = ql4xsess_recovery_tmo;6934 memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,6935 sizeof(struct dev_db_entry));6936 6937 qla4xxx_setup_flash_ddb_entry(ha, ddb_entry, idx);6938 6939 cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);6940 6941 if (!cls_conn) {6942 ret = QLA_ERROR;6943 goto exit_setup;6944 }6945 6946 ddb_entry->conn = cls_conn;6947 6948 /* Setup ep, for displaying attributes in sysfs */6949 ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);6950 if (ep) {6951 ep->conn = cls_conn;6952 cls_conn->ep = ep;6953 } else {6954 DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));6955 ret = QLA_ERROR;6956 goto exit_setup;6957 }6958 6959 /* Update sess/conn params */6960 qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);6961 qla4xxx_update_sess_disc_idx(ha, ddb_entry, fw_ddb_entry);6962 6963 if (is_reset == RESET_ADAPTER) {6964 iscsi_block_session(cls_sess);6965 /* Use the relogin path to discover new devices6966 * by short-circuiting the logic of setting6967 * timer to relogin - instead set the flags6968 * to initiate login right away.6969 */6970 set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);6971 set_bit(DF_RELOGIN, &ddb_entry->flags);6972 }6973 6974exit_setup:6975 return ret;6976}6977 6978static void qla4xxx_update_fw_ddb_link(struct scsi_qla_host *ha,6979 struct list_head *list_ddb,6980 struct dev_db_entry *fw_ddb_entry)6981{6982 struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;6983 uint16_t ddb_link;6984 6985 ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link);6986 6987 list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {6988 if (ddb_idx->fw_ddb_idx == ddb_link) {6989 DEBUG2(ql4_printk(KERN_INFO, ha,6990 "Updating NT parent idx from [%d] to [%d]\n",6991 ddb_link, ddb_idx->flash_ddb_idx));6992 fw_ddb_entry->ddb_link =6993 cpu_to_le16(ddb_idx->flash_ddb_idx);6994 return;6995 }6996 }6997}6998 6999static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,7000 struct list_head *list_nt,7001 struct list_head *list_st,7002 int is_reset)7003{7004 struct dev_db_entry *fw_ddb_entry;7005 struct ddb_entry *ddb_entry = NULL;7006 dma_addr_t fw_ddb_dma;7007 int max_ddbs;7008 int fw_idx_size;7009 int ret;7010 uint32_t idx = 0, next_idx = 0;7011 uint32_t state = 0, conn_err = 0;7012 uint32_t ddb_idx = -1;7013 uint16_t conn_id = 0;7014 uint16_t ddb_link = -1;7015 struct qla_ddb_index *nt_ddb_idx;7016 7017 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,7018 &fw_ddb_dma);7019 if (fw_ddb_entry == NULL) {7020 DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));7021 goto exit_nt_list;7022 }7023 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :7024 MAX_DEV_DB_ENTRIES;7025 fw_idx_size = sizeof(struct qla_ddb_index);7026 7027 for (idx = 0; idx < max_ddbs; idx = next_idx) {7028 ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,7029 NULL, &next_idx, &state,7030 &conn_err, NULL, &conn_id);7031 if (ret == QLA_ERROR)7032 break;7033 7034 if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)7035 goto continue_next_nt;7036 7037 /* Check if NT, then add to list it */7038 if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)7039 goto continue_next_nt;7040 7041 ddb_link = le16_to_cpu(fw_ddb_entry->ddb_link);7042 if (ddb_link < max_ddbs)7043 qla4xxx_update_fw_ddb_link(ha, list_st, fw_ddb_entry);7044 7045 if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||7046 state == DDB_DS_SESSION_FAILED) &&7047 (is_reset == INIT_ADAPTER))7048 goto continue_next_nt;7049 7050 DEBUG2(ql4_printk(KERN_INFO, ha,7051 "Adding DDB to session = 0x%x\n", idx));7052 7053 if (is_reset == INIT_ADAPTER) {7054 nt_ddb_idx = vmalloc(fw_idx_size);7055 if (!nt_ddb_idx)7056 break;7057 7058 nt_ddb_idx->fw_ddb_idx = idx;7059 7060 /* Copy original isid as it may get updated in function7061 * qla4xxx_update_isid(). We need original isid in7062 * function qla4xxx_compare_tuple_ddb to find duplicate7063 * target */7064 memcpy(&nt_ddb_idx->flash_isid[0],7065 &fw_ddb_entry->isid[0],7066 sizeof(nt_ddb_idx->flash_isid));7067 7068 ret = qla4xxx_is_flash_ddb_exists(ha, list_nt,7069 fw_ddb_entry);7070 if (ret == QLA_SUCCESS) {7071 /* free nt_ddb_idx and do not add to list_nt */7072 vfree(nt_ddb_idx);7073 goto continue_next_nt;7074 }7075 7076 /* Copy updated isid */7077 memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,7078 sizeof(struct dev_db_entry));7079 7080 list_add_tail(&nt_ddb_idx->list, list_nt);7081 } else if (is_reset == RESET_ADAPTER) {7082 ret = qla4xxx_is_session_exists(ha, fw_ddb_entry,7083 &ddb_idx);7084 if (ret == QLA_SUCCESS) {7085 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha,7086 ddb_idx);7087 if (ddb_entry != NULL)7088 qla4xxx_update_sess_disc_idx(ha,7089 ddb_entry,7090 fw_ddb_entry);7091 goto continue_next_nt;7092 }7093 }7094 7095 ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset, idx);7096 if (ret == QLA_ERROR)7097 goto exit_nt_list;7098 7099continue_next_nt:7100 if (next_idx == 0)7101 break;7102 }7103 7104exit_nt_list:7105 if (fw_ddb_entry)7106 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);7107}7108 7109static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha,7110 struct list_head *list_nt,7111 uint16_t target_id)7112{7113 struct dev_db_entry *fw_ddb_entry;7114 dma_addr_t fw_ddb_dma;7115 int max_ddbs;7116 int fw_idx_size;7117 int ret;7118 uint32_t idx = 0, next_idx = 0;7119 uint32_t state = 0, conn_err = 0;7120 uint16_t conn_id = 0;7121 struct qla_ddb_index *nt_ddb_idx;7122 7123 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,7124 &fw_ddb_dma);7125 if (fw_ddb_entry == NULL) {7126 DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));7127 goto exit_new_nt_list;7128 }7129 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :7130 MAX_DEV_DB_ENTRIES;7131 fw_idx_size = sizeof(struct qla_ddb_index);7132 7133 for (idx = 0; idx < max_ddbs; idx = next_idx) {7134 ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,7135 NULL, &next_idx, &state,7136 &conn_err, NULL, &conn_id);7137 if (ret == QLA_ERROR)7138 break;7139 7140 /* Check if NT, then add it to list */7141 if (strlen((char *)fw_ddb_entry->iscsi_name) == 0)7142 goto continue_next_new_nt;7143 7144 if (!(state == DDB_DS_NO_CONNECTION_ACTIVE))7145 goto continue_next_new_nt;7146 7147 DEBUG2(ql4_printk(KERN_INFO, ha,7148 "Adding DDB to session = 0x%x\n", idx));7149 7150 nt_ddb_idx = vmalloc(fw_idx_size);7151 if (!nt_ddb_idx)7152 break;7153 7154 nt_ddb_idx->fw_ddb_idx = idx;7155 7156 ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL);7157 if (ret == QLA_SUCCESS) {7158 /* free nt_ddb_idx and do not add to list_nt */7159 vfree(nt_ddb_idx);7160 goto continue_next_new_nt;7161 }7162 7163 if (target_id < max_ddbs)7164 fw_ddb_entry->ddb_link = cpu_to_le16(target_id);7165 7166 list_add_tail(&nt_ddb_idx->list, list_nt);7167 7168 ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER,7169 idx);7170 if (ret == QLA_ERROR)7171 goto exit_new_nt_list;7172 7173continue_next_new_nt:7174 if (next_idx == 0)7175 break;7176 }7177 7178exit_new_nt_list:7179 if (fw_ddb_entry)7180 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);7181}7182 7183/**7184 * qla4xxx_sysfs_ddb_is_non_persistent - check for non-persistence of ddb entry7185 * @dev: dev associated with the sysfs entry7186 * @data: pointer to flashnode session object7187 *7188 * Returns:7189 * 1: if flashnode entry is non-persistent7190 * 0: if flashnode entry is persistent7191 **/7192static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data)7193{7194 struct iscsi_bus_flash_session *fnode_sess;7195 7196 if (!iscsi_flashnode_bus_match(dev, NULL))7197 return 0;7198 7199 fnode_sess = iscsi_dev_to_flash_session(dev);7200 7201 return (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT);7202}7203 7204/**7205 * qla4xxx_sysfs_ddb_tgt_create - Create sysfs entry for target7206 * @ha: pointer to host7207 * @fw_ddb_entry: flash ddb data7208 * @idx: target index7209 * @user: if set then this call is made from userland else from kernel7210 *7211 * Returns:7212 * On sucess: QLA_SUCCESS7213 * On failure: QLA_ERROR7214 *7215 * This create separate sysfs entries for session and connection attributes of7216 * the given fw ddb entry.7217 * If this is invoked as a result of a userspace call then the entry is marked7218 * as nonpersistent using flash_state field.7219 **/7220static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,7221 struct dev_db_entry *fw_ddb_entry,7222 uint16_t *idx, int user)7223{7224 struct iscsi_bus_flash_session *fnode_sess = NULL;7225 struct iscsi_bus_flash_conn *fnode_conn = NULL;7226 int rc = QLA_ERROR;7227 7228 fnode_sess = iscsi_create_flashnode_sess(ha->host, *idx,7229 &qla4xxx_iscsi_transport, 0);7230 if (!fnode_sess) {7231 ql4_printk(KERN_ERR, ha,7232 "%s: Unable to create session sysfs entry for flashnode %d of host%lu\n",7233 __func__, *idx, ha->host_no);7234 goto exit_tgt_create;7235 }7236 7237 fnode_conn = iscsi_create_flashnode_conn(ha->host, fnode_sess,7238 &qla4xxx_iscsi_transport, 0);7239 if (!fnode_conn) {7240 ql4_printk(KERN_ERR, ha,7241 "%s: Unable to create conn sysfs entry for flashnode %d of host%lu\n",7242 __func__, *idx, ha->host_no);7243 goto free_sess;7244 }7245 7246 if (user) {7247 fnode_sess->flash_state = DEV_DB_NON_PERSISTENT;7248 } else {7249 fnode_sess->flash_state = DEV_DB_PERSISTENT;7250 7251 if (*idx == ha->pri_ddb_idx || *idx == ha->sec_ddb_idx)7252 fnode_sess->is_boot_target = 1;7253 else7254 fnode_sess->is_boot_target = 0;7255 }7256 7257 rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,7258 fw_ddb_entry);7259 if (rc)7260 goto free_sess;7261 7262 ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",7263 __func__, fnode_sess->dev.kobj.name);7264 7265 ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",7266 __func__, fnode_conn->dev.kobj.name);7267 7268 return QLA_SUCCESS;7269 7270free_sess:7271 iscsi_destroy_flashnode_sess(fnode_sess);7272 7273exit_tgt_create:7274 return QLA_ERROR;7275}7276 7277/**7278 * qla4xxx_sysfs_ddb_add - Add new ddb entry in flash7279 * @shost: pointer to host7280 * @buf: type of ddb entry (ipv4/ipv6)7281 * @len: length of buf7282 *7283 * This creates new ddb entry in the flash by finding first free index and7284 * storing default ddb there. And then create sysfs entry for the new ddb entry.7285 **/7286static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf,7287 int len)7288{7289 struct scsi_qla_host *ha = to_qla_host(shost);7290 struct dev_db_entry *fw_ddb_entry = NULL;7291 dma_addr_t fw_ddb_entry_dma;7292 struct device *dev;7293 uint16_t idx = 0;7294 uint16_t max_ddbs = 0;7295 uint32_t options = 0;7296 uint32_t rval = QLA_ERROR;7297 7298 if (strncasecmp(PORTAL_TYPE_IPV4, buf, 4) &&7299 strncasecmp(PORTAL_TYPE_IPV6, buf, 4)) {7300 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Invalid portal type\n",7301 __func__));7302 goto exit_ddb_add;7303 }7304 7305 max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :7306 MAX_DEV_DB_ENTRIES;7307 7308 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7309 &fw_ddb_entry_dma, GFP_KERNEL);7310 if (!fw_ddb_entry) {7311 DEBUG2(ql4_printk(KERN_ERR, ha,7312 "%s: Unable to allocate dma buffer\n",7313 __func__));7314 goto exit_ddb_add;7315 }7316 7317 dev = iscsi_find_flashnode_sess(ha->host, NULL,7318 qla4xxx_sysfs_ddb_is_non_persistent);7319 if (dev) {7320 ql4_printk(KERN_ERR, ha,7321 "%s: A non-persistent entry %s found\n",7322 __func__, dev->kobj.name);7323 put_device(dev);7324 goto exit_ddb_add;7325 }7326 7327 /* Index 0 and 1 are reserved for boot target entries */7328 for (idx = 2; idx < max_ddbs; idx++) {7329 if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry,7330 fw_ddb_entry_dma, idx))7331 break;7332 }7333 7334 if (idx == max_ddbs)7335 goto exit_ddb_add;7336 7337 if (!strncasecmp("ipv6", buf, 4))7338 options |= IPV6_DEFAULT_DDB_ENTRY;7339 7340 rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);7341 if (rval == QLA_ERROR)7342 goto exit_ddb_add;7343 7344 rval = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 1);7345 7346exit_ddb_add:7347 if (fw_ddb_entry)7348 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7349 fw_ddb_entry, fw_ddb_entry_dma);7350 if (rval == QLA_SUCCESS)7351 return idx;7352 else7353 return -EIO;7354}7355 7356/**7357 * qla4xxx_sysfs_ddb_apply - write the target ddb contents to Flash7358 * @fnode_sess: pointer to session attrs of flash ddb entry7359 * @fnode_conn: pointer to connection attrs of flash ddb entry7360 *7361 * This writes the contents of target ddb buffer to Flash with a valid cookie7362 * value in order to make the ddb entry persistent.7363 **/7364static int qla4xxx_sysfs_ddb_apply(struct iscsi_bus_flash_session *fnode_sess,7365 struct iscsi_bus_flash_conn *fnode_conn)7366{7367 struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);7368 struct scsi_qla_host *ha = to_qla_host(shost);7369 uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;7370 struct dev_db_entry *fw_ddb_entry = NULL;7371 dma_addr_t fw_ddb_entry_dma;7372 uint32_t options = 0;7373 int rval = 0;7374 7375 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7376 &fw_ddb_entry_dma, GFP_KERNEL);7377 if (!fw_ddb_entry) {7378 DEBUG2(ql4_printk(KERN_ERR, ha,7379 "%s: Unable to allocate dma buffer\n",7380 __func__));7381 rval = -ENOMEM;7382 goto exit_ddb_apply;7383 }7384 7385 if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))7386 options |= IPV6_DEFAULT_DDB_ENTRY;7387 7388 rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);7389 if (rval == QLA_ERROR)7390 goto exit_ddb_apply;7391 7392 dev_db_start_offset += (fnode_sess->target_id *7393 sizeof(*fw_ddb_entry));7394 7395 qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry);7396 fw_ddb_entry->cookie = DDB_VALID_COOKIE;7397 7398 rval = qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,7399 sizeof(*fw_ddb_entry), FLASH_OPT_RMW_COMMIT);7400 7401 if (rval == QLA_SUCCESS) {7402 fnode_sess->flash_state = DEV_DB_PERSISTENT;7403 ql4_printk(KERN_INFO, ha,7404 "%s: flash node %u of host %lu written to flash\n",7405 __func__, fnode_sess->target_id, ha->host_no);7406 } else {7407 rval = -EIO;7408 ql4_printk(KERN_ERR, ha,7409 "%s: Error while writing flash node %u of host %lu to flash\n",7410 __func__, fnode_sess->target_id, ha->host_no);7411 }7412 7413exit_ddb_apply:7414 if (fw_ddb_entry)7415 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7416 fw_ddb_entry, fw_ddb_entry_dma);7417 return rval;7418}7419 7420static ssize_t qla4xxx_sysfs_ddb_conn_open(struct scsi_qla_host *ha,7421 struct dev_db_entry *fw_ddb_entry,7422 uint16_t idx)7423{7424 struct dev_db_entry *ddb_entry = NULL;7425 dma_addr_t ddb_entry_dma;7426 unsigned long wtime;7427 uint32_t mbx_sts = 0;7428 uint32_t state = 0, conn_err = 0;7429 uint16_t tmo = 0;7430 int ret = 0;7431 7432 ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*ddb_entry),7433 &ddb_entry_dma, GFP_KERNEL);7434 if (!ddb_entry) {7435 DEBUG2(ql4_printk(KERN_ERR, ha,7436 "%s: Unable to allocate dma buffer\n",7437 __func__));7438 return QLA_ERROR;7439 }7440 7441 memcpy(ddb_entry, fw_ddb_entry, sizeof(*ddb_entry));7442 7443 ret = qla4xxx_set_ddb_entry(ha, idx, ddb_entry_dma, &mbx_sts);7444 if (ret != QLA_SUCCESS) {7445 DEBUG2(ql4_printk(KERN_ERR, ha,7446 "%s: Unable to set ddb entry for index %d\n",7447 __func__, idx));7448 goto exit_ddb_conn_open;7449 }7450 7451 qla4xxx_conn_open(ha, idx);7452 7453 /* To ensure that sendtargets is done, wait for at least 12 secs */7454 tmo = ((ha->def_timeout > LOGIN_TOV) &&7455 (ha->def_timeout < LOGIN_TOV * 10) ?7456 ha->def_timeout : LOGIN_TOV);7457 7458 DEBUG2(ql4_printk(KERN_INFO, ha,7459 "Default time to wait for login to ddb %d\n", tmo));7460 7461 wtime = jiffies + (HZ * tmo);7462 do {7463 ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL,7464 NULL, &state, &conn_err, NULL,7465 NULL);7466 if (ret == QLA_ERROR)7467 continue;7468 7469 if (state == DDB_DS_NO_CONNECTION_ACTIVE ||7470 state == DDB_DS_SESSION_FAILED)7471 break;7472 7473 schedule_timeout_uninterruptible(HZ / 10);7474 } while (time_after(wtime, jiffies));7475 7476exit_ddb_conn_open:7477 if (ddb_entry)7478 dma_free_coherent(&ha->pdev->dev, sizeof(*ddb_entry),7479 ddb_entry, ddb_entry_dma);7480 return ret;7481}7482 7483static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha,7484 struct dev_db_entry *fw_ddb_entry,7485 uint16_t target_id)7486{7487 struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;7488 struct list_head list_nt;7489 uint16_t ddb_index;7490 int ret = 0;7491 7492 if (test_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags)) {7493 ql4_printk(KERN_WARNING, ha,7494 "%s: A discovery already in progress!\n", __func__);7495 return QLA_ERROR;7496 }7497 7498 INIT_LIST_HEAD(&list_nt);7499 7500 set_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags);7501 7502 ret = qla4xxx_get_ddb_index(ha, &ddb_index);7503 if (ret == QLA_ERROR)7504 goto exit_login_st_clr_bit;7505 7506 ret = qla4xxx_sysfs_ddb_conn_open(ha, fw_ddb_entry, ddb_index);7507 if (ret == QLA_ERROR)7508 goto exit_login_st;7509 7510 qla4xxx_build_new_nt_list(ha, &list_nt, target_id);7511 7512 list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) {7513 list_del_init(&ddb_idx->list);7514 qla4xxx_clear_ddb_entry(ha, ddb_idx->fw_ddb_idx);7515 vfree(ddb_idx);7516 }7517 7518exit_login_st:7519 if (qla4xxx_clear_ddb_entry(ha, ddb_index) == QLA_ERROR) {7520 ql4_printk(KERN_ERR, ha,7521 "Unable to clear DDB index = 0x%x\n", ddb_index);7522 }7523 7524 clear_bit(ddb_index, ha->ddb_idx_map);7525 7526exit_login_st_clr_bit:7527 clear_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags);7528 return ret;7529}7530 7531static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha,7532 struct dev_db_entry *fw_ddb_entry,7533 uint16_t idx)7534{7535 int ret = QLA_ERROR;7536 7537 ret = qla4xxx_is_session_exists(ha, fw_ddb_entry, NULL);7538 if (ret != QLA_SUCCESS)7539 ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER,7540 idx);7541 else7542 ret = -EPERM;7543 7544 return ret;7545}7546 7547/**7548 * qla4xxx_sysfs_ddb_login - Login to the specified target7549 * @fnode_sess: pointer to session attrs of flash ddb entry7550 * @fnode_conn: pointer to connection attrs of flash ddb entry7551 *7552 * This logs in to the specified target7553 **/7554static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess,7555 struct iscsi_bus_flash_conn *fnode_conn)7556{7557 struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);7558 struct scsi_qla_host *ha = to_qla_host(shost);7559 struct dev_db_entry *fw_ddb_entry = NULL;7560 dma_addr_t fw_ddb_entry_dma;7561 uint32_t options = 0;7562 int ret = 0;7563 7564 if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) {7565 ql4_printk(KERN_ERR, ha,7566 "%s: Target info is not persistent\n", __func__);7567 ret = -EIO;7568 goto exit_ddb_login;7569 }7570 7571 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7572 &fw_ddb_entry_dma, GFP_KERNEL);7573 if (!fw_ddb_entry) {7574 DEBUG2(ql4_printk(KERN_ERR, ha,7575 "%s: Unable to allocate dma buffer\n",7576 __func__));7577 ret = -ENOMEM;7578 goto exit_ddb_login;7579 }7580 7581 if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))7582 options |= IPV6_DEFAULT_DDB_ENTRY;7583 7584 ret = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma);7585 if (ret == QLA_ERROR)7586 goto exit_ddb_login;7587 7588 qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry);7589 fw_ddb_entry->cookie = DDB_VALID_COOKIE;7590 7591 if (strlen((char *)fw_ddb_entry->iscsi_name) == 0)7592 ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry,7593 fnode_sess->target_id);7594 else7595 ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry,7596 fnode_sess->target_id);7597 7598 if (ret > 0)7599 ret = -EIO;7600 7601exit_ddb_login:7602 if (fw_ddb_entry)7603 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7604 fw_ddb_entry, fw_ddb_entry_dma);7605 return ret;7606}7607 7608/**7609 * qla4xxx_sysfs_ddb_logout_sid - Logout session for the specified target7610 * @cls_sess: pointer to session to be logged out7611 *7612 * This performs session log out from the specified target7613 **/7614static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess)7615{7616 struct iscsi_session *sess;7617 struct ddb_entry *ddb_entry = NULL;7618 struct scsi_qla_host *ha;7619 struct dev_db_entry *fw_ddb_entry = NULL;7620 dma_addr_t fw_ddb_entry_dma;7621 unsigned long flags;7622 unsigned long wtime;7623 uint32_t ddb_state;7624 int options;7625 int ret = 0;7626 7627 sess = cls_sess->dd_data;7628 ddb_entry = sess->dd_data;7629 ha = ddb_entry->ha;7630 7631 if (ddb_entry->ddb_type != FLASH_DDB) {7632 ql4_printk(KERN_ERR, ha, "%s: Not a flash node session\n",7633 __func__);7634 ret = -ENXIO;7635 goto exit_ddb_logout;7636 }7637 7638 if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) {7639 ql4_printk(KERN_ERR, ha,7640 "%s: Logout from boot target entry is not permitted.\n",7641 __func__);7642 ret = -EPERM;7643 goto exit_ddb_logout;7644 }7645 7646 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7647 &fw_ddb_entry_dma, GFP_KERNEL);7648 if (!fw_ddb_entry) {7649 ql4_printk(KERN_ERR, ha,7650 "%s: Unable to allocate dma buffer\n", __func__);7651 ret = -ENOMEM;7652 goto exit_ddb_logout;7653 }7654 7655 if (test_and_set_bit(DF_DISABLE_RELOGIN, &ddb_entry->flags))7656 goto ddb_logout_init;7657 7658 ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index,7659 fw_ddb_entry, fw_ddb_entry_dma,7660 NULL, NULL, &ddb_state, NULL,7661 NULL, NULL);7662 if (ret == QLA_ERROR)7663 goto ddb_logout_init;7664 7665 if (ddb_state == DDB_DS_SESSION_ACTIVE)7666 goto ddb_logout_init;7667 7668 /* wait until next relogin is triggered using DF_RELOGIN and7669 * clear DF_RELOGIN to avoid invocation of further relogin7670 */7671 wtime = jiffies + (HZ * RELOGIN_TOV);7672 do {7673 if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags))7674 goto ddb_logout_init;7675 7676 schedule_timeout_uninterruptible(HZ);7677 } while ((time_after(wtime, jiffies)));7678 7679ddb_logout_init:7680 atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);7681 atomic_set(&ddb_entry->relogin_timer, 0);7682 7683 options = LOGOUT_OPTION_CLOSE_SESSION;7684 qla4xxx_session_logout_ddb(ha, ddb_entry, options);7685 7686 memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));7687 wtime = jiffies + (HZ * LOGOUT_TOV);7688 do {7689 ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index,7690 fw_ddb_entry, fw_ddb_entry_dma,7691 NULL, NULL, &ddb_state, NULL,7692 NULL, NULL);7693 if (ret == QLA_ERROR)7694 goto ddb_logout_clr_sess;7695 7696 if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) ||7697 (ddb_state == DDB_DS_SESSION_FAILED))7698 goto ddb_logout_clr_sess;7699 7700 schedule_timeout_uninterruptible(HZ);7701 } while ((time_after(wtime, jiffies)));7702 7703ddb_logout_clr_sess:7704 qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);7705 /*7706 * we have decremented the reference count of the driver7707 * when we setup the session to have the driver unload7708 * to be seamless without actually destroying the7709 * session7710 **/7711 try_module_get(qla4xxx_iscsi_transport.owner);7712 iscsi_destroy_endpoint(ddb_entry->conn->ep);7713 7714 spin_lock_irqsave(&ha->hardware_lock, flags);7715 qla4xxx_free_ddb(ha, ddb_entry);7716 clear_bit(ddb_entry->fw_ddb_index, ha->ddb_idx_map);7717 spin_unlock_irqrestore(&ha->hardware_lock, flags);7718 7719 iscsi_session_teardown(ddb_entry->sess);7720 7721 clear_bit(DF_DISABLE_RELOGIN, &ddb_entry->flags);7722 ret = QLA_SUCCESS;7723 7724exit_ddb_logout:7725 if (fw_ddb_entry)7726 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),7727 fw_ddb_entry, fw_ddb_entry_dma);7728 return ret;7729}7730 7731/**7732 * qla4xxx_sysfs_ddb_logout - Logout from the specified target7733 * @fnode_sess: pointer to session attrs of flash ddb entry7734 * @fnode_conn: pointer to connection attrs of flash ddb entry7735 *7736 * This performs log out from the specified target7737 **/7738static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess,7739 struct iscsi_bus_flash_conn *fnode_conn)7740{7741 struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);7742 struct scsi_qla_host *ha = to_qla_host(shost);7743 struct ql4_tuple_ddb *flash_tddb = NULL;7744 struct ql4_tuple_ddb *tmp_tddb = NULL;7745 struct dev_db_entry *fw_ddb_entry = NULL;7746 struct ddb_entry *ddb_entry = NULL;7747 dma_addr_t fw_ddb_dma;7748 uint32_t next_idx = 0;7749 uint32_t state = 0, conn_err = 0;7750 uint16_t conn_id = 0;7751 int idx, index;7752 int status, ret = 0;7753 7754 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,7755 &fw_ddb_dma);7756 if (fw_ddb_entry == NULL) {7757 ql4_printk(KERN_ERR, ha, "%s:Out of memory\n", __func__);7758 ret = -ENOMEM;7759 goto exit_ddb_logout;7760 }7761 7762 flash_tddb = vzalloc(sizeof(*flash_tddb));7763 if (!flash_tddb) {7764 ql4_printk(KERN_WARNING, ha,7765 "%s:Memory Allocation failed.\n", __func__);7766 ret = -ENOMEM;7767 goto exit_ddb_logout;7768 }7769 7770 tmp_tddb = vzalloc(sizeof(*tmp_tddb));7771 if (!tmp_tddb) {7772 ql4_printk(KERN_WARNING, ha,7773 "%s:Memory Allocation failed.\n", __func__);7774 ret = -ENOMEM;7775 goto exit_ddb_logout;7776 }7777 7778 if (!fnode_sess->targetname) {7779 ql4_printk(KERN_ERR, ha,7780 "%s:Cannot logout from SendTarget entry\n",7781 __func__);7782 ret = -EPERM;7783 goto exit_ddb_logout;7784 }7785 7786 if (fnode_sess->is_boot_target) {7787 ql4_printk(KERN_ERR, ha,7788 "%s: Logout from boot target entry is not permitted.\n",7789 __func__);7790 ret = -EPERM;7791 goto exit_ddb_logout;7792 }7793 7794 strscpy(flash_tddb->iscsi_name, fnode_sess->targetname,7795 sizeof(flash_tddb->iscsi_name));7796 7797 if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))7798 sprintf(flash_tddb->ip_addr, "%pI6", fnode_conn->ipaddress);7799 else7800 sprintf(flash_tddb->ip_addr, "%pI4", fnode_conn->ipaddress);7801 7802 flash_tddb->tpgt = fnode_sess->tpgt;7803 flash_tddb->port = fnode_conn->port;7804 7805 COPY_ISID(flash_tddb->isid, fnode_sess->isid);7806 7807 for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {7808 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);7809 if (ddb_entry == NULL)7810 continue;7811 7812 if (ddb_entry->ddb_type != FLASH_DDB)7813 continue;7814 7815 index = ddb_entry->sess->target_id;7816 status = qla4xxx_get_fwddb_entry(ha, index, fw_ddb_entry,7817 fw_ddb_dma, NULL, &next_idx,7818 &state, &conn_err, NULL,7819 &conn_id);7820 if (status == QLA_ERROR) {7821 ret = -ENOMEM;7822 break;7823 }7824 7825 qla4xxx_convert_param_ddb(fw_ddb_entry, tmp_tddb, NULL);7826 7827 status = qla4xxx_compare_tuple_ddb(ha, flash_tddb, tmp_tddb,7828 true);7829 if (status == QLA_SUCCESS) {7830 ret = qla4xxx_sysfs_ddb_logout_sid(ddb_entry->sess);7831 break;7832 }7833 }7834 7835 if (idx == MAX_DDB_ENTRIES)7836 ret = -ESRCH;7837 7838exit_ddb_logout:7839 vfree(flash_tddb);7840 vfree(tmp_tddb);7841 if (fw_ddb_entry)7842 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);7843 7844 return ret;7845}7846 7847static int7848qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess,7849 int param, char *buf)7850{7851 struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);7852 struct scsi_qla_host *ha = to_qla_host(shost);7853 struct iscsi_bus_flash_conn *fnode_conn;7854 struct ql4_chap_table chap_tbl;7855 struct device *dev;7856 int parent_type;7857 int rc = 0;7858 7859 dev = iscsi_find_flashnode_conn(fnode_sess);7860 if (!dev)7861 return -EIO;7862 7863 fnode_conn = iscsi_dev_to_flash_conn(dev);7864 7865 switch (param) {7866 case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6:7867 rc = sprintf(buf, "%u\n", fnode_conn->is_fw_assigned_ipv6);7868 break;7869 case ISCSI_FLASHNODE_PORTAL_TYPE:7870 rc = sprintf(buf, "%s\n", fnode_sess->portal_type);7871 break;7872 case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE:7873 rc = sprintf(buf, "%u\n", fnode_sess->auto_snd_tgt_disable);7874 break;7875 case ISCSI_FLASHNODE_DISCOVERY_SESS:7876 rc = sprintf(buf, "%u\n", fnode_sess->discovery_sess);7877 break;7878 case ISCSI_FLASHNODE_ENTRY_EN:7879 rc = sprintf(buf, "%u\n", fnode_sess->entry_state);7880 break;7881 case ISCSI_FLASHNODE_HDR_DGST_EN:7882 rc = sprintf(buf, "%u\n", fnode_conn->hdrdgst_en);7883 break;7884 case ISCSI_FLASHNODE_DATA_DGST_EN:7885 rc = sprintf(buf, "%u\n", fnode_conn->datadgst_en);7886 break;7887 case ISCSI_FLASHNODE_IMM_DATA_EN:7888 rc = sprintf(buf, "%u\n", fnode_sess->imm_data_en);7889 break;7890 case ISCSI_FLASHNODE_INITIAL_R2T_EN:7891 rc = sprintf(buf, "%u\n", fnode_sess->initial_r2t_en);7892 break;7893 case ISCSI_FLASHNODE_DATASEQ_INORDER:7894 rc = sprintf(buf, "%u\n", fnode_sess->dataseq_inorder_en);7895 break;7896 case ISCSI_FLASHNODE_PDU_INORDER:7897 rc = sprintf(buf, "%u\n", fnode_sess->pdu_inorder_en);7898 break;7899 case ISCSI_FLASHNODE_CHAP_AUTH_EN:7900 rc = sprintf(buf, "%u\n", fnode_sess->chap_auth_en);7901 break;7902 case ISCSI_FLASHNODE_SNACK_REQ_EN:7903 rc = sprintf(buf, "%u\n", fnode_conn->snack_req_en);7904 break;7905 case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN:7906 rc = sprintf(buf, "%u\n", fnode_sess->discovery_logout_en);7907 break;7908 case ISCSI_FLASHNODE_BIDI_CHAP_EN:7909 rc = sprintf(buf, "%u\n", fnode_sess->bidi_chap_en);7910 break;7911 case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL:7912 rc = sprintf(buf, "%u\n", fnode_sess->discovery_auth_optional);7913 break;7914 case ISCSI_FLASHNODE_ERL:7915 rc = sprintf(buf, "%u\n", fnode_sess->erl);7916 break;7917 case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT:7918 rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_stat);7919 break;7920 case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE:7921 rc = sprintf(buf, "%u\n", fnode_conn->tcp_nagle_disable);7922 break;7923 case ISCSI_FLASHNODE_TCP_WSF_DISABLE:7924 rc = sprintf(buf, "%u\n", fnode_conn->tcp_wsf_disable);7925 break;7926 case ISCSI_FLASHNODE_TCP_TIMER_SCALE:7927 rc = sprintf(buf, "%u\n", fnode_conn->tcp_timer_scale);7928 break;7929 case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN:7930 rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_en);7931 break;7932 case ISCSI_FLASHNODE_IP_FRAG_DISABLE:7933 rc = sprintf(buf, "%u\n", fnode_conn->fragment_disable);7934 break;7935 case ISCSI_FLASHNODE_MAX_RECV_DLENGTH:7936 rc = sprintf(buf, "%u\n", fnode_conn->max_recv_dlength);7937 break;7938 case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH:7939 rc = sprintf(buf, "%u\n", fnode_conn->max_xmit_dlength);7940 break;7941 case ISCSI_FLASHNODE_FIRST_BURST:7942 rc = sprintf(buf, "%u\n", fnode_sess->first_burst);7943 break;7944 case ISCSI_FLASHNODE_DEF_TIME2WAIT:7945 rc = sprintf(buf, "%u\n", fnode_sess->time2wait);7946 break;7947 case ISCSI_FLASHNODE_DEF_TIME2RETAIN:7948 rc = sprintf(buf, "%u\n", fnode_sess->time2retain);7949 break;7950 case ISCSI_FLASHNODE_MAX_R2T:7951 rc = sprintf(buf, "%u\n", fnode_sess->max_r2t);7952 break;7953 case ISCSI_FLASHNODE_KEEPALIVE_TMO:7954 rc = sprintf(buf, "%u\n", fnode_conn->keepalive_timeout);7955 break;7956 case ISCSI_FLASHNODE_ISID:7957 rc = sprintf(buf, "%pm\n", fnode_sess->isid);7958 break;7959 case ISCSI_FLASHNODE_TSID:7960 rc = sprintf(buf, "%u\n", fnode_sess->tsid);7961 break;7962 case ISCSI_FLASHNODE_PORT:7963 rc = sprintf(buf, "%d\n", fnode_conn->port);7964 break;7965 case ISCSI_FLASHNODE_MAX_BURST:7966 rc = sprintf(buf, "%u\n", fnode_sess->max_burst);7967 break;7968 case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO:7969 rc = sprintf(buf, "%u\n",7970 fnode_sess->default_taskmgmt_timeout);7971 break;7972 case ISCSI_FLASHNODE_IPADDR:7973 if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))7974 rc = sprintf(buf, "%pI6\n", fnode_conn->ipaddress);7975 else7976 rc = sprintf(buf, "%pI4\n", fnode_conn->ipaddress);7977 break;7978 case ISCSI_FLASHNODE_ALIAS:7979 if (fnode_sess->targetalias)7980 rc = sprintf(buf, "%s\n", fnode_sess->targetalias);7981 else7982 rc = sprintf(buf, "\n");7983 break;7984 case ISCSI_FLASHNODE_REDIRECT_IPADDR:7985 if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))7986 rc = sprintf(buf, "%pI6\n",7987 fnode_conn->redirect_ipaddr);7988 else7989 rc = sprintf(buf, "%pI4\n",7990 fnode_conn->redirect_ipaddr);7991 break;7992 case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE:7993 rc = sprintf(buf, "%u\n", fnode_conn->max_segment_size);7994 break;7995 case ISCSI_FLASHNODE_LOCAL_PORT:7996 rc = sprintf(buf, "%u\n", fnode_conn->local_port);7997 break;7998 case ISCSI_FLASHNODE_IPV4_TOS:7999 rc = sprintf(buf, "%u\n", fnode_conn->ipv4_tos);8000 break;8001 case ISCSI_FLASHNODE_IPV6_TC:8002 if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))8003 rc = sprintf(buf, "%u\n",8004 fnode_conn->ipv6_traffic_class);8005 else8006 rc = sprintf(buf, "\n");8007 break;8008 case ISCSI_FLASHNODE_IPV6_FLOW_LABEL:8009 rc = sprintf(buf, "%u\n", fnode_conn->ipv6_flow_label);8010 break;8011 case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:8012 if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4))8013 rc = sprintf(buf, "%pI6\n",8014 fnode_conn->link_local_ipv6_addr);8015 else8016 rc = sprintf(buf, "\n");8017 break;8018 case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX:8019 rc = sprintf(buf, "%u\n", fnode_sess->discovery_parent_idx);8020 break;8021 case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE:8022 if (fnode_sess->discovery_parent_type == DDB_ISNS)8023 parent_type = ISCSI_DISC_PARENT_ISNS;8024 else if (fnode_sess->discovery_parent_type == DDB_NO_LINK)8025 parent_type = ISCSI_DISC_PARENT_UNKNOWN;8026 else if (fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES)8027 parent_type = ISCSI_DISC_PARENT_SENDTGT;8028 else8029 parent_type = ISCSI_DISC_PARENT_UNKNOWN;8030 8031 rc = sprintf(buf, "%s\n",8032 iscsi_get_discovery_parent_name(parent_type));8033 break;8034 case ISCSI_FLASHNODE_NAME:8035 if (fnode_sess->targetname)8036 rc = sprintf(buf, "%s\n", fnode_sess->targetname);8037 else8038 rc = sprintf(buf, "\n");8039 break;8040 case ISCSI_FLASHNODE_TPGT:8041 rc = sprintf(buf, "%u\n", fnode_sess->tpgt);8042 break;8043 case ISCSI_FLASHNODE_TCP_XMIT_WSF:8044 rc = sprintf(buf, "%u\n", fnode_conn->tcp_xmit_wsf);8045 break;8046 case ISCSI_FLASHNODE_TCP_RECV_WSF:8047 rc = sprintf(buf, "%u\n", fnode_conn->tcp_recv_wsf);8048 break;8049 case ISCSI_FLASHNODE_CHAP_OUT_IDX:8050 rc = sprintf(buf, "%u\n", fnode_sess->chap_out_idx);8051 break;8052 case ISCSI_FLASHNODE_USERNAME:8053 if (fnode_sess->chap_auth_en) {8054 qla4xxx_get_uni_chap_at_index(ha,8055 chap_tbl.name,8056 chap_tbl.secret,8057 fnode_sess->chap_out_idx);8058 rc = sprintf(buf, "%s\n", chap_tbl.name);8059 } else {8060 rc = sprintf(buf, "\n");8061 }8062 break;8063 case ISCSI_FLASHNODE_PASSWORD:8064 if (fnode_sess->chap_auth_en) {8065 qla4xxx_get_uni_chap_at_index(ha,8066 chap_tbl.name,8067 chap_tbl.secret,8068 fnode_sess->chap_out_idx);8069 rc = sprintf(buf, "%s\n", chap_tbl.secret);8070 } else {8071 rc = sprintf(buf, "\n");8072 }8073 break;8074 case ISCSI_FLASHNODE_STATSN:8075 rc = sprintf(buf, "%u\n", fnode_conn->statsn);8076 break;8077 case ISCSI_FLASHNODE_EXP_STATSN:8078 rc = sprintf(buf, "%u\n", fnode_conn->exp_statsn);8079 break;8080 case ISCSI_FLASHNODE_IS_BOOT_TGT:8081 rc = sprintf(buf, "%u\n", fnode_sess->is_boot_target);8082 break;8083 default:8084 rc = -ENOSYS;8085 break;8086 }8087 8088 put_device(dev);8089 return rc;8090}8091 8092/**8093 * qla4xxx_sysfs_ddb_set_param - Set parameter for firmware DDB entry8094 * @fnode_sess: pointer to session attrs of flash ddb entry8095 * @fnode_conn: pointer to connection attrs of flash ddb entry8096 * @data: Parameters and their values to update8097 * @len: len of data8098 *8099 * This sets the parameter of flash ddb entry and writes them to flash8100 **/8101static int8102qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess,8103 struct iscsi_bus_flash_conn *fnode_conn,8104 void *data, int len)8105{8106 struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);8107 struct scsi_qla_host *ha = to_qla_host(shost);8108 struct iscsi_flashnode_param_info *fnode_param;8109 struct ql4_chap_table chap_tbl;8110 struct nlattr *attr;8111 uint16_t chap_out_idx = INVALID_ENTRY;8112 int rc = QLA_ERROR;8113 uint32_t rem = len;8114 8115 memset((void *)&chap_tbl, 0, sizeof(chap_tbl));8116 nla_for_each_attr(attr, data, len, rem) {8117 if (nla_len(attr) < sizeof(*fnode_param)) {8118 rc = -EINVAL;8119 goto exit_set_param;8120 }8121 8122 fnode_param = nla_data(attr);8123 8124 switch (fnode_param->param) {8125 case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6:8126 fnode_conn->is_fw_assigned_ipv6 = fnode_param->value[0];8127 break;8128 case ISCSI_FLASHNODE_PORTAL_TYPE:8129 memcpy(fnode_sess->portal_type, fnode_param->value,8130 strlen(fnode_sess->portal_type));8131 break;8132 case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE:8133 fnode_sess->auto_snd_tgt_disable =8134 fnode_param->value[0];8135 break;8136 case ISCSI_FLASHNODE_DISCOVERY_SESS:8137 fnode_sess->discovery_sess = fnode_param->value[0];8138 break;8139 case ISCSI_FLASHNODE_ENTRY_EN:8140 fnode_sess->entry_state = fnode_param->value[0];8141 break;8142 case ISCSI_FLASHNODE_HDR_DGST_EN:8143 fnode_conn->hdrdgst_en = fnode_param->value[0];8144 break;8145 case ISCSI_FLASHNODE_DATA_DGST_EN:8146 fnode_conn->datadgst_en = fnode_param->value[0];8147 break;8148 case ISCSI_FLASHNODE_IMM_DATA_EN:8149 fnode_sess->imm_data_en = fnode_param->value[0];8150 break;8151 case ISCSI_FLASHNODE_INITIAL_R2T_EN:8152 fnode_sess->initial_r2t_en = fnode_param->value[0];8153 break;8154 case ISCSI_FLASHNODE_DATASEQ_INORDER:8155 fnode_sess->dataseq_inorder_en = fnode_param->value[0];8156 break;8157 case ISCSI_FLASHNODE_PDU_INORDER:8158 fnode_sess->pdu_inorder_en = fnode_param->value[0];8159 break;8160 case ISCSI_FLASHNODE_CHAP_AUTH_EN:8161 fnode_sess->chap_auth_en = fnode_param->value[0];8162 /* Invalidate chap index if chap auth is disabled */8163 if (!fnode_sess->chap_auth_en)8164 fnode_sess->chap_out_idx = INVALID_ENTRY;8165 8166 break;8167 case ISCSI_FLASHNODE_SNACK_REQ_EN:8168 fnode_conn->snack_req_en = fnode_param->value[0];8169 break;8170 case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN:8171 fnode_sess->discovery_logout_en = fnode_param->value[0];8172 break;8173 case ISCSI_FLASHNODE_BIDI_CHAP_EN:8174 fnode_sess->bidi_chap_en = fnode_param->value[0];8175 break;8176 case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL:8177 fnode_sess->discovery_auth_optional =8178 fnode_param->value[0];8179 break;8180 case ISCSI_FLASHNODE_ERL:8181 fnode_sess->erl = fnode_param->value[0];8182 break;8183 case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT:8184 fnode_conn->tcp_timestamp_stat = fnode_param->value[0];8185 break;8186 case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE:8187 fnode_conn->tcp_nagle_disable = fnode_param->value[0];8188 break;8189 case ISCSI_FLASHNODE_TCP_WSF_DISABLE:8190 fnode_conn->tcp_wsf_disable = fnode_param->value[0];8191 break;8192 case ISCSI_FLASHNODE_TCP_TIMER_SCALE:8193 fnode_conn->tcp_timer_scale = fnode_param->value[0];8194 break;8195 case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN:8196 fnode_conn->tcp_timestamp_en = fnode_param->value[0];8197 break;8198 case ISCSI_FLASHNODE_IP_FRAG_DISABLE:8199 fnode_conn->fragment_disable = fnode_param->value[0];8200 break;8201 case ISCSI_FLASHNODE_MAX_RECV_DLENGTH:8202 fnode_conn->max_recv_dlength =8203 *(unsigned *)fnode_param->value;8204 break;8205 case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH:8206 fnode_conn->max_xmit_dlength =8207 *(unsigned *)fnode_param->value;8208 break;8209 case ISCSI_FLASHNODE_FIRST_BURST:8210 fnode_sess->first_burst =8211 *(unsigned *)fnode_param->value;8212 break;8213 case ISCSI_FLASHNODE_DEF_TIME2WAIT:8214 fnode_sess->time2wait = *(uint16_t *)fnode_param->value;8215 break;8216 case ISCSI_FLASHNODE_DEF_TIME2RETAIN:8217 fnode_sess->time2retain =8218 *(uint16_t *)fnode_param->value;8219 break;8220 case ISCSI_FLASHNODE_MAX_R2T:8221 fnode_sess->max_r2t =8222 *(uint16_t *)fnode_param->value;8223 break;8224 case ISCSI_FLASHNODE_KEEPALIVE_TMO:8225 fnode_conn->keepalive_timeout =8226 *(uint16_t *)fnode_param->value;8227 break;8228 case ISCSI_FLASHNODE_ISID:8229 memcpy(fnode_sess->isid, fnode_param->value,8230 sizeof(fnode_sess->isid));8231 break;8232 case ISCSI_FLASHNODE_TSID:8233 fnode_sess->tsid = *(uint16_t *)fnode_param->value;8234 break;8235 case ISCSI_FLASHNODE_PORT:8236 fnode_conn->port = *(uint16_t *)fnode_param->value;8237 break;8238 case ISCSI_FLASHNODE_MAX_BURST:8239 fnode_sess->max_burst = *(unsigned *)fnode_param->value;8240 break;8241 case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO:8242 fnode_sess->default_taskmgmt_timeout =8243 *(uint16_t *)fnode_param->value;8244 break;8245 case ISCSI_FLASHNODE_IPADDR:8246 memcpy(fnode_conn->ipaddress, fnode_param->value,8247 IPv6_ADDR_LEN);8248 break;8249 case ISCSI_FLASHNODE_ALIAS:8250 rc = iscsi_switch_str_param(&fnode_sess->targetalias,8251 (char *)fnode_param->value);8252 break;8253 case ISCSI_FLASHNODE_REDIRECT_IPADDR:8254 memcpy(fnode_conn->redirect_ipaddr, fnode_param->value,8255 IPv6_ADDR_LEN);8256 break;8257 case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE:8258 fnode_conn->max_segment_size =8259 *(unsigned *)fnode_param->value;8260 break;8261 case ISCSI_FLASHNODE_LOCAL_PORT:8262 fnode_conn->local_port =8263 *(uint16_t *)fnode_param->value;8264 break;8265 case ISCSI_FLASHNODE_IPV4_TOS:8266 fnode_conn->ipv4_tos = fnode_param->value[0];8267 break;8268 case ISCSI_FLASHNODE_IPV6_TC:8269 fnode_conn->ipv6_traffic_class = fnode_param->value[0];8270 break;8271 case ISCSI_FLASHNODE_IPV6_FLOW_LABEL:8272 fnode_conn->ipv6_flow_label = fnode_param->value[0];8273 break;8274 case ISCSI_FLASHNODE_NAME:8275 rc = iscsi_switch_str_param(&fnode_sess->targetname,8276 (char *)fnode_param->value);8277 break;8278 case ISCSI_FLASHNODE_TPGT:8279 fnode_sess->tpgt = *(uint16_t *)fnode_param->value;8280 break;8281 case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:8282 memcpy(fnode_conn->link_local_ipv6_addr,8283 fnode_param->value, IPv6_ADDR_LEN);8284 break;8285 case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX:8286 fnode_sess->discovery_parent_idx =8287 *(uint16_t *)fnode_param->value;8288 break;8289 case ISCSI_FLASHNODE_TCP_XMIT_WSF:8290 fnode_conn->tcp_xmit_wsf =8291 *(uint8_t *)fnode_param->value;8292 break;8293 case ISCSI_FLASHNODE_TCP_RECV_WSF:8294 fnode_conn->tcp_recv_wsf =8295 *(uint8_t *)fnode_param->value;8296 break;8297 case ISCSI_FLASHNODE_STATSN:8298 fnode_conn->statsn = *(uint32_t *)fnode_param->value;8299 break;8300 case ISCSI_FLASHNODE_EXP_STATSN:8301 fnode_conn->exp_statsn =8302 *(uint32_t *)fnode_param->value;8303 break;8304 case ISCSI_FLASHNODE_CHAP_OUT_IDX:8305 chap_out_idx = *(uint16_t *)fnode_param->value;8306 if (!qla4xxx_get_uni_chap_at_index(ha,8307 chap_tbl.name,8308 chap_tbl.secret,8309 chap_out_idx)) {8310 fnode_sess->chap_out_idx = chap_out_idx;8311 /* Enable chap auth if chap index is valid */8312 fnode_sess->chap_auth_en = QL4_PARAM_ENABLE;8313 }8314 break;8315 default:8316 ql4_printk(KERN_ERR, ha,8317 "%s: No such sysfs attribute\n", __func__);8318 rc = -ENOSYS;8319 goto exit_set_param;8320 }8321 }8322 8323 rc = qla4xxx_sysfs_ddb_apply(fnode_sess, fnode_conn);8324 8325exit_set_param:8326 return rc;8327}8328 8329/**8330 * qla4xxx_sysfs_ddb_delete - Delete firmware DDB entry8331 * @fnode_sess: pointer to session attrs of flash ddb entry8332 *8333 * This invalidates the flash ddb entry at the given index8334 **/8335static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess)8336{8337 struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess);8338 struct scsi_qla_host *ha = to_qla_host(shost);8339 uint32_t dev_db_start_offset;8340 uint32_t dev_db_end_offset;8341 struct dev_db_entry *fw_ddb_entry = NULL;8342 dma_addr_t fw_ddb_entry_dma;8343 uint16_t *ddb_cookie = NULL;8344 size_t ddb_size = 0;8345 void *pddb = NULL;8346 int target_id;8347 int rc = 0;8348 8349 if (fnode_sess->is_boot_target) {8350 rc = -EPERM;8351 DEBUG2(ql4_printk(KERN_ERR, ha,8352 "%s: Deletion of boot target entry is not permitted.\n",8353 __func__));8354 goto exit_ddb_del;8355 }8356 8357 if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT)8358 goto sysfs_ddb_del;8359 8360 if (is_qla40XX(ha)) {8361 dev_db_start_offset = FLASH_OFFSET_DB_INFO;8362 dev_db_end_offset = FLASH_OFFSET_DB_END;8363 dev_db_start_offset += (fnode_sess->target_id *8364 sizeof(*fw_ddb_entry));8365 ddb_size = sizeof(*fw_ddb_entry);8366 } else {8367 dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +8368 (ha->hw.flt_region_ddb << 2);8369 /* flt_ddb_size is DDB table size for both ports8370 * so divide it by 2 to calculate the offset for second port8371 */8372 if (ha->port_num == 1)8373 dev_db_start_offset += (ha->hw.flt_ddb_size / 2);8374 8375 dev_db_end_offset = dev_db_start_offset +8376 (ha->hw.flt_ddb_size / 2);8377 8378 dev_db_start_offset += (fnode_sess->target_id *8379 sizeof(*fw_ddb_entry));8380 dev_db_start_offset += offsetof(struct dev_db_entry, cookie);8381 8382 ddb_size = sizeof(*ddb_cookie);8383 }8384 8385 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: start offset=%u, end offset=%u\n",8386 __func__, dev_db_start_offset, dev_db_end_offset));8387 8388 if (dev_db_start_offset > dev_db_end_offset) {8389 rc = -EIO;8390 DEBUG2(ql4_printk(KERN_ERR, ha, "%s:Invalid DDB index %u\n",8391 __func__, fnode_sess->target_id));8392 goto exit_ddb_del;8393 }8394 8395 pddb = dma_alloc_coherent(&ha->pdev->dev, ddb_size,8396 &fw_ddb_entry_dma, GFP_KERNEL);8397 if (!pddb) {8398 rc = -ENOMEM;8399 DEBUG2(ql4_printk(KERN_ERR, ha,8400 "%s: Unable to allocate dma buffer\n",8401 __func__));8402 goto exit_ddb_del;8403 }8404 8405 if (is_qla40XX(ha)) {8406 fw_ddb_entry = pddb;8407 memset(fw_ddb_entry, 0, ddb_size);8408 ddb_cookie = &fw_ddb_entry->cookie;8409 } else {8410 ddb_cookie = pddb;8411 }8412 8413 /* invalidate the cookie */8414 *ddb_cookie = 0xFFEE;8415 qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,8416 ddb_size, FLASH_OPT_RMW_COMMIT);8417 8418sysfs_ddb_del:8419 target_id = fnode_sess->target_id;8420 iscsi_destroy_flashnode_sess(fnode_sess);8421 ql4_printk(KERN_INFO, ha,8422 "%s: session and conn entries for flashnode %u of host %lu deleted\n",8423 __func__, target_id, ha->host_no);8424exit_ddb_del:8425 if (pddb)8426 dma_free_coherent(&ha->pdev->dev, ddb_size, pddb,8427 fw_ddb_entry_dma);8428 return rc;8429}8430 8431/**8432 * qla4xxx_sysfs_ddb_export - Create sysfs entries for firmware DDBs8433 * @ha: pointer to adapter structure8434 *8435 * Export the firmware DDB for all send targets and normal targets to sysfs.8436 **/8437int qla4xxx_sysfs_ddb_export(struct scsi_qla_host *ha)8438{8439 struct dev_db_entry *fw_ddb_entry = NULL;8440 dma_addr_t fw_ddb_entry_dma;8441 uint16_t max_ddbs;8442 uint16_t idx = 0;8443 int ret = QLA_SUCCESS;8444 8445 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,8446 sizeof(*fw_ddb_entry),8447 &fw_ddb_entry_dma, GFP_KERNEL);8448 if (!fw_ddb_entry) {8449 DEBUG2(ql4_printk(KERN_ERR, ha,8450 "%s: Unable to allocate dma buffer\n",8451 __func__));8452 return -ENOMEM;8453 }8454 8455 max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :8456 MAX_DEV_DB_ENTRIES;8457 8458 for (idx = 0; idx < max_ddbs; idx++) {8459 if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, fw_ddb_entry_dma,8460 idx))8461 continue;8462 8463 ret = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 0);8464 if (ret) {8465 ret = -EIO;8466 break;8467 }8468 }8469 8470 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,8471 fw_ddb_entry_dma);8472 8473 return ret;8474}8475 8476static void qla4xxx_sysfs_ddb_remove(struct scsi_qla_host *ha)8477{8478 iscsi_destroy_all_flashnode(ha->host);8479}8480 8481/**8482 * qla4xxx_build_ddb_list - Build ddb list and setup sessions8483 * @ha: pointer to adapter structure8484 * @is_reset: Is this init path or reset path8485 *8486 * Create a list of sendtargets (st) from firmware DDBs, issue send targets8487 * using connection open, then create the list of normal targets (nt)8488 * from firmware DDBs. Based on the list of nt setup session and connection8489 * objects.8490 **/8491void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)8492{8493 uint16_t tmo = 0;8494 struct list_head list_st, list_nt;8495 struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;8496 unsigned long wtime;8497 8498 if (!test_bit(AF_LINK_UP, &ha->flags)) {8499 set_bit(AF_BUILD_DDB_LIST, &ha->flags);8500 ha->is_reset = is_reset;8501 return;8502 }8503 8504 INIT_LIST_HEAD(&list_st);8505 INIT_LIST_HEAD(&list_nt);8506 8507 qla4xxx_build_st_list(ha, &list_st);8508 8509 /* Before issuing conn open mbox, ensure all IPs states are configured8510 * Note, conn open fails if IPs are not configured8511 */8512 qla4xxx_wait_for_ip_configuration(ha);8513 8514 /* Go thru the STs and fire the sendtargets by issuing conn open mbx */8515 list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {8516 qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);8517 }8518 8519 /* Wait to ensure all sendtargets are done for min 12 sec wait */8520 tmo = ((ha->def_timeout > LOGIN_TOV) &&8521 (ha->def_timeout < LOGIN_TOV * 10) ?8522 ha->def_timeout : LOGIN_TOV);8523 8524 DEBUG2(ql4_printk(KERN_INFO, ha,8525 "Default time to wait for build ddb %d\n", tmo));8526 8527 wtime = jiffies + (HZ * tmo);8528 do {8529 if (list_empty(&list_st))8530 break;8531 8532 qla4xxx_remove_failed_ddb(ha, &list_st);8533 schedule_timeout_uninterruptible(HZ / 10);8534 } while (time_after(wtime, jiffies));8535 8536 8537 qla4xxx_build_nt_list(ha, &list_nt, &list_st, is_reset);8538 8539 qla4xxx_free_ddb_list(&list_st);8540 qla4xxx_free_ddb_list(&list_nt);8541 8542 qla4xxx_free_ddb_index(ha);8543}8544 8545/**8546 * qla4xxx_wait_login_resp_boot_tgt - Wait for iSCSI boot target login8547 * response.8548 * @ha: pointer to adapter structure8549 *8550 * When the boot entry is normal iSCSI target then DF_BOOT_TGT flag will be8551 * set in DDB and we will wait for login response of boot targets during8552 * probe.8553 **/8554static void qla4xxx_wait_login_resp_boot_tgt(struct scsi_qla_host *ha)8555{8556 struct ddb_entry *ddb_entry;8557 struct dev_db_entry *fw_ddb_entry = NULL;8558 dma_addr_t fw_ddb_entry_dma;8559 unsigned long wtime;8560 uint32_t ddb_state;8561 int max_ddbs, idx, ret;8562 8563 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :8564 MAX_DEV_DB_ENTRIES;8565 8566 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),8567 &fw_ddb_entry_dma, GFP_KERNEL);8568 if (!fw_ddb_entry) {8569 ql4_printk(KERN_ERR, ha,8570 "%s: Unable to allocate dma buffer\n", __func__);8571 goto exit_login_resp;8572 }8573 8574 wtime = jiffies + (HZ * BOOT_LOGIN_RESP_TOV);8575 8576 for (idx = 0; idx < max_ddbs; idx++) {8577 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);8578 if (ddb_entry == NULL)8579 continue;8580 8581 if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) {8582 DEBUG2(ql4_printk(KERN_INFO, ha,8583 "%s: DDB index [%d]\n", __func__,8584 ddb_entry->fw_ddb_index));8585 do {8586 ret = qla4xxx_get_fwddb_entry(ha,8587 ddb_entry->fw_ddb_index,8588 fw_ddb_entry, fw_ddb_entry_dma,8589 NULL, NULL, &ddb_state, NULL,8590 NULL, NULL);8591 if (ret == QLA_ERROR)8592 goto exit_login_resp;8593 8594 if ((ddb_state == DDB_DS_SESSION_ACTIVE) ||8595 (ddb_state == DDB_DS_SESSION_FAILED))8596 break;8597 8598 schedule_timeout_uninterruptible(HZ);8599 8600 } while ((time_after(wtime, jiffies)));8601 8602 if (!time_after(wtime, jiffies)) {8603 DEBUG2(ql4_printk(KERN_INFO, ha,8604 "%s: Login response wait timer expired\n",8605 __func__));8606 goto exit_login_resp;8607 }8608 }8609 }8610 8611exit_login_resp:8612 if (fw_ddb_entry)8613 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),8614 fw_ddb_entry, fw_ddb_entry_dma);8615}8616 8617/**8618 * qla4xxx_probe_adapter - callback function to probe HBA8619 * @pdev: pointer to pci_dev structure8620 * @ent: pointer to pci_device entry8621 *8622 * This routine will probe for Qlogic 4xxx iSCSI host adapters.8623 * It returns zero if successful. It also initializes all data necessary for8624 * the driver.8625 **/8626static int qla4xxx_probe_adapter(struct pci_dev *pdev,8627 const struct pci_device_id *ent)8628{8629 int ret = -ENODEV, status;8630 struct Scsi_Host *host;8631 struct scsi_qla_host *ha;8632 uint8_t init_retry_count = 0;8633 char buf[34];8634 struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;8635 uint32_t dev_state;8636 8637 if (pci_enable_device(pdev))8638 return -1;8639 8640 host = iscsi_host_alloc(&qla4xxx_driver_template, sizeof(*ha), 0);8641 if (host == NULL) {8642 printk(KERN_WARNING8643 "qla4xxx: Couldn't allocate host from scsi layer!\n");8644 goto probe_disable_device;8645 }8646 8647 /* Clear our data area */8648 ha = to_qla_host(host);8649 memset(ha, 0, sizeof(*ha));8650 8651 /* Save the information from PCI BIOS. */8652 ha->pdev = pdev;8653 ha->host = host;8654 ha->host_no = host->host_no;8655 ha->func_num = PCI_FUNC(ha->pdev->devfn);8656 8657 /* Setup Runtime configurable options */8658 if (is_qla8022(ha)) {8659 ha->isp_ops = &qla4_82xx_isp_ops;8660 ha->reg_tbl = (uint32_t *) qla4_82xx_reg_tbl;8661 ha->qdr_sn_window = -1;8662 ha->ddr_mn_window = -1;8663 ha->curr_window = 255;8664 nx_legacy_intr = &legacy_intr[ha->func_num];8665 ha->nx_legacy_intr.int_vec_bit = nx_legacy_intr->int_vec_bit;8666 ha->nx_legacy_intr.tgt_status_reg =8667 nx_legacy_intr->tgt_status_reg;8668 ha->nx_legacy_intr.tgt_mask_reg = nx_legacy_intr->tgt_mask_reg;8669 ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;8670 } else if (is_qla8032(ha) || is_qla8042(ha)) {8671 ha->isp_ops = &qla4_83xx_isp_ops;8672 ha->reg_tbl = (uint32_t *)qla4_83xx_reg_tbl;8673 } else {8674 ha->isp_ops = &qla4xxx_isp_ops;8675 }8676 8677 if (is_qla80XX(ha)) {8678 rwlock_init(&ha->hw_lock);8679 ha->pf_bit = ha->func_num << 16;8680 /* Set EEH reset type to fundamental if required by hba */8681 pdev->needs_freset = 1;8682 }8683 8684 /* Configure PCI I/O space. */8685 ret = ha->isp_ops->iospace_config(ha);8686 if (ret)8687 goto probe_failed_ioconfig;8688 8689 ql4_printk(KERN_INFO, ha, "Found an ISP%04x, irq %d, iobase 0x%p\n",8690 pdev->device, pdev->irq, ha->reg);8691 8692 qla4xxx_config_dma_addressing(ha);8693 8694 /* Initialize lists and spinlocks. */8695 INIT_LIST_HEAD(&ha->free_srb_q);8696 8697 mutex_init(&ha->mbox_sem);8698 mutex_init(&ha->chap_sem);8699 init_completion(&ha->mbx_intr_comp);8700 init_completion(&ha->disable_acb_comp);8701 init_completion(&ha->idc_comp);8702 init_completion(&ha->link_up_comp);8703 8704 spin_lock_init(&ha->hardware_lock);8705 spin_lock_init(&ha->work_lock);8706 8707 /* Initialize work list */8708 INIT_LIST_HEAD(&ha->work_list);8709 8710 /* Allocate dma buffers */8711 if (qla4xxx_mem_alloc(ha)) {8712 ql4_printk(KERN_WARNING, ha,8713 "[ERROR] Failed to allocate memory for adapter\n");8714 8715 ret = -ENOMEM;8716 goto probe_failed;8717 }8718 8719 host->cmd_per_lun = 3;8720 host->max_channel = 0;8721 host->max_lun = MAX_LUNS - 1;8722 host->max_id = MAX_TARGETS;8723 host->max_cmd_len = IOCB_MAX_CDB_LEN;8724 host->can_queue = MAX_SRBS ;8725 host->transportt = qla4xxx_scsi_transport;8726 8727 pci_set_drvdata(pdev, ha);8728 8729 ret = scsi_add_host(host, &pdev->dev);8730 if (ret)8731 goto probe_failed;8732 8733 if (is_qla80XX(ha))8734 qla4_8xxx_get_flash_info(ha);8735 8736 if (is_qla8032(ha) || is_qla8042(ha)) {8737 qla4_83xx_read_reset_template(ha);8738 /*8739 * NOTE: If ql4dontresethba==1, set IDC_CTRL DONTRESET_BIT0.8740 * If DONRESET_BIT0 is set, drivers should not set dev_state8741 * to NEED_RESET. But if NEED_RESET is set, drivers should8742 * should honor the reset.8743 */8744 if (ql4xdontresethba == 1)8745 qla4_83xx_set_idc_dontreset(ha);8746 }8747 8748 /*8749 * Initialize the Host adapter request/response queues and8750 * firmware8751 * NOTE: interrupts enabled upon successful completion8752 */8753 status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);8754 8755 /* Dont retry adapter initialization if IRQ allocation failed */8756 if (is_qla80XX(ha) && (status == QLA_ERROR))8757 goto skip_retry_init;8758 8759 while ((!test_bit(AF_ONLINE, &ha->flags)) &&8760 init_retry_count++ < MAX_INIT_RETRIES) {8761 8762 if (is_qla80XX(ha)) {8763 ha->isp_ops->idc_lock(ha);8764 dev_state = qla4_8xxx_rd_direct(ha,8765 QLA8XXX_CRB_DEV_STATE);8766 ha->isp_ops->idc_unlock(ha);8767 if (dev_state == QLA8XXX_DEV_FAILED) {8768 ql4_printk(KERN_WARNING, ha, "%s: don't retry "8769 "initialize adapter. H/W is in failed state\n",8770 __func__);8771 break;8772 }8773 }8774 DEBUG2(printk("scsi: %s: retrying adapter initialization "8775 "(%d)\n", __func__, init_retry_count));8776 8777 if (ha->isp_ops->reset_chip(ha) == QLA_ERROR)8778 continue;8779 8780 status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER);8781 if (is_qla80XX(ha) && (status == QLA_ERROR)) {8782 if (qla4_8xxx_check_init_adapter_retry(ha) == QLA_ERROR)8783 goto skip_retry_init;8784 }8785 }8786 8787skip_retry_init:8788 if (!test_bit(AF_ONLINE, &ha->flags)) {8789 ql4_printk(KERN_WARNING, ha, "Failed to initialize adapter\n");8790 8791 if ((is_qla8022(ha) && ql4xdontresethba) ||8792 ((is_qla8032(ha) || is_qla8042(ha)) &&8793 qla4_83xx_idc_dontreset(ha))) {8794 /* Put the device in failed state. */8795 DEBUG2(printk(KERN_ERR "HW STATE: FAILED\n"));8796 ha->isp_ops->idc_lock(ha);8797 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,8798 QLA8XXX_DEV_FAILED);8799 ha->isp_ops->idc_unlock(ha);8800 }8801 ret = -ENODEV;8802 goto remove_host;8803 }8804 8805 /* Startup the kernel thread for this host adapter. */8806 DEBUG2(printk("scsi: %s: Starting kernel thread for "8807 "qla4xxx_dpc\n", __func__));8808 sprintf(buf, "qla4xxx_%lu_dpc", ha->host_no);8809 ha->dpc_thread = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, buf);8810 if (!ha->dpc_thread) {8811 ql4_printk(KERN_WARNING, ha, "Unable to start DPC thread!\n");8812 ret = -ENODEV;8813 goto remove_host;8814 }8815 INIT_WORK(&ha->dpc_work, qla4xxx_do_dpc);8816 8817 ha->task_wq = alloc_workqueue("qla4xxx_%lu_task", WQ_MEM_RECLAIM, 1,8818 ha->host_no);8819 if (!ha->task_wq) {8820 ql4_printk(KERN_WARNING, ha, "Unable to start task thread!\n");8821 ret = -ENODEV;8822 goto remove_host;8823 }8824 8825 /*8826 * For ISP-8XXX, request_irqs is called in qla4_8xxx_load_risc8827 * (which is called indirectly by qla4xxx_initialize_adapter),8828 * so that irqs will be registered after crbinit but before8829 * mbx_intr_enable.8830 */8831 if (is_qla40XX(ha)) {8832 ret = qla4xxx_request_irqs(ha);8833 if (ret) {8834 ql4_printk(KERN_WARNING, ha, "Failed to reserve "8835 "interrupt %d already in use.\n", pdev->irq);8836 goto remove_host;8837 }8838 }8839 8840 pci_save_state(ha->pdev);8841 ha->isp_ops->enable_intrs(ha);8842 8843 /* Start timer thread. */8844 qla4xxx_start_timer(ha, 1);8845 8846 set_bit(AF_INIT_DONE, &ha->flags);8847 8848 qla4_8xxx_alloc_sysfs_attr(ha);8849 8850 printk(KERN_INFO8851 " QLogic iSCSI HBA Driver version: %s\n"8852 " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n",8853 qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev),8854 ha->host_no, ha->fw_info.fw_major, ha->fw_info.fw_minor,8855 ha->fw_info.fw_patch, ha->fw_info.fw_build);8856 8857 /* Set the driver version */8858 if (is_qla80XX(ha))8859 qla4_8xxx_set_param(ha, SET_DRVR_VERSION);8860 8861 if (qla4xxx_setup_boot_info(ha))8862 ql4_printk(KERN_ERR, ha,8863 "%s: No iSCSI boot target configured\n", __func__);8864 8865 set_bit(DPC_SYSFS_DDB_EXPORT, &ha->dpc_flags);8866 /* Perform the build ddb list and login to each */8867 qla4xxx_build_ddb_list(ha, INIT_ADAPTER);8868 iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb);8869 qla4xxx_wait_login_resp_boot_tgt(ha);8870 8871 qla4xxx_create_chap_list(ha);8872 8873 qla4xxx_create_ifaces(ha);8874 return 0;8875 8876remove_host:8877 scsi_remove_host(ha->host);8878 8879probe_failed:8880 qla4xxx_free_adapter(ha);8881 8882probe_failed_ioconfig:8883 scsi_host_put(ha->host);8884 8885probe_disable_device:8886 pci_disable_device(pdev);8887 8888 return ret;8889}8890 8891/**8892 * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize8893 * @ha: pointer to adapter structure8894 *8895 * Mark the other ISP-4xxx port to indicate that the driver is being removed,8896 * so that the other port will not re-initialize while in the process of8897 * removing the ha due to driver unload or hba hotplug.8898 **/8899static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)8900{8901 struct scsi_qla_host *other_ha = NULL;8902 struct pci_dev *other_pdev = NULL;8903 int fn = ISP4XXX_PCI_FN_2;8904 8905 /*iscsi function numbers for ISP4xxx is 1 and 3*/8906 if (PCI_FUNC(ha->pdev->devfn) & BIT_1)8907 fn = ISP4XXX_PCI_FN_1;8908 8909 other_pdev =8910 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),8911 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),8912 fn));8913 8914 /* Get other_ha if other_pdev is valid and state is enable*/8915 if (other_pdev) {8916 if (atomic_read(&other_pdev->enable_cnt)) {8917 other_ha = pci_get_drvdata(other_pdev);8918 if (other_ha) {8919 set_bit(AF_HA_REMOVAL, &other_ha->flags);8920 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: "8921 "Prevent %s reinit\n", __func__,8922 dev_name(&other_ha->pdev->dev)));8923 }8924 }8925 pci_dev_put(other_pdev);8926 }8927}8928 8929static void qla4xxx_destroy_ddb(struct scsi_qla_host *ha,8930 struct ddb_entry *ddb_entry)8931{8932 struct dev_db_entry *fw_ddb_entry = NULL;8933 dma_addr_t fw_ddb_entry_dma;8934 unsigned long wtime;8935 uint32_t ddb_state;8936 int options;8937 int status;8938 8939 options = LOGOUT_OPTION_CLOSE_SESSION;8940 if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR) {8941 ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);8942 goto clear_ddb;8943 }8944 8945 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),8946 &fw_ddb_entry_dma, GFP_KERNEL);8947 if (!fw_ddb_entry) {8948 ql4_printk(KERN_ERR, ha,8949 "%s: Unable to allocate dma buffer\n", __func__);8950 goto clear_ddb;8951 }8952 8953 wtime = jiffies + (HZ * LOGOUT_TOV);8954 do {8955 status = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index,8956 fw_ddb_entry, fw_ddb_entry_dma,8957 NULL, NULL, &ddb_state, NULL,8958 NULL, NULL);8959 if (status == QLA_ERROR)8960 goto free_ddb;8961 8962 if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) ||8963 (ddb_state == DDB_DS_SESSION_FAILED))8964 goto free_ddb;8965 8966 schedule_timeout_uninterruptible(HZ);8967 } while ((time_after(wtime, jiffies)));8968 8969free_ddb:8970 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),8971 fw_ddb_entry, fw_ddb_entry_dma);8972clear_ddb:8973 qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);8974}8975 8976static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha)8977{8978 struct ddb_entry *ddb_entry;8979 int idx;8980 8981 for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) {8982 8983 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx);8984 if ((ddb_entry != NULL) &&8985 (ddb_entry->ddb_type == FLASH_DDB)) {8986 8987 qla4xxx_destroy_ddb(ha, ddb_entry);8988 /*8989 * we have decremented the reference count of the driver8990 * when we setup the session to have the driver unload8991 * to be seamless without actually destroying the8992 * session8993 **/8994 try_module_get(qla4xxx_iscsi_transport.owner);8995 iscsi_destroy_endpoint(ddb_entry->conn->ep);8996 qla4xxx_free_ddb(ha, ddb_entry);8997 iscsi_session_teardown(ddb_entry->sess);8998 }8999 }9000}9001/**9002 * qla4xxx_remove_adapter - callback function to remove adapter.9003 * @pdev: PCI device pointer9004 **/9005static void qla4xxx_remove_adapter(struct pci_dev *pdev)9006{9007 struct scsi_qla_host *ha;9008 9009 /*9010 * If the PCI device is disabled then it means probe_adapter had9011 * failed and resources already cleaned up on probe_adapter exit.9012 */9013 if (!pci_is_enabled(pdev))9014 return;9015 9016 ha = pci_get_drvdata(pdev);9017 9018 if (is_qla40XX(ha))9019 qla4xxx_prevent_other_port_reinit(ha);9020 9021 /* destroy iface from sysfs */9022 qla4xxx_destroy_ifaces(ha);9023 9024 if ((!ql4xdisablesysfsboot) && ha->boot_kset)9025 iscsi_boot_destroy_kset(ha->boot_kset);9026 9027 qla4xxx_destroy_fw_ddb_session(ha);9028 qla4_8xxx_free_sysfs_attr(ha);9029 9030 qla4xxx_sysfs_ddb_remove(ha);9031 scsi_remove_host(ha->host);9032 9033 qla4xxx_free_adapter(ha);9034 9035 scsi_host_put(ha->host);9036 9037 pci_disable_device(pdev);9038}9039 9040/**9041 * qla4xxx_config_dma_addressing() - Configure OS DMA addressing method.9042 * @ha: HA context9043 */9044static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)9045{9046 /* Update our PCI device dma_mask for full 64 bit mask */9047 if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) {9048 dev_dbg(&ha->pdev->dev,9049 "Failed to set 64 bit PCI consistent mask; "9050 "using 32 bit.\n");9051 dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(32));9052 }9053}9054 9055static int qla4xxx_slave_alloc(struct scsi_device *sdev)9056{9057 struct iscsi_cls_session *cls_sess;9058 struct iscsi_session *sess;9059 struct ddb_entry *ddb;9060 int queue_depth = QL4_DEF_QDEPTH;9061 9062 cls_sess = starget_to_session(sdev->sdev_target);9063 sess = cls_sess->dd_data;9064 ddb = sess->dd_data;9065 9066 sdev->hostdata = ddb;9067 9068 if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)9069 queue_depth = ql4xmaxqdepth;9070 9071 scsi_change_queue_depth(sdev, queue_depth);9072 return 0;9073}9074 9075/**9076 * qla4xxx_del_from_active_array - returns an active srb9077 * @ha: Pointer to host adapter structure.9078 * @index: index into the active_array9079 *9080 * This routine removes and returns the srb at the specified index9081 **/9082struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha,9083 uint32_t index)9084{9085 struct srb *srb = NULL;9086 struct scsi_cmnd *cmd = NULL;9087 9088 cmd = scsi_host_find_tag(ha->host, index);9089 if (!cmd)9090 return srb;9091 9092 srb = qla4xxx_cmd_priv(cmd)->srb;9093 if (!srb)9094 return srb;9095 9096 /* update counters */9097 if (srb->flags & SRB_DMA_VALID) {9098 ha->iocb_cnt -= srb->iocb_cnt;9099 if (srb->cmd)9100 srb->cmd->host_scribble =9101 (unsigned char *)(unsigned long) MAX_SRBS;9102 }9103 return srb;9104}9105 9106/**9107 * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware9108 * @ha: Pointer to host adapter structure.9109 * @cmd: Scsi Command to wait on.9110 *9111 * This routine waits for the command to be returned by the Firmware9112 * for some max time.9113 **/9114static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha,9115 struct scsi_cmnd *cmd)9116{9117 int done = 0;9118 struct srb *rp;9119 uint32_t max_wait_time = EH_WAIT_CMD_TOV;9120 int ret = SUCCESS;9121 9122 /* Dont wait on command if PCI error is being handled9123 * by PCI AER driver9124 */9125 if (unlikely(pci_channel_offline(ha->pdev)) ||9126 (test_bit(AF_EEH_BUSY, &ha->flags))) {9127 ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n",9128 ha->host_no, __func__);9129 return ret;9130 }9131 9132 do {9133 /* Checking to see if its returned to OS */9134 rp = qla4xxx_cmd_priv(cmd)->srb;9135 if (rp == NULL) {9136 done++;9137 break;9138 }9139 9140 msleep(2000);9141 } while (max_wait_time--);9142 9143 return done;9144}9145 9146/**9147 * qla4xxx_wait_for_hba_online - waits for HBA to come online9148 * @ha: Pointer to host adapter structure9149 **/9150static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)9151{9152 unsigned long wait_online;9153 9154 wait_online = jiffies + (HBA_ONLINE_TOV * HZ);9155 while (time_before(jiffies, wait_online)) {9156 9157 if (adapter_up(ha))9158 return QLA_SUCCESS;9159 9160 msleep(2000);9161 }9162 9163 return QLA_ERROR;9164}9165 9166/**9167 * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.9168 * @ha: pointer to HBA9169 * @stgt: pointer to SCSI target9170 * @sdev: pointer to SCSI device9171 *9172 * This function waits for all outstanding commands to a lun to complete. It9173 * returns 0 if all pending commands are returned and 1 otherwise.9174 **/9175static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,9176 struct scsi_target *stgt,9177 struct scsi_device *sdev)9178{9179 int cnt;9180 int status = 0;9181 struct scsi_cmnd *cmd;9182 9183 /*9184 * Waiting for all commands for the designated target or dev9185 * in the active array9186 */9187 for (cnt = 0; cnt < ha->host->can_queue; cnt++) {9188 cmd = scsi_host_find_tag(ha->host, cnt);9189 if (cmd && stgt == scsi_target(cmd->device) &&9190 (!sdev || sdev == cmd->device)) {9191 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {9192 status++;9193 break;9194 }9195 }9196 }9197 return status;9198}9199 9200/**9201 * qla4xxx_eh_abort - callback for abort task.9202 * @cmd: Pointer to Linux's SCSI command structure9203 *9204 * This routine is called by the Linux OS to abort the specified9205 * command.9206 **/9207static int qla4xxx_eh_abort(struct scsi_cmnd *cmd)9208{9209 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);9210 unsigned int id = cmd->device->id;9211 uint64_t lun = cmd->device->lun;9212 unsigned long flags;9213 struct srb *srb = NULL;9214 int ret = SUCCESS;9215 int wait = 0;9216 int rval;9217 9218 ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n",9219 ha->host_no, id, lun, cmd, cmd->cmnd[0]);9220 9221 rval = qla4xxx_isp_check_reg(ha);9222 if (rval != QLA_SUCCESS) {9223 ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");9224 return FAILED;9225 }9226 9227 spin_lock_irqsave(&ha->hardware_lock, flags);9228 srb = qla4xxx_cmd_priv(cmd)->srb;9229 if (!srb) {9230 spin_unlock_irqrestore(&ha->hardware_lock, flags);9231 ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Specified command has already completed.\n",9232 ha->host_no, id, lun);9233 return SUCCESS;9234 }9235 kref_get(&srb->srb_ref);9236 spin_unlock_irqrestore(&ha->hardware_lock, flags);9237 9238 if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) {9239 DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx failed.\n",9240 ha->host_no, id, lun));9241 ret = FAILED;9242 } else {9243 DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx success.\n",9244 ha->host_no, id, lun));9245 wait = 1;9246 }9247 9248 kref_put(&srb->srb_ref, qla4xxx_srb_compl);9249 9250 /* Wait for command to complete */9251 if (wait) {9252 if (!qla4xxx_eh_wait_on_command(ha, cmd)) {9253 DEBUG2(printk("scsi%ld:%d:%llu: Abort handler timed out\n",9254 ha->host_no, id, lun));9255 ret = FAILED;9256 }9257 }9258 9259 ql4_printk(KERN_INFO, ha,9260 "scsi%ld:%d:%llu: Abort command - %s\n",9261 ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed");9262 9263 return ret;9264}9265 9266/**9267 * qla4xxx_eh_device_reset - callback for target reset.9268 * @cmd: Pointer to Linux's SCSI command structure9269 *9270 * This routine is called by the Linux OS to reset all luns on the9271 * specified target.9272 **/9273static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)9274{9275 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);9276 struct ddb_entry *ddb_entry = cmd->device->hostdata;9277 int ret = FAILED, stat;9278 int rval;9279 9280 if (!ddb_entry)9281 return ret;9282 9283 ret = iscsi_block_scsi_eh(cmd);9284 if (ret)9285 return ret;9286 ret = FAILED;9287 9288 ql4_printk(KERN_INFO, ha,9289 "scsi%ld:%d:%d:%llu: DEVICE RESET ISSUED.\n", ha->host_no,9290 cmd->device->channel, cmd->device->id, cmd->device->lun);9291 9292 DEBUG2(printk(KERN_INFO9293 "scsi%ld: DEVICE_RESET cmd=%p jiffies = 0x%lx, to=%x,"9294 "dpc_flags=%lx, status=%x allowed=%d\n", ha->host_no,9295 cmd, jiffies, scsi_cmd_to_rq(cmd)->timeout / HZ,9296 ha->dpc_flags, cmd->result, cmd->allowed));9297 9298 rval = qla4xxx_isp_check_reg(ha);9299 if (rval != QLA_SUCCESS) {9300 ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");9301 return FAILED;9302 }9303 9304 /* FIXME: wait for hba to go online */9305 stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);9306 if (stat != QLA_SUCCESS) {9307 ql4_printk(KERN_INFO, ha, "DEVICE RESET FAILED. %d\n", stat);9308 goto eh_dev_reset_done;9309 }9310 9311 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),9312 cmd->device)) {9313 ql4_printk(KERN_INFO, ha,9314 "DEVICE RESET FAILED - waiting for "9315 "commands.\n");9316 goto eh_dev_reset_done;9317 }9318 9319 /* Send marker. */9320 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,9321 MM_LUN_RESET) != QLA_SUCCESS)9322 goto eh_dev_reset_done;9323 9324 ql4_printk(KERN_INFO, ha,9325 "scsi(%ld:%d:%d:%llu): DEVICE RESET SUCCEEDED.\n",9326 ha->host_no, cmd->device->channel, cmd->device->id,9327 cmd->device->lun);9328 9329 ret = SUCCESS;9330 9331eh_dev_reset_done:9332 9333 return ret;9334}9335 9336/**9337 * qla4xxx_eh_target_reset - callback for target reset.9338 * @cmd: Pointer to Linux's SCSI command structure9339 *9340 * This routine is called by the Linux OS to reset the target.9341 **/9342static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)9343{9344 struct scsi_qla_host *ha = to_qla_host(cmd->device->host);9345 struct ddb_entry *ddb_entry = cmd->device->hostdata;9346 int stat, ret;9347 int rval;9348 9349 if (!ddb_entry)9350 return FAILED;9351 9352 ret = iscsi_block_scsi_eh(cmd);9353 if (ret)9354 return ret;9355 9356 starget_printk(KERN_INFO, scsi_target(cmd->device),9357 "WARM TARGET RESET ISSUED.\n");9358 9359 DEBUG2(printk(KERN_INFO9360 "scsi%ld: TARGET_DEVICE_RESET cmd=%p jiffies = 0x%lx, "9361 "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",9362 ha->host_no, cmd, jiffies, scsi_cmd_to_rq(cmd)->timeout / HZ,9363 ha->dpc_flags, cmd->result, cmd->allowed));9364 9365 rval = qla4xxx_isp_check_reg(ha);9366 if (rval != QLA_SUCCESS) {9367 ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");9368 return FAILED;9369 }9370 9371 stat = qla4xxx_reset_target(ha, ddb_entry);9372 if (stat != QLA_SUCCESS) {9373 starget_printk(KERN_INFO, scsi_target(cmd->device),9374 "WARM TARGET RESET FAILED.\n");9375 return FAILED;9376 }9377 9378 if (qla4xxx_eh_wait_for_commands(ha, scsi_target(cmd->device),9379 NULL)) {9380 starget_printk(KERN_INFO, scsi_target(cmd->device),9381 "WARM TARGET DEVICE RESET FAILED - "9382 "waiting for commands.\n");9383 return FAILED;9384 }9385 9386 /* Send marker. */9387 if (qla4xxx_send_marker_iocb(ha, ddb_entry, cmd->device->lun,9388 MM_TGT_WARM_RESET) != QLA_SUCCESS) {9389 starget_printk(KERN_INFO, scsi_target(cmd->device),9390 "WARM TARGET DEVICE RESET FAILED - "9391 "marker iocb failed.\n");9392 return FAILED;9393 }9394 9395 starget_printk(KERN_INFO, scsi_target(cmd->device),9396 "WARM TARGET RESET SUCCEEDED.\n");9397 return SUCCESS;9398}9399 9400/**9401 * qla4xxx_is_eh_active - check if error handler is running9402 * @shost: Pointer to SCSI Host struct9403 *9404 * This routine finds that if reset host is called in EH9405 * scenario or from some application like sg_reset9406 **/9407static int qla4xxx_is_eh_active(struct Scsi_Host *shost)9408{9409 if (shost->shost_state == SHOST_RECOVERY)9410 return 1;9411 return 0;9412}9413 9414/**9415 * qla4xxx_eh_host_reset - kernel callback9416 * @cmd: Pointer to Linux's SCSI command structure9417 *9418 * This routine is invoked by the Linux kernel to perform fatal error9419 * recovery on the specified adapter.9420 **/9421static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)9422{9423 int return_status = FAILED;9424 struct scsi_qla_host *ha;9425 int rval;9426 9427 ha = to_qla_host(cmd->device->host);9428 9429 rval = qla4xxx_isp_check_reg(ha);9430 if (rval != QLA_SUCCESS) {9431 ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");9432 return FAILED;9433 }9434 9435 if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba)9436 qla4_83xx_set_idc_dontreset(ha);9437 9438 /*9439 * For ISP8324 and ISP8042, if IDC_CTRL DONTRESET_BIT0 is set by other9440 * protocol drivers, we should not set device_state to NEED_RESET9441 */9442 if (ql4xdontresethba ||9443 ((is_qla8032(ha) || is_qla8042(ha)) &&9444 qla4_83xx_idc_dontreset(ha))) {9445 DEBUG2(printk("scsi%ld: %s: Don't Reset HBA\n",9446 ha->host_no, __func__));9447 9448 /* Clear outstanding srb in queues */9449 if (qla4xxx_is_eh_active(cmd->device->host))9450 qla4xxx_abort_active_cmds(ha, DID_ABORT << 16);9451 9452 return FAILED;9453 }9454 9455 ql4_printk(KERN_INFO, ha,9456 "scsi(%ld:%d:%d:%llu): HOST RESET ISSUED.\n", ha->host_no,9457 cmd->device->channel, cmd->device->id, cmd->device->lun);9458 9459 if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {9460 DEBUG2(printk("scsi%ld:%d: %s: Unable to reset host. Adapter "9461 "DEAD.\n", ha->host_no, cmd->device->channel,9462 __func__));9463 9464 return FAILED;9465 }9466 9467 if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {9468 if (is_qla80XX(ha))9469 set_bit(DPC_RESET_HA_FW_CONTEXT, &ha->dpc_flags);9470 else9471 set_bit(DPC_RESET_HA, &ha->dpc_flags);9472 }9473 9474 if (qla4xxx_recover_adapter(ha) == QLA_SUCCESS)9475 return_status = SUCCESS;9476 9477 ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n",9478 return_status == FAILED ? "FAILED" : "SUCCEEDED");9479 9480 return return_status;9481}9482 9483static int qla4xxx_context_reset(struct scsi_qla_host *ha)9484{9485 uint32_t mbox_cmd[MBOX_REG_COUNT];9486 uint32_t mbox_sts[MBOX_REG_COUNT];9487 struct addr_ctrl_blk_def *acb = NULL;9488 uint32_t acb_len = sizeof(struct addr_ctrl_blk_def);9489 int rval = QLA_SUCCESS;9490 dma_addr_t acb_dma;9491 9492 acb = dma_alloc_coherent(&ha->pdev->dev,9493 sizeof(struct addr_ctrl_blk_def),9494 &acb_dma, GFP_KERNEL);9495 if (!acb) {9496 ql4_printk(KERN_ERR, ha, "%s: Unable to alloc acb\n",9497 __func__);9498 rval = -ENOMEM;9499 goto exit_port_reset;9500 }9501 9502 memset(acb, 0, acb_len);9503 9504 rval = qla4xxx_get_acb(ha, acb_dma, PRIMARI_ACB, acb_len);9505 if (rval != QLA_SUCCESS) {9506 rval = -EIO;9507 goto exit_free_acb;9508 }9509 9510 rval = qla4xxx_disable_acb(ha);9511 if (rval != QLA_SUCCESS) {9512 rval = -EIO;9513 goto exit_free_acb;9514 }9515 9516 wait_for_completion_timeout(&ha->disable_acb_comp,9517 DISABLE_ACB_TOV * HZ);9518 9519 rval = qla4xxx_set_acb(ha, &mbox_cmd[0], &mbox_sts[0], acb_dma);9520 if (rval != QLA_SUCCESS) {9521 rval = -EIO;9522 goto exit_free_acb;9523 }9524 9525exit_free_acb:9526 dma_free_coherent(&ha->pdev->dev, sizeof(struct addr_ctrl_blk_def),9527 acb, acb_dma);9528exit_port_reset:9529 DEBUG2(ql4_printk(KERN_INFO, ha, "%s %s\n", __func__,9530 rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED"));9531 return rval;9532}9533 9534static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type)9535{9536 struct scsi_qla_host *ha = to_qla_host(shost);9537 int rval = QLA_SUCCESS;9538 uint32_t idc_ctrl;9539 9540 if (ql4xdontresethba) {9541 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n",9542 __func__));9543 rval = -EPERM;9544 goto exit_host_reset;9545 }9546 9547 if (test_bit(DPC_RESET_HA, &ha->dpc_flags))9548 goto recover_adapter;9549 9550 switch (reset_type) {9551 case SCSI_ADAPTER_RESET:9552 set_bit(DPC_RESET_HA, &ha->dpc_flags);9553 break;9554 case SCSI_FIRMWARE_RESET:9555 if (!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {9556 if (is_qla80XX(ha))9557 /* set firmware context reset */9558 set_bit(DPC_RESET_HA_FW_CONTEXT,9559 &ha->dpc_flags);9560 else {9561 rval = qla4xxx_context_reset(ha);9562 goto exit_host_reset;9563 }9564 }9565 break;9566 }9567 9568recover_adapter:9569 /* For ISP8324 and ISP8042 set graceful reset bit in IDC_DRV_CTRL if9570 * reset is issued by application */9571 if ((is_qla8032(ha) || is_qla8042(ha)) &&9572 test_bit(DPC_RESET_HA, &ha->dpc_flags)) {9573 idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL);9574 qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL,9575 (idc_ctrl | GRACEFUL_RESET_BIT1));9576 }9577 9578 rval = qla4xxx_recover_adapter(ha);9579 if (rval != QLA_SUCCESS) {9580 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n",9581 __func__));9582 rval = -EIO;9583 }9584 9585exit_host_reset:9586 return rval;9587}9588 9589/* PCI AER driver recovers from all correctable errors w/o9590 * driver intervention. For uncorrectable errors PCI AER9591 * driver calls the following device driver's callbacks9592 *9593 * - Fatal Errors - link_reset9594 * - Non-Fatal Errors - driver's error_detected() which9595 * returns CAN_RECOVER, NEED_RESET or DISCONNECT.9596 *9597 * PCI AER driver calls9598 * CAN_RECOVER - driver's mmio_enabled(), mmio_enabled()9599 * returns RECOVERED or NEED_RESET if fw_hung9600 * NEED_RESET - driver's slot_reset()9601 * DISCONNECT - device is dead & cannot recover9602 * RECOVERED - driver's resume()9603 */9604static pci_ers_result_t9605qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)9606{9607 struct scsi_qla_host *ha = pci_get_drvdata(pdev);9608 9609 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n",9610 ha->host_no, __func__, state);9611 9612 if (!is_aer_supported(ha))9613 return PCI_ERS_RESULT_NONE;9614 9615 switch (state) {9616 case pci_channel_io_normal:9617 clear_bit(AF_EEH_BUSY, &ha->flags);9618 return PCI_ERS_RESULT_CAN_RECOVER;9619 case pci_channel_io_frozen:9620 set_bit(AF_EEH_BUSY, &ha->flags);9621 qla4xxx_mailbox_premature_completion(ha);9622 qla4xxx_free_irqs(ha);9623 pci_disable_device(pdev);9624 /* Return back all IOs */9625 qla4xxx_abort_active_cmds(ha, DID_RESET << 16);9626 return PCI_ERS_RESULT_NEED_RESET;9627 case pci_channel_io_perm_failure:9628 set_bit(AF_EEH_BUSY, &ha->flags);9629 set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags);9630 qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);9631 return PCI_ERS_RESULT_DISCONNECT;9632 }9633 return PCI_ERS_RESULT_NEED_RESET;9634}9635 9636/**9637 * qla4xxx_pci_mmio_enabled() - gets called if9638 * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER9639 * and read/write to the device still works.9640 * @pdev: PCI device pointer9641 **/9642static pci_ers_result_t9643qla4xxx_pci_mmio_enabled(struct pci_dev *pdev)9644{9645 struct scsi_qla_host *ha = pci_get_drvdata(pdev);9646 9647 if (!is_aer_supported(ha))9648 return PCI_ERS_RESULT_NONE;9649 9650 return PCI_ERS_RESULT_RECOVERED;9651}9652 9653static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha)9654{9655 uint32_t rval = QLA_ERROR;9656 int fn;9657 struct pci_dev *other_pdev = NULL;9658 9659 ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__);9660 9661 set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);9662 9663 if (test_bit(AF_ONLINE, &ha->flags)) {9664 clear_bit(AF_ONLINE, &ha->flags);9665 clear_bit(AF_LINK_UP, &ha->flags);9666 iscsi_host_for_each_session(ha->host, qla4xxx_fail_session);9667 qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);9668 }9669 9670 fn = PCI_FUNC(ha->pdev->devfn);9671 if (is_qla8022(ha)) {9672 while (fn > 0) {9673 fn--;9674 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at func %x\n",9675 ha->host_no, __func__, fn);9676 /* Get the pci device given the domain, bus,9677 * slot/function number */9678 other_pdev = pci_get_domain_bus_and_slot(9679 pci_domain_nr(ha->pdev->bus),9680 ha->pdev->bus->number,9681 PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),9682 fn));9683 9684 if (!other_pdev)9685 continue;9686 9687 if (atomic_read(&other_pdev->enable_cnt)) {9688 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI func in enabled state%x\n",9689 ha->host_no, __func__, fn);9690 pci_dev_put(other_pdev);9691 break;9692 }9693 pci_dev_put(other_pdev);9694 }9695 } else {9696 /* this case is meant for ISP83xx/ISP84xx only */9697 if (qla4_83xx_can_perform_reset(ha)) {9698 /* reset fn as iSCSI is going to perform the reset */9699 fn = 0;9700 }9701 }9702 9703 /* The first function on the card, the reset owner will9704 * start & initialize the firmware. The other functions9705 * on the card will reset the firmware context9706 */9707 if (!fn) {9708 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset "9709 "0x%x is the owner\n", ha->host_no, __func__,9710 ha->pdev->devfn);9711 9712 ha->isp_ops->idc_lock(ha);9713 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,9714 QLA8XXX_DEV_COLD);9715 ha->isp_ops->idc_unlock(ha);9716 9717 rval = qla4_8xxx_update_idc_reg(ha);9718 if (rval == QLA_ERROR) {9719 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: FAILED\n",9720 ha->host_no, __func__);9721 ha->isp_ops->idc_lock(ha);9722 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,9723 QLA8XXX_DEV_FAILED);9724 ha->isp_ops->idc_unlock(ha);9725 goto exit_error_recovery;9726 }9727 9728 clear_bit(AF_FW_RECOVERY, &ha->flags);9729 rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);9730 9731 if (rval != QLA_SUCCESS) {9732 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "9733 "FAILED\n", ha->host_no, __func__);9734 qla4xxx_free_irqs(ha);9735 ha->isp_ops->idc_lock(ha);9736 qla4_8xxx_clear_drv_active(ha);9737 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,9738 QLA8XXX_DEV_FAILED);9739 ha->isp_ops->idc_unlock(ha);9740 } else {9741 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: "9742 "READY\n", ha->host_no, __func__);9743 ha->isp_ops->idc_lock(ha);9744 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DEV_STATE,9745 QLA8XXX_DEV_READY);9746 /* Clear driver state register */9747 qla4_8xxx_wr_direct(ha, QLA8XXX_CRB_DRV_STATE, 0);9748 qla4_8xxx_set_drv_active(ha);9749 ha->isp_ops->idc_unlock(ha);9750 ha->isp_ops->enable_intrs(ha);9751 }9752 } else {9753 ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not "9754 "the reset owner\n", ha->host_no, __func__,9755 ha->pdev->devfn);9756 if ((qla4_8xxx_rd_direct(ha, QLA8XXX_CRB_DEV_STATE) ==9757 QLA8XXX_DEV_READY)) {9758 clear_bit(AF_FW_RECOVERY, &ha->flags);9759 rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER);9760 if (rval == QLA_SUCCESS)9761 ha->isp_ops->enable_intrs(ha);9762 else9763 qla4xxx_free_irqs(ha);9764 9765 ha->isp_ops->idc_lock(ha);9766 qla4_8xxx_set_drv_active(ha);9767 ha->isp_ops->idc_unlock(ha);9768 }9769 }9770exit_error_recovery:9771 clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);9772 return rval;9773}9774 9775static pci_ers_result_t9776qla4xxx_pci_slot_reset(struct pci_dev *pdev)9777{9778 pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT;9779 struct scsi_qla_host *ha = pci_get_drvdata(pdev);9780 int rc;9781 9782 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n",9783 ha->host_no, __func__);9784 9785 if (!is_aer_supported(ha))9786 return PCI_ERS_RESULT_NONE;9787 9788 /* Restore the saved state of PCIe device -9789 * BAR registers, PCI Config space, PCIX, MSI,9790 * IOV states9791 */9792 pci_restore_state(pdev);9793 9794 /* pci_restore_state() clears the saved_state flag of the device9795 * save restored state which resets saved_state flag9796 */9797 pci_save_state(pdev);9798 9799 /* Initialize device or resume if in suspended state */9800 rc = pci_enable_device(pdev);9801 if (rc) {9802 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Can't re-enable "9803 "device after reset\n", ha->host_no, __func__);9804 goto exit_slot_reset;9805 }9806 9807 ha->isp_ops->disable_intrs(ha);9808 9809 if (is_qla80XX(ha)) {9810 if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) {9811 ret = PCI_ERS_RESULT_RECOVERED;9812 goto exit_slot_reset;9813 } else9814 goto exit_slot_reset;9815 }9816 9817exit_slot_reset:9818 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n"9819 "device after reset\n", ha->host_no, __func__, ret);9820 return ret;9821}9822 9823static void9824qla4xxx_pci_resume(struct pci_dev *pdev)9825{9826 struct scsi_qla_host *ha = pci_get_drvdata(pdev);9827 int ret;9828 9829 ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n",9830 ha->host_no, __func__);9831 9832 ret = qla4xxx_wait_for_hba_online(ha);9833 if (ret != QLA_SUCCESS) {9834 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to "9835 "resume I/O from slot/link_reset\n", ha->host_no,9836 __func__);9837 }9838 9839 clear_bit(AF_EEH_BUSY, &ha->flags);9840}9841 9842static const struct pci_error_handlers qla4xxx_err_handler = {9843 .error_detected = qla4xxx_pci_error_detected,9844 .mmio_enabled = qla4xxx_pci_mmio_enabled,9845 .slot_reset = qla4xxx_pci_slot_reset,9846 .resume = qla4xxx_pci_resume,9847};9848 9849static struct pci_device_id qla4xxx_pci_tbl[] = {9850 {9851 .vendor = PCI_VENDOR_ID_QLOGIC,9852 .device = PCI_DEVICE_ID_QLOGIC_ISP4010,9853 .subvendor = PCI_ANY_ID,9854 .subdevice = PCI_ANY_ID,9855 },9856 {9857 .vendor = PCI_VENDOR_ID_QLOGIC,9858 .device = PCI_DEVICE_ID_QLOGIC_ISP4022,9859 .subvendor = PCI_ANY_ID,9860 .subdevice = PCI_ANY_ID,9861 },9862 {9863 .vendor = PCI_VENDOR_ID_QLOGIC,9864 .device = PCI_DEVICE_ID_QLOGIC_ISP4032,9865 .subvendor = PCI_ANY_ID,9866 .subdevice = PCI_ANY_ID,9867 },9868 {9869 .vendor = PCI_VENDOR_ID_QLOGIC,9870 .device = PCI_DEVICE_ID_QLOGIC_ISP8022,9871 .subvendor = PCI_ANY_ID,9872 .subdevice = PCI_ANY_ID,9873 },9874 {9875 .vendor = PCI_VENDOR_ID_QLOGIC,9876 .device = PCI_DEVICE_ID_QLOGIC_ISP8324,9877 .subvendor = PCI_ANY_ID,9878 .subdevice = PCI_ANY_ID,9879 },9880 {9881 .vendor = PCI_VENDOR_ID_QLOGIC,9882 .device = PCI_DEVICE_ID_QLOGIC_ISP8042,9883 .subvendor = PCI_ANY_ID,9884 .subdevice = PCI_ANY_ID,9885 },9886 {0, 0},9887};9888MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);9889 9890static struct pci_driver qla4xxx_pci_driver = {9891 .name = DRIVER_NAME,9892 .id_table = qla4xxx_pci_tbl,9893 .probe = qla4xxx_probe_adapter,9894 .remove = qla4xxx_remove_adapter,9895 .err_handler = &qla4xxx_err_handler,9896};9897 9898static int __init qla4xxx_module_init(void)9899{9900 int ret;9901 9902 if (ql4xqfulltracking)9903 qla4xxx_driver_template.track_queue_depth = 1;9904 9905 /* Allocate cache for SRBs. */9906 srb_cachep = kmem_cache_create("qla4xxx_srbs", sizeof(struct srb), 0,9907 SLAB_HWCACHE_ALIGN, NULL);9908 if (srb_cachep == NULL) {9909 printk(KERN_ERR9910 "%s: Unable to allocate SRB cache..."9911 "Failing load!\n", DRIVER_NAME);9912 ret = -ENOMEM;9913 goto no_srp_cache;9914 }9915 9916 /* Derive version string. */9917 strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION);9918 if (ql4xextended_error_logging)9919 strcat(qla4xxx_version_str, "-debug");9920 9921 qla4xxx_scsi_transport =9922 iscsi_register_transport(&qla4xxx_iscsi_transport);9923 if (!qla4xxx_scsi_transport){9924 ret = -ENODEV;9925 goto release_srb_cache;9926 }9927 9928 ret = pci_register_driver(&qla4xxx_pci_driver);9929 if (ret)9930 goto unregister_transport;9931 9932 printk(KERN_INFO "QLogic iSCSI HBA Driver\n");9933 return 0;9934 9935unregister_transport:9936 iscsi_unregister_transport(&qla4xxx_iscsi_transport);9937release_srb_cache:9938 kmem_cache_destroy(srb_cachep);9939no_srp_cache:9940 return ret;9941}9942 9943static void __exit qla4xxx_module_exit(void)9944{9945 pci_unregister_driver(&qla4xxx_pci_driver);9946 iscsi_unregister_transport(&qla4xxx_iscsi_transport);9947 kmem_cache_destroy(srb_cachep);9948}9949 9950module_init(qla4xxx_module_init);9951module_exit(qla4xxx_module_exit);9952 9953MODULE_AUTHOR("QLogic Corporation");9954MODULE_DESCRIPTION("QLogic iSCSI HBA Driver");9955MODULE_LICENSE("GPL");9956MODULE_VERSION(QLA4XXX_DRIVER_VERSION);9957