diff options
author | Jing Huang <huangj@brocade.com> | 2010-03-19 14:05:39 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-04-11 10:24:16 -0400 |
commit | b504293fe9dc42917a919044f2b672fb361329d0 (patch) | |
tree | 13a7a576560155c6c8b49976e286060b5c904aba /drivers/scsi/bfa/bfad_attr.c | |
parent | 12fb8c1574d7d0c262d2f4c667047889c4f27ebe (diff) |
[SCSI] bfa: add fc transport class based vport create/delete
Use duplicate fc transport template for physical and vitual port. Add
vport create/delete/disalbe functions in the transport template of physical
port. Changes to make the vport create/delete function to work under this
framework.
Signed-off-by: Jing Huang <huangj@brocade.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/bfa/bfad_attr.c')
-rw-r--r-- | drivers/scsi/bfa/bfad_attr.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 6a2efdd5ef24..e477bfbfa7d8 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c | |||
@@ -364,6 +364,152 @@ bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | |||
364 | 364 | ||
365 | } | 365 | } |
366 | 366 | ||
367 | static int | ||
368 | bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) | ||
369 | { | ||
370 | char *vname = fc_vport->symbolic_name; | ||
371 | struct Scsi_Host *shost = fc_vport->shost; | ||
372 | struct bfad_im_port_s *im_port = | ||
373 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
374 | struct bfad_s *bfad = im_port->bfad; | ||
375 | struct bfa_port_cfg_s port_cfg; | ||
376 | int status = 0, rc; | ||
377 | unsigned long flags; | ||
378 | |||
379 | memset(&port_cfg, 0, sizeof(port_cfg)); | ||
380 | |||
381 | port_cfg.pwwn = wwn_to_u64((u8 *) &fc_vport->port_name); | ||
382 | port_cfg.nwwn = wwn_to_u64((u8 *) &fc_vport->node_name); | ||
383 | |||
384 | if (strlen(vname) > 0) | ||
385 | strcpy((char *)&port_cfg.sym_name, vname); | ||
386 | |||
387 | port_cfg.roles = BFA_PORT_ROLE_FCP_IM; | ||
388 | rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev); | ||
389 | |||
390 | if (rc == BFA_STATUS_OK) { | ||
391 | struct bfad_vport_s *vport; | ||
392 | struct bfa_fcs_vport_s *fcs_vport; | ||
393 | struct Scsi_Host *vshost; | ||
394 | |||
395 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
396 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, | ||
397 | port_cfg.pwwn); | ||
398 | if (fcs_vport == NULL) { | ||
399 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
400 | return VPCERR_BAD_WWN; | ||
401 | } | ||
402 | |||
403 | fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); | ||
404 | if (disable) { | ||
405 | bfa_fcs_vport_stop(fcs_vport); | ||
406 | fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); | ||
407 | } | ||
408 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
409 | |||
410 | vport = fcs_vport->vport_drv; | ||
411 | vshost = vport->drv_port.im_port->shost; | ||
412 | fc_host_node_name(vshost) = wwn_to_u64((u8 *) &port_cfg.nwwn); | ||
413 | fc_host_port_name(vshost) = wwn_to_u64((u8 *) &port_cfg.pwwn); | ||
414 | fc_vport->dd_data = vport; | ||
415 | vport->drv_port.im_port->fc_vport = fc_vport; | ||
416 | |||
417 | } else if (rc == BFA_STATUS_INVALID_WWN) | ||
418 | return VPCERR_BAD_WWN; | ||
419 | else if (rc == BFA_STATUS_VPORT_EXISTS) | ||
420 | return VPCERR_BAD_WWN; | ||
421 | else if (rc == BFA_STATUS_VPORT_MAX) | ||
422 | return VPCERR_NO_FABRIC_SUPP; | ||
423 | else if (rc == BFA_STATUS_VPORT_WWN_BP) | ||
424 | return VPCERR_BAD_WWN; | ||
425 | else | ||
426 | return FC_VPORT_FAILED; | ||
427 | |||
428 | return status; | ||
429 | } | ||
430 | |||
431 | static int | ||
432 | bfad_im_vport_delete(struct fc_vport *fc_vport) | ||
433 | { | ||
434 | struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; | ||
435 | struct bfad_im_port_s *im_port = | ||
436 | (struct bfad_im_port_s *) vport->drv_port.im_port; | ||
437 | struct bfad_s *bfad = im_port->bfad; | ||
438 | struct bfad_port_s *port; | ||
439 | struct bfa_fcs_vport_s *fcs_vport; | ||
440 | struct Scsi_Host *vshost; | ||
441 | wwn_t pwwn; | ||
442 | int rc; | ||
443 | unsigned long flags; | ||
444 | struct completion fcomp; | ||
445 | |||
446 | if (im_port->flags & BFAD_PORT_DELETE) | ||
447 | goto free_scsi_host; | ||
448 | |||
449 | port = im_port->port; | ||
450 | |||
451 | vshost = vport->drv_port.im_port->shost; | ||
452 | pwwn = wwn_to_u64((u8 *) &fc_host_port_name(vshost)); | ||
453 | |||
454 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
455 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); | ||
456 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
457 | |||
458 | if (fcs_vport == NULL) | ||
459 | return VPCERR_BAD_WWN; | ||
460 | |||
461 | vport->drv_port.flags |= BFAD_PORT_DELETE; | ||
462 | |||
463 | vport->comp_del = &fcomp; | ||
464 | init_completion(vport->comp_del); | ||
465 | |||
466 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
467 | rc = bfa_fcs_vport_delete(&vport->fcs_vport); | ||
468 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
469 | |||
470 | wait_for_completion(vport->comp_del); | ||
471 | |||
472 | free_scsi_host: | ||
473 | bfad_os_scsi_host_free(bfad, im_port); | ||
474 | |||
475 | kfree(vport); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int | ||
481 | bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable) | ||
482 | { | ||
483 | struct bfad_vport_s *vport; | ||
484 | struct bfad_s *bfad; | ||
485 | struct bfa_fcs_vport_s *fcs_vport; | ||
486 | struct Scsi_Host *vshost; | ||
487 | wwn_t pwwn; | ||
488 | unsigned long flags; | ||
489 | |||
490 | vport = (struct bfad_vport_s *)fc_vport->dd_data; | ||
491 | bfad = vport->drv_port.bfad; | ||
492 | vshost = vport->drv_port.im_port->shost; | ||
493 | pwwn = wwn_to_u64((u8 *) &fc_vport->port_name); | ||
494 | |||
495 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
496 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); | ||
497 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
498 | |||
499 | if (fcs_vport == NULL) | ||
500 | return VPCERR_BAD_WWN; | ||
501 | |||
502 | if (disable) { | ||
503 | bfa_fcs_vport_stop(fcs_vport); | ||
504 | fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); | ||
505 | } else { | ||
506 | bfa_fcs_vport_start(fcs_vport); | ||
507 | fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); | ||
508 | } | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
367 | struct fc_function_template bfad_im_fc_function_template = { | 513 | struct fc_function_template bfad_im_fc_function_template = { |
368 | 514 | ||
369 | /* Target dynamic attributes */ | 515 | /* Target dynamic attributes */ |
@@ -413,6 +559,61 @@ struct fc_function_template bfad_im_fc_function_template = { | |||
413 | .show_rport_dev_loss_tmo = 1, | 559 | .show_rport_dev_loss_tmo = 1, |
414 | .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, | 560 | .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, |
415 | .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, | 561 | .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, |
562 | |||
563 | .vport_create = bfad_im_vport_create, | ||
564 | .vport_delete = bfad_im_vport_delete, | ||
565 | .vport_disable = bfad_im_vport_disable, | ||
566 | }; | ||
567 | |||
568 | struct fc_function_template bfad_im_vport_fc_function_template = { | ||
569 | |||
570 | /* Target dynamic attributes */ | ||
571 | .get_starget_port_id = bfad_im_get_starget_port_id, | ||
572 | .show_starget_port_id = 1, | ||
573 | .get_starget_node_name = bfad_im_get_starget_node_name, | ||
574 | .show_starget_node_name = 1, | ||
575 | .get_starget_port_name = bfad_im_get_starget_port_name, | ||
576 | .show_starget_port_name = 1, | ||
577 | |||
578 | /* Host dynamic attribute */ | ||
579 | .get_host_port_id = bfad_im_get_host_port_id, | ||
580 | .show_host_port_id = 1, | ||
581 | |||
582 | /* Host fixed attributes */ | ||
583 | .show_host_node_name = 1, | ||
584 | .show_host_port_name = 1, | ||
585 | .show_host_supported_classes = 1, | ||
586 | .show_host_supported_fc4s = 1, | ||
587 | .show_host_supported_speeds = 1, | ||
588 | .show_host_maxframe_size = 1, | ||
589 | |||
590 | /* More host dynamic attributes */ | ||
591 | .show_host_port_type = 1, | ||
592 | .get_host_port_type = bfad_im_get_host_port_type, | ||
593 | .show_host_port_state = 1, | ||
594 | .get_host_port_state = bfad_im_get_host_port_state, | ||
595 | .show_host_active_fc4s = 1, | ||
596 | .get_host_active_fc4s = bfad_im_get_host_active_fc4s, | ||
597 | .show_host_speed = 1, | ||
598 | .get_host_speed = bfad_im_get_host_speed, | ||
599 | .show_host_fabric_name = 1, | ||
600 | .get_host_fabric_name = bfad_im_get_host_fabric_name, | ||
601 | |||
602 | .show_host_symbolic_name = 1, | ||
603 | |||
604 | /* Statistics */ | ||
605 | .get_fc_host_stats = bfad_im_get_stats, | ||
606 | .reset_fc_host_stats = bfad_im_reset_stats, | ||
607 | |||
608 | /* Allocation length for host specific data */ | ||
609 | .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), | ||
610 | |||
611 | /* Remote port fixed attributes */ | ||
612 | .show_rport_maxframe_size = 1, | ||
613 | .show_rport_supported_classes = 1, | ||
614 | .show_rport_dev_loss_tmo = 1, | ||
615 | .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, | ||
616 | .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, | ||
416 | }; | 617 | }; |
417 | 618 | ||
418 | /** | 619 | /** |