diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 02:32:26 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-23 02:32:26 +0100 |
commit | 194e57fd1835564735fd0ba5e3870230861cacd2 (patch) | |
tree | 9f2fd1463109ec6b151088417e0c1e14204d0924 /drivers/scsi/qla4xxx | |
parent | Merge tag 'pci-v3.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
parent | Merge branch 'misc' into for-linus (diff) | |
download | linux-194e57fd1835564735fd0ba5e3870230861cacd2.tar.xz linux-194e57fd1835564735fd0ba5e3870230861cacd2.zip |
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This patch set is a lot of driver updates for qla4xxx, bfa, hpsa,
qla2xxx. It also removes the aic7xxx_old driver (which has been
deprecated for nearly a decade) and adds support for deadlines in
error handling"
* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (75 commits)
[SCSI] hpsa: allow SCSI mid layer to handle unit attention
[SCSI] hpsa: do not require board "not ready" status after hard reset
[SCSI] hpsa: enable unit attention reporting
[SCSI] hpsa: rename scsi prefetch field
[SCSI] hpsa: use workqueue instead of kernel thread for lockup detection
[SCSI] ipr: increase dump size in ipr driver
[SCSI] mac_scsi: Fix crash on out of memory
[SCSI] st: fix enlarge_buffer
[SCSI] qla1280: Annotate timer on stack so object debug does not complain
[SCSI] qla4xxx: Update driver version to 5.04.00-k3
[SCSI] qla4xxx: Recreate chap data list during get chap operation
[SCSI] qla4xxx: Add support for ISCSI_PARAM_LOCAL_IPADDR sysfs attr
[SCSI] libiscsi: Add local_ipaddr parameter in iscsi_conn struct
[SCSI] scsi_transport_iscsi: Export ISCSI_PARAM_LOCAL_IPADDR attr for iscsi_connection
[SCSI] qla4xxx: Add host statistics support
[SCSI] scsi_transport_iscsi: Add host statistics support
[SCSI] qla4xxx: Added support for Diagnostics MBOX command
[SCSI] bfa: Driver version upgrade to 3.2.23.0
[SCSI] bfa: change FC_ELS_TOV to 20sec
[SCSI] bfa: Observed auto D-port mode instead of manual
...
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_bsg.c | 360 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_bsg.h | 13 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 40 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 140 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 3 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 51 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 154 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 1474 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 |
9 files changed, 2033 insertions, 204 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_bsg.c b/drivers/scsi/qla4xxx/ql4_bsg.c index cf8fdf1d1257..04a0027dbca0 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.c +++ b/drivers/scsi/qla4xxx/ql4_bsg.c @@ -446,6 +446,363 @@ leave: return rval; } +static void ql4xxx_execute_diag_cmd(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint8_t *rsp_ptr = NULL; + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + int status = QLA_ERROR; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); + + if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) { + ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n", + __func__); + bsg_reply->result = DID_ERROR << 16; + goto exit_diag_mem_test; + } + + bsg_reply->reply_payload_rcv_len = 0; + memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1], + sizeof(uint32_t) * MBOX_REG_COUNT); + + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n", + __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2], + mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6], + mbox_cmd[7])); + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], + &mbox_sts[0]); + + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n", + __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2], + mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6], + mbox_sts[7])); + + if (status == QLA_SUCCESS) + bsg_reply->result = DID_OK << 16; + else + bsg_reply->result = DID_ERROR << 16; + + /* Send mbox_sts to application */ + bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts); + rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply); + memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts)); + +exit_diag_mem_test: + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: bsg_reply->result = x%x, status = %s\n", + __func__, bsg_reply->result, STATUS(status))); + + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); +} + +static int qla4_83xx_wait_for_loopback_config_comp(struct scsi_qla_host *ha, + int wait_for_link) +{ + int status = QLA_SUCCESS; + + if (!wait_for_completion_timeout(&ha->idc_comp, (IDC_COMP_TOV * HZ))) { + ql4_printk(KERN_INFO, ha, "%s: IDC Complete notification not received, Waiting for another %d timeout", + __func__, ha->idc_extend_tmo); + if (ha->idc_extend_tmo) { + if (!wait_for_completion_timeout(&ha->idc_comp, + (ha->idc_extend_tmo * HZ))) { + ha->notify_idc_comp = 0; + ha->notify_link_up_comp = 0; + ql4_printk(KERN_WARNING, ha, "%s: IDC Complete notification not received", + __func__); + status = QLA_ERROR; + goto exit_wait; + } else { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: IDC Complete notification received\n", + __func__)); + } + } + } else { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: IDC Complete notification received\n", + __func__)); + } + ha->notify_idc_comp = 0; + + if (wait_for_link) { + if (!wait_for_completion_timeout(&ha->link_up_comp, + (IDC_COMP_TOV * HZ))) { + ha->notify_link_up_comp = 0; + ql4_printk(KERN_WARNING, ha, "%s: LINK UP notification not received", + __func__); + status = QLA_ERROR; + goto exit_wait; + } else { + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: LINK UP notification received\n", + __func__)); + } + ha->notify_link_up_comp = 0; + } + +exit_wait: + return status; +} + +static int qla4_83xx_pre_loopback_config(struct scsi_qla_host *ha, + uint32_t *mbox_cmd) +{ + uint32_t config = 0; + int status = QLA_SUCCESS; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); + + status = qla4_83xx_get_port_config(ha, &config); + if (status != QLA_SUCCESS) + goto exit_pre_loopback_config; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Default port config=%08X\n", + __func__, config)); + + if ((config & ENABLE_INTERNAL_LOOPBACK) || + (config & ENABLE_EXTERNAL_LOOPBACK)) { + ql4_printk(KERN_INFO, ha, "%s: Loopback diagnostics already in progress. Invalid requiest\n", + __func__); + goto exit_pre_loopback_config; + } + + if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK) + config |= ENABLE_INTERNAL_LOOPBACK; + + if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK) + config |= ENABLE_EXTERNAL_LOOPBACK; + + config &= ~ENABLE_DCBX; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: New port config=%08X\n", + __func__, config)); + + ha->notify_idc_comp = 1; + ha->notify_link_up_comp = 1; + + /* get the link state */ + qla4xxx_get_firmware_state(ha); + + status = qla4_83xx_set_port_config(ha, &config); + if (status != QLA_SUCCESS) { + ha->notify_idc_comp = 0; + ha->notify_link_up_comp = 0; + goto exit_pre_loopback_config; + } +exit_pre_loopback_config: + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__, + STATUS(status))); + return status; +} + +static int qla4_83xx_post_loopback_config(struct scsi_qla_host *ha, + uint32_t *mbox_cmd) +{ + int status = QLA_SUCCESS; + uint32_t config = 0; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); + + status = qla4_83xx_get_port_config(ha, &config); + if (status != QLA_SUCCESS) + goto exit_post_loopback_config; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: port config=%08X\n", __func__, + config)); + + if (mbox_cmd[1] == QL_DIAG_CMD_TEST_INT_LOOPBACK) + config &= ~ENABLE_INTERNAL_LOOPBACK; + else if (mbox_cmd[1] == QL_DIAG_CMD_TEST_EXT_LOOPBACK) + config &= ~ENABLE_EXTERNAL_LOOPBACK; + + config |= ENABLE_DCBX; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: Restore default port config=%08X\n", __func__, + config)); + + ha->notify_idc_comp = 1; + if (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) + ha->notify_link_up_comp = 1; + + status = qla4_83xx_set_port_config(ha, &config); + if (status != QLA_SUCCESS) { + ql4_printk(KERN_INFO, ha, "%s: Scheduling adapter reset\n", + __func__); + set_bit(DPC_RESET_HA, &ha->dpc_flags); + clear_bit(AF_LOOPBACK, &ha->flags); + goto exit_post_loopback_config; + } + +exit_post_loopback_config: + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: status = %s\n", __func__, + STATUS(status))); + return status; +} + +static void qla4xxx_execute_diag_loopback_cmd(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + struct iscsi_bsg_reply *bsg_reply = bsg_job->reply; + uint8_t *rsp_ptr = NULL; + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + int wait_for_link = 1; + int status = QLA_ERROR; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); + + bsg_reply->reply_payload_rcv_len = 0; + + if (test_bit(AF_LOOPBACK, &ha->flags)) { + ql4_printk(KERN_INFO, ha, "%s: Loopback Diagnostics already in progress. Invalid Request\n", + __func__); + bsg_reply->result = DID_ERROR << 16; + goto exit_loopback_cmd; + } + + if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) { + ql4_printk(KERN_INFO, ha, "%s: Adapter reset in progress. Invalid Request\n", + __func__); + bsg_reply->result = DID_ERROR << 16; + goto exit_loopback_cmd; + } + + memcpy(mbox_cmd, &bsg_req->rqst_data.h_vendor.vendor_cmd[1], + sizeof(uint32_t) * MBOX_REG_COUNT); + + if (is_qla8032(ha) || is_qla8042(ha)) { + status = qla4_83xx_pre_loopback_config(ha, mbox_cmd); + if (status != QLA_SUCCESS) { + bsg_reply->result = DID_ERROR << 16; + goto exit_loopback_cmd; + } + + status = qla4_83xx_wait_for_loopback_config_comp(ha, + wait_for_link); + if (status != QLA_SUCCESS) { + bsg_reply->result = DID_TIME_OUT << 16; + goto restore; + } + } + + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: mbox_cmd: %08X %08X %08X %08X %08X %08X %08X %08X\n", + __func__, mbox_cmd[0], mbox_cmd[1], mbox_cmd[2], + mbox_cmd[3], mbox_cmd[4], mbox_cmd[5], mbox_cmd[6], + mbox_cmd[7])); + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 8, &mbox_cmd[0], + &mbox_sts[0]); + + if (status == QLA_SUCCESS) + bsg_reply->result = DID_OK << 16; + else + bsg_reply->result = DID_ERROR << 16; + + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: mbox_sts: %08X %08X %08X %08X %08X %08X %08X %08X\n", + __func__, mbox_sts[0], mbox_sts[1], mbox_sts[2], + mbox_sts[3], mbox_sts[4], mbox_sts[5], mbox_sts[6], + mbox_sts[7])); + + /* Send mbox_sts to application */ + bsg_job->reply_len = sizeof(struct iscsi_bsg_reply) + sizeof(mbox_sts); + rsp_ptr = ((uint8_t *)bsg_reply) + sizeof(struct iscsi_bsg_reply); + memcpy(rsp_ptr, mbox_sts, sizeof(mbox_sts)); +restore: + if (is_qla8032(ha) || is_qla8042(ha)) { + status = qla4_83xx_post_loopback_config(ha, mbox_cmd); + if (status != QLA_SUCCESS) { + bsg_reply->result = DID_ERROR << 16; + goto exit_loopback_cmd; + } + + /* for pre_loopback_config() wait for LINK UP only + * if PHY LINK is UP */ + if (!(ha->addl_fw_state & FW_ADDSTATE_LINK_UP)) + wait_for_link = 0; + + status = qla4_83xx_wait_for_loopback_config_comp(ha, + wait_for_link); + if (status != QLA_SUCCESS) { + bsg_reply->result = DID_TIME_OUT << 16; + goto exit_loopback_cmd; + } + } +exit_loopback_cmd: + DEBUG2(ql4_printk(KERN_INFO, ha, + "%s: bsg_reply->result = x%x, status = %s\n", + __func__, bsg_reply->result, STATUS(status))); + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); +} + +static int qla4xxx_execute_diag_test(struct bsg_job *bsg_job) +{ + struct Scsi_Host *host = iscsi_job_to_shost(bsg_job); + struct scsi_qla_host *ha = to_qla_host(host); + struct iscsi_bsg_request *bsg_req = bsg_job->request; + uint32_t diag_cmd; + int rval = -EINVAL; + + DEBUG2(ql4_printk(KERN_INFO, ha, "%s: in\n", __func__)); + + diag_cmd = bsg_req->rqst_data.h_vendor.vendor_cmd[1]; + if (diag_cmd == MBOX_CMD_DIAG_TEST) { + switch (bsg_req->rqst_data.h_vendor.vendor_cmd[2]) { + case QL_DIAG_CMD_TEST_DDR_SIZE: + case QL_DIAG_CMD_TEST_DDR_RW: + case QL_DIAG_CMD_TEST_ONCHIP_MEM_RW: + case QL_DIAG_CMD_TEST_NVRAM: + case QL_DIAG_CMD_TEST_FLASH_ROM: + case QL_DIAG_CMD_TEST_DMA_XFER: + case QL_DIAG_CMD_SELF_DDR_RW: + case QL_DIAG_CMD_SELF_ONCHIP_MEM_RW: + /* Execute diag test for adapter RAM/FLASH */ + ql4xxx_execute_diag_cmd(bsg_job); + /* Always return success as we want to sent bsg_reply + * to Application */ + rval = QLA_SUCCESS; + break; + + case QL_DIAG_CMD_TEST_INT_LOOPBACK: + case QL_DIAG_CMD_TEST_EXT_LOOPBACK: + /* Execute diag test for Network */ + qla4xxx_execute_diag_loopback_cmd(bsg_job); + /* Always return success as we want to sent bsg_reply + * to Application */ + rval = QLA_SUCCESS; + break; + default: + ql4_printk(KERN_ERR, ha, "%s: Invalid diag test: 0x%x\n", + __func__, + bsg_req->rqst_data.h_vendor.vendor_cmd[2]); + } + } else if ((diag_cmd == MBOX_CMD_SET_LED_CONFIG) || + (diag_cmd == MBOX_CMD_GET_LED_CONFIG)) { + ql4xxx_execute_diag_cmd(bsg_job); + rval = QLA_SUCCESS; + } else { + ql4_printk(KERN_ERR, ha, "%s: Invalid diag cmd: 0x%x\n", + __func__, diag_cmd); + } + + return rval; +} + /** * qla4xxx_process_vendor_specific - handle vendor specific bsg request * @job: iscsi_bsg_job to handle @@ -479,6 +836,9 @@ int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job) case QLISCSI_VND_GET_ACB: return qla4xxx_bsg_get_acb(bsg_job); + case QLISCSI_VND_DIAG_TEST: + return qla4xxx_execute_diag_test(bsg_job); + default: ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: " "0x%x\n", __func__, bsg_req->msgcode); diff --git a/drivers/scsi/qla4xxx/ql4_bsg.h b/drivers/scsi/qla4xxx/ql4_bsg.h index c6a0364509fd..88c2401910c0 100644 --- a/drivers/scsi/qla4xxx/ql4_bsg.h +++ b/drivers/scsi/qla4xxx/ql4_bsg.h @@ -15,5 +15,18 @@ #define QLISCSI_VND_UPDATE_NVRAM 5 #define QLISCSI_VND_RESTORE_DEFAULTS 6 #define QLISCSI_VND_GET_ACB 7 +#define QLISCSI_VND_DIAG_TEST 8 + +/* QLISCSI_VND_DIAG_CMD sub code */ +#define QL_DIAG_CMD_TEST_DDR_SIZE 0x2 +#define QL_DIAG_CMD_TEST_DDR_RW 0x3 +#define QL_DIAG_CMD_TEST_ONCHIP_MEM_RW 0x4 +#define QL_DIAG_CMD_TEST_NVRAM 0x5 /* Only ISP4XXX */ +#define QL_DIAG_CMD_TEST_FLASH_ROM 0x6 +#define QL_DIAG_CMD_TEST_INT_LOOPBACK 0x7 +#define QL_DIAG_CMD_TEST_EXT_LOOPBACK 0x8 +#define QL_DIAG_CMD_TEST_DMA_XFER 0x9 /* Only ISP4XXX */ +#define QL_DIAG_CMD_SELF_DDR_RW 0xC +#define QL_DIAG_CMD_SELF_ONCHIP_MEM_RW 0xD #endif diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 084d1fd59c9e..aa67bb9a4426 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -73,6 +73,7 @@ #define QLA_SUCCESS 0 #define QLA_ERROR 1 +#define STATUS(status) status == QLA_ERROR ? "FAILED" : "SUCCEEDED" /* * Data bit definitions @@ -179,6 +180,10 @@ n &= ~v; \ } +#define OP_STATE(o, f, p) { \ + p = (o & f) ? "enable" : "disable"; \ +} + /* * Retry & Timeout Values */ @@ -206,6 +211,8 @@ #define MAX_RESET_HA_RETRIES 2 #define FW_ALIVE_WAIT_TOV 3 #define IDC_EXTEND_TOV 8 +#define IDC_COMP_TOV 5 +#define LINK_UP_COMP_TOV 30 #define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr) @@ -476,6 +483,34 @@ struct ipaddress_config { uint16_t eth_mtu_size; uint16_t ipv4_port; uint16_t ipv6_port; + uint8_t control; + uint16_t ipv6_tcp_options; + uint8_t tcp_wsf; + uint8_t ipv6_tcp_wsf; + uint8_t ipv4_tos; + uint8_t ipv4_cache_id; + uint8_t ipv6_cache_id; + uint8_t ipv4_alt_cid_len; + uint8_t ipv4_alt_cid[11]; + uint8_t ipv4_vid_len; + uint8_t ipv4_vid[11]; + uint8_t ipv4_ttl; + uint16_t ipv6_flow_lbl; + uint8_t ipv6_traffic_class; + uint8_t ipv6_hop_limit; + uint32_t ipv6_nd_reach_time; + uint32_t ipv6_nd_rexmit_timer; + uint32_t ipv6_nd_stale_timeout; + uint8_t ipv6_dup_addr_detect_count; + uint32_t ipv6_gw_advrt_mtu; + uint16_t def_timeout; + uint8_t abort_timer; + uint16_t iscsi_options; + uint16_t iscsi_max_pdu_size; + uint16_t iscsi_first_burst_len; + uint16_t iscsi_max_outstnd_r2t; + uint16_t iscsi_max_burst_len; + uint8_t iscsi_name[224]; }; #define QL4_CHAP_MAX_NAME_LEN 256 @@ -790,6 +825,11 @@ struct scsi_qla_host { uint32_t pf_bit; struct qla4_83xx_idc_information idc_info; struct addr_ctrl_blk *saved_acb; + int notify_idc_comp; + int notify_link_up_comp; + int idc_extend_tmo; + struct completion idc_comp; + struct completion link_up_comp; }; struct ql4_task_data { diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 1243e5942b76..8d4092b33c07 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -410,6 +410,7 @@ struct qla_flt_region { #define DDB_DS_LOGIN_IN_PROCESS 0x07 #define MBOX_CMD_GET_FW_STATE 0x0069 #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A +#define MBOX_CMD_DIAG_TEST 0x0075 #define MBOX_CMD_GET_SYS_INFO 0x0078 #define MBOX_CMD_GET_NVRAM 0x0078 /* For 40xx */ #define MBOX_CMD_SET_NVRAM 0x0079 /* For 40xx */ @@ -425,8 +426,17 @@ struct qla_flt_region { #define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 #define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 #define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 +#define MBOX_CMD_SET_PORT_CONFIG 0x0122 +#define MBOX_CMD_GET_PORT_CONFIG 0x0123 +#define MBOX_CMD_SET_LED_CONFIG 0x0125 +#define MBOX_CMD_GET_LED_CONFIG 0x0126 #define MBOX_CMD_MINIDUMP 0x0129 +/* Port Config */ +#define ENABLE_INTERNAL_LOOPBACK 0x04 +#define ENABLE_EXTERNAL_LOOPBACK 0x08 +#define ENABLE_DCBX 0x10 + /* Minidump subcommand */ #define MINIDUMP_GET_SIZE_SUBCOMMAND 0x00 #define MINIDUMP_GET_TMPLT_SUBCOMMAND 0x01 @@ -535,10 +545,6 @@ struct qla_flt_region { #define FLASH_OPT_COMMIT 2 #define FLASH_OPT_RMW_COMMIT 3 -/* Loopback type */ -#define ENABLE_INTERNAL_LOOPBACK 0x04 -#define ENABLE_EXTERNAL_LOOPBACK 0x08 - /* generic defines to enable/disable params */ #define QL4_PARAM_DISABLE 0 #define QL4_PARAM_ENABLE 1 @@ -551,6 +557,7 @@ struct addr_ctrl_blk { #define IFCB_VER_MIN 0x01 #define IFCB_VER_MAX 0x02 uint8_t control; /* 01 */ +#define CTRLOPT_NEW_CONN_DISABLE 0x0002 uint16_t fw_options; /* 02-03 */ #define FWOPT_HEARTBEAT_ENABLE 0x1000 @@ -582,11 +589,40 @@ struct addr_ctrl_blk { uint32_t shdwreg_addr_hi; /* 2C-2F */ uint16_t iscsi_opts; /* 30-31 */ +#define ISCSIOPTS_HEADER_DIGEST_EN 0x2000 +#define ISCSIOPTS_DATA_DIGEST_EN 0x1000 +#define ISCSIOPTS_IMMEDIATE_DATA_EN 0x0800 +#define ISCSIOPTS_INITIAL_R2T_EN 0x0400 +#define ISCSIOPTS_DATA_SEQ_INORDER_EN 0x0200 +#define ISCSIOPTS_DATA_PDU_INORDER_EN 0x0100 +#define ISCSIOPTS_CHAP_AUTH_EN 0x0080 +#define ISCSIOPTS_SNACK_EN 0x0040 +#define ISCSIOPTS_DISCOVERY_LOGOUT_EN 0x0020 +#define ISCSIOPTS_BIDI_CHAP_EN 0x0010 +#define ISCSIOPTS_DISCOVERY_AUTH_EN 0x0008 +#define ISCSIOPTS_STRICT_LOGIN_COMP_EN 0x0004 +#define ISCSIOPTS_ERL 0x0003 uint16_t ipv4_tcp_opts; /* 32-33 */ +#define TCPOPT_DELAYED_ACK_DISABLE 0x8000 #define TCPOPT_DHCP_ENABLE 0x0200 +#define TCPOPT_DNS_SERVER_IP_EN 0x0100 +#define TCPOPT_SLP_DA_INFO_EN 0x0080 +#define TCPOPT_NAGLE_ALGO_DISABLE 0x0020 +#define TCPOPT_WINDOW_SCALE_DISABLE 0x0010 +#define TCPOPT_TIMER_SCALE 0x000E +#define TCPOPT_TIMESTAMP_ENABLE 0x0001 uint16_t ipv4_ip_opts; /* 34-35 */ #define IPOPT_IPV4_PROTOCOL_ENABLE 0x8000 +#define IPOPT_IPV4_TOS_EN 0x4000 #define IPOPT_VLAN_TAGGING_ENABLE 0x2000 +#define IPOPT_GRAT_ARP_EN 0x1000 +#define IPOPT_ALT_CID_EN 0x0800 +#define IPOPT_REQ_VID_EN 0x0400 +#define IPOPT_USE_VID_EN 0x0200 +#define IPOPT_LEARN_IQN_EN 0x0100 +#define IPOPT_FRAGMENTATION_DISABLE 0x0010 +#define IPOPT_IN_FORWARD_EN 0x0008 +#define IPOPT_ARP_REDIRECT_EN 0x0004 uint16_t iscsi_max_pdu_size; /* 36-37 */ uint8_t ipv4_tos; /* 38 */ @@ -637,15 +673,24 @@ struct addr_ctrl_blk { uint32_t cookie; /* 200-203 */ uint16_t ipv6_port; /* 204-205 */ uint16_t ipv6_opts; /* 206-207 */ -#define IPV6_OPT_IPV6_PROTOCOL_ENABLE 0x8000 -#define IPV6_OPT_VLAN_TAGGING_ENABLE 0x2000 +#define IPV6_OPT_IPV6_PROTOCOL_ENABLE 0x8000 +#define IPV6_OPT_VLAN_TAGGING_ENABLE 0x2000 +#define IPV6_OPT_GRAT_NEIGHBOR_ADV_EN 0x1000 +#define IPV6_OPT_REDIRECT_EN 0x0004 uint16_t ipv6_addtl_opts; /* 208-209 */ +#define IPV6_ADDOPT_IGNORE_ICMP_ECHO_REQ 0x0040 +#define IPV6_ADDOPT_MLD_EN 0x0004 #define IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE 0x0002 /* Pri ACB Only */ #define IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR 0x0001 uint16_t ipv6_tcp_opts; /* 20A-20B */ +#define IPV6_TCPOPT_DELAYED_ACK_DISABLE 0x8000 +#define IPV6_TCPOPT_NAGLE_ALGO_DISABLE 0x0020 +#define IPV6_TCPOPT_WINDOW_SCALE_DISABLE 0x0010 +#define IPV6_TCPOPT_TIMER_SCALE 0x000E +#define IPV6_TCPOPT_TIMESTAMP_EN 0x0001 uint8_t ipv6_tcp_wsf; /* 20C */ uint16_t ipv6_flow_lbl; /* 20D-20F */ uint8_t ipv6_dflt_rtr_addr[16]; /* 210-21F */ @@ -1252,7 +1297,88 @@ struct response { }; struct ql_iscsi_stats { - uint8_t reserved1[656]; /* 0000-028F */ + uint64_t mac_tx_frames; /* 0000–0007 */ + uint64_t mac_tx_bytes; /* 0008–000F */ + uint64_t mac_tx_multicast_frames; /* 0010–0017 */ + uint64_t mac_tx_broadcast_frames; /* 0018–001F */ + uint64_t mac_tx_pause_frames; /* 0020–0027 */ + uint64_t mac_tx_control_frames; /* 0028–002F */ + uint64_t mac_tx_deferral; /* 0030–0037 */ + uint64_t mac_tx_excess_deferral; /* 0038–003F */ + uint64_t mac_tx_late_collision; /* 0040–0047 */ + uint64_t mac_tx_abort; /* 0048–004F */ + uint64_t mac_tx_single_collision; /* 0050–0057 */ + uint64_t mac_tx_multiple_collision; /* 0058–005F */ + uint64_t mac_tx_collision; /* 0060–0067 */ + uint64_t mac_tx_frames_dropped; /* 0068–006F */ + uint64_t mac_tx_jumbo_frames; /* 0070–0077 */ + uint64_t mac_rx_frames; /* 0078–007F */ + uint64_t mac_rx_bytes; /* 0080–0087 */ + uint64_t mac_rx_unknown_control_frames; /* 0088–008F */ + uint64_t mac_rx_pause_frames; /* 0090–0097 */ + uint64_t mac_rx_control_frames; /* 0098–009F */ + uint64_t mac_rx_dribble; /* 00A0–00A7 */ + uint64_t mac_rx_frame_length_error; /* 00A8–00AF */ + uint64_t mac_rx_jabber; /* 00B0–00B7 */ + uint64_t mac_rx_carrier_sense_error; /* 00B8–00BF */ + uint64_t mac_rx_frame_discarded; /* 00C0–00C7 */ + uint64_t mac_rx_frames_dropped; /* 00C8–00CF */ + uint64_t mac_crc_error; /* 00D0–00D7 */ + uint64_t mac_encoding_error; /* 00D8–00DF */ + uint64_t mac_rx_length_error_large; /* 00E0–00E7 */ + uint64_t mac_rx_length_error_small; /* 00E8–00EF */ + uint64_t mac_rx_multicast_frames; /* 00F0–00F7 */ + uint64_t mac_rx_broadcast_frames; /* 00F8–00FF */ + uint64_t ip_tx_packets; /* 0100–0107 */ + uint64_t ip_tx_bytes; /* 0108–010F */ + uint64_t ip_tx_fragments; /* 0110–0117 */ + uint64_t ip_rx_packets; /* 0118–011F */ + uint64_t ip_rx_bytes; /* 0120–0127 */ + uint64_t ip_rx_fragments; /* 0128–012F */ + uint64_t ip_datagram_reassembly; /* 0130–0137 */ + uint64_t ip_invalid_address_error; /* 0138–013F */ + uint64_t ip_error_packets; /* 0140–0147 */ + uint64_t ip_fragrx_overlap; /* 0148–014F */ + uint64_t ip_fragrx_outoforder; /* 0150–0157 */ + uint64_t ip_datagram_reassembly_timeout; /* 0158–015F */ + uint64_t ipv6_tx_packets; /* 0160–0167 */ + uint64_t ipv6_tx_bytes; /* 0168–016F */ + uint64_t ipv6_tx_fragments; /* 0170–0177 */ + uint64_t ipv6_rx_packets; /* 0178–017F */ + uint64_t ipv6_rx_bytes; /* 0180–0187 */ + uint64_t ipv6_rx_fragments; /* 0188–018F */ + uint64_t ipv6_datagram_reassembly; /* 0190–0197 */ + uint64_t ipv6_invalid_address_error; /* 0198–019F */ + uint64_t ipv6_error_packets; /* 01A0–01A7 */ + uint64_t ipv6_fragrx_overlap; /* 01A8–01AF */ + uint64_t ipv6_fragrx_outoforder; /* 01B0–01B7 */ + uint64_t ipv6_datagram_reassembly_timeout; /* 01B8–01BF */ + uint64_t tcp_tx_segments; /* 01C0–01C7 */ + uint64_t tcp_tx_bytes; /* 01C8–01CF */ + uint64_t tcp_rx_segments; /* 01D0–01D7 */ + uint64_t tcp_rx_byte; /* 01D8–01DF */ + uint64_t tcp_duplicate_ack_retx; /* 01E0–01E7 */ + uint64_t tcp_retx_timer_expired; /* 01E8–01EF */ + uint64_t tcp_rx_duplicate_ack; /* 01F0–01F7 */ + uint64_t tcp_rx_pure_ackr; /* 01F8–01FF */ + uint64_t tcp_tx_delayed_ack; /* 0200–0207 */ + uint64_t tcp_tx_pure_ack; /* 0208–020F */ + uint64_t tcp_rx_segment_error; /* 0210–0217 */ + uint64_t tcp_rx_segment_outoforder; /* 0218–021F */ + uint64_t tcp_rx_window_probe; /* 0220–0227 */ + uint64_t tcp_rx_window_update; /* 0228–022F */ + uint64_t tcp_tx_window_probe_persist; /* 0230–0237 */ + uint64_t ecc_error_correction; /* 0238–023F */ + uint64_t iscsi_pdu_tx; /* 0240-0247 */ + uint64_t iscsi_data_bytes_tx; /* 0248-024F */ + uint64_t iscsi_pdu_rx; /* 0250-0257 */ + uint64_t iscsi_data_bytes_rx; /* 0258-025F */ + uint64_t iscsi_io_completed; /* 0260-0267 */ + uint64_t iscsi_unexpected_io_rx; /* 0268-026F */ + uint64_t iscsi_format_error; /* 0270-0277 */ + uint64_t iscsi_hdr_digest_error; /* 0278-027F */ + uint64_t iscsi_data_digest_error; /* 0280-0287 */ + uint64_t iscsi_sequence_error; /* 0288-028F */ uint32_t tx_cmd_pdu; /* 0290-0293 */ uint32_t tx_resp_pdu; /* 0294-0297 */ uint32_t rx_cmd_pdu; /* 0298-029B */ diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 5cef2527180a..d67c50e0b896 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -276,6 +276,9 @@ int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config); int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr, uint32_t *data, uint32_t count); +uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state); +int qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config); +int qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config); extern int ql4xextended_error_logging; extern int ql4xdontresethba; diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 7dff09f09b71..a3c8bc7706c2 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -606,6 +606,36 @@ static int qla4_83xx_loopback_in_progress(struct scsi_qla_host *ha) return rval; } +static void qla4xxx_update_ipaddr_state(struct scsi_qla_host *ha, + uint32_t ipaddr_idx, + uint32_t ipaddr_fw_state) +{ + uint8_t ipaddr_state; + uint8_t ip_idx; + + ip_idx = ipaddr_idx & 0xF; + ipaddr_state = qla4xxx_set_ipaddr_state((uint8_t)ipaddr_fw_state); + + switch (ip_idx) { + case 0: + ha->ip_config.ipv4_addr_state = ipaddr_state; + break; + case 1: + ha->ip_config.ipv6_link_local_state = ipaddr_state; + break; + case 2: + ha->ip_config.ipv6_addr0_state = ipaddr_state; + break; + case 3: + ha->ip_config.ipv6_addr1_state = ipaddr_state; + break; + default: + ql4_printk(KERN_INFO, ha, "%s: Invalid IPADDR index %d\n", + __func__, ip_idx); + } +} + + /** * qla4xxx_isr_decode_mailbox - decodes mailbox status * @ha: Pointer to host adapter structure. @@ -620,6 +650,7 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, int i; uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; __le32 __iomem *mailbox_out; + uint32_t opcode = 0; if (is_qla8032(ha) || is_qla8042(ha)) mailbox_out = &ha->qla4_83xx_reg->mailbox_out[0]; @@ -698,6 +729,11 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP, sizeof(mbox_sts), (uint8_t *) mbox_sts); + + if ((is_qla8032(ha) || is_qla8042(ha)) && + ha->notify_link_up_comp) + complete(&ha->link_up_comp); + break; case MBOX_ASTS_LINK_DOWN: @@ -741,6 +777,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, "mbox_sts[3]=%04x\n", ha->host_no, mbox_sts[0], mbox_sts[2], mbox_sts[3]); + qla4xxx_update_ipaddr_state(ha, mbox_sts[5], + mbox_sts[3]); /* mbox_sts[2] = Old ACB state * mbox_sts[3] = new ACB state */ if ((mbox_sts[3] == ACB_STATE_VALID) && @@ -841,8 +879,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, break; case MBOX_ASTS_IDC_REQUEST_NOTIFICATION: - { - uint32_t opcode; if (is_qla8032(ha) || is_qla8042(ha)) { DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n", @@ -862,7 +898,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, } } break; - } case MBOX_ASTS_IDC_COMPLETE: if (is_qla8032(ha) || is_qla8042(ha)) { @@ -875,6 +910,14 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, "scsi:%ld: AEN %04x IDC Complete notification\n", ha->host_no, mbox_sts[0])); + opcode = mbox_sts[1] >> 16; + if (ha->notify_idc_comp) + complete(&ha->idc_comp); + + if ((opcode == MBOX_CMD_SET_PORT_CONFIG) || + (opcode == MBOX_CMD_PORT_RESET)) + ha->idc_info.info2 = mbox_sts[3]; + if (qla4_83xx_loopback_in_progress(ha)) { set_bit(AF_LOOPBACK, &ha->flags); } else { @@ -907,6 +950,8 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld: AEN %04x Received IDC Extend Timeout notification\n", ha->host_no, mbox_sts[0])); + /* new IDC timeout */ + ha->idc_extend_tmo = mbox_sts[1]; break; case MBOX_ASTS_INITIALIZATION_FAILED: diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 22cbd005bdf4..9ae8ca3b69f9 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -418,6 +418,38 @@ qla4xxx_get_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, return QLA_SUCCESS; } +uint8_t qla4xxx_set_ipaddr_state(uint8_t fw_ipaddr_state) +{ + uint8_t ipaddr_state; + + switch (fw_ipaddr_state) { + case IP_ADDRSTATE_UNCONFIGURED: + ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; + break; + case IP_ADDRSTATE_INVALID: + ipaddr_state = ISCSI_IPDDRESS_STATE_INVALID; + break; + case IP_ADDRSTATE_ACQUIRING: + ipaddr_state = ISCSI_IPDDRESS_STATE_ACQUIRING; + break; + case IP_ADDRSTATE_TENTATIVE: + ipaddr_state = ISCSI_IPDDRESS_STATE_TENTATIVE; + break; + case IP_ADDRSTATE_DEPRICATED: + ipaddr_state = ISCSI_IPDDRESS_STATE_DEPRECATED; + break; + case IP_ADDRSTATE_PREFERRED: + ipaddr_state = ISCSI_IPDDRESS_STATE_VALID; + break; + case IP_ADDRSTATE_DISABLING: + ipaddr_state = ISCSI_IPDDRESS_STATE_DISABLING; + break; + default: + ipaddr_state = ISCSI_IPDDRESS_STATE_UNCONFIGURED; + } + return ipaddr_state; +} + static void qla4xxx_update_local_ip(struct scsi_qla_host *ha, struct addr_ctrl_blk *init_fw_cb) @@ -425,7 +457,7 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, ha->ip_config.tcp_options = le16_to_cpu(init_fw_cb->ipv4_tcp_opts); ha->ip_config.ipv4_options = le16_to_cpu(init_fw_cb->ipv4_ip_opts); ha->ip_config.ipv4_addr_state = - le16_to_cpu(init_fw_cb->ipv4_addr_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv4_addr_state); ha->ip_config.eth_mtu_size = le16_to_cpu(init_fw_cb->eth_mtu_size); ha->ip_config.ipv4_port = le16_to_cpu(init_fw_cb->ipv4_port); @@ -434,6 +466,8 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, ha->ip_config.ipv6_options = le16_to_cpu(init_fw_cb->ipv6_opts); ha->ip_config.ipv6_addl_options = le16_to_cpu(init_fw_cb->ipv6_addtl_opts); + ha->ip_config.ipv6_tcp_options = + le16_to_cpu(init_fw_cb->ipv6_tcp_opts); } /* Save IPv4 Address Info */ @@ -448,17 +482,65 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, sizeof(init_fw_cb->ipv4_gw_addr))); ha->ip_config.ipv4_vlan_tag = be16_to_cpu(init_fw_cb->ipv4_vlan_tag); + ha->ip_config.control = init_fw_cb->control; + ha->ip_config.tcp_wsf = init_fw_cb->ipv4_tcp_wsf; + ha->ip_config.ipv4_tos = init_fw_cb->ipv4_tos; + ha->ip_config.ipv4_cache_id = init_fw_cb->ipv4_cacheid; + ha->ip_config.ipv4_alt_cid_len = init_fw_cb->ipv4_dhcp_alt_cid_len; + memcpy(ha->ip_config.ipv4_alt_cid, init_fw_cb->ipv4_dhcp_alt_cid, + min(sizeof(ha->ip_config.ipv4_alt_cid), + sizeof(init_fw_cb->ipv4_dhcp_alt_cid))); + ha->ip_config.ipv4_vid_len = init_fw_cb->ipv4_dhcp_vid_len; + memcpy(ha->ip_config.ipv4_vid, init_fw_cb->ipv4_dhcp_vid, + min(sizeof(ha->ip_config.ipv4_vid), + sizeof(init_fw_cb->ipv4_dhcp_vid))); + ha->ip_config.ipv4_ttl = init_fw_cb->ipv4_ttl; + ha->ip_config.def_timeout = le16_to_cpu(init_fw_cb->def_timeout); + ha->ip_config.abort_timer = init_fw_cb->abort_timer; + ha->ip_config.iscsi_options = le16_to_cpu(init_fw_cb->iscsi_opts); + ha->ip_config.iscsi_max_pdu_size = + le16_to_cpu(init_fw_cb->iscsi_max_pdu_size); + ha->ip_config.iscsi_first_burst_len = + le16_to_cpu(init_fw_cb->iscsi_fburst_len); + ha->ip_config.iscsi_max_outstnd_r2t = + le16_to_cpu(init_fw_cb->iscsi_max_outstnd_r2t); + ha->ip_config.iscsi_max_burst_len = + le16_to_cpu(init_fw_cb->iscsi_max_burst_len); + memcpy(ha->ip_config.iscsi_name, init_fw_cb->iscsi_name, + min(sizeof(ha->ip_config.iscsi_name), + sizeof(init_fw_cb->iscsi_name))); if (is_ipv6_enabled(ha)) { /* Save IPv6 Address */ ha->ip_config.ipv6_link_local_state = - le16_to_cpu(init_fw_cb->ipv6_lnk_lcl_addr_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_lnk_lcl_addr_state); ha->ip_config.ipv6_addr0_state = - le16_to_cpu(init_fw_cb->ipv6_addr0_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr0_state); ha->ip_config.ipv6_addr1_state = - le16_to_cpu(init_fw_cb->ipv6_addr1_state); - ha->ip_config.ipv6_default_router_state = - le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state); + qla4xxx_set_ipaddr_state(init_fw_cb->ipv6_addr1_state); + + switch (le16_to_cpu(init_fw_cb->ipv6_dflt_rtr_state)) { + case IPV6_RTRSTATE_UNKNOWN: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_UNKNOWN; + break; + case IPV6_RTRSTATE_MANUAL: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_MANUAL; + break; + case IPV6_RTRSTATE_ADVERTISED: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_ADVERTISED; + break; + case IPV6_RTRSTATE_STALE: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_STALE; + break; + default: + ha->ip_config.ipv6_default_router_state = + ISCSI_ROUTER_STATE_UNKNOWN; + } + ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[0] = 0xFE; ha->ip_config.ipv6_link_local_addr.in6_u.u6_addr8[1] = 0x80; @@ -479,6 +561,23 @@ qla4xxx_update_local_ip(struct scsi_qla_host *ha, ha->ip_config.ipv6_vlan_tag = be16_to_cpu(init_fw_cb->ipv6_vlan_tag); ha->ip_config.ipv6_port = le16_to_cpu(init_fw_cb->ipv6_port); + ha->ip_config.ipv6_cache_id = init_fw_cb->ipv6_cache_id; + ha->ip_config.ipv6_flow_lbl = + le16_to_cpu(init_fw_cb->ipv6_flow_lbl); + ha->ip_config.ipv6_traffic_class = + init_fw_cb->ipv6_traffic_class; + ha->ip_config.ipv6_hop_limit = init_fw_cb->ipv6_hop_limit; + ha->ip_config.ipv6_nd_reach_time = + le32_to_cpu(init_fw_cb->ipv6_nd_reach_time); + ha->ip_config.ipv6_nd_rexmit_timer = + le32_to_cpu(init_fw_cb->ipv6_nd_rexmit_timer); + ha->ip_config.ipv6_nd_stale_timeout = + le32_to_cpu(init_fw_cb->ipv6_nd_stale_timeout); + ha->ip_config.ipv6_dup_addr_detect_count = + init_fw_cb->ipv6_dup_addr_detect_count; + ha->ip_config.ipv6_gw_advrt_mtu = + le32_to_cpu(init_fw_cb->ipv6_gw_advrt_mtu); + ha->ip_config.ipv6_tcp_wsf = init_fw_cb->ipv6_tcp_wsf; } } @@ -2317,3 +2416,46 @@ exit_config_acb: rval == QLA_SUCCESS ? "SUCCEEDED" : "FAILED")); return rval; } + +int qla4_83xx_get_port_config(struct scsi_qla_host *ha, uint32_t *config) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + int status; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_GET_PORT_CONFIG; + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, + mbox_cmd, mbox_sts); + if (status == QLA_SUCCESS) + *config = mbox_sts[1]; + else + ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, + mbox_sts[0]); + + return status; +} + +int qla4_83xx_set_port_config(struct scsi_qla_host *ha, uint32_t *config) +{ + uint32_t mbox_cmd[MBOX_REG_COUNT]; + uint32_t mbox_sts[MBOX_REG_COUNT]; + int status; + + memset(&mbox_cmd, 0, sizeof(mbox_cmd)); + memset(&mbox_sts, 0, sizeof(mbox_sts)); + + mbox_cmd[0] = MBOX_CMD_SET_PORT_CONFIG; + mbox_cmd[1] = *config; + + status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT, + mbox_cmd, mbox_sts); + if (status != QLA_SUCCESS) + ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__, + mbox_sts[0]); + + return status; +} diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index a28d5e624aab..c21adc338cf1 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -151,6 +151,7 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx); static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len); +static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len); /* * SCSI host template entry points @@ -262,6 +263,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { .login_flashnode = qla4xxx_sysfs_ddb_login, .logout_flashnode = qla4xxx_sysfs_ddb_logout, .logout_flashnode_sid = qla4xxx_sysfs_ddb_logout_sid, + .get_host_stats = qla4xxx_get_host_stats, }; static struct scsi_transport_template *qla4xxx_scsi_transport; @@ -419,6 +421,7 @@ static umode_t qla4_attr_is_visible(int param_type, int param) case ISCSI_PARAM_EXP_STATSN: case ISCSI_PARAM_DISCOVERY_PARENT_IDX: case ISCSI_PARAM_DISCOVERY_PARENT_TYPE: + case ISCSI_PARAM_LOCAL_IPADDR: return S_IRUGO; default: return 0; @@ -440,6 +443,65 @@ static umode_t qla4_attr_is_visible(int param_type, int param) case ISCSI_NET_PARAM_VLAN_ENABLED: case ISCSI_NET_PARAM_MTU: case ISCSI_NET_PARAM_PORT: + case ISCSI_NET_PARAM_IPADDR_STATE: + case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE: + case ISCSI_NET_PARAM_IPV6_ROUTER_STATE: + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + case ISCSI_NET_PARAM_TCP_WSF: + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + case ISCSI_NET_PARAM_CACHE_ID: + case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: + case ISCSI_NET_PARAM_IPV4_TOS_EN: + case ISCSI_NET_PARAM_IPV4_TOS: + case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: + case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: + case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: + case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: + case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: + case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: + case ISCSI_NET_PARAM_REDIRECT_EN: + case ISCSI_NET_PARAM_IPV4_TTL: + case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: + case ISCSI_NET_PARAM_IPV6_MLD_EN: + case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: + case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: + case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: + case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: + case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: + case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: + case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: + case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: + return S_IRUGO; + default: + return 0; + } + case ISCSI_IFACE_PARAM: + switch (param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + case ISCSI_IFACE_PARAM_HDRDGST_EN: + case ISCSI_IFACE_PARAM_DATADGST_EN: + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + case ISCSI_IFACE_PARAM_ERL: + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + case ISCSI_IFACE_PARAM_FIRST_BURST: + case ISCSI_IFACE_PARAM_MAX_R2T: + case ISCSI_IFACE_PARAM_MAX_BURST: + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + case ISCSI_IFACE_PARAM_INITIATOR_NAME: return S_IRUGO; default: return 0; @@ -511,6 +573,65 @@ static umode_t qla4_attr_is_visible(int param_type, int param) return 0; } +/** + * qla4xxx_create chap_list - Create CHAP list from FLASH + * @ha: pointer to adapter structure + * + * Read flash and make a list of CHAP entries, during login when a CHAP entry + * is received, it will be checked in this list. If entry exist then the CHAP + * entry index is set in the DDB. If CHAP entry does not exist in this list + * then a new entry is added in FLASH in CHAP table and the index obtained is + * used in the DDB. + **/ +static void qla4xxx_create_chap_list(struct scsi_qla_host *ha) +{ + int rval = 0; + uint8_t *chap_flash_data = NULL; + uint32_t offset; + dma_addr_t chap_dma; + uint32_t chap_size = 0; + + if (is_qla40XX(ha)) + chap_size = MAX_CHAP_ENTRIES_40XX * + sizeof(struct ql4_chap_table); + else /* Single region contains CHAP info for both + * ports which is divided into half for each port. + */ + chap_size = ha->hw.flt_chap_size / 2; + + chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size, + &chap_dma, GFP_KERNEL); + if (!chap_flash_data) { + ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n"); + return; + } + + if (is_qla40XX(ha)) { + offset = FLASH_CHAP_OFFSET; + } else { + offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); + if (ha->port_num == 1) + offset += chap_size; + } + + rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); + if (rval != QLA_SUCCESS) + goto exit_chap_list; + + if (ha->chap_list == NULL) + ha->chap_list = vmalloc(chap_size); + if (ha->chap_list == NULL) { + ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n"); + goto exit_chap_list; + } + + memset(ha->chap_list, 0, chap_size); + memcpy(ha->chap_list, chap_flash_data, chap_size); + +exit_chap_list: + dma_free_coherent(&ha->pdev->dev, chap_size, chap_flash_data, chap_dma); +} + static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha, int16_t chap_index, struct ql4_chap_table **chap_entry) @@ -624,6 +745,8 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, goto exit_get_chap_list; } + qla4xxx_create_chap_list(ha); + chap_rec = (struct iscsi_chap_rec *) buf; mutex_lock(&ha->chap_sem); for (i = chap_tbl_idx; i < max_chap_entries; i++) { @@ -802,6 +925,7 @@ static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) int type; int rem = len; int rc = 0; + int size; memset(&chap_rec, 0, sizeof(chap_rec)); @@ -816,12 +940,14 @@ static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) chap_rec.chap_type = param_info->value[0]; break; case ISCSI_CHAP_PARAM_USERNAME: - memcpy(chap_rec.username, param_info->value, - param_info->len); + size = min_t(size_t, sizeof(chap_rec.username), + param_info->len); + memcpy(chap_rec.username, param_info->value, size); break; case ISCSI_CHAP_PARAM_PASSWORD: - memcpy(chap_rec.password, param_info->value, - param_info->len); + size = min_t(size_t, sizeof(chap_rec.password), + param_info->len); + memcpy(chap_rec.password, param_info->value, size); break; case ISCSI_CHAP_PARAM_PASSWORD_LEN: chap_rec.password_length = param_info->value[0]; @@ -888,113 +1014,646 @@ exit_set_chap: return rc; } + +static int qla4xxx_get_host_stats(struct Scsi_Host *shost, char *buf, int len) +{ + struct scsi_qla_host *ha = to_qla_host(shost); + struct iscsi_offload_host_stats *host_stats = NULL; + int host_stats_size; + int ret = 0; + int ddb_idx = 0; + struct ql_iscsi_stats *ql_iscsi_stats = NULL; + int stats_size; + dma_addr_t iscsi_stats_dma; + + DEBUG2(ql4_printk(KERN_INFO, ha, "Func: %s\n", __func__)); + + host_stats_size = sizeof(struct iscsi_offload_host_stats); + + if (host_stats_size != len) { + ql4_printk(KERN_INFO, ha, "%s: host_stats size mismatch expected = %d, is = %d\n", + __func__, len, host_stats_size); + ret = -EINVAL; + goto exit_host_stats; + } + host_stats = (struct iscsi_offload_host_stats *)buf; + + if (!buf) { + ret = -ENOMEM; + goto exit_host_stats; + } + + stats_size = PAGE_ALIGN(sizeof(struct ql_iscsi_stats)); + + ql_iscsi_stats = dma_alloc_coherent(&ha->pdev->dev, stats_size, + &iscsi_stats_dma, GFP_KERNEL); + if (!ql_iscsi_stats) { + ql4_printk(KERN_ERR, ha, + "Unable to allocate memory for iscsi stats\n"); + goto exit_host_stats; + } + + ret = qla4xxx_get_mgmt_data(ha, ddb_idx, stats_size, + iscsi_stats_dma); + if (ret != QLA_SUCCESS) { + ql4_printk(KERN_ERR, ha, + "Unable to retrieve iscsi stats\n"); + goto exit_host_stats; + } + host_stats->mactx_frames = le64_to_cpu(ql_iscsi_stats->mac_tx_frames); + host_stats->mactx_bytes = le64_to_cpu(ql_iscsi_stats->mac_tx_bytes); + host_stats->mactx_multicast_frames = + le64_to_cpu(ql_iscsi_stats->mac_tx_multicast_frames); + host_stats->mactx_broadcast_frames = + le64_to_cpu(ql_iscsi_stats->mac_tx_broadcast_frames); + host_stats->mactx_pause_frames = + le64_to_cpu(ql_iscsi_stats->mac_tx_pause_frames); + host_stats->mactx_control_frames = + le64_to_cpu(ql_iscsi_stats->mac_tx_control_frames); + host_stats->mactx_deferral = + le64_to_cpu(ql_iscsi_stats->mac_tx_deferral); + host_stats->mactx_excess_deferral = + le64_to_cpu(ql_iscsi_stats->mac_tx_excess_deferral); + host_stats->mactx_late_collision = + le64_to_cpu(ql_iscsi_stats->mac_tx_late_collision); + host_stats->mactx_abort = le64_to_cpu(ql_iscsi_stats->mac_tx_abort); + host_stats->mactx_single_collision = + le64_to_cpu(ql_iscsi_stats->mac_tx_single_collision); + host_stats->mactx_multiple_collision = + le64_to_cpu(ql_iscsi_stats->mac_tx_multiple_collision); + host_stats->mactx_collision = + le64_to_cpu(ql_iscsi_stats->mac_tx_collision); + host_stats->mactx_frames_dropped = + le64_to_cpu(ql_iscsi_stats->mac_tx_frames_dropped); + host_stats->mactx_jumbo_frames = + le64_to_cpu(ql_iscsi_stats->mac_tx_jumbo_frames); + host_stats->macrx_frames = le64_to_cpu(ql_iscsi_stats->mac_rx_frames); + host_stats->macrx_bytes = le64_to_cpu(ql_iscsi_stats->mac_rx_bytes); + host_stats->macrx_unknown_control_frames = + le64_to_cpu(ql_iscsi_stats->mac_rx_unknown_control_frames); + host_stats->macrx_pause_frames = + le64_to_cpu(ql_iscsi_stats->mac_rx_pause_frames); + host_stats->macrx_control_frames = + le64_to_cpu(ql_iscsi_stats->mac_rx_control_frames); + host_stats->macrx_dribble = + le64_to_cpu(ql_iscsi_stats->mac_rx_dribble); + host_stats->macrx_frame_length_error = + le64_to_cpu(ql_iscsi_stats->mac_rx_frame_length_error); + host_stats->macrx_jabber = le64_to_cpu(ql_iscsi_stats->mac_rx_jabber); + host_stats->macrx_carrier_sense_error = + le64_to_cpu(ql_iscsi_stats->mac_rx_carrier_sense_error); + host_stats->macrx_frame_discarded = + le64_to_cpu(ql_iscsi_stats->mac_rx_frame_discarded); + host_stats->macrx_frames_dropped = + le64_to_cpu(ql_iscsi_stats->mac_rx_frames_dropped); + host_stats->mac_crc_error = le64_to_cpu(ql_iscsi_stats->mac_crc_error); + host_stats->mac_encoding_error = + le64_to_cpu(ql_iscsi_stats->mac_encoding_error); + host_stats->macrx_length_error_large = + le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_large); + host_stats->macrx_length_error_small = + le64_to_cpu(ql_iscsi_stats->mac_rx_length_error_small); + host_stats->macrx_multicast_frames = + le64_to_cpu(ql_iscsi_stats->mac_rx_multicast_frames); + host_stats->macrx_broadcast_frames = + le64_to_cpu(ql_iscsi_stats->mac_rx_broadcast_frames); + host_stats->iptx_packets = le64_to_cpu(ql_iscsi_stats->ip_tx_packets); + host_stats->iptx_bytes = le64_to_cpu(ql_iscsi_stats->ip_tx_bytes); + host_stats->iptx_fragments = + le64_to_cpu(ql_iscsi_stats->ip_tx_fragments); + host_stats->iprx_packets = le64_to_cpu(ql_iscsi_stats->ip_rx_packets); + host_stats->iprx_bytes = le64_to_cpu(ql_iscsi_stats->ip_rx_bytes); + host_stats->iprx_fragments = + le64_to_cpu(ql_iscsi_stats->ip_rx_fragments); + host_stats->ip_datagram_reassembly = + le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly); + host_stats->ip_invalid_address_error = + le64_to_cpu(ql_iscsi_stats->ip_invalid_address_error); + host_stats->ip_error_packets = + le64_to_cpu(ql_iscsi_stats->ip_error_packets); + host_stats->ip_fragrx_overlap = + le64_to_cpu(ql_iscsi_stats->ip_fragrx_overlap); + host_stats->ip_fragrx_outoforder = + le64_to_cpu(ql_iscsi_stats->ip_fragrx_outoforder); + host_stats->ip_datagram_reassembly_timeout = + le64_to_cpu(ql_iscsi_stats->ip_datagram_reassembly_timeout); + host_stats->ipv6tx_packets = + le64_to_cpu(ql_iscsi_stats->ipv6_tx_packets); + host_stats->ipv6tx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_tx_bytes); + host_stats->ipv6tx_fragments = + le64_to_cpu(ql_iscsi_stats->ipv6_tx_fragments); + host_stats->ipv6rx_packets = + le64_to_cpu(ql_iscsi_stats->ipv6_rx_packets); + host_stats->ipv6rx_bytes = le64_to_cpu(ql_iscsi_stats->ipv6_rx_bytes); + host_stats->ipv6rx_fragments = + le64_to_cpu(ql_iscsi_stats->ipv6_rx_fragments); + host_stats->ipv6_datagram_reassembly = + le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly); + host_stats->ipv6_invalid_address_error = + le64_to_cpu(ql_iscsi_stats->ipv6_invalid_address_error); + host_stats->ipv6_error_packets = + le64_to_cpu(ql_iscsi_stats->ipv6_error_packets); + host_stats->ipv6_fragrx_overlap = + le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_overlap); + host_stats->ipv6_fragrx_outoforder = + le64_to_cpu(ql_iscsi_stats->ipv6_fragrx_outoforder); + host_stats->ipv6_datagram_reassembly_timeout = + le64_to_cpu(ql_iscsi_stats->ipv6_datagram_reassembly_timeout); + host_stats->tcptx_segments = + le64_to_cpu(ql_iscsi_stats->tcp_tx_segments); + host_stats->tcptx_bytes = le64_to_cpu(ql_iscsi_stats->tcp_tx_bytes); + host_stats->tcprx_segments = + le64_to_cpu(ql_iscsi_stats->tcp_rx_segments); + host_stats->tcprx_byte = le64_to_cpu(ql_iscsi_stats->tcp_rx_byte); + host_stats->tcp_duplicate_ack_retx = + le64_to_cpu(ql_iscsi_stats->tcp_duplicate_ack_retx); + host_stats->tcp_retx_timer_expired = + le64_to_cpu(ql_iscsi_stats->tcp_retx_timer_expired); + host_stats->tcprx_duplicate_ack = + le64_to_cpu(ql_iscsi_stats->tcp_rx_duplicate_ack); + host_stats->tcprx_pure_ackr = + le64_to_cpu(ql_iscsi_stats->tcp_rx_pure_ackr); + host_stats->tcptx_delayed_ack = + le64_to_cpu(ql_iscsi_stats->tcp_tx_delayed_ack); + host_stats->tcptx_pure_ack = + le64_to_cpu(ql_iscsi_stats->tcp_tx_pure_ack); + host_stats->tcprx_segment_error = + le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_error); + host_stats->tcprx_segment_outoforder = + le64_to_cpu(ql_iscsi_stats->tcp_rx_segment_outoforder); + host_stats->tcprx_window_probe = + le64_to_cpu(ql_iscsi_stats->tcp_rx_window_probe); + host_stats->tcprx_window_update = + le64_to_cpu(ql_iscsi_stats->tcp_rx_window_update); + host_stats->tcptx_window_probe_persist = + le64_to_cpu(ql_iscsi_stats->tcp_tx_window_probe_persist); + host_stats->ecc_error_correction = + le64_to_cpu(ql_iscsi_stats->ecc_error_correction); + host_stats->iscsi_pdu_tx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_tx); + host_stats->iscsi_data_bytes_tx = + le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_tx); + host_stats->iscsi_pdu_rx = le64_to_cpu(ql_iscsi_stats->iscsi_pdu_rx); + host_stats->iscsi_data_bytes_rx = + le64_to_cpu(ql_iscsi_stats->iscsi_data_bytes_rx); + host_stats->iscsi_io_completed = + le64_to_cpu(ql_iscsi_stats->iscsi_io_completed); + host_stats->iscsi_unexpected_io_rx = + le64_to_cpu(ql_iscsi_stats->iscsi_unexpected_io_rx); + host_stats->iscsi_format_error = + le64_to_cpu(ql_iscsi_stats->iscsi_format_error); + host_stats->iscsi_hdr_digest_error = + le64_to_cpu(ql_iscsi_stats->iscsi_hdr_digest_error); + host_stats->iscsi_data_digest_error = + le64_to_cpu(ql_iscsi_stats->iscsi_data_digest_error); + host_stats->iscsi_sequence_error = + le64_to_cpu(ql_iscsi_stats->iscsi_sequence_error); +exit_host_stats: + if (ql_iscsi_stats) + dma_free_coherent(&ha->pdev->dev, host_stats_size, + ql_iscsi_stats, iscsi_stats_dma); + + ql4_printk(KERN_INFO, ha, "%s: Get host stats done\n", + __func__); + return ret; +} + static int qla4xxx_get_iface_param(struct iscsi_iface *iface, enum iscsi_param_type param_type, int param, char *buf) { struct Scsi_Host *shost = iscsi_iface_to_shost(iface); struct scsi_qla_host *ha = to_qla_host(shost); + int ival; + char *pval = NULL; int len = -ENOSYS; - if (param_type != ISCSI_NET_PARAM) - return -ENOSYS; + if (param_type == ISCSI_NET_PARAM) { + switch (param) { + case ISCSI_NET_PARAM_IPV4_ADDR: + len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); + break; + case ISCSI_NET_PARAM_IPV4_SUBNET: + len = sprintf(buf, "%pI4\n", + &ha->ip_config.subnet_mask); + break; + case ISCSI_NET_PARAM_IPV4_GW: + len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway); + break; + case ISCSI_NET_PARAM_IFACE_ENABLE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_IPV4_PROTOCOL_ENABLE, pval); + } else { + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_IPV6_PROTOCOL_ENABLE, pval); + } - switch (param) { - case ISCSI_NET_PARAM_IPV4_ADDR: - len = sprintf(buf, "%pI4\n", &ha->ip_config.ip_address); - break; - case ISCSI_NET_PARAM_IPV4_SUBNET: - len = sprintf(buf, "%pI4\n", &ha->ip_config.subnet_mask); - break; - case ISCSI_NET_PARAM_IPV4_GW: - len = sprintf(buf, "%pI4\n", &ha->ip_config.gateway); - break; - case ISCSI_NET_PARAM_IFACE_ENABLE: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv4_options & - IPOPT_IPV4_PROTOCOL_ENABLE) ? - "enabled" : "disabled"); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_BOOTPROTO: len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_options & - IPV6_OPT_IPV6_PROTOCOL_ENABLE) ? - "enabled" : "disabled"); - break; - case ISCSI_NET_PARAM_IPV4_BOOTPROTO: - len = sprintf(buf, "%s\n", - (ha->ip_config.tcp_options & TCPOPT_DHCP_ENABLE) ? - "dhcp" : "static"); - break; - case ISCSI_NET_PARAM_IPV6_ADDR: - if (iface->iface_num == 0) - len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr0); - if (iface->iface_num == 1) - len = sprintf(buf, "%pI6\n", &ha->ip_config.ipv6_addr1); - break; - case ISCSI_NET_PARAM_IPV6_LINKLOCAL: - len = sprintf(buf, "%pI6\n", - &ha->ip_config.ipv6_link_local_addr); - break; - case ISCSI_NET_PARAM_IPV6_ROUTER: - len = sprintf(buf, "%pI6\n", - &ha->ip_config.ipv6_default_router_addr); - break; - case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_addl_options & - IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ? - "nd" : "static"); - break; - case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_addl_options & - IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ? - "auto" : "static"); - break; - case ISCSI_NET_PARAM_VLAN_ID: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + (ha->ip_config.tcp_options & + TCPOPT_DHCP_ENABLE) ? + "dhcp" : "static"); + break; + case ISCSI_NET_PARAM_IPV6_ADDR: + if (iface->iface_num == 0) + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_addr0); + if (iface->iface_num == 1) + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_addr1); + break; + case ISCSI_NET_PARAM_IPV6_LINKLOCAL: + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_link_local_addr); + break; + case ISCSI_NET_PARAM_IPV6_ROUTER: + len = sprintf(buf, "%pI6\n", + &ha->ip_config.ipv6_default_router_addr); + break; + case ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG: + pval = (ha->ip_config.ipv6_addl_options & + IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) ? + "nd" : "static"; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: + pval = (ha->ip_config.ipv6_addl_options & + IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR) ? + "auto" : "static"; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_VLAN_ID: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ival = ha->ip_config.ipv4_vlan_tag & + ISCSI_MAX_VLAN_ID; + else + ival = ha->ip_config.ipv6_vlan_tag & + ISCSI_MAX_VLAN_ID; + + len = sprintf(buf, "%d\n", ival); + break; + case ISCSI_NET_PARAM_VLAN_PRIORITY: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ival = (ha->ip_config.ipv4_vlan_tag >> 13) & + ISCSI_MAX_VLAN_PRIORITY; + else + ival = (ha->ip_config.ipv6_vlan_tag >> 13) & + ISCSI_MAX_VLAN_PRIORITY; + + len = sprintf(buf, "%d\n", ival); + break; + case ISCSI_NET_PARAM_VLAN_ENABLED: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_VLAN_TAGGING_ENABLE, pval); + } else { + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_VLAN_TAGGING_ENABLE, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_MTU: + len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size); + break; + case ISCSI_NET_PARAM_PORT: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%d\n", + ha->ip_config.ipv4_port); + else + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_port); + break; + case ISCSI_NET_PARAM_IPADDR_STATE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv4_addr_state); + } else { + if (iface->iface_num == 0) + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv6_addr0_state); + else if (iface->iface_num == 1) + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv6_addr1_state); + } + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE: + pval = iscsi_get_ipaddress_state_name( + ha->ip_config.ipv6_link_local_state); + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_ROUTER_STATE: + pval = iscsi_get_router_state_name( + ha->ip_config.ipv6_default_router_state); + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(~ha->ip_config.tcp_options, + TCPOPT_DELAYED_ACK_DISABLE, pval); + } else { + OP_STATE(~ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_DELAYED_ACK_DISABLE, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(~ha->ip_config.tcp_options, + TCPOPT_NAGLE_ALGO_DISABLE, pval); + } else { + OP_STATE(~ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_NAGLE_ALGO_DISABLE, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(~ha->ip_config.tcp_options, + TCPOPT_WINDOW_SCALE_DISABLE, pval); + } else { + OP_STATE(~ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_WINDOW_SCALE_DISABLE, + pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_TCP_WSF: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%d\n", + ha->ip_config.tcp_wsf); + else + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_tcp_wsf); + break; + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ival = (ha->ip_config.tcp_options & + TCPOPT_TIMER_SCALE) >> 1; + else + ival = (ha->ip_config.ipv6_tcp_options & + IPV6_TCPOPT_TIMER_SCALE) >> 1; + + len = sprintf(buf, "%d\n", ival); + break; + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.tcp_options, + TCPOPT_TIMESTAMP_ENABLE, pval); + } else { + OP_STATE(ha->ip_config.ipv6_tcp_options, + IPV6_TCPOPT_TIMESTAMP_EN, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_CACHE_ID: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + len = sprintf(buf, "%d\n", + ha->ip_config.ipv4_cache_id); + else + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_cache_id); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: + OP_STATE(ha->ip_config.tcp_options, + TCPOPT_DNS_SERVER_IP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: + OP_STATE(ha->ip_config.tcp_options, + TCPOPT_SLP_DA_INFO_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_TOS_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_IPV4_TOS_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_TOS: + len = sprintf(buf, "%d\n", ha->ip_config.ipv4_tos); + break; + case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_GRAT_ARP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: + OP_STATE(ha->ip_config.ipv4_options, IPOPT_ALT_CID_EN, + pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: + pval = (ha->ip_config.ipv4_alt_cid_len) ? + (char *)ha->ip_config.ipv4_alt_cid : ""; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_REQ_VID_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_USE_VID_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: + pval = (ha->ip_config.ipv4_vid_len) ? + (char *)ha->ip_config.ipv4_vid : ""; + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_LEARN_IQN_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: + OP_STATE(~ha->ip_config.ipv4_options, + IPOPT_FRAGMENTATION_DISABLE, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_IN_FORWARD_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_REDIRECT_EN: + if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) { + OP_STATE(ha->ip_config.ipv4_options, + IPOPT_ARP_REDIRECT_EN, pval); + } else { + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_REDIRECT_EN, pval); + } + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV4_TTL: + len = sprintf(buf, "%d\n", ha->ip_config.ipv4_ttl); + break; + case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: + OP_STATE(ha->ip_config.ipv6_options, + IPV6_OPT_GRAT_NEIGHBOR_ADV_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_MLD_EN: + OP_STATE(ha->ip_config.ipv6_addl_options, + IPV6_ADDOPT_MLD_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: + len = sprintf(buf, "%u\n", ha->ip_config.ipv6_flow_lbl); + break; + case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: len = sprintf(buf, "%d\n", - (ha->ip_config.ipv4_vlan_tag & - ISCSI_MAX_VLAN_ID)); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + ha->ip_config.ipv6_traffic_class); + break; + case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: len = sprintf(buf, "%d\n", - (ha->ip_config.ipv6_vlan_tag & - ISCSI_MAX_VLAN_ID)); - break; - case ISCSI_NET_PARAM_VLAN_PRIORITY: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) + ha->ip_config.ipv6_hop_limit); + break; + case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: len = sprintf(buf, "%d\n", - ((ha->ip_config.ipv4_vlan_tag >> 13) & - ISCSI_MAX_VLAN_PRIORITY)); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) + ha->ip_config.ipv6_nd_reach_time); + break; + case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: len = sprintf(buf, "%d\n", - ((ha->ip_config.ipv6_vlan_tag >> 13) & - ISCSI_MAX_VLAN_PRIORITY)); - break; - case ISCSI_NET_PARAM_VLAN_ENABLED: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv4_options & - IPOPT_VLAN_TAGGING_ENABLE) ? - "enabled" : "disabled"); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) - len = sprintf(buf, "%s\n", - (ha->ip_config.ipv6_options & - IPV6_OPT_VLAN_TAGGING_ENABLE) ? - "enabled" : "disabled"); - break; - case ISCSI_NET_PARAM_MTU: - len = sprintf(buf, "%d\n", ha->ip_config.eth_mtu_size); - break; - case ISCSI_NET_PARAM_PORT: - if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) - len = sprintf(buf, "%d\n", ha->ip_config.ipv4_port); - else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) - len = sprintf(buf, "%d\n", ha->ip_config.ipv6_port); - break; - default: - len = -ENOSYS; + ha->ip_config.ipv6_nd_rexmit_timer); + break; + case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_nd_stale_timeout); + break; + case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_dup_addr_detect_count); + break; + case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: + len = sprintf(buf, "%d\n", + ha->ip_config.ipv6_gw_advrt_mtu); + break; + default: + len = -ENOSYS; + } + } else if (param_type == ISCSI_IFACE_PARAM) { + switch (param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + len = sprintf(buf, "%d\n", ha->ip_config.def_timeout); + break; + case ISCSI_IFACE_PARAM_HDRDGST_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_HEADER_DIGEST_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DATADGST_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DATA_DIGEST_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_IMMEDIATE_DATA_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_INITIAL_R2T_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DATA_SEQ_INORDER_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DATA_PDU_INORDER_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_ERL: + len = sprintf(buf, "%d\n", + (ha->ip_config.iscsi_options & + ISCSIOPTS_ERL)); + break; + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + len = sprintf(buf, "%u\n", + ha->ip_config.iscsi_max_pdu_size * + BYTE_UNITS); + break; + case ISCSI_IFACE_PARAM_FIRST_BURST: + len = sprintf(buf, "%u\n", + ha->ip_config.iscsi_first_burst_len * + BYTE_UNITS); + break; + case ISCSI_IFACE_PARAM_MAX_R2T: + len = sprintf(buf, "%d\n", + ha->ip_config.iscsi_max_outstnd_r2t); + break; + case ISCSI_IFACE_PARAM_MAX_BURST: + len = sprintf(buf, "%u\n", + ha->ip_config.iscsi_max_burst_len * + BYTE_UNITS); + break; + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_CHAP_AUTH_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_BIDI_CHAP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DISCOVERY_AUTH_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_DISCOVERY_LOGOUT_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + OP_STATE(ha->ip_config.iscsi_options, + ISCSIOPTS_STRICT_LOGIN_COMP_EN, pval); + + len = sprintf(buf, "%s\n", pval); + break; + case ISCSI_IFACE_PARAM_INITIATOR_NAME: + len = sprintf(buf, "%s\n", ha->ip_config.iscsi_name); + break; + default: + len = -ENOSYS; + } } return len; @@ -1366,8 +2025,8 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, cpu_to_le16( IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE); else - ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for " - "IPv6 addr\n"); + ql4_printk(KERN_ERR, ha, + "Invalid autocfg setting for IPv6 addr\n"); break; case ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG: /* Autocfg applies to even interface */ @@ -1383,8 +2042,8 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, init_fw_cb->ipv6_addtl_opts &= cpu_to_le16( ~IPV6_ADDOPT_AUTOCONFIG_LINK_LOCAL_ADDR); else - ql4_printk(KERN_ERR, ha, "Invalid autocfg setting for " - "IPv6 linklocal addr\n"); + ql4_printk(KERN_ERR, ha, + "Invalid autocfg setting for IPv6 linklocal addr\n"); break; case ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG: /* Autocfg applies to even interface */ @@ -1433,6 +2092,135 @@ static void qla4xxx_set_ipv6(struct scsi_qla_host *ha, init_fw_cb->ipv6_port = cpu_to_le16(*(uint16_t *)iface_param->value); break; + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_DELAYED_ACK_DISABLE); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_DELAYED_ACK_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_NAGLE_ALGO_DISABLE); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_NAGLE_ALGO_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_WINDOW_SCALE_DISABLE); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_WINDOW_SCALE_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_tcp_wsf = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_TIMER_SCALE); + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16((iface_param->value[0] << 1) & + IPV6_TCPOPT_TIMER_SCALE); + break; + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_tcp_opts |= + cpu_to_le16(IPV6_TCPOPT_TIMESTAMP_EN); + else + init_fw_cb->ipv6_tcp_opts &= + cpu_to_le16(~IPV6_TCPOPT_TIMESTAMP_EN); + break; + case ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_opts |= + cpu_to_le16(IPV6_OPT_GRAT_NEIGHBOR_ADV_EN); + else + init_fw_cb->ipv6_opts &= + cpu_to_le16(~IPV6_OPT_GRAT_NEIGHBOR_ADV_EN); + break; + case ISCSI_NET_PARAM_REDIRECT_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_opts |= + cpu_to_le16(IPV6_OPT_REDIRECT_EN); + else + init_fw_cb->ipv6_opts &= + cpu_to_le16(~IPV6_OPT_REDIRECT_EN); + break; + case ISCSI_NET_PARAM_IPV6_MLD_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv6_addtl_opts |= + cpu_to_le16(IPV6_ADDOPT_MLD_EN); + else + init_fw_cb->ipv6_addtl_opts &= + cpu_to_le16(~IPV6_ADDOPT_MLD_EN); + break; + case ISCSI_NET_PARAM_IPV6_FLOW_LABEL: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_flow_lbl = + cpu_to_le16(*(uint16_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_traffic_class = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV6_HOP_LIMIT: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_hop_limit = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_nd_reach_time = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_nd_rexmit_timer = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_ND_STALE_TMO: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_nd_stale_timeout = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; + case ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_dup_addr_detect_count = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv6_gw_advrt_mtu = + cpu_to_le32(*(uint32_t *)iface_param->value); + break; default: ql4_printk(KERN_ERR, ha, "Unknown IPv6 param = %d\n", iface_param->param); @@ -1501,6 +2289,195 @@ static void qla4xxx_set_ipv4(struct scsi_qla_host *ha, init_fw_cb->ipv4_port = cpu_to_le16(*(uint16_t *)iface_param->value); break; + case ISCSI_NET_PARAM_DELAYED_ACK_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_DELAYED_ACK_DISABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_DELAYED_ACK_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_NAGLE_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_NAGLE_ALGO_DISABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_NAGLE_ALGO_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_WINDOW_SCALE_DISABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_WINDOW_SCALE_DISABLE); + break; + case ISCSI_NET_PARAM_TCP_WSF: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_tcp_wsf = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_TCP_TIMER_SCALE: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_tcp_opts &= cpu_to_le16(~TCPOPT_TIMER_SCALE); + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16((iface_param->value[0] << 1) & + TCPOPT_TIMER_SCALE); + break; + case ISCSI_NET_PARAM_TCP_TIMESTAMP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_TIMESTAMP_ENABLE); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_TIMESTAMP_ENABLE); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_DNS_SERVER_IP_EN); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_DNS_SERVER_IP_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_tcp_opts |= + cpu_to_le16(TCPOPT_SLP_DA_INFO_EN); + else + init_fw_cb->ipv4_tcp_opts &= + cpu_to_le16(~TCPOPT_SLP_DA_INFO_EN); + break; + case ISCSI_NET_PARAM_IPV4_TOS_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_IPV4_TOS_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_IPV4_TOS_EN); + break; + case ISCSI_NET_PARAM_IPV4_TOS: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_tos = iface_param->value[0]; + break; + case ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_GRAT_ARP_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_GRAT_ARP_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_ALT_CID_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_ALT_CID_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID: + if (iface_param->iface_num & 0x1) + break; + memcpy(init_fw_cb->ipv4_dhcp_alt_cid, iface_param->value, + (sizeof(init_fw_cb->ipv4_dhcp_alt_cid) - 1)); + init_fw_cb->ipv4_dhcp_alt_cid_len = + strlen(init_fw_cb->ipv4_dhcp_alt_cid); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_REQ_VID_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_REQ_VID_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_USE_VID_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_USE_VID_EN); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID: + if (iface_param->iface_num & 0x1) + break; + memcpy(init_fw_cb->ipv4_dhcp_vid, iface_param->value, + (sizeof(init_fw_cb->ipv4_dhcp_vid) - 1)); + init_fw_cb->ipv4_dhcp_vid_len = + strlen(init_fw_cb->ipv4_dhcp_vid); + break; + case ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_LEARN_IQN_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_LEARN_IQN_EN); + break; + case ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_DISABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_FRAGMENTATION_DISABLE); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_FRAGMENTATION_DISABLE); + break; + case ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_IN_FORWARD_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_IN_FORWARD_EN); + break; + case ISCSI_NET_PARAM_REDIRECT_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->ipv4_ip_opts |= + cpu_to_le16(IPOPT_ARP_REDIRECT_EN); + else + init_fw_cb->ipv4_ip_opts &= + cpu_to_le16(~IPOPT_ARP_REDIRECT_EN); + break; + case ISCSI_NET_PARAM_IPV4_TTL: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->ipv4_ttl = iface_param->value[0]; + break; default: ql4_printk(KERN_ERR, ha, "Unknown IPv4 param = %d\n", iface_param->param); @@ -1508,6 +2485,168 @@ static void qla4xxx_set_ipv4(struct scsi_qla_host *ha, } } +static void qla4xxx_set_iscsi_param(struct scsi_qla_host *ha, + struct iscsi_iface_param_info *iface_param, + struct addr_ctrl_blk *init_fw_cb) +{ + switch (iface_param->param) { + case ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->def_timeout = + cpu_to_le16(*(uint16_t *)iface_param->value); + break; + case ISCSI_IFACE_PARAM_HDRDGST_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_HEADER_DIGEST_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_HEADER_DIGEST_EN); + break; + case ISCSI_IFACE_PARAM_DATADGST_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DATA_DIGEST_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DATA_DIGEST_EN); + break; + case ISCSI_IFACE_PARAM_IMM_DATA_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_IMMEDIATE_DATA_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_IMMEDIATE_DATA_EN); + break; + case ISCSI_IFACE_PARAM_INITIAL_R2T_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_INITIAL_R2T_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_INITIAL_R2T_EN); + break; + case ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DATA_SEQ_INORDER_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DATA_SEQ_INORDER_EN); + break; + case ISCSI_IFACE_PARAM_PDU_INORDER_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DATA_PDU_INORDER_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DATA_PDU_INORDER_EN); + break; + case ISCSI_IFACE_PARAM_ERL: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_opts &= cpu_to_le16(~ISCSIOPTS_ERL); + init_fw_cb->iscsi_opts |= cpu_to_le16(iface_param->value[0] & + ISCSIOPTS_ERL); + break; + case ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_max_pdu_size = + cpu_to_le32(*(uint32_t *)iface_param->value) / + BYTE_UNITS; + break; + case ISCSI_IFACE_PARAM_FIRST_BURST: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_fburst_len = + cpu_to_le32(*(uint32_t *)iface_param->value) / + BYTE_UNITS; + break; + case ISCSI_IFACE_PARAM_MAX_R2T: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_max_outstnd_r2t = + cpu_to_le16(*(uint16_t *)iface_param->value); + break; + case ISCSI_IFACE_PARAM_MAX_BURST: + if (iface_param->iface_num & 0x1) + break; + init_fw_cb->iscsi_max_burst_len = + cpu_to_le32(*(uint32_t *)iface_param->value) / + BYTE_UNITS; + break; + case ISCSI_IFACE_PARAM_CHAP_AUTH_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_CHAP_AUTH_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_CHAP_AUTH_EN); + break; + case ISCSI_IFACE_PARAM_BIDI_CHAP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_BIDI_CHAP_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_BIDI_CHAP_EN); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DISCOVERY_AUTH_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DISCOVERY_AUTH_EN); + break; + case ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_DISCOVERY_LOGOUT_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_DISCOVERY_LOGOUT_EN); + break; + case ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN: + if (iface_param->iface_num & 0x1) + break; + if (iface_param->value[0] == ISCSI_NET_PARAM_ENABLE) + init_fw_cb->iscsi_opts |= + cpu_to_le16(ISCSIOPTS_STRICT_LOGIN_COMP_EN); + else + init_fw_cb->iscsi_opts &= + cpu_to_le16(~ISCSIOPTS_STRICT_LOGIN_COMP_EN); + break; + default: + ql4_printk(KERN_ERR, ha, "Unknown iscsi param = %d\n", + iface_param->param); + break; + } +} + static void qla4xxx_initcb_to_acb(struct addr_ctrl_blk *init_fw_cb) { @@ -1565,40 +2704,47 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) nla_for_each_attr(attr, data, len, rem) { iface_param = nla_data(attr); - if (iface_param->param_type != ISCSI_NET_PARAM) - continue; - - switch (iface_param->iface_type) { - case ISCSI_IFACE_TYPE_IPV4: - switch (iface_param->iface_num) { - case 0: - qla4xxx_set_ipv4(ha, iface_param, init_fw_cb); - break; - default: + if (iface_param->param_type == ISCSI_NET_PARAM) { + switch (iface_param->iface_type) { + case ISCSI_IFACE_TYPE_IPV4: + switch (iface_param->iface_num) { + case 0: + qla4xxx_set_ipv4(ha, iface_param, + init_fw_cb); + break; + default: /* Cannot have more than one IPv4 interface */ - ql4_printk(KERN_ERR, ha, "Invalid IPv4 iface " - "number = %d\n", - iface_param->iface_num); + ql4_printk(KERN_ERR, ha, + "Invalid IPv4 iface number = %d\n", + iface_param->iface_num); + break; + } break; - } - break; - case ISCSI_IFACE_TYPE_IPV6: - switch (iface_param->iface_num) { - case 0: - case 1: - qla4xxx_set_ipv6(ha, iface_param, init_fw_cb); + case ISCSI_IFACE_TYPE_IPV6: + switch (iface_param->iface_num) { + case 0: + case 1: + qla4xxx_set_ipv6(ha, iface_param, + init_fw_cb); + break; + default: + /* Cannot have more than two IPv6 interface */ + ql4_printk(KERN_ERR, ha, + "Invalid IPv6 iface number = %d\n", + iface_param->iface_num); + break; + } break; default: - /* Cannot have more than two IPv6 interface */ - ql4_printk(KERN_ERR, ha, "Invalid IPv6 iface " - "number = %d\n", - iface_param->iface_num); + ql4_printk(KERN_ERR, ha, + "Invalid iface type\n"); break; } - break; - default: - ql4_printk(KERN_ERR, ha, "Invalid iface type\n"); - break; + } else if (iface_param->param_type == ISCSI_IFACE_PARAM) { + qla4xxx_set_iscsi_param(ha, iface_param, + init_fw_cb); + } else { + continue; } } @@ -2538,6 +3684,7 @@ static void qla4xxx_copy_to_sess_conn_params(struct iscsi_conn *conn, unsigned long options = 0; uint16_t ddb_link; uint16_t disc_parent; + char ip_addr[DDB_IPADDR_LEN]; options = le16_to_cpu(fw_ddb_entry->options); conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options); @@ -2619,6 +3766,14 @@ static void qla4xxx_copy_to_sess_conn_params(struct iscsi_conn *conn, iscsi_set_param(conn->cls_conn, ISCSI_PARAM_TARGET_ALIAS, (char *)fw_ddb_entry->iscsi_alias, 0); + + options = le16_to_cpu(fw_ddb_entry->options); + if (options & DDB_OPT_IPV6_DEVICE) { + memset(ip_addr, 0, sizeof(ip_addr)); + sprintf(ip_addr, "%pI6", fw_ddb_entry->link_local_ipv6_addr); + iscsi_set_param(conn->cls_conn, ISCSI_PARAM_LOCAL_IPADDR, + (char *)ip_addr, 0); + } } static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, @@ -5030,64 +6185,6 @@ kset_free: } -/** - * qla4xxx_create chap_list - Create CHAP list from FLASH - * @ha: pointer to adapter structure - * - * Read flash and make a list of CHAP entries, during login when a CHAP entry - * is received, it will be checked in this list. If entry exist then the CHAP - * entry index is set in the DDB. If CHAP entry does not exist in this list - * then a new entry is added in FLASH in CHAP table and the index obtained is - * used in the DDB. - **/ -static void qla4xxx_create_chap_list(struct scsi_qla_host *ha) -{ - int rval = 0; - uint8_t *chap_flash_data = NULL; - uint32_t offset; - dma_addr_t chap_dma; - uint32_t chap_size = 0; - - if (is_qla40XX(ha)) - chap_size = MAX_CHAP_ENTRIES_40XX * - sizeof(struct ql4_chap_table); - else /* Single region contains CHAP info for both - * ports which is divided into half for each port. - */ - chap_size = ha->hw.flt_chap_size / 2; - - chap_flash_data = dma_alloc_coherent(&ha->pdev->dev, chap_size, - &chap_dma, GFP_KERNEL); - if (!chap_flash_data) { - ql4_printk(KERN_ERR, ha, "No memory for chap_flash_data\n"); - return; - } - if (is_qla40XX(ha)) - offset = FLASH_CHAP_OFFSET; - else { - offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2); - if (ha->port_num == 1) - offset += chap_size; - } - - rval = qla4xxx_get_flash(ha, chap_dma, offset, chap_size); - if (rval != QLA_SUCCESS) - goto exit_chap_list; - - if (ha->chap_list == NULL) - ha->chap_list = vmalloc(chap_size); - if (ha->chap_list == NULL) { - ql4_printk(KERN_ERR, ha, "No memory for ha->chap_list\n"); - goto exit_chap_list; - } - - memcpy(ha->chap_list, chap_flash_data, chap_size); - -exit_chap_list: - dma_free_coherent(&ha->pdev->dev, chap_size, - chap_flash_data, chap_dma); -} - static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, struct ql4_tuple_ddb *tddb) { @@ -7521,6 +8618,9 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev, mutex_init(&ha->chap_sem); init_completion(&ha->mbx_intr_comp); init_completion(&ha->disable_acb_comp); + init_completion(&ha->idc_comp); + init_completion(&ha->link_up_comp); + init_completion(&ha->disable_acb_comp); spin_lock_init(&ha->hardware_lock); spin_lock_init(&ha->work_lock); diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index f4fef72c9bcd..9b2946658683 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.04.00-k1" +#define QLA4XXX_DRIVER_VERSION "5.04.00-k3" |