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

📄 mptsas.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		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],		    ioc->sas_index, 0);		ioc->sas_index++;	}	return 0; out_free_port_info:	if (ex) {		if (ex->phy_info)			kfree(ex->phy_info);		kfree(ex);	} out:	return error;}/* * mptsas_delete_expander_phys * * * This will traverse topology, and remove expanders * that are no longer present */static voidmptsas_delete_expander_phys(MPT_ADAPTER *ioc){	struct mptsas_portinfo buffer;	struct mptsas_portinfo *port_info, *n, *parent;	int i;	mutex_lock(&ioc->sas_topology_mutex);	list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {		if (port_info->phy_info &&		    (!(port_info->phy_info[0].identify.device_info &		    MPI_SAS_DEVICE_INFO_SMP_TARGET)))			continue;		if (mptsas_sas_expander_pg0(ioc, &buffer,		     (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<		     MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {			/*			 * Obtain the port_info instance to the parent port			 */			parent = mptsas_find_portinfo_by_handle(ioc,			    port_info->phy_info[0].identify.handle_parent);			if (!parent)				goto next_port;			/*			 * Delete rphys in the parent that point			 * to this expander.  The transport layer will			 * cleanup all the children.			 */			for (i = 0; i < parent->num_phys; i++) {				if ((!parent->phy_info[i].rphy) ||				    (parent->phy_info[i].attached.sas_address !=				   port_info->phy_info[i].identify.sas_address))					continue;				sas_rphy_delete(parent->phy_info[i].rphy);				memset(&parent->phy_info[i].attached, 0,				    sizeof(struct mptsas_devinfo));				parent->phy_info[i].rphy = NULL;				parent->phy_info[i].starget = NULL;			} next_port:			list_del(&port_info->list);			if (port_info->phy_info)				kfree(port_info->phy_info);			kfree(port_info);		}		/*		* Free this memory allocated from inside		* mptsas_sas_expander_pg0		*/		if (buffer.phy_info)			kfree(buffer.phy_info);	}	mutex_unlock(&ioc->sas_topology_mutex);}/* * Start of day discovery */static voidmptsas_scan_sas_topology(MPT_ADAPTER *ioc){	u32 handle = 0xFFFF;	int i;	mutex_lock(&ioc->sas_discovery_mutex);	mptsas_probe_hba_phys(ioc);	while (!mptsas_probe_expander_phys(ioc, &handle))		;	/*	  Reporting RAID volumes.	*/	if (!ioc->raid_data.pIocPg2)		goto out;	if (!ioc->raid_data.pIocPg2->NumActiveVolumes)		goto out;	for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {		scsi_add_device(ioc->sh, ioc->num_ports,		    ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);	} out:	mutex_unlock(&ioc->sas_discovery_mutex);}/* * Work queue thread to handle Runtime discovery * Mere purpose is the hot add/delete of expanders */static voidmptscsih_discovery_work(void * arg){	struct mptsas_discovery_event *ev = arg;	MPT_ADAPTER *ioc = ev->ioc;	u32 handle = 0xFFFF;	mutex_lock(&ioc->sas_discovery_mutex);	ioc->sas_discovery_runtime=1;	mptsas_delete_expander_phys(ioc);	mptsas_probe_hba_phys(ioc);	while (!mptsas_probe_expander_phys(ioc, &handle))		;	kfree(ev);	ioc->sas_discovery_runtime=0;	mutex_unlock(&ioc->sas_discovery_mutex);}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)		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;}/* * Work queue thread to clear the persitency table */static voidmptscsih_sas_persist_clear_table(void * arg){	MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;	mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);}static voidmptsas_reprobe_lun(struct scsi_device *sdev, void *data){	sdev->no_uld_attach = data ? 1 : 0;	scsi_device_reprobe(sdev);}static voidmptsas_reprobe_target(struct scsi_target *starget, int uld_attach){	starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,			mptsas_reprobe_lun);}/* * Work queue thread to handle SAS hotplug events */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;	struct sas_identify identify;	char *ds = NULL;	struct mptsas_devinfo sas_device;	VirtTarget *vtarget;	mutex_lock(&ioc->sas_discovery_mutex);	switch (ev->event_type) {	case MPTSAS_DEL_DEVICE:		phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);		/*		 * Sanity checks, for non-existing phys and remote rphys.		 */		if (!phy_info)			break;		if (!phy_info->rphy)			break;		if (phy_info->starget) {			vtarget = phy_info->starget->hostdata;			if (!vtarget)				break;			/*			 * Handling  RAID components			 */			if (ev->phys_disk_num_valid) {				vtarget->target_id = ev->phys_disk_num;				vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;				mptsas_reprobe_target(vtarget->starget, 1);				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);		sas_rphy_delete(phy_info->rphy);		memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));		phy_info->rphy = NULL;		phy_info->starget = NULL;		break;	case MPTSAS_ADD_DEVICE:		if (ev->phys_disk_num_valid)			mpt_findImVolumes(ioc);		/*		 * Refresh sas device pg0 data		 */		if (mptsas_sas_device_pg0(ioc, &sas_device,		    (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<		     MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))			break;		phy_info = mptsas_find_phyinfo_by_parent(ioc,				sas_device.handle_parent, sas_device.phy_id);		if (!phy_info) {			u32 handle = 0xFFFF;			/*			* Its possible when an expander has been hot added			* containing attached devices, the sas firmware			* may send a RC_ADDED event prior to the			* DISCOVERY STOP event. If that occurs, our			* view of the topology in the driver in respect to this			* expander might of not been setup, and we hit this			* condition.			* Therefore, this code kicks off discovery to			* refresh the data.			* Then again, we check whether the parent phy has			* been created.			*/			ioc->sas_discovery_runtime=1;			mptsas_delete_expander_phys(ioc);			mptsas_probe_hba_phys(ioc);			while (!mptsas_probe_expander_phys(ioc, &handle))				;			ioc->sas_discovery_runtime=0;			phy_info = mptsas_find_phyinfo_by_parent(ioc,				sas_device.handle_parent, sas_device.phy_id);			if (!phy_info)				break;		}		if (phy_info->starget) {			vtarget = phy_info->starget->hostdata;			if (!vtarget)				break;			/*			 * Handling  RAID components			 */			if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {				vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;				vtarget->target_id = ev->id;				mptsas_reprobe_target(phy_info->starget, 0);			}			break;		}		if (phy_info->rphy)			break;		memcpy(&phy_info->attached, &sas_device,		    sizeof(struct mptsas_devinfo));		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);		mptsas_parse_device_info(&identify, &phy_info->attached);		switch (identify.device_type) {		case SAS_END_DEVICE:			rphy = sas_end_device_alloc(phy_info->phy);			break;		case SAS_EDGE_EXPANDER_DEVICE:		case SAS_FANOUT_EXPANDER_DEVICE:			rphy = sas_expander_alloc(phy_info->phy, identify.device_type);			break;		default:			rphy = NULL;			break;		}		if (!rphy)			break; /* non-fatal: an rphy can be added later */		rphy->identify = identify;		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 raid volume, 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(			ioc->sh,			ioc->num_ports,			ev->id,			0);		if (!sdev)			break;		printk(MYIOC_s_INFO_FMT		       "removing raid volume, channel %d, id %d\n",		       ioc->name, ioc->num_ports, ev->id);		scsi_remove_device(sdev);		scsi_device_put(sdev);		mpt_findImVolumes(ioc);		break;	case MPTSAS_IGNORE_EVENT:	default:		break;	}	kfree(ev);	mutex_unlock(&ioc->sas_discovery_mutex);}static voidmptscsih_send_sas_event(MPT_ADAPTER *ioc,		EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data){	struct mptsas_hotplug_event *ev;	u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);	__le64 sas_address;	if ((device_info &	     (MPI_SAS_DEVICE_INFO_SSP_TARGET |	      MPI_SAS_DEVICE_INFO_STP_TARGET |	      MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)		return;	switch (sas_event_data->ReasonCode) {	case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:	case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:		ev = kmalloc(sizeof(*ev), GFP_ATOMIC);		if (!ev) {			printk(KERN_WARNING "mptsas: lost hotplug event\n");			break;		}		INIT_WORK(&ev->work, mptsas_hotplug_work, ev);		ev->ioc = ioc;		ev->handle = le16_to_cpu(sas_event_data->DevHandle);		ev->parent_handle =		    le16_to_cpu(sas_event_data->ParentDevHandle);		ev->channel = sas_event_data->Bus;		ev->id = sas_event_data->TargetID;		ev->phy_id = sas_event_data->PhyNum;		memcpy(&sas_address, &sas_event_data->SASAddress,		    sizeof(__le64));		ev->sas_address = le64_to_cpu(sas_address);		ev->device_info = device_info;		if (sas_event_data->ReasonCode &		    MPI_EVENT_SAS_DEV_STAT_RC_ADDED)			ev->event_type = MPTSAS_ADD_DEVICE;		else			ev->event_type = MPTSAS_DEL_DEVICE;

⌨️ 快捷键说明

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