diff options
author | Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com> | 2013-09-18 03:32:44 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-10-25 04:58:16 -0400 |
commit | 279094079a442c19ff7e7c0fd9511d9404cb2518 (patch) | |
tree | 58a509a4ecb9160ddb5793db4200f9a6f7f5af68 /drivers/scsi/pm8001 | |
parent | 06f12f22cefdc2737b54fc986d9b82ec358cdbb8 (diff) |
[SCSI] pm80xx: Phy settings support for motherboard controller.
Phy profile implementation to support phy settings feature
for motherboard controllers.
[jejb: checkpatch fixes]
Signed-off-by: Anandkumar.Santhanam@pmcs.com
Reviewed-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 10 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 29 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 3 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 61 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.h | 4 |
5 files changed, 104 insertions, 3 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 7e879c5d0928..9d1178bcf689 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -4831,6 +4831,16 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
4831 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); | 4831 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); |
4832 | break; | 4832 | break; |
4833 | } | 4833 | } |
4834 | case IOP_RDUMP: { | ||
4835 | nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP); | ||
4836 | nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length); | ||
4837 | nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset); | ||
4838 | nvmd_req.resp_addr_hi = | ||
4839 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi); | ||
4840 | nvmd_req.resp_addr_lo = | ||
4841 | cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo); | ||
4842 | break; | ||
4843 | } | ||
4834 | default: | 4844 | default: |
4835 | break; | 4845 | break; |
4836 | } | 4846 | } |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 93e2d9e9d2b3..92a18c4d2ebb 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
@@ -667,6 +667,31 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
667 | #endif | 667 | #endif |
668 | } | 668 | } |
669 | 669 | ||
670 | /* | ||
671 | * pm8001_get_phy_settings_info : Read phy setting values. | ||
672 | * @pm8001_ha : our hba. | ||
673 | */ | ||
674 | void pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) | ||
675 | { | ||
676 | |||
677 | #ifdef PM8001_READ_VPD | ||
678 | /*OPTION ROM FLASH read for the SPC cards */ | ||
679 | DECLARE_COMPLETION_ONSTACK(completion); | ||
680 | struct pm8001_ioctl_payload payload; | ||
681 | |||
682 | pm8001_ha->nvmd_completion = &completion; | ||
683 | /* SAS ADDRESS read from flash / EEPROM */ | ||
684 | payload.minor_function = 6; | ||
685 | payload.offset = 0; | ||
686 | payload.length = 4096; | ||
687 | payload.func_specific = kzalloc(4096, GFP_KERNEL); | ||
688 | /* Read phy setting values from flash */ | ||
689 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); | ||
690 | wait_for_completion(&completion); | ||
691 | pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific); | ||
692 | #endif | ||
693 | } | ||
694 | |||
670 | #ifdef PM8001_USE_MSIX | 695 | #ifdef PM8001_USE_MSIX |
671 | /** | 696 | /** |
672 | * pm8001_setup_msix - enable MSI-X interrupt | 697 | * pm8001_setup_msix - enable MSI-X interrupt |
@@ -847,6 +872,10 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
847 | } | 872 | } |
848 | 873 | ||
849 | pm8001_init_sas_add(pm8001_ha); | 874 | pm8001_init_sas_add(pm8001_ha); |
875 | /* phy setting support for motherboard controller */ | ||
876 | if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && | ||
877 | pdev->subsystem_vendor != 0) | ||
878 | pm8001_get_phy_settings_info(pm8001_ha); | ||
850 | pm8001_post_sas_ha_init(shost, chip); | 879 | pm8001_post_sas_ha_init(shost, chip); |
851 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); | 880 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); |
852 | if (rc) | 881 | if (rc) |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 68e1147e3cec..cbde11a57a92 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -632,7 +632,8 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | |||
632 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | 632 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); |
633 | 633 | ||
634 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 634 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
635 | 635 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | |
636 | u32 length, u8 *buf); | ||
636 | /* ctl shared API */ | 637 | /* ctl shared API */ |
637 | extern struct device_attribute *pm8001_host_attrs[]; | 638 | extern struct device_attribute *pm8001_host_attrs[]; |
638 | 639 | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index c8a4465b74a5..91cf4242a03d 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
@@ -3183,9 +3183,27 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
3183 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, | 3183 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, |
3184 | void *piomb) | 3184 | void *piomb) |
3185 | { | 3185 | { |
3186 | PM8001_MSG_DBG(pm8001_ha, | 3186 | u8 page_code; |
3187 | pm8001_printk(" pm80xx_addition_functionality\n")); | 3187 | struct set_phy_profile_resp *pPayload = |
3188 | (struct set_phy_profile_resp *)(piomb + 4); | ||
3189 | u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid); | ||
3190 | u32 status = le32_to_cpu(pPayload->status); | ||
3188 | 3191 | ||
3192 | page_code = (u8)((ppc_phyid & 0xFF00) >> 8); | ||
3193 | if (status) { | ||
3194 | /* status is FAILED */ | ||
3195 | PM8001_FAIL_DBG(pm8001_ha, | ||
3196 | pm8001_printk("PhyProfile command failed with status " | ||
3197 | "0x%08X \n", status)); | ||
3198 | return -1; | ||
3199 | } else { | ||
3200 | if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) { | ||
3201 | PM8001_FAIL_DBG(pm8001_ha, | ||
3202 | pm8001_printk("Invalid page code 0x%X\n", | ||
3203 | page_code)); | ||
3204 | return -1; | ||
3205 | } | ||
3206 | } | ||
3189 | return 0; | 3207 | return 0; |
3190 | } | 3208 | } |
3191 | 3209 | ||
@@ -4281,6 +4299,45 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) | |||
4281 | return IRQ_HANDLED; | 4299 | return IRQ_HANDLED; |
4282 | } | 4300 | } |
4283 | 4301 | ||
4302 | void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, | ||
4303 | u32 operation, u32 phyid, u32 length, u32 *buf) | ||
4304 | { | ||
4305 | u32 tag , i, j = 0; | ||
4306 | int rc; | ||
4307 | struct set_phy_profile_req payload; | ||
4308 | struct inbound_queue_table *circularQ; | ||
4309 | u32 opc = OPC_INB_SET_PHY_PROFILE; | ||
4310 | |||
4311 | memset(&payload, 0, sizeof(payload)); | ||
4312 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
4313 | if (rc) | ||
4314 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n")); | ||
4315 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
4316 | payload.tag = cpu_to_le32(tag); | ||
4317 | payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid & 0xFF)); | ||
4318 | PM8001_INIT_DBG(pm8001_ha, | ||
4319 | pm8001_printk(" phy profile command for phy %x ,length is %d\n", | ||
4320 | payload.ppc_phyid, length)); | ||
4321 | for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { | ||
4322 | payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); | ||
4323 | j++; | ||
4324 | } | ||
4325 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
4326 | } | ||
4327 | |||
4328 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | ||
4329 | u32 length, u8 *buf) | ||
4330 | { | ||
4331 | u32 page_code, i; | ||
4332 | |||
4333 | page_code = SAS_PHY_ANALOG_SETTINGS_PAGE; | ||
4334 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | ||
4335 | mpi_set_phy_profile_req(pm8001_ha, | ||
4336 | SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf); | ||
4337 | length = length + PHY_DWORD_LENGTH; | ||
4338 | } | ||
4339 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); | ||
4340 | } | ||
4284 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | 4341 | const struct pm8001_dispatch pm8001_80xx_dispatch = { |
4285 | .name = "pmc80xx", | 4342 | .name = "pmc80xx", |
4286 | .chip_init = pm80xx_chip_init, | 4343 | .chip_init = pm80xx_chip_init, |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index 9a9116d43566..872d5cff824f 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h | |||
@@ -170,6 +170,10 @@ | |||
170 | #define LINKRATE_60 (0x06 << 8) | 170 | #define LINKRATE_60 (0x06 << 8) |
171 | #define LINKRATE_120 (0x08 << 8) | 171 | #define LINKRATE_120 (0x08 << 8) |
172 | 172 | ||
173 | /* phy_profile */ | ||
174 | #define SAS_PHY_ANALOG_SETTINGS_PAGE 0x04 | ||
175 | #define PHY_DWORD_LENGTH 0xC | ||
176 | |||
173 | /* Thermal related */ | 177 | /* Thermal related */ |
174 | #define THERMAL_ENABLE 0x1 | 178 | #define THERMAL_ENABLE 0x1 |
175 | #define THERMAL_LOG_ENABLE 0x1 | 179 | #define THERMAL_LOG_ENABLE 0x1 |