diff options
author | Adheer Chandravanshi <adheer.chandravanshi@qlogic.com> | 2013-03-22 07:41:31 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-04-11 18:32:26 -0400 |
commit | 1e9e2be3ee03b8b5c6066d3943c9c5ab1632ed0a (patch) | |
tree | febbbde85d138c7926a6fea8ea14409d83755231 | |
parent | adaf6990ddf50b301c38eda7c0cb7b182df01c3b (diff) |
[SCSI] qla4xxx: Add flash node mgmt support
This patch allows iscsiadm to manage iSCSI target information stored on
qla4xxx adapter flash on per host basis.
Signed-off-by: Adheer Chandravanshi <adheer.chandravanshi@qlogic.com>
Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 22 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 34 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 7 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 106 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 12 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 1647 |
6 files changed, 1824 insertions, 4 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 129f5dd02822..b487b0aa4dee 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -159,6 +159,25 @@ | |||
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_TYPE_IPV4 "ipv4" | ||
163 | #define DEV_TYPE_IPV6 "ipv6" | ||
164 | |||
165 | #define DEV_DB_NON_PERSISTENT 0 | ||
166 | #define DEV_DB_PERSISTENT 1 | ||
167 | |||
168 | #define COPY_ISID(dst_isid, src_isid) { \ | ||
169 | int i, j; \ | ||
170 | for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \ | ||
171 | dst_isid[i++] = src_isid[j--]; \ | ||
172 | } | ||
173 | |||
174 | #define SET_BITVAL(o, n, v) { \ | ||
175 | if (o) \ | ||
176 | n |= v; \ | ||
177 | else \ | ||
178 | n &= ~v; \ | ||
179 | } | ||
180 | |||
162 | /* | 181 | /* |
163 | * Retry & Timeout Values | 182 | * Retry & Timeout Values |
164 | */ | 183 | */ |
@@ -363,6 +382,8 @@ struct ql82xx_hw_data { | |||
363 | uint32_t flt_iscsi_param; | 382 | uint32_t flt_iscsi_param; |
364 | uint32_t flt_region_chap; | 383 | uint32_t flt_region_chap; |
365 | uint32_t flt_chap_size; | 384 | uint32_t flt_chap_size; |
385 | uint32_t flt_region_ddb; | ||
386 | uint32_t flt_ddb_size; | ||
366 | }; | 387 | }; |
367 | 388 | ||
368 | struct qla4_8xxx_legacy_intr_set { | 389 | struct qla4_8xxx_legacy_intr_set { |
@@ -501,6 +522,7 @@ struct scsi_qla_host { | |||
501 | #define AF_INIT_DONE 1 /* 0x00000002 */ | 522 | #define AF_INIT_DONE 1 /* 0x00000002 */ |
502 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ | 523 | #define AF_MBOX_COMMAND 2 /* 0x00000004 */ |
503 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ | 524 | #define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ |
525 | #define AF_ST_DISCOVERY_IN_PROGRESS 4 /* 0x00000010 */ | ||
504 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ | 526 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 */ |
505 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ | 527 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ |
506 | #define AF_LINK_UP 8 /* 0x00000100 */ | 528 | #define AF_LINK_UP 8 /* 0x00000100 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index ad9d2e2d370f..5945829d662f 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; |
@@ -779,12 +782,41 @@ struct dev_db_entry { | |||
779 | #define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */ | 782 | #define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */ |
780 | #define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */ | 783 | #define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */ |
781 | 784 | ||
785 | #define OPT_IS_FW_ASSIGNED_IPV6 11 | ||
786 | #define OPT_IPV6_DEVICE 8 | ||
787 | #define OPT_AUTO_SENDTGTS_DISABLE 6 | ||
788 | #define OPT_DISC_SESSION 4 | ||
789 | #define OPT_ENTRY_STATE 3 | ||
782 | uint16_t exec_throttle; /* 02-03 */ | 790 | uint16_t exec_throttle; /* 02-03 */ |
783 | uint16_t exec_count; /* 04-05 */ | 791 | uint16_t exec_count; /* 04-05 */ |
784 | uint16_t res0; /* 06-07 */ | 792 | uint16_t res0; /* 06-07 */ |
785 | uint16_t iscsi_options; /* 08-09 */ | 793 | uint16_t iscsi_options; /* 08-09 */ |
794 | #define ISCSIOPT_HEADER_DIGEST_EN 13 | ||
795 | #define ISCSIOPT_DATA_DIGEST_EN 12 | ||
796 | #define ISCSIOPT_IMMEDIATE_DATA_EN 11 | ||
797 | #define ISCSIOPT_INITIAL_R2T_EN 10 | ||
798 | #define ISCSIOPT_DATA_SEQ_IN_ORDER 9 | ||
799 | #define ISCSIOPT_DATA_PDU_IN_ORDER 8 | ||
800 | #define ISCSIOPT_CHAP_AUTH_EN 7 | ||
801 | #define ISCSIOPT_SNACK_REQ_EN 6 | ||
802 | #define ISCSIOPT_DISCOVERY_LOGOUT_EN 5 | ||
803 | #define ISCSIOPT_BIDI_CHAP_EN 4 | ||
804 | #define ISCSIOPT_DISCOVERY_AUTH_OPTIONAL 3 | ||
805 | #define ISCSIOPT_ERL1 1 | ||
806 | #define ISCSIOPT_ERL0 0 | ||
807 | |||
786 | uint16_t tcp_options; /* 0A-0B */ | 808 | uint16_t tcp_options; /* 0A-0B */ |
809 | #define TCPOPT_TIMESTAMP_STAT 6 | ||
810 | #define TCPOPT_NAGLE_DISABLE 5 | ||
811 | #define TCPOPT_WSF_DISABLE 4 | ||
812 | #define TCPOPT_TIMER_SCALE3 3 | ||
813 | #define TCPOPT_TIMER_SCALE2 2 | ||
814 | #define TCPOPT_TIMER_SCALE1 1 | ||
815 | #define TCPOPT_TIMESTAMP_EN 0 | ||
816 | |||
787 | uint16_t ip_options; /* 0C-0D */ | 817 | uint16_t ip_options; /* 0C-0D */ |
818 | #define IPOPT_FRAGMENT_DISABLE 4 | ||
819 | |||
788 | uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */ | 820 | uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */ |
789 | #define BYTE_UNITS 512 | 821 | #define BYTE_UNITS 512 |
790 | uint32_t res1; /* 10-13 */ | 822 | uint32_t res1; /* 10-13 */ |
@@ -816,6 +848,8 @@ struct dev_db_entry { | |||
816 | * much RAM */ | 848 | * much RAM */ |
817 | uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */ | 849 | uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */ |
818 | uint8_t res5[0x10]; /* 1B0-1BF */ | 850 | uint8_t res5[0x10]; /* 1B0-1BF */ |
851 | #define DDB_NO_LINK 0xFFFF | ||
852 | #define DDB_ISNS 0xFFFD | ||
819 | uint16_t ddb_link; /* 1C0-1C1 */ | 853 | uint16_t ddb_link; /* 1C0-1C1 */ |
820 | uint16_t chap_tbl_idx; /* 1C2-1C3 */ | 854 | uint16_t chap_tbl_idx; /* 1C2-1C3 */ |
821 | uint16_t tgt_portal_grp; /* 1C4-1C5 */ | 855 | uint16_t tgt_portal_grp; /* 1C4-1C5 */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 22706f66266f..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); |
@@ -259,6 +262,10 @@ int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha); | |||
259 | void qla4_83xx_disable_pause(struct scsi_qla_host *ha); | 262 | void qla4_83xx_disable_pause(struct scsi_qla_host *ha); |
260 | void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha); | 263 | void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha); |
261 | 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); | ||
262 | 269 | ||
263 | extern int ql4xextended_error_logging; | 270 | extern int ql4xextended_error_logging; |
264 | extern int ql4xdontresethba; | 271 | extern int ql4xdontresethba; |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index ce4654501fab..8985997de576 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -1288,8 +1288,8 @@ exit_about_fw: | |||
1288 | return status; | 1288 | return status; |
1289 | } | 1289 | } |
1290 | 1290 | ||
1291 | 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, |
1292 | dma_addr_t dma_addr) | 1292 | dma_addr_t dma_addr) |
1293 | { | 1293 | { |
1294 | uint32_t mbox_cmd[MBOX_REG_COUNT]; | 1294 | uint32_t mbox_cmd[MBOX_REG_COUNT]; |
1295 | uint32_t mbox_sts[MBOX_REG_COUNT]; | 1295 | uint32_t mbox_sts[MBOX_REG_COUNT]; |
@@ -1417,6 +1417,52 @@ exit_bootdb_failed: | |||
1417 | return status; | 1417 | return status; |
1418 | } | 1418 | } |
1419 | 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 = FLASH_OFFSET_DB_INFO; | ||
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 | } else { | ||
1433 | dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + | ||
1434 | (ha->hw.flt_region_ddb << 2); | ||
1435 | /* flt_ddb_size is DDB table size for both ports | ||
1436 | * so divide it by 2 to calculate the offset for second port | ||
1437 | */ | ||
1438 | if (ha->port_num == 1) | ||
1439 | dev_db_start_offset += (ha->hw.flt_ddb_size / 2); | ||
1440 | } | ||
1441 | |||
1442 | dev_db_end_offset = dev_db_start_offset + (ha->hw.flt_ddb_size / 2); | ||
1443 | dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry)); | ||
1444 | |||
1445 | if (dev_db_start_offset > dev_db_end_offset) { | ||
1446 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
1447 | "%s:Invalid DDB index %d", __func__, | ||
1448 | ddb_index)); | ||
1449 | goto exit_fdb_failed; | ||
1450 | } | ||
1451 | |||
1452 | if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, | ||
1453 | sizeof(*fw_ddb_entry)) != QLA_SUCCESS) { | ||
1454 | ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n", | ||
1455 | ha->host_no, __func__); | ||
1456 | goto exit_fdb_failed; | ||
1457 | } | ||
1458 | |||
1459 | if (fw_ddb_entry->cookie == DDB_VALID_COOKIE) | ||
1460 | status = QLA_SUCCESS; | ||
1461 | |||
1462 | exit_fdb_failed: | ||
1463 | return status; | ||
1464 | } | ||
1465 | |||
1420 | int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, | 1466 | int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password, |
1421 | uint16_t idx) | 1467 | uint16_t idx) |
1422 | { | 1468 | { |
@@ -1510,6 +1556,62 @@ exit_set_chap: | |||
1510 | return ret; | 1556 | return ret; |
1511 | } | 1557 | } |
1512 | 1558 | ||
1559 | |||
1560 | int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username, | ||
1561 | char *password, uint16_t chap_index) | ||
1562 | { | ||
1563 | int rval = QLA_ERROR; | ||
1564 | struct ql4_chap_table *chap_table = NULL; | ||
1565 | int max_chap_entries; | ||
1566 | |||
1567 | if (!ha->chap_list) { | ||
1568 | ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n"); | ||
1569 | rval = QLA_ERROR; | ||
1570 | goto exit_uni_chap; | ||
1571 | } | ||
1572 | |||
1573 | if (!username || !password) { | ||
1574 | ql4_printk(KERN_ERR, ha, "No memory for username & secret\n"); | ||
1575 | rval = QLA_ERROR; | ||
1576 | goto exit_uni_chap; | ||
1577 | } | ||
1578 | |||
1579 | if (is_qla80XX(ha)) | ||
1580 | max_chap_entries = (ha->hw.flt_chap_size / 2) / | ||
1581 | sizeof(struct ql4_chap_table); | ||
1582 | else | ||
1583 | max_chap_entries = MAX_CHAP_ENTRIES_40XX; | ||
1584 | |||
1585 | if (chap_index > max_chap_entries) { | ||
1586 | ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); | ||
1587 | rval = QLA_ERROR; | ||
1588 | goto exit_uni_chap; | ||
1589 | } | ||
1590 | |||
1591 | mutex_lock(&ha->chap_sem); | ||
1592 | chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index; | ||
1593 | if (chap_table->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { | ||
1594 | rval = QLA_ERROR; | ||
1595 | goto exit_unlock_uni_chap; | ||
1596 | } | ||
1597 | |||
1598 | if (!(chap_table->flags & BIT_6)) { | ||
1599 | ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n"); | ||
1600 | rval = QLA_ERROR; | ||
1601 | goto exit_unlock_uni_chap; | ||
1602 | } | ||
1603 | |||
1604 | strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN); | ||
1605 | strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN); | ||
1606 | |||
1607 | rval = QLA_SUCCESS; | ||
1608 | |||
1609 | exit_unlock_uni_chap: | ||
1610 | mutex_unlock(&ha->chap_sem); | ||
1611 | exit_uni_chap: | ||
1612 | return rval; | ||
1613 | } | ||
1614 | |||
1513 | /** | 1615 | /** |
1514 | * qla4xxx_get_chap_index - Get chap index given username and secret | 1616 | * qla4xxx_get_chap_index - Get chap index given username and secret |
1515 | * @ha: pointer to adapter structure | 1617 | * @ha: pointer to adapter structure |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 31fac90e54e2..5f1dbb7c7bef 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; |
@@ -3168,13 +3172,17 @@ no_flash_data: | |||
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 >> 2; | 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, | 3179 | DEBUG2(ql4_printk(KERN_INFO, ha, |
3174 | "FLT[%s]: flt=0x%x fdt=0x%x boot=0x%x bootload=0x%x fw=0x%x chap=0x%x\n", | 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 | loc, hw->flt_region_flt, hw->flt_region_fdt, | 3181 | loc, hw->flt_region_flt, hw->flt_region_fdt, |
3176 | hw->flt_region_boot, hw->flt_region_bootload, | 3182 | hw->flt_region_boot, hw->flt_region_bootload, |
3177 | hw->flt_region_fw, hw->flt_region_chap)); | 3183 | hw->flt_region_fw, hw->flt_region_chap, |
3184 | hw->flt_chap_size, hw->flt_region_ddb, | ||
3185 | hw->flt_ddb_size)); | ||
3178 | } | 3186 | } |
3179 | 3187 | ||
3180 | static void | 3188 | static void |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index f3cf04ebf516..497ac681d733 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; |
@@ -1922,6 +2011,250 @@ 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, DEV_TYPE_IPV6); | ||
2025 | if (rc) | ||
2026 | goto exit_copy; | ||
2027 | } else { | ||
2028 | rc = iscsi_switch_str_param(&sess->portal_type, DEV_TYPE_IPV4); | ||
2029 | if (rc) | ||
2030 | goto exit_copy; | ||
2031 | } | ||
2032 | |||
2033 | sess->auto_snd_tgt_disable = test_bit(OPT_AUTO_SENDTGTS_DISABLE, | ||
2034 | &options); | ||
2035 | sess->discovery_sess = test_bit(OPT_DISC_SESSION, &options); | ||
2036 | sess->entry_state = test_bit(OPT_ENTRY_STATE, &options); | ||
2037 | |||
2038 | options = le16_to_cpu(fw_ddb_entry->iscsi_options); | ||
2039 | conn->hdrdgst_en = test_bit(ISCSIOPT_HEADER_DIGEST_EN, &options); | ||
2040 | conn->datadgst_en = test_bit(ISCSIOPT_DATA_DIGEST_EN, &options); | ||
2041 | sess->imm_data_en = test_bit(ISCSIOPT_IMMEDIATE_DATA_EN, &options); | ||
2042 | sess->initial_r2t_en = test_bit(ISCSIOPT_INITIAL_R2T_EN, &options); | ||
2043 | sess->dataseq_inorder_en = test_bit(ISCSIOPT_DATA_SEQ_IN_ORDER, | ||
2044 | &options); | ||
2045 | sess->pdu_inorder_en = test_bit(ISCSIOPT_DATA_PDU_IN_ORDER, &options); | ||
2046 | sess->chap_auth_en = test_bit(ISCSIOPT_CHAP_AUTH_EN, &options); | ||
2047 | conn->snack_req_en = test_bit(ISCSIOPT_SNACK_REQ_EN, &options); | ||
2048 | sess->discovery_logout_en = test_bit(ISCSIOPT_DISCOVERY_LOGOUT_EN, | ||
2049 | &options); | ||
2050 | sess->bidi_chap_en = test_bit(ISCSIOPT_BIDI_CHAP_EN, &options); | ||
2051 | sess->discovery_auth_optional = | ||
2052 | test_bit(ISCSIOPT_DISCOVERY_AUTH_OPTIONAL, &options); | ||
2053 | if (test_bit(ISCSIOPT_ERL1, &options)) | ||
2054 | sess->erl |= BIT_1; | ||
2055 | if (test_bit(ISCSIOPT_ERL0, &options)) | ||
2056 | sess->erl |= BIT_0; | ||
2057 | |||
2058 | options = le16_to_cpu(fw_ddb_entry->tcp_options); | ||
2059 | conn->tcp_timestamp_stat = test_bit(TCPOPT_TIMESTAMP_STAT, &options); | ||
2060 | conn->tcp_nagle_disable = test_bit(TCPOPT_NAGLE_DISABLE, &options); | ||
2061 | conn->tcp_wsf_disable = test_bit(TCPOPT_WSF_DISABLE, &options); | ||
2062 | if (test_bit(TCPOPT_TIMER_SCALE3, &options)) | ||
2063 | conn->tcp_timer_scale |= BIT_3; | ||
2064 | if (test_bit(TCPOPT_TIMER_SCALE2, &options)) | ||
2065 | conn->tcp_timer_scale |= BIT_2; | ||
2066 | if (test_bit(TCPOPT_TIMER_SCALE1, &options)) | ||
2067 | conn->tcp_timer_scale |= BIT_1; | ||
2068 | |||
2069 | conn->tcp_timer_scale >>= 1; | ||
2070 | conn->tcp_timestamp_en = test_bit(TCPOPT_TIMESTAMP_EN, &options); | ||
2071 | |||
2072 | options = le16_to_cpu(fw_ddb_entry->ip_options); | ||
2073 | conn->fragment_disable = test_bit(IPOPT_FRAGMENT_DISABLE, &options); | ||
2074 | |||
2075 | conn->max_recv_dlength = BYTE_UNITS * | ||
2076 | le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); | ||
2077 | conn->max_xmit_dlength = BYTE_UNITS * | ||
2078 | le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len); | ||
2079 | sess->first_burst = BYTE_UNITS * | ||
2080 | le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len); | ||
2081 | sess->max_burst = BYTE_UNITS * | ||
2082 | le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len); | ||
2083 | sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t); | ||
2084 | sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); | ||
2085 | sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain); | ||
2086 | sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); | ||
2087 | conn->max_segment_size = le16_to_cpu(fw_ddb_entry->mss); | ||
2088 | conn->tcp_xmit_wsf = fw_ddb_entry->tcp_xmt_wsf; | ||
2089 | conn->tcp_recv_wsf = fw_ddb_entry->tcp_rcv_wsf; | ||
2090 | conn->ipv6_flow_label = le16_to_cpu(fw_ddb_entry->ipv6_flow_lbl); | ||
2091 | conn->keepalive_timeout = le16_to_cpu(fw_ddb_entry->ka_timeout); | ||
2092 | conn->local_port = le16_to_cpu(fw_ddb_entry->lcl_port); | ||
2093 | conn->statsn = le32_to_cpu(fw_ddb_entry->stat_sn); | ||
2094 | conn->exp_statsn = le32_to_cpu(fw_ddb_entry->exp_stat_sn); | ||
2095 | sess->discovery_parent_idx = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
2096 | sess->discovery_parent_type = le16_to_cpu(fw_ddb_entry->ddb_link); | ||
2097 | sess->chap_out_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx); | ||
2098 | sess->tsid = le16_to_cpu(fw_ddb_entry->tsid); | ||
2099 | |||
2100 | sess->default_taskmgmt_timeout = | ||
2101 | le16_to_cpu(fw_ddb_entry->def_timeout); | ||
2102 | conn->port = le16_to_cpu(fw_ddb_entry->port); | ||
2103 | |||
2104 | options = le16_to_cpu(fw_ddb_entry->options); | ||
2105 | conn->ipaddress = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); | ||
2106 | if (!conn->ipaddress) { | ||
2107 | rc = -ENOMEM; | ||
2108 | goto exit_copy; | ||
2109 | } | ||
2110 | |||
2111 | conn->redirect_ipaddr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); | ||
2112 | if (!conn->redirect_ipaddr) { | ||
2113 | rc = -ENOMEM; | ||
2114 | goto exit_copy; | ||
2115 | } | ||
2116 | |||
2117 | memcpy(conn->ipaddress, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN); | ||
2118 | memcpy(conn->redirect_ipaddr, fw_ddb_entry->tgt_addr, IPv6_ADDR_LEN); | ||
2119 | |||
2120 | if (test_bit(OPT_IPV6_DEVICE, &options)) { | ||
2121 | conn->ipv6_traffic_class = fw_ddb_entry->ipv4_tos; | ||
2122 | |||
2123 | conn->link_local_ipv6_addr = kzalloc(IPv6_ADDR_LEN, GFP_KERNEL); | ||
2124 | if (!conn->link_local_ipv6_addr) { | ||
2125 | rc = -ENOMEM; | ||
2126 | goto exit_copy; | ||
2127 | } | ||
2128 | |||
2129 | memcpy(conn->link_local_ipv6_addr, | ||
2130 | fw_ddb_entry->link_local_ipv6_addr, IPv6_ADDR_LEN); | ||
2131 | } else { | ||
2132 | conn->ipv4_tos = fw_ddb_entry->ipv4_tos; | ||
2133 | } | ||
2134 | |||
2135 | if (fw_ddb_entry->iscsi_name[0]) { | ||
2136 | rc = iscsi_switch_str_param(&sess->targetname, | ||
2137 | (char *)fw_ddb_entry->iscsi_name); | ||
2138 | if (rc) | ||
2139 | goto exit_copy; | ||
2140 | } | ||
2141 | |||
2142 | if (fw_ddb_entry->iscsi_alias[0]) { | ||
2143 | rc = iscsi_switch_str_param(&sess->targetalias, | ||
2144 | (char *)fw_ddb_entry->iscsi_alias); | ||
2145 | if (rc) | ||
2146 | goto exit_copy; | ||
2147 | } | ||
2148 | |||
2149 | COPY_ISID(sess->isid, fw_ddb_entry->isid); | ||
2150 | |||
2151 | exit_copy: | ||
2152 | return rc; | ||
2153 | } | ||
2154 | |||
2155 | static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess, | ||
2156 | struct iscsi_bus_flash_conn *conn, | ||
2157 | struct dev_db_entry *fw_ddb_entry) | ||
2158 | { | ||
2159 | uint16_t options; | ||
2160 | int rc = 0; | ||
2161 | |||
2162 | options = le16_to_cpu(fw_ddb_entry->options); | ||
2163 | SET_BITVAL(conn->is_fw_assigned_ipv6, options, BIT_11); | ||
2164 | if (!strncmp(sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
2165 | options |= BIT_8; | ||
2166 | else | ||
2167 | options &= ~BIT_8; | ||
2168 | |||
2169 | SET_BITVAL(sess->auto_snd_tgt_disable, options, BIT_6); | ||
2170 | SET_BITVAL(sess->discovery_sess, options, BIT_4); | ||
2171 | SET_BITVAL(sess->entry_state, options, BIT_3); | ||
2172 | fw_ddb_entry->options = cpu_to_le16(options); | ||
2173 | |||
2174 | options = le16_to_cpu(fw_ddb_entry->iscsi_options); | ||
2175 | SET_BITVAL(conn->hdrdgst_en, options, BIT_13); | ||
2176 | SET_BITVAL(conn->datadgst_en, options, BIT_12); | ||
2177 | SET_BITVAL(sess->imm_data_en, options, BIT_11); | ||
2178 | SET_BITVAL(sess->initial_r2t_en, options, BIT_10); | ||
2179 | SET_BITVAL(sess->dataseq_inorder_en, options, BIT_9); | ||
2180 | SET_BITVAL(sess->pdu_inorder_en, options, BIT_8); | ||
2181 | SET_BITVAL(sess->chap_auth_en, options, BIT_7); | ||
2182 | SET_BITVAL(conn->snack_req_en, options, BIT_6); | ||
2183 | SET_BITVAL(sess->discovery_logout_en, options, BIT_5); | ||
2184 | SET_BITVAL(sess->bidi_chap_en, options, BIT_4); | ||
2185 | SET_BITVAL(sess->discovery_auth_optional, options, BIT_3); | ||
2186 | SET_BITVAL(sess->erl & BIT_1, options, BIT_1); | ||
2187 | SET_BITVAL(sess->erl & BIT_0, options, BIT_0); | ||
2188 | fw_ddb_entry->iscsi_options = cpu_to_le16(options); | ||
2189 | |||
2190 | options = le16_to_cpu(fw_ddb_entry->tcp_options); | ||
2191 | SET_BITVAL(conn->tcp_timestamp_stat, options, BIT_6); | ||
2192 | SET_BITVAL(conn->tcp_nagle_disable, options, BIT_5); | ||
2193 | SET_BITVAL(conn->tcp_wsf_disable, options, BIT_4); | ||
2194 | SET_BITVAL(conn->tcp_timer_scale & BIT_2, options, BIT_3); | ||
2195 | SET_BITVAL(conn->tcp_timer_scale & BIT_1, options, BIT_2); | ||
2196 | SET_BITVAL(conn->tcp_timer_scale & BIT_0, options, BIT_1); | ||
2197 | SET_BITVAL(conn->tcp_timestamp_en, options, BIT_0); | ||
2198 | fw_ddb_entry->tcp_options = cpu_to_le16(options); | ||
2199 | |||
2200 | options = le16_to_cpu(fw_ddb_entry->ip_options); | ||
2201 | SET_BITVAL(conn->fragment_disable, options, BIT_4); | ||
2202 | fw_ddb_entry->ip_options = cpu_to_le16(options); | ||
2203 | |||
2204 | fw_ddb_entry->iscsi_max_outsnd_r2t = cpu_to_le16(sess->max_r2t); | ||
2205 | fw_ddb_entry->iscsi_max_rcv_data_seg_len = | ||
2206 | cpu_to_le16(conn->max_recv_dlength / BYTE_UNITS); | ||
2207 | fw_ddb_entry->iscsi_max_snd_data_seg_len = | ||
2208 | cpu_to_le16(conn->max_xmit_dlength / BYTE_UNITS); | ||
2209 | fw_ddb_entry->iscsi_first_burst_len = | ||
2210 | cpu_to_le16(sess->first_burst / BYTE_UNITS); | ||
2211 | fw_ddb_entry->iscsi_max_burst_len = cpu_to_le16(sess->max_burst / | ||
2212 | BYTE_UNITS); | ||
2213 | fw_ddb_entry->iscsi_def_time2wait = cpu_to_le16(sess->time2wait); | ||
2214 | fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain); | ||
2215 | fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt); | ||
2216 | fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size); | ||
2217 | fw_ddb_entry->tcp_xmt_wsf = cpu_to_le16(conn->tcp_xmit_wsf); | ||
2218 | fw_ddb_entry->tcp_rcv_wsf = cpu_to_le16(conn->tcp_recv_wsf); | ||
2219 | fw_ddb_entry->ipv4_tos = conn->ipv4_tos; | ||
2220 | fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label); | ||
2221 | fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout); | ||
2222 | fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port); | ||
2223 | fw_ddb_entry->stat_sn = cpu_to_le16(conn->statsn); | ||
2224 | fw_ddb_entry->exp_stat_sn = cpu_to_le16(conn->exp_statsn); | ||
2225 | fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_type); | ||
2226 | fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx); | ||
2227 | fw_ddb_entry->tsid = cpu_to_le16(sess->tsid); | ||
2228 | fw_ddb_entry->port = cpu_to_le16(conn->port); | ||
2229 | fw_ddb_entry->def_timeout = | ||
2230 | cpu_to_le16(sess->default_taskmgmt_timeout); | ||
2231 | |||
2232 | if (conn->ipaddress) | ||
2233 | memcpy(fw_ddb_entry->ip_addr, conn->ipaddress, | ||
2234 | sizeof(fw_ddb_entry->ip_addr)); | ||
2235 | |||
2236 | if (conn->redirect_ipaddr) | ||
2237 | memcpy(fw_ddb_entry->tgt_addr, conn->redirect_ipaddr, | ||
2238 | sizeof(fw_ddb_entry->tgt_addr)); | ||
2239 | |||
2240 | if (conn->link_local_ipv6_addr) | ||
2241 | memcpy(fw_ddb_entry->link_local_ipv6_addr, | ||
2242 | conn->link_local_ipv6_addr, | ||
2243 | sizeof(fw_ddb_entry->link_local_ipv6_addr)); | ||
2244 | |||
2245 | if (sess->targetname) | ||
2246 | memcpy(fw_ddb_entry->iscsi_name, sess->targetname, | ||
2247 | sizeof(fw_ddb_entry->iscsi_name)); | ||
2248 | |||
2249 | if (sess->targetalias) | ||
2250 | memcpy(fw_ddb_entry->iscsi_alias, sess->targetalias, | ||
2251 | sizeof(fw_ddb_entry->iscsi_alias)); | ||
2252 | |||
2253 | COPY_ISID(fw_ddb_entry->isid, sess->isid); | ||
2254 | |||
2255 | return rc; | ||
2256 | } | ||
2257 | |||
1925 | static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | 2258 | static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, |
1926 | struct dev_db_entry *fw_ddb_entry, | 2259 | struct dev_db_entry *fw_ddb_entry, |
1927 | struct iscsi_cls_session *cls_sess, | 2260 | struct iscsi_cls_session *cls_sess, |
@@ -5062,6 +5395,1315 @@ exit_nt_list: | |||
5062 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | 5395 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); |
5063 | } | 5396 | } |
5064 | 5397 | ||
5398 | static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, | ||
5399 | struct list_head *list_nt) | ||
5400 | { | ||
5401 | struct dev_db_entry *fw_ddb_entry; | ||
5402 | dma_addr_t fw_ddb_dma; | ||
5403 | int max_ddbs; | ||
5404 | int fw_idx_size; | ||
5405 | int ret; | ||
5406 | uint32_t idx = 0, next_idx = 0; | ||
5407 | uint32_t state = 0, conn_err = 0; | ||
5408 | uint16_t conn_id = 0; | ||
5409 | struct qla_ddb_index *nt_ddb_idx; | ||
5410 | |||
5411 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
5412 | &fw_ddb_dma); | ||
5413 | if (fw_ddb_entry == NULL) { | ||
5414 | DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); | ||
5415 | goto exit_new_nt_list; | ||
5416 | } | ||
5417 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5418 | MAX_DEV_DB_ENTRIES; | ||
5419 | fw_idx_size = sizeof(struct qla_ddb_index); | ||
5420 | |||
5421 | for (idx = 0; idx < max_ddbs; idx = next_idx) { | ||
5422 | ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma, | ||
5423 | NULL, &next_idx, &state, | ||
5424 | &conn_err, NULL, &conn_id); | ||
5425 | if (ret == QLA_ERROR) | ||
5426 | break; | ||
5427 | |||
5428 | /* Check if NT, then add it to list */ | ||
5429 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) | ||
5430 | goto continue_next_new_nt; | ||
5431 | |||
5432 | if (!(state == DDB_DS_NO_CONNECTION_ACTIVE)) | ||
5433 | goto continue_next_new_nt; | ||
5434 | |||
5435 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
5436 | "Adding DDB to session = 0x%x\n", idx)); | ||
5437 | |||
5438 | nt_ddb_idx = vmalloc(fw_idx_size); | ||
5439 | if (!nt_ddb_idx) | ||
5440 | break; | ||
5441 | |||
5442 | nt_ddb_idx->fw_ddb_idx = idx; | ||
5443 | |||
5444 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | ||
5445 | if (ret == QLA_SUCCESS) { | ||
5446 | /* free nt_ddb_idx and do not add to list_nt */ | ||
5447 | vfree(nt_ddb_idx); | ||
5448 | goto continue_next_new_nt; | ||
5449 | } | ||
5450 | |||
5451 | list_add_tail(&nt_ddb_idx->list, list_nt); | ||
5452 | |||
5453 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | ||
5454 | idx); | ||
5455 | if (ret == QLA_ERROR) | ||
5456 | goto exit_new_nt_list; | ||
5457 | |||
5458 | continue_next_new_nt: | ||
5459 | if (next_idx == 0) | ||
5460 | break; | ||
5461 | } | ||
5462 | |||
5463 | exit_new_nt_list: | ||
5464 | if (fw_ddb_entry) | ||
5465 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | ||
5466 | } | ||
5467 | |||
5468 | /** | ||
5469 | * qla4xxx_sysfs_ddb_is_non_persistent - check for non-persistence of ddb entry | ||
5470 | * @dev: dev associated with the sysfs entry | ||
5471 | * @data: pointer to flashnode session object | ||
5472 | * | ||
5473 | * Returns: | ||
5474 | * 1: if flashnode entry is non-persistent | ||
5475 | * 0: if flashnode entry is persistent | ||
5476 | **/ | ||
5477 | static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data) | ||
5478 | { | ||
5479 | struct iscsi_bus_flash_session *fnode_sess; | ||
5480 | |||
5481 | if (!iscsi_flashnode_bus_match(dev, NULL)) | ||
5482 | return 0; | ||
5483 | |||
5484 | fnode_sess = iscsi_dev_to_flash_session(dev); | ||
5485 | |||
5486 | return (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT); | ||
5487 | } | ||
5488 | |||
5489 | /** | ||
5490 | * qla4xxx_sysfs_ddb_tgt_create - Create sysfs entry for target | ||
5491 | * @ha: pointer to host | ||
5492 | * @fw_ddb_entry: flash ddb data | ||
5493 | * @idx: target index | ||
5494 | * @user: if set then this call is made from userland else from kernel | ||
5495 | * | ||
5496 | * Returns: | ||
5497 | * On sucess: QLA_SUCCESS | ||
5498 | * On failure: QLA_ERROR | ||
5499 | * | ||
5500 | * This create separate sysfs entries for session and connection attributes of | ||
5501 | * the given fw ddb entry. | ||
5502 | * If this is invoked as a result of a userspace call then the entry is marked | ||
5503 | * as nonpersistent using flash_state field. | ||
5504 | **/ | ||
5505 | int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, | ||
5506 | struct dev_db_entry *fw_ddb_entry, | ||
5507 | uint16_t *idx, int user) | ||
5508 | { | ||
5509 | struct iscsi_bus_flash_session *fnode_sess = NULL; | ||
5510 | struct iscsi_bus_flash_conn *fnode_conn = NULL; | ||
5511 | int rc = QLA_ERROR; | ||
5512 | |||
5513 | fnode_sess = iscsi_create_flashnode_sess(ha->host, *idx, | ||
5514 | &qla4xxx_iscsi_transport, 0); | ||
5515 | if (!fnode_sess) { | ||
5516 | ql4_printk(KERN_ERR, ha, | ||
5517 | "%s: Unable to create session sysfs entry for flashnode %d of host%lu\n", | ||
5518 | __func__, *idx, ha->host_no); | ||
5519 | goto exit_tgt_create; | ||
5520 | } | ||
5521 | |||
5522 | fnode_conn = iscsi_create_flashnode_conn(ha->host, fnode_sess, | ||
5523 | &qla4xxx_iscsi_transport, 0); | ||
5524 | if (!fnode_conn) { | ||
5525 | ql4_printk(KERN_ERR, ha, | ||
5526 | "%s: Unable to create conn sysfs entry for flashnode %d of host%lu\n", | ||
5527 | __func__, *idx, ha->host_no); | ||
5528 | goto free_sess; | ||
5529 | } | ||
5530 | |||
5531 | if (user) { | ||
5532 | fnode_sess->flash_state = DEV_DB_NON_PERSISTENT; | ||
5533 | } else { | ||
5534 | fnode_sess->flash_state = DEV_DB_PERSISTENT; | ||
5535 | |||
5536 | if (*idx == ha->pri_ddb_idx || *idx == ha->sec_ddb_idx) | ||
5537 | fnode_sess->is_boot_target = 1; | ||
5538 | else | ||
5539 | fnode_sess->is_boot_target = 0; | ||
5540 | } | ||
5541 | |||
5542 | rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn, | ||
5543 | fw_ddb_entry); | ||
5544 | |||
5545 | ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", | ||
5546 | __func__, fnode_sess->dev.kobj.name); | ||
5547 | |||
5548 | ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n", | ||
5549 | __func__, fnode_conn->dev.kobj.name); | ||
5550 | |||
5551 | return QLA_SUCCESS; | ||
5552 | |||
5553 | free_sess: | ||
5554 | iscsi_destroy_flashnode_sess(fnode_sess); | ||
5555 | |||
5556 | exit_tgt_create: | ||
5557 | return QLA_ERROR; | ||
5558 | } | ||
5559 | |||
5560 | /** | ||
5561 | * qla4xxx_sysfs_ddb_add - Add new ddb entry in flash | ||
5562 | * @shost: pointer to host | ||
5563 | * @buf: type of ddb entry (ipv4/ipv6) | ||
5564 | * @len: length of buf | ||
5565 | * | ||
5566 | * This creates new ddb entry in the flash by finding first free index and | ||
5567 | * storing default ddb there. And then create sysfs entry for the new ddb entry. | ||
5568 | **/ | ||
5569 | static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, | ||
5570 | int len) | ||
5571 | { | ||
5572 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5573 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5574 | dma_addr_t fw_ddb_entry_dma; | ||
5575 | struct device *dev; | ||
5576 | uint16_t idx = 0; | ||
5577 | uint16_t max_ddbs = 0; | ||
5578 | uint32_t options = 0; | ||
5579 | uint32_t rval = QLA_ERROR; | ||
5580 | |||
5581 | if (strncasecmp(DEV_TYPE_IPV4, buf, 4) && | ||
5582 | strncasecmp(DEV_TYPE_IPV6, buf, 4)) { | ||
5583 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Invalid portal type\n", | ||
5584 | __func__)); | ||
5585 | goto exit_ddb_add; | ||
5586 | } | ||
5587 | |||
5588 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
5589 | MAX_DEV_DB_ENTRIES; | ||
5590 | |||
5591 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5592 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5593 | if (!fw_ddb_entry) { | ||
5594 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5595 | "%s: Unable to allocate dma buffer\n", | ||
5596 | __func__)); | ||
5597 | goto exit_ddb_add; | ||
5598 | } | ||
5599 | |||
5600 | dev = iscsi_find_flashnode_sess(ha->host, NULL, | ||
5601 | qla4xxx_sysfs_ddb_is_non_persistent); | ||
5602 | if (dev) { | ||
5603 | ql4_printk(KERN_ERR, ha, | ||
5604 | "%s: A non-persistent entry %s found\n", | ||
5605 | __func__, dev->kobj.name); | ||
5606 | goto exit_ddb_add; | ||
5607 | } | ||
5608 | |||
5609 | for (idx = 0; idx < max_ddbs; idx++) { | ||
5610 | if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, | ||
5611 | fw_ddb_entry_dma, idx)) | ||
5612 | break; | ||
5613 | } | ||
5614 | |||
5615 | if (idx == max_ddbs) | ||
5616 | goto exit_ddb_add; | ||
5617 | |||
5618 | if (!strncasecmp("ipv6", buf, 4)) | ||
5619 | options |= IPV6_DEFAULT_DDB_ENTRY; | ||
5620 | |||
5621 | rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); | ||
5622 | if (rval == QLA_ERROR) | ||
5623 | goto exit_ddb_add; | ||
5624 | |||
5625 | rval = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 1); | ||
5626 | |||
5627 | exit_ddb_add: | ||
5628 | if (fw_ddb_entry) | ||
5629 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5630 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5631 | if (rval == QLA_SUCCESS) | ||
5632 | return idx; | ||
5633 | else | ||
5634 | return -EIO; | ||
5635 | } | ||
5636 | |||
5637 | /** | ||
5638 | * qla4xxx_sysfs_ddb_apply - write the target ddb contents to Flash | ||
5639 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
5640 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
5641 | * | ||
5642 | * This writes the contents of target ddb buffer to Flash with a valid cookie | ||
5643 | * value in order to make the ddb entry persistent. | ||
5644 | **/ | ||
5645 | static int qla4xxx_sysfs_ddb_apply(struct iscsi_bus_flash_session *fnode_sess, | ||
5646 | struct iscsi_bus_flash_conn *fnode_conn) | ||
5647 | { | ||
5648 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
5649 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5650 | uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO; | ||
5651 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5652 | dma_addr_t fw_ddb_entry_dma; | ||
5653 | uint32_t options = 0; | ||
5654 | int rval = 0; | ||
5655 | |||
5656 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5657 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5658 | if (!fw_ddb_entry) { | ||
5659 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5660 | "%s: Unable to allocate dma buffer\n", | ||
5661 | __func__)); | ||
5662 | rval = -ENOMEM; | ||
5663 | goto exit_ddb_apply; | ||
5664 | } | ||
5665 | |||
5666 | if (!strncasecmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
5667 | options |= IPV6_DEFAULT_DDB_ENTRY; | ||
5668 | |||
5669 | rval = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); | ||
5670 | if (rval == QLA_ERROR) | ||
5671 | goto exit_ddb_apply; | ||
5672 | |||
5673 | dev_db_start_offset += (fnode_sess->target_id * | ||
5674 | sizeof(*fw_ddb_entry)); | ||
5675 | |||
5676 | qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); | ||
5677 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; | ||
5678 | |||
5679 | rval = qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, | ||
5680 | sizeof(*fw_ddb_entry), FLASH_OPT_RMW_COMMIT); | ||
5681 | |||
5682 | if (rval == QLA_SUCCESS) { | ||
5683 | fnode_sess->flash_state = DEV_DB_PERSISTENT; | ||
5684 | ql4_printk(KERN_INFO, ha, | ||
5685 | "%s: flash node %u of host %lu written to flash\n", | ||
5686 | __func__, fnode_sess->target_id, ha->host_no); | ||
5687 | } else { | ||
5688 | rval = -EIO; | ||
5689 | ql4_printk(KERN_ERR, ha, | ||
5690 | "%s: Error while writing flash node %u of host %lu to flash\n", | ||
5691 | __func__, fnode_sess->target_id, ha->host_no); | ||
5692 | } | ||
5693 | |||
5694 | exit_ddb_apply: | ||
5695 | if (fw_ddb_entry) | ||
5696 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5697 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5698 | return rval; | ||
5699 | } | ||
5700 | |||
5701 | static ssize_t qla4xxx_sysfs_ddb_conn_open(struct scsi_qla_host *ha, | ||
5702 | struct dev_db_entry *fw_ddb_entry, | ||
5703 | uint16_t idx) | ||
5704 | { | ||
5705 | struct dev_db_entry *ddb_entry = NULL; | ||
5706 | dma_addr_t ddb_entry_dma; | ||
5707 | unsigned long wtime; | ||
5708 | uint32_t mbx_sts = 0; | ||
5709 | uint32_t state = 0, conn_err = 0; | ||
5710 | uint16_t tmo = 0; | ||
5711 | int ret = 0; | ||
5712 | |||
5713 | ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*ddb_entry), | ||
5714 | &ddb_entry_dma, GFP_KERNEL); | ||
5715 | if (!ddb_entry) { | ||
5716 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5717 | "%s: Unable to allocate dma buffer\n", | ||
5718 | __func__)); | ||
5719 | return QLA_ERROR; | ||
5720 | } | ||
5721 | |||
5722 | memcpy(ddb_entry, fw_ddb_entry, sizeof(*ddb_entry)); | ||
5723 | |||
5724 | ret = qla4xxx_set_ddb_entry(ha, idx, ddb_entry_dma, &mbx_sts); | ||
5725 | if (ret != QLA_SUCCESS) { | ||
5726 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5727 | "%s: Unable to set ddb entry for index %d\n", | ||
5728 | __func__, idx)); | ||
5729 | goto exit_ddb_conn_open; | ||
5730 | } | ||
5731 | |||
5732 | qla4xxx_conn_open(ha, idx); | ||
5733 | |||
5734 | /* To ensure that sendtargets is done, wait for at least 12 secs */ | ||
5735 | tmo = ((ha->def_timeout > LOGIN_TOV) && | ||
5736 | (ha->def_timeout < LOGIN_TOV * 10) ? | ||
5737 | ha->def_timeout : LOGIN_TOV); | ||
5738 | |||
5739 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
5740 | "Default time to wait for login to ddb %d\n", tmo)); | ||
5741 | |||
5742 | wtime = jiffies + (HZ * tmo); | ||
5743 | do { | ||
5744 | ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, | ||
5745 | NULL, &state, &conn_err, NULL, | ||
5746 | NULL); | ||
5747 | if (ret == QLA_ERROR) | ||
5748 | continue; | ||
5749 | |||
5750 | if (state == DDB_DS_NO_CONNECTION_ACTIVE || | ||
5751 | state == DDB_DS_SESSION_FAILED) | ||
5752 | break; | ||
5753 | |||
5754 | schedule_timeout_uninterruptible(HZ / 10); | ||
5755 | } while (time_after(wtime, jiffies)); | ||
5756 | |||
5757 | exit_ddb_conn_open: | ||
5758 | if (ddb_entry) | ||
5759 | dma_free_coherent(&ha->pdev->dev, sizeof(*ddb_entry), | ||
5760 | ddb_entry, ddb_entry_dma); | ||
5761 | return ret; | ||
5762 | } | ||
5763 | |||
5764 | static int qla4xxx_ddb_login_st(struct scsi_qla_host *ha, | ||
5765 | struct dev_db_entry *fw_ddb_entry) | ||
5766 | { | ||
5767 | struct qla_ddb_index *ddb_idx, *ddb_idx_tmp; | ||
5768 | struct list_head list_nt; | ||
5769 | uint16_t ddb_index; | ||
5770 | int ret = 0; | ||
5771 | |||
5772 | if (test_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags)) { | ||
5773 | ql4_printk(KERN_WARNING, ha, | ||
5774 | "%s: A discovery already in progress!\n", __func__); | ||
5775 | return QLA_ERROR; | ||
5776 | } | ||
5777 | |||
5778 | INIT_LIST_HEAD(&list_nt); | ||
5779 | |||
5780 | set_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags); | ||
5781 | |||
5782 | ret = qla4xxx_get_ddb_index(ha, &ddb_index); | ||
5783 | if (ret == QLA_ERROR) | ||
5784 | goto exit_login_st_clr_bit; | ||
5785 | |||
5786 | ret = qla4xxx_sysfs_ddb_conn_open(ha, fw_ddb_entry, ddb_index); | ||
5787 | if (ret == QLA_ERROR) | ||
5788 | goto exit_login_st; | ||
5789 | |||
5790 | qla4xxx_build_new_nt_list(ha, &list_nt); | ||
5791 | |||
5792 | list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, &list_nt, list) { | ||
5793 | list_del_init(&ddb_idx->list); | ||
5794 | qla4xxx_clear_ddb_entry(ha, ddb_idx->fw_ddb_idx); | ||
5795 | vfree(ddb_idx); | ||
5796 | } | ||
5797 | |||
5798 | exit_login_st: | ||
5799 | if (qla4xxx_clear_ddb_entry(ha, ddb_index) == QLA_ERROR) { | ||
5800 | ql4_printk(KERN_ERR, ha, | ||
5801 | "Unable to clear DDB index = 0x%x\n", ddb_index); | ||
5802 | } | ||
5803 | |||
5804 | clear_bit(ddb_index, ha->ddb_idx_map); | ||
5805 | |||
5806 | exit_login_st_clr_bit: | ||
5807 | clear_bit(AF_ST_DISCOVERY_IN_PROGRESS, &ha->flags); | ||
5808 | return ret; | ||
5809 | } | ||
5810 | |||
5811 | static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha, | ||
5812 | struct dev_db_entry *fw_ddb_entry, | ||
5813 | uint16_t idx) | ||
5814 | { | ||
5815 | int ret = QLA_ERROR; | ||
5816 | |||
5817 | ret = qla4xxx_is_session_exists(ha, fw_ddb_entry); | ||
5818 | if (ret != QLA_SUCCESS) | ||
5819 | ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, RESET_ADAPTER, | ||
5820 | idx); | ||
5821 | else | ||
5822 | ret = -EPERM; | ||
5823 | |||
5824 | return ret; | ||
5825 | } | ||
5826 | |||
5827 | /** | ||
5828 | * qla4xxx_sysfs_ddb_login - Login to the specified target | ||
5829 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
5830 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
5831 | * | ||
5832 | * This logs in to the specified target | ||
5833 | **/ | ||
5834 | static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, | ||
5835 | struct iscsi_bus_flash_conn *fnode_conn) | ||
5836 | { | ||
5837 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
5838 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5839 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5840 | dma_addr_t fw_ddb_entry_dma; | ||
5841 | uint32_t options = 0; | ||
5842 | int ret = 0; | ||
5843 | |||
5844 | if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) { | ||
5845 | ql4_printk(KERN_ERR, ha, | ||
5846 | "%s: Target info is not persistent\n", __func__); | ||
5847 | ret = -EIO; | ||
5848 | goto exit_ddb_login; | ||
5849 | } | ||
5850 | |||
5851 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5852 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5853 | if (!fw_ddb_entry) { | ||
5854 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
5855 | "%s: Unable to allocate dma buffer\n", | ||
5856 | __func__)); | ||
5857 | ret = -ENOMEM; | ||
5858 | goto exit_ddb_login; | ||
5859 | } | ||
5860 | |||
5861 | if (!strncasecmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
5862 | options |= IPV6_DEFAULT_DDB_ENTRY; | ||
5863 | |||
5864 | ret = qla4xxx_get_default_ddb(ha, options, fw_ddb_entry_dma); | ||
5865 | if (ret == QLA_ERROR) | ||
5866 | goto exit_ddb_login; | ||
5867 | |||
5868 | qla4xxx_copy_to_fwddb_param(fnode_sess, fnode_conn, fw_ddb_entry); | ||
5869 | fw_ddb_entry->cookie = DDB_VALID_COOKIE; | ||
5870 | |||
5871 | if (strlen((char *)fw_ddb_entry->iscsi_name) == 0) | ||
5872 | ret = qla4xxx_ddb_login_st(ha, fw_ddb_entry); | ||
5873 | else | ||
5874 | ret = qla4xxx_ddb_login_nt(ha, fw_ddb_entry, | ||
5875 | fnode_sess->target_id); | ||
5876 | |||
5877 | if (ret > 0) | ||
5878 | ret = -EIO; | ||
5879 | |||
5880 | exit_ddb_login: | ||
5881 | if (fw_ddb_entry) | ||
5882 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5883 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5884 | return ret; | ||
5885 | } | ||
5886 | |||
5887 | /** | ||
5888 | * qla4xxx_sysfs_ddb_logout_sid - Logout session for the specified target | ||
5889 | * @cls_sess: pointer to session to be logged out | ||
5890 | * | ||
5891 | * This performs session log out from the specified target | ||
5892 | **/ | ||
5893 | static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess) | ||
5894 | { | ||
5895 | struct iscsi_session *sess; | ||
5896 | struct ddb_entry *ddb_entry = NULL; | ||
5897 | struct scsi_qla_host *ha; | ||
5898 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5899 | dma_addr_t fw_ddb_entry_dma; | ||
5900 | unsigned long flags; | ||
5901 | unsigned long wtime; | ||
5902 | uint32_t ddb_state; | ||
5903 | int options; | ||
5904 | int ret = 0; | ||
5905 | |||
5906 | sess = cls_sess->dd_data; | ||
5907 | ddb_entry = sess->dd_data; | ||
5908 | ha = ddb_entry->ha; | ||
5909 | |||
5910 | if (ddb_entry->ddb_type != FLASH_DDB) { | ||
5911 | ql4_printk(KERN_ERR, ha, "%s: Not a flash node session\n", | ||
5912 | __func__); | ||
5913 | ret = -ENXIO; | ||
5914 | goto exit_ddb_logout; | ||
5915 | } | ||
5916 | |||
5917 | options = LOGOUT_OPTION_CLOSE_SESSION; | ||
5918 | if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR) { | ||
5919 | ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__); | ||
5920 | ret = -EIO; | ||
5921 | goto exit_ddb_logout; | ||
5922 | } | ||
5923 | |||
5924 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5925 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
5926 | if (!fw_ddb_entry) { | ||
5927 | ql4_printk(KERN_ERR, ha, | ||
5928 | "%s: Unable to allocate dma buffer\n", __func__); | ||
5929 | ret = -ENOMEM; | ||
5930 | goto exit_ddb_logout; | ||
5931 | } | ||
5932 | |||
5933 | wtime = jiffies + (HZ * LOGOUT_TOV); | ||
5934 | do { | ||
5935 | ret = qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, | ||
5936 | fw_ddb_entry, fw_ddb_entry_dma, | ||
5937 | NULL, NULL, &ddb_state, NULL, | ||
5938 | NULL, NULL); | ||
5939 | if (ret == QLA_ERROR) | ||
5940 | goto ddb_logout_clr_sess; | ||
5941 | |||
5942 | if ((ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) || | ||
5943 | (ddb_state == DDB_DS_SESSION_FAILED)) | ||
5944 | goto ddb_logout_clr_sess; | ||
5945 | |||
5946 | schedule_timeout_uninterruptible(HZ); | ||
5947 | } while ((time_after(wtime, jiffies))); | ||
5948 | |||
5949 | ddb_logout_clr_sess: | ||
5950 | qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); | ||
5951 | /* | ||
5952 | * we have decremented the reference count of the driver | ||
5953 | * when we setup the session to have the driver unload | ||
5954 | * to be seamless without actually destroying the | ||
5955 | * session | ||
5956 | **/ | ||
5957 | try_module_get(qla4xxx_iscsi_transport.owner); | ||
5958 | iscsi_destroy_endpoint(ddb_entry->conn->ep); | ||
5959 | |||
5960 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
5961 | qla4xxx_free_ddb(ha, ddb_entry); | ||
5962 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
5963 | |||
5964 | iscsi_session_teardown(ddb_entry->sess); | ||
5965 | |||
5966 | ret = QLA_SUCCESS; | ||
5967 | |||
5968 | exit_ddb_logout: | ||
5969 | if (fw_ddb_entry) | ||
5970 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
5971 | fw_ddb_entry, fw_ddb_entry_dma); | ||
5972 | return ret; | ||
5973 | } | ||
5974 | |||
5975 | /** | ||
5976 | * qla4xxx_sysfs_ddb_logout - Logout from the specified target | ||
5977 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
5978 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
5979 | * | ||
5980 | * This performs log out from the specified target | ||
5981 | **/ | ||
5982 | static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, | ||
5983 | struct iscsi_bus_flash_conn *fnode_conn) | ||
5984 | { | ||
5985 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
5986 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
5987 | struct ql4_tuple_ddb *flash_tddb = NULL; | ||
5988 | struct ql4_tuple_ddb *tmp_tddb = NULL; | ||
5989 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
5990 | struct ddb_entry *ddb_entry = NULL; | ||
5991 | dma_addr_t fw_ddb_dma; | ||
5992 | uint32_t next_idx = 0; | ||
5993 | uint32_t state = 0, conn_err = 0; | ||
5994 | uint16_t conn_id = 0; | ||
5995 | int idx, index; | ||
5996 | int status, ret = 0; | ||
5997 | |||
5998 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
5999 | &fw_ddb_dma); | ||
6000 | if (fw_ddb_entry == NULL) { | ||
6001 | ql4_printk(KERN_ERR, ha, "%s:Out of memory\n", __func__); | ||
6002 | ret = -ENOMEM; | ||
6003 | goto exit_ddb_logout; | ||
6004 | } | ||
6005 | |||
6006 | flash_tddb = vzalloc(sizeof(*flash_tddb)); | ||
6007 | if (!flash_tddb) { | ||
6008 | ql4_printk(KERN_WARNING, ha, | ||
6009 | "%s:Memory Allocation failed.\n", __func__); | ||
6010 | ret = -ENOMEM; | ||
6011 | goto exit_ddb_logout; | ||
6012 | } | ||
6013 | |||
6014 | tmp_tddb = vzalloc(sizeof(*tmp_tddb)); | ||
6015 | if (!tmp_tddb) { | ||
6016 | ql4_printk(KERN_WARNING, ha, | ||
6017 | "%s:Memory Allocation failed.\n", __func__); | ||
6018 | ret = -ENOMEM; | ||
6019 | goto exit_ddb_logout; | ||
6020 | } | ||
6021 | |||
6022 | if (!fnode_sess->targetname) { | ||
6023 | ql4_printk(KERN_ERR, ha, | ||
6024 | "%s:Cannot logout from SendTarget entry\n", | ||
6025 | __func__); | ||
6026 | ret = -EPERM; | ||
6027 | goto exit_ddb_logout; | ||
6028 | } | ||
6029 | |||
6030 | if (fnode_sess->is_boot_target) { | ||
6031 | ql4_printk(KERN_ERR, ha, | ||
6032 | "%s: Logout from boot target entry is not permitted.\n", | ||
6033 | __func__); | ||
6034 | ret = -EPERM; | ||
6035 | goto exit_ddb_logout; | ||
6036 | } | ||
6037 | |||
6038 | strncpy(flash_tddb->iscsi_name, fnode_sess->targetname, | ||
6039 | ISCSI_NAME_SIZE); | ||
6040 | |||
6041 | if (!strncmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
6042 | sprintf(flash_tddb->ip_addr, "%pI6", fnode_conn->ipaddress); | ||
6043 | else | ||
6044 | sprintf(flash_tddb->ip_addr, "%pI4", fnode_conn->ipaddress); | ||
6045 | |||
6046 | flash_tddb->tpgt = fnode_sess->tpgt; | ||
6047 | flash_tddb->port = fnode_conn->port; | ||
6048 | |||
6049 | COPY_ISID(flash_tddb->isid, fnode_sess->isid); | ||
6050 | |||
6051 | for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { | ||
6052 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); | ||
6053 | if (ddb_entry == NULL) | ||
6054 | continue; | ||
6055 | |||
6056 | if (ddb_entry->ddb_type != FLASH_DDB) | ||
6057 | continue; | ||
6058 | |||
6059 | index = ddb_entry->sess->target_id; | ||
6060 | status = qla4xxx_get_fwddb_entry(ha, index, fw_ddb_entry, | ||
6061 | fw_ddb_dma, NULL, &next_idx, | ||
6062 | &state, &conn_err, NULL, | ||
6063 | &conn_id); | ||
6064 | if (status == QLA_ERROR) { | ||
6065 | ret = -ENOMEM; | ||
6066 | break; | ||
6067 | } | ||
6068 | |||
6069 | qla4xxx_convert_param_ddb(fw_ddb_entry, tmp_tddb, NULL); | ||
6070 | |||
6071 | status = qla4xxx_compare_tuple_ddb(ha, flash_tddb, tmp_tddb, | ||
6072 | true); | ||
6073 | if (status == QLA_SUCCESS) { | ||
6074 | ret = qla4xxx_sysfs_ddb_logout_sid(ddb_entry->sess); | ||
6075 | break; | ||
6076 | } | ||
6077 | } | ||
6078 | |||
6079 | if (idx == MAX_DDB_ENTRIES) | ||
6080 | ret = -ESRCH; | ||
6081 | |||
6082 | exit_ddb_logout: | ||
6083 | if (flash_tddb) | ||
6084 | vfree(flash_tddb); | ||
6085 | if (tmp_tddb) | ||
6086 | vfree(tmp_tddb); | ||
6087 | if (fw_ddb_entry) | ||
6088 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | ||
6089 | |||
6090 | return ret; | ||
6091 | } | ||
6092 | |||
6093 | static int | ||
6094 | qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | ||
6095 | int param, char *buf) | ||
6096 | { | ||
6097 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
6098 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
6099 | struct iscsi_bus_flash_conn *fnode_conn; | ||
6100 | struct ql4_chap_table chap_tbl; | ||
6101 | struct device *dev; | ||
6102 | int parent_type, parent_index = 0xffff; | ||
6103 | int rc = 0; | ||
6104 | |||
6105 | dev = iscsi_find_flashnode_conn(fnode_sess, NULL, | ||
6106 | iscsi_is_flashnode_conn_dev); | ||
6107 | if (!dev) | ||
6108 | return -EIO; | ||
6109 | |||
6110 | fnode_conn = iscsi_dev_to_flash_conn(dev); | ||
6111 | |||
6112 | switch (param) { | ||
6113 | case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: | ||
6114 | rc = sprintf(buf, "%u\n", fnode_conn->is_fw_assigned_ipv6); | ||
6115 | break; | ||
6116 | case ISCSI_FLASHNODE_PORTAL_TYPE: | ||
6117 | rc = sprintf(buf, "%s\n", fnode_sess->portal_type); | ||
6118 | break; | ||
6119 | case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: | ||
6120 | rc = sprintf(buf, "%u\n", fnode_sess->auto_snd_tgt_disable); | ||
6121 | break; | ||
6122 | case ISCSI_FLASHNODE_DISCOVERY_SESS: | ||
6123 | rc = sprintf(buf, "%u\n", fnode_sess->discovery_sess); | ||
6124 | break; | ||
6125 | case ISCSI_FLASHNODE_ENTRY_EN: | ||
6126 | rc = sprintf(buf, "%u\n", fnode_sess->entry_state); | ||
6127 | break; | ||
6128 | case ISCSI_FLASHNODE_HDR_DGST_EN: | ||
6129 | rc = sprintf(buf, "%u\n", fnode_conn->hdrdgst_en); | ||
6130 | break; | ||
6131 | case ISCSI_FLASHNODE_DATA_DGST_EN: | ||
6132 | rc = sprintf(buf, "%u\n", fnode_conn->datadgst_en); | ||
6133 | break; | ||
6134 | case ISCSI_FLASHNODE_IMM_DATA_EN: | ||
6135 | rc = sprintf(buf, "%u\n", fnode_sess->imm_data_en); | ||
6136 | break; | ||
6137 | case ISCSI_FLASHNODE_INITIAL_R2T_EN: | ||
6138 | rc = sprintf(buf, "%u\n", fnode_sess->initial_r2t_en); | ||
6139 | break; | ||
6140 | case ISCSI_FLASHNODE_DATASEQ_INORDER: | ||
6141 | rc = sprintf(buf, "%u\n", fnode_sess->dataseq_inorder_en); | ||
6142 | break; | ||
6143 | case ISCSI_FLASHNODE_PDU_INORDER: | ||
6144 | rc = sprintf(buf, "%u\n", fnode_sess->pdu_inorder_en); | ||
6145 | break; | ||
6146 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | ||
6147 | rc = sprintf(buf, "%u\n", fnode_sess->chap_auth_en); | ||
6148 | break; | ||
6149 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | ||
6150 | rc = sprintf(buf, "%u\n", fnode_conn->snack_req_en); | ||
6151 | break; | ||
6152 | case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: | ||
6153 | rc = sprintf(buf, "%u\n", fnode_sess->discovery_logout_en); | ||
6154 | break; | ||
6155 | case ISCSI_FLASHNODE_BIDI_CHAP_EN: | ||
6156 | rc = sprintf(buf, "%u\n", fnode_sess->bidi_chap_en); | ||
6157 | break; | ||
6158 | case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: | ||
6159 | rc = sprintf(buf, "%u\n", fnode_sess->discovery_auth_optional); | ||
6160 | break; | ||
6161 | case ISCSI_FLASHNODE_ERL: | ||
6162 | rc = sprintf(buf, "%u\n", fnode_sess->erl); | ||
6163 | break; | ||
6164 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: | ||
6165 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_stat); | ||
6166 | break; | ||
6167 | case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: | ||
6168 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_nagle_disable); | ||
6169 | break; | ||
6170 | case ISCSI_FLASHNODE_TCP_WSF_DISABLE: | ||
6171 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_wsf_disable); | ||
6172 | break; | ||
6173 | case ISCSI_FLASHNODE_TCP_TIMER_SCALE: | ||
6174 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_timer_scale); | ||
6175 | break; | ||
6176 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: | ||
6177 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_timestamp_en); | ||
6178 | break; | ||
6179 | case ISCSI_FLASHNODE_IP_FRAG_DISABLE: | ||
6180 | rc = sprintf(buf, "%u\n", fnode_conn->fragment_disable); | ||
6181 | break; | ||
6182 | case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: | ||
6183 | rc = sprintf(buf, "%u\n", fnode_conn->max_recv_dlength); | ||
6184 | break; | ||
6185 | case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: | ||
6186 | rc = sprintf(buf, "%u\n", fnode_conn->max_xmit_dlength); | ||
6187 | break; | ||
6188 | case ISCSI_FLASHNODE_FIRST_BURST: | ||
6189 | rc = sprintf(buf, "%u\n", fnode_sess->first_burst); | ||
6190 | break; | ||
6191 | case ISCSI_FLASHNODE_DEF_TIME2WAIT: | ||
6192 | rc = sprintf(buf, "%u\n", fnode_sess->time2wait); | ||
6193 | break; | ||
6194 | case ISCSI_FLASHNODE_DEF_TIME2RETAIN: | ||
6195 | rc = sprintf(buf, "%u\n", fnode_sess->time2retain); | ||
6196 | break; | ||
6197 | case ISCSI_FLASHNODE_MAX_R2T: | ||
6198 | rc = sprintf(buf, "%u\n", fnode_sess->max_r2t); | ||
6199 | break; | ||
6200 | case ISCSI_FLASHNODE_KEEPALIVE_TMO: | ||
6201 | rc = sprintf(buf, "%u\n", fnode_conn->keepalive_timeout); | ||
6202 | break; | ||
6203 | case ISCSI_FLASHNODE_ISID: | ||
6204 | rc = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", | ||
6205 | fnode_sess->isid[0], fnode_sess->isid[1], | ||
6206 | fnode_sess->isid[2], fnode_sess->isid[3], | ||
6207 | fnode_sess->isid[4], fnode_sess->isid[5]); | ||
6208 | break; | ||
6209 | case ISCSI_FLASHNODE_TSID: | ||
6210 | rc = sprintf(buf, "%u\n", fnode_sess->tsid); | ||
6211 | break; | ||
6212 | case ISCSI_FLASHNODE_PORT: | ||
6213 | rc = sprintf(buf, "%d\n", fnode_conn->port); | ||
6214 | break; | ||
6215 | case ISCSI_FLASHNODE_MAX_BURST: | ||
6216 | rc = sprintf(buf, "%u\n", fnode_sess->max_burst); | ||
6217 | break; | ||
6218 | case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: | ||
6219 | rc = sprintf(buf, "%u\n", | ||
6220 | fnode_sess->default_taskmgmt_timeout); | ||
6221 | break; | ||
6222 | case ISCSI_FLASHNODE_IPADDR: | ||
6223 | if (!strncmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
6224 | rc = sprintf(buf, "%pI6\n", fnode_conn->ipaddress); | ||
6225 | else | ||
6226 | rc = sprintf(buf, "%pI4\n", fnode_conn->ipaddress); | ||
6227 | break; | ||
6228 | case ISCSI_FLASHNODE_ALIAS: | ||
6229 | if (fnode_sess->targetalias) | ||
6230 | rc = sprintf(buf, "%s\n", fnode_sess->targetalias); | ||
6231 | else | ||
6232 | rc = sprintf(buf, "\n"); | ||
6233 | break; | ||
6234 | case ISCSI_FLASHNODE_REDIRECT_IPADDR: | ||
6235 | if (!strncmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
6236 | rc = sprintf(buf, "%pI6\n", | ||
6237 | fnode_conn->redirect_ipaddr); | ||
6238 | else | ||
6239 | rc = sprintf(buf, "%pI4\n", | ||
6240 | fnode_conn->redirect_ipaddr); | ||
6241 | break; | ||
6242 | case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: | ||
6243 | rc = sprintf(buf, "%u\n", fnode_conn->max_segment_size); | ||
6244 | break; | ||
6245 | case ISCSI_FLASHNODE_LOCAL_PORT: | ||
6246 | rc = sprintf(buf, "%u\n", fnode_conn->local_port); | ||
6247 | break; | ||
6248 | case ISCSI_FLASHNODE_IPV4_TOS: | ||
6249 | rc = sprintf(buf, "%u\n", fnode_conn->ipv4_tos); | ||
6250 | break; | ||
6251 | case ISCSI_FLASHNODE_IPV6_TC: | ||
6252 | if (!strncmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
6253 | rc = sprintf(buf, "%u\n", | ||
6254 | fnode_conn->ipv6_traffic_class); | ||
6255 | else | ||
6256 | rc = sprintf(buf, "\n"); | ||
6257 | break; | ||
6258 | case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: | ||
6259 | rc = sprintf(buf, "%u\n", fnode_conn->ipv6_flow_label); | ||
6260 | break; | ||
6261 | case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: | ||
6262 | if (!strncmp(fnode_sess->portal_type, DEV_TYPE_IPV6, 4)) | ||
6263 | rc = sprintf(buf, "%pI6\n", | ||
6264 | fnode_conn->link_local_ipv6_addr); | ||
6265 | else | ||
6266 | rc = sprintf(buf, "\n"); | ||
6267 | break; | ||
6268 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: | ||
6269 | if ((fnode_sess->discovery_parent_idx) >= 0 && | ||
6270 | (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES)) | ||
6271 | parent_index = fnode_sess->discovery_parent_idx; | ||
6272 | |||
6273 | rc = sprintf(buf, "%u\n", parent_index); | ||
6274 | break; | ||
6275 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: | ||
6276 | if (fnode_sess->discovery_parent_type == DDB_ISNS) | ||
6277 | parent_type = ISCSI_DISC_PARENT_ISNS; | ||
6278 | else if (fnode_sess->discovery_parent_type == DDB_NO_LINK) | ||
6279 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; | ||
6280 | else if (fnode_sess->discovery_parent_type >= 0 && | ||
6281 | fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES) | ||
6282 | parent_type = ISCSI_DISC_PARENT_SENDTGT; | ||
6283 | else | ||
6284 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; | ||
6285 | |||
6286 | rc = sprintf(buf, "%s\n", | ||
6287 | iscsi_get_discovery_parent_name(parent_type)); | ||
6288 | break; | ||
6289 | case ISCSI_FLASHNODE_NAME: | ||
6290 | if (fnode_sess->targetname) | ||
6291 | rc = sprintf(buf, "%s\n", fnode_sess->targetname); | ||
6292 | else | ||
6293 | rc = sprintf(buf, "\n"); | ||
6294 | break; | ||
6295 | case ISCSI_FLASHNODE_TPGT: | ||
6296 | rc = sprintf(buf, "%u\n", fnode_sess->tpgt); | ||
6297 | break; | ||
6298 | case ISCSI_FLASHNODE_TCP_XMIT_WSF: | ||
6299 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_xmit_wsf); | ||
6300 | break; | ||
6301 | case ISCSI_FLASHNODE_TCP_RECV_WSF: | ||
6302 | rc = sprintf(buf, "%u\n", fnode_conn->tcp_recv_wsf); | ||
6303 | break; | ||
6304 | case ISCSI_FLASHNODE_CHAP_OUT_IDX: | ||
6305 | rc = sprintf(buf, "%u\n", fnode_sess->chap_out_idx); | ||
6306 | break; | ||
6307 | case ISCSI_FLASHNODE_USERNAME: | ||
6308 | if (fnode_sess->chap_auth_en) { | ||
6309 | qla4xxx_get_uni_chap_at_index(ha, | ||
6310 | chap_tbl.name, | ||
6311 | chap_tbl.secret, | ||
6312 | fnode_sess->chap_out_idx); | ||
6313 | rc = sprintf(buf, "%s\n", chap_tbl.name); | ||
6314 | } else { | ||
6315 | rc = sprintf(buf, "\n"); | ||
6316 | } | ||
6317 | break; | ||
6318 | case ISCSI_FLASHNODE_PASSWORD: | ||
6319 | if (fnode_sess->chap_auth_en) { | ||
6320 | qla4xxx_get_uni_chap_at_index(ha, | ||
6321 | chap_tbl.name, | ||
6322 | chap_tbl.secret, | ||
6323 | fnode_sess->chap_out_idx); | ||
6324 | rc = sprintf(buf, "%s\n", chap_tbl.secret); | ||
6325 | } else { | ||
6326 | rc = sprintf(buf, "\n"); | ||
6327 | } | ||
6328 | break; | ||
6329 | case ISCSI_FLASHNODE_STATSN: | ||
6330 | rc = sprintf(buf, "%u\n", fnode_conn->statsn); | ||
6331 | break; | ||
6332 | case ISCSI_FLASHNODE_EXP_STATSN: | ||
6333 | rc = sprintf(buf, "%u\n", fnode_conn->exp_statsn); | ||
6334 | break; | ||
6335 | case ISCSI_FLASHNODE_IS_BOOT_TGT: | ||
6336 | rc = sprintf(buf, "%u\n", fnode_sess->is_boot_target); | ||
6337 | break; | ||
6338 | default: | ||
6339 | rc = -ENOSYS; | ||
6340 | break; | ||
6341 | } | ||
6342 | return rc; | ||
6343 | } | ||
6344 | |||
6345 | /** | ||
6346 | * qla4xxx_sysfs_ddb_set_param - Set parameter for firmware DDB entry | ||
6347 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
6348 | * @fnode_conn: pointer to connection attrs of flash ddb entry | ||
6349 | * @data: Parameters and their values to update | ||
6350 | * @len: len of data | ||
6351 | * | ||
6352 | * This sets the parameter of flash ddb entry and writes them to flash | ||
6353 | **/ | ||
6354 | static int | ||
6355 | qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | ||
6356 | struct iscsi_bus_flash_conn *fnode_conn, | ||
6357 | void *data, int len) | ||
6358 | { | ||
6359 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
6360 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
6361 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6362 | struct iscsi_flashnode_param_info *fnode_param; | ||
6363 | struct nlattr *attr; | ||
6364 | int rc = QLA_ERROR; | ||
6365 | uint32_t rem = len; | ||
6366 | |||
6367 | fw_ddb_entry = kzalloc(sizeof(*fw_ddb_entry), GFP_KERNEL); | ||
6368 | if (!fw_ddb_entry) { | ||
6369 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6370 | "%s: Unable to allocate ddb buffer\n", | ||
6371 | __func__)); | ||
6372 | return -ENOMEM; | ||
6373 | } | ||
6374 | |||
6375 | nla_for_each_attr(attr, data, len, rem) { | ||
6376 | fnode_param = nla_data(attr); | ||
6377 | |||
6378 | switch (fnode_param->param) { | ||
6379 | case ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6: | ||
6380 | fnode_conn->is_fw_assigned_ipv6 = fnode_param->value[0]; | ||
6381 | break; | ||
6382 | case ISCSI_FLASHNODE_PORTAL_TYPE: | ||
6383 | memcpy(fnode_sess->portal_type, fnode_param->value, | ||
6384 | strlen(fnode_sess->portal_type)); | ||
6385 | break; | ||
6386 | case ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE: | ||
6387 | fnode_sess->auto_snd_tgt_disable = | ||
6388 | fnode_param->value[0]; | ||
6389 | break; | ||
6390 | case ISCSI_FLASHNODE_DISCOVERY_SESS: | ||
6391 | fnode_sess->discovery_sess = fnode_param->value[0]; | ||
6392 | break; | ||
6393 | case ISCSI_FLASHNODE_ENTRY_EN: | ||
6394 | fnode_sess->entry_state = fnode_param->value[0]; | ||
6395 | break; | ||
6396 | case ISCSI_FLASHNODE_HDR_DGST_EN: | ||
6397 | fnode_conn->hdrdgst_en = fnode_param->value[0]; | ||
6398 | break; | ||
6399 | case ISCSI_FLASHNODE_DATA_DGST_EN: | ||
6400 | fnode_conn->datadgst_en = fnode_param->value[0]; | ||
6401 | break; | ||
6402 | case ISCSI_FLASHNODE_IMM_DATA_EN: | ||
6403 | fnode_sess->imm_data_en = fnode_param->value[0]; | ||
6404 | break; | ||
6405 | case ISCSI_FLASHNODE_INITIAL_R2T_EN: | ||
6406 | fnode_sess->initial_r2t_en = fnode_param->value[0]; | ||
6407 | break; | ||
6408 | case ISCSI_FLASHNODE_DATASEQ_INORDER: | ||
6409 | fnode_sess->dataseq_inorder_en = fnode_param->value[0]; | ||
6410 | break; | ||
6411 | case ISCSI_FLASHNODE_PDU_INORDER: | ||
6412 | fnode_sess->pdu_inorder_en = fnode_param->value[0]; | ||
6413 | break; | ||
6414 | case ISCSI_FLASHNODE_CHAP_AUTH_EN: | ||
6415 | fnode_sess->chap_auth_en = fnode_param->value[0]; | ||
6416 | break; | ||
6417 | case ISCSI_FLASHNODE_SNACK_REQ_EN: | ||
6418 | fnode_conn->snack_req_en = fnode_param->value[0]; | ||
6419 | break; | ||
6420 | case ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN: | ||
6421 | fnode_sess->discovery_logout_en = fnode_param->value[0]; | ||
6422 | break; | ||
6423 | case ISCSI_FLASHNODE_BIDI_CHAP_EN: | ||
6424 | fnode_sess->bidi_chap_en = fnode_param->value[0]; | ||
6425 | break; | ||
6426 | case ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL: | ||
6427 | fnode_sess->discovery_auth_optional = | ||
6428 | fnode_param->value[0]; | ||
6429 | break; | ||
6430 | case ISCSI_FLASHNODE_ERL: | ||
6431 | fnode_sess->erl = fnode_param->value[0]; | ||
6432 | break; | ||
6433 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT: | ||
6434 | fnode_conn->tcp_timestamp_stat = fnode_param->value[0]; | ||
6435 | break; | ||
6436 | case ISCSI_FLASHNODE_TCP_NAGLE_DISABLE: | ||
6437 | fnode_conn->tcp_nagle_disable = fnode_param->value[0]; | ||
6438 | break; | ||
6439 | case ISCSI_FLASHNODE_TCP_WSF_DISABLE: | ||
6440 | fnode_conn->tcp_wsf_disable = fnode_param->value[0]; | ||
6441 | break; | ||
6442 | case ISCSI_FLASHNODE_TCP_TIMER_SCALE: | ||
6443 | fnode_conn->tcp_timer_scale = fnode_param->value[0]; | ||
6444 | break; | ||
6445 | case ISCSI_FLASHNODE_TCP_TIMESTAMP_EN: | ||
6446 | fnode_conn->tcp_timestamp_en = fnode_param->value[0]; | ||
6447 | break; | ||
6448 | case ISCSI_FLASHNODE_IP_FRAG_DISABLE: | ||
6449 | fnode_conn->fragment_disable = fnode_param->value[0]; | ||
6450 | break; | ||
6451 | case ISCSI_FLASHNODE_MAX_RECV_DLENGTH: | ||
6452 | fnode_conn->max_recv_dlength = | ||
6453 | *(unsigned *)fnode_param->value; | ||
6454 | break; | ||
6455 | case ISCSI_FLASHNODE_MAX_XMIT_DLENGTH: | ||
6456 | fnode_conn->max_xmit_dlength = | ||
6457 | *(unsigned *)fnode_param->value; | ||
6458 | break; | ||
6459 | case ISCSI_FLASHNODE_FIRST_BURST: | ||
6460 | fnode_sess->first_burst = | ||
6461 | *(unsigned *)fnode_param->value; | ||
6462 | break; | ||
6463 | case ISCSI_FLASHNODE_DEF_TIME2WAIT: | ||
6464 | fnode_sess->time2wait = *(uint16_t *)fnode_param->value; | ||
6465 | break; | ||
6466 | case ISCSI_FLASHNODE_DEF_TIME2RETAIN: | ||
6467 | fnode_sess->time2retain = | ||
6468 | *(uint16_t *)fnode_param->value; | ||
6469 | break; | ||
6470 | case ISCSI_FLASHNODE_MAX_R2T: | ||
6471 | fnode_sess->max_r2t = | ||
6472 | *(uint16_t *)fnode_param->value; | ||
6473 | break; | ||
6474 | case ISCSI_FLASHNODE_KEEPALIVE_TMO: | ||
6475 | fnode_conn->keepalive_timeout = | ||
6476 | *(uint16_t *)fnode_param->value; | ||
6477 | break; | ||
6478 | case ISCSI_FLASHNODE_ISID: | ||
6479 | memcpy(fnode_sess->isid, fnode_param->value, | ||
6480 | sizeof(fnode_sess->isid)); | ||
6481 | break; | ||
6482 | case ISCSI_FLASHNODE_TSID: | ||
6483 | fnode_sess->tsid = *(uint16_t *)fnode_param->value; | ||
6484 | break; | ||
6485 | case ISCSI_FLASHNODE_PORT: | ||
6486 | fnode_conn->port = *(uint16_t *)fnode_param->value; | ||
6487 | break; | ||
6488 | case ISCSI_FLASHNODE_MAX_BURST: | ||
6489 | fnode_sess->max_burst = *(unsigned *)fnode_param->value; | ||
6490 | break; | ||
6491 | case ISCSI_FLASHNODE_DEF_TASKMGMT_TMO: | ||
6492 | fnode_sess->default_taskmgmt_timeout = | ||
6493 | *(uint16_t *)fnode_param->value; | ||
6494 | break; | ||
6495 | case ISCSI_FLASHNODE_IPADDR: | ||
6496 | memcpy(fnode_conn->ipaddress, fnode_param->value, | ||
6497 | IPv6_ADDR_LEN); | ||
6498 | break; | ||
6499 | case ISCSI_FLASHNODE_ALIAS: | ||
6500 | rc = iscsi_switch_str_param(&fnode_sess->targetalias, | ||
6501 | (char *)fnode_param->value); | ||
6502 | break; | ||
6503 | case ISCSI_FLASHNODE_REDIRECT_IPADDR: | ||
6504 | memcpy(fnode_conn->redirect_ipaddr, fnode_param->value, | ||
6505 | IPv6_ADDR_LEN); | ||
6506 | break; | ||
6507 | case ISCSI_FLASHNODE_MAX_SEGMENT_SIZE: | ||
6508 | fnode_conn->max_segment_size = | ||
6509 | *(unsigned *)fnode_param->value; | ||
6510 | break; | ||
6511 | case ISCSI_FLASHNODE_LOCAL_PORT: | ||
6512 | fnode_conn->local_port = | ||
6513 | *(uint16_t *)fnode_param->value; | ||
6514 | break; | ||
6515 | case ISCSI_FLASHNODE_IPV4_TOS: | ||
6516 | fnode_conn->ipv4_tos = fnode_param->value[0]; | ||
6517 | break; | ||
6518 | case ISCSI_FLASHNODE_IPV6_TC: | ||
6519 | fnode_conn->ipv6_traffic_class = fnode_param->value[0]; | ||
6520 | break; | ||
6521 | case ISCSI_FLASHNODE_IPV6_FLOW_LABEL: | ||
6522 | fnode_conn->ipv6_flow_label = fnode_param->value[0]; | ||
6523 | break; | ||
6524 | case ISCSI_FLASHNODE_NAME: | ||
6525 | rc = iscsi_switch_str_param(&fnode_sess->targetname, | ||
6526 | (char *)fnode_param->value); | ||
6527 | break; | ||
6528 | case ISCSI_FLASHNODE_TPGT: | ||
6529 | fnode_sess->tpgt = *(uint16_t *)fnode_param->value; | ||
6530 | break; | ||
6531 | case ISCSI_FLASHNODE_LINK_LOCAL_IPV6: | ||
6532 | memcpy(fnode_conn->link_local_ipv6_addr, | ||
6533 | fnode_param->value, IPv6_ADDR_LEN); | ||
6534 | break; | ||
6535 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE: | ||
6536 | fnode_sess->discovery_parent_type = | ||
6537 | *(uint16_t *)fnode_param->value; | ||
6538 | break; | ||
6539 | case ISCSI_FLASHNODE_TCP_XMIT_WSF: | ||
6540 | fnode_conn->tcp_xmit_wsf = | ||
6541 | *(uint8_t *)fnode_param->value; | ||
6542 | break; | ||
6543 | case ISCSI_FLASHNODE_TCP_RECV_WSF: | ||
6544 | fnode_conn->tcp_recv_wsf = | ||
6545 | *(uint8_t *)fnode_param->value; | ||
6546 | break; | ||
6547 | case ISCSI_FLASHNODE_STATSN: | ||
6548 | fnode_conn->statsn = *(uint32_t *)fnode_param->value; | ||
6549 | break; | ||
6550 | case ISCSI_FLASHNODE_EXP_STATSN: | ||
6551 | fnode_conn->exp_statsn = | ||
6552 | *(uint32_t *)fnode_param->value; | ||
6553 | break; | ||
6554 | default: | ||
6555 | ql4_printk(KERN_ERR, ha, | ||
6556 | "%s: No such sysfs attribute\n", __func__); | ||
6557 | rc = -ENOSYS; | ||
6558 | goto exit_set_param; | ||
6559 | } | ||
6560 | } | ||
6561 | |||
6562 | rc = qla4xxx_sysfs_ddb_apply(fnode_sess, fnode_conn); | ||
6563 | |||
6564 | exit_set_param: | ||
6565 | return rc; | ||
6566 | } | ||
6567 | |||
6568 | /** | ||
6569 | * qla4xxx_sysfs_ddb_delete - Delete firmware DDB entry | ||
6570 | * @fnode_sess: pointer to session attrs of flash ddb entry | ||
6571 | * | ||
6572 | * This invalidates the flash ddb entry at the given index | ||
6573 | **/ | ||
6574 | static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess) | ||
6575 | { | ||
6576 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | ||
6577 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
6578 | uint32_t dev_db_start_offset; | ||
6579 | uint32_t dev_db_end_offset; | ||
6580 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6581 | dma_addr_t fw_ddb_entry_dma; | ||
6582 | uint16_t *ddb_cookie = NULL; | ||
6583 | int target_id; | ||
6584 | int rc = 0; | ||
6585 | |||
6586 | if (!fnode_sess) { | ||
6587 | rc = -EINVAL; | ||
6588 | goto exit_ddb_del; | ||
6589 | } | ||
6590 | |||
6591 | if (fnode_sess->is_boot_target) { | ||
6592 | rc = -EPERM; | ||
6593 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6594 | "%s: Deletion of boot target entry is not permitted.\n", | ||
6595 | __func__)); | ||
6596 | goto exit_ddb_del; | ||
6597 | } | ||
6598 | |||
6599 | if (fnode_sess->flash_state == DEV_DB_NON_PERSISTENT) | ||
6600 | goto sysfs_ddb_del; | ||
6601 | |||
6602 | ddb_cookie = dma_alloc_coherent(&ha->pdev->dev, sizeof(*ddb_cookie), | ||
6603 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
6604 | if (!ddb_cookie) { | ||
6605 | rc = -ENOMEM; | ||
6606 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6607 | "%s: Unable to allocate dma buffer\n", | ||
6608 | __func__)); | ||
6609 | goto exit_ddb_del; | ||
6610 | } | ||
6611 | |||
6612 | if (is_qla40XX(ha)) { | ||
6613 | dev_db_start_offset = FLASH_OFFSET_DB_INFO; | ||
6614 | } else { | ||
6615 | dev_db_start_offset = FLASH_RAW_ACCESS_ADDR + | ||
6616 | (ha->hw.flt_region_ddb << 2); | ||
6617 | /* flt_ddb_size is DDB table size for both ports | ||
6618 | * so divide it by 2 to calculate the offset for second port | ||
6619 | */ | ||
6620 | if (ha->port_num == 1) | ||
6621 | dev_db_start_offset += (ha->hw.flt_ddb_size / 2); | ||
6622 | } | ||
6623 | |||
6624 | dev_db_end_offset = dev_db_start_offset + (ha->hw.flt_ddb_size / 2); | ||
6625 | dev_db_start_offset += (fnode_sess->target_id * sizeof(*fw_ddb_entry)); | ||
6626 | dev_db_start_offset += (void *)&(fw_ddb_entry->cookie) - | ||
6627 | (void *)fw_ddb_entry; | ||
6628 | |||
6629 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s: start offset=%u, end offset=%u\n", | ||
6630 | __func__, dev_db_start_offset, dev_db_end_offset)); | ||
6631 | |||
6632 | if (dev_db_start_offset > dev_db_end_offset) { | ||
6633 | rc = -EIO; | ||
6634 | DEBUG2(ql4_printk(KERN_ERR, ha, "%s:Invalid DDB index %u\n", | ||
6635 | __func__, fnode_sess->target_id)); | ||
6636 | goto exit_ddb_del; | ||
6637 | } | ||
6638 | |||
6639 | /* invalidate the cookie */ | ||
6640 | *ddb_cookie = 0xFFEE; | ||
6641 | qla4xxx_set_flash(ha, fw_ddb_entry_dma, dev_db_start_offset, | ||
6642 | sizeof(*ddb_cookie), FLASH_OPT_RMW_COMMIT); | ||
6643 | |||
6644 | sysfs_ddb_del: | ||
6645 | target_id = fnode_sess->target_id; | ||
6646 | iscsi_destroy_flashnode_sess(fnode_sess); | ||
6647 | ql4_printk(KERN_INFO, ha, | ||
6648 | "%s: session and conn entries for flashnode %u of host %lu deleted\n", | ||
6649 | __func__, target_id, ha->host_no); | ||
6650 | exit_ddb_del: | ||
6651 | if (ddb_cookie) | ||
6652 | dma_free_coherent(&ha->pdev->dev, sizeof(*ddb_cookie), | ||
6653 | ddb_cookie, fw_ddb_entry_dma); | ||
6654 | return rc; | ||
6655 | } | ||
6656 | |||
6657 | /** | ||
6658 | * qla4xxx_sysfs_ddb_export - Create sysfs entries for firmware DDBs | ||
6659 | * @ha: pointer to adapter structure | ||
6660 | * | ||
6661 | * Export the firmware DDB for all send targets and normal targets to sysfs. | ||
6662 | **/ | ||
6663 | static int qla4xxx_sysfs_ddb_export(struct scsi_qla_host *ha) | ||
6664 | { | ||
6665 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
6666 | dma_addr_t fw_ddb_entry_dma; | ||
6667 | uint16_t max_ddbs; | ||
6668 | uint16_t idx = 0; | ||
6669 | int ret = QLA_SUCCESS; | ||
6670 | |||
6671 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, | ||
6672 | sizeof(*fw_ddb_entry), | ||
6673 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
6674 | if (!fw_ddb_entry) { | ||
6675 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
6676 | "%s: Unable to allocate dma buffer\n", | ||
6677 | __func__)); | ||
6678 | return -ENOMEM; | ||
6679 | } | ||
6680 | |||
6681 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
6682 | MAX_DEV_DB_ENTRIES; | ||
6683 | |||
6684 | for (idx = 0; idx < max_ddbs; idx++) { | ||
6685 | if (qla4xxx_flashdb_by_index(ha, fw_ddb_entry, fw_ddb_entry_dma, | ||
6686 | idx)) | ||
6687 | continue; | ||
6688 | |||
6689 | ret = qla4xxx_sysfs_ddb_tgt_create(ha, fw_ddb_entry, &idx, 0); | ||
6690 | if (ret) { | ||
6691 | ret = -EIO; | ||
6692 | break; | ||
6693 | } | ||
6694 | } | ||
6695 | |||
6696 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry, | ||
6697 | fw_ddb_entry_dma); | ||
6698 | |||
6699 | return ret; | ||
6700 | } | ||
6701 | |||
6702 | static void qla4xxx_sysfs_ddb_remove(struct scsi_qla_host *ha) | ||
6703 | { | ||
6704 | iscsi_destroy_all_flashnode(ha->host); | ||
6705 | } | ||
6706 | |||
5065 | /** | 6707 | /** |
5066 | * qla4xxx_build_ddb_list - Build ddb list and setup sessions | 6708 | * qla4xxx_build_ddb_list - Build ddb list and setup sessions |
5067 | * @ha: pointer to adapter structure | 6709 | * @ha: pointer to adapter structure |
@@ -5452,6 +7094,10 @@ skip_retry_init: | |||
5452 | ql4_printk(KERN_ERR, ha, | 7094 | ql4_printk(KERN_ERR, ha, |
5453 | "%s: No iSCSI boot target configured\n", __func__); | 7095 | "%s: No iSCSI boot target configured\n", __func__); |
5454 | 7096 | ||
7097 | if (qla4xxx_sysfs_ddb_export(ha)) | ||
7098 | ql4_printk(KERN_ERR, ha, | ||
7099 | "%s: Error exporting ddb to sysfs\n", __func__); | ||
7100 | |||
5455 | /* Perform the build ddb list and login to each */ | 7101 | /* Perform the build ddb list and login to each */ |
5456 | qla4xxx_build_ddb_list(ha, INIT_ADAPTER); | 7102 | qla4xxx_build_ddb_list(ha, INIT_ADAPTER); |
5457 | iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); | 7103 | iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); |
@@ -5577,6 +7223,7 @@ static void qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
5577 | qla4xxx_destroy_fw_ddb_session(ha); | 7223 | qla4xxx_destroy_fw_ddb_session(ha); |
5578 | qla4_8xxx_free_sysfs_attr(ha); | 7224 | qla4_8xxx_free_sysfs_attr(ha); |
5579 | 7225 | ||
7226 | qla4xxx_sysfs_ddb_remove(ha); | ||
5580 | scsi_remove_host(ha->host); | 7227 | scsi_remove_host(ha->host); |
5581 | 7228 | ||
5582 | qla4xxx_free_adapter(ha); | 7229 | qla4xxx_free_adapter(ha); |