aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2011-08-21 21:49:16 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-29 03:16:19 -0400
commitf7a919b4cd048f345c07c2235d0fb8ac93d24cca (patch)
tree2abd6930e878997db35dc57bf8374a3af6272a59 /drivers/scsi/lpfc
parent079b5c916d19e7533c060b32d4a31ce45c3552d2 (diff)
[SCSI] lpfc 8.3.26: Fix SYSFS interface issues
Fix SYSFS interface issues. - In the lpfc_sli4_pdev_status_reg_wait() routine, after initial 100ms delay following write to PHYSDEV_CONTROL register for the firmware reaction, check the RN bit and ERR bit of the SLIPORT_STATUS register. If none of them became 1, the previous PHYSDEV_CONTROL register should be considered failed due to lack of privilege and error for no permission should be returned immediately without getting into the wait for RDY bits on the SLIPORT_STATUS register. - Remove the driver check on dev->is_physfn before proceed to perform the PHYSDEV_CONTROL register write, and let the PCI function's privilege setting and driver handling of PHYSDEV_CONTROL register write failure to handle the reset-ability through the SLI port. - Added key to ctlreg_write to prevent unauthorized or unexpected write to the control register. - Change return to EACCES for sysfs access that are failed because hba_reset is disabled. Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c42
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c3
2 files changed, 28 insertions, 17 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 2542f1f8bf8..13215cd396a 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -52,6 +52,13 @@
52#define LPFC_MIN_DEVLOSS_TMO 1 52#define LPFC_MIN_DEVLOSS_TMO 1
53#define LPFC_MAX_DEVLOSS_TMO 255 53#define LPFC_MAX_DEVLOSS_TMO 255
54 54
55/*
56 * Write key size should be multiple of 4. If write key is changed
57 * make sure that library write key is also changed.
58 */
59#define LPFC_REG_WRITE_KEY_SIZE 4
60#define LPFC_REG_WRITE_KEY "EMLX"
61
55/** 62/**
56 * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules 63 * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
57 * @incr: integer to convert. 64 * @incr: integer to convert.
@@ -693,7 +700,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
693 int rc; 700 int rc;
694 701
695 if (!phba->cfg_enable_hba_reset) 702 if (!phba->cfg_enable_hba_reset)
696 return -EIO; 703 return -EACCES;
697 704
698 status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); 705 status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
699 706
@@ -768,13 +775,18 @@ lpfc_issue_reset(struct device *dev, struct device_attribute *attr,
768static int 775static int
769lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) 776lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba)
770{ 777{
771 struct lpfc_register portstat_reg; 778 struct lpfc_register portstat_reg = {0};
772 int i; 779 int i;
773 780
774 781 msleep(100);
775 lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr, 782 lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
776 &portstat_reg.word0); 783 &portstat_reg.word0);
777 784
785 /* verify if privilaged for the request operation */
786 if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
787 !bf_get(lpfc_sliport_status_err, &portstat_reg))
788 return -EPERM;
789
778 /* wait for the SLI port firmware ready after firmware reset */ 790 /* wait for the SLI port firmware ready after firmware reset */
779 for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) { 791 for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
780 msleep(10); 792 msleep(10);
@@ -816,16 +828,13 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
816 int rc; 828 int rc;
817 829
818 if (!phba->cfg_enable_hba_reset) 830 if (!phba->cfg_enable_hba_reset)
819 return -EIO; 831 return -EACCES;
820 832
821 if ((phba->sli_rev < LPFC_SLI_REV4) || 833 if ((phba->sli_rev < LPFC_SLI_REV4) ||
822 (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != 834 (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) !=
823 LPFC_SLI_INTF_IF_TYPE_2)) 835 LPFC_SLI_INTF_IF_TYPE_2))
824 return -EPERM; 836 return -EPERM;
825 837
826 if (!pdev->is_physfn)
827 return -EPERM;
828
829 /* Disable SR-IOV virtual functions if enabled */ 838 /* Disable SR-IOV virtual functions if enabled */
830 if (phba->cfg_sriov_nr_virtfn) { 839 if (phba->cfg_sriov_nr_virtfn) {
831 pci_disable_sriov(pdev); 840 pci_disable_sriov(pdev);
@@ -858,7 +867,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode)
858 rc = lpfc_sli4_pdev_status_reg_wait(phba); 867 rc = lpfc_sli4_pdev_status_reg_wait(phba);
859 868
860 if (rc) 869 if (rc)
861 return -EIO; 870 return rc;
862 871
863 init_completion(&online_compl); 872 init_completion(&online_compl);
864 rc = lpfc_workq_post_event(phba, &status, &online_compl, 873 rc = lpfc_workq_post_event(phba, &status, &online_compl,
@@ -984,7 +993,7 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
984 if (!status) 993 if (!status)
985 return strlen(buf); 994 return strlen(buf);
986 else 995 else
987 return -EIO; 996 return status;
988} 997}
989 998
990/** 999/**
@@ -3885,18 +3894,23 @@ sysfs_ctlreg_write(struct file *filp, struct kobject *kobj,
3885 if ((off + count) > FF_REG_AREA_SIZE) 3894 if ((off + count) > FF_REG_AREA_SIZE)
3886 return -ERANGE; 3895 return -ERANGE;
3887 3896
3888 if (count == 0) return 0; 3897 if (count <= LPFC_REG_WRITE_KEY_SIZE)
3898 return 0;
3889 3899
3890 if (off % 4 || count % 4 || (unsigned long)buf % 4) 3900 if (off % 4 || count % 4 || (unsigned long)buf % 4)
3891 return -EINVAL; 3901 return -EINVAL;
3892 3902
3893 if (!(vport->fc_flag & FC_OFFLINE_MODE)) { 3903 /* This is to protect HBA registers from accidental writes. */
3904 if (memcmp(buf, LPFC_REG_WRITE_KEY, LPFC_REG_WRITE_KEY_SIZE))
3905 return -EINVAL;
3906
3907 if (!(vport->fc_flag & FC_OFFLINE_MODE))
3894 return -EPERM; 3908 return -EPERM;
3895 }
3896 3909
3897 spin_lock_irq(&phba->hbalock); 3910 spin_lock_irq(&phba->hbalock);
3898 for (buf_off = 0; buf_off < count; buf_off += sizeof(uint32_t)) 3911 for (buf_off = 0; buf_off < count - LPFC_REG_WRITE_KEY_SIZE;
3899 writel(*((uint32_t *)(buf + buf_off)), 3912 buf_off += sizeof(uint32_t))
3913 writel(*((uint32_t *)(buf + buf_off + LPFC_REG_WRITE_KEY_SIZE)),
3900 phba->ctrl_regs_memmap_p + off + buf_off); 3914 phba->ctrl_regs_memmap_p + off + buf_off);
3901 3915
3902 spin_unlock_irq(&phba->hbalock); 3916 spin_unlock_irq(&phba->hbalock);
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index b9ff38fa7c2..d8ac7694854 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4056,9 +4056,6 @@ lpfc_sli_sriov_nr_virtfn_get(struct lpfc_hba *phba)
4056 uint16_t nr_virtfn; 4056 uint16_t nr_virtfn;
4057 int pos; 4057 int pos;
4058 4058
4059 if (!pdev->is_physfn)
4060 return 0;
4061
4062 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); 4059 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
4063 if (pos == 0) 4060 if (pos == 0)
4064 return 0; 4061 return 0;