aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc.h3
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c84
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
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,
552static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); 552static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
553 553
554 554
555static char *lpfc_soft_wwpn_key = "C99G71SL8032A"; 555static char *lpfc_soft_wwn_key = "C99G71SL8032A";
556 556
557static ssize_t 557static ssize_t
558lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, 558lpfc_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}
589static CLASS_DEVICE_ATTR(lpfc_soft_wwpn_enable, S_IWUSR, NULL, 589static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
590 lpfc_soft_wwpn_enable_store); 590 lpfc_soft_wwn_enable_store);
591 591
592static ssize_t 592static ssize_t
593lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) 593lpfc_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)
664static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ 666static 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
669static ssize_t
670lpfc_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
679static ssize_t
680lpfc_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}
726static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
727 lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
728
667 729
668static int lpfc_poll = 0; 730static int lpfc_poll = 0;
669module_param(lpfc_poll, int, 0); 731module_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,