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

📄 mptsas.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			vdevice->lun = sdev->lun;			/*			 * Exposing hidden raid components			 */			if (mptscsih_is_phys_disk(ioc,			    p->phy_info[i].attached.channel,			    p->phy_info[i].attached.id))				sdev->no_uld_attach = 1;			mutex_unlock(&ioc->sas_topology_mutex);			goto out;		}	}	mutex_unlock(&ioc->sas_topology_mutex);	kfree(vdevice);	return -ENXIO; out:	vdevice->vtarget->num_luns++;	sdev->hostdata = vdevice;	return 0;}static intmptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){	VirtDevice	*vdevice = SCpnt->device->hostdata;	if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {		SCpnt->result = DID_NO_CONNECT << 16;		done(SCpnt);		return 0;	}//	scsi_print_command(SCpnt);	return mptscsih_qcmd(SCpnt,done);}static struct scsi_host_template mptsas_driver_template = {	.module				= THIS_MODULE,	.proc_name			= "mptsas",	.proc_info			= mptscsih_proc_info,	.name				= "MPT SPI Host",	.info				= mptscsih_info,	.queuecommand			= mptsas_qcmd,	.target_alloc			= mptsas_target_alloc,	.slave_alloc			= mptsas_slave_alloc,	.slave_configure		= mptsas_slave_configure,	.target_destroy			= mptsas_target_destroy,	.slave_destroy			= mptscsih_slave_destroy,	.change_queue_depth 		= mptscsih_change_queue_depth,	.eh_abort_handler		= mptscsih_abort,	.eh_device_reset_handler	= mptscsih_dev_reset,	.eh_bus_reset_handler		= mptscsih_bus_reset,	.eh_host_reset_handler		= mptscsih_host_reset,	.bios_param			= mptscsih_bios_param,	.can_queue			= MPT_FC_CAN_QUEUE,	.this_id			= -1,	.sg_tablesize			= MPT_SCSI_SG_DEPTH,	.max_sectors			= 8192,	.cmd_per_lun			= 7,	.use_clustering			= ENABLE_CLUSTERING,	.shost_attrs			= mptscsih_host_attrs,};static int mptsas_get_linkerrors(struct sas_phy *phy){	MPT_ADAPTER *ioc = phy_to_ioc(phy);	ConfigExtendedPageHeader_t hdr;	CONFIGPARMS cfg;	SasPhyPage1_t *buffer;	dma_addr_t dma_handle;	int error;	/* FIXME: only have link errors on local phys */	if (!scsi_is_sas_phy_local(phy))		return -EINVAL;	hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;	hdr.ExtPageLength = 0;	hdr.PageNumber = 1 /* page number 1*/;	hdr.Reserved1 = 0;	hdr.Reserved2 = 0;	hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;	hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;	cfg.cfghdr.ehdr = &hdr;	cfg.physAddr = -1;	cfg.pageAddr = phy->identify.phy_identifier;	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;	cfg.dir = 0;    /* read */	cfg.timeout = 10;	error = mpt_config(ioc, &cfg);	if (error)		return error;	if (!hdr.ExtPageLength)		return -ENXIO;	buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,				      &dma_handle);	if (!buffer)		return -ENOMEM;	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_phy_pg1(ioc, buffer);	phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);	phy->running_disparity_error_count =		le32_to_cpu(buffer->RunningDisparityErrorCount);	phy->loss_of_dword_sync_count =		le32_to_cpu(buffer->LossDwordSynchCount);	phy->phy_reset_problem_count =		le32_to_cpu(buffer->PhyResetProblemCount); out_free_consistent:	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,			    buffer, dma_handle);	return error;}static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,		MPT_FRAME_HDR *reply){	ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;	if (reply != NULL) {		ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;		memcpy(ioc->sas_mgmt.reply, reply,		    min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));	}	complete(&ioc->sas_mgmt.done);	return 1;}static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset){	MPT_ADAPTER *ioc = phy_to_ioc(phy);	SasIoUnitControlRequest_t *req;	SasIoUnitControlReply_t *reply;	MPT_FRAME_HDR *mf;	MPIHeader_t *hdr;	unsigned long timeleft;	int error = -ERESTARTSYS;	/* FIXME: fusion doesn't allow non-local phy reset */	if (!scsi_is_sas_phy_local(phy))		return -EINVAL;	/* not implemented for expanders */	if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)		return -ENXIO;	if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))		goto out;	mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);	if (!mf) {		error = -ENOMEM;		goto out_unlock;	}	hdr = (MPIHeader_t *) mf;	req = (SasIoUnitControlRequest_t *)mf;	memset(req, 0, sizeof(SasIoUnitControlRequest_t));	req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;	req->MsgContext = hdr->MsgContext;	req->Operation = hard_reset ?		MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;	req->PhyNum = phy->identify.phy_identifier;	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,			10 * HZ);	if (!timeleft) {		/* On timeout reset the board */		mpt_free_msg_frame(ioc, mf);		mpt_HardResetHandler(ioc, CAN_SLEEP);		error = -ETIMEDOUT;		goto out_unlock;	}	/* a reply frame is expected */	if ((ioc->sas_mgmt.status &	    MPT_IOCTL_STATUS_RF_VALID) == 0) {		error = -ENXIO;		goto out_unlock;	}	/* process the completed Reply Message Frame */	reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;	if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {		printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",		    ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);		error = -ENXIO;		goto out_unlock;	}	error = 0; out_unlock:	mutex_unlock(&ioc->sas_mgmt.mutex); out:	return error;}static intmptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier){	MPT_ADAPTER *ioc = rphy_to_ioc(rphy);	int i, error;	struct mptsas_portinfo *p;	struct mptsas_enclosure enclosure_info;	u64 enclosure_handle;	mutex_lock(&ioc->sas_topology_mutex);	list_for_each_entry(p, &ioc->sas_topology, list) {		for (i = 0; i < p->num_phys; i++) {			if (p->phy_info[i].attached.sas_address ==			    rphy->identify.sas_address) {				enclosure_handle = p->phy_info[i].					attached.handle_enclosure;				goto found_info;			}		}	}	mutex_unlock(&ioc->sas_topology_mutex);	return -ENXIO; found_info:	mutex_unlock(&ioc->sas_topology_mutex);	memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));	error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,			(MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<			 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);	if (!error)		*identifier = enclosure_info.enclosure_logical_id;	return error;}static intmptsas_get_bay_identifier(struct sas_rphy *rphy){	MPT_ADAPTER *ioc = rphy_to_ioc(rphy);	struct mptsas_portinfo *p;	int i, rc;	mutex_lock(&ioc->sas_topology_mutex);	list_for_each_entry(p, &ioc->sas_topology, list) {		for (i = 0; i < p->num_phys; i++) {			if (p->phy_info[i].attached.sas_address ==			    rphy->identify.sas_address) {				rc = p->phy_info[i].attached.slot;				goto out;			}		}	}	rc = -ENXIO; out:	mutex_unlock(&ioc->sas_topology_mutex);	return rc;}static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,			      struct request *req){	MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;	MPT_FRAME_HDR *mf;	SmpPassthroughRequest_t *smpreq;	struct request *rsp = req->next_rq;	int ret;	int flagsLength;	unsigned long timeleft;	char *psge;	dma_addr_t dma_addr_in = 0;	dma_addr_t dma_addr_out = 0;	u64 sas_address = 0;	if (!rsp) {		printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",		    ioc->name, __FUNCTION__);		return -EINVAL;	}	/* do we need to support multiple segments? */	if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {		printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",		    ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len,		    rsp->bio->bi_vcnt, rsp->data_len);		return -EINVAL;	}	ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);	if (ret)		goto out;	mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);	if (!mf) {		ret = -ENOMEM;		goto out_unlock;	}	smpreq = (SmpPassthroughRequest_t *)mf;	memset(smpreq, 0, sizeof(*smpreq));	smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);	smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;	if (rphy)		sas_address = rphy->identify.sas_address;	else {		struct mptsas_portinfo *port_info;		mutex_lock(&ioc->sas_topology_mutex);		port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);		if (port_info && port_info->phy_info)			sas_address =				port_info->phy_info[0].phy->identify.sas_address;		mutex_unlock(&ioc->sas_topology_mutex);	}	*((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);	psge = (char *)		(((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));	/* request */	flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |		       MPI_SGE_FLAGS_END_OF_BUFFER |		       MPI_SGE_FLAGS_DIRECTION |		       mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;	flagsLength |= (req->data_len - 4);	dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),				      req->data_len, PCI_DMA_BIDIRECTIONAL);	if (!dma_addr_out)		goto put_mf;	mpt_add_sge(psge, flagsLength, dma_addr_out);	psge += (sizeof(u32) + sizeof(dma_addr_t));	/* response */	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;	flagsLength |= rsp->data_len + 4;	dma_addr_in =  pci_map_single(ioc->pcidev, bio_data(rsp->bio),				      rsp->data_len, PCI_DMA_BIDIRECTIONAL);	if (!dma_addr_in)		goto unmap;	mpt_add_sge(psge, flagsLength, dma_addr_in);	mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);	timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);	if (!timeleft) {		printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);		/* On timeout reset the board */		mpt_HardResetHandler(ioc, CAN_SLEEP);		ret = -ETIMEDOUT;		goto unmap;	}	mf = NULL;	if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {		SmpPassthroughReply_t *smprep;		smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;		memcpy(req->sense, smprep, sizeof(*smprep));		req->sense_len = sizeof(*smprep);	} else {		printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",		    ioc->name, __FUNCTION__);		ret = -ENXIO;	}unmap:	if (dma_addr_out)		pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,				 PCI_DMA_BIDIRECTIONAL);	if (dma_addr_in)		pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,				 PCI_DMA_BIDIRECTIONAL);put_mf:	if (mf)		mpt_free_msg_frame(ioc, mf);out_unlock:	mutex_unlock(&ioc->sas_mgmt.mutex);out:	return ret;}static struct sas_function_template mptsas_transport_functions = {	.get_linkerrors		= mptsas_get_linkerrors,	.get_enclosure_identifier = mptsas_get_enclosure_identifier,	.get_bay_identifier	= mptsas_get_bay_identifier,	.phy_reset		= mptsas_phy_reset,	.smp_handler		= mptsas_smp_handler,};static struct scsi_transport_template *mptsas_transport_template;static intmptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info){	ConfigExtendedPageHeader_t hdr;	CONFIGPARMS cfg;	SasIOUnitPage0_t *buffer;	dma_addr_t dma_handle;	int error, i;	hdr.PageVersion = MPI_SASIOUNITPAGE0_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_IO_UNIT;	cfg.cfghdr.ehdr = &hdr;	cfg.physAddr = -1;	cfg.pageAddr = 0;	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;	port_info->num_phys = buffer->NumPhys;	port_info->phy_info = kcalloc(port_info->num_phys,		sizeof(*port_info->phy_info),GFP_KERNEL);	if (!port_info->phy_info) {		error = -ENOMEM;		goto out_free_consistent;	}	ioc->nvdata_version_persistent =	    le16_to_cpu(buffer->NvdataVersionPersistent);	ioc->nvdata_version_default =	    le16_to_cpu(buffer->NvdataVersionDefault);	for (i = 0; i < port_info->num_phys; i++) {		mptsas_print_phy_data(ioc, &buffer->PhyData[i]);		port_info->phy_info[i].phy_id = i;		port_info->phy_info[i].port_id =		    buffer->PhyData[i].Port;		port_info->phy_info[i].negotiated_link_rate =		    buffer->PhyData[i].NegotiatedLinkRate;		port_info->phy_info[i].portinfo = port_info;		port_info->phy_info[i].handle =		    le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);	} out_free_consistent:	pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,			    buffer, dma_handle); out:	return error;}static int

⌨️ 快捷键说明

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