diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 23 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 20 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 94 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 7 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 68 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 36 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 30 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 4 |
10 files changed, 240 insertions, 51 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 420238cc794e..114bc5a81171 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1838,26 +1838,33 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) | |||
1838 | 1838 | ||
1839 | qla24xx_disable_vp(vha); | 1839 | qla24xx_disable_vp(vha); |
1840 | 1840 | ||
1841 | vha->flags.delete_progress = 1; | ||
1842 | |||
1841 | fc_remove_host(vha->host); | 1843 | fc_remove_host(vha->host); |
1842 | 1844 | ||
1843 | scsi_remove_host(vha->host); | 1845 | scsi_remove_host(vha->host); |
1844 | 1846 | ||
1845 | qla2x00_free_fcports(vha); | 1847 | if (vha->timer_active) { |
1848 | qla2x00_vp_stop_timer(vha); | ||
1849 | DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]" | ||
1850 | " = %p has stopped\n", vha->host_no, vha->vp_idx, vha)); | ||
1851 | } | ||
1846 | 1852 | ||
1847 | qla24xx_deallocate_vp_id(vha); | 1853 | qla24xx_deallocate_vp_id(vha); |
1848 | 1854 | ||
1855 | /* No pending activities shall be there on the vha now */ | ||
1856 | DEBUG(msleep(random32()%10)); /* Just to see if something falls on | ||
1857 | * the net we have placed below */ | ||
1858 | |||
1859 | BUG_ON(atomic_read(&vha->vref_count)); | ||
1860 | |||
1861 | qla2x00_free_fcports(vha); | ||
1862 | |||
1849 | mutex_lock(&ha->vport_lock); | 1863 | mutex_lock(&ha->vport_lock); |
1850 | ha->cur_vport_count--; | 1864 | ha->cur_vport_count--; |
1851 | clear_bit(vha->vp_idx, ha->vp_idx_map); | 1865 | clear_bit(vha->vp_idx, ha->vp_idx_map); |
1852 | mutex_unlock(&ha->vport_lock); | 1866 | mutex_unlock(&ha->vport_lock); |
1853 | 1867 | ||
1854 | if (vha->timer_active) { | ||
1855 | qla2x00_vp_stop_timer(vha); | ||
1856 | DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " | ||
1857 | "has stopped\n", | ||
1858 | vha->host_no, vha->vp_idx, vha)); | ||
1859 | } | ||
1860 | |||
1861 | if (vha->req->id && !ha->flags.cpu_affinity_enabled) { | 1868 | if (vha->req->id && !ha->flags.cpu_affinity_enabled) { |
1862 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) | 1869 | if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) |
1863 | qla_printk(KERN_WARNING, ha, | 1870 | qla_printk(KERN_WARNING, ha, |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 6cfc28a25eb3..b74e6b5743dc 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h | |||
@@ -29,8 +29,6 @@ | |||
29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ | 29 | /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ |
30 | /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */ | 30 | /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */ |
31 | 31 | ||
32 | /* #define QL_PRINTK_BUF */ /* Captures printk to buffer */ | ||
33 | |||
34 | /* | 32 | /* |
35 | * Macros use for debugging the driver. | 33 | * Macros use for debugging the driver. |
36 | */ | 34 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3a432ea0c7a3..d2a4e1530708 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2641,6 +2641,7 @@ struct qla_hw_data { | |||
2641 | #define MBX_UPDATE_FLASH_ACTIVE 3 | 2641 | #define MBX_UPDATE_FLASH_ACTIVE 3 |
2642 | 2642 | ||
2643 | struct mutex vport_lock; /* Virtual port synchronization */ | 2643 | struct mutex vport_lock; /* Virtual port synchronization */ |
2644 | spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */ | ||
2644 | struct completion mbx_cmd_comp; /* Serialize mbx access */ | 2645 | struct completion mbx_cmd_comp; /* Serialize mbx access */ |
2645 | struct completion mbx_intr_comp; /* Used for completion notification */ | 2646 | struct completion mbx_intr_comp; /* Used for completion notification */ |
2646 | struct completion dcbx_comp; /* For set port config notification */ | 2647 | struct completion dcbx_comp; /* For set port config notification */ |
@@ -2828,6 +2829,7 @@ typedef struct scsi_qla_host { | |||
2828 | uint32_t management_server_logged_in :1; | 2829 | uint32_t management_server_logged_in :1; |
2829 | uint32_t process_response_queue :1; | 2830 | uint32_t process_response_queue :1; |
2830 | uint32_t difdix_supported:1; | 2831 | uint32_t difdix_supported:1; |
2832 | uint32_t delete_progress:1; | ||
2831 | } flags; | 2833 | } flags; |
2832 | 2834 | ||
2833 | atomic_t loop_state; | 2835 | atomic_t loop_state; |
@@ -2922,6 +2924,8 @@ typedef struct scsi_qla_host { | |||
2922 | struct req_que *req; | 2924 | struct req_que *req; |
2923 | int fw_heartbeat_counter; | 2925 | int fw_heartbeat_counter; |
2924 | int seconds_since_last_heartbeat; | 2926 | int seconds_since_last_heartbeat; |
2927 | |||
2928 | atomic_t vref_count; | ||
2925 | } scsi_qla_host_t; | 2929 | } scsi_qla_host_t; |
2926 | 2930 | ||
2927 | /* | 2931 | /* |
@@ -2932,6 +2936,22 @@ typedef struct scsi_qla_host { | |||
2932 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ | 2936 | test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ |
2933 | atomic_read(&ha->loop_state) == LOOP_DOWN) | 2937 | atomic_read(&ha->loop_state) == LOOP_DOWN) |
2934 | 2938 | ||
2939 | #define QLA_VHA_MARK_BUSY(__vha, __bail) do { \ | ||
2940 | atomic_inc(&__vha->vref_count); \ | ||
2941 | mb(); \ | ||
2942 | if (__vha->flags.delete_progress) { \ | ||
2943 | atomic_dec(&__vha->vref_count); \ | ||
2944 | __bail = 1; \ | ||
2945 | } else { \ | ||
2946 | __bail = 0; \ | ||
2947 | } \ | ||
2948 | } while (0) | ||
2949 | |||
2950 | #define QLA_VHA_MARK_NOT_BUSY(__vha) do { \ | ||
2951 | atomic_dec(&__vha->vref_count); \ | ||
2952 | } while (0) | ||
2953 | |||
2954 | |||
2935 | #define qla_printk(level, ha, format, arg...) \ | 2955 | #define qla_printk(level, ha, format, arg...) \ |
2936 | dev_printk(level , &((ha)->pdev->dev) , format , ## arg) | 2956 | dev_printk(level , &((ha)->pdev->dev) , format , ## arg) |
2937 | 2957 | ||
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d863ed2619b5..9c383baebe27 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -69,21 +69,29 @@ qla2x00_ctx_sp_free(srb_t *sp) | |||
69 | { | 69 | { |
70 | struct srb_ctx *ctx = sp->ctx; | 70 | struct srb_ctx *ctx = sp->ctx; |
71 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | 71 | struct srb_iocb *iocb = ctx->u.iocb_cmd; |
72 | struct scsi_qla_host *vha = sp->fcport->vha; | ||
72 | 73 | ||
73 | del_timer_sync(&iocb->timer); | 74 | del_timer_sync(&iocb->timer); |
74 | kfree(iocb); | 75 | kfree(iocb); |
75 | kfree(ctx); | 76 | kfree(ctx); |
76 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); | 77 | mempool_free(sp, sp->fcport->vha->hw->srb_mempool); |
78 | |||
79 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
77 | } | 80 | } |
78 | 81 | ||
79 | inline srb_t * | 82 | inline srb_t * |
80 | qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | 83 | qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, |
81 | unsigned long tmo) | 84 | unsigned long tmo) |
82 | { | 85 | { |
83 | srb_t *sp; | 86 | srb_t *sp = NULL; |
84 | struct qla_hw_data *ha = vha->hw; | 87 | struct qla_hw_data *ha = vha->hw; |
85 | struct srb_ctx *ctx; | 88 | struct srb_ctx *ctx; |
86 | struct srb_iocb *iocb; | 89 | struct srb_iocb *iocb; |
90 | uint8_t bail; | ||
91 | |||
92 | QLA_VHA_MARK_BUSY(vha, bail); | ||
93 | if (bail) | ||
94 | return NULL; | ||
87 | 95 | ||
88 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); | 96 | sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); |
89 | if (!sp) | 97 | if (!sp) |
@@ -116,6 +124,8 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, | |||
116 | iocb->timer.function = qla2x00_ctx_sp_timeout; | 124 | iocb->timer.function = qla2x00_ctx_sp_timeout; |
117 | add_timer(&iocb->timer); | 125 | add_timer(&iocb->timer); |
118 | done: | 126 | done: |
127 | if (!sp) | ||
128 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
119 | return sp; | 129 | return sp; |
120 | } | 130 | } |
121 | 131 | ||
@@ -1777,11 +1787,15 @@ qla2x00_init_rings(scsi_qla_host_t *vha) | |||
1777 | qla2x00_init_response_q_entries(rsp); | 1787 | qla2x00_init_response_q_entries(rsp); |
1778 | } | 1788 | } |
1779 | 1789 | ||
1790 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
1780 | /* Clear RSCN queue. */ | 1791 | /* Clear RSCN queue. */ |
1781 | list_for_each_entry(vp, &ha->vp_list, list) { | 1792 | list_for_each_entry(vp, &ha->vp_list, list) { |
1782 | vp->rscn_in_ptr = 0; | 1793 | vp->rscn_in_ptr = 0; |
1783 | vp->rscn_out_ptr = 0; | 1794 | vp->rscn_out_ptr = 0; |
1784 | } | 1795 | } |
1796 | |||
1797 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
1798 | |||
1785 | ha->isp_ops->config_rings(vha); | 1799 | ha->isp_ops->config_rings(vha); |
1786 | 1800 | ||
1787 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1801 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
@@ -3218,12 +3232,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
3218 | /* Bypass virtual ports of the same host. */ | 3232 | /* Bypass virtual ports of the same host. */ |
3219 | found = 0; | 3233 | found = 0; |
3220 | if (ha->num_vhosts) { | 3234 | if (ha->num_vhosts) { |
3235 | unsigned long flags; | ||
3236 | |||
3237 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
3221 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 3238 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { |
3222 | if (new_fcport->d_id.b24 == vp->d_id.b24) { | 3239 | if (new_fcport->d_id.b24 == vp->d_id.b24) { |
3223 | found = 1; | 3240 | found = 1; |
3224 | break; | 3241 | break; |
3225 | } | 3242 | } |
3226 | } | 3243 | } |
3244 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
3245 | |||
3227 | if (found) | 3246 | if (found) |
3228 | continue; | 3247 | continue; |
3229 | } | 3248 | } |
@@ -3343,6 +3362,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | |||
3343 | struct qla_hw_data *ha = vha->hw; | 3362 | struct qla_hw_data *ha = vha->hw; |
3344 | struct scsi_qla_host *vp; | 3363 | struct scsi_qla_host *vp; |
3345 | struct scsi_qla_host *tvp; | 3364 | struct scsi_qla_host *tvp; |
3365 | unsigned long flags = 0; | ||
3346 | 3366 | ||
3347 | rval = QLA_SUCCESS; | 3367 | rval = QLA_SUCCESS; |
3348 | 3368 | ||
@@ -3367,6 +3387,8 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | |||
3367 | /* Check for loop ID being already in use. */ | 3387 | /* Check for loop ID being already in use. */ |
3368 | found = 0; | 3388 | found = 0; |
3369 | fcport = NULL; | 3389 | fcport = NULL; |
3390 | |||
3391 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
3370 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 3392 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { |
3371 | list_for_each_entry(fcport, &vp->vp_fcports, list) { | 3393 | list_for_each_entry(fcport, &vp->vp_fcports, list) { |
3372 | if (fcport->loop_id == dev->loop_id && | 3394 | if (fcport->loop_id == dev->loop_id && |
@@ -3379,6 +3401,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) | |||
3379 | if (found) | 3401 | if (found) |
3380 | break; | 3402 | break; |
3381 | } | 3403 | } |
3404 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
3382 | 3405 | ||
3383 | /* If not in use then it is free to use. */ | 3406 | /* If not in use then it is free to use. */ |
3384 | if (!found) { | 3407 | if (!found) { |
@@ -3791,14 +3814,27 @@ void | |||
3791 | qla2x00_update_fcports(scsi_qla_host_t *base_vha) | 3814 | qla2x00_update_fcports(scsi_qla_host_t *base_vha) |
3792 | { | 3815 | { |
3793 | fc_port_t *fcport; | 3816 | fc_port_t *fcport; |
3794 | struct scsi_qla_host *tvp, *vha; | 3817 | struct scsi_qla_host *vha; |
3818 | struct qla_hw_data *ha = base_vha->hw; | ||
3819 | unsigned long flags; | ||
3795 | 3820 | ||
3821 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
3796 | /* Go with deferred removal of rport references. */ | 3822 | /* Go with deferred removal of rport references. */ |
3797 | list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list) | 3823 | list_for_each_entry(vha, &base_vha->hw->vp_list, list) { |
3798 | list_for_each_entry(fcport, &vha->vp_fcports, list) | 3824 | atomic_inc(&vha->vref_count); |
3825 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | ||
3799 | if (fcport && fcport->drport && | 3826 | if (fcport && fcport->drport && |
3800 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) | 3827 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) { |
3828 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
3829 | |||
3801 | qla2x00_rport_del(fcport); | 3830 | qla2x00_rport_del(fcport); |
3831 | |||
3832 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
3833 | } | ||
3834 | } | ||
3835 | atomic_dec(&vha->vref_count); | ||
3836 | } | ||
3837 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
3802 | } | 3838 | } |
3803 | 3839 | ||
3804 | void | 3840 | void |
@@ -3806,7 +3842,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | |||
3806 | { | 3842 | { |
3807 | struct qla_hw_data *ha = vha->hw; | 3843 | struct qla_hw_data *ha = vha->hw; |
3808 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); | 3844 | struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); |
3809 | struct scsi_qla_host *tvp; | 3845 | unsigned long flags; |
3810 | 3846 | ||
3811 | vha->flags.online = 0; | 3847 | vha->flags.online = 0; |
3812 | ha->flags.chip_reset_done = 0; | 3848 | ha->flags.chip_reset_done = 0; |
@@ -3824,8 +3860,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) | |||
3824 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { | 3860 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
3825 | atomic_set(&vha->loop_state, LOOP_DOWN); | 3861 | atomic_set(&vha->loop_state, LOOP_DOWN); |
3826 | qla2x00_mark_all_devices_lost(vha, 0); | 3862 | qla2x00_mark_all_devices_lost(vha, 0); |
3827 | list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list) | 3863 | |
3864 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
3865 | list_for_each_entry(vp, &base_vha->hw->vp_list, list) { | ||
3866 | atomic_inc(&vp->vref_count); | ||
3867 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
3868 | |||
3828 | qla2x00_mark_all_devices_lost(vp, 0); | 3869 | qla2x00_mark_all_devices_lost(vp, 0); |
3870 | |||
3871 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
3872 | atomic_dec(&vp->vref_count); | ||
3873 | } | ||
3874 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
3829 | } else { | 3875 | } else { |
3830 | if (!atomic_read(&vha->loop_down_timer)) | 3876 | if (!atomic_read(&vha->loop_down_timer)) |
3831 | atomic_set(&vha->loop_down_timer, | 3877 | atomic_set(&vha->loop_down_timer, |
@@ -3862,8 +3908,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3862 | uint8_t status = 0; | 3908 | uint8_t status = 0; |
3863 | struct qla_hw_data *ha = vha->hw; | 3909 | struct qla_hw_data *ha = vha->hw; |
3864 | struct scsi_qla_host *vp; | 3910 | struct scsi_qla_host *vp; |
3865 | struct scsi_qla_host *tvp; | ||
3866 | struct req_que *req = ha->req_q_map[0]; | 3911 | struct req_que *req = ha->req_q_map[0]; |
3912 | unsigned long flags; | ||
3867 | 3913 | ||
3868 | if (vha->flags.online) { | 3914 | if (vha->flags.online) { |
3869 | qla2x00_abort_isp_cleanup(vha); | 3915 | qla2x00_abort_isp_cleanup(vha); |
@@ -3970,10 +4016,21 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) | |||
3970 | DEBUG(printk(KERN_INFO | 4016 | DEBUG(printk(KERN_INFO |
3971 | "qla2x00_abort_isp(%ld): succeeded.\n", | 4017 | "qla2x00_abort_isp(%ld): succeeded.\n", |
3972 | vha->host_no)); | 4018 | vha->host_no)); |
3973 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 4019 | |
3974 | if (vp->vp_idx) | 4020 | spin_lock_irqsave(&ha->vport_slock, flags); |
4021 | list_for_each_entry(vp, &ha->vp_list, list) { | ||
4022 | if (vp->vp_idx) { | ||
4023 | atomic_inc(&vp->vref_count); | ||
4024 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
4025 | |||
3975 | qla2x00_vp_abort_isp(vp); | 4026 | qla2x00_vp_abort_isp(vp); |
4027 | |||
4028 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
4029 | atomic_dec(&vp->vref_count); | ||
4030 | } | ||
3976 | } | 4031 | } |
4032 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
4033 | |||
3977 | } else { | 4034 | } else { |
3978 | qla_printk(KERN_INFO, ha, | 4035 | qla_printk(KERN_INFO, ha, |
3979 | "qla2x00_abort_isp: **** FAILED ****\n"); | 4036 | "qla2x00_abort_isp: **** FAILED ****\n"); |
@@ -5185,7 +5242,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) | |||
5185 | struct req_que *req = ha->req_q_map[0]; | 5242 | struct req_que *req = ha->req_q_map[0]; |
5186 | struct rsp_que *rsp = ha->rsp_q_map[0]; | 5243 | struct rsp_que *rsp = ha->rsp_q_map[0]; |
5187 | struct scsi_qla_host *vp; | 5244 | struct scsi_qla_host *vp; |
5188 | struct scsi_qla_host *tvp; | 5245 | unsigned long flags; |
5189 | 5246 | ||
5190 | status = qla2x00_init_rings(vha); | 5247 | status = qla2x00_init_rings(vha); |
5191 | if (!status) { | 5248 | if (!status) { |
@@ -5272,10 +5329,21 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) | |||
5272 | DEBUG(printk(KERN_INFO | 5329 | DEBUG(printk(KERN_INFO |
5273 | "qla82xx_restart_isp(%ld): succeeded.\n", | 5330 | "qla82xx_restart_isp(%ld): succeeded.\n", |
5274 | vha->host_no)); | 5331 | vha->host_no)); |
5275 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 5332 | |
5276 | if (vp->vp_idx) | 5333 | spin_lock_irqsave(&ha->vport_slock, flags); |
5334 | list_for_each_entry(vp, &ha->vp_list, list) { | ||
5335 | if (vp->vp_idx) { | ||
5336 | atomic_inc(&vp->vref_count); | ||
5337 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
5338 | |||
5277 | qla2x00_vp_abort_isp(vp); | 5339 | qla2x00_vp_abort_isp(vp); |
5340 | |||
5341 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
5342 | atomic_dec(&vp->vref_count); | ||
5343 | } | ||
5278 | } | 5344 | } |
5345 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
5346 | |||
5279 | } else { | 5347 | } else { |
5280 | qla_printk(KERN_INFO, ha, | 5348 | qla_printk(KERN_INFO, ha, |
5281 | "qla82xx_restart_isp: **** FAILED ****\n"); | 5349 | "qla82xx_restart_isp: **** FAILED ****\n"); |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6982ba70e12a..28f65be19dad 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1706,19 +1706,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1706 | cp->result = DID_ERROR << 16; | 1706 | cp->result = DID_ERROR << 16; |
1707 | break; | 1707 | break; |
1708 | } | 1708 | } |
1709 | } else if (!lscsi_status) { | 1709 | } else { |
1710 | DEBUG2(qla_printk(KERN_INFO, ha, | 1710 | DEBUG2(qla_printk(KERN_INFO, ha, |
1711 | "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x " | 1711 | "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x " |
1712 | "of 0x%x bytes).\n", vha->host_no, cp->device->id, | 1712 | "of 0x%x bytes).\n", vha->host_no, cp->device->id, |
1713 | cp->device->lun, resid, scsi_bufflen(cp))); | 1713 | cp->device->lun, resid, scsi_bufflen(cp))); |
1714 | 1714 | ||
1715 | cp->result = DID_ERROR << 16; | 1715 | cp->result = DID_ERROR << 16 | lscsi_status; |
1716 | break; | 1716 | goto check_scsi_status; |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | cp->result = DID_OK << 16 | lscsi_status; | 1719 | cp->result = DID_OK << 16 | lscsi_status; |
1720 | logit = 0; | 1720 | logit = 0; |
1721 | 1721 | ||
1722 | check_scsi_status: | ||
1722 | /* | 1723 | /* |
1723 | * Check to see if SCSI Status is non zero. If so report SCSI | 1724 | * Check to see if SCSI Status is non zero. If so report SCSI |
1724 | * Status. | 1725 | * Status. |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 6009b0c69488..a595ec8264f8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -2913,7 +2913,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
2913 | uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); | 2913 | uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); |
2914 | struct qla_hw_data *ha = vha->hw; | 2914 | struct qla_hw_data *ha = vha->hw; |
2915 | scsi_qla_host_t *vp; | 2915 | scsi_qla_host_t *vp; |
2916 | scsi_qla_host_t *tvp; | 2916 | unsigned long flags; |
2917 | 2917 | ||
2918 | if (rptid_entry->entry_status != 0) | 2918 | if (rptid_entry->entry_status != 0) |
2919 | return; | 2919 | return; |
@@ -2945,9 +2945,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, | |||
2945 | return; | 2945 | return; |
2946 | } | 2946 | } |
2947 | 2947 | ||
2948 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) | 2948 | spin_lock_irqsave(&ha->vport_slock, flags); |
2949 | list_for_each_entry(vp, &ha->vp_list, list) | ||
2949 | if (vp_idx == vp->vp_idx) | 2950 | if (vp_idx == vp->vp_idx) |
2950 | break; | 2951 | break; |
2952 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
2953 | |||
2951 | if (!vp) | 2954 | if (!vp) |
2952 | return; | 2955 | return; |
2953 | 2956 | ||
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 987c5b0ca78e..2b69392a71a1 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -30,6 +30,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | |||
30 | { | 30 | { |
31 | uint32_t vp_id; | 31 | uint32_t vp_id; |
32 | struct qla_hw_data *ha = vha->hw; | 32 | struct qla_hw_data *ha = vha->hw; |
33 | unsigned long flags; | ||
33 | 34 | ||
34 | /* Find an empty slot and assign an vp_id */ | 35 | /* Find an empty slot and assign an vp_id */ |
35 | mutex_lock(&ha->vport_lock); | 36 | mutex_lock(&ha->vport_lock); |
@@ -44,7 +45,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) | |||
44 | set_bit(vp_id, ha->vp_idx_map); | 45 | set_bit(vp_id, ha->vp_idx_map); |
45 | ha->num_vhosts++; | 46 | ha->num_vhosts++; |
46 | vha->vp_idx = vp_id; | 47 | vha->vp_idx = vp_id; |
48 | |||
49 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
47 | list_add_tail(&vha->list, &ha->vp_list); | 50 | list_add_tail(&vha->list, &ha->vp_list); |
51 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
52 | |||
48 | mutex_unlock(&ha->vport_lock); | 53 | mutex_unlock(&ha->vport_lock); |
49 | return vp_id; | 54 | return vp_id; |
50 | } | 55 | } |
@@ -54,12 +59,31 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) | |||
54 | { | 59 | { |
55 | uint16_t vp_id; | 60 | uint16_t vp_id; |
56 | struct qla_hw_data *ha = vha->hw; | 61 | struct qla_hw_data *ha = vha->hw; |
62 | unsigned long flags = 0; | ||
57 | 63 | ||
58 | mutex_lock(&ha->vport_lock); | 64 | mutex_lock(&ha->vport_lock); |
65 | /* | ||
66 | * Wait for all pending activities to finish before removing vport from | ||
67 | * the list. | ||
68 | * Lock needs to be held for safe removal from the list (it | ||
69 | * ensures no active vp_list traversal while the vport is removed | ||
70 | * from the queue) | ||
71 | */ | ||
72 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
73 | while (atomic_read(&vha->vref_count)) { | ||
74 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
75 | |||
76 | msleep(500); | ||
77 | |||
78 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
79 | } | ||
80 | list_del(&vha->list); | ||
81 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
82 | |||
59 | vp_id = vha->vp_idx; | 83 | vp_id = vha->vp_idx; |
60 | ha->num_vhosts--; | 84 | ha->num_vhosts--; |
61 | clear_bit(vp_id, ha->vp_idx_map); | 85 | clear_bit(vp_id, ha->vp_idx_map); |
62 | list_del(&vha->list); | 86 | |
63 | mutex_unlock(&ha->vport_lock); | 87 | mutex_unlock(&ha->vport_lock); |
64 | } | 88 | } |
65 | 89 | ||
@@ -68,12 +92,17 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) | |||
68 | { | 92 | { |
69 | scsi_qla_host_t *vha; | 93 | scsi_qla_host_t *vha; |
70 | struct scsi_qla_host *tvha; | 94 | struct scsi_qla_host *tvha; |
95 | unsigned long flags; | ||
71 | 96 | ||
97 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
72 | /* Locate matching device in database. */ | 98 | /* Locate matching device in database. */ |
73 | list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { | 99 | list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { |
74 | if (!memcmp(port_name, vha->port_name, WWN_SIZE)) | 100 | if (!memcmp(port_name, vha->port_name, WWN_SIZE)) { |
101 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
75 | return vha; | 102 | return vha; |
103 | } | ||
76 | } | 104 | } |
105 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
77 | return NULL; | 106 | return NULL; |
78 | } | 107 | } |
79 | 108 | ||
@@ -93,6 +122,12 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) | |||
93 | static void | 122 | static void |
94 | qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) | 123 | qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) |
95 | { | 124 | { |
125 | /* | ||
126 | * !!! NOTE !!! | ||
127 | * This function, if called in contexts other than vp create, disable | ||
128 | * or delete, please make sure this is synchronized with the | ||
129 | * delete thread. | ||
130 | */ | ||
96 | fc_port_t *fcport; | 131 | fc_port_t *fcport; |
97 | 132 | ||
98 | list_for_each_entry(fcport, &vha->vp_fcports, list) { | 133 | list_for_each_entry(fcport, &vha->vp_fcports, list) { |
@@ -100,7 +135,6 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) | |||
100 | "loop_id=0x%04x :%x\n", | 135 | "loop_id=0x%04x :%x\n", |
101 | vha->host_no, fcport->loop_id, fcport->vp_idx)); | 136 | vha->host_no, fcport->loop_id, fcport->vp_idx)); |
102 | 137 | ||
103 | atomic_set(&fcport->state, FCS_DEVICE_DEAD); | ||
104 | qla2x00_mark_device_lost(vha, fcport, 0, 0); | 138 | qla2x00_mark_device_lost(vha, fcport, 0, 0); |
105 | atomic_set(&fcport->state, FCS_UNCONFIGURED); | 139 | atomic_set(&fcport->state, FCS_UNCONFIGURED); |
106 | } | 140 | } |
@@ -194,12 +228,17 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) | |||
194 | void | 228 | void |
195 | qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) | 229 | qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) |
196 | { | 230 | { |
197 | scsi_qla_host_t *vha, *tvha; | 231 | scsi_qla_host_t *vha; |
198 | struct qla_hw_data *ha = rsp->hw; | 232 | struct qla_hw_data *ha = rsp->hw; |
199 | int i = 0; | 233 | int i = 0; |
234 | unsigned long flags; | ||
200 | 235 | ||
201 | list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { | 236 | spin_lock_irqsave(&ha->vport_slock, flags); |
237 | list_for_each_entry(vha, &ha->vp_list, list) { | ||
202 | if (vha->vp_idx) { | 238 | if (vha->vp_idx) { |
239 | atomic_inc(&vha->vref_count); | ||
240 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
241 | |||
203 | switch (mb[0]) { | 242 | switch (mb[0]) { |
204 | case MBA_LIP_OCCURRED: | 243 | case MBA_LIP_OCCURRED: |
205 | case MBA_LOOP_UP: | 244 | case MBA_LOOP_UP: |
@@ -215,9 +254,13 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) | |||
215 | qla2x00_async_event(vha, rsp, mb); | 254 | qla2x00_async_event(vha, rsp, mb); |
216 | break; | 255 | break; |
217 | } | 256 | } |
257 | |||
258 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
259 | atomic_dec(&vha->vref_count); | ||
218 | } | 260 | } |
219 | i++; | 261 | i++; |
220 | } | 262 | } |
263 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
221 | } | 264 | } |
222 | 265 | ||
223 | int | 266 | int |
@@ -297,7 +340,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) | |||
297 | int ret; | 340 | int ret; |
298 | struct qla_hw_data *ha = vha->hw; | 341 | struct qla_hw_data *ha = vha->hw; |
299 | scsi_qla_host_t *vp; | 342 | scsi_qla_host_t *vp; |
300 | struct scsi_qla_host *tvp; | 343 | unsigned long flags = 0; |
301 | 344 | ||
302 | if (vha->vp_idx) | 345 | if (vha->vp_idx) |
303 | return; | 346 | return; |
@@ -309,10 +352,19 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) | |||
309 | if (!(ha->current_topology & ISP_CFG_F)) | 352 | if (!(ha->current_topology & ISP_CFG_F)) |
310 | return; | 353 | return; |
311 | 354 | ||
312 | list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { | 355 | spin_lock_irqsave(&ha->vport_slock, flags); |
313 | if (vp->vp_idx) | 356 | list_for_each_entry(vp, &ha->vp_list, list) { |
357 | if (vp->vp_idx) { | ||
358 | atomic_inc(&vp->vref_count); | ||
359 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
360 | |||
314 | ret = qla2x00_do_dpc_vp(vp); | 361 | ret = qla2x00_do_dpc_vp(vp); |
362 | |||
363 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
364 | atomic_dec(&vp->vref_count); | ||
365 | } | ||
315 | } | 366 | } |
367 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
316 | } | 368 | } |
317 | 369 | ||
318 | int | 370 | int |
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 915b77a6e193..0a71cc71eab2 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -2672,6 +2672,19 @@ qla82xx_start_scsi(srb_t *sp) | |||
2672 | sufficient_dsds: | 2672 | sufficient_dsds: |
2673 | req_cnt = 1; | 2673 | req_cnt = 1; |
2674 | 2674 | ||
2675 | if (req->cnt < (req_cnt + 2)) { | ||
2676 | cnt = (uint16_t)RD_REG_DWORD_RELAXED( | ||
2677 | ®->req_q_out[0]); | ||
2678 | if (req->ring_index < cnt) | ||
2679 | req->cnt = cnt - req->ring_index; | ||
2680 | else | ||
2681 | req->cnt = req->length - | ||
2682 | (req->ring_index - cnt); | ||
2683 | } | ||
2684 | |||
2685 | if (req->cnt < (req_cnt + 2)) | ||
2686 | goto queuing_error; | ||
2687 | |||
2675 | ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); | 2688 | ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); |
2676 | if (!sp->ctx) { | 2689 | if (!sp->ctx) { |
2677 | DEBUG(printk(KERN_INFO | 2690 | DEBUG(printk(KERN_INFO |
@@ -3307,16 +3320,19 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha) | |||
3307 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3320 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
3308 | } | 3321 | } |
3309 | qla2xxx_wake_dpc(vha); | 3322 | qla2xxx_wake_dpc(vha); |
3323 | ha->flags.fw_hung = 1; | ||
3310 | if (ha->flags.mbox_busy) { | 3324 | if (ha->flags.mbox_busy) { |
3311 | ha->flags.fw_hung = 1; | ||
3312 | ha->flags.mbox_int = 1; | 3325 | ha->flags.mbox_int = 1; |
3313 | DEBUG2(qla_printk(KERN_ERR, ha, | 3326 | DEBUG2(qla_printk(KERN_ERR, ha, |
3314 | "Due to fw hung, doing premature " | 3327 | "Due to fw hung, doing premature " |
3315 | "completion of mbx command\n")); | 3328 | "completion of mbx command\n")); |
3316 | complete(&ha->mbx_intr_comp); | 3329 | if (test_bit(MBX_INTR_WAIT, |
3330 | &ha->mbx_cmd_flags)) | ||
3331 | complete(&ha->mbx_intr_comp); | ||
3317 | } | 3332 | } |
3318 | } | 3333 | } |
3319 | } | 3334 | } else |
3335 | vha->seconds_since_last_heartbeat = 0; | ||
3320 | vha->fw_heartbeat_counter = fw_heartbeat_counter; | 3336 | vha->fw_heartbeat_counter = fw_heartbeat_counter; |
3321 | } | 3337 | } |
3322 | 3338 | ||
@@ -3418,13 +3434,15 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3418 | "%s(): Adapter reset needed!\n", __func__); | 3434 | "%s(): Adapter reset needed!\n", __func__); |
3419 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); | 3435 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
3420 | qla2xxx_wake_dpc(vha); | 3436 | qla2xxx_wake_dpc(vha); |
3437 | ha->flags.fw_hung = 1; | ||
3421 | if (ha->flags.mbox_busy) { | 3438 | if (ha->flags.mbox_busy) { |
3422 | ha->flags.fw_hung = 1; | ||
3423 | ha->flags.mbox_int = 1; | 3439 | ha->flags.mbox_int = 1; |
3424 | DEBUG2(qla_printk(KERN_ERR, ha, | 3440 | DEBUG2(qla_printk(KERN_ERR, ha, |
3425 | "Need reset, doing premature " | 3441 | "Need reset, doing premature " |
3426 | "completion of mbx command\n")); | 3442 | "completion of mbx command\n")); |
3427 | complete(&ha->mbx_intr_comp); | 3443 | if (test_bit(MBX_INTR_WAIT, |
3444 | &ha->mbx_cmd_flags)) | ||
3445 | complete(&ha->mbx_intr_comp); | ||
3428 | } | 3446 | } |
3429 | } else { | 3447 | } else { |
3430 | qla82xx_check_fw_alive(vha); | 3448 | qla82xx_check_fw_alive(vha); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8c80b49ac1c4..1e4bff695254 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -2341,16 +2341,28 @@ probe_out: | |||
2341 | static void | 2341 | static void |
2342 | qla2x00_remove_one(struct pci_dev *pdev) | 2342 | qla2x00_remove_one(struct pci_dev *pdev) |
2343 | { | 2343 | { |
2344 | scsi_qla_host_t *base_vha, *vha, *temp; | 2344 | scsi_qla_host_t *base_vha, *vha; |
2345 | struct qla_hw_data *ha; | 2345 | struct qla_hw_data *ha; |
2346 | unsigned long flags; | ||
2346 | 2347 | ||
2347 | base_vha = pci_get_drvdata(pdev); | 2348 | base_vha = pci_get_drvdata(pdev); |
2348 | ha = base_vha->hw; | 2349 | ha = base_vha->hw; |
2349 | 2350 | ||
2350 | list_for_each_entry_safe(vha, temp, &ha->vp_list, list) { | 2351 | spin_lock_irqsave(&ha->vport_slock, flags); |
2351 | if (vha && vha->fc_vport) | 2352 | list_for_each_entry(vha, &ha->vp_list, list) { |
2353 | atomic_inc(&vha->vref_count); | ||
2354 | |||
2355 | if (vha && vha->fc_vport) { | ||
2356 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
2357 | |||
2352 | fc_vport_terminate(vha->fc_vport); | 2358 | fc_vport_terminate(vha->fc_vport); |
2359 | |||
2360 | spin_lock_irqsave(&ha->vport_slock, flags); | ||
2361 | } | ||
2362 | |||
2363 | atomic_dec(&vha->vref_count); | ||
2353 | } | 2364 | } |
2365 | spin_unlock_irqrestore(&ha->vport_slock, flags); | ||
2354 | 2366 | ||
2355 | set_bit(UNLOADING, &base_vha->dpc_flags); | 2367 | set_bit(UNLOADING, &base_vha->dpc_flags); |
2356 | 2368 | ||
@@ -2975,10 +2987,17 @@ static struct qla_work_evt * | |||
2975 | qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) | 2987 | qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) |
2976 | { | 2988 | { |
2977 | struct qla_work_evt *e; | 2989 | struct qla_work_evt *e; |
2990 | uint8_t bail; | ||
2991 | |||
2992 | QLA_VHA_MARK_BUSY(vha, bail); | ||
2993 | if (bail) | ||
2994 | return NULL; | ||
2978 | 2995 | ||
2979 | e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); | 2996 | e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); |
2980 | if (!e) | 2997 | if (!e) { |
2998 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
2981 | return NULL; | 2999 | return NULL; |
3000 | } | ||
2982 | 3001 | ||
2983 | INIT_LIST_HEAD(&e->list); | 3002 | INIT_LIST_HEAD(&e->list); |
2984 | e->type = type; | 3003 | e->type = type; |
@@ -3135,6 +3154,9 @@ qla2x00_do_work(struct scsi_qla_host *vha) | |||
3135 | } | 3154 | } |
3136 | if (e->flags & QLA_EVT_FLAG_FREE) | 3155 | if (e->flags & QLA_EVT_FLAG_FREE) |
3137 | kfree(e); | 3156 | kfree(e); |
3157 | |||
3158 | /* For each work completed decrement vha ref count */ | ||
3159 | QLA_VHA_MARK_NOT_BUSY(vha); | ||
3138 | } | 3160 | } |
3139 | } | 3161 | } |
3140 | 3162 | ||
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e75ccb91317d..8edbccb3232d 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,9 +7,9 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.03.03-k0" | 10 | #define QLA2XXX_VERSION "8.03.04-k0" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 3 | 13 | #define QLA_DRIVER_MINOR_VER 3 |
14 | #define QLA_DRIVER_PATCH_VER 3 | 14 | #define QLA_DRIVER_PATCH_VER 4 |
15 | #define QLA_DRIVER_BETA_VER 0 | 15 | #define QLA_DRIVER_BETA_VER 0 |