aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_mid.c
diff options
context:
space:
mode:
authorAnirban Chakraborty <anirban.chakraborty@qlogic.com>2008-11-06 13:40:19 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:24:15 -0500
commit7b867cf76fbcc8d77867cbec6f509f71dce8a98f (patch)
treeef5fcc1e21701ed1baa1b131c7c29f29cd41d5d6 /drivers/scsi/qla2xxx/qla_mid.c
parenta9b589d90e3d7748dae459031c2d912cd9e83c88 (diff)
[SCSI] qla2xxx: Refactor qla data structures
Following changes have been made to the qla2xxx FC driver in preparation for the multi- queue and future SR IOV hardware. 1. scsi_qla_host structure has been changed to contain scsi host specific data only. 2. A new structure, qla_hw_data is created to contain HBA specific hardware data. 3. Request and response IO specific data strucures are created. 4. The global list of fcports for the hba is not maintained anymore, instead a fcport list is construted on per scsi_qla_host. Signed-of-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mid.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c173
1 files changed, 70 insertions, 103 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 93560cd72784..da3db3abb82c 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -5,6 +5,7 @@
5 * See LICENSE.qla2xxx for copyright and licensing details. 5 * See LICENSE.qla2xxx for copyright and licensing details.
6 */ 6 */
7#include "qla_def.h" 7#include "qla_def.h"
8#include "qla_gbl.h"
8 9
9#include <linux/moduleparam.h> 10#include <linux/moduleparam.h>
10#include <linux/vmalloc.h> 11#include <linux/vmalloc.h>
@@ -18,7 +19,7 @@
18void 19void
19qla2x00_vp_stop_timer(scsi_qla_host_t *vha) 20qla2x00_vp_stop_timer(scsi_qla_host_t *vha)
20{ 21{
21 if (vha->parent && vha->timer_active) { 22 if (vha->vp_idx && vha->timer_active) {
22 del_timer_sync(&vha->timer); 23 del_timer_sync(&vha->timer);
23 vha->timer_active = 0; 24 vha->timer_active = 0;
24 } 25 }
@@ -28,7 +29,7 @@ static uint32_t
28qla24xx_allocate_vp_id(scsi_qla_host_t *vha) 29qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
29{ 30{
30 uint32_t vp_id; 31 uint32_t vp_id;
31 scsi_qla_host_t *ha = vha->parent; 32 struct qla_hw_data *ha = vha->hw;
32 33
33 /* Find an empty slot and assign an vp_id */ 34 /* Find an empty slot and assign an vp_id */
34 mutex_lock(&ha->vport_lock); 35 mutex_lock(&ha->vport_lock);
@@ -44,7 +45,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
44 ha->num_vhosts++; 45 ha->num_vhosts++;
45 ha->cur_vport_count++; 46 ha->cur_vport_count++;
46 vha->vp_idx = vp_id; 47 vha->vp_idx = vp_id;
47 list_add_tail(&vha->vp_list, &ha->vp_list); 48 list_add_tail(&vha->list, &ha->vp_list);
48 mutex_unlock(&ha->vport_lock); 49 mutex_unlock(&ha->vport_lock);
49 return vp_id; 50 return vp_id;
50} 51}
@@ -53,24 +54,24 @@ void
53qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) 54qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
54{ 55{
55 uint16_t vp_id; 56 uint16_t vp_id;
56 scsi_qla_host_t *ha = vha->parent; 57 struct qla_hw_data *ha = vha->hw;
57 58
58 mutex_lock(&ha->vport_lock); 59 mutex_lock(&ha->vport_lock);
59 vp_id = vha->vp_idx; 60 vp_id = vha->vp_idx;
60 ha->num_vhosts--; 61 ha->num_vhosts--;
61 ha->cur_vport_count--; 62 ha->cur_vport_count--;
62 clear_bit(vp_id, ha->vp_idx_map); 63 clear_bit(vp_id, ha->vp_idx_map);
63 list_del(&vha->vp_list); 64 list_del(&vha->list);
64 mutex_unlock(&ha->vport_lock); 65 mutex_unlock(&ha->vport_lock);
65} 66}
66 67
67static scsi_qla_host_t * 68static scsi_qla_host_t *
68qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name) 69qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name)
69{ 70{
70 scsi_qla_host_t *vha; 71 scsi_qla_host_t *vha;
71 72
72 /* Locate matching device in database. */ 73 /* Locate matching device in database. */
73 list_for_each_entry(vha, &ha->vp_list, vp_list) { 74 list_for_each_entry(vha, &ha->vp_list, list) {
74 if (!memcmp(port_name, vha->port_name, WWN_SIZE)) 75 if (!memcmp(port_name, vha->port_name, WWN_SIZE))
75 return vha; 76 return vha;
76 } 77 }
@@ -94,12 +95,8 @@ static void
94qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) 95qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
95{ 96{
96 fc_port_t *fcport; 97 fc_port_t *fcport;
97 scsi_qla_host_t *pha = to_qla_parent(vha);
98
99 list_for_each_entry(fcport, &pha->fcports, list) {
100 if (fcport->vp_idx != vha->vp_idx)
101 continue;
102 98
99 list_for_each_entry(fcport, &vha->vp_fcports, list) {
103 DEBUG15(printk("scsi(%ld): Marking port dead, " 100 DEBUG15(printk("scsi(%ld): Marking port dead, "
104 "loop_id=0x%04x :%x\n", 101 "loop_id=0x%04x :%x\n",
105 vha->host_no, fcport->loop_id, fcport->vp_idx)); 102 vha->host_no, fcport->loop_id, fcport->vp_idx));
@@ -118,7 +115,6 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
118 atomic_set(&vha->loop_state, LOOP_DOWN); 115 atomic_set(&vha->loop_state, LOOP_DOWN);
119 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); 116 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
120 117
121 /* Delete all vp's fcports from parent's list */
122 qla2x00_mark_vp_devices_dead(vha); 118 qla2x00_mark_vp_devices_dead(vha);
123 atomic_set(&vha->vp_state, VP_FAILED); 119 atomic_set(&vha->vp_state, VP_FAILED);
124 vha->flags.management_server_logged_in = 0; 120 vha->flags.management_server_logged_in = 0;
@@ -135,11 +131,12 @@ int
135qla24xx_enable_vp(scsi_qla_host_t *vha) 131qla24xx_enable_vp(scsi_qla_host_t *vha)
136{ 132{
137 int ret; 133 int ret;
138 scsi_qla_host_t *ha = vha->parent; 134 struct qla_hw_data *ha = vha->hw;
135 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
139 136
140 /* Check if physical ha port is Up */ 137 /* Check if physical ha port is Up */
141 if (atomic_read(&ha->loop_state) == LOOP_DOWN || 138 if (atomic_read(&base_vha->loop_state) == LOOP_DOWN ||
142 atomic_read(&ha->loop_state) == LOOP_DEAD ) { 139 atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
143 vha->vp_err_state = VP_ERR_PORTDWN; 140 vha->vp_err_state = VP_ERR_PORTDWN;
144 fc_vport_set_state(vha->fc_vport, FC_VPORT_LINKDOWN); 141 fc_vport_set_state(vha->fc_vport, FC_VPORT_LINKDOWN);
145 goto enable_failed; 142 goto enable_failed;
@@ -177,8 +174,8 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
177 vha->host_no, __func__)); 174 vha->host_no, __func__));
178 ret = qla2x00_send_change_request(vha, 0x3, vha->vp_idx); 175 ret = qla2x00_send_change_request(vha, 0x3, vha->vp_idx);
179 if (ret != QLA_SUCCESS) { 176 if (ret != QLA_SUCCESS) {
180 DEBUG15(qla_printk(KERN_ERR, vha, "Failed to enable receiving" 177 DEBUG15(qla_printk(KERN_ERR, vha->hw, "Failed to enable "
181 " of RSCN requests: 0x%x\n", ret)); 178 "receiving of RSCN requests: 0x%x\n", ret));
182 return; 179 return;
183 } else { 180 } else {
184 /* Corresponds to SCR enabled */ 181 /* Corresponds to SCR enabled */
@@ -194,25 +191,13 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
194} 191}
195 192
196void 193void
197qla2x00_alert_all_vps(scsi_qla_host_t *ha, uint16_t *mb) 194qla2x00_alert_all_vps(struct qla_hw_data *ha, uint16_t *mb)
198{ 195{
199 int i, vp_idx_matched;
200 scsi_qla_host_t *vha; 196 scsi_qla_host_t *vha;
197 int i = 0;
201 198
202 if (ha->parent) 199 list_for_each_entry(vha, &ha->vp_list, list) {
203 return; 200 if (vha->vp_idx) {
204
205 for_each_mapped_vp_idx(ha, i) {
206 vp_idx_matched = 0;
207
208 list_for_each_entry(vha, &ha->vp_list, vp_list) {
209 if (i == vha->vp_idx) {
210 vp_idx_matched = 1;
211 break;
212 }
213 }
214
215 if (vp_idx_matched) {
216 switch (mb[0]) { 201 switch (mb[0]) {
217 case MBA_LIP_OCCURRED: 202 case MBA_LIP_OCCURRED:
218 case MBA_LOOP_UP: 203 case MBA_LOOP_UP:
@@ -223,16 +208,17 @@ qla2x00_alert_all_vps(scsi_qla_host_t *ha, uint16_t *mb)
223 case MBA_PORT_UPDATE: 208 case MBA_PORT_UPDATE:
224 case MBA_RSCN_UPDATE: 209 case MBA_RSCN_UPDATE:
225 DEBUG15(printk("scsi(%ld)%s: Async_event for" 210 DEBUG15(printk("scsi(%ld)%s: Async_event for"
226 " VP[%d], mb = 0x%x, vha=%p\n", 211 " VP[%d], mb = 0x%x, vha=%p\n",
227 vha->host_no, __func__,i, *mb, vha)); 212 vha->host_no, __func__, i, *mb, vha));
228 qla2x00_async_event(vha, mb); 213 qla2x00_async_event(vha, mb);
229 break; 214 break;
230 } 215 }
231 } 216 }
217 i++;
232 } 218 }
233} 219}
234 220
235void 221int
236qla2x00_vp_abort_isp(scsi_qla_host_t *vha) 222qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
237{ 223{
238 /* 224 /*
@@ -247,30 +233,49 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
247 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); 233 atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
248 } 234 }
249 235
236 /* To exclusively reset vport, we need to log it out first.*/
237 if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
238 qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
239
250 DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n", 240 DEBUG15(printk("scsi(%ld): Scheduling enable of Vport %d...\n",
251 vha->host_no, vha->vp_idx)); 241 vha->host_no, vha->vp_idx));
252 qla24xx_enable_vp(vha); 242 return qla24xx_enable_vp(vha);
253} 243}
254 244
255static int 245static int
256qla2x00_do_dpc_vp(scsi_qla_host_t *vha) 246qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
257{ 247{
258 scsi_qla_host_t *ha = vha->parent; 248 struct qla_hw_data *ha = vha->hw;
249 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
259 250
260 if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { 251 if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) {
261 /* VP acquired. complete port configuration */ 252 /* VP acquired. complete port configuration */
262 if (atomic_read(&ha->loop_state) == LOOP_READY) { 253 if (atomic_read(&base_vha->loop_state) == LOOP_READY) {
263 qla24xx_configure_vp(vha); 254 qla24xx_configure_vp(vha);
264 } else { 255 } else {
265 set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); 256 set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
266 set_bit(VP_DPC_NEEDED, &ha->dpc_flags); 257 set_bit(VP_DPC_NEEDED, &base_vha->dpc_flags);
267 } 258 }
268 259
269 return 0; 260 return 0;
270 } 261 }
271 262
272 if (test_and_clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) 263 if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) {
273 qla2x00_vp_abort_isp(vha); 264 qla2x00_update_fcports(vha);
265 clear_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags);
266 }
267
268 if ((test_and_clear_bit(RELOGIN_NEEDED, &vha->dpc_flags)) &&
269 !test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) &&
270 atomic_read(&vha->loop_state) != LOOP_DOWN) {
271
272 DEBUG(printk("scsi(%ld): qla2x00_port_login()\n",
273 vha->host_no));
274 qla2x00_relogin(vha);
275
276 DEBUG(printk("scsi(%ld): qla2x00_port_login - end\n",
277 vha->host_no));
278 }
274 279
275 if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) && 280 if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) &&
276 (!(test_and_set_bit(RESET_ACTIVE, &vha->dpc_flags)))) { 281 (!(test_and_set_bit(RESET_ACTIVE, &vha->dpc_flags)))) {
@@ -289,38 +294,30 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
289} 294}
290 295
291void 296void
292qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha) 297qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
293{ 298{
294 int ret; 299 int ret;
295 int i, vp_idx_matched; 300 struct qla_hw_data *ha = vha->hw;
296 scsi_qla_host_t *vha; 301 scsi_qla_host_t *vp;
297 302
298 if (ha->parent) 303 if (vha->vp_idx)
299 return; 304 return;
300 if (list_empty(&ha->vp_list)) 305 if (list_empty(&ha->vp_list))
301 return; 306 return;
302 307
303 clear_bit(VP_DPC_NEEDED, &ha->dpc_flags); 308 clear_bit(VP_DPC_NEEDED, &vha->dpc_flags);
304
305 for_each_mapped_vp_idx(ha, i) {
306 vp_idx_matched = 0;
307
308 list_for_each_entry(vha, &ha->vp_list, vp_list) {
309 if (i == vha->vp_idx) {
310 vp_idx_matched = 1;
311 break;
312 }
313 }
314 309
315 if (vp_idx_matched) 310 list_for_each_entry(vp, &ha->vp_list, list) {
316 ret = qla2x00_do_dpc_vp(vha); 311 if (vp->vp_idx)
312 ret = qla2x00_do_dpc_vp(vp);
317 } 313 }
318} 314}
319 315
320int 316int
321qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) 317qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
322{ 318{
323 scsi_qla_host_t *ha = shost_priv(fc_vport->shost); 319 scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
320 struct qla_hw_data *ha = base_vha->hw;
324 scsi_qla_host_t *vha; 321 scsi_qla_host_t *vha;
325 uint8_t port_name[WWN_SIZE]; 322 uint8_t port_name[WWN_SIZE];
326 323
@@ -337,7 +334,7 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
337 334
338 /* Check up unique WWPN */ 335 /* Check up unique WWPN */
339 u64_to_wwn(fc_vport->port_name, port_name); 336 u64_to_wwn(fc_vport->port_name, port_name);
340 if (!memcmp(port_name, ha->port_name, WWN_SIZE)) 337 if (!memcmp(port_name, base_vha->port_name, WWN_SIZE))
341 return VPCERR_BAD_WWN; 338 return VPCERR_BAD_WWN;
342 vha = qla24xx_find_vhost_by_name(ha, port_name); 339 vha = qla24xx_find_vhost_by_name(ha, port_name);
343 if (vha) 340 if (vha)
@@ -346,7 +343,7 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
346 /* Check up max-npiv-supports */ 343 /* Check up max-npiv-supports */
347 if (ha->num_vhosts > ha->max_npiv_vports) { 344 if (ha->num_vhosts > ha->max_npiv_vports) {
348 DEBUG15(printk("scsi(%ld): num_vhosts %ud is bigger than " 345 DEBUG15(printk("scsi(%ld): num_vhosts %ud is bigger than "
349 "max_npv_vports %ud.\n", ha->host_no, 346 "max_npv_vports %ud.\n", base_vha->host_no,
350 ha->num_vhosts, ha->max_npiv_vports)); 347 ha->num_vhosts, ha->max_npiv_vports));
351 return VPCERR_UNSUPPORTED; 348 return VPCERR_UNSUPPORTED;
352 } 349 }
@@ -356,59 +353,35 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport)
356scsi_qla_host_t * 353scsi_qla_host_t *
357qla24xx_create_vhost(struct fc_vport *fc_vport) 354qla24xx_create_vhost(struct fc_vport *fc_vport)
358{ 355{
359 scsi_qla_host_t *ha = shost_priv(fc_vport->shost); 356 scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
357 struct qla_hw_data *ha = base_vha->hw;
360 scsi_qla_host_t *vha; 358 scsi_qla_host_t *vha;
359 struct scsi_host_template *sht = &qla24xx_driver_template;
361 struct Scsi_Host *host; 360 struct Scsi_Host *host;
362 361
363 host = scsi_host_alloc(&qla24xx_driver_template, 362 vha = qla2x00_create_host(sht, ha);
364 sizeof(scsi_qla_host_t)); 363 if (!vha) {
365 if (!host) { 364 DEBUG(printk("qla2xxx: scsi_host_alloc() failed for vport\n"));
366 printk(KERN_WARNING
367 "qla2xxx: scsi_host_alloc() failed for vport\n");
368 return(NULL); 365 return(NULL);
369 } 366 }
370 367
371 vha = shost_priv(host); 368 host = vha->host;
372
373 /* clone the parent hba */
374 memcpy(vha, ha, sizeof (scsi_qla_host_t));
375
376 fc_vport->dd_data = vha; 369 fc_vport->dd_data = vha;
377 370
378 vha->node_name = kmalloc(WWN_SIZE * sizeof(char), GFP_KERNEL);
379 if (!vha->node_name)
380 goto create_vhost_failed_1;
381
382 vha->port_name = kmalloc(WWN_SIZE * sizeof(char), GFP_KERNEL);
383 if (!vha->port_name)
384 goto create_vhost_failed_2;
385
386 /* New host info */ 371 /* New host info */
387 u64_to_wwn(fc_vport->node_name, vha->node_name); 372 u64_to_wwn(fc_vport->node_name, vha->node_name);
388 u64_to_wwn(fc_vport->port_name, vha->port_name); 373 u64_to_wwn(fc_vport->port_name, vha->port_name);
389 374
390 vha->host = host;
391 vha->host_no = host->host_no;
392 vha->parent = ha;
393 vha->fc_vport = fc_vport; 375 vha->fc_vport = fc_vport;
394 vha->device_flags = 0; 376 vha->device_flags = 0;
395 vha->vp_idx = qla24xx_allocate_vp_id(vha); 377 vha->vp_idx = qla24xx_allocate_vp_id(vha);
396 if (vha->vp_idx > ha->max_npiv_vports) { 378 if (vha->vp_idx > ha->max_npiv_vports) {
397 DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n", 379 DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
398 vha->host_no)); 380 vha->host_no));
399 goto create_vhost_failed_3; 381 goto create_vhost_failed;
400 } 382 }
401 vha->mgmt_svr_loop_id = 10 + vha->vp_idx; 383 vha->mgmt_svr_loop_id = 10 + vha->vp_idx;
402 384
403 init_completion(&vha->mbx_cmd_comp);
404 complete(&vha->mbx_cmd_comp);
405 init_completion(&vha->mbx_intr_comp);
406
407 INIT_LIST_HEAD(&vha->list);
408 INIT_LIST_HEAD(&vha->fcports);
409 INIT_LIST_HEAD(&vha->vp_fcports);
410 INIT_LIST_HEAD(&vha->work_list);
411
412 vha->dpc_flags = 0L; 385 vha->dpc_flags = 0L;
413 set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); 386 set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
414 set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); 387 set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
@@ -423,7 +396,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
423 396
424 qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL); 397 qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL);
425 398
426 host->can_queue = vha->request_q_length + 128; 399 host->can_queue = ha->req->length + 128;
427 host->this_id = 255; 400 host->this_id = 255;
428 host->cmd_per_lun = 3; 401 host->cmd_per_lun = 3;
429 host->max_cmd_len = MAX_CMDSZ; 402 host->max_cmd_len = MAX_CMDSZ;
@@ -440,12 +413,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
440 413
441 return vha; 414 return vha;
442 415
443create_vhost_failed_3: 416create_vhost_failed:
444 kfree(vha->port_name);
445
446create_vhost_failed_2:
447 kfree(vha->node_name);
448
449create_vhost_failed_1:
450 return NULL; 417 return NULL;
451} 418}