scsi: pm80xx: Fix for phy enable/disable functionality

Added proper mask for phy id in mpi_phy_stop_resp().

Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Acked-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Deepak Ukey 2018-09-11 14:18:02 +05:30 committed by Martin K. Petersen
parent 0b1b1d8861
commit cd135754d8
7 changed files with 49 additions and 17 deletions

View File

@ -132,4 +132,12 @@ enum pm8001_hba_info_flags {
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

View File

@ -3810,7 +3810,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb)
" status = %x\n", status));
if (status == 0) {
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);
}
break;

View File

@ -131,10 +131,6 @@
#define LINKRATE_30 (0x02 << 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 */
#define GSM_SM_BASE 0x4F0000
struct mpi_msg_hdr{

View File

@ -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 asd_sas_phy *sas_phy = &phy->sas_phy;
phy->phy_state = 0;
phy->phy_state = PHY_LINK_DISABLE;
phy->pm8001_ha = pm8001_ha;
sas_phy->enabled = (phy_id < pm8001_ha->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS;
@ -1067,6 +1067,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
if (rc)
goto err_out_shost;
scsi_scan_host(pm8001_ha->shost);
pm8001_ha->flags = PM8001F_RUN_TIME;
return 0;
err_out_shost:

View File

@ -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;
struct pm8001_hba_info *pm8001_ha = NULL;
struct sas_phy_linkrates *rates;
struct sas_ha_struct *sas_ha;
struct pm8001_phy *phy;
DECLARE_COMPLETION_ONSTACK(completion);
unsigned long flags;
pm8001_ha = sas_phy->ha->lldd_ha;
phy = &pm8001_ha->phy[phy_id];
pm8001_ha->phy[phy_id].enable_completion = &completion;
switch (func) {
case PHY_FUNC_SET_LINK_RATE:
@ -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 =
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);
wait_for_completion(&completion);
}
@ -180,7 +183,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PHY_LINK_RESET);
break;
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);
wait_for_completion(&completion);
}
@ -188,7 +191,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PHY_HARD_RESET);
break;
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);
wait_for_completion(&completion);
}
@ -200,6 +203,25 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
PHY_LINK_RESET);
break;
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);
break;
case PHY_FUNC_GET_EVENTS:

View File

@ -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",
status, phy_id));
if (status == 0) {
phy->phy_state = 1;
if (pm8001_ha->flags == PM8001F_RUN_TIME)
phy->phy_state = PHY_LINK_DOWN;
if (pm8001_ha->flags == PM8001F_RUN_TIME &&
phy->enable_completion != NULL)
complete(phy->enable_completion);
}
return 0;
@ -3211,7 +3212,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
return 0;
}
phy->phy_attached = 0;
phy->phy_state = 0;
phy->phy_state = PHY_LINK_DISABLE;
break;
case HW_EVENT_PORT_INVALID:
PM8001_MSG_DBG(pm8001_ha,
@ -3384,13 +3385,14 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 status =
le32_to_cpu(pPayload->status);
u32 phyid =
le32_to_cpu(pPayload->phyid);
le32_to_cpu(pPayload->phyid) & 0xFF;
struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("phy:0x%x status:0x%x\n",
phyid, status));
if (status == 0)
phy->phy_state = 0;
if (status == PHY_STOP_SUCCESS ||
status == PHY_STOP_ERR_DEVICE_ATTACHED)
phy->phy_state = PHY_LINK_DISABLE;
return 0;
}

View File

@ -170,6 +170,10 @@
#define LINKRATE_60 (0x04 << 8)
#define LINKRATE_120 (0x08 << 8)
/*phy_stop*/
#define PHY_STOP_SUCCESS 0x00
#define PHY_STOP_ERR_DEVICE_ATTACHED 0x1046
/* phy_profile */
#define SAS_PHY_ANALOG_SETTINGS_PAGE 0x04
#define PHY_DWORD_LENGTH 0xC
@ -216,8 +220,6 @@
#define SAS_DOPNRJT_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.
Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128