aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 15:55:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-22 15:55:29 -0400
commit424a6f6ef990b7e9f56f6627bfc6c46b493faeb4 (patch)
tree0028356ed8003495fbbe1f716f359e3c8ebc35b6 /drivers/scsi/qla4xxx
parent1ab142d499294b844ecc81e8004db4ce029b0b61 (diff)
parentcd8df932d894f3128c884e3ae1b2b484540513db (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
SCSI updates from James Bottomley: "The update includes the usual assortment of driver updates (lpfc, qla2xxx, qla4xxx, bfa, bnx2fc, bnx2i, isci, fcoe, hpsa) plus a huge amount of infrastructure work in the SAS library and transport class as well as an iSCSI update. There's also a new SCSI based virtio driver." * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (177 commits) [SCSI] qla4xxx: Update driver version to 5.02.00-k15 [SCSI] qla4xxx: trivial cleanup [SCSI] qla4xxx: Fix sparse warning [SCSI] qla4xxx: Add support for multiple session per host. [SCSI] qla4xxx: Export CHAP index as sysfs attribute [SCSI] scsi_transport: Export CHAP index as sysfs attribute [SCSI] qla4xxx: Add support to display CHAP list and delete CHAP entry [SCSI] iscsi_transport: Add support to display CHAP list and delete CHAP entry [SCSI] pm8001: fix endian issue with code optimization. [SCSI] pm8001: Fix possible racing condition. [SCSI] pm8001: Fix bogus interrupt state flag issue. [SCSI] ipr: update PCI ID definitions for new adapters [SCSI] qla2xxx: handle default case in qla2x00_request_firmware() [SCSI] isci: improvements in driver unloading routine [SCSI] isci: improve phy event warnings [SCSI] isci: debug, provide state-enum-to-string conversions [SCSI] scsi_transport_sas: 'enable' phys on reset [SCSI] libsas: don't recover end devices attached to disabled phys [SCSI] libsas: fixup target_port_protocols for expanders that don't report sata [SCSI] libsas: set attached device type and target protocols for local phys ...
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h45
-rw-r--r--drivers/scsi/qla4xxx/ql4_fw.h24
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h9
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c5
-rw-r--r--drivers/scsi/qla4xxx/ql4_iocb.c92
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c78
-rw-r--r--drivers/scsi/qla4xxx/ql4_mbx.c23
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c17
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c563
-rw-r--r--drivers/scsi/qla4xxx/ql4_version.h2
11 files changed, 808 insertions, 51 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index bfe68545203f..7f2492e88be7 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -150,8 +150,6 @@
150#define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */ 150#define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */
151 /* recovery timeout */ 151 /* recovery timeout */
152 152
153#define MSB(x) ((uint8_t)((uint16_t)(x) >> 8))
154#define LSW(x) ((uint16_t)(x))
155#define LSDW(x) ((u32)((u64)(x))) 153#define LSDW(x) ((u32)((u64)(x)))
156#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) 154#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
157 155
@@ -223,6 +221,15 @@ struct srb {
223 uint16_t reserved2; 221 uint16_t reserved2;
224}; 222};
225 223
224/* Mailbox request block structure */
225struct mrb {
226 struct scsi_qla_host *ha;
227 struct mbox_cmd_iocb *mbox;
228 uint32_t mbox_cmd;
229 uint16_t iocb_cnt; /* Number of used iocbs */
230 uint32_t pid;
231};
232
226/* 233/*
227 * Asynchronous Event Queue structure 234 * Asynchronous Event Queue structure
228 */ 235 */
@@ -265,7 +272,7 @@ struct ddb_entry {
265 * retried */ 272 * retried */
266 uint32_t default_time2wait; /* Default Min time between 273 uint32_t default_time2wait; /* Default Min time between
267 * relogins (+aens) */ 274 * relogins (+aens) */
268 275 uint16_t chap_tbl_idx;
269}; 276};
270 277
271struct qla_ddb_index { 278struct qla_ddb_index {
@@ -284,6 +291,7 @@ struct ql4_tuple_ddb {
284 uint16_t options; 291 uint16_t options;
285#define DDB_OPT_IPV6 0x0e0e 292#define DDB_OPT_IPV6 0x0e0e
286#define DDB_OPT_IPV4 0x0f0f 293#define DDB_OPT_IPV4 0x0f0f
294 uint8_t isid[6];
287}; 295};
288 296
289/* 297/*
@@ -303,7 +311,28 @@ struct ql4_tuple_ddb {
303#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */ 311#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */
304#define DF_FO_MASKED 3 312#define DF_FO_MASKED 3
305 313
314enum qla4_work_type {
315 QLA4_EVENT_AEN,
316 QLA4_EVENT_PING_STATUS,
317};
306 318
319struct qla4_work_evt {
320 struct list_head list;
321 enum qla4_work_type type;
322 union {
323 struct {
324 enum iscsi_host_event_code code;
325 uint32_t data_size;
326 uint8_t data[0];
327 } aen;
328 struct {
329 uint32_t status;
330 uint32_t pid;
331 uint32_t data_size;
332 uint8_t data[0];
333 } ping;
334 } u;
335};
307 336
308struct ql82xx_hw_data { 337struct ql82xx_hw_data {
309 /* Offsets for flash/nvram access (set to ~0 if not used). */ 338 /* Offsets for flash/nvram access (set to ~0 if not used). */
@@ -657,6 +686,7 @@ struct scsi_qla_host {
657 struct dma_pool *chap_dma_pool; 686 struct dma_pool *chap_dma_pool;
658 uint8_t *chap_list; /* CHAP table cache */ 687 uint8_t *chap_list; /* CHAP table cache */
659 struct mutex chap_sem; 688 struct mutex chap_sem;
689
660#define CHAP_DMA_BLOCK_SIZE 512 690#define CHAP_DMA_BLOCK_SIZE 512
661 struct workqueue_struct *task_wq; 691 struct workqueue_struct *task_wq;
662 unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG]; 692 unsigned long ddb_idx_map[MAX_DDB_ENTRIES / BITS_PER_LONG];
@@ -674,6 +704,15 @@ struct scsi_qla_host {
674 uint16_t sec_ddb_idx; 704 uint16_t sec_ddb_idx;
675 int is_reset; 705 int is_reset;
676 uint16_t temperature; 706 uint16_t temperature;
707
708 /* event work list */
709 struct list_head work_list;
710 spinlock_t work_lock;
711
712 /* mbox iocb */
713#define MAX_MRB 128
714 struct mrb *active_mrb_array[MAX_MRB];
715 uint32_t mrb_index;
677}; 716};
678 717
679struct ql4_task_data { 718struct ql4_task_data {
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 7825c141bc1a..210cd1d64475 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -331,6 +331,10 @@ struct qla_flt_region {
331/* Mailbox command definitions */ 331/* Mailbox command definitions */
332#define MBOX_CMD_ABOUT_FW 0x0009 332#define MBOX_CMD_ABOUT_FW 0x0009
333#define MBOX_CMD_PING 0x000B 333#define MBOX_CMD_PING 0x000B
334#define PING_IPV6_PROTOCOL_ENABLE 0x1
335#define PING_IPV6_LINKLOCAL_ADDR 0x4
336#define PING_IPV6_ADDR0 0x8
337#define PING_IPV6_ADDR1 0xC
334#define MBOX_CMD_ENABLE_INTRS 0x0010 338#define MBOX_CMD_ENABLE_INTRS 0x0010
335#define INTR_DISABLE 0 339#define INTR_DISABLE 0
336#define INTR_ENABLE 1 340#define INTR_ENABLE 1
@@ -396,6 +400,10 @@ struct qla_flt_region {
396#define FW_ADDSTATE_DHCPv4_LEASE_EXPIRED 0x0008 400#define FW_ADDSTATE_DHCPv4_LEASE_EXPIRED 0x0008
397#define FW_ADDSTATE_LINK_UP 0x0010 401#define FW_ADDSTATE_LINK_UP 0x0010
398#define FW_ADDSTATE_ISNS_SVC_ENABLED 0x0020 402#define FW_ADDSTATE_ISNS_SVC_ENABLED 0x0020
403#define FW_ADDSTATE_LINK_SPEED_10MBPS 0x0100
404#define FW_ADDSTATE_LINK_SPEED_100MBPS 0x0200
405#define FW_ADDSTATE_LINK_SPEED_1GBPS 0x0400
406#define FW_ADDSTATE_LINK_SPEED_10GBPS 0x0800
399 407
400#define MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS 0x006B 408#define MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS 0x006B
401#define IPV6_DEFAULT_DDB_ENTRY 0x0001 409#define IPV6_DEFAULT_DDB_ENTRY 0x0001
@@ -918,6 +926,8 @@ struct qla4_header {
918#define ET_CMND_T3 0x19 926#define ET_CMND_T3 0x19
919#define ET_PASSTHRU0 0x3A 927#define ET_PASSTHRU0 0x3A
920#define ET_PASSTHRU_STATUS 0x3C 928#define ET_PASSTHRU_STATUS 0x3C
929#define ET_MBOX_CMD 0x38
930#define ET_MBOX_STATUS 0x39
921 931
922 uint8_t entryStatus; 932 uint8_t entryStatus;
923 uint8_t systemDefined; 933 uint8_t systemDefined;
@@ -1118,6 +1128,20 @@ struct passthru_status {
1118 uint8_t res4[16]; /* 30-3F */ 1128 uint8_t res4[16]; /* 30-3F */
1119}; 1129};
1120 1130
1131struct mbox_cmd_iocb {
1132 struct qla4_header hdr; /* 00-03 */
1133 uint32_t handle; /* 04-07 */
1134 uint32_t in_mbox[8]; /* 08-25 */
1135 uint32_t res1[6]; /* 26-3F */
1136};
1137
1138struct mbox_status_iocb {
1139 struct qla4_header hdr; /* 00-03 */
1140 uint32_t handle; /* 04-07 */
1141 uint32_t out_mbox[8]; /* 08-25 */
1142 uint32_t res1[6]; /* 26-3F */
1143};
1144
1121/* 1145/*
1122 * ISP queue - response queue entry definition. 1146 * ISP queue - response queue entry definition.
1123 */ 1147 */
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index d0dd4b330206..910536667cf5 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -81,6 +81,8 @@ int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr,
81 uint32_t offset, uint32_t length, uint32_t options); 81 uint32_t offset, uint32_t length, uint32_t options);
82int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, 82int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
83 uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts); 83 uint8_t outCount, uint32_t *mbx_cmd, uint32_t *mbx_sts);
84int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
85 char *password, int bidi, uint16_t *chap_index);
84 86
85void qla4xxx_queue_iocb(struct scsi_qla_host *ha); 87void qla4xxx_queue_iocb(struct scsi_qla_host *ha);
86void qla4xxx_complete_iocb(struct scsi_qla_host *ha); 88void qla4xxx_complete_iocb(struct scsi_qla_host *ha);
@@ -181,6 +183,13 @@ int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
181int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, 183int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
182 struct ddb_entry *ddb_entry, uint32_t state); 184 struct ddb_entry *ddb_entry, uint32_t state);
183void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); 185void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset);
186int qla4xxx_post_aen_work(struct scsi_qla_host *ha, uint32_t aen_code,
187 uint32_t data_size, uint8_t *data);
188int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options,
189 uint32_t payload_size, uint32_t pid, uint8_t *ipaddr);
190int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,
191 uint32_t status, uint32_t pid,
192 uint32_t data_size, uint8_t *data);
184 193
185/* BSG Functions */ 194/* BSG Functions */
186int qla4xxx_bsg_request(struct bsg_job *bsg_job); 195int qla4xxx_bsg_request(struct bsg_job *bsg_job);
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 90614f38b55d..90ee5d8fa731 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -86,6 +86,7 @@ static void qla4xxx_init_response_q_entries(struct scsi_qla_host *ha)
86int qla4xxx_init_rings(struct scsi_qla_host *ha) 86int qla4xxx_init_rings(struct scsi_qla_host *ha)
87{ 87{
88 unsigned long flags = 0; 88 unsigned long flags = 0;
89 int i;
89 90
90 /* Initialize request queue. */ 91 /* Initialize request queue. */
91 spin_lock_irqsave(&ha->hardware_lock, flags); 92 spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -125,6 +126,10 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha)
125 126
126 qla4xxx_init_response_q_entries(ha); 127 qla4xxx_init_response_q_entries(ha);
127 128
129 /* Initialize mabilbox active array */
130 for (i = 0; i < MAX_MRB; i++)
131 ha->active_mrb_array[i] = NULL;
132
128 spin_unlock_irqrestore(&ha->hardware_lock, flags); 133 spin_unlock_irqrestore(&ha->hardware_lock, flags);
129 134
130 return QLA_SUCCESS; 135 return QLA_SUCCESS;
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c
index 410669351906..2a2022a6bb9b 100644
--- a/drivers/scsi/qla4xxx/ql4_iocb.c
+++ b/drivers/scsi/qla4xxx/ql4_iocb.c
@@ -445,3 +445,95 @@ queuing_error:
445 spin_unlock_irqrestore(&ha->hardware_lock, flags); 445 spin_unlock_irqrestore(&ha->hardware_lock, flags);
446 return ret; 446 return ret;
447} 447}
448
449static struct mrb *qla4xxx_get_new_mrb(struct scsi_qla_host *ha)
450{
451 struct mrb *mrb;
452
453 mrb = kzalloc(sizeof(*mrb), GFP_KERNEL);
454 if (!mrb)
455 return mrb;
456
457 mrb->ha = ha;
458 return mrb;
459}
460
461static int qla4xxx_send_mbox_iocb(struct scsi_qla_host *ha, struct mrb *mrb,
462 uint32_t *in_mbox)
463{
464 int rval = QLA_SUCCESS;
465 uint32_t i;
466 unsigned long flags;
467 uint32_t index = 0;
468
469 /* Acquire hardware specific lock */
470 spin_lock_irqsave(&ha->hardware_lock, flags);
471
472 /* Get pointer to the queue entry for the marker */
473 rval = qla4xxx_get_req_pkt(ha, (struct queue_entry **) &(mrb->mbox));
474 if (rval != QLA_SUCCESS)
475 goto exit_mbox_iocb;
476
477 index = ha->mrb_index;
478 /* get valid mrb index*/
479 for (i = 0; i < MAX_MRB; i++) {
480 index++;
481 if (index == MAX_MRB)
482 index = 1;
483 if (ha->active_mrb_array[index] == NULL) {
484 ha->mrb_index = index;
485 break;
486 }
487 }
488
489 mrb->iocb_cnt = 1;
490 ha->active_mrb_array[index] = mrb;
491 mrb->mbox->handle = index;
492 mrb->mbox->hdr.entryType = ET_MBOX_CMD;
493 mrb->mbox->hdr.entryCount = mrb->iocb_cnt;
494 memcpy(mrb->mbox->in_mbox, in_mbox, 32);
495 mrb->mbox_cmd = in_mbox[0];
496 wmb();
497
498 ha->isp_ops->queue_iocb(ha);
499exit_mbox_iocb:
500 spin_unlock_irqrestore(&ha->hardware_lock, flags);
501 return rval;
502}
503
504int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options,
505 uint32_t payload_size, uint32_t pid, uint8_t *ipaddr)
506{
507 uint32_t in_mbox[8];
508 struct mrb *mrb = NULL;
509 int rval = QLA_SUCCESS;
510
511 memset(in_mbox, 0, sizeof(in_mbox));
512
513 mrb = qla4xxx_get_new_mrb(ha);
514 if (!mrb) {
515 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: fail to get new mrb\n",
516 __func__));
517 rval = QLA_ERROR;
518 goto exit_ping;
519 }
520
521 in_mbox[0] = MBOX_CMD_PING;
522 in_mbox[1] = options;
523 memcpy(&in_mbox[2], &ipaddr[0], 4);
524 memcpy(&in_mbox[3], &ipaddr[4], 4);
525 memcpy(&in_mbox[4], &ipaddr[8], 4);
526 memcpy(&in_mbox[5], &ipaddr[12], 4);
527 in_mbox[6] = payload_size;
528
529 mrb->pid = pid;
530 rval = qla4xxx_send_mbox_iocb(ha, mrb, in_mbox);
531
532 if (rval != QLA_SUCCESS)
533 goto exit_ping;
534
535 return rval;
536exit_ping:
537 kfree(mrb);
538 return rval;
539}
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 95828862eea0..7c9f28b7da72 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -385,6 +385,71 @@ static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha,
385 queue_work(ha->task_wq, &task_data->task_work); 385 queue_work(ha->task_wq, &task_data->task_work);
386} 386}
387 387
388static struct mrb *qla4xxx_del_mrb_from_active_array(struct scsi_qla_host *ha,
389 uint32_t index)
390{
391 struct mrb *mrb = NULL;
392
393 /* validate handle and remove from active array */
394 if (index >= MAX_MRB)
395 return mrb;
396
397 mrb = ha->active_mrb_array[index];
398 ha->active_mrb_array[index] = NULL;
399 if (!mrb)
400 return mrb;
401
402 /* update counters */
403 ha->req_q_count += mrb->iocb_cnt;
404 ha->iocb_cnt -= mrb->iocb_cnt;
405
406 return mrb;
407}
408
409static void qla4xxx_mbox_status_entry(struct scsi_qla_host *ha,
410 struct mbox_status_iocb *mbox_sts_entry)
411{
412 struct mrb *mrb;
413 uint32_t status;
414 uint32_t data_size;
415
416 mrb = qla4xxx_del_mrb_from_active_array(ha,
417 le32_to_cpu(mbox_sts_entry->handle));
418
419 if (mrb == NULL) {
420 ql4_printk(KERN_WARNING, ha, "%s: mrb[%d] is null\n", __func__,
421 mbox_sts_entry->handle);
422 return;
423 }
424
425 switch (mrb->mbox_cmd) {
426 case MBOX_CMD_PING:
427 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: mbox_cmd = 0x%x, "
428 "mbox_sts[0] = 0x%x, mbox_sts[6] = 0x%x\n",
429 __func__, mrb->mbox_cmd,
430 mbox_sts_entry->out_mbox[0],
431 mbox_sts_entry->out_mbox[6]));
432
433 if (mbox_sts_entry->out_mbox[0] == MBOX_STS_COMMAND_COMPLETE)
434 status = QLA_SUCCESS;
435 else
436 status = QLA_ERROR;
437
438 data_size = sizeof(mbox_sts_entry->out_mbox);
439
440 qla4xxx_post_ping_evt_work(ha, status, mrb->pid, data_size,
441 (uint8_t *) mbox_sts_entry->out_mbox);
442 break;
443
444 default:
445 DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: invalid mbox_cmd = "
446 "0x%x\n", __func__, mrb->mbox_cmd));
447 }
448
449 kfree(mrb);
450 return;
451}
452
388/** 453/**
389 * qla4xxx_process_response_queue - process response queue completions 454 * qla4xxx_process_response_queue - process response queue completions
390 * @ha: Pointer to host adapter structure. 455 * @ha: Pointer to host adapter structure.
@@ -461,6 +526,13 @@ void qla4xxx_process_response_queue(struct scsi_qla_host *ha)
461 "ignoring\n", ha->host_no, __func__)); 526 "ignoring\n", ha->host_no, __func__));
462 break; 527 break;
463 528
529 case ET_MBOX_STATUS:
530 DEBUG2(ql4_printk(KERN_INFO, ha,
531 "%s: mbox status IOCB\n", __func__));
532 qla4xxx_mbox_status_entry(ha,
533 (struct mbox_status_iocb *)sts_entry);
534 break;
535
464 default: 536 default:
465 /* 537 /*
466 * Invalid entry in response queue, reset RISC 538 * Invalid entry in response queue, reset RISC
@@ -576,6 +648,9 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
576 set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); 648 set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
577 649
578 ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__); 650 ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__);
651 qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP,
652 sizeof(mbox_sts),
653 (uint8_t *) mbox_sts);
579 break; 654 break;
580 655
581 case MBOX_ASTS_LINK_DOWN: 656 case MBOX_ASTS_LINK_DOWN:
@@ -584,6 +659,9 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
584 set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); 659 set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
585 660
586 ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__); 661 ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__);
662 qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKDOWN,
663 sizeof(mbox_sts),
664 (uint8_t *) mbox_sts);
587 break; 665 break;
588 666
589 case MBOX_ASTS_HEARTBEAT: 667 case MBOX_ASTS_HEARTBEAT:
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index e1e66a45e4d0..7ac21dabbf22 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -622,7 +622,7 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
622 return QLA_ERROR; 622 return QLA_ERROR;
623 } 623 }
624 624
625 ql4_printk(KERN_INFO, ha, "%ld firmare IOCBs available (%d).\n", 625 ql4_printk(KERN_INFO, ha, "%ld firmware IOCBs available (%d).\n",
626 ha->host_no, mbox_sts[2]); 626 ha->host_no, mbox_sts[2]);
627 627
628 return QLA_SUCCESS; 628 return QLA_SUCCESS;
@@ -661,6 +661,8 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
661 } 661 }
662 memset(&mbox_cmd, 0, sizeof(mbox_cmd)); 662 memset(&mbox_cmd, 0, sizeof(mbox_cmd));
663 memset(&mbox_sts, 0, sizeof(mbox_sts)); 663 memset(&mbox_sts, 0, sizeof(mbox_sts));
664 if (fw_ddb_entry)
665 memset(fw_ddb_entry, 0, sizeof(struct dev_db_entry));
664 666
665 mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; 667 mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
666 mbox_cmd[1] = (uint32_t) fw_ddb_index; 668 mbox_cmd[1] = (uint32_t) fw_ddb_index;
@@ -1424,8 +1426,8 @@ exit_set_chap:
1424 * match is found. If a match is not found then add the entry in FLASH and 1426 * match is found. If a match is not found then add the entry in FLASH and
1425 * return the index at which entry is written in the FLASH. 1427 * return the index at which entry is written in the FLASH.
1426 **/ 1428 **/
1427static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username, 1429int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
1428 char *password, int bidi, uint16_t *chap_index) 1430 char *password, int bidi, uint16_t *chap_index)
1429{ 1431{
1430 int i, rval; 1432 int i, rval;
1431 int free_index = -1; 1433 int free_index = -1;
@@ -1444,6 +1446,11 @@ static int qla4xxx_get_chap_index(struct scsi_qla_host *ha, char *username,
1444 return QLA_ERROR; 1446 return QLA_ERROR;
1445 } 1447 }
1446 1448
1449 if (!username || !password) {
1450 ql4_printk(KERN_ERR, ha, "Do not have username and psw\n");
1451 return QLA_ERROR;
1452 }
1453
1447 mutex_lock(&ha->chap_sem); 1454 mutex_lock(&ha->chap_sem);
1448 for (i = 0; i < max_chap_entries; i++) { 1455 for (i = 0; i < max_chap_entries; i++) {
1449 chap_table = (struct ql4_chap_table *)ha->chap_list + i; 1456 chap_table = (struct ql4_chap_table *)ha->chap_list + i;
@@ -1600,7 +1607,7 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
1600 char *ip; 1607 char *ip;
1601 uint16_t iscsi_opts = 0; 1608 uint16_t iscsi_opts = 0;
1602 uint32_t options = 0; 1609 uint32_t options = 0;
1603 uint16_t idx; 1610 uint16_t idx, *ptid;
1604 1611
1605 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 1612 fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
1606 &fw_ddb_entry_dma, GFP_KERNEL); 1613 &fw_ddb_entry_dma, GFP_KERNEL);
@@ -1626,6 +1633,14 @@ int qla4xxx_set_param_ddbentry(struct scsi_qla_host *ha,
1626 goto exit_set_param; 1633 goto exit_set_param;
1627 } 1634 }
1628 1635
1636 ptid = (uint16_t *)&fw_ddb_entry->isid[1];
1637 *ptid = cpu_to_le16((uint16_t)ddb_entry->sess->target_id);
1638
1639 DEBUG2(ql4_printk(KERN_INFO, ha, "ISID [%02x%02x%02x%02x%02x%02x]\n",
1640 fw_ddb_entry->isid[5], fw_ddb_entry->isid[4],
1641 fw_ddb_entry->isid[3], fw_ddb_entry->isid[2],
1642 fw_ddb_entry->isid[1], fw_ddb_entry->isid[0]));
1643
1629 iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options); 1644 iscsi_opts = le16_to_cpu(fw_ddb_entry->iscsi_options);
1630 memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias)); 1645 memset(fw_ddb_entry->iscsi_alias, 0, sizeof(fw_ddb_entry->iscsi_alias));
1631 1646
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 65253dfbe962..e1e46b6dac75 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -841,11 +841,8 @@ qla4_8xxx_rom_lock(struct scsi_qla_host *ha)
841 done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); 841 done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK));
842 if (done == 1) 842 if (done == 1)
843 break; 843 break;
844 if (timeout >= qla4_8xxx_rom_lock_timeout) { 844 if (timeout >= qla4_8xxx_rom_lock_timeout)
845 ql4_printk(KERN_WARNING, ha,
846 "%s: Failed to acquire rom lock", __func__);
847 return -1; 845 return -1;
848 }
849 846
850 timeout++; 847 timeout++;
851 848
@@ -996,18 +993,6 @@ qla4_8xxx_pinit_from_rom(struct scsi_qla_host *ha, int verbose)
996 else 993 else
997 qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff); 994 qla4_8xxx_wr_32(ha, QLA82XX_ROMUSB_GLB_SW_RESET, 0xffffffff);
998 995
999 /* reset ms */
1000 val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
1001 val |= (1 << 1);
1002 qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
1003
1004 msleep(20);
1005 /* unreset ms */
1006 val = qla4_8xxx_rd_32(ha, QLA82XX_CRB_QDR_NET + 0xe4);
1007 val &= ~(1 << 1);
1008 qla4_8xxx_wr_32(ha, QLA82XX_CRB_QDR_NET + 0xe4, val);
1009 msleep(20);
1010
1011 qla4_8xxx_rom_unlock(ha); 996 qla4_8xxx_rom_unlock(ha);
1012 997
1013 /* Read the signature value from the flash. 998 /* Read the signature value from the flash.
diff --git a/drivers/scsi/qla4xxx/ql4_nx.h b/drivers/scsi/qla4xxx/ql4_nx.h
index dc45ac923691..dc7500e47b8b 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.h
+++ b/drivers/scsi/qla4xxx/ql4_nx.h
@@ -623,6 +623,7 @@ struct crb_addr_pair {
623 623
624#define ADDR_ERROR ((unsigned long) 0xffffffff) 624#define ADDR_ERROR ((unsigned long) 0xffffffff)
625#define MAX_CTL_CHECK 1000 625#define MAX_CTL_CHECK 1000
626#define QLA82XX_FWERROR_CODE(code) ((code >> 8) & 0x1fffff)
626 627
627/*************************************************************************** 628/***************************************************************************
628 * PCI related defines. 629 * PCI related defines.
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index edf503437e96..3d9419460e0c 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -32,14 +32,14 @@ static struct kmem_cache *srb_cachep;
32/* 32/*
33 * Module parameter information and variables 33 * Module parameter information and variables
34 */ 34 */
35int ql4xdisablesysfsboot = 1; 35static int ql4xdisablesysfsboot = 1;
36module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR); 36module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
37MODULE_PARM_DESC(ql4xdisablesysfsboot, 37MODULE_PARM_DESC(ql4xdisablesysfsboot,
38 " Set to disable exporting boot targets to sysfs.\n" 38 " Set to disable exporting boot targets to sysfs.\n"
39 "\t\t 0 - Export boot targets\n" 39 "\t\t 0 - Export boot targets\n"
40 "\t\t 1 - Do not export boot targets (Default)"); 40 "\t\t 1 - Do not export boot targets (Default)");
41 41
42int ql4xdontresethba = 0; 42int ql4xdontresethba;
43module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); 43module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
44MODULE_PARM_DESC(ql4xdontresethba, 44MODULE_PARM_DESC(ql4xdontresethba,
45 " Don't reset the HBA for driver recovery.\n" 45 " Don't reset the HBA for driver recovery.\n"
@@ -71,7 +71,7 @@ MODULE_PARM_DESC(ql4xmaxqdepth,
71static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; 71static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
72module_param(ql4xsess_recovery_tmo, int, S_IRUGO); 72module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
73MODULE_PARM_DESC(ql4xsess_recovery_tmo, 73MODULE_PARM_DESC(ql4xsess_recovery_tmo,
74 "Target Session Recovery Timeout.\n" 74 " Target Session Recovery Timeout.\n"
75 "\t\t Default: 120 sec."); 75 "\t\t Default: 120 sec.");
76 76
77static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); 77static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
@@ -83,6 +83,8 @@ static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
83/* 83/*
84 * iSCSI template entry points 84 * iSCSI template entry points
85 */ 85 */
86static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,
87 enum iscsi_param param, char *buf);
86static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn, 88static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn,
87 enum iscsi_param param, char *buf); 89 enum iscsi_param param, char *buf);
88static int qla4xxx_host_get_param(struct Scsi_Host *shost, 90static int qla4xxx_host_get_param(struct Scsi_Host *shost,
@@ -118,6 +120,13 @@ static void qla4xxx_task_cleanup(struct iscsi_task *);
118static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session); 120static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session);
119static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, 121static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
120 struct iscsi_stats *stats); 122 struct iscsi_stats *stats);
123static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
124 uint32_t iface_type, uint32_t payload_size,
125 uint32_t pid, struct sockaddr *dst_addr);
126static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
127 uint32_t *num_entries, char *buf);
128static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx);
129
121/* 130/*
122 * SCSI host template entry points 131 * SCSI host template entry points
123 */ 132 */
@@ -179,7 +188,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
179 .destroy_conn = qla4xxx_conn_destroy, 188 .destroy_conn = qla4xxx_conn_destroy,
180 .set_param = iscsi_set_param, 189 .set_param = iscsi_set_param,
181 .get_conn_param = qla4xxx_conn_get_param, 190 .get_conn_param = qla4xxx_conn_get_param,
182 .get_session_param = iscsi_session_get_param, 191 .get_session_param = qla4xxx_session_get_param,
183 .get_ep_param = qla4xxx_get_ep_param, 192 .get_ep_param = qla4xxx_get_ep_param,
184 .ep_connect = qla4xxx_ep_connect, 193 .ep_connect = qla4xxx_ep_connect,
185 .ep_poll = qla4xxx_ep_poll, 194 .ep_poll = qla4xxx_ep_poll,
@@ -194,10 +203,93 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
194 .set_iface_param = qla4xxx_iface_set_param, 203 .set_iface_param = qla4xxx_iface_set_param,
195 .get_iface_param = qla4xxx_get_iface_param, 204 .get_iface_param = qla4xxx_get_iface_param,
196 .bsg_request = qla4xxx_bsg_request, 205 .bsg_request = qla4xxx_bsg_request,
206 .send_ping = qla4xxx_send_ping,
207 .get_chap = qla4xxx_get_chap_list,
208 .delete_chap = qla4xxx_delete_chap,
197}; 209};
198 210
199static struct scsi_transport_template *qla4xxx_scsi_transport; 211static struct scsi_transport_template *qla4xxx_scsi_transport;
200 212
213static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
214 uint32_t iface_type, uint32_t payload_size,
215 uint32_t pid, struct sockaddr *dst_addr)
216{
217 struct scsi_qla_host *ha = to_qla_host(shost);
218 struct sockaddr_in *addr;
219 struct sockaddr_in6 *addr6;
220 uint32_t options = 0;
221 uint8_t ipaddr[IPv6_ADDR_LEN];
222 int rval;
223
224 memset(ipaddr, 0, IPv6_ADDR_LEN);
225 /* IPv4 to IPv4 */
226 if ((iface_type == ISCSI_IFACE_TYPE_IPV4) &&
227 (dst_addr->sa_family == AF_INET)) {
228 addr = (struct sockaddr_in *)dst_addr;
229 memcpy(ipaddr, &addr->sin_addr.s_addr, IP_ADDR_LEN);
230 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv4 Ping src: %pI4 "
231 "dest: %pI4\n", __func__,
232 &ha->ip_config.ip_address, ipaddr));
233 rval = qla4xxx_ping_iocb(ha, options, payload_size, pid,
234 ipaddr);
235 if (rval)
236 rval = -EINVAL;
237 } else if ((iface_type == ISCSI_IFACE_TYPE_IPV6) &&
238 (dst_addr->sa_family == AF_INET6)) {
239 /* IPv6 to IPv6 */
240 addr6 = (struct sockaddr_in6 *)dst_addr;
241 memcpy(ipaddr, &addr6->sin6_addr.in6_u.u6_addr8, IPv6_ADDR_LEN);
242
243 options |= PING_IPV6_PROTOCOL_ENABLE;
244
245 /* Ping using LinkLocal address */
246 if ((iface_num == 0) || (iface_num == 1)) {
247 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: LinkLocal Ping "
248 "src: %pI6 dest: %pI6\n", __func__,
249 &ha->ip_config.ipv6_link_local_addr,
250 ipaddr));
251 options |= PING_IPV6_LINKLOCAL_ADDR;
252 rval = qla4xxx_ping_iocb(ha, options, payload_size,
253 pid, ipaddr);
254 } else {
255 ql4_printk(KERN_WARNING, ha, "%s: iface num = %d "
256 "not supported\n", __func__, iface_num);
257 rval = -ENOSYS;
258 goto exit_send_ping;
259 }
260
261 /*
262 * If ping using LinkLocal address fails, try ping using
263 * IPv6 address
264 */
265 if (rval != QLA_SUCCESS) {
266 options &= ~PING_IPV6_LINKLOCAL_ADDR;
267 if (iface_num == 0) {
268 options |= PING_IPV6_ADDR0;
269 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 "
270 "Ping src: %pI6 "
271 "dest: %pI6\n", __func__,
272 &ha->ip_config.ipv6_addr0,
273 ipaddr));
274 } else if (iface_num == 1) {
275 options |= PING_IPV6_ADDR1;
276 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 "
277 "Ping src: %pI6 "
278 "dest: %pI6\n", __func__,
279 &ha->ip_config.ipv6_addr1,
280 ipaddr));
281 }
282 rval = qla4xxx_ping_iocb(ha, options, payload_size,
283 pid, ipaddr);
284 if (rval)
285 rval = -EINVAL;
286 }
287 } else
288 rval = -ENOSYS;
289exit_send_ping:
290 return rval;
291}
292
201static umode_t ql4_attr_is_visible(int param_type, int param) 293static umode_t ql4_attr_is_visible(int param_type, int param)
202{ 294{
203 switch (param_type) { 295 switch (param_type) {
@@ -206,6 +298,8 @@ static umode_t ql4_attr_is_visible(int param_type, int param)
206 case ISCSI_HOST_PARAM_HWADDRESS: 298 case ISCSI_HOST_PARAM_HWADDRESS:
207 case ISCSI_HOST_PARAM_IPADDRESS: 299 case ISCSI_HOST_PARAM_IPADDRESS:
208 case ISCSI_HOST_PARAM_INITIATOR_NAME: 300 case ISCSI_HOST_PARAM_INITIATOR_NAME:
301 case ISCSI_HOST_PARAM_PORT_STATE:
302 case ISCSI_HOST_PARAM_PORT_SPEED:
209 return S_IRUGO; 303 return S_IRUGO;
210 default: 304 default:
211 return 0; 305 return 0;
@@ -225,6 +319,12 @@ static umode_t ql4_attr_is_visible(int param_type, int param)
225 case ISCSI_PARAM_MAX_RECV_DLENGTH: 319 case ISCSI_PARAM_MAX_RECV_DLENGTH:
226 case ISCSI_PARAM_MAX_XMIT_DLENGTH: 320 case ISCSI_PARAM_MAX_XMIT_DLENGTH:
227 case ISCSI_PARAM_IFACE_NAME: 321 case ISCSI_PARAM_IFACE_NAME:
322 case ISCSI_PARAM_CHAP_OUT_IDX:
323 case ISCSI_PARAM_CHAP_IN_IDX:
324 case ISCSI_PARAM_USERNAME:
325 case ISCSI_PARAM_PASSWORD:
326 case ISCSI_PARAM_USERNAME_IN:
327 case ISCSI_PARAM_PASSWORD_IN:
228 return S_IRUGO; 328 return S_IRUGO;
229 default: 329 default:
230 return 0; 330 return 0;
@@ -255,6 +355,189 @@ static umode_t ql4_attr_is_visible(int param_type, int param)
255 return 0; 355 return 0;
256} 356}
257 357
358static int qla4xxx_get_chap_list(struct Scsi_Host *shost, uint16_t chap_tbl_idx,
359 uint32_t *num_entries, char *buf)
360{
361 struct scsi_qla_host *ha = to_qla_host(shost);
362 struct ql4_chap_table *chap_table;
363 struct iscsi_chap_rec *chap_rec;
364 int max_chap_entries = 0;
365 int valid_chap_entries = 0;
366 int ret = 0, i;
367
368 if (is_qla8022(ha))
369 max_chap_entries = (ha->hw.flt_chap_size / 2) /
370 sizeof(struct ql4_chap_table);
371 else
372 max_chap_entries = MAX_CHAP_ENTRIES_40XX;
373
374 ql4_printk(KERN_INFO, ha, "%s: num_entries = %d, CHAP idx = %d\n",
375 __func__, *num_entries, chap_tbl_idx);
376
377 if (!buf) {
378 ret = -ENOMEM;
379 goto exit_get_chap_list;
380 }
381
382 chap_rec = (struct iscsi_chap_rec *) buf;
383 mutex_lock(&ha->chap_sem);
384 for (i = chap_tbl_idx; i < max_chap_entries; i++) {
385 chap_table = (struct ql4_chap_table *)ha->chap_list + i;
386 if (chap_table->cookie !=
387 __constant_cpu_to_le16(CHAP_VALID_COOKIE))
388 continue;
389
390 chap_rec->chap_tbl_idx = i;
391 strncpy(chap_rec->username, chap_table->name,
392 ISCSI_CHAP_AUTH_NAME_MAX_LEN);
393 strncpy(chap_rec->password, chap_table->secret,
394 QL4_CHAP_MAX_SECRET_LEN);
395 chap_rec->password_length = chap_table->secret_len;
396
397 if (chap_table->flags & BIT_7) /* local */
398 chap_rec->chap_type = CHAP_TYPE_OUT;
399
400 if (chap_table->flags & BIT_6) /* peer */
401 chap_rec->chap_type = CHAP_TYPE_IN;
402
403 chap_rec++;
404
405 valid_chap_entries++;
406 if (valid_chap_entries == *num_entries)
407 break;
408 else
409 continue;
410 }
411 mutex_unlock(&ha->chap_sem);
412
413exit_get_chap_list:
414 ql4_printk(KERN_INFO, ha, "%s: Valid CHAP Entries = %d\n",
415 __func__, valid_chap_entries);
416 *num_entries = valid_chap_entries;
417 return ret;
418}
419
420static int __qla4xxx_is_chap_active(struct device *dev, void *data)
421{
422 int ret = 0;
423 uint16_t *chap_tbl_idx = (uint16_t *) data;
424 struct iscsi_cls_session *cls_session;
425 struct iscsi_session *sess;
426 struct ddb_entry *ddb_entry;
427
428 if (!iscsi_is_session_dev(dev))
429 goto exit_is_chap_active;
430
431 cls_session = iscsi_dev_to_session(dev);
432 sess = cls_session->dd_data;
433 ddb_entry = sess->dd_data;
434
435 if (iscsi_session_chkready(cls_session))
436 goto exit_is_chap_active;
437
438 if (ddb_entry->chap_tbl_idx == *chap_tbl_idx)
439 ret = 1;
440
441exit_is_chap_active:
442 return ret;
443}
444
445static int qla4xxx_is_chap_active(struct Scsi_Host *shost,
446 uint16_t chap_tbl_idx)
447{
448 int ret = 0;
449
450 ret = device_for_each_child(&shost->shost_gendev, &chap_tbl_idx,
451 __qla4xxx_is_chap_active);
452
453 return ret;
454}
455
456static int qla4xxx_delete_chap(struct Scsi_Host *shost, uint16_t chap_tbl_idx)
457{
458 struct scsi_qla_host *ha = to_qla_host(shost);
459 struct ql4_chap_table *chap_table;
460 dma_addr_t chap_dma;
461 int max_chap_entries = 0;
462 uint32_t offset = 0;
463 uint32_t chap_size;
464 int ret = 0;
465
466 chap_table = dma_pool_alloc(ha->chap_dma_pool, GFP_KERNEL, &chap_dma);
467 if (chap_table == NULL)
468 return -ENOMEM;
469
470 memset(chap_table, 0, sizeof(struct ql4_chap_table));
471
472 if (is_qla8022(ha))
473 max_chap_entries = (ha->hw.flt_chap_size / 2) /
474 sizeof(struct ql4_chap_table);
475 else
476 max_chap_entries = MAX_CHAP_ENTRIES_40XX;
477
478 if (chap_tbl_idx > max_chap_entries) {
479 ret = -EINVAL;
480 goto exit_delete_chap;
481 }
482
483 /* Check if chap index is in use.
484 * If chap is in use don't delet chap entry */
485 ret = qla4xxx_is_chap_active(shost, chap_tbl_idx);
486 if (ret) {
487 ql4_printk(KERN_INFO, ha, "CHAP entry %d is in use, cannot "
488 "delete from flash\n", chap_tbl_idx);
489 ret = -EBUSY;
490 goto exit_delete_chap;
491 }
492
493 chap_size = sizeof(struct ql4_chap_table);
494 if (is_qla40XX(ha))
495 offset = FLASH_CHAP_OFFSET | (chap_tbl_idx * chap_size);
496 else {
497 offset = FLASH_RAW_ACCESS_ADDR + (ha->hw.flt_region_chap << 2);
498 /* flt_chap_size is CHAP table size for both ports
499 * so divide it by 2 to calculate the offset for second port
500 */
501 if (ha->port_num == 1)
502 offset += (ha->hw.flt_chap_size / 2);
503 offset += (chap_tbl_idx * chap_size);
504 }
505
506 ret = qla4xxx_get_flash(ha, chap_dma, offset, chap_size);
507 if (ret != QLA_SUCCESS) {
508 ret = -EINVAL;
509 goto exit_delete_chap;
510 }
511
512 DEBUG2(ql4_printk(KERN_INFO, ha, "Chap Cookie: x%x\n",
513 __le16_to_cpu(chap_table->cookie)));
514
515 if (__le16_to_cpu(chap_table->cookie) != CHAP_VALID_COOKIE) {
516 ql4_printk(KERN_ERR, ha, "No valid chap entry found\n");
517 goto exit_delete_chap;
518 }
519
520 chap_table->cookie = __constant_cpu_to_le16(0xFFFF);
521
522 offset = FLASH_CHAP_OFFSET |
523 (chap_tbl_idx * sizeof(struct ql4_chap_table));
524 ret = qla4xxx_set_flash(ha, chap_dma, offset, chap_size,
525 FLASH_OPT_RMW_COMMIT);
526 if (ret == QLA_SUCCESS && ha->chap_list) {
527 mutex_lock(&ha->chap_sem);
528 /* Update ha chap_list cache */
529 memcpy((struct ql4_chap_table *)ha->chap_list + chap_tbl_idx,
530 chap_table, sizeof(struct ql4_chap_table));
531 mutex_unlock(&ha->chap_sem);
532 }
533 if (ret != QLA_SUCCESS)
534 ret = -EINVAL;
535
536exit_delete_chap:
537 dma_pool_free(ha->chap_dma_pool, chap_table, chap_dma);
538 return ret;
539}
540
258static int qla4xxx_get_iface_param(struct iscsi_iface *iface, 541static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
259 enum iscsi_param_type param_type, 542 enum iscsi_param_type param_type,
260 int param, char *buf) 543 int param, char *buf)
@@ -548,6 +831,43 @@ static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
548 return ret; 831 return ret;
549} 832}
550 833
834static void qla4xxx_set_port_speed(struct Scsi_Host *shost)
835{
836 struct scsi_qla_host *ha = to_qla_host(shost);
837 struct iscsi_cls_host *ihost = shost_priv(shost);
838 uint32_t speed = ISCSI_PORT_SPEED_UNKNOWN;
839
840 qla4xxx_get_firmware_state(ha);
841
842 switch (ha->addl_fw_state & 0x0F00) {
843 case FW_ADDSTATE_LINK_SPEED_10MBPS:
844 speed = ISCSI_PORT_SPEED_10MBPS;
845 break;
846 case FW_ADDSTATE_LINK_SPEED_100MBPS:
847 speed = ISCSI_PORT_SPEED_100MBPS;
848 break;
849 case FW_ADDSTATE_LINK_SPEED_1GBPS:
850 speed = ISCSI_PORT_SPEED_1GBPS;
851 break;
852 case FW_ADDSTATE_LINK_SPEED_10GBPS:
853 speed = ISCSI_PORT_SPEED_10GBPS;
854 break;
855 }
856 ihost->port_speed = speed;
857}
858
859static void qla4xxx_set_port_state(struct Scsi_Host *shost)
860{
861 struct scsi_qla_host *ha = to_qla_host(shost);
862 struct iscsi_cls_host *ihost = shost_priv(shost);
863 uint32_t state = ISCSI_PORT_STATE_DOWN;
864
865 if (test_bit(AF_LINK_UP, &ha->flags))
866 state = ISCSI_PORT_STATE_UP;
867
868 ihost->port_state = state;
869}
870
551static int qla4xxx_host_get_param(struct Scsi_Host *shost, 871static int qla4xxx_host_get_param(struct Scsi_Host *shost,
552 enum iscsi_host_param param, char *buf) 872 enum iscsi_host_param param, char *buf)
553{ 873{
@@ -564,6 +884,14 @@ static int qla4xxx_host_get_param(struct Scsi_Host *shost,
564 case ISCSI_HOST_PARAM_INITIATOR_NAME: 884 case ISCSI_HOST_PARAM_INITIATOR_NAME:
565 len = sprintf(buf, "%s\n", ha->name_string); 885 len = sprintf(buf, "%s\n", ha->name_string);
566 break; 886 break;
887 case ISCSI_HOST_PARAM_PORT_STATE:
888 qla4xxx_set_port_state(shost);
889 len = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
890 break;
891 case ISCSI_HOST_PARAM_PORT_SPEED:
892 qla4xxx_set_port_speed(shost);
893 len = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
894 break;
567 default: 895 default:
568 return -ENOSYS; 896 return -ENOSYS;
569 } 897 }
@@ -968,6 +1296,41 @@ exit_init_fw_cb:
968 return rval; 1296 return rval;
969} 1297}
970 1298
1299static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess,
1300 enum iscsi_param param, char *buf)
1301{
1302 struct iscsi_session *sess = cls_sess->dd_data;
1303 struct ddb_entry *ddb_entry = sess->dd_data;
1304 struct scsi_qla_host *ha = ddb_entry->ha;
1305 int rval, len;
1306 uint16_t idx;
1307
1308 switch (param) {
1309 case ISCSI_PARAM_CHAP_IN_IDX:
1310 rval = qla4xxx_get_chap_index(ha, sess->username_in,
1311 sess->password_in, BIDI_CHAP,
1312 &idx);
1313 if (rval)
1314 return -EINVAL;
1315
1316 len = sprintf(buf, "%hu\n", idx);
1317 break;
1318 case ISCSI_PARAM_CHAP_OUT_IDX:
1319 rval = qla4xxx_get_chap_index(ha, sess->username,
1320 sess->password, LOCAL_CHAP,
1321 &idx);
1322 if (rval)
1323 return -EINVAL;
1324
1325 len = sprintf(buf, "%hu\n", idx);
1326 break;
1327 default:
1328 return iscsi_session_get_param(cls_sess, param, buf);
1329 }
1330
1331 return len;
1332}
1333
971static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn, 1334static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn,
972 enum iscsi_param param, char *buf) 1335 enum iscsi_param param, char *buf)
973{ 1336{
@@ -1506,13 +1869,17 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,
1506{ 1869{
1507 int buflen = 0; 1870 int buflen = 0;
1508 struct iscsi_session *sess; 1871 struct iscsi_session *sess;
1872 struct ddb_entry *ddb_entry;
1509 struct iscsi_conn *conn; 1873 struct iscsi_conn *conn;
1510 char ip_addr[DDB_IPADDR_LEN]; 1874 char ip_addr[DDB_IPADDR_LEN];
1511 uint16_t options = 0; 1875 uint16_t options = 0;
1512 1876
1513 sess = cls_sess->dd_data; 1877 sess = cls_sess->dd_data;
1878 ddb_entry = sess->dd_data;
1514 conn = cls_conn->dd_data; 1879 conn = cls_conn->dd_data;
1515 1880
1881 ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
1882
1516 conn->max_recv_dlength = BYTE_UNITS * 1883 conn->max_recv_dlength = BYTE_UNITS *
1517 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); 1884 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
1518 1885
@@ -1552,6 +1919,8 @@ static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha,
1552 (char *)ha->name_string, buflen); 1919 (char *)ha->name_string, buflen);
1553 iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS, 1920 iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS,
1554 (char *)ip_addr, buflen); 1921 (char *)ip_addr, buflen);
1922 iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_ALIAS,
1923 (char *)fw_ddb_entry->iscsi_alias, buflen);
1555} 1924}
1556 1925
1557void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, 1926void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha,
@@ -1638,6 +2007,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
1638 le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); 2007 le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
1639 2008
1640 /* Update params */ 2009 /* Update params */
2010 ddb_entry->chap_tbl_idx = le16_to_cpu(fw_ddb_entry->chap_tbl_idx);
1641 conn->max_recv_dlength = BYTE_UNITS * 2011 conn->max_recv_dlength = BYTE_UNITS *
1642 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); 2012 le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len);
1643 2013
@@ -1666,6 +2036,9 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
1666 memcpy(sess->initiatorname, ha->name_string, 2036 memcpy(sess->initiatorname, ha->name_string,
1667 min(sizeof(ha->name_string), sizeof(sess->initiatorname))); 2037 min(sizeof(ha->name_string), sizeof(sess->initiatorname)));
1668 2038
2039 iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_ALIAS,
2040 (char *)fw_ddb_entry->iscsi_alias, 0);
2041
1669exit_session_conn_param: 2042exit_session_conn_param:
1670 if (fw_ddb_entry) 2043 if (fw_ddb_entry)
1671 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), 2044 dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
@@ -2113,7 +2486,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
2113 halt_status = qla4_8xxx_rd_32(ha, 2486 halt_status = qla4_8xxx_rd_32(ha,
2114 QLA82XX_PEG_HALT_STATUS1); 2487 QLA82XX_PEG_HALT_STATUS1);
2115 2488
2116 if (LSW(MSB(halt_status)) == 0x67) 2489 if (QLA82XX_FWERROR_CODE(halt_status) == 0x67)
2117 ql4_printk(KERN_ERR, ha, "%s:" 2490 ql4_printk(KERN_ERR, ha, "%s:"
2118 " Firmware aborted with" 2491 " Firmware aborted with"
2119 " error code 0x00006700." 2492 " error code 0x00006700."
@@ -2230,6 +2603,10 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
2230 } 2603 }
2231 } 2604 }
2232 2605
2606 /* Process any deferred work. */
2607 if (!list_empty(&ha->work_list))
2608 start_dpc++;
2609
2233 /* Wakeup the dpc routine for this adapter, if needed. */ 2610 /* Wakeup the dpc routine for this adapter, if needed. */
2234 if (start_dpc || 2611 if (start_dpc ||
2235 test_bit(DPC_RESET_HA, &ha->dpc_flags) || 2612 test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
@@ -2795,6 +3172,109 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
2795 queue_work(ha->dpc_thread, &ha->dpc_work); 3172 queue_work(ha->dpc_thread, &ha->dpc_work);
2796} 3173}
2797 3174
3175static struct qla4_work_evt *
3176qla4xxx_alloc_work(struct scsi_qla_host *ha, uint32_t data_size,
3177 enum qla4_work_type type)
3178{
3179 struct qla4_work_evt *e;
3180 uint32_t size = sizeof(struct qla4_work_evt) + data_size;
3181
3182 e = kzalloc(size, GFP_ATOMIC);
3183 if (!e)
3184 return NULL;
3185
3186 INIT_LIST_HEAD(&e->list);
3187 e->type = type;
3188 return e;
3189}
3190
3191static void qla4xxx_post_work(struct scsi_qla_host *ha,
3192 struct qla4_work_evt *e)
3193{
3194 unsigned long flags;
3195
3196 spin_lock_irqsave(&ha->work_lock, flags);
3197 list_add_tail(&e->list, &ha->work_list);
3198 spin_unlock_irqrestore(&ha->work_lock, flags);
3199 qla4xxx_wake_dpc(ha);
3200}
3201
3202int qla4xxx_post_aen_work(struct scsi_qla_host *ha,
3203 enum iscsi_host_event_code aen_code,
3204 uint32_t data_size, uint8_t *data)
3205{
3206 struct qla4_work_evt *e;
3207
3208 e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_AEN);
3209 if (!e)
3210 return QLA_ERROR;
3211
3212 e->u.aen.code = aen_code;
3213 e->u.aen.data_size = data_size;
3214 memcpy(e->u.aen.data, data, data_size);
3215
3216 qla4xxx_post_work(ha, e);
3217
3218 return QLA_SUCCESS;
3219}
3220
3221int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,
3222 uint32_t status, uint32_t pid,
3223 uint32_t data_size, uint8_t *data)
3224{
3225 struct qla4_work_evt *e;
3226
3227 e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_PING_STATUS);
3228 if (!e)
3229 return QLA_ERROR;
3230
3231 e->u.ping.status = status;
3232 e->u.ping.pid = pid;
3233 e->u.ping.data_size = data_size;
3234 memcpy(e->u.ping.data, data, data_size);
3235
3236 qla4xxx_post_work(ha, e);
3237
3238 return QLA_SUCCESS;
3239}
3240
3241static void qla4xxx_do_work(struct scsi_qla_host *ha)
3242{
3243 struct qla4_work_evt *e, *tmp;
3244 unsigned long flags;
3245 LIST_HEAD(work);
3246
3247 spin_lock_irqsave(&ha->work_lock, flags);
3248 list_splice_init(&ha->work_list, &work);
3249 spin_unlock_irqrestore(&ha->work_lock, flags);
3250
3251 list_for_each_entry_safe(e, tmp, &work, list) {
3252 list_del_init(&e->list);
3253
3254 switch (e->type) {
3255 case QLA4_EVENT_AEN:
3256 iscsi_post_host_event(ha->host_no,
3257 &qla4xxx_iscsi_transport,
3258 e->u.aen.code,
3259 e->u.aen.data_size,
3260 e->u.aen.data);
3261 break;
3262 case QLA4_EVENT_PING_STATUS:
3263 iscsi_ping_comp_event(ha->host_no,
3264 &qla4xxx_iscsi_transport,
3265 e->u.ping.status,
3266 e->u.ping.pid,
3267 e->u.ping.data_size,
3268 e->u.ping.data);
3269 break;
3270 default:
3271 ql4_printk(KERN_WARNING, ha, "event type: 0x%x not "
3272 "supported", e->type);
3273 }
3274 kfree(e);
3275 }
3276}
3277
2798/** 3278/**
2799 * qla4xxx_do_dpc - dpc routine 3279 * qla4xxx_do_dpc - dpc routine
2800 * @data: in our case pointer to adapter structure 3280 * @data: in our case pointer to adapter structure
@@ -2826,6 +3306,9 @@ static void qla4xxx_do_dpc(struct work_struct *work)
2826 return; 3306 return;
2827 } 3307 }
2828 3308
3309 /* post events to application */
3310 qla4xxx_do_work(ha);
3311
2829 if (is_qla8022(ha)) { 3312 if (is_qla8022(ha)) {
2830 if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { 3313 if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
2831 qla4_8xxx_idc_lock(ha); 3314 qla4_8xxx_idc_lock(ha);
@@ -3341,9 +3824,8 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
3341 /* Check Boot Mode */ 3824 /* Check Boot Mode */
3342 val = rd_nvram_byte(ha, addr); 3825 val = rd_nvram_byte(ha, addr);
3343 if (!(val & 0x07)) { 3826 if (!(val & 0x07)) {
3344 DEBUG2(ql4_printk(KERN_ERR, ha, 3827 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Adapter boot "
3345 "%s: Failed Boot options : 0x%x\n", 3828 "options : 0x%x\n", __func__, val));
3346 __func__, val));
3347 ret = QLA_ERROR; 3829 ret = QLA_ERROR;
3348 goto exit_boot_info; 3830 goto exit_boot_info;
3349 } 3831 }
@@ -3388,9 +3870,8 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
3388 } 3870 }
3389 /* Check Boot Mode */ 3871 /* Check Boot Mode */
3390 if (!(buf[1] & 0x07)) { 3872 if (!(buf[1] & 0x07)) {
3391 DEBUG2(ql4_printk(KERN_INFO, ha, 3873 DEBUG2(ql4_printk(KERN_INFO, ha, "Firmware boot options"
3392 "Failed: Boot options : 0x%x\n", 3874 " : 0x%x\n", buf[1]));
3393 buf[1]));
3394 ret = QLA_ERROR; 3875 ret = QLA_ERROR;
3395 goto exit_boot_info_free; 3876 goto exit_boot_info_free;
3396 } 3877 }
@@ -3411,12 +3892,11 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[])
3411 " target ID %d\n", __func__, ddb_index[0], 3892 " target ID %d\n", __func__, ddb_index[0],
3412 ddb_index[1])); 3893 ddb_index[1]));
3413 3894
3414 ha->pri_ddb_idx = ddb_index[0];
3415 ha->sec_ddb_idx = ddb_index[1];
3416
3417exit_boot_info_free: 3895exit_boot_info_free:
3418 dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma); 3896 dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma);
3419exit_boot_info: 3897exit_boot_info:
3898 ha->pri_ddb_idx = ddb_index[0];
3899 ha->sec_ddb_idx = ddb_index[1];
3420 return ret; 3900 return ret;
3421} 3901}
3422 3902
@@ -3497,8 +3977,8 @@ static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
3497 3977
3498 if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry, 3978 if (qla4xxx_bootdb_by_index(ha, fw_ddb_entry,
3499 fw_ddb_entry_dma, ddb_index)) { 3979 fw_ddb_entry_dma, ddb_index)) {
3500 DEBUG2(ql4_printk(KERN_ERR, ha, 3980 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: No Flash DDB found at "
3501 "%s: Flash DDB read Failed\n", __func__)); 3981 "index [%d]\n", __func__, ddb_index));
3502 ret = QLA_ERROR; 3982 ret = QLA_ERROR;
3503 goto exit_boot_target; 3983 goto exit_boot_target;
3504 } 3984 }
@@ -3576,8 +4056,8 @@ static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
3576 ddb_index[1] = 0xffff; 4056 ddb_index[1] = 0xffff;
3577 ret = get_fw_boot_info(ha, ddb_index); 4057 ret = get_fw_boot_info(ha, ddb_index);
3578 if (ret != QLA_SUCCESS) { 4058 if (ret != QLA_SUCCESS) {
3579 DEBUG2(ql4_printk(KERN_ERR, ha, 4059 DEBUG2(ql4_printk(KERN_INFO, ha,
3580 "%s: Failed to set boot info.\n", __func__)); 4060 "%s: No boot target configured.\n", __func__));
3581 return ret; 4061 return ret;
3582 } 4062 }
3583 4063
@@ -3590,8 +4070,8 @@ static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
3590 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess), 4070 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
3591 ddb_index[0]); 4071 ddb_index[0]);
3592 if (rval != QLA_SUCCESS) { 4072 if (rval != QLA_SUCCESS) {
3593 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get " 4073 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Primary boot target not "
3594 "primary target\n", __func__)); 4074 "configured\n", __func__));
3595 } else 4075 } else
3596 ret = QLA_SUCCESS; 4076 ret = QLA_SUCCESS;
3597 4077
@@ -3602,8 +4082,8 @@ sec_target:
3602 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess), 4082 rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
3603 ddb_index[1]); 4083 ddb_index[1]);
3604 if (rval != QLA_SUCCESS) { 4084 if (rval != QLA_SUCCESS) {
3605 DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get " 4085 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Secondary boot target not"
3606 "secondary target\n", __func__)); 4086 " configured\n", __func__));
3607 } else 4087 } else
3608 ret = QLA_SUCCESS; 4088 ret = QLA_SUCCESS;
3609 4089
@@ -3772,11 +4252,13 @@ static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry,
3772 sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr); 4252 sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr);
3773 4253
3774 tddb->port = le16_to_cpu(fw_ddb_entry->port); 4254 tddb->port = le16_to_cpu(fw_ddb_entry->port);
4255 memcpy(&tddb->isid[0], &fw_ddb_entry->isid[0], sizeof(tddb->isid));
3775} 4256}
3776 4257
3777static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, 4258static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
3778 struct ql4_tuple_ddb *old_tddb, 4259 struct ql4_tuple_ddb *old_tddb,
3779 struct ql4_tuple_ddb *new_tddb) 4260 struct ql4_tuple_ddb *new_tddb,
4261 uint8_t is_isid_compare)
3780{ 4262{
3781 if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name)) 4263 if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name))
3782 return QLA_ERROR; 4264 return QLA_ERROR;
@@ -3787,6 +4269,26 @@ static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha,
3787 if (old_tddb->port != new_tddb->port) 4269 if (old_tddb->port != new_tddb->port)
3788 return QLA_ERROR; 4270 return QLA_ERROR;
3789 4271
4272 /* For multi sessions, driver generates the ISID, so do not compare
4273 * ISID in reset path since it would be a comparision between the
4274 * driver generated ISID and firmware generated ISID. This could
4275 * lead to adding duplicated DDBs in the list as driver generated
4276 * ISID would not match firmware generated ISID.
4277 */
4278 if (is_isid_compare) {
4279 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: old ISID [%02x%02x%02x"
4280 "%02x%02x%02x] New ISID [%02x%02x%02x%02x%02x%02x]\n",
4281 __func__, old_tddb->isid[5], old_tddb->isid[4],
4282 old_tddb->isid[3], old_tddb->isid[2], old_tddb->isid[1],
4283 old_tddb->isid[0], new_tddb->isid[5], new_tddb->isid[4],
4284 new_tddb->isid[3], new_tddb->isid[2], new_tddb->isid[1],
4285 new_tddb->isid[0]));
4286
4287 if (memcmp(&old_tddb->isid[0], &new_tddb->isid[0],
4288 sizeof(old_tddb->isid)))
4289 return QLA_ERROR;
4290 }
4291
3790 DEBUG2(ql4_printk(KERN_INFO, ha, 4292 DEBUG2(ql4_printk(KERN_INFO, ha,
3791 "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]", 4293 "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]",
3792 old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr, 4294 old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr,
@@ -3829,7 +4331,7 @@ static int qla4xxx_is_session_exists(struct scsi_qla_host *ha,
3829 continue; 4331 continue;
3830 4332
3831 qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); 4333 qla4xxx_get_param_ddb(ddb_entry, tmp_tddb);
3832 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) { 4334 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, false)) {
3833 ret = QLA_SUCCESS; /* found */ 4335 ret = QLA_SUCCESS; /* found */
3834 goto exit_check; 4336 goto exit_check;
3835 } 4337 }
@@ -3872,7 +4374,7 @@ static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
3872 4374
3873 list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { 4375 list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
3874 qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb); 4376 qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb);
3875 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) { 4377 if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb, true)) {
3876 ret = QLA_SUCCESS; /* found */ 4378 ret = QLA_SUCCESS; /* found */
3877 goto exit_check; 4379 goto exit_check;
3878 } 4380 }
@@ -4038,6 +4540,10 @@ static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
4038 if (ret == QLA_ERROR) 4540 if (ret == QLA_ERROR)
4039 break; 4541 break;
4040 4542
4543 /* Ignore DDB if invalid state (unassigned) */
4544 if (state == DDB_DS_UNASSIGNED)
4545 goto continue_next_st;
4546
4041 /* Check if ST, add to the list_st */ 4547 /* Check if ST, add to the list_st */
4042 if (strlen((char *) fw_ddb_entry->iscsi_name) != 0) 4548 if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
4043 goto continue_next_st; 4549 goto continue_next_st;
@@ -4397,6 +4903,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
4397 4903
4398 spin_lock_init(&ha->hardware_lock); 4904 spin_lock_init(&ha->hardware_lock);
4399 4905
4906 /* Initialize work list */
4907 INIT_LIST_HEAD(&ha->work_list);
4908
4400 /* Allocate dma buffers */ 4909 /* Allocate dma buffers */
4401 if (qla4xxx_mem_alloc(ha)) { 4910 if (qla4xxx_mem_alloc(ha)) {
4402 ql4_printk(KERN_WARNING, ha, 4911 ql4_printk(KERN_WARNING, ha,
@@ -4524,8 +5033,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
4524 ha->patch_number, ha->build_number); 5033 ha->patch_number, ha->build_number);
4525 5034
4526 if (qla4xxx_setup_boot_info(ha)) 5035 if (qla4xxx_setup_boot_info(ha))
4527 ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n", 5036 ql4_printk(KERN_ERR, ha,
4528 __func__); 5037 "%s: No iSCSI boot target configured\n", __func__);
4529 5038
4530 /* Perform the build ddb list and login to each */ 5039 /* Perform the build ddb list and login to each */
4531 qla4xxx_build_ddb_list(ha, INIT_ADAPTER); 5040 qla4xxx_build_ddb_list(ha, INIT_ADAPTER);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index 133989b3a9f4..ede9af944141 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,4 +5,4 @@
5 * See LICENSE.qla4xxx for copyright and licensing details. 5 * See LICENSE.qla4xxx for copyright and licensing details.
6 */ 6 */
7 7
8#define QLA4XXX_DRIVER_VERSION "5.02.00-k12" 8#define QLA4XXX_DRIVER_VERSION "5.02.00-k15"