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

📄 mptspi.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	size = ioc->spi_data.sdp0length * 4;	/*	if (ioc->spi_data.sdp0length & 1)		size += size + 4;	size += 2048;	*/	spi_dev_pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &spi_dev_pg0_dma, GFP_KERNEL);	if (spi_dev_pg0 == NULL) {		starget_printk(KERN_ERR, starget, MYIOC_s_FMT		    "dma_alloc_coherent for parameters failed\n", ioc->name);		return -EINVAL;	}	memset(&hdr, 0, sizeof(hdr));	hdr.PageVersion = ioc->spi_data.sdp0version;	hdr.PageLength = ioc->spi_data.sdp0length;	hdr.PageNumber = 0;	hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;	memset(&cfg, 0, sizeof(cfg));	cfg.cfghdr.hdr = &hdr;	cfg.physAddr = spi_dev_pg0_dma;	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;	cfg.dir = 0;	cfg.pageAddr = starget->id;	if (mpt_config(ioc, &cfg)) {		starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name);		goto out_free;	}	err = 0;	memcpy(pass_pg0, spi_dev_pg0, size);	mptspi_print_read_nego(hd, starget, le32_to_cpu(spi_dev_pg0->NegotiatedParameters)); out_free:	dma_free_coherent(&ioc->pcidev->dev, size, spi_dev_pg0, spi_dev_pg0_dma);	return err;}static u32 mptspi_getRP(struct scsi_target *starget){	u32 nego = 0;	nego |= spi_iu(starget) ? MPI_SCSIDEVPAGE1_RP_IU : 0;	nego |= spi_dt(starget) ? MPI_SCSIDEVPAGE1_RP_DT : 0;	nego |= spi_qas(starget) ? MPI_SCSIDEVPAGE1_RP_QAS : 0;	nego |= spi_hold_mcs(starget) ? MPI_SCSIDEVPAGE1_RP_HOLD_MCS : 0;	nego |= spi_wr_flow(starget) ? MPI_SCSIDEVPAGE1_RP_WR_FLOW : 0;	nego |= spi_rd_strm(starget) ? MPI_SCSIDEVPAGE1_RP_RD_STRM : 0;	nego |= spi_rti(starget) ? MPI_SCSIDEVPAGE1_RP_RTI : 0;	nego |= spi_pcomp_en(starget) ? MPI_SCSIDEVPAGE1_RP_PCOMP_EN : 0;	nego |= (spi_period(starget) <<  MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD) & MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK;	nego |= (spi_offset(starget) << MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET) & MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK;	nego |= spi_width(starget) ?  MPI_SCSIDEVPAGE1_RP_WIDE : 0;	return nego;}static void mptspi_read_parameters(struct scsi_target *starget){	int nego;	struct _CONFIG_PAGE_SCSI_DEVICE_0 spi_dev_pg0;	mptspi_read_spi_device_pg0(starget, &spi_dev_pg0);	nego = le32_to_cpu(spi_dev_pg0.NegotiatedParameters);	spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0;	spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0;	spi_qas(starget) = (nego & MPI_SCSIDEVPAGE0_NP_QAS) ? 1 : 0;	spi_wr_flow(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WR_FLOW) ? 1 : 0;	spi_rd_strm(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RD_STRM) ? 1 : 0;	spi_rti(starget) = (nego & MPI_SCSIDEVPAGE0_NP_RTI) ? 1 : 0;	spi_pcomp_en(starget) = (nego & MPI_SCSIDEVPAGE0_NP_PCOMP_EN) ? 1 : 0;	spi_hold_mcs(starget) = (nego & MPI_SCSIDEVPAGE0_NP_HOLD_MCS) ? 1 : 0;	spi_period(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD;	spi_offset(starget) = (nego & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) >> MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET;	spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0;}static intmptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id){	MpiRaidActionRequest_t	*pReq;	MPT_FRAME_HDR		*mf;	MPT_ADAPTER *ioc = hd->ioc;	/* Get and Populate a free Frame	 */	if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) {		ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",					ioc->name));		return -EAGAIN;	}	pReq = (MpiRaidActionRequest_t *)mf;	if (quiesce)		pReq->Action = MPI_RAID_ACTION_QUIESCE_PHYS_IO;	else		pReq->Action = MPI_RAID_ACTION_ENABLE_PHYS_IO;	pReq->Reserved1 = 0;	pReq->ChainOffset = 0;	pReq->Function = MPI_FUNCTION_RAID_ACTION;	pReq->VolumeID = id;	pReq->VolumeBus = channel;	pReq->PhysDiskNum = 0;	pReq->MsgFlags = 0;	pReq->Reserved2 = 0;	pReq->ActionDataWord = 0; /* Reserved for this action */	mpt_add_sge((char *)&pReq->ActionDataSGE,		MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1);	ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n",			ioc->name, pReq->Action, channel, id));	hd->pLocal = NULL;	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */	hd->scandv_wait_done = 0;	/* Save cmd pointer, for resource free if timeout or	 * FW reload occurs	 */	hd->cmdPtr = mf;	add_timer(&hd->timer);	mpt_put_msg_frame(ioc->InternalCtx, ioc, mf);	wait_event(hd->scandv_waitq, hd->scandv_wait_done);	if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0))		return -1;	return 0;}static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd,			     struct scsi_device *sdev){	VirtTarget *vtarget = scsi_target(sdev)->hostdata;	MPT_ADAPTER *ioc = hd->ioc;	/* no DV on RAID devices */	if (sdev->channel == 0 &&	    mptspi_is_raid(hd, sdev->id))		return;	/* If this is a piece of a RAID, then quiesce first */	if (sdev->channel == 1 &&	    mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) {		starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT		    "Integrated RAID quiesce failed\n", ioc->name);		return;	}	hd->spi_pending |= (1 << sdev->id);	spi_dv_device(sdev);	hd->spi_pending &= ~(1 << sdev->id);	if (sdev->channel == 1 &&	    mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0)		starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT		    "Integrated RAID resume failed\n", ioc->name);	mptspi_read_parameters(sdev->sdev_target);	spi_display_xfer_agreement(sdev->sdev_target);	mptspi_read_parameters(sdev->sdev_target);}static int mptspi_slave_alloc(struct scsi_device *sdev){	MPT_SCSI_HOST *hd = shost_priv(sdev->host);	VirtTarget		*vtarget;	VirtDevice		*vdevice;	struct scsi_target 	*starget;	MPT_ADAPTER *ioc = hd->ioc;	if (sdev->channel == 1 &&		mptscsih_is_phys_disk(ioc, 0, sdev->id) == 0)			return -ENXIO;	vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);	if (!vdevice) {		printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",				ioc->name, sizeof(VirtDevice));		return -ENOMEM;	}	vdevice->lun = sdev->lun;	sdev->hostdata = vdevice;	starget = scsi_target(sdev);	vtarget = starget->hostdata;	vdevice->vtarget = vtarget;	vtarget->num_luns++;	if (sdev->channel == 1)		sdev->no_uld_attach = 1;	return 0;}static int mptspi_slave_configure(struct scsi_device *sdev){	struct _MPT_SCSI_HOST *hd = shost_priv(sdev->host);	VirtTarget *vtarget = scsi_target(sdev)->hostdata;	int ret;	mptspi_initTarget(hd, vtarget, sdev);	ret = mptscsih_slave_configure(sdev);	if (ret)		return ret;	ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "id=%d min_period=0x%02x"		" max_offset=0x%02x max_width=%d\n", hd->ioc->name,		sdev->id, spi_min_period(scsi_target(sdev)),		spi_max_offset(scsi_target(sdev)),		spi_max_width(scsi_target(sdev))));	if ((sdev->channel == 1 ||	     !(mptspi_is_raid(hd, sdev->id))) &&	    !spi_initial_dv(sdev->sdev_target))		mptspi_dv_device(hd, sdev);	return 0;}static intmptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)){	struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host);	VirtDevice	*vdevice = SCpnt->device->hostdata;	MPT_ADAPTER *ioc = hd->ioc;	if (!vdevice || !vdevice->vtarget) {		SCpnt->result = DID_NO_CONNECT << 16;		done(SCpnt);		return 0;	}	if (SCpnt->device->channel == 1 &&		mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) {		SCpnt->result = DID_NO_CONNECT << 16;		done(SCpnt);		return 0;	}	if (spi_dv_pending(scsi_target(SCpnt->device)))		ddvprintk(ioc, scsi_print_command(SCpnt));	return mptscsih_qcmd(SCpnt,done);}static void mptspi_slave_destroy(struct scsi_device *sdev){	struct scsi_target *starget = scsi_target(sdev);	VirtTarget *vtarget = starget->hostdata;	VirtDevice *vdevice = sdev->hostdata;	/* Will this be the last lun on a non-raid device? */	if (vtarget->num_luns == 1 && vdevice->configured_lun) {		struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;		/* Async Narrow */		pg1.RequestedParameters = 0;		pg1.Reserved = 0;		pg1.Configuration = 0;		mptspi_write_spi_device_pg1(starget, &pg1);	}	mptscsih_slave_destroy(sdev);}static struct scsi_host_template mptspi_driver_template = {	.module				= THIS_MODULE,	.proc_name			= "mptspi",	.proc_info			= mptscsih_proc_info,	.name				= "MPT SPI Host",	.info				= mptscsih_info,	.queuecommand			= mptspi_qcmd,	.target_alloc			= mptspi_target_alloc,	.slave_alloc			= mptspi_slave_alloc,	.slave_configure		= mptspi_slave_configure,	.target_destroy			= mptspi_target_destroy,	.slave_destroy			= mptspi_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_SCSI_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 mptspi_write_spi_device_pg1(struct scsi_target *starget,			       struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1){	struct Scsi_Host *shost = dev_to_shost(&starget->dev);	struct _MPT_SCSI_HOST *hd = shost_priv(shost);	struct _MPT_ADAPTER *ioc = hd->ioc;	struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1;	dma_addr_t pg1_dma;	int size;	struct _x_config_parms cfg;	struct _CONFIG_PAGE_HEADER hdr;	int err = -EBUSY;	/* don't allow updating nego parameters on RAID devices */	if (starget->channel == 0 &&	    mptspi_is_raid(hd, starget->id))		return -1;	size = ioc->spi_data.sdp1length * 4;	pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL);	if (pg1 == NULL) {		starget_printk(KERN_ERR, starget, MYIOC_s_FMT		    "dma_alloc_coherent for parameters failed\n", ioc->name);		return -EINVAL;	}	memset(&hdr, 0, sizeof(hdr));	hdr.PageVersion = ioc->spi_data.sdp1version;	hdr.PageLength = ioc->spi_data.sdp1length;	hdr.PageNumber = 1;	hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE;	memset(&cfg, 0, sizeof(cfg));	cfg.cfghdr.hdr = &hdr;	cfg.physAddr = pg1_dma;	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;	cfg.dir = 1;	cfg.pageAddr = starget->id;	memcpy(pg1, pass_pg1, size);	pg1->Header.PageVersion = hdr.PageVersion;	pg1->Header.PageLength = hdr.PageLength;	pg1->Header.PageNumber = hdr.PageNumber;	pg1->Header.PageType = hdr.PageType;	mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters));	if (mpt_config(ioc, &cfg)) {		starget_printk(KERN_ERR, starget, MYIOC_s_FMT		    "mpt_config failed\n", ioc->name);		goto out_free;	}	err = 0; out_free:	dma_free_coherent(&ioc->pcidev->dev, size, pg1, pg1_dma);	return err;}static void mptspi_write_offset(struct scsi_target *starget, int offset){	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	u32 nego;	if (offset < 0)		offset = 0;	if (offset > 255)		offset = 255;	if (spi_offset(starget) == -1)		mptspi_read_parameters(starget);	spi_offset(starget) = offset;	nego = mptspi_getRP(starget);	pg1.RequestedParameters = cpu_to_le32(nego);	pg1.Reserved = 0;	pg1.Configuration = 0;	mptspi_write_spi_device_pg1(starget, &pg1);}static void mptspi_write_period(struct scsi_target *starget, int period){	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	u32 nego;	if (period < 8)		period = 8;	if (period > 255)		period = 255;	if (spi_period(starget) == -1)		mptspi_read_parameters(starget);	if (period == 8) {		spi_iu(starget) = 1;		spi_dt(starget) = 1;	} else if (period == 9) {		spi_dt(starget) = 1;	}	spi_period(starget) = period;	nego = mptspi_getRP(starget);	pg1.RequestedParameters = cpu_to_le32(nego);	pg1.Reserved = 0;	pg1.Configuration = 0;	mptspi_write_spi_device_pg1(starget, &pg1);}static void mptspi_write_dt(struct scsi_target *starget, int dt){	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	u32 nego;	if (spi_period(starget) == -1)		mptspi_read_parameters(starget);	if (!dt && spi_period(starget) < 10)		spi_period(starget) = 10;	spi_dt(starget) = dt;	nego = mptspi_getRP(starget);	pg1.RequestedParameters = cpu_to_le32(nego);	pg1.Reserved = 0;	pg1.Configuration = 0;	mptspi_write_spi_device_pg1(starget, &pg1);}static void mptspi_write_iu(struct scsi_target *starget, int iu){	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	u32 nego;	if (spi_period(starget) == -1)		mptspi_read_parameters(starget);	if (!iu && spi_period(starget) < 9)		spi_period(starget) = 9;	spi_iu(starget) = iu;	nego = mptspi_getRP(starget);	pg1.RequestedParameters = cpu_to_le32(nego);	pg1.Reserved = 0;	pg1.Configuration = 0;	mptspi_write_spi_device_pg1(starget, &pg1);}#define MPTSPI_SIMPLE_TRANSPORT_PARM(parm) 				\static void mptspi_write_##parm(struct scsi_target *starget, int parm)\{									\	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;				\	u32 nego;							\									\	spi_##parm(starget) = parm;					\									\	nego = mptspi_getRP(starget);					\									\	pg1.RequestedParameters = cpu_to_le32(nego);			\	pg1.Reserved = 0;						\	pg1.Configuration = 0;						\									\	mptspi_write_spi_device_pg1(starget, &pg1);				\}MPTSPI_SIMPLE_TRANSPORT_PARM(rd_strm)MPTSPI_SIMPLE_TRANSPORT_PARM(wr_flow)MPTSPI_SIMPLE_TRANSPORT_PARM(rti)MPTSPI_SIMPLE_TRANSPORT_PARM(hold_mcs)MPTSPI_SIMPLE_TRANSPORT_PARM(pcomp_en)static void mptspi_write_qas(struct scsi_target *starget, int qas){	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	struct Scsi_Host *shost = dev_to_shost(&starget->dev);	struct _MPT_SCSI_HOST *hd = shost_priv(shost);	VirtTarget *vtarget = starget->hostdata;	u32 nego;	if ((vtarget->negoFlags & MPT_TARGET_NO_NEGO_QAS) ||	    hd->ioc->spi_data.noQas)		spi_qas(starget) = 0;	else		spi_qas(starget) = qas;	nego = mptspi_getRP(starget);	pg1.RequestedParameters = cpu_to_le32(nego);	pg1.Reserved = 0;	pg1.Configuration = 0;	mptspi_write_spi_device_pg1(starget, &pg1);}static void mptspi_write_width(struct scsi_target *starget, int width){	struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1;	u32 nego;	if (!width) {		spi_dt(starget) = 0;		if (spi_period(starget) < 10)			spi_period(starget) = 10;	}	spi_width(starget) = width;

⌨️ 快捷键说明

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