aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorManish Rangankar <manish.rangankar@qlogic.com>2011-07-25 14:48:55 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 10:36:27 -0400
commit2a991c2159782b8d318ac9f88a36c22dda3e7185 (patch)
tree963cc3bec9517038458ad7e71b9a5d45ede4d360 /drivers
parent0e7e85019c2709131b10c5f34b602cc6b94fe782 (diff)
[SCSI] qla4xxx: Boot from SAN support for open-iscsi
Hook qla4xxx in fw boot sysfs interface so iscsi tools can use the info to create boot sessions. Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com> Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h42
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h21
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h7
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c77
-rw-r--r--drivers/scsi/qla4xxx/ql4_nvram.c21
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c480
7 files changed, 650 insertions, 2 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 6e2be9d963ac..30efb6c6594c 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -276,6 +276,8 @@ struct ql82xx_hw_data {
276 uint32_t flt_region_boot; 276 uint32_t flt_region_boot;
277 uint32_t flt_region_bootload; 277 uint32_t flt_region_bootload;
278 uint32_t flt_region_fw; 278 uint32_t flt_region_fw;
279
280 uint32_t flt_iscsi_param;
279 uint32_t reserved; 281 uint32_t reserved;
280}; 282};
281 283
@@ -343,6 +345,41 @@ struct ipaddress_config {
343 struct in6_addr ipv6_default_router_addr; 345 struct in6_addr ipv6_default_router_addr;
344}; 346};
345 347
348#define QL4_CHAP_MAX_NAME_LEN 256
349#define QL4_CHAP_MAX_SECRET_LEN 100
350
351struct ql4_chap_format {
352 u8 intr_chap_name[QL4_CHAP_MAX_NAME_LEN];
353 u8 intr_secret[QL4_CHAP_MAX_SECRET_LEN];
354 u8 target_chap_name[QL4_CHAP_MAX_NAME_LEN];
355 u8 target_secret[QL4_CHAP_MAX_SECRET_LEN];
356 u16 intr_chap_name_length;
357 u16 intr_secret_length;
358 u16 target_chap_name_length;
359 u16 target_secret_length;
360};
361
362struct ip_address_format {
363 u8 ip_type;
364 u8 ip_address[16];
365};
366
367struct ql4_conn_info {
368 u16 dest_port;
369 struct ip_address_format dest_ipaddr;
370 struct ql4_chap_format chap;
371};
372
373struct ql4_boot_session_info {
374 u8 target_name[224];
375 struct ql4_conn_info conn_list[1];
376};
377
378struct ql4_boot_tgt_info {
379 struct ql4_boot_session_info boot_pri_sess;
380 struct ql4_boot_session_info boot_sec_sess;
381};
382
346/* 383/*
347 * Linux Host Adapter structure 384 * Linux Host Adapter structure
348 */ 385 */
@@ -444,7 +481,7 @@ struct scsi_qla_host {
444 /* --- From FlashSysInfo --- */ 481 /* --- From FlashSysInfo --- */
445 uint8_t my_mac[MAC_ADDR_LEN]; 482 uint8_t my_mac[MAC_ADDR_LEN];
446 uint8_t serial_number[16]; 483 uint8_t serial_number[16];
447 484 uint16_t port_num;
448 /* --- From GetFwState --- */ 485 /* --- From GetFwState --- */
449 uint32_t firmware_state; 486 uint32_t firmware_state;
450 uint32_t addl_fw_state; 487 uint32_t addl_fw_state;
@@ -569,6 +606,9 @@ struct scsi_qla_host {
569#define CHAP_DMA_BLOCK_SIZE 512 606#define CHAP_DMA_BLOCK_SIZE 512
570 struct workqueue_struct *task_wq; 607 struct workqueue_struct *task_wq;
571 unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG]; 608 unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
609#define SYSFS_FLAG_FW_SEL_BOOT 2
610 struct iscsi_boot_kset *boot_kset;
611 struct ql4_boot_tgt_info boot_tgt;
572}; 612};
573 613
574struct ql4_task_data { 614struct ql4_task_data {
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 99098d51543b..9dc439b0d75f 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -146,6 +146,13 @@ struct isp_reg {
146#define QL4022_NVRAM_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (10+16)) 146#define QL4022_NVRAM_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (10+16))
147#define QL4022_FLASH_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (13+16)) 147#define QL4022_FLASH_SEM_MASK (QL4022_RESOURCE_MASK_BASE_CODE << (13+16))
148 148
149/* nvram address for 4032 */
150#define NVRAM_PORT0_BOOT_MODE 0x03b1
151#define NVRAM_PORT0_BOOT_PRI_TGT 0x03b2
152#define NVRAM_PORT0_BOOT_SEC_TGT 0x03bb
153#define NVRAM_PORT1_BOOT_MODE 0x07b1
154#define NVRAM_PORT1_BOOT_PRI_TGT 0x07b2
155#define NVRAM_PORT1_BOOT_SEC_TGT 0x07bb
149 156
150 157
151/* Page # defines for 4022 */ 158/* Page # defines for 4022 */
@@ -298,6 +305,7 @@ struct qla_flt_header {
298#define FLT_REG_FW_82 0x74 305#define FLT_REG_FW_82 0x74
299#define FLT_REG_GOLD_FW_82 0x75 306#define FLT_REG_GOLD_FW_82 0x75
300#define FLT_REG_BOOT_CODE_82 0x78 307#define FLT_REG_BOOT_CODE_82 0x78
308#define FLT_REG_ISCSI_PARAM 0x65
301 309
302struct qla_flt_region { 310struct qla_flt_region {
303 uint32_t code; 311 uint32_t code;
@@ -733,7 +741,10 @@ struct dev_db_entry {
733 uint8_t tcp_rcv_wsf; /* 1C7 */ 741 uint8_t tcp_rcv_wsf; /* 1C7 */
734 uint32_t stat_sn; /* 1C8-1CB */ 742 uint32_t stat_sn; /* 1C8-1CB */
735 uint32_t exp_stat_sn; /* 1CC-1CF */ 743 uint32_t exp_stat_sn; /* 1CC-1CF */
736 uint8_t res6[0x30]; /* 1D0-1FF */ 744 uint8_t res6[0x2b]; /* 1D0-1FB */
745#define DDB_VALID_COOKIE 0x9034
746 uint16_t cookie; /* 1FC-1FD */
747 uint16_t len; /* 1FE-1FF */
737}; 748};
738 749
739/*************************************************************************/ 750/*************************************************************************/
@@ -745,6 +756,14 @@ struct dev_db_entry {
745#define FLASH_EOF_OFFSET (FLASH_DEFAULTBLOCKSIZE-8) /* 4 bytes 756#define FLASH_EOF_OFFSET (FLASH_DEFAULTBLOCKSIZE-8) /* 4 bytes
746 * for EOF 757 * for EOF
747 * signature */ 758 * signature */
759#define FLASH_RAW_ACCESS_ADDR 0x8e000000
760
761#define BOOT_PARAM_OFFSET_PORT0 0x3b0
762#define BOOT_PARAM_OFFSET_PORT1 0x7b0
763
764#define FLASH_OFFSET_DB_INFO 0x05000000
765#define FLASH_OFFSET_DB_END (FLASH_OFFSET_DB_INFO + 0x7fff)
766
748 767
749struct sys_info_phys_addr { 768struct sys_info_phys_addr {
750 uint8_t address[6]; /* 00-05 */ 769 uint8_t address[6]; /* 00-05 */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 85b8253b3fc2..98d4b17e8b10 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -60,6 +60,7 @@ int qla4xxx_get_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd,
60 uint32_t *mbox_sts, dma_addr_t acb_dma); 60 uint32_t *mbox_sts, dma_addr_t acb_dma);
61void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session); 61void qla4xxx_mark_device_missing(struct iscsi_cls_session *cls_session);
62u16 rd_nvram_word(struct scsi_qla_host *ha, int offset); 62u16 rd_nvram_word(struct scsi_qla_host *ha, int offset);
63u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset);
63void qla4xxx_get_crash_record(struct scsi_qla_host *ha); 64void qla4xxx_get_crash_record(struct scsi_qla_host *ha);
64int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha); 65int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host *ha);
65int qla4xxx_about_firmware(struct scsi_qla_host *ha); 66int qla4xxx_about_firmware(struct scsi_qla_host *ha);
@@ -154,6 +155,12 @@ int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index,
154 uint16_t stats_size, dma_addr_t stats_dma); 155 uint16_t stats_size, dma_addr_t stats_dma);
155void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, 156void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
156 struct ddb_entry *ddb_entry); 157 struct ddb_entry *ddb_entry);
158int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
159 struct dev_db_entry *fw_ddb_entry,
160 dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index);
161int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username,
162 char *password, uint16_t idx);
163
157/* BSG Functions */ 164/* BSG Functions */
158int qla4xxx_bsg_request(struct bsg_job *bsg_job); 165int qla4xxx_bsg_request(struct bsg_job *bsg_job);
159int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); 166int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job);
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index 21884019dab8..72ec7e092296 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -1262,6 +1262,83 @@ int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
1262 return status; 1262 return status;
1263} 1263}
1264 1264
1265int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
1266 struct dev_db_entry *fw_ddb_entry,
1267 dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
1268{
1269 uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
1270 uint32_t dev_db_end_offset;
1271 int status = QLA_ERROR;
1272
1273 memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
1274
1275 dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
1276 dev_db_end_offset = FLASH_OFFSET_DB_END;
1277
1278 if (dev_db_start_offset > dev_db_end_offset) {
1279 DEBUG2(ql4_printk(KERN_ERR, ha,
1280 "%s:Invalid DDB index %d", __func__,
1281 ddb_index));
1282 goto exit_bootdb_failed;
1283 }
1284
1285 if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
1286 sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
1287 ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
1288 "failed\n", ha->host_no, __func__);
1289 goto exit_bootdb_failed;
1290 }
1291
1292 if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
1293 status = QLA_SUCCESS;
1294
1295exit_bootdb_failed:
1296 return status;
1297}
1298
1299int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
1300 uint16_t idx)
1301{
1302 int ret = 0;
1303 int rval = QLA_ERROR;
1304 uint32_t offset = 0;
1305 struct ql4_chap_table *chap_table;
1306 dma_addr_t chap_dma;
1307
1308 chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
1309 if (chap_table == NULL) {
1310 ret = -ENOMEM;
1311 goto exit_get_chap;
1312 }
1313
1314 memset(chap_table, 0, sizeof(struct ql4_chap_table));
1315
1316 offset = 0x06000000 | (idx * sizeof(struct ql4_chap_table));
1317
1318 rval = qla4xxx_get_flash(ha, chap_dma, offset,
1319 sizeof(struct ql4_chap_table));
1320 if (rval != QLA_SUCCESS) {
1321 ret = -EINVAL;
1322 goto exit_get_chap;
1323 }
1324
1325 DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
1326 __le16_to_cpu(chap_table->cookie)));
1327
1328 if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
1329 ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
1330 goto exit_get_chap;
1331 }
1332
1333 strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
1334 strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
1335 chap_table->cookie = __constant_cpu_to_le16(CHAP_VALID_COOKIE);
1336
1337exit_get_chap:
1338 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
1339 return ret;
1340}
1341
1265static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username, 1342static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
1266 char *password, uint16_t idx, int bidi) 1343 char *password, uint16_t idx, int bidi)
1267{ 1344{
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c
index b4b859b2d47e..7851f314ba96 100644
--- a/drivers/scsi/qla4xxx/ql4_nvram.c
+++ b/drivers/scsi/qla4xxx/ql4_nvram.c
@@ -156,6 +156,27 @@ u16 rd_nvram_word(struct scsi_qla_host * ha, int offset)
156 return val; 156 return val;
157} 157}
158 158
159u8 rd_nvram_byte(struct scsi_qla_host *ha, int offset)
160{
161 u16 val = 0;
162 u8 rval = 0;
163 int index = 0;
164
165 if (offset & 0x1)
166 index = (offset - 1) / 2;
167 else
168 index = offset / 2;
169
170 val = le16_to_cpu(rd_nvram_word(ha, index));
171
172 if (offset & 0x1)
173 rval = (u8)((val & 0xff00) >> 8);
174 else
175 rval = (u8)((val & 0x00ff));
176
177 return rval;
178}
179
159int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha) 180int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha)
160{ 181{
161 int status = QLA_ERROR; 182 int status = QLA_ERROR;
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index fdfe27b38698..52a1063e4fd5 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -2020,6 +2020,9 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
2020 case FLT_REG_BOOTLOAD_82: 2020 case FLT_REG_BOOTLOAD_82:
2021 hw->flt_region_bootload = start; 2021 hw->flt_region_bootload = start;
2022 break; 2022 break;
2023 case FLT_REG_ISCSI_PARAM:
2024 hw->flt_iscsi_param = start;
2025 break;
2023 } 2026 }
2024 } 2027 }
2025 goto done; 2028 goto done;
@@ -2258,6 +2261,7 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
2258 } 2261 }
2259 2262
2260 /* Save M.A.C. address & serial_number */ 2263 /* Save M.A.C. address & serial_number */
2264 ha->port_num = sys_info->port_num;
2261 memcpy(ha->my_mac, &sys_info->mac_addr[0], 2265 memcpy(ha->my_mac, &sys_info->mac_addr[0],
2262 min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr))); 2266 min(sizeof(ha->my_mac), sizeof(sys_info->mac_addr)));
2263 memcpy(ha->serial_number, &sys_info->serial_number, 2267 memcpy(ha->serial_number, &sys_info->serial_number,
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index bfb3d37612fc..15355f95f560 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -6,6 +6,8 @@
6 */ 6 */
7#include <linux/moduleparam.h> 7#include <linux/moduleparam.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/blkdev.h>
10#include <linux/iscsi_boot_sysfs.h>
9 11
10#include <scsi/scsi_tcq.h> 12#include <scsi/scsi_tcq.h>
11#include <scsi/scsicam.h> 13#include <scsi/scsicam.h>
@@ -2551,6 +2553,477 @@ uint16_t qla4_8xxx_rd_shdw_rsp_q_in(struct scsi_qla_host *ha)
2551 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in)); 2553 return (uint16_t)le32_to_cpu(readl(&ha->qla4_8xxx_reg->rsp_q_in));
2552} 2554}
2553 2555
2556static ssize_t qla4xxx_show_boot_eth_info(void *data, int type, char *buf)
2557{
2558 struct scsi_qla_host *ha = data;
2559 char *str = buf;
2560 int rc;
2561
2562 switch (type) {
2563 case ISCSI_BOOT_ETH_FLAGS:
2564 rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
2565 break;
2566 case ISCSI_BOOT_ETH_INDEX:
2567 rc = sprintf(str, "0\n");
2568 break;
2569 case ISCSI_BOOT_ETH_MAC:
2570 rc = sysfs_format_mac(str, ha->my_mac,
2571 MAC_ADDR_LEN);
2572 break;
2573 default:
2574 rc = -ENOSYS;
2575 break;
2576 }
2577 return rc;
2578}
2579
2580static mode_t qla4xxx_eth_get_attr_visibility(void *data, int type)
2581{
2582 int rc;
2583
2584 switch (type) {
2585 case ISCSI_BOOT_ETH_FLAGS:
2586 case ISCSI_BOOT_ETH_MAC:
2587 case ISCSI_BOOT_ETH_INDEX:
2588 rc = S_IRUGO;
2589 break;
2590 default:
2591 rc = 0;
2592 break;
2593 }
2594 return rc;
2595}
2596
2597static ssize_t qla4xxx_show_boot_ini_info(void *data, int type, char *buf)
2598{
2599 struct scsi_qla_host *ha = data;
2600 char *str = buf;
2601 int rc;
2602
2603 switch (type) {
2604 case ISCSI_BOOT_INI_INITIATOR_NAME:
2605 rc = sprintf(str, "%s\n", ha->name_string);
2606 break;
2607 default:
2608 rc = -ENOSYS;
2609 break;
2610 }
2611 return rc;
2612}
2613
2614static mode_t qla4xxx_ini_get_attr_visibility(void *data, int type)
2615{
2616 int rc;
2617
2618 switch (type) {
2619 case ISCSI_BOOT_INI_INITIATOR_NAME:
2620 rc = S_IRUGO;
2621 break;
2622 default:
2623 rc = 0;
2624 break;
2625 }
2626 return rc;
2627}
2628
2629static ssize_t
2630qla4xxx_show_boot_tgt_info(struct ql4_boot_session_info *boot_sess, int type,
2631 char *buf)
2632{
2633 struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
2634 char *str = buf;
2635 int rc;
2636
2637 switch (type) {
2638 case ISCSI_BOOT_TGT_NAME:
2639 rc = sprintf(buf, "%s\n", (char *)&boot_sess->target_name);
2640 break;
2641 case ISCSI_BOOT_TGT_IP_ADDR:
2642 if (boot_sess->conn_list[0].dest_ipaddr.ip_type == 0x1)
2643 rc = sprintf(buf, "%pI4\n",
2644 &boot_conn->dest_ipaddr.ip_address);
2645 else
2646 rc = sprintf(str, "%pI6\n",
2647 &boot_conn->dest_ipaddr.ip_address);
2648 break;
2649 case ISCSI_BOOT_TGT_PORT:
2650 rc = sprintf(str, "%d\n", boot_conn->dest_port);
2651 break;
2652 case ISCSI_BOOT_TGT_CHAP_NAME:
2653 rc = sprintf(str, "%.*s\n",
2654 boot_conn->chap.target_chap_name_length,
2655 (char *)&boot_conn->chap.target_chap_name);
2656 break;
2657 case ISCSI_BOOT_TGT_CHAP_SECRET:
2658 rc = sprintf(str, "%.*s\n",
2659 boot_conn->chap.target_secret_length,
2660 (char *)&boot_conn->chap.target_secret);
2661 break;
2662 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
2663 rc = sprintf(str, "%.*s\n",
2664 boot_conn->chap.intr_chap_name_length,
2665 (char *)&boot_conn->chap.intr_chap_name);
2666 break;
2667 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
2668 rc = sprintf(str, "%.*s\n",
2669 boot_conn->chap.intr_secret_length,
2670 (char *)&boot_conn->chap.intr_secret);
2671 break;
2672 case ISCSI_BOOT_TGT_FLAGS:
2673 rc = sprintf(str, "%d\n", SYSFS_FLAG_FW_SEL_BOOT);
2674 break;
2675 case ISCSI_BOOT_TGT_NIC_ASSOC:
2676 rc = sprintf(str, "0\n");
2677 break;
2678 default:
2679 rc = -ENOSYS;
2680 break;
2681 }
2682 return rc;
2683}
2684
2685static ssize_t qla4xxx_show_boot_tgt_pri_info(void *data, int type, char *buf)
2686{
2687 struct scsi_qla_host *ha = data;
2688 struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_pri_sess);
2689
2690 return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
2691}
2692
2693static ssize_t qla4xxx_show_boot_tgt_sec_info(void *data, int type, char *buf)
2694{
2695 struct scsi_qla_host *ha = data;
2696 struct ql4_boot_session_info *boot_sess = &(ha->boot_tgt.boot_sec_sess);
2697
2698 return qla4xxx_show_boot_tgt_info(boot_sess, type, buf);
2699}
2700
2701static mode_t qla4xxx_tgt_get_attr_visibility(void *data, int type)
2702{
2703 int rc;
2704
2705 switch (type) {
2706 case ISCSI_BOOT_TGT_NAME:
2707 case ISCSI_BOOT_TGT_IP_ADDR:
2708 case ISCSI_BOOT_TGT_PORT:
2709 case ISCSI_BOOT_TGT_CHAP_NAME:
2710 case ISCSI_BOOT_TGT_CHAP_SECRET:
2711 case ISCSI_BOOT_TGT_REV_CHAP_NAME:
2712 case ISCSI_BOOT_TGT_REV_CHAP_SECRET:
2713 case ISCSI_BOOT_TGT_NIC_ASSOC:
2714 case ISCSI_BOOT_TGT_FLAGS:
2715 rc = S_IRUGO;
2716 break;
2717 default:
2718 rc = 0;
2719 break;
2720 }
2721 return rc;
2722}
2723
2724static void qla4xxx_boot_release(void *data)
2725{
2726 struct scsi_qla_host *ha = data;
2727
2728 scsi_host_put(ha->host);
2729}
2730
2731static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
2732{
2733 dma_addr_t buf_dma;
2734 uint32_t addr, pri_addr, sec_addr;
2735 uint32_t offset;
2736 uint16_t func_num;
2737 uint8_t val;
2738 uint8_t *buf = NULL;
2739 size_t size = 13 * sizeof(uint8_t);
2740 int ret = QLA_SUCCESS;
2741
2742 func_num = PCI_FUNC(ha->pdev->devfn);
2743
2744 DEBUG2(ql4_printk(KERN_INFO, ha,
2745 "%s: Get FW boot info for 0x%x func %d\n", __func__,
2746 (is_qla4032(ha) ? PCI_DEVICE_ID_QLOGIC_ISP4032 :
2747 PCI_DEVICE_ID_QLOGIC_ISP8022), func_num));
2748
2749 if (is_qla4032(ha)) {
2750 if (func_num == 1) {
2751 addr = NVRAM_PORT0_BOOT_MODE;
2752 pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;
2753 sec_addr = NVRAM_PORT0_BOOT_SEC_TGT;
2754 } else if (func_num == 3) {
2755 addr = NVRAM_PORT1_BOOT_MODE;
2756 pri_addr = NVRAM_PORT1_BOOT_PRI_TGT;
2757 sec_addr = NVRAM_PORT1_BOOT_SEC_TGT;
2758 } else {
2759 ret = QLA_ERROR;
2760 goto exit_boot_info;
2761 }
2762
2763 /* Check Boot Mode */
2764 val = rd_nvram_byte(ha, addr);
2765 if (!(val & 0x07)) {
2766 DEBUG2(ql4_printk(KERN_ERR, ha,
2767 "%s: Failed Boot options : 0x%x\n",
2768 __func__, val));
2769 ret = QLA_ERROR;
2770 goto exit_boot_info;
2771 }
2772
2773 /* get primary valid target index */
2774 val = rd_nvram_byte(ha, pri_addr);
2775 if (val & BIT_7)
2776 ddb_index[0] = (val & 0x7f);
2777 else
2778 ddb_index[0] = 0;
2779
2780 /* get secondary valid target index */
2781 val = rd_nvram_byte(ha, sec_addr);
2782 if (val & BIT_7)
2783 ddb_index[1] = (val & 0x7f);
2784 else
2785 ddb_index[1] = 1;
2786
2787 } else if (is_qla8022(ha)) {
2788 buf = dma_alloc_coherent(&ha->pdev->dev, size,
2789 &buf_dma, GFP_KERNEL);
2790 if (!buf) {
2791 DEBUG2(ql4_printk(KERN_ERR, ha,
2792 "%s: Unable to allocate dma buffer\n",
2793 __func__));
2794 ret = QLA_ERROR;
2795 goto exit_boot_info;
2796 }
2797
2798 if (ha->port_num == 0)
2799 offset = BOOT_PARAM_OFFSET_PORT0;
2800 else if (ha->port_num == 1)
2801 offset = BOOT_PARAM_OFFSET_PORT1;
2802 else {
2803 ret = QLA_ERROR;
2804 goto exit_boot_info_free;
2805 }
2806 addr = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_iscsi_param * 4) +
2807 offset;
2808 if (qla4xxx_get_flash(ha, buf_dma, addr,
2809 13 * sizeof(uint8_t)) != QLA_SUCCESS) {
2810 DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash"
2811 "failed\n", ha->host_no, __func__));
2812 ret = QLA_ERROR;
2813 goto exit_boot_info_free;
2814 }
2815 /* Check Boot Mode */
2816 if (!(buf[1] & 0x07)) {
2817 DEBUG2(ql4_printk(KERN_INFO, ha,
2818 "Failed: Boot options : 0x%x\n",
2819 buf[1]));
2820 ret = QLA_ERROR;
2821 goto exit_boot_info_free;
2822 }
2823
2824 /* get primary valid target index */
2825 if (buf[2] & BIT_7)
2826 ddb_index[0] = buf[2] & 0x7f;
2827 else
2828 ddb_index[0] = 0;
2829
2830 /* get secondary valid target index */
2831 if (buf[11] & BIT_7)
2832 ddb_index[1] = buf[11] & 0x7f;
2833 else
2834 ddb_index[1] = 1;
2835
2836 } else {
2837 ret = QLA_ERROR;
2838 goto exit_boot_info;
2839 }
2840
2841 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary target ID %d, Secondary"
2842 " target ID %d\n", __func__, ddb_index[0],
2843 ddb_index[1]));
2844
2845exit_boot_info_free:
2846 dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);
2847exit_boot_info:
2848 return ret;
2849}
2850
2851static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
2852 struct ql4_boot_session_info *boot_sess,
2853 uint16_t ddb_index)
2854{
2855 struct ql4_conn_info *boot_conn = &boot_sess->conn_list[0];
2856 struct dev_db_entry *fw_ddb_entry;
2857 dma_addr_t fw_ddb_entry_dma;
2858 uint16_t idx;
2859 uint16_t options;
2860 int ret = QLA_SUCCESS;
2861
2862 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
2863 &fw_ddb_entry_dma, GFP_KERNEL);
2864 if (!fw_ddb_entry) {
2865 DEBUG2(ql4_printk(KERN_ERR, ha,
2866 "%s: Unable to allocate dma buffer.\n",
2867 __func__));
2868 ret = QLA_ERROR;
2869 return ret;
2870 }
2871
2872 if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry,
2873 fw_ddb_entry_dma, ddb_index)) {
2874 DEBUG2(ql4_printk(KERN_ERR, ha,
2875 "%s: Flash DDB read Failed\n", __func__));
2876 ret = QLA_ERROR;
2877 goto exit_boot_target;
2878 }
2879
2880 /* Update target name and IP from DDB */
2881 memcpy(boot_sess->target_name, fw_ddb_entry->iscsi_name,
2882 min(sizeof(boot_sess->target_name),
2883 sizeof(fw_ddb_entry->iscsi_name)));
2884
2885 options = le16_to_cpu(fw_ddb_entry->options);
2886 if (options & DDB_OPT_IPV6_DEVICE) {
2887 memcpy(&boot_conn->dest_ipaddr.ip_address,
2888 &fw_ddb_entry->ip_addr[0], IPv6_ADDR_LEN);
2889 } else {
2890 boot_conn->dest_ipaddr.ip_type = 0x1;
2891 memcpy(&boot_conn->dest_ipaddr.ip_address,
2892 &fw_ddb_entry->ip_addr[0], IP_ADDR_LEN);
2893 }
2894
2895 boot_conn->dest_port = le16_to_cpu(fw_ddb_entry->port);
2896
2897 /* update chap information */
2898 idx = __le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
2899
2900 if (BIT_7 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
2901
2902 DEBUG2(ql4_printk(KERN_INFO, ha, "Setting chap\n"));
2903
2904 ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
2905 target_chap_name,
2906 (char *)&boot_conn->chap.target_secret,
2907 idx);
2908 if (ret) {
2909 ql4_printk(KERN_ERR, ha, "Failed to set chap\n");
2910 ret = QLA_ERROR;
2911 goto exit_boot_target;
2912 }
2913
2914 boot_conn->chap.target_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
2915 boot_conn->chap.target_secret_length = QL4_CHAP_MAX_SECRET_LEN;
2916 }
2917
2918 if (BIT_4 & le16_to_cpu(fw_ddb_entry->iscsi_options)) {
2919
2920 DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));
2921
2922 ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
2923 intr_chap_name,
2924 (char *)&boot_conn->chap.intr_secret,
2925 (idx + 1));
2926 if (ret) {
2927 ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");
2928 ret = QLA_ERROR;
2929 goto exit_boot_target;
2930 }
2931
2932 boot_conn->chap.intr_chap_name_length = QL4_CHAP_MAX_NAME_LEN;
2933 boot_conn->chap.intr_secret_length = QL4_CHAP_MAX_SECRET_LEN;
2934 }
2935
2936exit_boot_target:
2937 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
2938 fw_ddb_entry, fw_ddb_entry_dma);
2939 return ret;
2940}
2941
2942static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
2943{
2944 uint16_t ddb_index[2];
2945 int ret = QLA_SUCCESS;
2946
2947 memset(ddb_index, 0, sizeof(ddb_index));
2948 ret = get_fw_boot_info(ha, ddb_index);
2949 if (ret != QLA_SUCCESS) {
2950 DEBUG2(ql4_printk(KERN_ERR, ha,
2951 "%s: Failed to set boot info.\n", __func__));
2952 return ret;
2953 }
2954
2955 ret = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
2956 ddb_index[0]);
2957 if (ret != QLA_SUCCESS) {
2958 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
2959 "primary target\n", __func__));
2960 }
2961
2962 ret = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
2963 ddb_index[1]);
2964 if (ret != QLA_SUCCESS) {
2965 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
2966 "secondary target\n", __func__));
2967 }
2968 return ret;
2969}
2970
2971static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha)
2972{
2973 struct iscsi_boot_kobj *boot_kobj;
2974
2975 if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS)
2976 return 0;
2977
2978 ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no);
2979 if (!ha->boot_kset)
2980 goto kset_free;
2981
2982 if (!scsi_host_get(ha->host))
2983 goto kset_free;
2984 boot_kobj = iscsi_boot_create_target(ha->boot_kset, 0, ha,
2985 qla4xxx_show_boot_tgt_pri_info,
2986 qla4xxx_tgt_get_attr_visibility,
2987 qla4xxx_boot_release);
2988 if (!boot_kobj)
2989 goto put_host;
2990
2991 if (!scsi_host_get(ha->host))
2992 goto kset_free;
2993 boot_kobj = iscsi_boot_create_target(ha->boot_kset, 1, ha,
2994 qla4xxx_show_boot_tgt_sec_info,
2995 qla4xxx_tgt_get_attr_visibility,
2996 qla4xxx_boot_release);
2997 if (!boot_kobj)
2998 goto put_host;
2999
3000 if (!scsi_host_get(ha->host))
3001 goto kset_free;
3002 boot_kobj = iscsi_boot_create_initiator(ha->boot_kset, 0, ha,
3003 qla4xxx_show_boot_ini_info,
3004 qla4xxx_ini_get_attr_visibility,
3005 qla4xxx_boot_release);
3006 if (!boot_kobj)
3007 goto put_host;
3008
3009 if (!scsi_host_get(ha->host))
3010 goto kset_free;
3011 boot_kobj = iscsi_boot_create_ethernet(ha->boot_kset, 0, ha,
3012 qla4xxx_show_boot_eth_info,
3013 qla4xxx_eth_get_attr_visibility,
3014 qla4xxx_boot_release);
3015 if (!boot_kobj)
3016 goto put_host;
3017
3018 return 0;
3019
3020put_host:
3021 scsi_host_put(ha->host);
3022kset_free:
3023 iscsi_boot_destroy_kset(ha->boot_kset);
3024 return -ENOMEM;
3025}
3026
2554/** 3027/**
2555 * qla4xxx_probe_adapter - callback function to probe HBA 3028 * qla4xxx_probe_adapter - callback function to probe HBA
2556 * @pdev: pointer to pci_dev structure 3029 * @pdev: pointer to pci_dev structure
@@ -2758,6 +3231,10 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
2758 ha->host_no, ha->firmware_version[0], ha->firmware_version[1], 3231 ha->host_no, ha->firmware_version[0], ha->firmware_version[1],
2759 ha->patch_number, ha->build_number); 3232 ha->patch_number, ha->build_number);
2760 3233
3234 if (qla4xxx_setup_boot_info(ha))
3235 ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n",
3236 __func__);
3237
2761 qla4xxx_create_ifaces(ha); 3238 qla4xxx_create_ifaces(ha);
2762 return 0; 3239 return 0;
2763 3240
@@ -2831,6 +3308,9 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
2831 /* destroy iface from sysfs */ 3308 /* destroy iface from sysfs */
2832 qla4xxx_destroy_ifaces(ha); 3309 qla4xxx_destroy_ifaces(ha);
2833 3310
3311 if (ha->boot_kset)
3312 iscsi_boot_destroy_kset(ha->boot_kset);
3313
2834 scsi_remove_host(ha->host); 3314 scsi_remove_host(ha->host);
2835 3315
2836 qla4xxx_free_adapter(ha); 3316 qla4xxx_free_adapter(ha);