[SCSI] lpfc 8.1.11 : Add soft_wwnn sysfs attribute, rename soft_wwn_enable
authorJames Smart <James.Smart@Emulex.Com>
Sat, 2 Dec 2006 18:35:30 +0000 (13:35 -0500)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Sun, 3 Dec 2006 15:34:43 +0000 (09:34 -0600)
The driver now allows both wwpn and wwnn to be set.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c

index 1ec9cf0e374abd4fcacbfe07ba80979272925cfb..a7de0bca5bdd31efd19b2683e95feaa39e7aadcd 100644 (file)
@@ -306,6 +306,7 @@ struct lpfc_hba {
        uint32_t cfg_use_msi;
        uint32_t cfg_sg_seg_cnt;
        uint32_t cfg_sg_dma_buf_size;
+       uint64_t cfg_soft_wwnn;
        uint64_t cfg_soft_wwpn;
 
        uint32_t dev_loss_tmo_changed;
@@ -358,7 +359,7 @@ struct lpfc_hba {
 #define VPD_PORT            0x8         /* valid vpd port data */
 #define VPD_MASK            0xf         /* mask for any vpd data */
 
-       uint8_t soft_wwpn_enable;
+       uint8_t soft_wwn_enable;
 
        struct timer_list fcp_poll_timer;
        struct timer_list els_tmofunc;
index e2ac7ba3d8ada0249517121f160c0d0e02ecf8bd..f247e786af99487cda664cae44193adec19af7b3 100644 (file)
@@ -552,10 +552,10 @@ static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
 static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
 
 
-static char *lpfc_soft_wwpn_key = "C99G71SL8032A";
+static char *lpfc_soft_wwn_key = "C99G71SL8032A";
 
 static ssize_t
-lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf,
+lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
                                size_t count)
 {
        struct Scsi_Host *host = class_to_shost(cdev);
@@ -579,15 +579,15 @@ lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf,
        if (buf[cnt-1] == '\n')
                cnt--;
 
-       if ((cnt != strlen(lpfc_soft_wwpn_key)) ||
-           (strncmp(buf, lpfc_soft_wwpn_key, strlen(lpfc_soft_wwpn_key)) != 0))
+       if ((cnt != strlen(lpfc_soft_wwn_key)) ||
+           (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0))
                return -EINVAL;
 
-       phba->soft_wwpn_enable = 1;
+       phba->soft_wwn_enable = 1;
        return count;
 }
-static CLASS_DEVICE_ATTR(lpfc_soft_wwpn_enable, S_IWUSR, NULL,
-                               lpfc_soft_wwpn_enable_store);
+static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
+                               lpfc_soft_wwn_enable_store);
 
 static ssize_t
 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)
        if (buf[cnt-1] == '\n')
                cnt--;
 
-       if (!phba->soft_wwpn_enable || (cnt < 16) || (cnt > 18) ||
+       if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) ||
            ((cnt == 17) && (*buf++ != 'x')) ||
            ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
                return -EINVAL;
 
-       phba->soft_wwpn_enable = 0;
+       phba->soft_wwn_enable = 0;
 
        memset(wwpn, 0, sizeof(wwpn));
 
@@ -639,6 +639,8 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
        }
        phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
        fc_host_port_name(host) = phba->cfg_soft_wwpn;
+       if (phba->cfg_soft_wwnn)
+               fc_host_node_name(host) = phba->cfg_soft_wwnn;
 
        dev_printk(KERN_NOTICE, &phba->pcidev->dev,
                   "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)
 static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
                         lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
 
+static ssize_t
+lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
+{
+       struct Scsi_Host *host = class_to_shost(cdev);
+       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       return snprintf(buf, PAGE_SIZE, "0x%llx\n",
+                       (unsigned long long)phba->cfg_soft_wwnn);
+}
+
+
+static ssize_t
+lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
+{
+       struct Scsi_Host *host = class_to_shost(cdev);
+       struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
+       unsigned int i, j, cnt=count;
+       u8 wwnn[8];
+
+       /* count may include a LF at end of string */
+       if (buf[cnt-1] == '\n')
+               cnt--;
+
+       if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) ||
+           ((cnt == 17) && (*buf++ != 'x')) ||
+           ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
+               return -EINVAL;
+
+       /*
+        * Allow wwnn to be set many times, as long as the enable is set.
+        * However, once the wwpn is set, everything locks.
+        */
+
+       memset(wwnn, 0, sizeof(wwnn));
+
+       /* Validate and store the new name */
+       for (i=0, j=0; i < 16; i++) {
+               if ((*buf >= 'a') && (*buf <= 'f'))
+                       j = ((j << 4) | ((*buf++ -'a') + 10));
+               else if ((*buf >= 'A') && (*buf <= 'F'))
+                       j = ((j << 4) | ((*buf++ -'A') + 10));
+               else if ((*buf >= '0') && (*buf <= '9'))
+                       j = ((j << 4) | (*buf++ -'0'));
+               else
+                       return -EINVAL;
+               if (i % 2) {
+                       wwnn[i/2] = j & 0xff;
+                       j = 0;
+               }
+       }
+       phba->cfg_soft_wwnn = wwn_to_u64(wwnn);
+
+       dev_printk(KERN_NOTICE, &phba->pcidev->dev,
+                  "lpfc%d: soft_wwnn set. Value will take effect upon "
+                  "setting of the soft_wwpn\n", phba->brd_no);
+
+       return count;
+}
+static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
+                        lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
+
 
 static int lpfc_poll = 0;
 module_param(lpfc_poll, int, 0);
@@ -1009,8 +1071,9 @@ struct class_device_attribute *lpfc_host_attrs[] = {
        &class_device_attr_lpfc_poll,
        &class_device_attr_lpfc_poll_tmo,
        &class_device_attr_lpfc_use_msi,
+       &class_device_attr_lpfc_soft_wwnn,
        &class_device_attr_lpfc_soft_wwpn,
-       &class_device_attr_lpfc_soft_wwpn_enable,
+       &class_device_attr_lpfc_soft_wwn_enable,
        NULL,
 };
 
@@ -1815,6 +1878,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
        lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
        lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
        phba->cfg_poll = lpfc_poll;
+       phba->cfg_soft_wwnn = 0L;
        phba->cfg_soft_wwpn = 0L;
 
        /*
index 1118b6d49fccc88c717f6d9ef7abc635db2f0cf6..c39564e85e944f62ebed5d8b3d41a6f75daf4ff7 100644 (file)
@@ -672,6 +672,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
 
        memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt,
               sizeof (struct serv_parm));
+       if (phba->cfg_soft_wwnn)
+               u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
        if (phba->cfg_soft_wwpn)
                u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
        memcpy((uint8_t *) & phba->fc_nodename,
index b872519e2cedf19c337541a8d7467a67f714d64b..cf9081c262d7a92d6950cf88efd9c6feab896f64 100644 (file)
@@ -268,6 +268,8 @@ lpfc_config_port_post(struct lpfc_hba * phba)
        kfree(mp);
        pmb->context1 = NULL;
 
+       if (phba->cfg_soft_wwnn)
+               u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
        if (phba->cfg_soft_wwpn)
                u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
        memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,