diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 84 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 2 |
4 files changed, 80 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 1ec9cf0e374a..a7de0bca5bdd 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -306,6 +306,7 @@ struct lpfc_hba { | |||
306 | uint32_t cfg_use_msi; | 306 | uint32_t cfg_use_msi; |
307 | uint32_t cfg_sg_seg_cnt; | 307 | uint32_t cfg_sg_seg_cnt; |
308 | uint32_t cfg_sg_dma_buf_size; | 308 | uint32_t cfg_sg_dma_buf_size; |
309 | uint64_t cfg_soft_wwnn; | ||
309 | uint64_t cfg_soft_wwpn; | 310 | uint64_t cfg_soft_wwpn; |
310 | 311 | ||
311 | uint32_t dev_loss_tmo_changed; | 312 | uint32_t dev_loss_tmo_changed; |
@@ -358,7 +359,7 @@ struct lpfc_hba { | |||
358 | #define VPD_PORT 0x8 /* valid vpd port data */ | 359 | #define VPD_PORT 0x8 /* valid vpd port data */ |
359 | #define VPD_MASK 0xf /* mask for any vpd data */ | 360 | #define VPD_MASK 0xf /* mask for any vpd data */ |
360 | 361 | ||
361 | uint8_t soft_wwpn_enable; | 362 | uint8_t soft_wwn_enable; |
362 | 363 | ||
363 | struct timer_list fcp_poll_timer; | 364 | struct timer_list fcp_poll_timer; |
364 | struct timer_list els_tmofunc; | 365 | struct timer_list els_tmofunc; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e2ac7ba3d8ad..f247e786af99 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -552,10 +552,10 @@ static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR, | |||
552 | static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); | 552 | static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); |
553 | 553 | ||
554 | 554 | ||
555 | static char *lpfc_soft_wwpn_key = "C99G71SL8032A"; | 555 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
556 | 556 | ||
557 | static ssize_t | 557 | static ssize_t |
558 | lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, | 558 | lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf, |
559 | size_t count) | 559 | size_t count) |
560 | { | 560 | { |
561 | struct Scsi_Host *host = class_to_shost(cdev); | 561 | struct Scsi_Host *host = class_to_shost(cdev); |
@@ -579,15 +579,15 @@ lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, | |||
579 | if (buf[cnt-1] == '\n') | 579 | if (buf[cnt-1] == '\n') |
580 | cnt--; | 580 | cnt--; |
581 | 581 | ||
582 | if ((cnt != strlen(lpfc_soft_wwpn_key)) || | 582 | if ((cnt != strlen(lpfc_soft_wwn_key)) || |
583 | (strncmp(buf, lpfc_soft_wwpn_key, strlen(lpfc_soft_wwpn_key)) != 0)) | 583 | (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0)) |
584 | return -EINVAL; | 584 | return -EINVAL; |
585 | 585 | ||
586 | phba->soft_wwpn_enable = 1; | 586 | phba->soft_wwn_enable = 1; |
587 | return count; | 587 | return count; |
588 | } | 588 | } |
589 | static CLASS_DEVICE_ATTR(lpfc_soft_wwpn_enable, S_IWUSR, NULL, | 589 | static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, |
590 | lpfc_soft_wwpn_enable_store); | 590 | lpfc_soft_wwn_enable_store); |
591 | 591 | ||
592 | static ssize_t | 592 | static ssize_t |
593 | lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) | 593 | lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) |
@@ -613,12 +613,12 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
613 | if (buf[cnt-1] == '\n') | 613 | if (buf[cnt-1] == '\n') |
614 | cnt--; | 614 | cnt--; |
615 | 615 | ||
616 | if (!phba->soft_wwpn_enable || (cnt < 16) || (cnt > 18) || | 616 | if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || |
617 | ((cnt == 17) && (*buf++ != 'x')) || | 617 | ((cnt == 17) && (*buf++ != 'x')) || |
618 | ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) | 618 | ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) |
619 | return -EINVAL; | 619 | return -EINVAL; |
620 | 620 | ||
621 | phba->soft_wwpn_enable = 0; | 621 | phba->soft_wwn_enable = 0; |
622 | 622 | ||
623 | memset(wwpn, 0, sizeof(wwpn)); | 623 | memset(wwpn, 0, sizeof(wwpn)); |
624 | 624 | ||
@@ -639,6 +639,8 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
639 | } | 639 | } |
640 | phba->cfg_soft_wwpn = wwn_to_u64(wwpn); | 640 | phba->cfg_soft_wwpn = wwn_to_u64(wwpn); |
641 | fc_host_port_name(host) = phba->cfg_soft_wwpn; | 641 | fc_host_port_name(host) = phba->cfg_soft_wwpn; |
642 | if (phba->cfg_soft_wwnn) | ||
643 | fc_host_node_name(host) = phba->cfg_soft_wwnn; | ||
642 | 644 | ||
643 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, | 645 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, |
644 | "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); | 646 | "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); |
@@ -664,6 +666,66 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
664 | static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ | 666 | static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ |
665 | lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); | 667 | lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); |
666 | 668 | ||
669 | static ssize_t | ||
670 | lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) | ||
671 | { | ||
672 | struct Scsi_Host *host = class_to_shost(cdev); | ||
673 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | ||
674 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", | ||
675 | (unsigned long long)phba->cfg_soft_wwnn); | ||
676 | } | ||
677 | |||
678 | |||
679 | static ssize_t | ||
680 | lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) | ||
681 | { | ||
682 | struct Scsi_Host *host = class_to_shost(cdev); | ||
683 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | ||
684 | unsigned int i, j, cnt=count; | ||
685 | u8 wwnn[8]; | ||
686 | |||
687 | /* count may include a LF at end of string */ | ||
688 | if (buf[cnt-1] == '\n') | ||
689 | cnt--; | ||
690 | |||
691 | if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || | ||
692 | ((cnt == 17) && (*buf++ != 'x')) || | ||
693 | ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) | ||
694 | return -EINVAL; | ||
695 | |||
696 | /* | ||
697 | * Allow wwnn to be set many times, as long as the enable is set. | ||
698 | * However, once the wwpn is set, everything locks. | ||
699 | */ | ||
700 | |||
701 | memset(wwnn, 0, sizeof(wwnn)); | ||
702 | |||
703 | /* Validate and store the new name */ | ||
704 | for (i=0, j=0; i < 16; i++) { | ||
705 | if ((*buf >= 'a') && (*buf <= 'f')) | ||
706 | j = ((j << 4) | ((*buf++ -'a') + 10)); | ||
707 | else if ((*buf >= 'A') && (*buf <= 'F')) | ||
708 | j = ((j << 4) | ((*buf++ -'A') + 10)); | ||
709 | else if ((*buf >= '0') && (*buf <= '9')) | ||
710 | j = ((j << 4) | (*buf++ -'0')); | ||
711 | else | ||
712 | return -EINVAL; | ||
713 | if (i % 2) { | ||
714 | wwnn[i/2] = j & 0xff; | ||
715 | j = 0; | ||
716 | } | ||
717 | } | ||
718 | phba->cfg_soft_wwnn = wwn_to_u64(wwnn); | ||
719 | |||
720 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, | ||
721 | "lpfc%d: soft_wwnn set. Value will take effect upon " | ||
722 | "setting of the soft_wwpn\n", phba->brd_no); | ||
723 | |||
724 | return count; | ||
725 | } | ||
726 | static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\ | ||
727 | lpfc_soft_wwnn_show, lpfc_soft_wwnn_store); | ||
728 | |||
667 | 729 | ||
668 | static int lpfc_poll = 0; | 730 | static int lpfc_poll = 0; |
669 | module_param(lpfc_poll, int, 0); | 731 | module_param(lpfc_poll, int, 0); |
@@ -1009,8 +1071,9 @@ struct class_device_attribute *lpfc_host_attrs[] = { | |||
1009 | &class_device_attr_lpfc_poll, | 1071 | &class_device_attr_lpfc_poll, |
1010 | &class_device_attr_lpfc_poll_tmo, | 1072 | &class_device_attr_lpfc_poll_tmo, |
1011 | &class_device_attr_lpfc_use_msi, | 1073 | &class_device_attr_lpfc_use_msi, |
1074 | &class_device_attr_lpfc_soft_wwnn, | ||
1012 | &class_device_attr_lpfc_soft_wwpn, | 1075 | &class_device_attr_lpfc_soft_wwpn, |
1013 | &class_device_attr_lpfc_soft_wwpn_enable, | 1076 | &class_device_attr_lpfc_soft_wwn_enable, |
1014 | NULL, | 1077 | NULL, |
1015 | }; | 1078 | }; |
1016 | 1079 | ||
@@ -1815,6 +1878,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
1815 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); | 1878 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); |
1816 | lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); | 1879 | lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); |
1817 | phba->cfg_poll = lpfc_poll; | 1880 | phba->cfg_poll = lpfc_poll; |
1881 | phba->cfg_soft_wwnn = 0L; | ||
1818 | phba->cfg_soft_wwpn = 0L; | 1882 | phba->cfg_soft_wwpn = 0L; |
1819 | 1883 | ||
1820 | /* | 1884 | /* |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 1118b6d49fcc..c39564e85e94 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -672,6 +672,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
672 | 672 | ||
673 | memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt, | 673 | memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt, |
674 | sizeof (struct serv_parm)); | 674 | sizeof (struct serv_parm)); |
675 | if (phba->cfg_soft_wwnn) | ||
676 | u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn); | ||
675 | if (phba->cfg_soft_wwpn) | 677 | if (phba->cfg_soft_wwpn) |
676 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); | 678 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); |
677 | memcpy((uint8_t *) & phba->fc_nodename, | 679 | memcpy((uint8_t *) & phba->fc_nodename, |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b872519e2ced..cf9081c262d7 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -268,6 +268,8 @@ lpfc_config_port_post(struct lpfc_hba * phba) | |||
268 | kfree(mp); | 268 | kfree(mp); |
269 | pmb->context1 = NULL; | 269 | pmb->context1 = NULL; |
270 | 270 | ||
271 | if (phba->cfg_soft_wwnn) | ||
272 | u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn); | ||
271 | if (phba->cfg_soft_wwpn) | 273 | if (phba->cfg_soft_wwpn) |
272 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); | 274 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); |
273 | memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName, | 275 | memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName, |