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

📄 mptsas.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * 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){	struct sas_phy *phy;	int error;	phy = sas_phy_alloc(dev, index);	if (!phy)		return -ENOMEM;	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 (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) {		struct sas_rphy *rphy;		rphy = sas_rphy_alloc(phy);		if (!rphy)			return 0; /* non-fatal: an rphy can be added later */		mptsas_parse_device_info(&rphy->identify, &phy_info->attached);		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, int *index){	struct mptsas_portinfo *port_info;	u32 handle = 0xFFFF;	int error = -ENOMEM, i;	port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);	if (!port_info)		goto out;	error = mptsas_sas_io_unit_pg0(ioc, port_info);	if (error)		goto out_free_port_info;	ioc->num_ports = port_info->num_phys;	mutex_lock(&ioc->sas_topology_mutex);	list_add_tail(&port_info->list, &ioc->sas_topology);	mutex_unlock(&ioc->sas_topology_mutex);	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], *index, 1);		(*index)++;	}	return 0; out_free_port_info:	kfree(port_info); out:	return error;}static intmptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index){	struct mptsas_portinfo *port_info, *p;	int error = -ENOMEM, i, j;	port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);	if (!port_info)		goto out;	error = mptsas_sas_expander_pg0(ioc, port_info,		(MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<		 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);	if (error)		goto out_free_port_info;	*handle = port_info->handle;	mutex_lock(&ioc->sas_topology_mutex);	list_add_tail(&port_info->list, &ioc->sas_topology);	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);		}		/*		 * If we find a parent port handle this expander is		 * attached to another expander, else it hangs of the		 * HBA phys.		 */		parent = &ioc->sh->shost_gendev;		mutex_lock(&ioc->sas_topology_mutex);		list_for_each_entry(p, &ioc->sas_topology, list) {			for (j = 0; j < p->num_phys; j++) {				if (port_info->phy_info[i].identify.handle ==						p->phy_info[j].attached.handle)					parent = &p->phy_info[j].rphy->dev;			}		}		mutex_unlock(&ioc->sas_topology_mutex);		mptsas_probe_one_phy(parent, &port_info->phy_info[i],				     *index, 0);		(*index)++;	}	return 0; out_free_port_info:	kfree(port_info); out:	return error;}static voidmptsas_scan_sas_topology(MPT_ADAPTER *ioc){	u32 handle = 0xFFFF;	int index = 0;	mptsas_probe_hba_phys(ioc, &index);	while (!mptsas_probe_expander_phys(ioc, &handle, &index))		;}static struct mptsas_phyinfo *mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id){	struct mptsas_portinfo *port_info;	struct mptsas_devinfo device_info;	struct mptsas_phyinfo *phy_info = NULL;	int i, error;	/*	 * Retrieve the parent sas_address	 */	error = mptsas_sas_device_pg0(ioc, &device_info,		(MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<		 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),		parent_handle);	if (error) {		printk("mptsas: failed to retrieve device page\n");		return NULL;	}	/*	 * The phy_info structures are never deallocated during lifetime of	 * a host, so the code below is safe without additional refcounting.	 */	mutex_lock(&ioc->sas_topology_mutex);	list_for_each_entry(port_info, &ioc->sas_topology, list) {		for (i = 0; i < port_info->num_phys; i++) {			if (port_info->phy_info[i].identify.sas_address ==			    device_info.sas_address &&			    port_info->phy_info[i].phy_id == phy_id) {				phy_info = &port_info->phy_info[i];				break;			}		}	}	mutex_unlock(&ioc->sas_topology_mutex);	return phy_info;}static struct mptsas_phyinfo *mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id){	struct mptsas_portinfo *port_info;	struct mptsas_phyinfo *phy_info = NULL;	int i;	/*	 * The phy_info structures are never deallocated during lifetime of	 * a host, so the code below is safe without additional refcounting.	 */	mutex_lock(&ioc->sas_topology_mutex);	list_for_each_entry(port_info, &ioc->sas_topology, list) {		for (i = 0; i < port_info->num_phys; i++)			if (mptsas_is_end_device(&port_info->phy_info[i].attached))				if (port_info->phy_info[i].attached.id == id) {					phy_info = &port_info->phy_info[i];					break;				}	}	mutex_unlock(&ioc->sas_topology_mutex);	return phy_info;}static voidmptsas_hotplug_work(void *arg){	struct mptsas_hotplug_event *ev = arg;	MPT_ADAPTER *ioc = ev->ioc;	struct mptsas_phyinfo *phy_info;	struct sas_rphy *rphy;	struct scsi_device *sdev;	char *ds = NULL;	struct mptsas_devinfo sas_device;	switch (ev->event_type) {	case MPTSAS_DEL_DEVICE:		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);		if (!phy_info) {			printk("mptsas: remove event for non-existant PHY.\n");			break;		}		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)			ds = "ssp";		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)			ds = "stp";		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)			ds = "sata";		printk(MYIOC_s_INFO_FMT		       "removing %s device, channel %d, id %d, phy %d\n",		       ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);		if (phy_info->rphy) {			sas_rphy_delete(phy_info->rphy);			phy_info->rphy = NULL;		}		break;	case MPTSAS_ADD_DEVICE:		/*		 * When there is no sas address,		 * RAID volumes are being deleted,		 * and hidden phy disk are being added.		 * We don't know the SAS data yet,		 * so lookup sas device page to get		 * pertaining info		 */		if (!ev->sas_address) {			if (mptsas_sas_device_pg0(ioc,			    &sas_device, ev->id,			    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<			     MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))				break;			ev->handle = sas_device.handle;			ev->parent_handle = sas_device.handle_parent;			ev->channel = sas_device.channel;			ev->phy_id = sas_device.phy_id;			ev->sas_address = sas_device.sas_address;			ev->device_info = sas_device.device_info;		}		phy_info = mptsas_find_phyinfo_by_parent(ioc,				ev->parent_handle, ev->phy_id);		if (!phy_info) {			printk("mptsas: add event for non-existant PHY.\n");			break;		}		if (phy_info->rphy) {			printk("mptsas: trying to add existing device.\n");			break;		}		/* fill attached info */		phy_info->attached.handle = ev->handle;		phy_info->attached.phy_id = ev->phy_id;		phy_info->attached.port_id = phy_info->identify.port_id;		phy_info->attached.id = ev->id;		phy_info->attached.channel = ev->channel;		phy_info->attached.sas_address = ev->sas_address;		phy_info->attached.device_info = ev->device_info;		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)			ds = "ssp";		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)			ds = "stp";		if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)			ds = "sata";		printk(MYIOC_s_INFO_FMT		       "attaching %s device, channel %d, id %d, phy %d\n",		       ioc->name, ds, ev->channel, ev->id, ev->phy_id);		rphy = sas_rphy_alloc(phy_info->phy);		if (!rphy)			break; /* non-fatal: an rphy can be added later */		rphy->scsi_target_id = phy_info->attached.id;		mptsas_parse_device_info(&rphy->identify, &phy_info->attached);		if (sas_rphy_add(rphy)) {			sas_rphy_free(rphy);			break;		}		phy_info->rphy = rphy;		break;	case MPTSAS_ADD_RAID:		sdev = scsi_device_lookup(			ioc->sh,			ioc->num_ports,			ev->id,			0);		if (sdev) {			scsi_device_put(sdev);			break;		}		printk(MYIOC_s_INFO_FMT		       "attaching device, channel %d, id %d\n",		       ioc->name, ioc->num_ports, ev->id);		scsi_add_device(ioc->sh,			ioc->num_ports,			ev->id,			0);		mpt_findImVolumes(ioc);		break;	case MPTSAS_DEL_RAID:		sdev = scsi_device_lookup(

⌨️ 快捷键说明

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