mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[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>
This commit is contained in:
		
							parent
							
								
									06f12f22ce
								
							
						
					
					
						commit
						279094079a
					
				
					 5 changed files with 104 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -4831,6 +4831,16 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha,
 | 
			
		|||
		    cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case IOP_RDUMP: {
 | 
			
		||||
		nvmd_req.len_ir_vpdd = cpu_to_le32(IPMode | IOP_RDUMP);
 | 
			
		||||
		nvmd_req.resp_len = cpu_to_le32(ioctl_payload->length);
 | 
			
		||||
		nvmd_req.vpd_offset = cpu_to_le32(ioctl_payload->offset);
 | 
			
		||||
		nvmd_req.resp_addr_hi =
 | 
			
		||||
		cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_hi);
 | 
			
		||||
		nvmd_req.resp_addr_lo =
 | 
			
		||||
		cpu_to_le32(pm8001_ha->memoryMap.region[NVMD].phys_addr_lo);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -667,6 +667,31 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * pm8001_get_phy_settings_info : Read phy setting values.
 | 
			
		||||
 * @pm8001_ha : our hba.
 | 
			
		||||
 */
 | 
			
		||||
void pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifdef PM8001_READ_VPD
 | 
			
		||||
	/*OPTION ROM FLASH read for the SPC cards */
 | 
			
		||||
	DECLARE_COMPLETION_ONSTACK(completion);
 | 
			
		||||
	struct pm8001_ioctl_payload payload;
 | 
			
		||||
 | 
			
		||||
	pm8001_ha->nvmd_completion = &completion;
 | 
			
		||||
	/* SAS ADDRESS read from flash / EEPROM */
 | 
			
		||||
	payload.minor_function = 6;
 | 
			
		||||
	payload.offset = 0;
 | 
			
		||||
	payload.length = 4096;
 | 
			
		||||
	payload.func_specific = kzalloc(4096, GFP_KERNEL);
 | 
			
		||||
	/* Read phy setting values from flash */
 | 
			
		||||
	PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload);
 | 
			
		||||
	wait_for_completion(&completion);
 | 
			
		||||
	pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef PM8001_USE_MSIX
 | 
			
		||||
/**
 | 
			
		||||
 * pm8001_setup_msix - enable MSI-X interrupt
 | 
			
		||||
| 
						 | 
				
			
			@ -847,6 +872,10 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	pm8001_init_sas_add(pm8001_ha);
 | 
			
		||||
	/* phy setting support for motherboard controller */
 | 
			
		||||
	if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 &&
 | 
			
		||||
		pdev->subsystem_vendor != 0)
 | 
			
		||||
		pm8001_get_phy_settings_info(pm8001_ha);
 | 
			
		||||
	pm8001_post_sas_ha_init(shost, chip);
 | 
			
		||||
	rc = sas_register_ha(SHOST_TO_SAS_HA(shost));
 | 
			
		||||
	if (rc)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -632,7 +632,8 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
 | 
			
		|||
int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha);
 | 
			
		||||
 | 
			
		||||
int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue);
 | 
			
		||||
 | 
			
		||||
void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
 | 
			
		||||
	u32 length, u8 *buf);
 | 
			
		||||
/* ctl shared API */
 | 
			
		||||
extern struct device_attribute *pm8001_host_attrs[];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3183,9 +3183,27 @@ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
 | 
			
		|||
static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha,
 | 
			
		||||
			void *piomb)
 | 
			
		||||
{
 | 
			
		||||
	PM8001_MSG_DBG(pm8001_ha,
 | 
			
		||||
			pm8001_printk(" pm80xx_addition_functionality\n"));
 | 
			
		||||
	u8 page_code;
 | 
			
		||||
	struct set_phy_profile_resp *pPayload =
 | 
			
		||||
		(struct set_phy_profile_resp *)(piomb + 4);
 | 
			
		||||
	u32 ppc_phyid = le32_to_cpu(pPayload->ppc_phyid);
 | 
			
		||||
	u32 status = le32_to_cpu(pPayload->status);
 | 
			
		||||
 | 
			
		||||
	page_code = (u8)((ppc_phyid & 0xFF00) >> 8);
 | 
			
		||||
	if (status) {
 | 
			
		||||
		/* status is FAILED */
 | 
			
		||||
		PM8001_FAIL_DBG(pm8001_ha,
 | 
			
		||||
			pm8001_printk("PhyProfile command failed  with status "
 | 
			
		||||
			"0x%08X \n", status));
 | 
			
		||||
		return -1;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) {
 | 
			
		||||
			PM8001_FAIL_DBG(pm8001_ha,
 | 
			
		||||
				pm8001_printk("Invalid page code 0x%X\n",
 | 
			
		||||
					page_code));
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4281,6 +4299,45 @@ pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec)
 | 
			
		|||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha,
 | 
			
		||||
	u32 operation, u32 phyid, u32 length, u32 *buf)
 | 
			
		||||
{
 | 
			
		||||
	u32 tag , i, j = 0;
 | 
			
		||||
	int rc;
 | 
			
		||||
	struct set_phy_profile_req payload;
 | 
			
		||||
	struct inbound_queue_table *circularQ;
 | 
			
		||||
	u32 opc = OPC_INB_SET_PHY_PROFILE;
 | 
			
		||||
 | 
			
		||||
	memset(&payload, 0, sizeof(payload));
 | 
			
		||||
	rc = pm8001_tag_alloc(pm8001_ha, &tag);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n"));
 | 
			
		||||
	circularQ = &pm8001_ha->inbnd_q_tbl[0];
 | 
			
		||||
	payload.tag = cpu_to_le32(tag);
 | 
			
		||||
	payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid  & 0xFF));
 | 
			
		||||
	PM8001_INIT_DBG(pm8001_ha,
 | 
			
		||||
		pm8001_printk(" phy profile command for phy %x ,length is %d\n",
 | 
			
		||||
			payload.ppc_phyid, length));
 | 
			
		||||
	for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) {
 | 
			
		||||
		payload.reserved[j] =  cpu_to_le32(*((u32 *)buf + i));
 | 
			
		||||
		j++;
 | 
			
		||||
	}
 | 
			
		||||
	pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha,
 | 
			
		||||
	u32 length, u8 *buf)
 | 
			
		||||
{
 | 
			
		||||
	u32 page_code, i;
 | 
			
		||||
 | 
			
		||||
	page_code = SAS_PHY_ANALOG_SETTINGS_PAGE;
 | 
			
		||||
	for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
 | 
			
		||||
		mpi_set_phy_profile_req(pm8001_ha,
 | 
			
		||||
			SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf);
 | 
			
		||||
		length = length + PHY_DWORD_LENGTH;
 | 
			
		||||
	}
 | 
			
		||||
	PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n"));
 | 
			
		||||
}
 | 
			
		||||
const struct pm8001_dispatch pm8001_80xx_dispatch = {
 | 
			
		||||
	.name			= "pmc80xx",
 | 
			
		||||
	.chip_init		= pm80xx_chip_init,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,6 +170,10 @@
 | 
			
		|||
#define LINKRATE_60			(0x06 << 8)
 | 
			
		||||
#define LINKRATE_120			(0x08 << 8)
 | 
			
		||||
 | 
			
		||||
/* phy_profile */
 | 
			
		||||
#define SAS_PHY_ANALOG_SETTINGS_PAGE	0x04
 | 
			
		||||
#define PHY_DWORD_LENGTH		0xC
 | 
			
		||||
 | 
			
		||||
/* Thermal related */
 | 
			
		||||
#define	THERMAL_ENABLE			0x1
 | 
			
		||||
#define	THERMAL_LOG_ENABLE		0x1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue