aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-12-04 22:39:13 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:24:26 -0500
commiteada272dfc32ba3dcd33e7ca5875337defb13c54 (patch)
tree89e52427d2458a59db3a1aca0fdc01453bf1f748 /drivers/scsi
parent109f6ed05aadb7dd1cc9671a63603658d3ba518e (diff)
[SCSI] lpfc 8.3.0 : Fix multiple NPIV issues
- Fix lock up on rmmod with vports defined by having lpfc_pci_remove_one() invoke fc_vport_terminate() to remove all the vports before invoking fc_remove_host() for the physical port - Fix echotest failure when NPIV is enabled - Add the vport_disable function to the physical port's transport template to make the vport disable attribute visible - Set the vport state to DISABLE on create if the disable flag is true - Call lpfc_alloc_sysfs_attr() for vports so that statistical data collection works on them - Support setting a vport's symbolic name via sysfs by writing to /sys/class/fc_vport/vportX/symbolic_name - Fix create vport fails when link is down or in loop mode. Should be able to be create vports any time NPIV is enabled - Fix slow vport deletes when deleting multiple vports at once Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c47
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c17
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c13
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c28
6 files changed, 78 insertions, 35 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 60a9e6e9384b..030f9eb46f2a 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -354,8 +354,6 @@ struct lpfc_vport {
354 uint8_t load_flag; 354 uint8_t load_flag;
355#define FC_LOADING 0x1 /* HBA in process of loading drvr */ 355#define FC_LOADING 0x1 /* HBA in process of loading drvr */
356#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */ 356#define FC_UNLOADING 0x2 /* HBA in process of unloading drvr */
357 char *vname; /* Application assigned name */
358
359 /* Vport Config Parameters */ 357 /* Vport Config Parameters */
360 uint32_t cfg_scan_down; 358 uint32_t cfg_scan_down;
361 uint32_t cfg_lun_queue_depth; 359 uint32_t cfg_lun_queue_depth;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index aa3d6277581d..7c015982b40f 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3282,25 +3282,28 @@ lpfc_alloc_sysfs_attr(struct lpfc_vport *vport)
3282 int error; 3282 int error;
3283 3283
3284 error = sysfs_create_bin_file(&shost->shost_dev.kobj, 3284 error = sysfs_create_bin_file(&shost->shost_dev.kobj,
3285 &sysfs_ctlreg_attr); 3285 &sysfs_drvr_stat_data_attr);
3286 if (error) 3286
3287 /* Virtual ports do not need ctrl_reg and mbox */
3288 if (error || vport->port_type == LPFC_NPIV_PORT)
3287 goto out; 3289 goto out;
3288 3290
3289 error = sysfs_create_bin_file(&shost->shost_dev.kobj, 3291 error = sysfs_create_bin_file(&shost->shost_dev.kobj,
3290 &sysfs_mbox_attr); 3292 &sysfs_ctlreg_attr);
3291 if (error) 3293 if (error)
3292 goto out_remove_ctlreg_attr; 3294 goto out_remove_stat_attr;
3293 3295
3294 error = sysfs_create_bin_file(&shost->shost_dev.kobj, 3296 error = sysfs_create_bin_file(&shost->shost_dev.kobj,
3295 &sysfs_drvr_stat_data_attr); 3297 &sysfs_mbox_attr);
3296 if (error) 3298 if (error)
3297 goto out_remove_mbox_attr; 3299 goto out_remove_ctlreg_attr;
3298 3300
3299 return 0; 3301 return 0;
3300out_remove_mbox_attr:
3301 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
3302out_remove_ctlreg_attr: 3302out_remove_ctlreg_attr:
3303 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); 3303 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
3304out_remove_stat_attr:
3305 sysfs_remove_bin_file(&shost->shost_dev.kobj,
3306 &sysfs_drvr_stat_data_attr);
3304out: 3307out:
3305 return error; 3308 return error;
3306} 3309}
@@ -3315,6 +3318,9 @@ lpfc_free_sysfs_attr(struct lpfc_vport *vport)
3315 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 3318 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3316 sysfs_remove_bin_file(&shost->shost_dev.kobj, 3319 sysfs_remove_bin_file(&shost->shost_dev.kobj,
3317 &sysfs_drvr_stat_data_attr); 3320 &sysfs_drvr_stat_data_attr);
3321 /* Virtual ports do not need ctrl_reg and mbox */
3322 if (vport->port_type == LPFC_NPIV_PORT)
3323 return;
3318 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr); 3324 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_mbox_attr);
3319 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr); 3325 sysfs_remove_bin_file(&shost->shost_dev.kobj, &sysfs_ctlreg_attr);
3320} 3326}
@@ -3792,6 +3798,23 @@ lpfc_show_rport_##field (struct device *dev, \
3792 lpfc_rport_show_function(field, format_string, sz, ) \ 3798 lpfc_rport_show_function(field, format_string, sz, ) \
3793static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL) 3799static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL)
3794 3800
3801/**
3802 * lpfc_set_vport_symbolic_name: Set the vport's symbolic name.
3803 * @fc_vport: The fc_vport who's symbolic name has been changed.
3804 *
3805 * Description:
3806 * This function is called by the transport after the @fc_vport's symbolic name
3807 * has been changed. This function re-registers the symbolic name with the
3808 * switch to propogate the change into the fabric if the vport is active.
3809 **/
3810static void
3811lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport)
3812{
3813 struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
3814
3815 if (vport->port_state == LPFC_VPORT_READY)
3816 lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
3817}
3795 3818
3796struct fc_function_template lpfc_transport_functions = { 3819struct fc_function_template lpfc_transport_functions = {
3797 /* fixed attributes the driver supports */ 3820 /* fixed attributes the driver supports */
@@ -3801,6 +3824,7 @@ struct fc_function_template lpfc_transport_functions = {
3801 .show_host_supported_fc4s = 1, 3824 .show_host_supported_fc4s = 1,
3802 .show_host_supported_speeds = 1, 3825 .show_host_supported_speeds = 1,
3803 .show_host_maxframe_size = 1, 3826 .show_host_maxframe_size = 1,
3827 .show_host_symbolic_name = 1,
3804 3828
3805 /* dynamic attributes the driver supports */ 3829 /* dynamic attributes the driver supports */
3806 .get_host_port_id = lpfc_get_host_port_id, 3830 .get_host_port_id = lpfc_get_host_port_id,
@@ -3850,6 +3874,10 @@ struct fc_function_template lpfc_transport_functions = {
3850 .terminate_rport_io = lpfc_terminate_rport_io, 3874 .terminate_rport_io = lpfc_terminate_rport_io,
3851 3875
3852 .dd_fcvport_size = sizeof(struct lpfc_vport *), 3876 .dd_fcvport_size = sizeof(struct lpfc_vport *),
3877
3878 .vport_disable = lpfc_vport_disable,
3879
3880 .set_vport_symbolic_name = lpfc_set_vport_symbolic_name,
3853}; 3881};
3854 3882
3855struct fc_function_template lpfc_vport_transport_functions = { 3883struct fc_function_template lpfc_vport_transport_functions = {
@@ -3860,6 +3888,7 @@ struct fc_function_template lpfc_vport_transport_functions = {
3860 .show_host_supported_fc4s = 1, 3888 .show_host_supported_fc4s = 1,
3861 .show_host_supported_speeds = 1, 3889 .show_host_supported_speeds = 1,
3862 .show_host_maxframe_size = 1, 3890 .show_host_maxframe_size = 1,
3891 .show_host_symbolic_name = 1,
3863 3892
3864 /* dynamic attributes the driver supports */ 3893 /* dynamic attributes the driver supports */
3865 .get_host_port_id = lpfc_get_host_port_id, 3894 .get_host_port_id = lpfc_get_host_port_id,
@@ -3908,6 +3937,8 @@ struct fc_function_template lpfc_vport_transport_functions = {
3908 .terminate_rport_io = lpfc_terminate_rport_io, 3937 .terminate_rport_io = lpfc_terminate_rport_io,
3909 3938
3910 .vport_disable = lpfc_vport_disable, 3939 .vport_disable = lpfc_vport_disable,
3940
3941 .set_vport_symbolic_name = lpfc_set_vport_symbolic_name,
3911}; 3942};
3912 3943
3913/** 3944/**
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 26dae8bae2d1..896c7b0351e5 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -560,18 +560,25 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
560 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry); 560 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
561 561
562 /* Don't bother processing response if vport is being torn down. */ 562 /* Don't bother processing response if vport is being torn down. */
563 if (vport->load_flag & FC_UNLOADING) 563 if (vport->load_flag & FC_UNLOADING) {
564 if (vport->fc_flag & FC_RSCN_MODE)
565 lpfc_els_flush_rscn(vport);
564 goto out; 566 goto out;
567 }
565 568
566 if (lpfc_els_chk_latt(vport)) { 569 if (lpfc_els_chk_latt(vport)) {
567 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, 570 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
568 "0216 Link event during NS query\n"); 571 "0216 Link event during NS query\n");
572 if (vport->fc_flag & FC_RSCN_MODE)
573 lpfc_els_flush_rscn(vport);
569 lpfc_vport_set_state(vport, FC_VPORT_FAILED); 574 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
570 goto out; 575 goto out;
571 } 576 }
572 if (lpfc_error_lost_link(irsp)) { 577 if (lpfc_error_lost_link(irsp)) {
573 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, 578 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
574 "0226 NS query failed due to link event\n"); 579 "0226 NS query failed due to link event\n");
580 if (vport->fc_flag & FC_RSCN_MODE)
581 lpfc_els_flush_rscn(vport);
575 goto out; 582 goto out;
576 } 583 }
577 if (irsp->ulpStatus) { 584 if (irsp->ulpStatus) {
@@ -587,6 +594,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
587 if (rc == 0) 594 if (rc == 0)
588 goto out; 595 goto out;
589 } 596 }
597 if (vport->fc_flag & FC_RSCN_MODE)
598 lpfc_els_flush_rscn(vport);
590 lpfc_vport_set_state(vport, FC_VPORT_FAILED); 599 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
591 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, 600 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
592 "0257 GID_FT Query error: 0x%x 0x%x\n", 601 "0257 GID_FT Query error: 0x%x 0x%x\n",
@@ -1008,8 +1017,10 @@ lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
1008 if (n < size) 1017 if (n < size)
1009 n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi); 1018 n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
1010 1019
1011 if (n < size && vport->vname) 1020 if (n < size &&
1012 n += snprintf(symbol + n, size - n, " VName-%s", vport->vname); 1021 strlen(vport->fc_vport->symbolic_name))
1022 n += snprintf(symbol + n, size - n, " VName-%s",
1023 vport->fc_vport->symbolic_name);
1013 return n; 1024 return n;
1014} 1025}
1015 1026
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 50c2faa50f0c..442cb882e6d3 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -221,7 +221,11 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
221 /* For ELS_REQUEST64_CR, use the VPI by default */ 221 /* For ELS_REQUEST64_CR, use the VPI by default */
222 icmd->ulpContext = vport->vpi; 222 icmd->ulpContext = vport->vpi;
223 icmd->ulpCt_h = 0; 223 icmd->ulpCt_h = 0;
224 icmd->ulpCt_l = 1; 224 /* The CT field must be 0=INVALID_RPI for the ECHO cmd */
225 if (elscmd == ELS_CMD_ECHO)
226 icmd->ulpCt_l = 0; /* context = invalid RPI */
227 else
228 icmd->ulpCt_l = 1; /* context = VPI */
225 } 229 }
226 230
227 bpl = (struct ulp_bde64 *) pbuflist->virt; 231 bpl = (struct ulp_bde64 *) pbuflist->virt;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b213d1d01fee..56ed5282117c 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2041,8 +2041,6 @@ destroy_port(struct lpfc_vport *vport)
2041 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 2041 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2042 struct lpfc_hba *phba = vport->phba; 2042 struct lpfc_hba *phba = vport->phba;
2043 2043
2044 kfree(vport->vname);
2045
2046 lpfc_debugfs_terminate(vport); 2044 lpfc_debugfs_terminate(vport);
2047 fc_remove_host(shost); 2045 fc_remove_host(shost);
2048 scsi_remove_host(shost); 2046 scsi_remove_host(shost);
@@ -2716,18 +2714,27 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
2716{ 2714{
2717 struct Scsi_Host *shost = pci_get_drvdata(pdev); 2715 struct Scsi_Host *shost = pci_get_drvdata(pdev);
2718 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; 2716 struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
2717 struct lpfc_vport **vports;
2719 struct lpfc_hba *phba = vport->phba; 2718 struct lpfc_hba *phba = vport->phba;
2719 int i;
2720 int bars = pci_select_bars(pdev, IORESOURCE_MEM); 2720 int bars = pci_select_bars(pdev, IORESOURCE_MEM);
2721 2721
2722 spin_lock_irq(&phba->hbalock); 2722 spin_lock_irq(&phba->hbalock);
2723 vport->load_flag |= FC_UNLOADING; 2723 vport->load_flag |= FC_UNLOADING;
2724 spin_unlock_irq(&phba->hbalock); 2724 spin_unlock_irq(&phba->hbalock);
2725 2725
2726 kfree(vport->vname);
2727 lpfc_free_sysfs_attr(vport); 2726 lpfc_free_sysfs_attr(vport);
2728 2727
2729 kthread_stop(phba->worker_thread); 2728 kthread_stop(phba->worker_thread);
2730 2729
2730 /* Release all the vports against this physical port */
2731 vports = lpfc_create_vport_work_array(phba);
2732 if (vports != NULL)
2733 for (i = 1; i <= phba->max_vpi && vports[i] != NULL; i++)
2734 fc_vport_terminate(vports[i]->fc_vport);
2735 lpfc_destroy_vport_work_array(phba, vports);
2736
2737 /* Remove FC host and then SCSI host with the physical port */
2731 fc_remove_host(shost); 2738 fc_remove_host(shost);
2732 scsi_remove_host(shost); 2739 scsi_remove_host(shost);
2733 lpfc_cleanup(vport); 2740 lpfc_cleanup(vport);
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index a7de1cc02b40..63b54c66756c 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -288,10 +288,8 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
288 int vpi; 288 int vpi;
289 int rc = VPORT_ERROR; 289 int rc = VPORT_ERROR;
290 int status; 290 int status;
291 int size;
292 291
293 if ((phba->sli_rev < 3) || 292 if ((phba->sli_rev < 3) || !(phba->cfg_enable_npiv)) {
294 !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
295 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, 293 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
296 "1808 Create VPORT failed: " 294 "1808 Create VPORT failed: "
297 "NPIV is not enabled: SLImode:%d\n", 295 "NPIV is not enabled: SLImode:%d\n",
@@ -351,20 +349,6 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
351 349
352 memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8); 350 memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8);
353 memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8); 351 memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8);
354 size = strnlen(fc_vport->symbolic_name, LPFC_VNAME_LEN);
355 if (size) {
356 vport->vname = kzalloc(size+1, GFP_KERNEL);
357 if (!vport->vname) {
358 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
359 "1814 Create VPORT failed. "
360 "vname allocation failed.\n");
361 rc = VPORT_ERROR;
362 lpfc_free_vpi(phba, vpi);
363 destroy_port(vport);
364 goto error_out;
365 }
366 memcpy(vport->vname, fc_vport->symbolic_name, size+1);
367 }
368 if (fc_vport->node_name != 0) 352 if (fc_vport->node_name != 0)
369 u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn); 353 u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
370 if (fc_vport->port_name != 0) 354 if (fc_vport->port_name != 0)
@@ -394,6 +378,9 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
394 goto error_out; 378 goto error_out;
395 } 379 }
396 380
381 /* Create binary sysfs attribute for vport */
382 lpfc_alloc_sysfs_attr(vport);
383
397 *(struct lpfc_vport **)fc_vport->dd_data = vport; 384 *(struct lpfc_vport **)fc_vport->dd_data = vport;
398 vport->fc_vport = fc_vport; 385 vport->fc_vport = fc_vport;
399 386
@@ -405,6 +392,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
405 } 392 }
406 393
407 if (disable) { 394 if (disable) {
395 lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
408 rc = VPORT_OK; 396 rc = VPORT_OK;
409 goto out; 397 goto out;
410 } 398 }
@@ -587,8 +575,12 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
587 spin_lock_irq(&phba->hbalock); 575 spin_lock_irq(&phba->hbalock);
588 vport->load_flag |= FC_UNLOADING; 576 vport->load_flag |= FC_UNLOADING;
589 spin_unlock_irq(&phba->hbalock); 577 spin_unlock_irq(&phba->hbalock);
590 kfree(vport->vname); 578
579 lpfc_free_sysfs_attr(vport);
580
591 lpfc_debugfs_terminate(vport); 581 lpfc_debugfs_terminate(vport);
582
583 /* Remove FC host and then SCSI host with the vport */
592 fc_remove_host(lpfc_shost_from_vport(vport)); 584 fc_remove_host(lpfc_shost_from_vport(vport));
593 scsi_remove_host(lpfc_shost_from_vport(vport)); 585 scsi_remove_host(lpfc_shost_from_vport(vport));
594 586