diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 16:16:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 16:16:38 -0400 |
commit | 5aa1c98862d3f365d9cf6d0833d5dc127d2a76e7 (patch) | |
tree | 89cbf0b67634ecc43a863a6ca058ff749df3cce7 /drivers/scsi/qla4xxx | |
parent | 6da6dc2380c3cfe8d6b59d7c3c55fdd7a521fe6c (diff) | |
parent | 9e45dd73234af9a59613dc2989dcc2df2dab847f (diff) |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull first round of SCSI updates from James "Jej B" Bottomley:
"The patch set is mostly driver updates (qla4, qla2 [ISF support
updates], lpfc, aacraid [dual firmware image support]) and a few bug
fixes"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (47 commits)
[SCSI] iscsi_tcp: support PF_MEMALLOC/__GFP_MEMALLOC
[SCSI] libiscsi: avoid unnecessary multiple NULL assignments
[SCSI] qla4xxx: Update driver version to 5.03.00-k8
[SCSI] qla4xxx: Added print statements to display AENs
[SCSI] qla4xxx: Use correct value for max flash node entries
[SCSI] qla4xxx: Restrict logout from boot target session using session id
[SCSI] qla4xxx: Use correct flash ddb offset for ISP40XX
[SCSI] isci: add CONFIG_PM_SLEEP to suspend/resume functions
[SCSI] scsi_dh_alua: Add module parameter to allow failover to non preferred path without STPG
[SCSI] qla2xxx: Update the driver version to 8.05.00.03-k.
[SCSI] qla2xxx: Obtain loopback iteration count from bsg request.
[SCSI] qla2xxx: Add clarifying printk to thermal access fail cases.
[SCSI] qla2xxx: Remove duplicated include form qla_isr.c
[SCSI] qla2xxx: Enhancements to support ISPFx00.
[SCSI] qla4xxx: Update driver version to 5.03.00-k7
[SCSI] qla4xxx: Replace dev type macros with generic portal type macros
[SCSI] scsi_transport_iscsi: Declare portal type string macros for generic use
[SCSI] qla4xxx: Add flash node mgmt support
[SCSI] libiscsi: export function iscsi_switch_str_param
[SCSI] scsi_transport_iscsi: Add flash node mgmt support
...
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.c | 28 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.h | 10 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_dbg.h | 7 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 19 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 38 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 9 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 47 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 120 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 19 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 1731 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 |
11 files changed, 1992 insertions, 38 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c index 5d8fe4f75650..d607eb8e24cb 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.c +++ b/drivers/scsi/qla4xxx/ql4_83xx.c | |||
@@ -1629,9 +1629,37 @@ static void __qla4_83xx_disable_pause(struct scsi_qla_host *ha) | |||
1629 | ql4_printk(KERN_INFO, ha, "Disabled pause frames successfully.\n"); | 1629 | ql4_printk(KERN_INFO, ha, "Disabled pause frames successfully.\n"); |
1630 | } | 1630 | } |
1631 | 1631 | ||
1632 | /** | ||
1633 | * qla4_83xx_eport_init - Initialize EPort. | ||
1634 | * @ha: Pointer to host adapter structure. | ||
1635 | * | ||
1636 | * If EPort hardware is in reset state before disabling pause, there would be | ||
1637 | * serious hardware wedging issues. To prevent this perform eport init everytime | ||
1638 | * before disabling pause frames. | ||
1639 | **/ | ||
1640 | static void qla4_83xx_eport_init(struct scsi_qla_host *ha) | ||
1641 | { | ||
1642 | /* Clear the 8 registers */ | ||
1643 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_REG, 0x0); | ||
1644 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT0, 0x0); | ||
1645 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT1, 0x0); | ||
1646 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT2, 0x0); | ||
1647 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_PORT3, 0x0); | ||
1648 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_SRE_SHIM, 0x0); | ||
1649 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_EPG_SHIM, 0x0); | ||
1650 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_ETHER_PCS, 0x0); | ||
1651 | |||
1652 | /* Write any value to Reset Control register */ | ||
1653 | qla4_83xx_wr_reg_indirect(ha, QLA83XX_RESET_CONTROL, 0xFF); | ||
1654 | |||
1655 | ql4_printk(KERN_INFO, ha, "EPORT is out of reset.\n"); | ||
1656 | } | ||
1657 | |||
1632 | void qla4_83xx_disable_pause(struct scsi_qla_host *ha) | 1658 | void qla4_83xx_disable_pause(struct scsi_qla_host *ha) |
1633 | { | 1659 | { |
1634 | ha->isp_ops->idc_lock(ha); | 1660 | ha->isp_ops->idc_lock(ha); |
1661 | /* Before disabling pause frames, ensure that eport is not in reset */ | ||
1662 | qla4_83xx_eport_init(ha); | ||
1635 | qla4_83xx_dump_pause_control_regs(ha); | 1663 | qla4_83xx_dump_pause_control_regs(ha); |
1636 | __qla4_83xx_disable_pause(ha); | 1664 | __qla4_83xx_disable_pause(ha); |
1637 | ha->isp_ops->idc_unlock(ha); | 1665 | ha->isp_ops->idc_unlock(ha); |
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h index 6a00f903f2a6..fab237fa32cc 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.h +++ b/drivers/scsi/qla4xxx/ql4_83xx.h | |||
@@ -55,6 +55,16 @@ | |||
55 | #define QLA83XX_SET_PAUSE_VAL 0x0 | 55 | #define QLA83XX_SET_PAUSE_VAL 0x0 |
56 | #define QLA83XX_SET_TC_MAX_CELL_VAL 0x03FF03FF | 56 | #define QLA83XX_SET_TC_MAX_CELL_VAL 0x03FF03FF |
57 | 57 | ||
58 | #define QLA83XX_RESET_CONTROL 0x28084E50 | ||
59 | #define QLA83XX_RESET_REG 0x28084E60 | ||
60 | #define QLA83XX_RESET_PORT0 0x28084E70 | ||
61 | #define QLA83XX_RESET_PORT1 0x28084E80 | ||
62 | #define QLA83XX_RESET_PORT2 0x28084E90 | ||
63 | #define QLA83XX_RESET_PORT3 0x28084EA0 | ||
64 | #define QLA83XX_RESET_SRE_SHIM 0x28084EB0 | ||
65 | #define QLA83XX_RESET_EPG_SHIM 0x28084EC0 | ||
66 | #define QLA83XX_RESET_ETHER_PCS 0x28084ED0 | ||
67 | |||
58 | /* qla_83xx_reg_tbl registers */ | 68 | /* qla_83xx_reg_tbl registers */ |
59 | #define QLA83XX_PEG_HALT_STATUS1 0x34A8 | 69 | #define QLA83XX_PEG_HALT_STATUS1 0x34A8 |
60 | #define QLA83XX_PEG_HALT_STATUS2 0x34AC | 70 | #define QLA83XX_PEG_HALT_STATUS2 0x34AC |
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h index 5b0afc18ef18..51c365bcf912 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.h +++ b/drivers/scsi/qla4xxx/ql4_dbg.h | |||
@@ -12,6 +12,7 @@ | |||
12 | /* #define QL_DEBUG_LEVEL_3 */ /* Output function tracing */ | 12 | /* #define QL_DEBUG_LEVEL_3 */ /* Output function tracing */ |
13 | /* #define QL_DEBUG_LEVEL_4 */ | 13 | /* #define QL_DEBUG_LEVEL_4 */ |
14 | /* #define QL_DEBUG_LEVEL_5 */ | 14 | /* #define QL_DEBUG_LEVEL_5 */ |
15 | /* #define QL_DEBUG_LEVEL_7 */ | ||
15 | /* #define QL_DEBUG_LEVEL_9 */ | 16 | /* #define QL_DEBUG_LEVEL_9 */ |
16 | 17 | ||
17 | #define QL_DEBUG_LEVEL_2 /* ALways enable error messagess */ | 18 | #define QL_DEBUG_LEVEL_2 /* ALways enable error messagess */ |
@@ -48,6 +49,12 @@ | |||
48 | #define DEBUG5(x) do {} while (0); | 49 | #define DEBUG5(x) do {} while (0); |
49 | #endif /* */ | 50 | #endif /* */ |
50 | 51 | ||
52 | #if defined(QL_DEBUG_LEVEL_7) | ||
53 | #define DEBUG7(x) do {x; } while (0) | ||
54 | #else /* */ | ||
55 | #define DEBUG7(x) do {} while (0) | ||
56 | #endif /* */ | ||
57 | |||
51 | #if defined(QL_DEBUG_LEVEL_9) | 58 | #if defined(QL_DEBUG_LEVEL_9) |
52 | #define DEBUG9(x) do {x;} while (0); | 59 | #define DEBUG9(x) do {x;} while (0); |
53 | #else /* */ | 60 | #else /* */ |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 129f5dd02822..ddf16a86bbf5 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -159,6 +159,22 @@ | |||
159 | #define LSDW(x) ((u32)((u64)(x))) | 159 | #define LSDW(x) ((u32)((u64)(x))) |
160 | #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) | 160 | #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) |
161 | 161 | ||
162 | #define DEV_DB_NON_PERSISTENT 0 | ||
163 | #define DEV_DB_PERSISTENT 1 | ||
164 | |||
165 | #define COPY_ISID(dst_isid, src_isid) { \ | ||
166 | int i, j; \ | ||
167 | for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \ | ||
168 | dst_isid[i++] = src_isid[j--]; \ | ||
169 | } | ||
170 | |||
171 | #define SET_BITVAL(o, n, v) { \ | ||
172 | if (o) \ | ||
173 | n |= v; \ | ||
174 | else \ | ||
175 | n &= ~v; \ | ||
176 | } | ||
177 | |||
162 | /* | 178 | /* |
163 | * Retry & Timeout Values | 179 | * Retry & Timeout Values |
164 | */ | 180 | */ |
@@ -363,6 +379,8 @@ struct ql82xx_hw_data { | |||
363 | uint32_t flt_iscsi_param; | 379 | uint32_t flt_iscsi_param; |
364 | uint32_t flt_region_chap; | 380 | uint32_t flt_region_chap; |
365 | uint32_t flt_chap_size; | 381 | uint32_t flt_chap_size; |
382 | uint32_t flt_region_ddb; | ||
383 | uint32_t flt_ddb_size; | ||
366 | }; | 384 | }; |
367 | 385 | ||
368 | struct qla4_8xxx_legacy_intr_set { | 386 | struct qla4_8xxx_legacy_intr_set { |
@@ -501,6 +519,7 @@ struct scsi_qla_host { | |||
501 | #define AF_INIT_DONE 1 /* 0x00000002 */ | 519 | #define AF_INIT_DONE 1 /* 0x00000002 */ |
502 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ | 520 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ |
503 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ | 521 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ |
522 | #define AF_ST_DISCOVERY_IN_PROGRESS 4 /* 0x00000010 */ | ||
504 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ | 523 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ |
505 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ | 524 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ |
506 | #define AF_LINK_UP 8 /* 0x00000100 */ | 525 | #define AF_LINK_UP 8 /* 0x00000100 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index ad9d2e2d370f..c7b8892b5a83 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -288,6 +288,8 @@ union external_hw_config_reg { | |||
288 | #define FA_GOLD_RISC_CODE_ADDR_82 0x80000 | 288 | #define FA_GOLD_RISC_CODE_ADDR_82 0x80000 |
289 | #define FA_FLASH_ISCSI_CHAP 0x540000 | 289 | #define FA_FLASH_ISCSI_CHAP 0x540000 |
290 | #define FA_FLASH_CHAP_SIZE 0xC0000 | 290 | #define FA_FLASH_CHAP_SIZE 0xC0000 |
291 | #define FA_FLASH_ISCSI_DDB 0x420000 | ||
292 | #define FA_FLASH_DDB_SIZE 0x080000 | ||
291 | 293 | ||
292 | /* Flash Description Table */ | 294 | /* Flash Description Table */ |
293 | struct qla_fdt_layout { | 295 | struct qla_fdt_layout { |
@@ -348,6 +350,7 @@ struct qla_flt_header { | |||
348 | #define FLT_REG_BOOT_CODE_82 0x78 | 350 | #define FLT_REG_BOOT_CODE_82 0x78 |
349 | #define FLT_REG_ISCSI_PARAM 0x65 | 351 | #define FLT_REG_ISCSI_PARAM 0x65 |
350 | #define FLT_REG_ISCSI_CHAP 0x63 | 352 | #define FLT_REG_ISCSI_CHAP 0x63 |
353 | #define FLT_REG_ISCSI_DDB 0x6A | ||
351 | 354 | ||
352 | struct qla_flt_region { | 355 | struct qla_flt_region { |
353 | uint32_t code; | 356 | uint32_t code; |
@@ -490,12 +493,16 @@ struct qla_flt_region { | |||
490 | #define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 | 493 | #define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 |
491 | #define MBOX_ASTS_RESPONSE_QUEUE_FULL 0x8028 | 494 | #define MBOX_ASTS_RESPONSE_QUEUE_FULL 0x8028 |
492 | #define MBOX_ASTS_IP_ADDR_STATE_CHANGED 0x8029 | 495 | #define MBOX_ASTS_IP_ADDR_STATE_CHANGED 0x8029 |
496 | #define MBOX_ASTS_IPV6_DEFAULT_ROUTER_CHANGED 0x802A | ||
493 | #define MBOX_ASTS_IPV6_PREFIX_EXPIRED 0x802B | 497 | #define MBOX_ASTS_IPV6_PREFIX_EXPIRED 0x802B |
494 | #define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED 0x802C | 498 | #define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED 0x802C |
495 | #define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D | 499 | #define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D |
496 | #define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD 0x802E | 500 | #define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD 0x802E |
501 | #define MBOX_ASTS_INITIALIZATION_FAILED 0x8031 | ||
502 | #define MBOX_ASTS_SYSTEM_WARNING_EVENT 0x8036 | ||
497 | #define MBOX_ASTS_IDC_COMPLETE 0x8100 | 503 | #define MBOX_ASTS_IDC_COMPLETE 0x8100 |
498 | #define MBOX_ASTS_IDC_REQUEST_NOTIFICATION 0x8101 | 504 | #define MBOX_ASTS_IDC_REQUEST_NOTIFICATION 0x8101 |
505 | #define MBOX_ASTS_DCBX_CONF_CHANGE 0x8110 | ||
499 | #define MBOX_ASTS_TXSCVR_INSERTED 0x8130 | 506 | #define MBOX_ASTS_TXSCVR_INSERTED 0x8130 |
500 | #define MBOX_ASTS_TXSCVR_REMOVED 0x8131 | 507 | #define MBOX_ASTS_TXSCVR_REMOVED 0x8131 |
501 | 508 | ||
@@ -779,12 +786,41 @@ struct dev_db_entry { | |||
779 | #define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */ | 786 | #define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */ |
780 | #define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */ | 787 | #define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */ |
781 | 788 | ||
789 | #define OPT_IS_FW_ASSIGNED_IPV6 11 | ||
790 | #define OPT_IPV6_DEVICE 8 | ||
791 | #define OPT_AUTO_SENDTGTS_DISABLE 6 | ||
792 | #define OPT_DISC_SESSION 4 | ||
793 | #define OPT_ENTRY_STATE 3 | ||
782 | uint16_t exec_throttle; /* 02-03 */ | 794 | uint16_t exec_throttle; /* 02-03 */ |
783 | uint16_t exec_count; /* 04-05 */ | 795 | uint16_t exec_count; /* 04-05 */ |
784 | uint16_t res0; /* 06-07 */ | 796 | uint16_t res0; /* 06-07 */ |
785 | uint16_t iscsi_options; /* 08-09 */ | 797 | uint16_t iscsi_options; /* 08-09 */ |
798 | #define ISCSIOPT_HEADER_DIGEST_EN 13 | ||
799 | #define ISCSIOPT_DATA_DIGEST_EN 12 | ||
800 | #define ISCSIOPT_IMMEDIATE_DATA_EN 11 | ||
801 | #define ISCSIOPT_INITIAL_R2T_EN 10 | ||
802 | #define ISCSIOPT_DATA_SEQ_IN_ORDER 9 | ||
803 | #define ISCSIOPT_DATA_PDU_IN_ORDER 8 | ||
804 | #define ISCSIOPT_CHAP_AUTH_EN 7 | ||
805 | #define ISCSIOPT_SNACK_REQ_EN 6 | ||
806 | #define ISCSIOPT_DISCOVERY_LOGOUT_EN 5 | ||
807 | #define ISCSIOPT_BIDI_CHAP_EN 4 | ||
808 | #define ISCSIOPT_DISCOVERY_AUTH_OPTIONAL 3 | ||
809 | #define ISCSIOPT_ERL1 1 | ||
810 | #define ISCSIOPT_ERL0 0 | ||
811 | |||
786 | uint16_t tcp_options; /* 0A-0B */ | 812 | uint16_t tcp_options; /* 0A-0B */ |
813 | #define TCPOPT_TIMESTAMP_STAT 6 | ||
814 | #define TCPOPT_NAGLE_DISABLE 5 | ||
815 | #define TCPOPT_WSF_DISABLE 4 | ||
816 | #define TCPOPT_TIMER_SCALE3 3 | ||
817 | #define TCPOPT_TIMER_SCALE2 2 | ||
818 | #define TCPOPT_TIMER_SCALE1 1 | ||
819 | #define TCPOPT_TIMESTAMP_EN 0 | ||
820 | |||
787 | uint16_t ip_options; /* 0C-0D */ | 821 | uint16_t ip_options; /* 0C-0D */ |
822 | #define IPOPT_FRAGMENT_DISABLE 4 | ||
823 | |||
788 | uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */ | 824 | uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */ |
789 | #define BYTE_UNITS 512 | 825 | #define BYTE_UNITS 512 |
790 | uint32_t res1; /* 10-13 */ | 826 | uint32_t res1; /* 10-13 */ |
@@ -816,6 +852,8 @@ struct dev_db_entry { | |||
816 | * much RAM */ | 852 | * much RAM */ |
817 | uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */ | 853 | uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */ |
818 | uint8_t res5[0x10]; /* 1B0-1BF */ | 854 | uint8_t res5[0x10]; /* 1B0-1BF */ |
855 | #define DDB_NO_LINK 0xFFFF | ||
856 | #define DDB_ISNS 0xFFFD | ||
819 | uint16_t ddb_link; /* 1C0-1C1 */ | 857 | uint16_t ddb_link; /* 1C0-1C1 */ |
820 | uint16_t chap_tbl_idx; /* 1C2-1C3 */ | 858 | uint16_t chap_tbl_idx; /* 1C2-1C3 */ |
821 | uint16_t tgt_portal_grp; /* 1C4-1C5 */ | 859 | uint16_t tgt_portal_grp; /* 1C4-1C5 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 982293edf02c..4a428009f699 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -191,6 +191,9 @@ int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options, | |||
191 | int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha, | 191 | int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha, |
192 | uint32_t status, uint32_t pid, | 192 | uint32_t status, uint32_t pid, |
193 | uint32_t data_size, uint8_t *data); | 193 | uint32_t data_size, uint8_t *data); |
194 | int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha, | ||
195 | struct dev_db_entry *fw_ddb_entry, | ||
196 | dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index); | ||
194 | 197 | ||
195 | /* BSG Functions */ | 198 | /* BSG Functions */ |
196 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); | 199 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); |
@@ -224,8 +227,6 @@ void qla4_83xx_interrupt_service_routine(struct scsi_qla_host *ha, | |||
224 | int qla4_83xx_isp_reset(struct scsi_qla_host *ha); | 227 | int qla4_83xx_isp_reset(struct scsi_qla_host *ha); |
225 | void qla4_83xx_queue_iocb(struct scsi_qla_host *ha); | 228 | void qla4_83xx_queue_iocb(struct scsi_qla_host *ha); |
226 | void qla4_83xx_complete_iocb(struct scsi_qla_host *ha); | 229 | void qla4_83xx_complete_iocb(struct scsi_qla_host *ha); |
227 | uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha); | ||
228 | uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha); | ||
229 | uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr); | 230 | uint32_t qla4_83xx_rd_reg(struct scsi_qla_host *ha, ulong addr); |
230 | void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val); | 231 | void qla4_83xx_wr_reg(struct scsi_qla_host *ha, ulong addr, uint32_t val); |
231 | int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr, | 232 | int qla4_83xx_rd_reg_indirect(struct scsi_qla_host *ha, uint32_t addr, |
@@ -261,6 +262,10 @@ int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha); | |||
261 | void qla4_83xx_disable_pause(struct scsi_qla_host *ha); | 262 | void qla4_83xx_disable_pause(struct scsi_qla_host *ha); |
262 | void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha); | 263 | void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha); |
263 | int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha); | 264 | int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha); |
265 | int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options, | ||
266 | dma_addr_t dma_addr); | ||
267 | int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, | ||
268 | char *password, uint16_t chap_index); | ||
264 | 269 | ||
265 | extern int ql4xextended_error_logging; | 270 | extern int ql4xextended_error_logging; |
266 | extern int ql4xdontresethba; | 271 | extern int ql4xdontresethba; |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 1b83dc283d2e..482287f4005f 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -396,7 +396,6 @@ static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha, | |||
396 | 396 | ||
397 | task_data = task->dd_data; | 397 | task_data = task->dd_data; |
398 | memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status)); | 398 | memcpy(&task_data->sts, sts_entry, sizeof(struct passthru_status)); |
399 | ha->req_q_count += task_data->iocb_req_cnt; | ||
400 | ha->iocb_cnt -= task_data->iocb_req_cnt; | 399 | ha->iocb_cnt -= task_data->iocb_req_cnt; |
401 | queue_work(ha->task_wq, &task_data->task_work); | 400 | queue_work(ha->task_wq, &task_data->task_work); |
402 | } | 401 | } |
@@ -416,7 +415,6 @@ static struct mrb *qla4xxx_del_mrb_from_active_array(struct scsi_qla_host *ha, | |||
416 | return mrb; | 415 | return mrb; |
417 | 416 | ||
418 | /* update counters */ | 417 | /* update counters */ |
419 | ha->req_q_count += mrb->iocb_cnt; | ||
420 | ha->iocb_cnt -= mrb->iocb_cnt; | 418 | ha->iocb_cnt -= mrb->iocb_cnt; |
421 | 419 | ||
422 | return mrb; | 420 | return mrb; |
@@ -877,6 +875,43 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
877 | } | 875 | } |
878 | break; | 876 | break; |
879 | 877 | ||
878 | case MBOX_ASTS_IPV6_DEFAULT_ROUTER_CHANGED: | ||
879 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
880 | "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n", | ||
881 | ha->host_no, mbox_sts[0], mbox_sts[1], | ||
882 | mbox_sts[2], mbox_sts[3], mbox_sts[4], | ||
883 | mbox_sts[5])); | ||
884 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
885 | "scsi%ld: AEN %04x Received IPv6 default router changed notification\n", | ||
886 | ha->host_no, mbox_sts[0])); | ||
887 | break; | ||
888 | |||
889 | case MBOX_ASTS_INITIALIZATION_FAILED: | ||
890 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
891 | "scsi%ld: AEN %04x, mbox_sts[3]=%08x\n", | ||
892 | ha->host_no, mbox_sts[0], | ||
893 | mbox_sts[3])); | ||
894 | break; | ||
895 | |||
896 | case MBOX_ASTS_SYSTEM_WARNING_EVENT: | ||
897 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
898 | "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n", | ||
899 | ha->host_no, mbox_sts[0], mbox_sts[1], | ||
900 | mbox_sts[2], mbox_sts[3], mbox_sts[4], | ||
901 | mbox_sts[5])); | ||
902 | break; | ||
903 | |||
904 | case MBOX_ASTS_DCBX_CONF_CHANGE: | ||
905 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
906 | "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x mbox_sts[5]=%08x\n", | ||
907 | ha->host_no, mbox_sts[0], mbox_sts[1], | ||
908 | mbox_sts[2], mbox_sts[3], mbox_sts[4], | ||
909 | mbox_sts[5])); | ||
910 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
911 | "scsi%ld: AEN %04x Received DCBX configuration changed notification\n", | ||
912 | ha->host_no, mbox_sts[0])); | ||
913 | break; | ||
914 | |||
880 | default: | 915 | default: |
881 | DEBUG2(printk(KERN_WARNING | 916 | DEBUG2(printk(KERN_WARNING |
882 | "scsi%ld: AEN %04x UNKNOWN\n", | 917 | "scsi%ld: AEN %04x UNKNOWN\n", |
@@ -1099,8 +1134,8 @@ irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id) | |||
1099 | 1134 | ||
1100 | status = qla4_82xx_rd_32(ha, ISR_INT_STATE_REG); | 1135 | status = qla4_82xx_rd_32(ha, ISR_INT_STATE_REG); |
1101 | if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) { | 1136 | if (!ISR_IS_LEGACY_INTR_TRIGGERED(status)) { |
1102 | DEBUG2(ql4_printk(KERN_INFO, ha, | 1137 | DEBUG7(ql4_printk(KERN_INFO, ha, |
1103 | "%s legacy Int not triggered\n", __func__)); | 1138 | "%s legacy Int not triggered\n", __func__)); |
1104 | return IRQ_NONE; | 1139 | return IRQ_NONE; |
1105 | } | 1140 | } |
1106 | 1141 | ||
@@ -1158,7 +1193,7 @@ irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id) | |||
1158 | 1193 | ||
1159 | /* Legacy interrupt is valid if bit31 of leg_int_ptr is set */ | 1194 | /* Legacy interrupt is valid if bit31 of leg_int_ptr is set */ |
1160 | if (!(leg_int_ptr & LEG_INT_PTR_B31)) { | 1195 | if (!(leg_int_ptr & LEG_INT_PTR_B31)) { |
1161 | DEBUG2(ql4_printk(KERN_ERR, ha, | 1196 | DEBUG7(ql4_printk(KERN_ERR, ha, |
1162 | "%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n", | 1197 | "%s: Legacy Interrupt Bit 31 not set, spurious interrupt!\n", |
1163 | __func__)); | 1198 | __func__)); |
1164 | return IRQ_NONE; | 1199 | return IRQ_NONE; |
@@ -1166,7 +1201,7 @@ irqreturn_t qla4_83xx_intr_handler(int irq, void *dev_id) | |||
1166 | 1201 | ||
1167 | /* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */ | 1202 | /* Validate the PCIE function ID set in leg_int_ptr bits [19..16] */ |
1168 | if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit) { | 1203 | if ((leg_int_ptr & PF_BITS_MASK) != ha->pf_bit) { |
1169 | DEBUG2(ql4_printk(KERN_ERR, ha, | 1204 | DEBUG7(ql4_printk(KERN_ERR, ha, |
1170 | "%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n", | 1205 | "%s: Incorrect function ID 0x%x in legacy interrupt register, ha->pf_bit = 0x%x\n", |
1171 | __func__, (leg_int_ptr & PF_BITS_MASK), | 1206 | __func__, (leg_int_ptr & PF_BITS_MASK), |
1172 | ha->pf_bit)); | 1207 | ha->pf_bit)); |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 160d33697216..a501beab3ffe 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -1129,6 +1129,7 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, | |||
1129 | { | 1129 | { |
1130 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 1130 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
1131 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 1131 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
1132 | uint32_t scsi_lun[2]; | ||
1132 | int status = QLA_SUCCESS; | 1133 | int status = QLA_SUCCESS; |
1133 | 1134 | ||
1134 | DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, | 1135 | DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, |
@@ -1140,10 +1141,16 @@ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, | |||
1140 | */ | 1141 | */ |
1141 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); | 1142 | memset(&mbox_cmd, 0, sizeof(mbox_cmd)); |
1142 | memset(&mbox_sts, 0, sizeof(mbox_sts)); | 1143 | memset(&mbox_sts, 0, sizeof(mbox_sts)); |
1144 | int_to_scsilun(lun, (struct scsi_lun *) scsi_lun); | ||
1143 | 1145 | ||
1144 | mbox_cmd[0] = MBOX_CMD_LUN_RESET; | 1146 | mbox_cmd[0] = MBOX_CMD_LUN_RESET; |
1145 | mbox_cmd[1] = ddb_entry->fw_ddb_index; | 1147 | mbox_cmd[1] = ddb_entry->fw_ddb_index; |
1146 | mbox_cmd[2] = lun << 8; | 1148 | /* FW expects LUN bytes 0-3 in Incoming Mailbox 2 |
1149 | * (LUN byte 0 is LSByte, byte 3 is MSByte) */ | ||
1150 | mbox_cmd[2] = cpu_to_le32(scsi_lun[0]); | ||
1151 | /* FW expects LUN bytes 4-7 in Incoming Mailbox 3 | ||
1152 | * (LUN byte 4 is LSByte, byte 7 is MSByte) */ | ||
1153 | mbox_cmd[3] = cpu_to_le32(scsi_lun[1]); | ||
1147 | mbox_cmd[5] = 0x01; /* Immediate Command Enable */ | 1154 | mbox_cmd[5] = 0x01; /* Immediate Command Enable */ |
1148 | 1155 | ||
1149 | qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); | 1156 | qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); |
@@ -1281,8 +1288,8 @@ exit_about_fw: | |||
1281 | return status; | 1288 | return status; |
1282 | } | 1289 | } |
1283 | 1290 | ||
1284 | static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options, | 1291 | int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options, |
1285 | dma_addr_t dma_addr) | 1292 | dma_addr_t dma_addr) |
1286 | { | 1293 | { |
1287 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 1294 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
1288 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 1295 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
@@ -1410,6 +1417,55 @@ exit_bootdb_failed: | |||
1410 | return status; | 1417 | return status; |
1411 | } | 1418 | } |
1412 | 1419 | ||
1420 | int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha, | ||
1421 | struct dev_db_entry *fw_ddb_entry, | ||
1422 | dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index) | ||
1423 | { | ||
1424 | uint32_t dev_db_start_offset; | ||
1425 | uint32_t dev_db_end_offset; | ||
1426 | int status = QLA_ERROR; | ||
1427 | |||
1428 | memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry)); | ||
1429 | |||
1430 | if (is_qla40XX(ha)) { | ||
1431 | dev_db_start_offset = FLASH_OFFSET_DB_INFO; | ||
1432 | dev_db_end_offset = FLASH_OFFSET_DB_END; | ||
1433 | } else { | ||
1434 | dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + | ||
1435 | (ha->hw.flt_region_ddb << 2); | ||
1436 | /* flt_ddb_size is DDB table size for both ports | ||
1437 | * so divide it by 2 to calculate the offset for second port | ||
1438 | */ | ||
1439 | if (ha->port_num == 1) | ||
1440 | dev_db_start_offset += (ha->hw.flt_ddb_size / 2); | ||
1441 | |||
1442 | dev_db_end_offset = dev_db_start_offset + | ||
1443 | (ha->hw.flt_ddb_size / 2); | ||
1444 | } | ||
1445 | |||
1446 | dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); | ||
1447 | |||
1448 | if (dev_db_start_offset > dev_db_end_offset) { | ||
1449 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
1450 | "%s:Invalid DDB index %d", __func__, | ||
1451 | ddb_index)); | ||
1452 | goto exit_fdb_failed; | ||
1453 | } | ||
1454 | |||
1455 | if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, | ||
1456 | sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { | ||
1457 | ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n", | ||
1458 | ha->host_no, __func__); | ||
1459 | goto exit_fdb_failed; | ||
1460 | } | ||
1461 | |||
1462 | if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) | ||
1463 | status = QLA_SUCCESS; | ||
1464 | |||
1465 | exit_fdb_failed: | ||
1466 | return status; | ||
1467 | } | ||
1468 | |||
1413 | int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, | 1469 | int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, |
1414 | uint16_t idx) | 1470 | uint16_t idx) |
1415 | { | 1471 | { |
@@ -1503,6 +1559,62 @@ exit_set_chap: | |||
1503 | return ret; | 1559 | return ret; |
1504 | } | 1560 | } |
1505 | 1561 | ||
1562 | |||
1563 | int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, | ||
1564 | char *password, uint16_t chap_index) | ||
1565 | { | ||
1566 | int rval = QLA_ERROR; | ||
1567 | struct ql4_chap_table *chap_table = NULL; | ||
1568 | int max_chap_entries; | ||
1569 | |||
1570 | if (!ha->chap_list) { | ||
1571 | ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); | ||
1572 | rval = QLA_ERROR; | ||
1573 | goto exit_uni_chap; | ||
1574 | } | ||
1575 | |||
1576 | if (!username || !password) { | ||
1577 | ql4_printk(KERN_ERR, ha, "No memory for username & secret\n"); | ||
1578 | rval = QLA_ERROR; | ||
1579 | goto exit_uni_chap; | ||
1580 | } | ||
1581 | |||
1582 | if (is_qla80XX(ha)) | ||
1583 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
1584 | sizeof(struct ql4_chap_table); | ||
1585 | else | ||
1586 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
1587 | |||
1588 | if (chap_index > max_chap_entries) { | ||
1589 | ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); | ||
1590 | rval = QLA_ERROR; | ||
1591 | goto exit_uni_chap; | ||
1592 | } | ||
1593 | |||
1594 | mutex_lock(&ha->chap_sem); | ||
1595 | chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index; | ||
1596 | if (chap_table->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { | ||
1597 | rval = QLA_ERROR; | ||
1598 | goto exit_unlock_uni_chap; | ||
1599 | } | ||
1600 | |||
1601 | if (!(chap_table->flags & BIT_6)) { | ||
1602 | ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n"); | ||
1603 | rval = QLA_ERROR; | ||
1604 | goto exit_unlock_uni_chap; | ||
1605 | } | ||
1606 | |||
1607 | strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); | ||
1608 | strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN); | ||
1609 | |||
1610 | rval = QLA_SUCCESS; | ||
1611 | |||
1612 | exit_unlock_uni_chap: | ||
1613 | mutex_unlock(&ha->chap_sem); | ||
1614 | exit_uni_chap: | ||
1615 | return rval; | ||
1616 | } | ||
1617 | |||
1506 | /** | 1618 | /** |
1507 | * qla4xxx_get_chap_index - Get chap index given username and secret | 1619 | * qla4xxx_get_chap_index - Get chap index given username and secret |
1508 | * @ha: pointer to adapter structure | 1620 | * @ha: pointer to adapter structure |
@@ -1524,7 +1636,7 @@ int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, | |||
1524 | int max_chap_entries = 0; | 1636 | int max_chap_entries = 0; |
1525 | struct ql4_chap_table *chap_table; | 1637 | struct ql4_chap_table *chap_table; |
1526 | 1638 | ||
1527 | if (is_qla8022(ha)) | 1639 | if (is_qla80XX(ha)) |
1528 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | 1640 | max_chap_entries = (ha->hw.flt_chap_size / 2) / |
1529 | sizeof(struct ql4_chap_table); | 1641 | sizeof(struct ql4_chap_table); |
1530 | else | 1642 | else |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 9299400d3c9e..eaf00c162eb2 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -3154,6 +3154,10 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr) | |||
3154 | hw->flt_region_chap = start; | 3154 | hw->flt_region_chap = start; |
3155 | hw->flt_chap_size = le32_to_cpu(region->size); | 3155 | hw->flt_chap_size = le32_to_cpu(region->size); |
3156 | break; | 3156 | break; |
3157 | case FLT_REG_ISCSI_DDB: | ||
3158 | hw->flt_region_ddb = start; | ||
3159 | hw->flt_ddb_size = le32_to_cpu(region->size); | ||
3160 | break; | ||
3157 | } | 3161 | } |
3158 | } | 3162 | } |
3159 | goto done; | 3163 | goto done; |
@@ -3166,14 +3170,19 @@ no_flash_data: | |||
3166 | hw->flt_region_boot = FA_BOOT_CODE_ADDR_82; | 3170 | hw->flt_region_boot = FA_BOOT_CODE_ADDR_82; |
3167 | hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82; | 3171 | hw->flt_region_bootload = FA_BOOT_LOAD_ADDR_82; |
3168 | hw->flt_region_fw = FA_RISC_CODE_ADDR_82; | 3172 | hw->flt_region_fw = FA_RISC_CODE_ADDR_82; |
3169 | hw->flt_region_chap = FA_FLASH_ISCSI_CHAP; | 3173 | hw->flt_region_chap = FA_FLASH_ISCSI_CHAP >> 2; |
3170 | hw->flt_chap_size = FA_FLASH_CHAP_SIZE; | 3174 | hw->flt_chap_size = FA_FLASH_CHAP_SIZE; |
3175 | hw->flt_region_ddb = FA_FLASH_ISCSI_DDB >> 2; | ||
3176 | hw->flt_ddb_size = FA_FLASH_DDB_SIZE; | ||
3171 | 3177 | ||
3172 | done: | 3178 | done: |
3173 | DEBUG2(ql4_printk(KERN_INFO, ha, "FLT[%s]: flt=0x%x fdt=0x%x " | 3179 | DEBUG2(ql4_printk(KERN_INFO, ha, |
3174 | "boot=0x%x bootload=0x%x fw=0x%x\n", loc, hw->flt_region_flt, | 3180 | "FLT[%s]: flt=0x%x fdt=0x%x boot=0x%x bootload=0x%x fw=0x%x chap=0x%x chap_size=0x%x ddb=0x%x ddb_size=0x%x\n", |
3175 | hw->flt_region_fdt, hw->flt_region_boot, hw->flt_region_bootload, | 3181 | loc, hw->flt_region_flt, hw->flt_region_fdt, |
3176 | hw->flt_region_fw)); | 3182 | hw->flt_region_boot, hw->flt_region_bootload, |
3183 | hw->flt_region_fw, hw->flt_region_chap, | ||
3184 | hw->flt_chap_size, hw->flt_region_ddb, | ||
3185 | hw->flt_ddb_size)); | ||
3177 | } | 3186 | } |
3178 | 3187 | ||
3179 | static void | 3188 | static void |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 6142729167f4..a47f99957ba8 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -166,6 +166,26 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); | |||
166 | static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, | 166 | static int qla4xxx_change_queue_depth(struct scsi_device *sdev, int qdepth, |
167 | int reason); | 167 | int reason); |
168 | 168 | ||
169 | /* | ||
170 | * iSCSI Flash DDB sysfs entry points | ||
171 | */ | ||
172 | static int | ||
173 | qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | ||
174 | struct iscsi_bus_flash_conn *fnode_conn, | ||
175 | void *data, int len); | ||
176 | static int | ||
177 | qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | ||
178 | int param, char *buf); | ||
179 | static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, | ||
180 | int len); | ||
181 | static int | ||
182 | qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess); | ||
183 | static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, | ||
184 | struct iscsi_bus_flash_conn *fnode_conn); | ||
185 | static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, | ||
186 | struct iscsi_bus_flash_conn *fnode_conn); | ||
187 | static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess); | ||
188 | |||
169 | static struct qla4_8xxx_legacy_intr_set legacy_intr[] = | 189 | static struct qla4_8xxx_legacy_intr_set legacy_intr[] = |
170 | QLA82XX_LEGACY_INTR_CONFIG; | 190 | QLA82XX_LEGACY_INTR_CONFIG; |
171 | 191 | ||
@@ -232,6 +252,13 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
232 | .send_ping = qla4xxx_send_ping, | 252 | .send_ping = qla4xxx_send_ping, |
233 | .get_chap = qla4xxx_get_chap_list, | 253 | .get_chap = qla4xxx_get_chap_list, |
234 | .delete_chap = qla4xxx_delete_chap, | 254 | .delete_chap = qla4xxx_delete_chap, |
255 | .get_flashnode_param = qla4xxx_sysfs_ddb_get_param, | ||
256 | .set_flashnode_param = qla4xxx_sysfs_ddb_set_param, | ||
257 | .new_flashnode = qla4xxx_sysfs_ddb_add, | ||
258 | .del_flashnode = qla4xxx_sysfs_ddb_delete, | ||
259 | .login_flashnode = qla4xxx_sysfs_ddb_login, | ||
260 | .logout_flashnode = qla4xxx_sysfs_ddb_logout, | ||
261 | .logout_flashnode_sid = qla4xxx_sysfs_ddb_logout_sid, | ||
235 | }; | 262 | }; |
236 | 263 | ||
237 | static struct scsi_transport_template *qla4xxx_scsi_transport; | 264 | static struct scsi_transport_template *qla4xxx_scsi_transport; |
@@ -376,6 +403,68 @@ static umode_t qla4_attr_is_visible(int param_type, int param) | |||
376 | default: | 403 | default: |
377 | return 0; | 404 | return 0; |
378 | } | 405 | } |
406 | case ISCSI_FLASHNODE_PARAM: | ||
407 | switch (param) { | ||
408 | case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: | ||
409 | case ISCSI_FLASHNODE_PORTAL_TYPE: | ||
410 | case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: | ||
411 | case ISCSI_FLASHNODE_DISCOVERY_SESS: | ||
412 | case ISCSI_FLASHNODE_ENTRY_EN: | ||
413 | case ISCSI_FLASHNODE_HDR_DGST_EN: | ||
414 | case ISCSI_FLASHNODE_DATA_DGST_EN: | ||
415 | case ISCSI_FLASHNODE_IMM_DATA_EN: | ||
416 | case ISCSI_FLASHNODE_INITIAL_R2T_EN: | ||
417 | case ISCSI_FLASHNODE_DATASEQ_INORDER: | ||
418 | case ISCSI_FLASHNODE_PDU_INORDER: | ||
419 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | ||
420 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | ||
421 | case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: | ||
422 | case ISCSI_FLASHNODE_BIDI_CHAP_EN: | ||
423 | case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: | ||
424 | case ISCSI_FLASHNODE_ERL: | ||
425 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: | ||
426 | case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: | ||
427 | case ISCSI_FLASHNODE_TCP_WSF_DISABLE: | ||
428 | case ISCSI_FLASHNODE_TCP_TIMER_SCALE: | ||
429 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: | ||
430 | case ISCSI_FLASHNODE_IP_FRAG_DISABLE: | ||
431 | case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: | ||
432 | case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: | ||
433 | case ISCSI_FLASHNODE_FIRST_BURST: | ||
434 | case ISCSI_FLASHNODE_DEF_TIME2WAIT: | ||
435 | case ISCSI_FLASHNODE_DEF_TIME2RETAIN: | ||
436 | case ISCSI_FLASHNODE_MAX_R2T: | ||
437 | case ISCSI_FLASHNODE_KEEPALIVE_TMO: | ||
438 | case ISCSI_FLASHNODE_ISID: | ||
439 | case ISCSI_FLASHNODE_TSID: | ||
440 | case ISCSI_FLASHNODE_PORT: | ||
441 | case ISCSI_FLASHNODE_MAX_BURST: | ||
442 | case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: | ||
443 | case ISCSI_FLASHNODE_IPADDR: | ||
444 | case ISCSI_FLASHNODE_ALIAS: | ||
445 | case ISCSI_FLASHNODE_REDIRECT_IPADDR: | ||
446 | case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: | ||
447 | case ISCSI_FLASHNODE_LOCAL_PORT: | ||
448 | case ISCSI_FLASHNODE_IPV4_TOS: | ||
449 | case ISCSI_FLASHNODE_IPV6_TC: | ||
450 | case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: | ||
451 | case ISCSI_FLASHNODE_NAME: | ||
452 | case ISCSI_FLASHNODE_TPGT: | ||
453 | case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: | ||
454 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: | ||
455 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: | ||
456 | case ISCSI_FLASHNODE_TCP_XMIT_WSF: | ||
457 | case ISCSI_FLASHNODE_TCP_RECV_WSF: | ||
458 | case ISCSI_FLASHNODE_CHAP_OUT_IDX: | ||
459 | case ISCSI_FLASHNODE_USERNAME: | ||
460 | case ISCSI_FLASHNODE_PASSWORD: | ||
461 | case ISCSI_FLASHNODE_STATSN: | ||
462 | case ISCSI_FLASHNODE_EXP_STATSN: | ||
463 | case ISCSI_FLASHNODE_IS_BOOT_TGT: | ||
464 | return S_IRUGO; | ||
465 | default: | ||
466 | return 0; | ||
467 | } | ||
379 | } | 468 | } |
380 | 469 | ||
381 | return 0; | 470 | return 0; |
@@ -391,7 +480,7 @@ static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx, | |||
391 | int valid_chap_entries = 0; | 480 | int valid_chap_entries = 0; |
392 | int ret = 0, i; | 481 | int ret = 0, i; |
393 | 482 | ||
394 | if (is_qla8022(ha)) | 483 | if (is_qla80XX(ha)) |
395 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | 484 | max_chap_entries = (ha->hw.flt_chap_size / 2) / |
396 | sizeof(struct ql4_chap_table); | 485 | sizeof(struct ql4_chap_table); |
397 | else | 486 | else |
@@ -495,7 +584,7 @@ static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx) | |||
495 | 584 | ||
496 | memset(chap_table, 0, sizeof(struct ql4_chap_table)); | 585 | memset(chap_table, 0, sizeof(struct ql4_chap_table)); |
497 | 586 | ||
498 | if (is_qla8022(ha)) | 587 | if (is_qla80XX(ha)) |
499 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | 588 | max_chap_entries = (ha->hw.flt_chap_size / 2) / |
500 | sizeof(struct ql4_chap_table); | 589 | sizeof(struct ql4_chap_table); |
501 | else | 590 | else |
@@ -1922,6 +2011,252 @@ static int qla4xxx_task_xmit(struct iscsi_task *task) | |||
1922 | return -ENOSYS; | 2011 | return -ENOSYS; |
1923 | } | 2012 | } |
1924 | 2013 | ||
2014 | static int qla4xxx_copy_from_fwddb_param(struct iscsi_bus_flash_session *sess, | ||
2015 | struct iscsi_bus_flash_conn *conn, | ||
2016 | struct dev_db_entry *fw_ddb_entry) | ||
2017 | { | ||
2018 | unsigned long options = 0; | ||
2019 | int rc = 0; | ||
2020 | |||
2021 | options = le16_to_cpu(fw_ddb_entry->options); | ||
2022 | conn->is_fw_assigned_ipv6 = test_bit(OPT_IS_FW_ASSIGNED_IPV6, &options); | ||
2023 | if (test_bit(OPT_IPV6_DEVICE, &options)) { | ||
2024 | rc = iscsi_switch_str_param(&sess->portal_type, | ||
2025 | PORTAL_TYPE_IPV6); | ||
2026 | if (rc) | ||
2027 | goto exit_copy; | ||
2028 | } else { | ||
2029 | rc = iscsi_switch_str_param(&sess->portal_type, | ||
2030 | PORTAL_TYPE_IPV4); | ||
2031 | if (rc) | ||
2032 | goto exit_copy; | ||
2033 | } | ||
2034 | |||
2035 | sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE, | ||
2036 | &options); | ||
2037 | sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options); | ||
2038 | sess->entry_state = test_bit(OPT_ENTRY_STATE, &options); | ||
2039 | |||
2040 | options = le16_to_cpu(fw_ddb_entry->iscsi_options); | ||
2041 | conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options); | ||
2042 | conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options); | ||
2043 | sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options); | ||
2044 | sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options); | ||
2045 | sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER, | ||
2046 | &options); | ||
2047 | sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options); | ||
2048 | sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options); | ||
2049 | conn->snack_req_en = test_bit(ISCSIOPT_SNACK_REQ_EN, &options); | ||
2050 | sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN, | ||
2051 | &options); | ||
2052 | sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options); | ||
2053 | sess->discovery_auth_optional = | ||
2054 | test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options); | ||
2055 | if (test_bit(ISCSIOPT_ERL1, &options)) | ||
2056 | sess->erl |= BIT_1; | ||
2057 | if (test_bit(ISCSIOPT_ERL0, &options)) | ||
2058 | sess->erl |= BIT_0; | ||
2059 | |||
2060 | options = le16_to_cpu(fw_ddb_entry->tcp_options); | ||
2061 | conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options); | ||
2062 | conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options); | ||
2063 | conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options); | ||
2064 | if (test_bit(TCPOPT_TIMER_SCALE3, &options)) | ||
2065 | conn->tcp_timer_scale |= BIT_3; | ||
2066 | if (test_bit(TCPOPT_TIMER_SCALE2, &options)) | ||
2067 | conn->tcp_timer_scale |= BIT_2; | ||
2068 | if (test_bit(TCPOPT_TIMER_SCALE1, &options)) | ||
2069 | conn->tcp_timer_scale |= BIT_1; | ||
2070 | |||
2071 | conn->tcp_timer_scale >>= 1; | ||
2072 | conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options); | ||
2073 | |||
2074 | options = le16_to_cpu(fw_ddb_entry->ip_options); | ||
2075 | conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options); | ||
2076 | |||
2077 | conn->max_recv_dlength = BYTE_UNITS * | ||
2078 | le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); | ||
2079 | conn->max_xmit_dlength = BYTE_UNITS * | ||
2080 | le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len); | ||
2081 | sess->first_burst = BYTE_UNITS * | ||
2082 | le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len); | ||
2083 | sess->max_burst = BYTE_UNITS * | ||
2084 | le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len); | ||
2085 | sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t); | ||
2086 | sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); | ||
2087 | sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain); | ||
2088 | sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); | ||
2089 | conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss); | ||
2090 | conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf; | ||
2091 | conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf; | ||
2092 | conn->ipv6_flow_label = le16_to_cpu(fw_ddb_entry->ipv6_flow_lbl); | ||
2093 | conn->keepalive_timeout = le16_to_cpu(fw_ddb_entry->ka_timeout); | ||
2094 | conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port); | ||
2095 | conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn); | ||
2096 | conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn); | ||
2097 | sess->discovery_parent_idx = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
2098 | sess->discovery_parent_type = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
2099 | sess->chap_out_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); | ||
2100 | sess->tsid = le16_to_cpu(fw_ddb_entry->tsid); | ||
2101 | |||
2102 | sess->default_taskmgmt_timeout = | ||
2103 | le16_to_cpu(fw_ddb_entry->def_timeout); | ||
2104 | conn->port = le16_to_cpu(fw_ddb_entry->port); | ||
2105 | |||
2106 | options = le16_to_cpu(fw_ddb_entry->options); | ||
2107 | conn->ipaddress = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); | ||
2108 | if (!conn->ipaddress) { | ||
2109 | rc = -ENOMEM; | ||
2110 | goto exit_copy; | ||
2111 | } | ||
2112 | |||
2113 | conn->redirect_ipaddr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); | ||
2114 | if (!conn->redirect_ipaddr) { | ||
2115 | rc = -ENOMEM; | ||
2116 | goto exit_copy; | ||
2117 | } | ||
2118 | |||
2119 | memcpy(conn->ipaddress, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN); | ||
2120 | memcpy(conn->redirect_ipaddr, fw_ddb_entry->tgt_addr, IPv6_ADDR_LEN); | ||
2121 | |||
2122 | if (test_bit(OPT_IPV6_DEVICE, &options)) { | ||
2123 | conn->ipv6_traffic_class = fw_ddb_entry->ipv4_tos; | ||
2124 | |||
2125 | conn->link_local_ipv6_addr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); | ||
2126 | if (!conn->link_local_ipv6_addr) { | ||
2127 | rc = -ENOMEM; | ||
2128 | goto exit_copy; | ||
2129 | } | ||
2130 | |||
2131 | memcpy(conn->link_local_ipv6_addr, | ||
2132 | fw_ddb_entry->link_local_ipv6_addr, IPv6_ADDR_LEN); | ||
2133 | } else { | ||
2134 | conn->ipv4_tos = fw_ddb_entry->ipv4_tos; | ||
2135 | } | ||
2136 | |||
2137 | if (fw_ddb_entry->iscsi_name[0]) { | ||
2138 | rc = iscsi_switch_str_param(&sess->targetname, | ||
2139 | (char *)fw_ddb_entry->iscsi_name); | ||
2140 | if (rc) | ||
2141 | goto exit_copy; | ||
2142 | } | ||
2143 | |||
2144 | if (fw_ddb_entry->iscsi_alias[0]) { | ||
2145 | rc = iscsi_switch_str_param(&sess->targetalias, | ||
2146 | (char *)fw_ddb_entry->iscsi_alias); | ||
2147 | if (rc) | ||
2148 | goto exit_copy; | ||
2149 | } | ||
2150 | |||
2151 | COPY_ISID(sess->isid, fw_ddb_entry->isid); | ||
2152 | |||
2153 | exit_copy: | ||
2154 | return rc; | ||
2155 | } | ||
2156 | |||
2157 | static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess, | ||
2158 | struct iscsi_bus_flash_conn *conn, | ||
2159 | struct dev_db_entry *fw_ddb_entry) | ||
2160 | { | ||
2161 | uint16_t options; | ||
2162 | int rc = 0; | ||
2163 | |||
2164 | options = le16_to_cpu(fw_ddb_entry->options); | ||
2165 | SET_BITVAL(conn->is_fw_assigned_ipv6, options, BIT_11); | ||
2166 | if (!strncmp(sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
2167 | options |= BIT_8; | ||
2168 | else | ||
2169 | options &= ~BIT_8; | ||
2170 | |||
2171 | SET_BITVAL(sess->auto_snd_tgt_disable, options, BIT_6); | ||
2172 | SET_BITVAL(sess->discovery_sess, options, BIT_4); | ||
2173 | SET_BITVAL(sess->entry_state, options, BIT_3); | ||
2174 | fw_ddb_entry->options = cpu_to_le16(options); | ||
2175 | |||
2176 | options = le16_to_cpu(fw_ddb_entry->iscsi_options); | ||
2177 | SET_BITVAL(conn->hdrdgst_en, options, BIT_13); | ||
2178 | SET_BITVAL(conn->datadgst_en, options, BIT_12); | ||
2179 | SET_BITVAL(sess->imm_data_en, options, BIT_11); | ||
2180 | SET_BITVAL(sess->initial_r2t_en, options, BIT_10); | ||
2181 | SET_BITVAL(sess->dataseq_inorder_en, options, BIT_9); | ||
2182 | SET_BITVAL(sess->pdu_inorder_en, options, BIT_8); | ||
2183 | SET_BITVAL(sess->chap_auth_en, options, BIT_7); | ||
2184 | SET_BITVAL(conn->snack_req_en, options, BIT_6); | ||
2185 | SET_BITVAL(sess->discovery_logout_en, options, BIT_5); | ||
2186 | SET_BITVAL(sess->bidi_chap_en, options, BIT_4); | ||
2187 | SET_BITVAL(sess->discovery_auth_optional, options, BIT_3); | ||
2188 | SET_BITVAL(sess->erl & BIT_1, options, BIT_1); | ||
2189 | SET_BITVAL(sess->erl & BIT_0, options, BIT_0); | ||
2190 | fw_ddb_entry->iscsi_options = cpu_to_le16(options); | ||
2191 | |||
2192 | options = le16_to_cpu(fw_ddb_entry->tcp_options); | ||
2193 | SET_BITVAL(conn->tcp_timestamp_stat, options, BIT_6); | ||
2194 | SET_BITVAL(conn->tcp_nagle_disable, options, BIT_5); | ||
2195 | SET_BITVAL(conn->tcp_wsf_disable, options, BIT_4); | ||
2196 | SET_BITVAL(conn->tcp_timer_scale & BIT_2, options, BIT_3); | ||
2197 | SET_BITVAL(conn->tcp_timer_scale & BIT_1, options, BIT_2); | ||
2198 | SET_BITVAL(conn->tcp_timer_scale & BIT_0, options, BIT_1); | ||
2199 | SET_BITVAL(conn->tcp_timestamp_en, options, BIT_0); | ||
2200 | fw_ddb_entry->tcp_options = cpu_to_le16(options); | ||
2201 | |||
2202 | options = le16_to_cpu(fw_ddb_entry->ip_options); | ||
2203 | SET_BITVAL(conn->fragment_disable, options, BIT_4); | ||
2204 | fw_ddb_entry->ip_options = cpu_to_le16(options); | ||
2205 | |||
2206 | fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t); | ||
2207 | fw_ddb_entry->iscsi_max_rcv_data_seg_len = | ||
2208 | cpu_to_le16(conn->max_recv_dlength / BYTE_UNITS); | ||
2209 | fw_ddb_entry->iscsi_max_snd_data_seg_len = | ||
2210 | cpu_to_le16(conn->max_xmit_dlength / BYTE_UNITS); | ||
2211 | fw_ddb_entry->iscsi_first_burst_len = | ||
2212 | cpu_to_le16(sess->first_burst / BYTE_UNITS); | ||
2213 | fw_ddb_entry->iscsi_max_burst_len = cpu_to_le16(sess->max_burst / | ||
2214 | BYTE_UNITS); | ||
2215 | fw_ddb_entry->iscsi_def_time2wait = cpu_to_le16(sess->time2wait); | ||
2216 | fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain); | ||
2217 | fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt); | ||
2218 | fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size); | ||
2219 | fw_ddb_entry->tcp_xmt_wsf = cpu_to_le16(conn->tcp_xmit_wsf); | ||
2220 | fw_ddb_entry->tcp_rcv_wsf = cpu_to_le16(conn->tcp_recv_wsf); | ||
2221 | fw_ddb_entry->ipv4_tos = conn->ipv4_tos; | ||
2222 | fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label); | ||
2223 | fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout); | ||
2224 | fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port); | ||
2225 | fw_ddb_entry->stat_sn = cpu_to_le16(conn->statsn); | ||
2226 | fw_ddb_entry->exp_stat_sn = cpu_to_le16(conn->exp_statsn); | ||
2227 | fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_type); | ||
2228 | fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx); | ||
2229 | fw_ddb_entry->tsid = cpu_to_le16(sess->tsid); | ||
2230 | fw_ddb_entry->port = cpu_to_le16(conn->port); | ||
2231 | fw_ddb_entry->def_timeout = | ||
2232 | cpu_to_le16(sess->default_taskmgmt_timeout); | ||
2233 | |||
2234 | if (conn->ipaddress) | ||
2235 | memcpy(fw_ddb_entry->ip_addr, conn->ipaddress, | ||
2236 | sizeof(fw_ddb_entry->ip_addr)); | ||
2237 | |||
2238 | if (conn->redirect_ipaddr) | ||
2239 | memcpy(fw_ddb_entry->tgt_addr, conn->redirect_ipaddr, | ||
2240 | sizeof(fw_ddb_entry->tgt_addr)); | ||
2241 | |||
2242 | if (conn->link_local_ipv6_addr) | ||
2243 | memcpy(fw_ddb_entry->link_local_ipv6_addr, | ||
2244 | conn->link_local_ipv6_addr, | ||
2245 | sizeof(fw_ddb_entry->link_local_ipv6_addr)); | ||
2246 | |||
2247 | if (sess->targetname) | ||
2248 | memcpy(fw_ddb_entry->iscsi_name, sess->targetname, | ||
2249 | sizeof(fw_ddb_entry->iscsi_name)); | ||
2250 | |||
2251 | if (sess->targetalias) | ||
2252 | memcpy(fw_ddb_entry->iscsi_alias, sess->targetalias, | ||
2253 | sizeof(fw_ddb_entry->iscsi_alias)); | ||
2254 | |||
2255 | COPY_ISID(fw_ddb_entry->isid, sess->isid); | ||
2256 | |||
2257 | return rc; | ||
2258 | } | ||
2259 | |||
1925 | static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | 2260 | static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, |
1926 | struct dev_db_entry *fw_ddb_entry, | 2261 | struct dev_db_entry *fw_ddb_entry, |
1927 | struct iscsi_cls_session *cls_sess, | 2262 | struct iscsi_cls_session *cls_sess, |
@@ -2543,6 +2878,7 @@ static void qla4_8xxx_process_fw_error(struct scsi_qla_host *ha) | |||
2543 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | 2878 | void qla4_8xxx_watchdog(struct scsi_qla_host *ha) |
2544 | { | 2879 | { |
2545 | uint32_t dev_state; | 2880 | uint32_t dev_state; |
2881 | uint32_t idc_ctrl; | ||
2546 | 2882 | ||
2547 | /* don't poll if reset is going on */ | 2883 | /* don't poll if reset is going on */ |
2548 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || | 2884 | if (!(test_bit(DPC_RESET_ACTIVE, &ha->dpc_flags) || |
@@ -2561,10 +2897,23 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
2561 | qla4xxx_wake_dpc(ha); | 2897 | qla4xxx_wake_dpc(ha); |
2562 | } else if (dev_state == QLA8XXX_DEV_NEED_RESET && | 2898 | } else if (dev_state == QLA8XXX_DEV_NEED_RESET && |
2563 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | 2899 | !test_bit(DPC_RESET_HA, &ha->dpc_flags)) { |
2900 | |||
2901 | ql4_printk(KERN_INFO, ha, "%s: HW State: NEED RESET!\n", | ||
2902 | __func__); | ||
2903 | |||
2904 | if (is_qla8032(ha)) { | ||
2905 | idc_ctrl = qla4_83xx_rd_reg(ha, | ||
2906 | QLA83XX_IDC_DRV_CTRL); | ||
2907 | if (!(idc_ctrl & GRACEFUL_RESET_BIT1)) { | ||
2908 | ql4_printk(KERN_INFO, ha, "%s: Graceful reset bit is not set\n", | ||
2909 | __func__); | ||
2910 | qla4xxx_mailbox_premature_completion( | ||
2911 | ha); | ||
2912 | } | ||
2913 | } | ||
2914 | |||
2564 | if (is_qla8032(ha) || | 2915 | if (is_qla8032(ha) || |
2565 | (is_qla8022(ha) && !ql4xdontresethba)) { | 2916 | (is_qla8022(ha) && !ql4xdontresethba)) { |
2566 | ql4_printk(KERN_INFO, ha, "%s: HW State: " | ||
2567 | "NEED RESET!\n", __func__); | ||
2568 | set_bit(DPC_RESET_HA, &ha->dpc_flags); | 2917 | set_bit(DPC_RESET_HA, &ha->dpc_flags); |
2569 | qla4xxx_wake_dpc(ha); | 2918 | qla4xxx_wake_dpc(ha); |
2570 | } | 2919 | } |
@@ -3737,8 +4086,8 @@ static struct isp_operations qla4_83xx_isp_ops = { | |||
3737 | .reset_firmware = qla4_8xxx_stop_firmware, | 4086 | .reset_firmware = qla4_8xxx_stop_firmware, |
3738 | .queue_iocb = qla4_83xx_queue_iocb, | 4087 | .queue_iocb = qla4_83xx_queue_iocb, |
3739 | .complete_iocb = qla4_83xx_complete_iocb, | 4088 | .complete_iocb = qla4_83xx_complete_iocb, |
3740 | .rd_shdw_req_q_out = qla4_83xx_rd_shdw_req_q_out, | 4089 | .rd_shdw_req_q_out = qla4xxx_rd_shdw_req_q_out, |
3741 | .rd_shdw_rsp_q_in = qla4_83xx_rd_shdw_rsp_q_in, | 4090 | .rd_shdw_rsp_q_in = qla4xxx_rd_shdw_rsp_q_in, |
3742 | .get_sys_info = qla4_8xxx_get_sys_info, | 4091 | .get_sys_info = qla4_8xxx_get_sys_info, |
3743 | .rd_reg_direct = qla4_83xx_rd_reg, | 4092 | .rd_reg_direct = qla4_83xx_rd_reg, |
3744 | .wr_reg_direct = qla4_83xx_wr_reg, | 4093 | .wr_reg_direct = qla4_83xx_wr_reg, |
@@ -3761,11 +4110,6 @@ uint16_t qla4_82xx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | |||
3761 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out)); | 4110 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->req_q_out)); |
3762 | } | 4111 | } |
3763 | 4112 | ||
3764 | uint16_t qla4_83xx_rd_shdw_req_q_out(struct scsi_qla_host *ha) | ||
3765 | { | ||
3766 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->req_q_out)); | ||
3767 | } | ||
3768 | |||
3769 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | 4113 | uint16_t qla4xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) |
3770 | { | 4114 | { |
3771 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); | 4115 | return (uint16_t)le32_to_cpu(ha->shadow_regs->rsp_q_in); |
@@ -3776,11 +4120,6 @@ uint16_t qla4_82xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | |||
3776 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in)); | 4120 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_82xx_reg->rsp_q_in)); |
3777 | } | 4121 | } |
3778 | 4122 | ||
3779 | uint16_t qla4_83xx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha) | ||
3780 | { | ||
3781 | return (uint16_t)le32_to_cpu(readl(&ha->qla4_83xx_reg->rsp_q_in)); | ||
3782 | } | ||
3783 | |||
3784 | static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf) | 4123 | static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf) |
3785 | { | 4124 | { |
3786 | struct scsi_qla_host *ha = data; | 4125 | struct scsi_qla_host *ha = data; |
@@ -4005,7 +4344,7 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[]) | |||
4005 | if (val & BIT_7) | 4344 | if (val & BIT_7) |
4006 | ddb_index[1] = (val & 0x7f); | 4345 | ddb_index[1] = (val & 0x7f); |
4007 | 4346 | ||
4008 | } else if (is_qla8022(ha)) { | 4347 | } else if (is_qla80XX(ha)) { |
4009 | buf = dma_alloc_coherent(&ha->pdev->dev, size, | 4348 | buf = dma_alloc_coherent(&ha->pdev->dev, size, |
4010 | &buf_dma, GFP_KERNEL); | 4349 | &buf_dma, GFP_KERNEL); |
4011 | if (!buf) { | 4350 | if (!buf) { |
@@ -4083,7 +4422,7 @@ static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username, | |||
4083 | int max_chap_entries = 0; | 4422 | int max_chap_entries = 0; |
4084 | struct ql4_chap_table *chap_table; | 4423 | struct ql4_chap_table *chap_table; |
4085 | 4424 | ||
4086 | if (is_qla8022(ha)) | 4425 | if (is_qla80XX(ha)) |
4087 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | 4426 | max_chap_entries = (ha->hw.flt_chap_size / 2) / |
4088 | sizeof(struct ql4_chap_table); | 4427 | sizeof(struct ql4_chap_table); |
4089 | else | 4428 | else |
@@ -5058,6 +5397,1342 @@ exit_nt_list: | |||
5058 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | 5397 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); |
5059 | } | 5398 | } |
5060 | 5399 | ||
5400 | static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, | ||
5401 | struct list_head *list_nt) | ||
5402 | { | ||
5403 | struct dev_db_entry *fw_ddb_entry; | ||
5404 | dma_addr_t fw_ddb_dma; | ||
5405 | int max_ddbs; | ||
5406 | int fw_idx_size; | ||
5407 | int ret; | ||
5408 | uint32_t idx = 0, next_idx = 0; | ||
5409 | uint32_t state = 0, conn_err = 0; | ||
5410 | uint16_t conn_id = 0; | ||
5411 | struct qla_ddb_index *nt_ddb_idx; | ||
5412 | |||
5413 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
5414 | &fw_ddb_dma); | ||
5415 | if (fw_ddb_entry == NULL) { | ||
5416 | DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); | ||
5417 | goto exit_new_nt_list; | ||
5418 | } | ||
5419 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5420 | MAX_DEV_DB_ENTRIES; | ||
5421 | fw_idx_size = sizeof(struct qla_ddb_index); | ||
5422 | |||
5423 | for (idx = 0; idx < max_ddbs; idx = next_idx) { | ||
5424 | ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, | ||
5425 | NULL, &next_idx, &state, | ||
5426 | &conn_err, NULL, &conn_id); | ||
5427 | if (ret == QLA_ERROR) | ||
5428 | break; | ||
5429 | |||
5430 | /* Check if NT, then add it to list */ | ||
5431 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) | ||
5432 | goto continue_next_new_nt; | ||
5433 | |||
5434 | if (!(state == DDB_DS_NO_CONNECTION_ACTIVE)) | ||
5435 | goto continue_next_new_nt; | ||
5436 | |||
5437 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
5438 | "Adding DDB to session = 0x%x\n", idx)); | ||
5439 | |||
5440 | nt_ddb_idx = vmalloc(fw_idx_size); | ||
5441 | if (!nt_ddb_idx) | ||
5442 | break; | ||
5443 | |||
5444 | nt_ddb_idx->fw_ddb_idx = idx; | ||
5445 | |||
5446 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | ||
5447 | if (ret == QLA_SUCCESS) { | ||
5448 | /* free nt_ddb_idx and do not add to list_nt */ | ||
5449 | vfree(nt_ddb_idx); | ||
5450 | goto continue_next_new_nt; | ||
5451 | } | ||
5452 | |||
5453 | list_add_tail(&nt_ddb_idx->list, list_nt); | ||
5454 | |||
5455 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | ||
5456 | idx); | ||
5457 | if (ret == QLA_ERROR) | ||
5458 | goto exit_new_nt_list; | ||
5459 | |||
5460 | continue_next_new_nt: | ||
5461 | if (next_idx == 0) | ||
5462 | break; | ||
5463 | } | ||
5464 | |||
5465 | exit_new_nt_list: | ||
5466 | if (fw_ddb_entry) | ||
5467 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | ||
5468 | } | ||
5469 | |||
5470 | /** | ||
5471 | * qla4xxx_sysfs_ddb_is_non_persistent - check for non-persistence of ddb entry | ||
5472 | * @dev: dev associated with the sysfs entry | ||
5473 | * @data: pointer to flashnode session object | ||
5474 | * | ||
5475 | * Returns: | ||
5476 | * 1: if flashnode entry is non-persistent | ||
5477 | * 0: if flashnode entry is persistent | ||
5478 | **/ | ||
5479 | static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data) | ||
5480 | { | ||
5481 | struct iscsi_bus_flash_session *fnode_sess; | ||
5482 | |||
5483 | if (!iscsi_flashnode_bus_match(dev, NULL)) | ||
5484 | return 0; | ||
5485 | |||
5486 | fnode_sess = iscsi_dev_to_flash_session(dev); | ||
5487 | |||
5488 | return (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT); | ||
5489 | } | ||
5490 | |||
5491 | /** | ||
5492 | * qla4xxx_sysfs_ddb_tgt_create - Create sysfs entry for target | ||
5493 | * @ha: pointer to host | ||
5494 | * @fw_ddb_entry: flash ddb data | ||
5495 | * @idx: target index | ||
5496 | * @user: if set then this call is made from userland else from kernel | ||
5497 | * | ||
5498 | * Returns: | ||
5499 | * On sucess: QLA_SUCCESS | ||
5500 | * On failure: QLA_ERROR | ||
5501 | * | ||
5502 | * This create separate sysfs entries for session and connection attributes of | ||
5503 | * the given fw ddb entry. | ||
5504 | * If this is invoked as a result of a userspace call then the entry is marked | ||
5505 | * as nonpersistent using flash_state field. | ||
5506 | **/ | ||
5507 | int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, | ||
5508 | struct dev_db_entry *fw_ddb_entry, | ||
5509 | uint16_t *idx, int user) | ||
5510 | { | ||
5511 | struct iscsi_bus_flash_session *fnode_sess = NULL; | ||
5512 | struct iscsi_bus_flash_conn *fnode_conn = NULL; | ||
5513 | int rc = QLA_ERROR; | ||
5514 | |||
5515 | fnode_sess = iscsi_create_flashnode_sess(ha->host, *idx, | ||
5516 | &qla4xxx_iscsi_transport, 0); | ||
5517 | if (!fnode_sess) { | ||
5518 | ql4_printk(KERN_ERR, ha, | ||
5519 | "%s: Unable to create session sysfs entry for flashnode %d of host%lu\n", | ||
5520 | __func__, *idx, ha->host_no); | ||
5521 | goto exit_tgt_create; | ||
5522 | } | ||
5523 | |||
5524 | fnode_conn = iscsi_create_flashnode_conn(ha->host, fnode_sess, | ||
5525 | &qla4xxx_iscsi_transport, 0); | ||
5526 | if (!fnode_conn) { | ||
5527 | ql4_printk(KERN_ERR, ha, | ||
5528 | "%s: Unable to create conn sysfs entry for flashnode %d of host%lu\n", | ||
5529 | __func__, *idx, ha->host_no); | ||
5530 | goto free_sess; | ||
5531 | } | ||
5532 | |||
5533 | if (user) { | ||
5534 | fnode_sess->flash_state = DEV_DB_NON_PERSISTENT; | ||
5535 | } else { | ||
5536 | fnode_sess->flash_state = DEV_DB_PERSISTENT; | ||
5537 | |||
5538 | if (*idx == ha->pri_ddb_idx || *idx == ha->sec_ddb_idx) | ||
5539 | fnode_sess->is_boot_target = 1; | ||
5540 | else | ||
5541 | fnode_sess->is_boot_target = 0; | ||
5542 | } | ||
5543 | |||
5544 | rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn, | ||
5545 | fw_ddb_entry); | ||
5546 | |||
5547 | ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", | ||
5548 | __func__, fnode_sess->dev.kobj.name); | ||
5549 | |||
5550 | ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", | ||
5551 | __func__, fnode_conn->dev.kobj.name); | ||
5552 | |||
5553 | return QLA_SUCCESS; | ||
5554 | |||
5555 | free_sess: | ||
5556 | iscsi_destroy_flashnode_sess(fnode_sess); | ||
5557 | |||
5558 | exit_tgt_create: | ||
5559 | return QLA_ERROR; | ||
5560 | } | ||
5561 | |||
5562 | /** | ||
5563 | * qla4xxx_sysfs_ddb_add - Add new ddb entry in flash | ||
5564 | * @shost: pointer to host | ||
5565 | * @buf: type of ddb entry (ipv4/ipv6) | ||
5566 | * @len: length of buf | ||
5567 | * | ||
5568 | * This creates new ddb entry in the flash by finding first free index and | ||
5569 | * storing default ddb there. And then create sysfs entry for the new ddb entry. | ||
5570 | **/ | ||
5571 | static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, | ||
5572 | int len) | ||
5573 | { | ||
5574 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5575 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5576 | dma_addr_t fw_ddb_entry_dma; | ||
5577 | struct device *dev; | ||
5578 | uint16_t idx = 0; | ||
5579 | uint16_t max_ddbs = 0; | ||
5580 | uint32_t options = 0; | ||
5581 | uint32_t rval = QLA_ERROR; | ||
5582 | |||
5583 | if (strncasecmp(PORTAL_TYPE_IPV4, buf, 4) && | ||
5584 | strncasecmp(PORTAL_TYPE_IPV6, buf, 4)) { | ||
5585 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Invalid portal type\n", | ||
5586 | __func__)); | ||
5587 | goto exit_ddb_add; | ||
5588 | } | ||
5589 | |||
5590 | max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : | ||
5591 | MAX_DEV_DB_ENTRIES; | ||
5592 | |||
5593 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5594 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5595 | if (!fw_ddb_entry) { | ||
5596 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5597 | "%s: Unable to allocate dma buffer\n", | ||
5598 | __func__)); | ||
5599 | goto exit_ddb_add; | ||
5600 | } | ||
5601 | |||
5602 | dev = iscsi_find_flashnode_sess(ha->host, NULL, | ||
5603 | qla4xxx_sysfs_ddb_is_non_persistent); | ||
5604 | if (dev) { | ||
5605 | ql4_printk(KERN_ERR, ha, | ||
5606 | "%s: A non-persistent entry %s found\n", | ||
5607 | __func__, dev->kobj.name); | ||
5608 | goto exit_ddb_add; | ||
5609 | } | ||
5610 | |||
5611 | for (idx = 0; idx < max_ddbs; idx++) { | ||
5612 | if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, | ||
5613 | fw_ddb_entry_dma, idx)) | ||
5614 | break; | ||
5615 | } | ||
5616 | |||
5617 | if (idx == max_ddbs) | ||
5618 | goto exit_ddb_add; | ||
5619 | |||
5620 | if (!strncasecmp("ipv6", buf, 4)) | ||
5621 | options |= IPV6_DEFAULT_DDB_ENTRY; | ||
5622 | |||
5623 | rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); | ||
5624 | if (rval == QLA_ERROR) | ||
5625 | goto exit_ddb_add; | ||
5626 | |||
5627 | rval = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 1); | ||
5628 | |||
5629 | exit_ddb_add: | ||
5630 | if (fw_ddb_entry) | ||
5631 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5632 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5633 | if (rval == QLA_SUCCESS) | ||
5634 | return idx; | ||
5635 | else | ||
5636 | return -EIO; | ||
5637 | } | ||
5638 | |||
5639 | /** | ||
5640 | * qla4xxx_sysfs_ddb_apply - write the target ddb contents to Flash | ||
5641 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
5642 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
5643 | * | ||
5644 | * This writes the contents of target ddb buffer to Flash with a valid cookie | ||
5645 | * value in order to make the ddb entry persistent. | ||
5646 | **/ | ||
5647 | static int qla4xxx_sysfs_ddb_apply(struct iscsi_bus_flash_session *fnode_sess, | ||
5648 | struct iscsi_bus_flash_conn *fnode_conn) | ||
5649 | { | ||
5650 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
5651 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5652 | uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO; | ||
5653 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5654 | dma_addr_t fw_ddb_entry_dma; | ||
5655 | uint32_t options = 0; | ||
5656 | int rval = 0; | ||
5657 | |||
5658 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5659 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5660 | if (!fw_ddb_entry) { | ||
5661 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5662 | "%s: Unable to allocate dma buffer\n", | ||
5663 | __func__)); | ||
5664 | rval = -ENOMEM; | ||
5665 | goto exit_ddb_apply; | ||
5666 | } | ||
5667 | |||
5668 | if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
5669 | options |= IPV6_DEFAULT_DDB_ENTRY; | ||
5670 | |||
5671 | rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); | ||
5672 | if (rval == QLA_ERROR) | ||
5673 | goto exit_ddb_apply; | ||
5674 | |||
5675 | dev_db_start_offset += (fnode_sess->target_id * | ||
5676 | sizeof(*fw_ddb_entry)); | ||
5677 | |||
5678 | qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); | ||
5679 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; | ||
5680 | |||
5681 | rval = qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, | ||
5682 | sizeof(*fw_ddb_entry), FLASH_OPT_RMW_COMMIT); | ||
5683 | |||
5684 | if (rval == QLA_SUCCESS) { | ||
5685 | fnode_sess->flash_state = DEV_DB_PERSISTENT; | ||
5686 | ql4_printk(KERN_INFO, ha, | ||
5687 | "%s: flash node %u of host %lu written to flash\n", | ||
5688 | __func__, fnode_sess->target_id, ha->host_no); | ||
5689 | } else { | ||
5690 | rval = -EIO; | ||
5691 | ql4_printk(KERN_ERR, ha, | ||
5692 | "%s: Error while writing flash node %u of host %lu to flash\n", | ||
5693 | __func__, fnode_sess->target_id, ha->host_no); | ||
5694 | } | ||
5695 | |||
5696 | exit_ddb_apply: | ||
5697 | if (fw_ddb_entry) | ||
5698 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5699 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5700 | return rval; | ||
5701 | } | ||
5702 | |||
5703 | static ssize_t qla4xxx_sysfs_ddb_conn_open(struct scsi_qla_host *ha, | ||
5704 | struct dev_db_entry *fw_ddb_entry, | ||
5705 | uint16_t idx) | ||
5706 | { | ||
5707 | struct dev_db_entry *ddb_entry = NULL; | ||
5708 | dma_addr_t ddb_entry_dma; | ||
5709 | unsigned long wtime; | ||
5710 | uint32_t mbx_sts = 0; | ||
5711 | uint32_t state = 0, conn_err = 0; | ||
5712 | uint16_t tmo = 0; | ||
5713 | int ret = 0; | ||
5714 | |||
5715 | ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*ddb_entry), | ||
5716 | &ddb_entry_dma, GFP_KERNEL); | ||
5717 | if (!ddb_entry) { | ||
5718 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5719 | "%s: Unable to allocate dma buffer\n", | ||
5720 | __func__)); | ||
5721 | return QLA_ERROR; | ||
5722 | } | ||
5723 | |||
5724 | memcpy(ddb_entry, fw_ddb_entry, sizeof(*ddb_entry)); | ||
5725 | |||
5726 | ret = qla4xxx_set_ddb_entry(ha, idx, ddb_entry_dma, &mbx_sts); | ||
5727 | if (ret != QLA_SUCCESS) { | ||
5728 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5729 | "%s: Unable to set ddb entry for index %d\n", | ||
5730 | __func__, idx)); | ||
5731 | goto exit_ddb_conn_open; | ||
5732 | } | ||
5733 | |||
5734 | qla4xxx_conn_open(ha, idx); | ||
5735 | |||
5736 | /* To ensure that sendtargets is done, wait for at least 12 secs */ | ||
5737 | tmo = ((ha->def_timeout > LOGIN_TOV) && | ||
5738 | (ha->def_timeout < LOGIN_TOV * 10) ? | ||
5739 | ha->def_timeout : LOGIN_TOV); | ||
5740 | |||
5741 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
5742 | "Default time to wait for login to ddb %d\n", tmo)); | ||
5743 | |||
5744 | wtime = jiffies + (HZ * tmo); | ||
5745 | do { | ||
5746 | ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, | ||
5747 | NULL, &state, &conn_err, NULL, | ||
5748 | NULL); | ||
5749 | if (ret == QLA_ERROR) | ||
5750 | continue; | ||
5751 | |||
5752 | if (state == DDB_DS_NO_CONNECTION_ACTIVE || | ||
5753 | state == DDB_DS_SESSION_FAILED) | ||
5754 | break; | ||
5755 | |||
5756 | schedule_timeout_uninterruptible(HZ / 10); | ||
5757 | } while (time_after(wtime, jiffies)); | ||
5758 | |||
5759 | exit_ddb_conn_open: | ||
5760 | if (ddb_entry) | ||
5761 | dma_free_coherent(&ha->pdev->dev, sizeof(*ddb_entry), | ||
5762 | ddb_entry, ddb_entry_dma); | ||
5763 | return ret; | ||
5764 | } | ||
5765 | |||
5766 | static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, | ||
5767 | struct dev_db_entry *fw_ddb_entry) | ||
5768 | { | ||
5769 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; | ||
5770 | struct list_head list_nt; | ||
5771 | uint16_t ddb_index; | ||
5772 | int ret = 0; | ||
5773 | |||
5774 | if (test_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags)) { | ||
5775 | ql4_printk(KERN_WARNING, ha, | ||
5776 | "%s: A discovery already in progress!\n", __func__); | ||
5777 | return QLA_ERROR; | ||
5778 | } | ||
5779 | |||
5780 | INIT_LIST_HEAD(&list_nt); | ||
5781 | |||
5782 | set_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags); | ||
5783 | |||
5784 | ret = qla4xxx_get_ddb_index(ha, &ddb_index); | ||
5785 | if (ret == QLA_ERROR) | ||
5786 | goto exit_login_st_clr_bit; | ||
5787 | |||
5788 | ret = qla4xxx_sysfs_ddb_conn_open(ha, fw_ddb_entry, ddb_index); | ||
5789 | if (ret == QLA_ERROR) | ||
5790 | goto exit_login_st; | ||
5791 | |||
5792 | qla4xxx_build_new_nt_list(ha, &list_nt); | ||
5793 | |||
5794 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { | ||
5795 | list_del_init(&ddb_idx->list); | ||
5796 | qla4xxx_clear_ddb_entry(ha, ddb_idx->fw_ddb_idx); | ||
5797 | vfree(ddb_idx); | ||
5798 | } | ||
5799 | |||
5800 | exit_login_st: | ||
5801 | if (qla4xxx_clear_ddb_entry(ha, ddb_index) == QLA_ERROR) { | ||
5802 | ql4_printk(KERN_ERR, ha, | ||
5803 | "Unable to clear DDB index = 0x%x\n", ddb_index); | ||
5804 | } | ||
5805 | |||
5806 | clear_bit(ddb_index, ha->ddb_idx_map); | ||
5807 | |||
5808 | exit_login_st_clr_bit: | ||
5809 | clear_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags); | ||
5810 | return ret; | ||
5811 | } | ||
5812 | |||
5813 | static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha, | ||
5814 | struct dev_db_entry *fw_ddb_entry, | ||
5815 | uint16_t idx) | ||
5816 | { | ||
5817 | int ret = QLA_ERROR; | ||
5818 | |||
5819 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | ||
5820 | if (ret != QLA_SUCCESS) | ||
5821 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | ||
5822 | idx); | ||
5823 | else | ||
5824 | ret = -EPERM; | ||
5825 | |||
5826 | return ret; | ||
5827 | } | ||
5828 | |||
5829 | /** | ||
5830 | * qla4xxx_sysfs_ddb_login - Login to the specified target | ||
5831 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
5832 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
5833 | * | ||
5834 | * This logs in to the specified target | ||
5835 | **/ | ||
5836 | static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, | ||
5837 | struct iscsi_bus_flash_conn *fnode_conn) | ||
5838 | { | ||
5839 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
5840 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5841 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5842 | dma_addr_t fw_ddb_entry_dma; | ||
5843 | uint32_t options = 0; | ||
5844 | int ret = 0; | ||
5845 | |||
5846 | if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) { | ||
5847 | ql4_printk(KERN_ERR, ha, | ||
5848 | "%s: Target info is not persistent\n", __func__); | ||
5849 | ret = -EIO; | ||
5850 | goto exit_ddb_login; | ||
5851 | } | ||
5852 | |||
5853 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5854 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5855 | if (!fw_ddb_entry) { | ||
5856 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5857 | "%s: Unable to allocate dma buffer\n", | ||
5858 | __func__)); | ||
5859 | ret = -ENOMEM; | ||
5860 | goto exit_ddb_login; | ||
5861 | } | ||
5862 | |||
5863 | if (!strncasecmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
5864 | options |= IPV6_DEFAULT_DDB_ENTRY; | ||
5865 | |||
5866 | ret = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); | ||
5867 | if (ret == QLA_ERROR) | ||
5868 | goto exit_ddb_login; | ||
5869 | |||
5870 | qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); | ||
5871 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; | ||
5872 | |||
5873 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) | ||
5874 | ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry); | ||
5875 | else | ||
5876 | ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, | ||
5877 | fnode_sess->target_id); | ||
5878 | |||
5879 | if (ret > 0) | ||
5880 | ret = -EIO; | ||
5881 | |||
5882 | exit_ddb_login: | ||
5883 | if (fw_ddb_entry) | ||
5884 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5885 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5886 | return ret; | ||
5887 | } | ||
5888 | |||
5889 | /** | ||
5890 | * qla4xxx_sysfs_ddb_logout_sid - Logout session for the specified target | ||
5891 | * @cls_sess: pointer to session to be logged out | ||
5892 | * | ||
5893 | * This performs session log out from the specified target | ||
5894 | **/ | ||
5895 | static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess) | ||
5896 | { | ||
5897 | struct iscsi_session *sess; | ||
5898 | struct ddb_entry *ddb_entry = NULL; | ||
5899 | struct scsi_qla_host *ha; | ||
5900 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5901 | dma_addr_t fw_ddb_entry_dma; | ||
5902 | unsigned long flags; | ||
5903 | unsigned long wtime; | ||
5904 | uint32_t ddb_state; | ||
5905 | int options; | ||
5906 | int ret = 0; | ||
5907 | |||
5908 | sess = cls_sess->dd_data; | ||
5909 | ddb_entry = sess->dd_data; | ||
5910 | ha = ddb_entry->ha; | ||
5911 | |||
5912 | if (ddb_entry->ddb_type != FLASH_DDB) { | ||
5913 | ql4_printk(KERN_ERR, ha, "%s: Not a flash node session\n", | ||
5914 | __func__); | ||
5915 | ret = -ENXIO; | ||
5916 | goto exit_ddb_logout; | ||
5917 | } | ||
5918 | |||
5919 | if (test_bit(DF_BOOT_TGT, &ddb_entry->flags)) { | ||
5920 | ql4_printk(KERN_ERR, ha, | ||
5921 | "%s: Logout from boot target entry is not permitted.\n", | ||
5922 | __func__); | ||
5923 | ret = -EPERM; | ||
5924 | goto exit_ddb_logout; | ||
5925 | } | ||
5926 | |||
5927 | options = LOGOUT_OPTION_CLOSE_SESSION; | ||
5928 | if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR) { | ||
5929 | ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__); | ||
5930 | ret = -EIO; | ||
5931 | goto exit_ddb_logout; | ||
5932 | } | ||
5933 | |||
5934 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5935 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5936 | if (!fw_ddb_entry) { | ||
5937 | ql4_printk(KERN_ERR, ha, | ||
5938 | "%s: Unable to allocate dma buffer\n", __func__); | ||
5939 | ret = -ENOMEM; | ||
5940 | goto exit_ddb_logout; | ||
5941 | } | ||
5942 | |||
5943 | wtime = jiffies + (HZ * LOGOUT_TOV); | ||
5944 | do { | ||
5945 | ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, | ||
5946 | fw_ddb_entry, fw_ddb_entry_dma, | ||
5947 | NULL, NULL, &ddb_state, NULL, | ||
5948 | NULL, NULL); | ||
5949 | if (ret == QLA_ERROR) | ||
5950 | goto ddb_logout_clr_sess; | ||
5951 | |||
5952 | if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || | ||
5953 | (ddb_state == DDB_DS_SESSION_FAILED)) | ||
5954 | goto ddb_logout_clr_sess; | ||
5955 | |||
5956 | schedule_timeout_uninterruptible(HZ); | ||
5957 | } while ((time_after(wtime, jiffies))); | ||
5958 | |||
5959 | ddb_logout_clr_sess: | ||
5960 | qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); | ||
5961 | /* | ||
5962 | * we have decremented the reference count of the driver | ||
5963 | * when we setup the session to have the driver unload | ||
5964 | * to be seamless without actually destroying the | ||
5965 | * session | ||
5966 | **/ | ||
5967 | try_module_get(qla4xxx_iscsi_transport.owner); | ||
5968 | iscsi_destroy_endpoint(ddb_entry->conn->ep); | ||
5969 | |||
5970 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
5971 | qla4xxx_free_ddb(ha, ddb_entry); | ||
5972 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
5973 | |||
5974 | iscsi_session_teardown(ddb_entry->sess); | ||
5975 | |||
5976 | ret = QLA_SUCCESS; | ||
5977 | |||
5978 | exit_ddb_logout: | ||
5979 | if (fw_ddb_entry) | ||
5980 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5981 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5982 | return ret; | ||
5983 | } | ||
5984 | |||
5985 | /** | ||
5986 | * qla4xxx_sysfs_ddb_logout - Logout from the specified target | ||
5987 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
5988 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
5989 | * | ||
5990 | * This performs log out from the specified target | ||
5991 | **/ | ||
5992 | static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, | ||
5993 | struct iscsi_bus_flash_conn *fnode_conn) | ||
5994 | { | ||
5995 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
5996 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5997 | struct ql4_tuple_ddb *flash_tddb = NULL; | ||
5998 | struct ql4_tuple_ddb *tmp_tddb = NULL; | ||
5999 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6000 | struct ddb_entry *ddb_entry = NULL; | ||
6001 | dma_addr_t fw_ddb_dma; | ||
6002 | uint32_t next_idx = 0; | ||
6003 | uint32_t state = 0, conn_err = 0; | ||
6004 | uint16_t conn_id = 0; | ||
6005 | int idx, index; | ||
6006 | int status, ret = 0; | ||
6007 | |||
6008 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
6009 | &fw_ddb_dma); | ||
6010 | if (fw_ddb_entry == NULL) { | ||
6011 | ql4_printk(KERN_ERR, ha, "%s:Out of memory\n", __func__); | ||
6012 | ret = -ENOMEM; | ||
6013 | goto exit_ddb_logout; | ||
6014 | } | ||
6015 | |||
6016 | flash_tddb = vzalloc(sizeof(*flash_tddb)); | ||
6017 | if (!flash_tddb) { | ||
6018 | ql4_printk(KERN_WARNING, ha, | ||
6019 | "%s:Memory Allocation failed.\n", __func__); | ||
6020 | ret = -ENOMEM; | ||
6021 | goto exit_ddb_logout; | ||
6022 | } | ||
6023 | |||
6024 | tmp_tddb = vzalloc(sizeof(*tmp_tddb)); | ||
6025 | if (!tmp_tddb) { | ||
6026 | ql4_printk(KERN_WARNING, ha, | ||
6027 | "%s:Memory Allocation failed.\n", __func__); | ||
6028 | ret = -ENOMEM; | ||
6029 | goto exit_ddb_logout; | ||
6030 | } | ||
6031 | |||
6032 | if (!fnode_sess->targetname) { | ||
6033 | ql4_printk(KERN_ERR, ha, | ||
6034 | "%s:Cannot logout from SendTarget entry\n", | ||
6035 | __func__); | ||
6036 | ret = -EPERM; | ||
6037 | goto exit_ddb_logout; | ||
6038 | } | ||
6039 | |||
6040 | if (fnode_sess->is_boot_target) { | ||
6041 | ql4_printk(KERN_ERR, ha, | ||
6042 | "%s: Logout from boot target entry is not permitted.\n", | ||
6043 | __func__); | ||
6044 | ret = -EPERM; | ||
6045 | goto exit_ddb_logout; | ||
6046 | } | ||
6047 | |||
6048 | strncpy(flash_tddb->iscsi_name, fnode_sess->targetname, | ||
6049 | ISCSI_NAME_SIZE); | ||
6050 | |||
6051 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
6052 | sprintf(flash_tddb->ip_addr, "%pI6", fnode_conn->ipaddress); | ||
6053 | else | ||
6054 | sprintf(flash_tddb->ip_addr, "%pI4", fnode_conn->ipaddress); | ||
6055 | |||
6056 | flash_tddb->tpgt = fnode_sess->tpgt; | ||
6057 | flash_tddb->port = fnode_conn->port; | ||
6058 | |||
6059 | COPY_ISID(flash_tddb->isid, fnode_sess->isid); | ||
6060 | |||
6061 | for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { | ||
6062 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); | ||
6063 | if (ddb_entry == NULL) | ||
6064 | continue; | ||
6065 | |||
6066 | if (ddb_entry->ddb_type != FLASH_DDB) | ||
6067 | continue; | ||
6068 | |||
6069 | index = ddb_entry->sess->target_id; | ||
6070 | status = qla4xxx_get_fwddb_entry(ha, index, fw_ddb_entry, | ||
6071 | fw_ddb_dma, NULL, &next_idx, | ||
6072 | &state, &conn_err, NULL, | ||
6073 | &conn_id); | ||
6074 | if (status == QLA_ERROR) { | ||
6075 | ret = -ENOMEM; | ||
6076 | break; | ||
6077 | } | ||
6078 | |||
6079 | qla4xxx_convert_param_ddb(fw_ddb_entry, tmp_tddb, NULL); | ||
6080 | |||
6081 | status = qla4xxx_compare_tuple_ddb(ha, flash_tddb, tmp_tddb, | ||
6082 | true); | ||
6083 | if (status == QLA_SUCCESS) { | ||
6084 | ret = qla4xxx_sysfs_ddb_logout_sid(ddb_entry->sess); | ||
6085 | break; | ||
6086 | } | ||
6087 | } | ||
6088 | |||
6089 | if (idx == MAX_DDB_ENTRIES) | ||
6090 | ret = -ESRCH; | ||
6091 | |||
6092 | exit_ddb_logout: | ||
6093 | if (flash_tddb) | ||
6094 | vfree(flash_tddb); | ||
6095 | if (tmp_tddb) | ||
6096 | vfree(tmp_tddb); | ||
6097 | if (fw_ddb_entry) | ||
6098 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | ||
6099 | |||
6100 | return ret; | ||
6101 | } | ||
6102 | |||
6103 | static int | ||
6104 | qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | ||
6105 | int param, char *buf) | ||
6106 | { | ||
6107 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
6108 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
6109 | struct iscsi_bus_flash_conn *fnode_conn; | ||
6110 | struct ql4_chap_table chap_tbl; | ||
6111 | struct device *dev; | ||
6112 | int parent_type, parent_index = 0xffff; | ||
6113 | int rc = 0; | ||
6114 | |||
6115 | dev = iscsi_find_flashnode_conn(fnode_sess, NULL, | ||
6116 | iscsi_is_flashnode_conn_dev); | ||
6117 | if (!dev) | ||
6118 | return -EIO; | ||
6119 | |||
6120 | fnode_conn = iscsi_dev_to_flash_conn(dev); | ||
6121 | |||
6122 | switch (param) { | ||
6123 | case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: | ||
6124 | rc = sprintf(buf, "%u\n", fnode_conn->is_fw_assigned_ipv6); | ||
6125 | break; | ||
6126 | case ISCSI_FLASHNODE_PORTAL_TYPE: | ||
6127 | rc = sprintf(buf, "%s\n", fnode_sess->portal_type); | ||
6128 | break; | ||
6129 | case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: | ||
6130 | rc = sprintf(buf, "%u\n", fnode_sess->auto_snd_tgt_disable); | ||
6131 | break; | ||
6132 | case ISCSI_FLASHNODE_DISCOVERY_SESS: | ||
6133 | rc = sprintf(buf, "%u\n", fnode_sess->discovery_sess); | ||
6134 | break; | ||
6135 | case ISCSI_FLASHNODE_ENTRY_EN: | ||
6136 | rc = sprintf(buf, "%u\n", fnode_sess->entry_state); | ||
6137 | break; | ||
6138 | case ISCSI_FLASHNODE_HDR_DGST_EN: | ||
6139 | rc = sprintf(buf, "%u\n", fnode_conn->hdrdgst_en); | ||
6140 | break; | ||
6141 | case ISCSI_FLASHNODE_DATA_DGST_EN: | ||
6142 | rc = sprintf(buf, "%u\n", fnode_conn->datadgst_en); | ||
6143 | break; | ||
6144 | case ISCSI_FLASHNODE_IMM_DATA_EN: | ||
6145 | rc = sprintf(buf, "%u\n", fnode_sess->imm_data_en); | ||
6146 | break; | ||
6147 | case ISCSI_FLASHNODE_INITIAL_R2T_EN: | ||
6148 | rc = sprintf(buf, "%u\n", fnode_sess->initial_r2t_en); | ||
6149 | break; | ||
6150 | case ISCSI_FLASHNODE_DATASEQ_INORDER: | ||
6151 | rc = sprintf(buf, "%u\n", fnode_sess->dataseq_inorder_en); | ||
6152 | break; | ||
6153 | case ISCSI_FLASHNODE_PDU_INORDER: | ||
6154 | rc = sprintf(buf, "%u\n", fnode_sess->pdu_inorder_en); | ||
6155 | break; | ||
6156 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | ||
6157 | rc = sprintf(buf, "%u\n", fnode_sess->chap_auth_en); | ||
6158 | break; | ||
6159 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | ||
6160 | rc = sprintf(buf, "%u\n", fnode_conn->snack_req_en); | ||
6161 | break; | ||
6162 | case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: | ||
6163 | rc = sprintf(buf, "%u\n", fnode_sess->discovery_logout_en); | ||
6164 | break; | ||
6165 | case ISCSI_FLASHNODE_BIDI_CHAP_EN: | ||
6166 | rc = sprintf(buf, "%u\n", fnode_sess->bidi_chap_en); | ||
6167 | break; | ||
6168 | case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: | ||
6169 | rc = sprintf(buf, "%u\n", fnode_sess->discovery_auth_optional); | ||
6170 | break; | ||
6171 | case ISCSI_FLASHNODE_ERL: | ||
6172 | rc = sprintf(buf, "%u\n", fnode_sess->erl); | ||
6173 | break; | ||
6174 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: | ||
6175 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_stat); | ||
6176 | break; | ||
6177 | case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: | ||
6178 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_nagle_disable); | ||
6179 | break; | ||
6180 | case ISCSI_FLASHNODE_TCP_WSF_DISABLE: | ||
6181 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_wsf_disable); | ||
6182 | break; | ||
6183 | case ISCSI_FLASHNODE_TCP_TIMER_SCALE: | ||
6184 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_timer_scale); | ||
6185 | break; | ||
6186 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: | ||
6187 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_en); | ||
6188 | break; | ||
6189 | case ISCSI_FLASHNODE_IP_FRAG_DISABLE: | ||
6190 | rc = sprintf(buf, "%u\n", fnode_conn->fragment_disable); | ||
6191 | break; | ||
6192 | case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: | ||
6193 | rc = sprintf(buf, "%u\n", fnode_conn->max_recv_dlength); | ||
6194 | break; | ||
6195 | case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: | ||
6196 | rc = sprintf(buf, "%u\n", fnode_conn->max_xmit_dlength); | ||
6197 | break; | ||
6198 | case ISCSI_FLASHNODE_FIRST_BURST: | ||
6199 | rc = sprintf(buf, "%u\n", fnode_sess->first_burst); | ||
6200 | break; | ||
6201 | case ISCSI_FLASHNODE_DEF_TIME2WAIT: | ||
6202 | rc = sprintf(buf, "%u\n", fnode_sess->time2wait); | ||
6203 | break; | ||
6204 | case ISCSI_FLASHNODE_DEF_TIME2RETAIN: | ||
6205 | rc = sprintf(buf, "%u\n", fnode_sess->time2retain); | ||
6206 | break; | ||
6207 | case ISCSI_FLASHNODE_MAX_R2T: | ||
6208 | rc = sprintf(buf, "%u\n", fnode_sess->max_r2t); | ||
6209 | break; | ||
6210 | case ISCSI_FLASHNODE_KEEPALIVE_TMO: | ||
6211 | rc = sprintf(buf, "%u\n", fnode_conn->keepalive_timeout); | ||
6212 | break; | ||
6213 | case ISCSI_FLASHNODE_ISID: | ||
6214 | rc = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", | ||
6215 | fnode_sess->isid[0], fnode_sess->isid[1], | ||
6216 | fnode_sess->isid[2], fnode_sess->isid[3], | ||
6217 | fnode_sess->isid[4], fnode_sess->isid[5]); | ||
6218 | break; | ||
6219 | case ISCSI_FLASHNODE_TSID: | ||
6220 | rc = sprintf(buf, "%u\n", fnode_sess->tsid); | ||
6221 | break; | ||
6222 | case ISCSI_FLASHNODE_PORT: | ||
6223 | rc = sprintf(buf, "%d\n", fnode_conn->port); | ||
6224 | break; | ||
6225 | case ISCSI_FLASHNODE_MAX_BURST: | ||
6226 | rc = sprintf(buf, "%u\n", fnode_sess->max_burst); | ||
6227 | break; | ||
6228 | case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: | ||
6229 | rc = sprintf(buf, "%u\n", | ||
6230 | fnode_sess->default_taskmgmt_timeout); | ||
6231 | break; | ||
6232 | case ISCSI_FLASHNODE_IPADDR: | ||
6233 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
6234 | rc = sprintf(buf, "%pI6\n", fnode_conn->ipaddress); | ||
6235 | else | ||
6236 | rc = sprintf(buf, "%pI4\n", fnode_conn->ipaddress); | ||
6237 | break; | ||
6238 | case ISCSI_FLASHNODE_ALIAS: | ||
6239 | if (fnode_sess->targetalias) | ||
6240 | rc = sprintf(buf, "%s\n", fnode_sess->targetalias); | ||
6241 | else | ||
6242 | rc = sprintf(buf, "\n"); | ||
6243 | break; | ||
6244 | case ISCSI_FLASHNODE_REDIRECT_IPADDR: | ||
6245 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
6246 | rc = sprintf(buf, "%pI6\n", | ||
6247 | fnode_conn->redirect_ipaddr); | ||
6248 | else | ||
6249 | rc = sprintf(buf, "%pI4\n", | ||
6250 | fnode_conn->redirect_ipaddr); | ||
6251 | break; | ||
6252 | case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: | ||
6253 | rc = sprintf(buf, "%u\n", fnode_conn->max_segment_size); | ||
6254 | break; | ||
6255 | case ISCSI_FLASHNODE_LOCAL_PORT: | ||
6256 | rc = sprintf(buf, "%u\n", fnode_conn->local_port); | ||
6257 | break; | ||
6258 | case ISCSI_FLASHNODE_IPV4_TOS: | ||
6259 | rc = sprintf(buf, "%u\n", fnode_conn->ipv4_tos); | ||
6260 | break; | ||
6261 | case ISCSI_FLASHNODE_IPV6_TC: | ||
6262 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
6263 | rc = sprintf(buf, "%u\n", | ||
6264 | fnode_conn->ipv6_traffic_class); | ||
6265 | else | ||
6266 | rc = sprintf(buf, "\n"); | ||
6267 | break; | ||
6268 | case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: | ||
6269 | rc = sprintf(buf, "%u\n", fnode_conn->ipv6_flow_label); | ||
6270 | break; | ||
6271 | case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: | ||
6272 | if (!strncmp(fnode_sess->portal_type, PORTAL_TYPE_IPV6, 4)) | ||
6273 | rc = sprintf(buf, "%pI6\n", | ||
6274 | fnode_conn->link_local_ipv6_addr); | ||
6275 | else | ||
6276 | rc = sprintf(buf, "\n"); | ||
6277 | break; | ||
6278 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: | ||
6279 | if ((fnode_sess->discovery_parent_idx) >= 0 && | ||
6280 | (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES)) | ||
6281 | parent_index = fnode_sess->discovery_parent_idx; | ||
6282 | |||
6283 | rc = sprintf(buf, "%u\n", parent_index); | ||
6284 | break; | ||
6285 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: | ||
6286 | if (fnode_sess->discovery_parent_type == DDB_ISNS) | ||
6287 | parent_type = ISCSI_DISC_PARENT_ISNS; | ||
6288 | else if (fnode_sess->discovery_parent_type == DDB_NO_LINK) | ||
6289 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; | ||
6290 | else if (fnode_sess->discovery_parent_type >= 0 && | ||
6291 | fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES) | ||
6292 | parent_type = ISCSI_DISC_PARENT_SENDTGT; | ||
6293 | else | ||
6294 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; | ||
6295 | |||
6296 | rc = sprintf(buf, "%s\n", | ||
6297 | iscsi_get_discovery_parent_name(parent_type)); | ||
6298 | break; | ||
6299 | case ISCSI_FLASHNODE_NAME: | ||
6300 | if (fnode_sess->targetname) | ||
6301 | rc = sprintf(buf, "%s\n", fnode_sess->targetname); | ||
6302 | else | ||
6303 | rc = sprintf(buf, "\n"); | ||
6304 | break; | ||
6305 | case ISCSI_FLASHNODE_TPGT: | ||
6306 | rc = sprintf(buf, "%u\n", fnode_sess->tpgt); | ||
6307 | break; | ||
6308 | case ISCSI_FLASHNODE_TCP_XMIT_WSF: | ||
6309 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_xmit_wsf); | ||
6310 | break; | ||
6311 | case ISCSI_FLASHNODE_TCP_RECV_WSF: | ||
6312 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_recv_wsf); | ||
6313 | break; | ||
6314 | case ISCSI_FLASHNODE_CHAP_OUT_IDX: | ||
6315 | rc = sprintf(buf, "%u\n", fnode_sess->chap_out_idx); | ||
6316 | break; | ||
6317 | case ISCSI_FLASHNODE_USERNAME: | ||
6318 | if (fnode_sess->chap_auth_en) { | ||
6319 | qla4xxx_get_uni_chap_at_index(ha, | ||
6320 | chap_tbl.name, | ||
6321 | chap_tbl.secret, | ||
6322 | fnode_sess->chap_out_idx); | ||
6323 | rc = sprintf(buf, "%s\n", chap_tbl.name); | ||
6324 | } else { | ||
6325 | rc = sprintf(buf, "\n"); | ||
6326 | } | ||
6327 | break; | ||
6328 | case ISCSI_FLASHNODE_PASSWORD: | ||
6329 | if (fnode_sess->chap_auth_en) { | ||
6330 | qla4xxx_get_uni_chap_at_index(ha, | ||
6331 | chap_tbl.name, | ||
6332 | chap_tbl.secret, | ||
6333 | fnode_sess->chap_out_idx); | ||
6334 | rc = sprintf(buf, "%s\n", chap_tbl.secret); | ||
6335 | } else { | ||
6336 | rc = sprintf(buf, "\n"); | ||
6337 | } | ||
6338 | break; | ||
6339 | case ISCSI_FLASHNODE_STATSN: | ||
6340 | rc = sprintf(buf, "%u\n", fnode_conn->statsn); | ||
6341 | break; | ||
6342 | case ISCSI_FLASHNODE_EXP_STATSN: | ||
6343 | rc = sprintf(buf, "%u\n", fnode_conn->exp_statsn); | ||
6344 | break; | ||
6345 | case ISCSI_FLASHNODE_IS_BOOT_TGT: | ||
6346 | rc = sprintf(buf, "%u\n", fnode_sess->is_boot_target); | ||
6347 | break; | ||
6348 | default: | ||
6349 | rc = -ENOSYS; | ||
6350 | break; | ||
6351 | } | ||
6352 | return rc; | ||
6353 | } | ||
6354 | |||
6355 | /** | ||
6356 | * qla4xxx_sysfs_ddb_set_param - Set parameter for firmware DDB entry | ||
6357 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
6358 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
6359 | * @data: Parameters and their values to update | ||
6360 | * @len: len of data | ||
6361 | * | ||
6362 | * This sets the parameter of flash ddb entry and writes them to flash | ||
6363 | **/ | ||
6364 | static int | ||
6365 | qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | ||
6366 | struct iscsi_bus_flash_conn *fnode_conn, | ||
6367 | void *data, int len) | ||
6368 | { | ||
6369 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
6370 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
6371 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6372 | struct iscsi_flashnode_param_info *fnode_param; | ||
6373 | struct nlattr *attr; | ||
6374 | int rc = QLA_ERROR; | ||
6375 | uint32_t rem = len; | ||
6376 | |||
6377 | fw_ddb_entry = kzalloc(sizeof(*fw_ddb_entry), GFP_KERNEL); | ||
6378 | if (!fw_ddb_entry) { | ||
6379 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6380 | "%s: Unable to allocate ddb buffer\n", | ||
6381 | __func__)); | ||
6382 | return -ENOMEM; | ||
6383 | } | ||
6384 | |||
6385 | nla_for_each_attr(attr, data, len, rem) { | ||
6386 | fnode_param = nla_data(attr); | ||
6387 | |||
6388 | switch (fnode_param->param) { | ||
6389 | case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: | ||
6390 | fnode_conn->is_fw_assigned_ipv6 = fnode_param->value[0]; | ||
6391 | break; | ||
6392 | case ISCSI_FLASHNODE_PORTAL_TYPE: | ||
6393 | memcpy(fnode_sess->portal_type, fnode_param->value, | ||
6394 | strlen(fnode_sess->portal_type)); | ||
6395 | break; | ||
6396 | case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: | ||
6397 | fnode_sess->auto_snd_tgt_disable = | ||
6398 | fnode_param->value[0]; | ||
6399 | break; | ||
6400 | case ISCSI_FLASHNODE_DISCOVERY_SESS: | ||
6401 | fnode_sess->discovery_sess = fnode_param->value[0]; | ||
6402 | break; | ||
6403 | case ISCSI_FLASHNODE_ENTRY_EN: | ||
6404 | fnode_sess->entry_state = fnode_param->value[0]; | ||
6405 | break; | ||
6406 | case ISCSI_FLASHNODE_HDR_DGST_EN: | ||
6407 | fnode_conn->hdrdgst_en = fnode_param->value[0]; | ||
6408 | break; | ||
6409 | case ISCSI_FLASHNODE_DATA_DGST_EN: | ||
6410 | fnode_conn->datadgst_en = fnode_param->value[0]; | ||
6411 | break; | ||
6412 | case ISCSI_FLASHNODE_IMM_DATA_EN: | ||
6413 | fnode_sess->imm_data_en = fnode_param->value[0]; | ||
6414 | break; | ||
6415 | case ISCSI_FLASHNODE_INITIAL_R2T_EN: | ||
6416 | fnode_sess->initial_r2t_en = fnode_param->value[0]; | ||
6417 | break; | ||
6418 | case ISCSI_FLASHNODE_DATASEQ_INORDER: | ||
6419 | fnode_sess->dataseq_inorder_en = fnode_param->value[0]; | ||
6420 | break; | ||
6421 | case ISCSI_FLASHNODE_PDU_INORDER: | ||
6422 | fnode_sess->pdu_inorder_en = fnode_param->value[0]; | ||
6423 | break; | ||
6424 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | ||
6425 | fnode_sess->chap_auth_en = fnode_param->value[0]; | ||
6426 | break; | ||
6427 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | ||
6428 | fnode_conn->snack_req_en = fnode_param->value[0]; | ||
6429 | break; | ||
6430 | case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: | ||
6431 | fnode_sess->discovery_logout_en = fnode_param->value[0]; | ||
6432 | break; | ||
6433 | case ISCSI_FLASHNODE_BIDI_CHAP_EN: | ||
6434 | fnode_sess->bidi_chap_en = fnode_param->value[0]; | ||
6435 | break; | ||
6436 | case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: | ||
6437 | fnode_sess->discovery_auth_optional = | ||
6438 | fnode_param->value[0]; | ||
6439 | break; | ||
6440 | case ISCSI_FLASHNODE_ERL: | ||
6441 | fnode_sess->erl = fnode_param->value[0]; | ||
6442 | break; | ||
6443 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: | ||
6444 | fnode_conn->tcp_timestamp_stat = fnode_param->value[0]; | ||
6445 | break; | ||
6446 | case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: | ||
6447 | fnode_conn->tcp_nagle_disable = fnode_param->value[0]; | ||
6448 | break; | ||
6449 | case ISCSI_FLASHNODE_TCP_WSF_DISABLE: | ||
6450 | fnode_conn->tcp_wsf_disable = fnode_param->value[0]; | ||
6451 | break; | ||
6452 | case ISCSI_FLASHNODE_TCP_TIMER_SCALE: | ||
6453 | fnode_conn->tcp_timer_scale = fnode_param->value[0]; | ||
6454 | break; | ||
6455 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: | ||
6456 | fnode_conn->tcp_timestamp_en = fnode_param->value[0]; | ||
6457 | break; | ||
6458 | case ISCSI_FLASHNODE_IP_FRAG_DISABLE: | ||
6459 | fnode_conn->fragment_disable = fnode_param->value[0]; | ||
6460 | break; | ||
6461 | case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: | ||
6462 | fnode_conn->max_recv_dlength = | ||
6463 | *(unsigned *)fnode_param->value; | ||
6464 | break; | ||
6465 | case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: | ||
6466 | fnode_conn->max_xmit_dlength = | ||
6467 | *(unsigned *)fnode_param->value; | ||
6468 | break; | ||
6469 | case ISCSI_FLASHNODE_FIRST_BURST: | ||
6470 | fnode_sess->first_burst = | ||
6471 | *(unsigned *)fnode_param->value; | ||
6472 | break; | ||
6473 | case ISCSI_FLASHNODE_DEF_TIME2WAIT: | ||
6474 | fnode_sess->time2wait = *(uint16_t *)fnode_param->value; | ||
6475 | break; | ||
6476 | case ISCSI_FLASHNODE_DEF_TIME2RETAIN: | ||
6477 | fnode_sess->time2retain = | ||
6478 | *(uint16_t *)fnode_param->value; | ||
6479 | break; | ||
6480 | case ISCSI_FLASHNODE_MAX_R2T: | ||
6481 | fnode_sess->max_r2t = | ||
6482 | *(uint16_t *)fnode_param->value; | ||
6483 | break; | ||
6484 | case ISCSI_FLASHNODE_KEEPALIVE_TMO: | ||
6485 | fnode_conn->keepalive_timeout = | ||
6486 | *(uint16_t *)fnode_param->value; | ||
6487 | break; | ||
6488 | case ISCSI_FLASHNODE_ISID: | ||
6489 | memcpy(fnode_sess->isid, fnode_param->value, | ||
6490 | sizeof(fnode_sess->isid)); | ||
6491 | break; | ||
6492 | case ISCSI_FLASHNODE_TSID: | ||
6493 | fnode_sess->tsid = *(uint16_t *)fnode_param->value; | ||
6494 | break; | ||
6495 | case ISCSI_FLASHNODE_PORT: | ||
6496 | fnode_conn->port = *(uint16_t *)fnode_param->value; | ||
6497 | break; | ||
6498 | case ISCSI_FLASHNODE_MAX_BURST: | ||
6499 | fnode_sess->max_burst = *(unsigned *)fnode_param->value; | ||
6500 | break; | ||
6501 | case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: | ||
6502 | fnode_sess->default_taskmgmt_timeout = | ||
6503 | *(uint16_t *)fnode_param->value; | ||
6504 | break; | ||
6505 | case ISCSI_FLASHNODE_IPADDR: | ||
6506 | memcpy(fnode_conn->ipaddress, fnode_param->value, | ||
6507 | IPv6_ADDR_LEN); | ||
6508 | break; | ||
6509 | case ISCSI_FLASHNODE_ALIAS: | ||
6510 | rc = iscsi_switch_str_param(&fnode_sess->targetalias, | ||
6511 | (char *)fnode_param->value); | ||
6512 | break; | ||
6513 | case ISCSI_FLASHNODE_REDIRECT_IPADDR: | ||
6514 | memcpy(fnode_conn->redirect_ipaddr, fnode_param->value, | ||
6515 | IPv6_ADDR_LEN); | ||
6516 | break; | ||
6517 | case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: | ||
6518 | fnode_conn->max_segment_size = | ||
6519 | *(unsigned *)fnode_param->value; | ||
6520 | break; | ||
6521 | case ISCSI_FLASHNODE_LOCAL_PORT: | ||
6522 | fnode_conn->local_port = | ||
6523 | *(uint16_t *)fnode_param->value; | ||
6524 | break; | ||
6525 | case ISCSI_FLASHNODE_IPV4_TOS: | ||
6526 | fnode_conn->ipv4_tos = fnode_param->value[0]; | ||
6527 | break; | ||
6528 | case ISCSI_FLASHNODE_IPV6_TC: | ||
6529 | fnode_conn->ipv6_traffic_class = fnode_param->value[0]; | ||
6530 | break; | ||
6531 | case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: | ||
6532 | fnode_conn->ipv6_flow_label = fnode_param->value[0]; | ||
6533 | break; | ||
6534 | case ISCSI_FLASHNODE_NAME: | ||
6535 | rc = iscsi_switch_str_param(&fnode_sess->targetname, | ||
6536 | (char *)fnode_param->value); | ||
6537 | break; | ||
6538 | case ISCSI_FLASHNODE_TPGT: | ||
6539 | fnode_sess->tpgt = *(uint16_t *)fnode_param->value; | ||
6540 | break; | ||
6541 | case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: | ||
6542 | memcpy(fnode_conn->link_local_ipv6_addr, | ||
6543 | fnode_param->value, IPv6_ADDR_LEN); | ||
6544 | break; | ||
6545 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: | ||
6546 | fnode_sess->discovery_parent_type = | ||
6547 | *(uint16_t *)fnode_param->value; | ||
6548 | break; | ||
6549 | case ISCSI_FLASHNODE_TCP_XMIT_WSF: | ||
6550 | fnode_conn->tcp_xmit_wsf = | ||
6551 | *(uint8_t *)fnode_param->value; | ||
6552 | break; | ||
6553 | case ISCSI_FLASHNODE_TCP_RECV_WSF: | ||
6554 | fnode_conn->tcp_recv_wsf = | ||
6555 | *(uint8_t *)fnode_param->value; | ||
6556 | break; | ||
6557 | case ISCSI_FLASHNODE_STATSN: | ||
6558 | fnode_conn->statsn = *(uint32_t *)fnode_param->value; | ||
6559 | break; | ||
6560 | case ISCSI_FLASHNODE_EXP_STATSN: | ||
6561 | fnode_conn->exp_statsn = | ||
6562 | *(uint32_t *)fnode_param->value; | ||
6563 | break; | ||
6564 | default: | ||
6565 | ql4_printk(KERN_ERR, ha, | ||
6566 | "%s: No such sysfs attribute\n", __func__); | ||
6567 | rc = -ENOSYS; | ||
6568 | goto exit_set_param; | ||
6569 | } | ||
6570 | } | ||
6571 | |||
6572 | rc = qla4xxx_sysfs_ddb_apply(fnode_sess, fnode_conn); | ||
6573 | |||
6574 | exit_set_param: | ||
6575 | return rc; | ||
6576 | } | ||
6577 | |||
6578 | /** | ||
6579 | * qla4xxx_sysfs_ddb_delete - Delete firmware DDB entry | ||
6580 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
6581 | * | ||
6582 | * This invalidates the flash ddb entry at the given index | ||
6583 | **/ | ||
6584 | static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess) | ||
6585 | { | ||
6586 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
6587 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
6588 | uint32_t dev_db_start_offset; | ||
6589 | uint32_t dev_db_end_offset; | ||
6590 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6591 | dma_addr_t fw_ddb_entry_dma; | ||
6592 | uint16_t *ddb_cookie = NULL; | ||
6593 | size_t ddb_size; | ||
6594 | void *pddb = NULL; | ||
6595 | int target_id; | ||
6596 | int rc = 0; | ||
6597 | |||
6598 | if (!fnode_sess) { | ||
6599 | rc = -EINVAL; | ||
6600 | goto exit_ddb_del; | ||
6601 | } | ||
6602 | |||
6603 | if (fnode_sess->is_boot_target) { | ||
6604 | rc = -EPERM; | ||
6605 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6606 | "%s: Deletion of boot target entry is not permitted.\n", | ||
6607 | __func__)); | ||
6608 | goto exit_ddb_del; | ||
6609 | } | ||
6610 | |||
6611 | if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) | ||
6612 | goto sysfs_ddb_del; | ||
6613 | |||
6614 | if (is_qla40XX(ha)) { | ||
6615 | dev_db_start_offset = FLASH_OFFSET_DB_INFO; | ||
6616 | dev_db_end_offset = FLASH_OFFSET_DB_END; | ||
6617 | dev_db_start_offset += (fnode_sess->target_id * | ||
6618 | sizeof(*fw_ddb_entry)); | ||
6619 | ddb_size = sizeof(*fw_ddb_entry); | ||
6620 | } else { | ||
6621 | dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + | ||
6622 | (ha->hw.flt_region_ddb << 2); | ||
6623 | /* flt_ddb_size is DDB table size for both ports | ||
6624 | * so divide it by 2 to calculate the offset for second port | ||
6625 | */ | ||
6626 | if (ha->port_num == 1) | ||
6627 | dev_db_start_offset += (ha->hw.flt_ddb_size / 2); | ||
6628 | |||
6629 | dev_db_end_offset = dev_db_start_offset + | ||
6630 | (ha->hw.flt_ddb_size / 2); | ||
6631 | |||
6632 | dev_db_start_offset += (fnode_sess->target_id * | ||
6633 | sizeof(*fw_ddb_entry)); | ||
6634 | dev_db_start_offset += (void *)&(fw_ddb_entry->cookie) - | ||
6635 | (void *)fw_ddb_entry; | ||
6636 | |||
6637 | ddb_size = sizeof(*ddb_cookie); | ||
6638 | } | ||
6639 | |||
6640 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s: start offset=%u, end offset=%u\n", | ||
6641 | __func__, dev_db_start_offset, dev_db_end_offset)); | ||
6642 | |||
6643 | if (dev_db_start_offset > dev_db_end_offset) { | ||
6644 | rc = -EIO; | ||
6645 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s:Invalid DDB index %u\n", | ||
6646 | __func__, fnode_sess->target_id)); | ||
6647 | goto exit_ddb_del; | ||
6648 | } | ||
6649 | |||
6650 | pddb = dma_alloc_coherent(&ha->pdev->dev, ddb_size, | ||
6651 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
6652 | if (!pddb) { | ||
6653 | rc = -ENOMEM; | ||
6654 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6655 | "%s: Unable to allocate dma buffer\n", | ||
6656 | __func__)); | ||
6657 | goto exit_ddb_del; | ||
6658 | } | ||
6659 | |||
6660 | if (is_qla40XX(ha)) { | ||
6661 | fw_ddb_entry = pddb; | ||
6662 | memset(fw_ddb_entry, 0, ddb_size); | ||
6663 | ddb_cookie = &fw_ddb_entry->cookie; | ||
6664 | } else { | ||
6665 | ddb_cookie = pddb; | ||
6666 | } | ||
6667 | |||
6668 | /* invalidate the cookie */ | ||
6669 | *ddb_cookie = 0xFFEE; | ||
6670 | qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, | ||
6671 | ddb_size, FLASH_OPT_RMW_COMMIT); | ||
6672 | |||
6673 | sysfs_ddb_del: | ||
6674 | target_id = fnode_sess->target_id; | ||
6675 | iscsi_destroy_flashnode_sess(fnode_sess); | ||
6676 | ql4_printk(KERN_INFO, ha, | ||
6677 | "%s: session and conn entries for flashnode %u of host %lu deleted\n", | ||
6678 | __func__, target_id, ha->host_no); | ||
6679 | exit_ddb_del: | ||
6680 | if (pddb) | ||
6681 | dma_free_coherent(&ha->pdev->dev, ddb_size, pddb, | ||
6682 | fw_ddb_entry_dma); | ||
6683 | return rc; | ||
6684 | } | ||
6685 | |||
6686 | /** | ||
6687 | * qla4xxx_sysfs_ddb_export - Create sysfs entries for firmware DDBs | ||
6688 | * @ha: pointer to adapter structure | ||
6689 | * | ||
6690 | * Export the firmware DDB for all send targets and normal targets to sysfs. | ||
6691 | **/ | ||
6692 | static int qla4xxx_sysfs_ddb_export(struct scsi_qla_host *ha) | ||
6693 | { | ||
6694 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6695 | dma_addr_t fw_ddb_entry_dma; | ||
6696 | uint16_t max_ddbs; | ||
6697 | uint16_t idx = 0; | ||
6698 | int ret = QLA_SUCCESS; | ||
6699 | |||
6700 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, | ||
6701 | sizeof(*fw_ddb_entry), | ||
6702 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
6703 | if (!fw_ddb_entry) { | ||
6704 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6705 | "%s: Unable to allocate dma buffer\n", | ||
6706 | __func__)); | ||
6707 | return -ENOMEM; | ||
6708 | } | ||
6709 | |||
6710 | max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : | ||
6711 | MAX_DEV_DB_ENTRIES; | ||
6712 | |||
6713 | for (idx = 0; idx < max_ddbs; idx++) { | ||
6714 | if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, fw_ddb_entry_dma, | ||
6715 | idx)) | ||
6716 | continue; | ||
6717 | |||
6718 | ret = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 0); | ||
6719 | if (ret) { | ||
6720 | ret = -EIO; | ||
6721 | break; | ||
6722 | } | ||
6723 | } | ||
6724 | |||
6725 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, | ||
6726 | fw_ddb_entry_dma); | ||
6727 | |||
6728 | return ret; | ||
6729 | } | ||
6730 | |||
6731 | static void qla4xxx_sysfs_ddb_remove(struct scsi_qla_host *ha) | ||
6732 | { | ||
6733 | iscsi_destroy_all_flashnode(ha->host); | ||
6734 | } | ||
6735 | |||
5061 | /** | 6736 | /** |
5062 | * qla4xxx_build_ddb_list - Build ddb list and setup sessions | 6737 | * qla4xxx_build_ddb_list - Build ddb list and setup sessions |
5063 | * @ha: pointer to adapter structure | 6738 | * @ha: pointer to adapter structure |
@@ -5341,8 +7016,11 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
5341 | status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); | 7016 | status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); |
5342 | 7017 | ||
5343 | /* Dont retry adapter initialization if IRQ allocation failed */ | 7018 | /* Dont retry adapter initialization if IRQ allocation failed */ |
5344 | if (!test_bit(AF_IRQ_ATTACHED, &ha->flags)) | 7019 | if (is_qla80XX(ha) && !test_bit(AF_IRQ_ATTACHED, &ha->flags)) { |
7020 | ql4_printk(KERN_WARNING, ha, "%s: Skipping retry of adapter initialization\n", | ||
7021 | __func__); | ||
5345 | goto skip_retry_init; | 7022 | goto skip_retry_init; |
7023 | } | ||
5346 | 7024 | ||
5347 | while ((!test_bit(AF_ONLINE, &ha->flags)) && | 7025 | while ((!test_bit(AF_ONLINE, &ha->flags)) && |
5348 | init_retry_count++ < MAX_INIT_RETRIES) { | 7026 | init_retry_count++ < MAX_INIT_RETRIES) { |
@@ -5445,6 +7123,10 @@ skip_retry_init: | |||
5445 | ql4_printk(KERN_ERR, ha, | 7123 | ql4_printk(KERN_ERR, ha, |
5446 | "%s: No iSCSI boot target configured\n", __func__); | 7124 | "%s: No iSCSI boot target configured\n", __func__); |
5447 | 7125 | ||
7126 | if (qla4xxx_sysfs_ddb_export(ha)) | ||
7127 | ql4_printk(KERN_ERR, ha, | ||
7128 | "%s: Error exporting ddb to sysfs\n", __func__); | ||
7129 | |||
5448 | /* Perform the build ddb list and login to each */ | 7130 | /* Perform the build ddb list and login to each */ |
5449 | qla4xxx_build_ddb_list(ha, INIT_ADAPTER); | 7131 | qla4xxx_build_ddb_list(ha, INIT_ADAPTER); |
5450 | iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); | 7132 | iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); |
@@ -5570,6 +7252,7 @@ static void qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
5570 | qla4xxx_destroy_fw_ddb_session(ha); | 7252 | qla4xxx_destroy_fw_ddb_session(ha); |
5571 | qla4_8xxx_free_sysfs_attr(ha); | 7253 | qla4_8xxx_free_sysfs_attr(ha); |
5572 | 7254 | ||
7255 | qla4xxx_sysfs_ddb_remove(ha); | ||
5573 | scsi_remove_host(ha->host); | 7256 | scsi_remove_host(ha->host); |
5574 | 7257 | ||
5575 | qla4xxx_free_adapter(ha); | 7258 | qla4xxx_free_adapter(ha); |
@@ -5669,7 +7352,6 @@ struct srb *qla4xxx_del_from_active_array(struct scsi_qla_host *ha, | |||
5669 | 7352 | ||
5670 | /* update counters */ | 7353 | /* update counters */ |
5671 | if (srb->flags & SRB_DMA_VALID) { | 7354 | if (srb->flags & SRB_DMA_VALID) { |
5672 | ha->req_q_count += srb->iocb_cnt; | ||
5673 | ha->iocb_cnt -= srb->iocb_cnt; | 7355 | ha->iocb_cnt -= srb->iocb_cnt; |
5674 | if (srb->cmd) | 7356 | if (srb->cmd) |
5675 | srb->cmd->host_scribble = | 7357 | srb->cmd->host_scribble = |
@@ -6081,6 +7763,7 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type) | |||
6081 | { | 7763 | { |
6082 | struct scsi_qla_host *ha = to_qla_host(shost); | 7764 | struct scsi_qla_host *ha = to_qla_host(shost); |
6083 | int rval = QLA_SUCCESS; | 7765 | int rval = QLA_SUCCESS; |
7766 | uint32_t idc_ctrl; | ||
6084 | 7767 | ||
6085 | if (ql4xdontresethba) { | 7768 | if (ql4xdontresethba) { |
6086 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n", | 7769 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Don't Reset HBA\n", |
@@ -6111,6 +7794,14 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type) | |||
6111 | } | 7794 | } |
6112 | 7795 | ||
6113 | recover_adapter: | 7796 | recover_adapter: |
7797 | /* For ISP83XX set graceful reset bit in IDC_DRV_CTRL if | ||
7798 | * reset is issued by application */ | ||
7799 | if (is_qla8032(ha) && test_bit(DPC_RESET_HA, &ha->dpc_flags)) { | ||
7800 | idc_ctrl = qla4_83xx_rd_reg(ha, QLA83XX_IDC_DRV_CTRL); | ||
7801 | qla4_83xx_wr_reg(ha, QLA83XX_IDC_DRV_CTRL, | ||
7802 | (idc_ctrl | GRACEFUL_RESET_BIT1)); | ||
7803 | } | ||
7804 | |||
6114 | rval = qla4xxx_recover_adapter(ha); | 7805 | rval = qla4xxx_recover_adapter(ha); |
6115 | if (rval != QLA_SUCCESS) { | 7806 | if (rval != QLA_SUCCESS) { |
6116 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n", | 7807 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: recover adapter fail\n", |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 6775a45af315..83e0fec35d56 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,4 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.03.00-k4" | 8 | #define QLA4XXX_DRIVER_VERSION "5.03.00-k8" |