Commit cd135754 authored by Deepak Ukey's avatar Deepak Ukey Committed by Martin K. Petersen

scsi: pm80xx: Fix for phy enable/disable functionality

Added proper mask for phy id in mpi_phy_stop_resp().
Signed-off-by: default avatarDeepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: default avatarViswas G <Viswas.G@microchip.com>
Acked-by: default avatarJack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 0b1b1d88
...@@ -132,4 +132,12 @@ enum pm8001_hba_info_flags { ...@@ -132,4 +132,12 @@ enum pm8001_hba_info_flags {
PM8001F_RUN_TIME = (1U << 1), PM8001F_RUN_TIME = (1U << 1),
}; };
/**
* Phy Status
*/
#define PHY_LINK_DISABLE 0x00
#define PHY_LINK_DOWN 0x01
#define PHY_STATE_LINK_UP_SPCV 0x2
#define PHY_STATE_LINK_UP_SPC 0x1
#endif #endif
...@@ -3810,7 +3810,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) ...@@ -3810,7 +3810,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
" status = %x\n", status)); " status = %x\n", status));
if (status == 0) { if (status == 0) {
phy->phy_state = 1; phy->phy_state = 1;
if (pm8001_ha->flags == PM8001F_RUN_TIME) if (pm8001_ha->flags == PM8001F_RUN_TIME &&
phy->enable_completion != NULL)
complete(phy->enable_completion); complete(phy->enable_completion);
} }
break; break;
......
...@@ -131,10 +131,6 @@ ...@@ -131,10 +131,6 @@
#define LINKRATE_30 (0x02 << 8) #define LINKRATE_30 (0x02 << 8)
#define LINKRATE_60 (0x04 << 8) #define LINKRATE_60 (0x04 << 8)
/* for phy state */
#define PHY_STATE_LINK_UP_SPC 0x1
/* for new SPC controllers MEMBASE III is shared between BIOS and DATA */ /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
#define GSM_SM_BASE 0x4F0000 #define GSM_SM_BASE 0x4F0000
struct mpi_msg_hdr{ struct mpi_msg_hdr{
......
...@@ -121,7 +121,7 @@ static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id) ...@@ -121,7 +121,7 @@ static void pm8001_phy_init(struct pm8001_hba_info *pm8001_ha, int phy_id)
{ {
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
struct asd_sas_phy *sas_phy = &phy->sas_phy; struct asd_sas_phy *sas_phy = &phy->sas_phy;
phy->phy_state = 0; phy->phy_state = PHY_LINK_DISABLE;
phy->pm8001_ha = pm8001_ha; phy->pm8001_ha = pm8001_ha;
sas_phy->enabled = (phy_id < pm8001_ha->chip->n_phy) ? 1 : 0; sas_phy->enabled = (phy_id < pm8001_ha->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS; sas_phy->class = SAS;
...@@ -1067,6 +1067,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev, ...@@ -1067,6 +1067,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
if (rc) if (rc)
goto err_out_shost; goto err_out_shost;
scsi_scan_host(pm8001_ha->shost); scsi_scan_host(pm8001_ha->shost);
pm8001_ha->flags = PM8001F_RUN_TIME;
return 0; return 0;
err_out_shost: err_out_shost:
......
...@@ -157,9 +157,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, ...@@ -157,9 +157,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
int rc = 0, phy_id = sas_phy->id; int rc = 0, phy_id = sas_phy->id;
struct pm8001_hba_info *pm8001_ha = NULL; struct pm8001_hba_info *pm8001_ha = NULL;
struct sas_phy_linkrates *rates; struct sas_phy_linkrates *rates;
struct sas_ha_struct *sas_ha;
struct pm8001_phy *phy;
DECLARE_COMPLETION_ONSTACK(completion); DECLARE_COMPLETION_ONSTACK(completion);
unsigned long flags; unsigned long flags;
pm8001_ha = sas_phy->ha->lldd_ha; pm8001_ha = sas_phy->ha->lldd_ha;
phy = &pm8001_ha->phy[phy_id];
pm8001_ha->phy[phy_id].enable_completion = &completion; pm8001_ha->phy[phy_id].enable_completion = &completion;
switch (func) { switch (func) {
case PHY_FUNC_SET_LINK_RATE: case PHY_FUNC_SET_LINK_RATE:
...@@ -172,7 +175,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, ...@@ -172,7 +175,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
pm8001_ha->phy[phy_id].maximum_linkrate = pm8001_ha->phy[phy_id].maximum_linkrate =
rates->maximum_linkrate; rates->maximum_linkrate;
} }
if (pm8001_ha->phy[phy_id].phy_state == 0) { if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id); PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion(&completion); wait_for_completion(&completion);
} }
...@@ -180,7 +183,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, ...@@ -180,7 +183,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PHY_LINK_RESET); PHY_LINK_RESET);
break; break;
case PHY_FUNC_HARD_RESET: case PHY_FUNC_HARD_RESET:
if (pm8001_ha->phy[phy_id].phy_state == 0) { if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id); PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion(&completion); wait_for_completion(&completion);
} }
...@@ -188,7 +191,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, ...@@ -188,7 +191,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PHY_HARD_RESET); PHY_HARD_RESET);
break; break;
case PHY_FUNC_LINK_RESET: case PHY_FUNC_LINK_RESET:
if (pm8001_ha->phy[phy_id].phy_state == 0) { if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id); PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion(&completion); wait_for_completion(&completion);
} }
...@@ -200,6 +203,25 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, ...@@ -200,6 +203,25 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PHY_LINK_RESET); PHY_LINK_RESET);
break; break;
case PHY_FUNC_DISABLE: case PHY_FUNC_DISABLE:
if (pm8001_ha->chip_id != chip_8001) {
if (pm8001_ha->phy[phy_id].phy_state ==
PHY_STATE_LINK_UP_SPCV) {
sas_ha = pm8001_ha->sas;
sas_phy_disconnected(&phy->sas_phy);
sas_ha->notify_phy_event(&phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
}
} else {
if (pm8001_ha->phy[phy_id].phy_state ==
PHY_STATE_LINK_UP_SPC) {
sas_ha = pm8001_ha->sas;
sas_phy_disconnected(&phy->sas_phy);
sas_ha->notify_phy_event(&phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
}
}
PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id); PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id);
break; break;
case PHY_FUNC_GET_EVENTS: case PHY_FUNC_GET_EVENTS:
......
...@@ -3118,8 +3118,9 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) ...@@ -3118,8 +3118,9 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n", pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n",
status, phy_id)); status, phy_id));
if (status == 0) { if (status == 0) {
phy->phy_state = 1; phy->phy_state = PHY_LINK_DOWN;
if (pm8001_ha->flags == PM8001F_RUN_TIME) if (pm8001_ha->flags == PM8001F_RUN_TIME &&
phy->enable_completion != NULL)
complete(phy->enable_completion); complete(phy->enable_completion);
} }
return 0; return 0;
...@@ -3211,7 +3212,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) ...@@ -3211,7 +3212,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
return 0; return 0;
} }
phy->phy_attached = 0; phy->phy_attached = 0;
phy->phy_state = 0; phy->phy_state = PHY_LINK_DISABLE;
break; break;
case HW_EVENT_PORT_INVALID: case HW_EVENT_PORT_INVALID:
PM8001_MSG_DBG(pm8001_ha, PM8001_MSG_DBG(pm8001_ha,
...@@ -3384,13 +3385,14 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) ...@@ -3384,13 +3385,14 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 status = u32 status =
le32_to_cpu(pPayload->status); le32_to_cpu(pPayload->status);
u32 phyid = u32 phyid =
le32_to_cpu(pPayload->phyid); le32_to_cpu(pPayload->phyid) & 0xFF;
struct pm8001_phy *phy = &pm8001_ha->phy[phyid]; struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
PM8001_MSG_DBG(pm8001_ha, PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("phy:0x%x status:0x%x\n", pm8001_printk("phy:0x%x status:0x%x\n",
phyid, status)); phyid, status));
if (status == 0) if (status == PHY_STOP_SUCCESS ||
phy->phy_state = 0; status == PHY_STOP_ERR_DEVICE_ATTACHED)
phy->phy_state = PHY_LINK_DISABLE;
return 0; return 0;
} }
......
...@@ -170,6 +170,10 @@ ...@@ -170,6 +170,10 @@
#define LINKRATE_60 (0x04 << 8) #define LINKRATE_60 (0x04 << 8)
#define LINKRATE_120 (0x08 << 8) #define LINKRATE_120 (0x08 << 8)
/*phy_stop*/
#define PHY_STOP_SUCCESS 0x00
#define PHY_STOP_ERR_DEVICE_ATTACHED 0x1046
/* phy_profile */ /* phy_profile */
#define SAS_PHY_ANALOG_SETTINGS_PAGE 0x04 #define SAS_PHY_ANALOG_SETTINGS_PAGE 0x04
#define PHY_DWORD_LENGTH 0xC #define PHY_DWORD_LENGTH 0xC
...@@ -216,8 +220,6 @@ ...@@ -216,8 +220,6 @@
#define SAS_DOPNRJT_RTRY_TMO 128 #define SAS_DOPNRJT_RTRY_TMO 128
#define SAS_COPNRJT_RTRY_TMO 128 #define SAS_COPNRJT_RTRY_TMO 128
/* for phy state */
#define PHY_STATE_LINK_UP_SPCV 0x2
/* /*
Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second. Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second.
Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128 Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment