mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									0b1b1d8861
								
							
						
					
					
						commit
						cd135754d8
					
				
					 7 changed files with 49 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue