aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_mid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mid.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 987c5b0ca78e..bc1a7453c5d8 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)
93static void 122static void
94qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) 123qla2x00_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) {
@@ -194,12 +229,17 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
194void 229void
195qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) 230qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
196{ 231{
197 scsi_qla_host_t *vha, *tvha; 232 scsi_qla_host_t *vha;
198 struct qla_hw_data *ha = rsp->hw; 233 struct qla_hw_data *ha = rsp->hw;
199 int i = 0; 234 int i = 0;
235 unsigned long flags;
200 236
201 list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { 237 spin_lock_irqsave(&ha->vport_slock, flags);
238 list_for_each_entry(vha, &ha->vp_list, list) {
202 if (vha->vp_idx) { 239 if (vha->vp_idx) {
240 atomic_inc(&vha->vref_count);
241 spin_unlock_irqrestore(&ha->vport_slock, flags);
242
203 switch (mb[0]) { 243 switch (mb[0]) {
204 case MBA_LIP_OCCURRED: 244 case MBA_LIP_OCCURRED:
205 case MBA_LOOP_UP: 245 case MBA_LOOP_UP:
@@ -215,9 +255,13 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
215 qla2x00_async_event(vha, rsp, mb); 255 qla2x00_async_event(vha, rsp, mb);
216 break; 256 break;
217 } 257 }
258
259 spin_lock_irqsave(&ha->vport_slock, flags);
260 atomic_dec(&vha->vref_count);
218 } 261 }
219 i++; 262 i++;
220 } 263 }
264 spin_unlock_irqrestore(&ha->vport_slock, flags);
221} 265}
222 266
223int 267int
@@ -297,7 +341,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
297 int ret; 341 int ret;
298 struct qla_hw_data *ha = vha->hw; 342 struct qla_hw_data *ha = vha->hw;
299 scsi_qla_host_t *vp; 343 scsi_qla_host_t *vp;
300 struct scsi_qla_host *tvp; 344 unsigned long flags = 0;
301 345
302 if (vha->vp_idx) 346 if (vha->vp_idx)
303 return; 347 return;
@@ -309,10 +353,19 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
309 if (!(ha->current_topology & ISP_CFG_F)) 353 if (!(ha->current_topology & ISP_CFG_F))
310 return; 354 return;
311 355
312 list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { 356 spin_lock_irqsave(&ha->vport_slock, flags);
313 if (vp->vp_idx) 357 list_for_each_entry(vp, &ha->vp_list, list) {
358 if (vp->vp_idx) {
359 atomic_inc(&vp->vref_count);
360 spin_unlock_irqrestore(&ha->vport_slock, flags);
361
314 ret = qla2x00_do_dpc_vp(vp); 362 ret = qla2x00_do_dpc_vp(vp);
363
364 spin_lock_irqsave(&ha->vport_slock, flags);
365 atomic_dec(&vp->vref_count);
366 }
315 } 367 }
368 spin_unlock_irqrestore(&ha->vport_slock, flags);
316} 369}
317 370
318int 371int