Skip to content

Commit

Permalink
[SCSI] qla2xxx: Fix vport delete issues
Browse files Browse the repository at this point in the history
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Arun Easi authored and James Bottomley committed Sep 5, 2010
1 parent 2e4c332 commit feafb7b
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 36 deletions.
23 changes: 15 additions & 8 deletions drivers/scsi/qla2xxx/qla_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1838,26 +1838,33 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)

qla24xx_disable_vp(vha);

vha->flags.delete_progress = 1;

fc_remove_host(vha->host);

scsi_remove_host(vha->host);

qla2x00_free_fcports(vha);
if (vha->timer_active) {
qla2x00_vp_stop_timer(vha);
DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
" = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
}

qla24xx_deallocate_vp_id(vha);

/* No pending activities shall be there on the vha now */
DEBUG(msleep(random32()%10)); /* Just to see if something falls on
* the net we have placed below */

BUG_ON(atomic_read(&vha->vref_count));

qla2x00_free_fcports(vha);

mutex_lock(&ha->vport_lock);
ha->cur_vport_count--;
clear_bit(vha->vp_idx, ha->vp_idx_map);
mutex_unlock(&ha->vport_lock);

if (vha->timer_active) {
qla2x00_vp_stop_timer(vha);
DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
"has stopped\n",
vha->host_no, vha->vp_idx, vha));
}

if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
qla_printk(KERN_WARNING, ha,
Expand Down
2 changes: 0 additions & 2 deletions drivers/scsi/qla2xxx/qla_dbg.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */

/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */

/*
* Macros use for debugging the driver.
*/
Expand Down
20 changes: 20 additions & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2641,6 +2641,7 @@ struct qla_hw_data {
#define MBX_UPDATE_FLASH_ACTIVE 3

struct mutex vport_lock; /* Virtual port synchronization */
spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */
struct completion mbx_cmd_comp; /* Serialize mbx access */
struct completion mbx_intr_comp; /* Used for completion notification */
struct completion dcbx_comp; /* For set port config notification */
Expand Down Expand Up @@ -2828,6 +2829,7 @@ typedef struct scsi_qla_host {
uint32_t management_server_logged_in :1;
uint32_t process_response_queue :1;
uint32_t difdix_supported:1;
uint32_t delete_progress:1;
} flags;

atomic_t loop_state;
Expand Down Expand Up @@ -2922,6 +2924,8 @@ typedef struct scsi_qla_host {
struct req_que *req;
int fw_heartbeat_counter;
int seconds_since_last_heartbeat;

atomic_t vref_count;
} scsi_qla_host_t;

/*
Expand All @@ -2932,6 +2936,22 @@ typedef struct scsi_qla_host {
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
atomic_read(&ha->loop_state) == LOOP_DOWN)

#define QLA_VHA_MARK_BUSY(__vha, __bail) do { \
atomic_inc(&__vha->vref_count); \
mb(); \
if (__vha->flags.delete_progress) { \
atomic_dec(&__vha->vref_count); \
__bail = 1; \
} else { \
__bail = 0; \
} \
} while (0)

#define QLA_VHA_MARK_NOT_BUSY(__vha) do { \
atomic_dec(&__vha->vref_count); \
} while (0)


#define qla_printk(level, ha, format, arg...) \
dev_printk(level , &((ha)->pdev->dev) , format , ## arg)

Expand Down
94 changes: 81 additions & 13 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,29 @@ qla2x00_ctx_sp_free(srb_t *sp)
{
struct srb_ctx *ctx = sp->ctx;
struct srb_iocb *iocb = ctx->u.iocb_cmd;
struct scsi_qla_host *vha = sp->fcport->vha;

del_timer_sync(&iocb->timer);
kfree(iocb);
kfree(ctx);
mempool_free(sp, sp->fcport->vha->hw->srb_mempool);

QLA_VHA_MARK_NOT_BUSY(vha);
}

inline srb_t *
qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
unsigned long tmo)
{
srb_t *sp;
srb_t *sp = NULL;
struct qla_hw_data *ha = vha->hw;
struct srb_ctx *ctx;
struct srb_iocb *iocb;
uint8_t bail;

QLA_VHA_MARK_BUSY(vha, bail);
if (bail)
return NULL;

sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
if (!sp)
Expand Down Expand Up @@ -116,6 +124,8 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
iocb->timer.function = qla2x00_ctx_sp_timeout;
add_timer(&iocb->timer);
done:
if (!sp)
QLA_VHA_MARK_NOT_BUSY(vha);
return sp;
}

Expand Down Expand Up @@ -1777,11 +1787,15 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
qla2x00_init_response_q_entries(rsp);
}

spin_lock_irqsave(&ha->vport_slock, flags);
/* Clear RSCN queue. */
list_for_each_entry(vp, &ha->vp_list, list) {
vp->rscn_in_ptr = 0;
vp->rscn_out_ptr = 0;
}

spin_unlock_irqrestore(&ha->vport_slock, flags);

ha->isp_ops->config_rings(vha);

spin_unlock_irqrestore(&ha->hardware_lock, flags);
Expand Down Expand Up @@ -3218,12 +3232,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
/* Bypass virtual ports of the same host. */
found = 0;
if (ha->num_vhosts) {
unsigned long flags;

spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (new_fcport->d_id.b24 == vp->d_id.b24) {
found = 1;
break;
}
}
spin_unlock_irqrestore(&ha->vport_slock, flags);

if (found)
continue;
}
Expand Down Expand Up @@ -3343,6 +3362,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp;
struct scsi_qla_host *tvp;
unsigned long flags = 0;

rval = QLA_SUCCESS;

Expand All @@ -3367,6 +3387,8 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
/* Check for loop ID being already in use. */
found = 0;
fcport = NULL;

spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
list_for_each_entry(fcport, &vp->vp_fcports, list) {
if (fcport->loop_id == dev->loop_id &&
Expand All @@ -3379,6 +3401,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
if (found)
break;
}
spin_unlock_irqrestore(&ha->vport_slock, flags);

/* If not in use then it is free to use. */
if (!found) {
Expand Down Expand Up @@ -3791,22 +3814,35 @@ void
qla2x00_update_fcports(scsi_qla_host_t *base_vha)
{
fc_port_t *fcport;
struct scsi_qla_host *tvp, *vha;
struct scsi_qla_host *vha;
struct qla_hw_data *ha = base_vha->hw;
unsigned long flags;

spin_lock_irqsave(&ha->vport_slock, flags);
/* Go with deferred removal of rport references. */
list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list)
list_for_each_entry(fcport, &vha->vp_fcports, list)
list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
atomic_inc(&vha->vref_count);
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (fcport && fcport->drport &&
atomic_read(&fcport->state) != FCS_UNCONFIGURED)
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
spin_unlock_irqrestore(&ha->vport_slock, flags);

qla2x00_rport_del(fcport);

spin_lock_irqsave(&ha->vport_slock, flags);
}
}
atomic_dec(&vha->vref_count);
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
}

void
qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
struct scsi_qla_host *tvp;
unsigned long flags;

vha->flags.online = 0;
ha->flags.chip_reset_done = 0;
Expand All @@ -3824,8 +3860,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
qla2x00_mark_all_devices_lost(vha, 0);
list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list)

spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &base_vha->hw->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);

qla2x00_mark_all_devices_lost(vp, 0);

spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
} else {
if (!atomic_read(&vha->loop_down_timer))
atomic_set(&vha->loop_down_timer,
Expand Down Expand Up @@ -3862,8 +3908,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
uint8_t status = 0;
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp;
struct scsi_qla_host *tvp;
struct req_que *req = ha->req_q_map[0];
unsigned long flags;

if (vha->flags.online) {
qla2x00_abort_isp_cleanup(vha);
Expand Down Expand Up @@ -3970,10 +4016,21 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
DEBUG(printk(KERN_INFO
"qla2x00_abort_isp(%ld): succeeded.\n",
vha->host_no));
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx)

spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
if (vp->vp_idx) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);

qla2x00_vp_abort_isp(vp);

spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
}
}
spin_unlock_irqrestore(&ha->vport_slock, flags);

} else {
qla_printk(KERN_INFO, ha,
"qla2x00_abort_isp: **** FAILED ****\n");
Expand Down Expand Up @@ -5185,7 +5242,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
struct req_que *req = ha->req_q_map[0];
struct rsp_que *rsp = ha->rsp_q_map[0];
struct scsi_qla_host *vp;
struct scsi_qla_host *tvp;
unsigned long flags;

status = qla2x00_init_rings(vha);
if (!status) {
Expand Down Expand Up @@ -5272,10 +5329,21 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
DEBUG(printk(KERN_INFO
"qla82xx_restart_isp(%ld): succeeded.\n",
vha->host_no));
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx)

spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
if (vp->vp_idx) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);

qla2x00_vp_abort_isp(vp);

spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
}
}
spin_unlock_irqrestore(&ha->vport_slock, flags);

} else {
qla_printk(KERN_INFO, ha,
"qla82xx_restart_isp: **** FAILED ****\n");
Expand Down
7 changes: 5 additions & 2 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2913,7 +2913,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *vp;
scsi_qla_host_t *tvp;
unsigned long flags;

if (rptid_entry->entry_status != 0)
return;
Expand Down Expand Up @@ -2945,9 +2945,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
return;
}

list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list)
if (vp_idx == vp->vp_idx)
break;
spin_unlock_irqrestore(&ha->vport_slock, flags);

if (!vp)
return;

Expand Down
Loading

0 comments on commit feafb7b

Please sign in to comment.