⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mptsas.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	ConfigExtendedPageHeader_t hdr;	CONFIGPARMS cfg;	SasExpanderPage0_t *buffer;	dma_addr_t dma_handle;	int error;	hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;	hdr.ExtPageLength = 0;	hdr.PageNumber = 0;	hdr.Reserved1 = 0;	hdr.Reserved2 = 0;	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;	cfg.cfghdr.ehdr = &hdr;	cfg.physAddr = -1;	cfg.pageAddr = form + form_specific;	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;	cfg.dir = 0;	/* read */	cfg.timeout = 10;	memset(port_info, 0, sizeof(struct mptsas_portinfo));	error = mpt_config(ioc, &cfg);	if (error)		goto out;	if (!hdr.ExtPageLength) {		error = -ENXIO;		goto out;	}	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,				      &dma_handle);	if (!buffer) {		error = -ENOMEM;		goto out;	}	cfg.physAddr = dma_handle;	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;	error = mpt_config(ioc, &cfg);	if (error)		goto out_free_consistent;	/* save config data */	port_info->num_phys = buffer->NumPhys;	port_info->handle = le16_to_cpu(buffer->DevHandle);	port_info->phy_info = kcalloc(port_info->num_phys,		sizeof(struct mptsas_phyinfo),GFP_KERNEL);	if (!port_info->phy_info) {		error = -ENOMEM;		goto out_free_consistent;	} out_free_consistent:	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,			    buffer, dma_handle); out:	return error;}static intmptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,		u32 form, u32 form_specific){	ConfigExtendedPageHeader_t hdr;	CONFIGPARMS cfg;	SasExpanderPage1_t *buffer;	dma_addr_t dma_handle;	int error=0;	if (ioc->sas_discovery_runtime &&		mptsas_is_end_device(&phy_info->attached))			goto out;	hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;	hdr.ExtPageLength = 0;	hdr.PageNumber = 1;	hdr.Reserved1 = 0;	hdr.Reserved2 = 0;	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;	cfg.cfghdr.ehdr = &hdr;	cfg.physAddr = -1;	cfg.pageAddr = form + form_specific;	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;	cfg.dir = 0;	/* read */	cfg.timeout = 10;	error = mpt_config(ioc, &cfg);	if (error)		goto out;	if (!hdr.ExtPageLength) {		error = -ENXIO;		goto out;	}	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,				      &dma_handle);	if (!buffer) {		error = -ENOMEM;		goto out;	}	cfg.physAddr = dma_handle;	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;	error = mpt_config(ioc, &cfg);	if (error)		goto out_free_consistent;	mptsas_print_expander_pg1(buffer);	/* save config data */	phy_info->phy_id = buffer->PhyIdentifier;	phy_info->port_id = buffer->PhysicalPort;	phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;	phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;	phy_info->hw_link_rate = buffer->HwLinkRate;	phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);	phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); out_free_consistent:	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,			    buffer, dma_handle); out:	return error;}static voidmptsas_parse_device_info(struct sas_identify *identify,		struct mptsas_devinfo *device_info){	u16 protocols;	identify->sas_address = device_info->sas_address;	identify->phy_identifier = device_info->phy_id;	/*	 * Fill in Phy Initiator Port Protocol.	 * Bits 6:3, more than one bit can be set, fall through cases.	 */	protocols = device_info->device_info & 0x78;	identify->initiator_port_protocols = 0;	if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)		identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;	if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)		identify->initiator_port_protocols |= SAS_PROTOCOL_STP;	if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)		identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;	if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)		identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;	/*	 * Fill in Phy Target Port Protocol.	 * Bits 10:7, more than one bit can be set, fall through cases.	 */	protocols = device_info->device_info & 0x780;	identify->target_port_protocols = 0;	if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)		identify->target_port_protocols |= SAS_PROTOCOL_SSP;	if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)		identify->target_port_protocols |= SAS_PROTOCOL_STP;	if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)		identify->target_port_protocols |= SAS_PROTOCOL_SMP;	if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)		identify->target_port_protocols |= SAS_PROTOCOL_SATA;	/*	 * Fill in Attached device type.	 */	switch (device_info->device_info &			MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {	case MPI_SAS_DEVICE_INFO_NO_DEVICE:		identify->device_type = SAS_PHY_UNUSED;		break;	case MPI_SAS_DEVICE_INFO_END_DEVICE:		identify->device_type = SAS_END_DEVICE;		break;	case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:		identify->device_type = SAS_EDGE_EXPANDER_DEVICE;		break;	case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:		identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;		break;	}}static int mptsas_probe_one_phy(struct device *dev,		struct mptsas_phyinfo *phy_info, int index, int local){	MPT_ADAPTER *ioc;	struct sas_phy *phy;	int error;	if (!dev)		return -ENODEV;	if (!phy_info->phy) {		phy = sas_phy_alloc(dev, index);		if (!phy)			return -ENOMEM;	} else		phy = phy_info->phy;	phy->port_identifier = phy_info->port_id;	mptsas_parse_device_info(&phy->identify, &phy_info->identify);	/*	 * Set Negotiated link rate.	 */	switch (phy_info->negotiated_link_rate) {	case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:		phy->negotiated_linkrate = SAS_PHY_DISABLED;		break;	case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:		phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;		break;	case MPI_SAS_IOUNIT0_RATE_1_5:		phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;		break;	case MPI_SAS_IOUNIT0_RATE_3_0:		phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;		break;	case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:	case MPI_SAS_IOUNIT0_RATE_UNKNOWN:	default:		phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;		break;	}	/*	 * Set Max hardware link rate.	 */	switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {	case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:		phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;		break;	case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:		phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;		break;	default:		break;	}	/*	 * Set Max programmed link rate.	 */	switch (phy_info->programmed_link_rate &			MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {	case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:		phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;		break;	case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:		phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;		break;	default:		break;	}	/*	 * Set Min hardware link rate.	 */	switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {	case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:		phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;		break;	case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:		phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;		break;	default:		break;	}	/*	 * Set Min programmed link rate.	 */	switch (phy_info->programmed_link_rate &			MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {	case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:		phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;		break;	case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:		phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;		break;	default:		break;	}	if (!phy_info->phy) {		if (local)			phy->local_attached = 1;		error = sas_phy_add(phy);		if (error) {			sas_phy_free(phy);			return error;		}		phy_info->phy = phy;	}	if ((phy_info->attached.handle) &&	    (!phy_info->rphy)) {		struct sas_rphy *rphy;		struct sas_identify identify;		ioc = phy_to_ioc(phy_info->phy);		/*		 * Let the hotplug_work thread handle processing		 * the adding/removing of devices that occur		 * after start of day.		 */		if (ioc->sas_discovery_runtime &&			mptsas_is_end_device(&phy_info->attached))			return 0;		mptsas_parse_device_info(&identify, &phy_info->attached);		switch (identify.device_type) {		case SAS_END_DEVICE:			rphy = sas_end_device_alloc(phy);			break;		case SAS_EDGE_EXPANDER_DEVICE:		case SAS_FANOUT_EXPANDER_DEVICE:			rphy = sas_expander_alloc(phy, identify.device_type);			break;		default:			rphy = NULL;			break;		}		if (!rphy)			return 0; /* non-fatal: an rphy can be added later */		rphy->identify = identify;		error = sas_rphy_add(rphy);		if (error) {			sas_rphy_free(rphy);			return error;		}		phy_info->rphy = rphy;	}	return 0;}static intmptsas_probe_hba_phys(MPT_ADAPTER *ioc){	struct mptsas_portinfo *port_info, *hba;	u32 handle = 0xFFFF;	int error = -ENOMEM, i;	hba = kzalloc(sizeof(*port_info), GFP_KERNEL);	if (! hba)		goto out;	error = mptsas_sas_io_unit_pg0(ioc, hba);	if (error)		goto out_free_port_info;	mutex_lock(&ioc->sas_topology_mutex);	port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);	if (!port_info) {		port_info = hba;		list_add_tail(&port_info->list, &ioc->sas_topology);	} else {		port_info->handle = hba->handle;		for (i = 0; i < hba->num_phys; i++)			port_info->phy_info[i].negotiated_link_rate =				hba->phy_info[i].negotiated_link_rate;		if (hba->phy_info)			kfree(hba->phy_info);		kfree(hba);		hba = NULL;	}	mutex_unlock(&ioc->sas_topology_mutex);	ioc->num_ports = port_info->num_phys;	for (i = 0; i < port_info->num_phys; i++) {		mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],			(MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<			 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);		mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,			(MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<			 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);		port_info->phy_info[i].identify.phy_id =		    port_info->phy_info[i].phy_id;		handle = port_info->phy_info[i].identify.handle;		if (port_info->phy_info[i].attached.handle) {			mptsas_sas_device_pg0(ioc,				&port_info->phy_info[i].attached,				(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<				 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),				port_info->phy_info[i].attached.handle);		}		mptsas_probe_one_phy(&ioc->sh->shost_gendev,		    &port_info->phy_info[i], ioc->sas_index, 1);		ioc->sas_index++;	}	return 0; out_free_port_info:	if (hba)		kfree(hba); out:	return error;}static intmptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle){	struct mptsas_portinfo *port_info, *p, *ex;	int error = -ENOMEM, i, j;	ex = kzalloc(sizeof(*port_info), GFP_KERNEL);	if (!ex)		goto out;	error = mptsas_sas_expander_pg0(ioc, ex,		(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<		 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);	if (error)		goto out_free_port_info;	*handle = ex->handle;	mutex_lock(&ioc->sas_topology_mutex);	port_info = mptsas_find_portinfo_by_handle(ioc, *handle);	if (!port_info) {		port_info = ex;		list_add_tail(&port_info->list, &ioc->sas_topology);	} else {		port_info->handle = ex->handle;		if (ex->phy_info)			kfree(ex->phy_info);		kfree(ex);		ex = NULL;	}	mutex_unlock(&ioc->sas_topology_mutex);	for (i = 0; i < port_info->num_phys; i++) {		struct device *parent;		mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],			(MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<			 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);		if (port_info->phy_info[i].identify.handle) {			mptsas_sas_device_pg0(ioc,				&port_info->phy_info[i].identify,				(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<				 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),				port_info->phy_info[i].identify.handle);			port_info->phy_info[i].identify.phy_id =			    port_info->phy_info[i].phy_id;		}		if (port_info->phy_info[i].attached.handle) {			mptsas_sas_device_pg0(ioc,				&port_info->phy_info[i].attached,				(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<				 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),				port_info->phy_info[i].attached.handle);			port_info->phy_info[i].attached.phy_id =			    port_info->phy_info[i].phy_id;		}		/*		 * If we find a parent port handle this expander is		 * attached to another expander, else it hangs of the		 * HBA phys.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -