diff options
author | Seokmann Ju <seokmann.ju@qlogic.com> | 2007-07-05 16:16:51 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-14 20:08:05 -0400 |
commit | 2c3dfe3f6ad8daff5acdb01713e4f2b116e78136 (patch) | |
tree | 8d95e2356c0f5121ceab48ab564d2796b6530d29 /drivers/scsi/qla2xxx/qla_os.c | |
parent | 968a5763fb7247feb0e69573a2975a7a0c094267 (diff) |
[SCSI] qla2xxx: add support for NPIV
Following patch adds support for NPIV (N-Port ID Virtualization) to the
qla2xxx.
- supported within switched-fabric topologies only.
- supports up to 63 virtual ports on each physical port.
Signed-off-by: Seokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 229 |
1 files changed, 133 insertions, 96 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 18baa5bf69c4..a8658b1d284f 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -29,8 +29,7 @@ static struct kmem_cache *srb_cachep; | |||
29 | /* | 29 | /* |
30 | * Ioctl related information. | 30 | * Ioctl related information. |
31 | */ | 31 | */ |
32 | static int num_hosts; | 32 | int num_hosts; |
33 | |||
34 | int ql2xlogintimeout = 20; | 33 | int ql2xlogintimeout = 20; |
35 | module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); | 34 | module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); |
36 | MODULE_PARM_DESC(ql2xlogintimeout, | 35 | MODULE_PARM_DESC(ql2xlogintimeout, |
@@ -112,7 +111,7 @@ static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); | |||
112 | static int qla2x00_change_queue_depth(struct scsi_device *, int); | 111 | static int qla2x00_change_queue_depth(struct scsi_device *, int); |
113 | static int qla2x00_change_queue_type(struct scsi_device *, int); | 112 | static int qla2x00_change_queue_type(struct scsi_device *, int); |
114 | 113 | ||
115 | static struct scsi_host_template qla2x00_driver_template = { | 114 | struct scsi_host_template qla2x00_driver_template = { |
116 | .module = THIS_MODULE, | 115 | .module = THIS_MODULE, |
117 | .name = QLA2XXX_DRIVER_NAME, | 116 | .name = QLA2XXX_DRIVER_NAME, |
118 | .queuecommand = qla2x00_queuecommand, | 117 | .queuecommand = qla2x00_queuecommand, |
@@ -143,7 +142,7 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
143 | .shost_attrs = qla2x00_host_attrs, | 142 | .shost_attrs = qla2x00_host_attrs, |
144 | }; | 143 | }; |
145 | 144 | ||
146 | static struct scsi_host_template qla24xx_driver_template = { | 145 | struct scsi_host_template qla24xx_driver_template = { |
147 | .module = THIS_MODULE, | 146 | .module = THIS_MODULE, |
148 | .name = QLA2XXX_DRIVER_NAME, | 147 | .name = QLA2XXX_DRIVER_NAME, |
149 | .queuecommand = qla24xx_queuecommand, | 148 | .queuecommand = qla24xx_queuecommand, |
@@ -171,21 +170,21 @@ static struct scsi_host_template qla24xx_driver_template = { | |||
171 | }; | 170 | }; |
172 | 171 | ||
173 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; | 172 | static struct scsi_transport_template *qla2xxx_transport_template = NULL; |
173 | struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; | ||
174 | 174 | ||
175 | /* TODO Convert to inlines | 175 | /* TODO Convert to inlines |
176 | * | 176 | * |
177 | * Timer routines | 177 | * Timer routines |
178 | */ | 178 | */ |
179 | #define WATCH_INTERVAL 1 /* number of seconds */ | ||
180 | 179 | ||
181 | static void qla2x00_timer(scsi_qla_host_t *); | 180 | void qla2x00_timer(scsi_qla_host_t *); |
182 | 181 | ||
183 | static __inline__ void qla2x00_start_timer(scsi_qla_host_t *, | 182 | __inline__ void qla2x00_start_timer(scsi_qla_host_t *, |
184 | void *, unsigned long); | 183 | void *, unsigned long); |
185 | static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long); | 184 | static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long); |
186 | static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *); | 185 | __inline__ void qla2x00_stop_timer(scsi_qla_host_t *); |
187 | 186 | ||
188 | static inline void | 187 | __inline__ void |
189 | qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval) | 188 | qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval) |
190 | { | 189 | { |
191 | init_timer(&ha->timer); | 190 | init_timer(&ha->timer); |
@@ -202,7 +201,7 @@ qla2x00_restart_timer(scsi_qla_host_t *ha, unsigned long interval) | |||
202 | mod_timer(&ha->timer, jiffies + interval * HZ); | 201 | mod_timer(&ha->timer, jiffies + interval * HZ); |
203 | } | 202 | } |
204 | 203 | ||
205 | static __inline__ void | 204 | __inline__ void |
206 | qla2x00_stop_timer(scsi_qla_host_t *ha) | 205 | qla2x00_stop_timer(scsi_qla_host_t *ha) |
207 | { | 206 | { |
208 | del_timer_sync(&ha->timer); | 207 | del_timer_sync(&ha->timer); |
@@ -213,8 +212,8 @@ static int qla2x00_do_dpc(void *data); | |||
213 | 212 | ||
214 | static void qla2x00_rst_aen(scsi_qla_host_t *); | 213 | static void qla2x00_rst_aen(scsi_qla_host_t *); |
215 | 214 | ||
216 | static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); | 215 | uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); |
217 | static void qla2x00_mem_free(scsi_qla_host_t *ha); | 216 | void qla2x00_mem_free(scsi_qla_host_t *ha); |
218 | static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); | 217 | static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); |
219 | static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); | 218 | static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); |
220 | static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); | 219 | static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); |
@@ -438,6 +437,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
438 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); | 437 | struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); |
439 | srb_t *sp; | 438 | srb_t *sp; |
440 | int rval; | 439 | int rval; |
440 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
441 | 441 | ||
442 | rval = fc_remote_port_chkready(rport); | 442 | rval = fc_remote_port_chkready(rport); |
443 | if (rval) { | 443 | if (rval) { |
@@ -453,7 +453,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
453 | 453 | ||
454 | if (atomic_read(&fcport->state) != FCS_ONLINE) { | 454 | if (atomic_read(&fcport->state) != FCS_ONLINE) { |
455 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || | 455 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || |
456 | atomic_read(&ha->loop_state) == LOOP_DEAD) { | 456 | atomic_read(&pha->loop_state) == LOOP_DEAD) { |
457 | cmd->result = DID_NO_CONNECT << 16; | 457 | cmd->result = DID_NO_CONNECT << 16; |
458 | goto qc24_fail_command; | 458 | goto qc24_fail_command; |
459 | } | 459 | } |
@@ -462,7 +462,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
462 | 462 | ||
463 | spin_unlock_irq(ha->host->host_lock); | 463 | spin_unlock_irq(ha->host->host_lock); |
464 | 464 | ||
465 | sp = qla2x00_get_new_sp(ha, fcport, cmd, done); | 465 | sp = qla2x00_get_new_sp(pha, fcport, cmd, done); |
466 | if (!sp) | 466 | if (!sp) |
467 | goto qc24_host_busy_lock; | 467 | goto qc24_host_busy_lock; |
468 | 468 | ||
@@ -475,8 +475,8 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
475 | return 0; | 475 | return 0; |
476 | 476 | ||
477 | qc24_host_busy_free_sp: | 477 | qc24_host_busy_free_sp: |
478 | qla2x00_sp_free_dma(ha, sp); | 478 | qla2x00_sp_free_dma(pha, sp); |
479 | mempool_free(sp, ha->srb_mempool); | 479 | mempool_free(sp, pha->srb_mempool); |
480 | 480 | ||
481 | qc24_host_busy_lock: | 481 | qc24_host_busy_lock: |
482 | spin_lock_irq(ha->host->host_lock); | 482 | spin_lock_irq(ha->host->host_lock); |
@@ -548,16 +548,17 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) | |||
548 | { | 548 | { |
549 | int return_status; | 549 | int return_status; |
550 | unsigned long wait_online; | 550 | unsigned long wait_online; |
551 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
551 | 552 | ||
552 | wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); | 553 | wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); |
553 | while (((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || | 554 | while (((test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags)) || |
554 | test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || | 555 | test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags) || |
555 | test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) || | 556 | test_bit(ISP_ABORT_RETRY, &pha->dpc_flags) || |
556 | ha->dpc_active) && time_before(jiffies, wait_online)) { | 557 | pha->dpc_active) && time_before(jiffies, wait_online)) { |
557 | 558 | ||
558 | msleep(1000); | 559 | msleep(1000); |
559 | } | 560 | } |
560 | if (ha->flags.online) | 561 | if (pha->flags.online) |
561 | return_status = QLA_SUCCESS; | 562 | return_status = QLA_SUCCESS; |
562 | else | 563 | else |
563 | return_status = QLA_FUNCTION_FAILED; | 564 | return_status = QLA_FUNCTION_FAILED; |
@@ -588,14 +589,15 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) | |||
588 | { | 589 | { |
589 | int return_status = QLA_SUCCESS; | 590 | int return_status = QLA_SUCCESS; |
590 | unsigned long loop_timeout ; | 591 | unsigned long loop_timeout ; |
592 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
591 | 593 | ||
592 | /* wait for 5 min at the max for loop to be ready */ | 594 | /* wait for 5 min at the max for loop to be ready */ |
593 | loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); | 595 | loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); |
594 | 596 | ||
595 | while ((!atomic_read(&ha->loop_down_timer) && | 597 | while ((!atomic_read(&pha->loop_down_timer) && |
596 | atomic_read(&ha->loop_state) == LOOP_DOWN) || | 598 | atomic_read(&pha->loop_state) == LOOP_DOWN) || |
597 | atomic_read(&ha->loop_state) != LOOP_READY) { | 599 | atomic_read(&pha->loop_state) != LOOP_READY) { |
598 | if (atomic_read(&ha->loop_state) == LOOP_DEAD) { | 600 | if (atomic_read(&pha->loop_state) == LOOP_DEAD) { |
599 | return_status = QLA_FUNCTION_FAILED; | 601 | return_status = QLA_FUNCTION_FAILED; |
600 | break; | 602 | break; |
601 | } | 603 | } |
@@ -650,6 +652,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
650 | unsigned long serial; | 652 | unsigned long serial; |
651 | unsigned long flags; | 653 | unsigned long flags; |
652 | int wait = 0; | 654 | int wait = 0; |
655 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
653 | 656 | ||
654 | qla2x00_block_error_handler(cmd); | 657 | qla2x00_block_error_handler(cmd); |
655 | 658 | ||
@@ -663,9 +666,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
663 | serial = cmd->serial_number; | 666 | serial = cmd->serial_number; |
664 | 667 | ||
665 | /* Check active list for command command. */ | 668 | /* Check active list for command command. */ |
666 | spin_lock_irqsave(&ha->hardware_lock, flags); | 669 | spin_lock_irqsave(&pha->hardware_lock, flags); |
667 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { | 670 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { |
668 | sp = ha->outstanding_cmds[i]; | 671 | sp = pha->outstanding_cmds[i]; |
669 | 672 | ||
670 | if (sp == NULL) | 673 | if (sp == NULL) |
671 | continue; | 674 | continue; |
@@ -677,7 +680,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
677 | __func__, ha->host_no, sp, serial)); | 680 | __func__, ha->host_no, sp, serial)); |
678 | DEBUG3(qla2x00_print_scsi_cmd(cmd)); | 681 | DEBUG3(qla2x00_print_scsi_cmd(cmd)); |
679 | 682 | ||
680 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 683 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
681 | if (ha->isp_ops.abort_command(ha, sp)) { | 684 | if (ha->isp_ops.abort_command(ha, sp)) { |
682 | DEBUG2(printk("%s(%ld): abort_command " | 685 | DEBUG2(printk("%s(%ld): abort_command " |
683 | "mbx failed.\n", __func__, ha->host_no)); | 686 | "mbx failed.\n", __func__, ha->host_no)); |
@@ -686,11 +689,11 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) | |||
686 | "mbx success.\n", __func__, ha->host_no)); | 689 | "mbx success.\n", __func__, ha->host_no)); |
687 | wait = 1; | 690 | wait = 1; |
688 | } | 691 | } |
689 | spin_lock_irqsave(&ha->hardware_lock, flags); | 692 | spin_lock_irqsave(&pha->hardware_lock, flags); |
690 | 693 | ||
691 | break; | 694 | break; |
692 | } | 695 | } |
693 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 696 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
694 | 697 | ||
695 | /* Wait for the command to be returned. */ | 698 | /* Wait for the command to be returned. */ |
696 | if (wait) { | 699 | if (wait) { |
@@ -731,6 +734,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) | |||
731 | srb_t *sp; | 734 | srb_t *sp; |
732 | struct scsi_cmnd *cmd; | 735 | struct scsi_cmnd *cmd; |
733 | unsigned long flags; | 736 | unsigned long flags; |
737 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
734 | 738 | ||
735 | status = 0; | 739 | status = 0; |
736 | 740 | ||
@@ -739,19 +743,20 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) | |||
739 | * array | 743 | * array |
740 | */ | 744 | */ |
741 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | 745 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { |
742 | spin_lock_irqsave(&ha->hardware_lock, flags); | 746 | spin_lock_irqsave(&pha->hardware_lock, flags); |
743 | sp = ha->outstanding_cmds[cnt]; | 747 | sp = pha->outstanding_cmds[cnt]; |
744 | if (sp) { | 748 | if (sp) { |
745 | cmd = sp->cmd; | 749 | cmd = sp->cmd; |
746 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 750 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
747 | if (cmd->device->id == t) { | 751 | if (cmd->device->id == t && |
752 | ha->vp_idx == sp->ha->vp_idx) { | ||
748 | if (!qla2x00_eh_wait_on_command(ha, cmd)) { | 753 | if (!qla2x00_eh_wait_on_command(ha, cmd)) { |
749 | status = 1; | 754 | status = 1; |
750 | break; | 755 | break; |
751 | } | 756 | } |
752 | } | 757 | } |
753 | } else { | 758 | } else { |
754 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 759 | spin_unlock_irqrestore(&pha->hardware_lock, flags); |
755 | } | 760 | } |
756 | } | 761 | } |
757 | return (status); | 762 | return (status); |
@@ -782,14 +787,12 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) | |||
782 | { | 787 | { |
783 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 788 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
784 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 789 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
785 | int ret; | 790 | int ret = FAILED; |
786 | unsigned int id, lun; | 791 | unsigned int id, lun; |
787 | unsigned long serial; | 792 | unsigned long serial; |
788 | 793 | ||
789 | qla2x00_block_error_handler(cmd); | 794 | qla2x00_block_error_handler(cmd); |
790 | 795 | ||
791 | ret = FAILED; | ||
792 | |||
793 | id = cmd->device->id; | 796 | id = cmd->device->id; |
794 | lun = cmd->device->lun; | 797 | lun = cmd->device->lun; |
795 | serial = cmd->serial_number; | 798 | serial = cmd->serial_number; |
@@ -912,15 +915,14 @@ static int | |||
912 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | 915 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) |
913 | { | 916 | { |
914 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 917 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
918 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
915 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 919 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
916 | int ret; | 920 | int ret = FAILED; |
917 | unsigned int id, lun; | 921 | unsigned int id, lun; |
918 | unsigned long serial; | 922 | unsigned long serial; |
919 | 923 | ||
920 | qla2x00_block_error_handler(cmd); | 924 | qla2x00_block_error_handler(cmd); |
921 | 925 | ||
922 | ret = FAILED; | ||
923 | |||
924 | id = cmd->device->id; | 926 | id = cmd->device->id; |
925 | lun = cmd->device->lun; | 927 | lun = cmd->device->lun; |
926 | serial = cmd->serial_number; | 928 | serial = cmd->serial_number; |
@@ -944,7 +946,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
944 | goto eh_bus_reset_done; | 946 | goto eh_bus_reset_done; |
945 | 947 | ||
946 | /* Flush outstanding commands. */ | 948 | /* Flush outstanding commands. */ |
947 | if (!qla2x00_eh_wait_for_pending_commands(ha)) | 949 | if (!qla2x00_eh_wait_for_pending_commands(pha)) |
948 | ret = FAILED; | 950 | ret = FAILED; |
949 | 951 | ||
950 | eh_bus_reset_done: | 952 | eh_bus_reset_done: |
@@ -974,14 +976,13 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
974 | { | 976 | { |
975 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 977 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
976 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; | 978 | fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; |
977 | int ret; | 979 | int ret = FAILED; |
978 | unsigned int id, lun; | 980 | unsigned int id, lun; |
979 | unsigned long serial; | 981 | unsigned long serial; |
982 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
980 | 983 | ||
981 | qla2x00_block_error_handler(cmd); | 984 | qla2x00_block_error_handler(cmd); |
982 | 985 | ||
983 | ret = FAILED; | ||
984 | |||
985 | id = cmd->device->id; | 986 | id = cmd->device->id; |
986 | lun = cmd->device->lun; | 987 | lun = cmd->device->lun; |
987 | serial = cmd->serial_number; | 988 | serial = cmd->serial_number; |
@@ -1004,21 +1005,24 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1004 | * while dpc is stuck for the mailbox to complete. | 1005 | * while dpc is stuck for the mailbox to complete. |
1005 | */ | 1006 | */ |
1006 | qla2x00_wait_for_loop_ready(ha); | 1007 | qla2x00_wait_for_loop_ready(ha); |
1007 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 1008 | set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); |
1008 | if (qla2x00_abort_isp(ha)) { | 1009 | if (qla2x00_abort_isp(pha)) { |
1009 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 1010 | clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); |
1010 | /* failed. schedule dpc to try */ | 1011 | /* failed. schedule dpc to try */ |
1011 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 1012 | set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags); |
1012 | 1013 | ||
1013 | if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) | 1014 | if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) |
1014 | goto eh_host_reset_lock; | 1015 | goto eh_host_reset_lock; |
1015 | } | 1016 | } |
1016 | clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 1017 | clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); |
1017 | 1018 | ||
1018 | /* Waiting for our command in done_queue to be returned to OS.*/ | 1019 | /* Waiting for our command in done_queue to be returned to OS.*/ |
1019 | if (qla2x00_eh_wait_for_pending_commands(ha)) | 1020 | if (qla2x00_eh_wait_for_pending_commands(pha)) |
1020 | ret = SUCCESS; | 1021 | ret = SUCCESS; |
1021 | 1022 | ||
1023 | if (ha->parent) | ||
1024 | qla2x00_vp_abort_isp(ha); | ||
1025 | |||
1022 | eh_host_reset_lock: | 1026 | eh_host_reset_lock: |
1023 | qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, | 1027 | qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, |
1024 | (ret == FAILED) ? "failed" : "succeded"); | 1028 | (ret == FAILED) ? "failed" : "succeded"); |
@@ -1435,6 +1439,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1435 | ha->host = host; | 1439 | ha->host = host; |
1436 | ha->host_no = host->host_no; | 1440 | ha->host_no = host->host_no; |
1437 | sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); | 1441 | sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); |
1442 | ha->parent = NULL; | ||
1438 | 1443 | ||
1439 | /* Set ISP-type information. */ | 1444 | /* Set ISP-type information. */ |
1440 | qla2x00_set_isp_flags(ha); | 1445 | qla2x00_set_isp_flags(ha); |
@@ -1452,7 +1457,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1452 | 1457 | ||
1453 | ha->prev_topology = 0; | 1458 | ha->prev_topology = 0; |
1454 | ha->init_cb_size = sizeof(init_cb_t); | 1459 | ha->init_cb_size = sizeof(init_cb_t); |
1455 | ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; | 1460 | ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx; |
1456 | ha->link_data_rate = PORT_SPEED_UNKNOWN; | 1461 | ha->link_data_rate = PORT_SPEED_UNKNOWN; |
1457 | ha->optrom_size = OPTROM_SIZE_2300; | 1462 | ha->optrom_size = OPTROM_SIZE_2300; |
1458 | 1463 | ||
@@ -1524,8 +1529,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1524 | ha->request_q_length = REQUEST_ENTRY_CNT_24XX; | 1529 | ha->request_q_length = REQUEST_ENTRY_CNT_24XX; |
1525 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; | 1530 | ha->response_q_length = RESPONSE_ENTRY_CNT_2300; |
1526 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; | 1531 | ha->last_loop_id = SNS_LAST_LOOP_ID_2300; |
1527 | ha->init_cb_size = sizeof(struct init_cb_24xx); | 1532 | ha->init_cb_size = sizeof(struct mid_init_cb_24xx); |
1528 | ha->mgmt_svr_loop_id = 10; | 1533 | ha->mgmt_svr_loop_id = 10 + ha->vp_idx; |
1529 | ha->isp_ops.pci_config = qla24xx_pci_config; | 1534 | ha->isp_ops.pci_config = qla24xx_pci_config; |
1530 | ha->isp_ops.reset_chip = qla24xx_reset_chip; | 1535 | ha->isp_ops.reset_chip = qla24xx_reset_chip; |
1531 | ha->isp_ops.chip_diag = qla24xx_chip_diag; | 1536 | ha->isp_ops.chip_diag = qla24xx_chip_diag; |
@@ -1563,10 +1568,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1563 | ha->instance = num_hosts; | 1568 | ha->instance = num_hosts; |
1564 | 1569 | ||
1565 | init_MUTEX(&ha->mbx_cmd_sem); | 1570 | init_MUTEX(&ha->mbx_cmd_sem); |
1571 | init_MUTEX(&ha->vport_sem); | ||
1566 | init_MUTEX_LOCKED(&ha->mbx_intr_sem); | 1572 | init_MUTEX_LOCKED(&ha->mbx_intr_sem); |
1567 | 1573 | ||
1568 | INIT_LIST_HEAD(&ha->list); | 1574 | INIT_LIST_HEAD(&ha->list); |
1569 | INIT_LIST_HEAD(&ha->fcports); | 1575 | INIT_LIST_HEAD(&ha->fcports); |
1576 | INIT_LIST_HEAD(&ha->vp_list); | ||
1577 | |||
1578 | set_bit(0, (unsigned long *) ha->vp_idx_map); | ||
1570 | 1579 | ||
1571 | qla2x00_config_dma_addressing(ha); | 1580 | qla2x00_config_dma_addressing(ha); |
1572 | if (qla2x00_mem_alloc(ha)) { | 1581 | if (qla2x00_mem_alloc(ha)) { |
@@ -1789,7 +1798,8 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, | |||
1789 | void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, | 1798 | void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, |
1790 | int do_login, int defer) | 1799 | int do_login, int defer) |
1791 | { | 1800 | { |
1792 | if (atomic_read(&fcport->state) == FCS_ONLINE) | 1801 | if (atomic_read(&fcport->state) == FCS_ONLINE && |
1802 | ha->vp_idx == fcport->vp_idx) | ||
1793 | qla2x00_schedule_rport_del(ha, fcport, defer); | 1803 | qla2x00_schedule_rport_del(ha, fcport, defer); |
1794 | 1804 | ||
1795 | /* | 1805 | /* |
@@ -1840,19 +1850,23 @@ void | |||
1840 | qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) | 1850 | qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) |
1841 | { | 1851 | { |
1842 | fc_port_t *fcport; | 1852 | fc_port_t *fcport; |
1853 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
1843 | 1854 | ||
1844 | list_for_each_entry(fcport, &ha->fcports, list) { | 1855 | list_for_each_entry(fcport, &pha->fcports, list) { |
1845 | if (fcport->port_type != FCT_TARGET) | 1856 | if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx) |
1846 | continue; | 1857 | continue; |
1847 | |||
1848 | /* | 1858 | /* |
1849 | * No point in marking the device as lost, if the device is | 1859 | * No point in marking the device as lost, if the device is |
1850 | * already DEAD. | 1860 | * already DEAD. |
1851 | */ | 1861 | */ |
1852 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) | 1862 | if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) |
1853 | continue; | 1863 | continue; |
1854 | if (atomic_read(&fcport->state) == FCS_ONLINE) | 1864 | if (atomic_read(&fcport->state) == FCS_ONLINE) { |
1855 | qla2x00_schedule_rport_del(ha, fcport, defer); | 1865 | if (defer) |
1866 | qla2x00_schedule_rport_del(ha, fcport, defer); | ||
1867 | else if (ha->vp_idx == fcport->vp_idx) | ||
1868 | qla2x00_schedule_rport_del(ha, fcport, defer); | ||
1869 | } | ||
1856 | atomic_set(&fcport->state, FCS_DEVICE_LOST); | 1870 | atomic_set(&fcport->state, FCS_DEVICE_LOST); |
1857 | } | 1871 | } |
1858 | 1872 | ||
@@ -1868,7 +1882,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) | |||
1868 | * 0 = success. | 1882 | * 0 = success. |
1869 | * 1 = failure. | 1883 | * 1 = failure. |
1870 | */ | 1884 | */ |
1871 | static uint8_t | 1885 | uint8_t |
1872 | qla2x00_mem_alloc(scsi_qla_host_t *ha) | 1886 | qla2x00_mem_alloc(scsi_qla_host_t *ha) |
1873 | { | 1887 | { |
1874 | char name[16]; | 1888 | char name[16]; |
@@ -1920,33 +1934,33 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) | |||
1920 | continue; | 1934 | continue; |
1921 | } | 1935 | } |
1922 | 1936 | ||
1923 | snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, | 1937 | /* get consistent memory allocated for init control block */ |
1924 | ha->host_no); | 1938 | ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, |
1925 | ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, | 1939 | ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); |
1926 | DMA_POOL_SIZE, 8, 0); | 1940 | if (ha->init_cb == NULL) { |
1927 | if (ha->s_dma_pool == NULL) { | ||
1928 | qla_printk(KERN_WARNING, ha, | 1941 | qla_printk(KERN_WARNING, ha, |
1929 | "Memory Allocation failed - s_dma_pool\n"); | 1942 | "Memory Allocation failed - init_cb\n"); |
1930 | 1943 | ||
1931 | qla2x00_mem_free(ha); | 1944 | qla2x00_mem_free(ha); |
1932 | msleep(100); | 1945 | msleep(100); |
1933 | 1946 | ||
1934 | continue; | 1947 | continue; |
1935 | } | 1948 | } |
1949 | memset(ha->init_cb, 0, ha->init_cb_size); | ||
1936 | 1950 | ||
1937 | /* get consistent memory allocated for init control block */ | 1951 | snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, |
1938 | ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, | 1952 | ha->host_no); |
1939 | &ha->init_cb_dma); | 1953 | ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, |
1940 | if (ha->init_cb == NULL) { | 1954 | DMA_POOL_SIZE, 8, 0); |
1955 | if (ha->s_dma_pool == NULL) { | ||
1941 | qla_printk(KERN_WARNING, ha, | 1956 | qla_printk(KERN_WARNING, ha, |
1942 | "Memory Allocation failed - init_cb\n"); | 1957 | "Memory Allocation failed - s_dma_pool\n"); |
1943 | 1958 | ||
1944 | qla2x00_mem_free(ha); | 1959 | qla2x00_mem_free(ha); |
1945 | msleep(100); | 1960 | msleep(100); |
1946 | 1961 | ||
1947 | continue; | 1962 | continue; |
1948 | } | 1963 | } |
1949 | memset(ha->init_cb, 0, ha->init_cb_size); | ||
1950 | 1964 | ||
1951 | if (qla2x00_allocate_sp_pool(ha)) { | 1965 | if (qla2x00_allocate_sp_pool(ha)) { |
1952 | qla_printk(KERN_WARNING, ha, | 1966 | qla_printk(KERN_WARNING, ha, |
@@ -2052,7 +2066,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) | |||
2052 | * Input: | 2066 | * Input: |
2053 | * ha = adapter block pointer. | 2067 | * ha = adapter block pointer. |
2054 | */ | 2068 | */ |
2055 | static void | 2069 | void |
2056 | qla2x00_mem_free(scsi_qla_host_t *ha) | 2070 | qla2x00_mem_free(scsi_qla_host_t *ha) |
2057 | { | 2071 | { |
2058 | struct list_head *fcpl, *fcptemp; | 2072 | struct list_head *fcpl, *fcptemp; |
@@ -2088,12 +2102,13 @@ qla2x00_mem_free(scsi_qla_host_t *ha) | |||
2088 | if (ha->ms_iocb) | 2102 | if (ha->ms_iocb) |
2089 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); | 2103 | dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); |
2090 | 2104 | ||
2091 | if (ha->init_cb) | ||
2092 | dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); | ||
2093 | |||
2094 | if (ha->s_dma_pool) | 2105 | if (ha->s_dma_pool) |
2095 | dma_pool_destroy(ha->s_dma_pool); | 2106 | dma_pool_destroy(ha->s_dma_pool); |
2096 | 2107 | ||
2108 | if (ha->init_cb) | ||
2109 | dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, | ||
2110 | ha->init_cb, ha->init_cb_dma); | ||
2111 | |||
2097 | if (ha->gid_list) | 2112 | if (ha->gid_list) |
2098 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, | 2113 | dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, |
2099 | ha->gid_list_dma); | 2114 | ha->gid_list_dma); |
@@ -2199,6 +2214,7 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha) | |||
2199 | static int | 2214 | static int |
2200 | qla2x00_do_dpc(void *data) | 2215 | qla2x00_do_dpc(void *data) |
2201 | { | 2216 | { |
2217 | int rval; | ||
2202 | scsi_qla_host_t *ha; | 2218 | scsi_qla_host_t *ha; |
2203 | fc_port_t *fcport; | 2219 | fc_port_t *fcport; |
2204 | uint8_t status; | 2220 | uint8_t status; |
@@ -2347,7 +2363,7 @@ qla2x00_do_dpc(void *data) | |||
2347 | if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, | 2363 | if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, |
2348 | &ha->dpc_flags))) { | 2364 | &ha->dpc_flags))) { |
2349 | 2365 | ||
2350 | qla2x00_loop_resync(ha); | 2366 | rval = qla2x00_loop_resync(ha); |
2351 | 2367 | ||
2352 | clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); | 2368 | clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); |
2353 | } | 2369 | } |
@@ -2374,6 +2390,8 @@ qla2x00_do_dpc(void *data) | |||
2374 | if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) | 2390 | if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) |
2375 | ha->isp_ops.beacon_blink(ha); | 2391 | ha->isp_ops.beacon_blink(ha); |
2376 | 2392 | ||
2393 | qla2x00_do_dpc_all_vps(ha); | ||
2394 | |||
2377 | ha->dpc_active = 0; | 2395 | ha->dpc_active = 0; |
2378 | } /* End of while(1) */ | 2396 | } /* End of while(1) */ |
2379 | 2397 | ||
@@ -2452,7 +2470,7 @@ qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp) | |||
2452 | * | 2470 | * |
2453 | * Context: Interrupt | 2471 | * Context: Interrupt |
2454 | ***************************************************************************/ | 2472 | ***************************************************************************/ |
2455 | static void | 2473 | void |
2456 | qla2x00_timer(scsi_qla_host_t *ha) | 2474 | qla2x00_timer(scsi_qla_host_t *ha) |
2457 | { | 2475 | { |
2458 | unsigned long cpu_flags = 0; | 2476 | unsigned long cpu_flags = 0; |
@@ -2461,6 +2479,7 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2461 | int index; | 2479 | int index; |
2462 | srb_t *sp; | 2480 | srb_t *sp; |
2463 | int t; | 2481 | int t; |
2482 | scsi_qla_host_t *pha = to_qla_parent(ha); | ||
2464 | 2483 | ||
2465 | /* | 2484 | /* |
2466 | * Ports - Port down timer. | 2485 | * Ports - Port down timer. |
@@ -2506,23 +2525,29 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2506 | atomic_set(&ha->loop_state, LOOP_DEAD); | 2525 | atomic_set(&ha->loop_state, LOOP_DEAD); |
2507 | 2526 | ||
2508 | /* Schedule an ISP abort to return any tape commands. */ | 2527 | /* Schedule an ISP abort to return any tape commands. */ |
2509 | spin_lock_irqsave(&ha->hardware_lock, cpu_flags); | 2528 | /* NPIV - scan physical port only */ |
2510 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; | 2529 | if (!ha->parent) { |
2511 | index++) { | 2530 | spin_lock_irqsave(&ha->hardware_lock, |
2512 | fc_port_t *sfcp; | 2531 | cpu_flags); |
2532 | for (index = 1; | ||
2533 | index < MAX_OUTSTANDING_COMMANDS; | ||
2534 | index++) { | ||
2535 | fc_port_t *sfcp; | ||
2536 | |||
2537 | sp = ha->outstanding_cmds[index]; | ||
2538 | if (!sp) | ||
2539 | continue; | ||
2540 | sfcp = sp->fcport; | ||
2541 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) | ||
2542 | continue; | ||
2513 | 2543 | ||
2514 | sp = ha->outstanding_cmds[index]; | 2544 | set_bit(ISP_ABORT_NEEDED, |
2515 | if (!sp) | 2545 | &ha->dpc_flags); |
2516 | continue; | 2546 | break; |
2517 | sfcp = sp->fcport; | 2547 | } |
2518 | if (!(sfcp->flags & FCF_TAPE_PRESENT)) | 2548 | spin_unlock_irqrestore(&ha->hardware_lock, |
2519 | continue; | 2549 | cpu_flags); |
2520 | |||
2521 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | ||
2522 | break; | ||
2523 | } | 2550 | } |
2524 | spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); | ||
2525 | |||
2526 | set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); | 2551 | set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); |
2527 | start_dpc++; | 2552 | start_dpc++; |
2528 | } | 2553 | } |
@@ -2566,8 +2591,9 @@ qla2x00_timer(scsi_qla_host_t *ha) | |||
2566 | test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || | 2591 | test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || |
2567 | test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || | 2592 | test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || |
2568 | test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || | 2593 | test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || |
2594 | test_bit(VP_DPC_NEEDED, &ha->dpc_flags) || | ||
2569 | test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) | 2595 | test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) |
2570 | qla2xxx_wake_dpc(ha); | 2596 | qla2xxx_wake_dpc(pha); |
2571 | 2597 | ||
2572 | qla2x00_restart_timer(ha, WATCH_INTERVAL); | 2598 | qla2x00_restart_timer(ha, WATCH_INTERVAL); |
2573 | } | 2599 | } |
@@ -2711,14 +2737,24 @@ qla2x00_module_init(void) | |||
2711 | 2737 | ||
2712 | qla2xxx_transport_template = | 2738 | qla2xxx_transport_template = |
2713 | fc_attach_transport(&qla2xxx_transport_functions); | 2739 | fc_attach_transport(&qla2xxx_transport_functions); |
2714 | if (!qla2xxx_transport_template) | 2740 | if (!qla2xxx_transport_template) { |
2741 | kmem_cache_destroy(srb_cachep); | ||
2742 | return -ENODEV; | ||
2743 | } | ||
2744 | qla2xxx_transport_vport_template = | ||
2745 | fc_attach_transport(&qla2xxx_transport_vport_functions); | ||
2746 | if (!qla2xxx_transport_vport_template) { | ||
2747 | kmem_cache_destroy(srb_cachep); | ||
2748 | fc_release_transport(qla2xxx_transport_template); | ||
2715 | return -ENODEV; | 2749 | return -ENODEV; |
2750 | } | ||
2716 | 2751 | ||
2717 | printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); | 2752 | printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); |
2718 | ret = pci_register_driver(&qla2xxx_pci_driver); | 2753 | ret = pci_register_driver(&qla2xxx_pci_driver); |
2719 | if (ret) { | 2754 | if (ret) { |
2720 | kmem_cache_destroy(srb_cachep); | 2755 | kmem_cache_destroy(srb_cachep); |
2721 | fc_release_transport(qla2xxx_transport_template); | 2756 | fc_release_transport(qla2xxx_transport_template); |
2757 | fc_release_transport(qla2xxx_transport_vport_template); | ||
2722 | } | 2758 | } |
2723 | return ret; | 2759 | return ret; |
2724 | } | 2760 | } |
@@ -2733,6 +2769,7 @@ qla2x00_module_exit(void) | |||
2733 | qla2x00_release_firmware(); | 2769 | qla2x00_release_firmware(); |
2734 | kmem_cache_destroy(srb_cachep); | 2770 | kmem_cache_destroy(srb_cachep); |
2735 | fc_release_transport(qla2xxx_transport_template); | 2771 | fc_release_transport(qla2xxx_transport_template); |
2772 | fc_release_transport(qla2xxx_transport_vport_template); | ||
2736 | } | 2773 | } |
2737 | 2774 | ||
2738 | module_init(qla2x00_module_init); | 2775 | module_init(qla2x00_module_init); |