欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

mptctl.c

linux 内核源代码
C
第 1 页 / 共 5 页
字号:
			iocp->name);		return -EBADRQC;	} else if (iocstat == MPI_IOCSTATUS_BUSY) {		printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name);		printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name);		return -EBUSY;	} else {		printk(MYIOC_s_WARN_FMT "ioctl_fwdl() returned [bad] status = %04xh\n",			iocp->name, iocstat);		printk(MYIOC_s_WARN_FMT "(bad VooDoo)\n", iocp->name);		return -ENOMSG;	}	return 0;fwdl_out:        kfree_sgl(sgl, sgl_dma, buflist, iocp);	return ret;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * SGE Allocation routine * * Inputs:	bytes - number of bytes to be transferred *		sgdir - data direction *		sge_offset - offset (in bytes) from the start of the request *			frame to the first SGE *		ioc - pointer to the mptadapter * Outputs:	frags - number of scatter gather elements *		blp - point to the buflist pointer *		sglbuf_dma - pointer to the (dma) sgl * Returns:	Null if failes *		pointer to the (virtual) sgl if successful. */static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags,		 struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc){	MptSge_t	*sglbuf = NULL;		/* pointer to array of SGE */						/* and chain buffers */	struct buflist	*buflist = NULL;	/* kernel routine */	MptSge_t	*sgl;	int		 numfrags = 0;	int		 fragcnt = 0;	int		 alloc_sz = min(bytes,MAX_KMALLOC_SZ);	// avoid kernel warning msg!	int		 bytes_allocd = 0;	int		 this_alloc;	dma_addr_t	 pa;					// phys addr	int		 i, buflist_ent;	int		 sg_spill = MAX_FRAGS_SPILL1;	int		 dir;	/* initialization */	*frags = 0;	*blp = NULL;	/* Allocate and initialize an array of kernel	 * structures for the SG elements.	 */	i = MAX_SGL_BYTES / 8;	buflist = kzalloc(i, GFP_USER);	if (!buflist)		return NULL;	buflist_ent = 0;	/* Allocate a single block of memory to store the sg elements and	 * the chain buffers.  The calling routine is responsible for	 * copying the data in this array into the correct place in the	 * request and chain buffers.	 */	sglbuf = pci_alloc_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf_dma);	if (sglbuf == NULL)		goto free_and_fail;	if (sgdir & 0x04000000)		dir = PCI_DMA_TODEVICE;	else		dir = PCI_DMA_FROMDEVICE;	/* At start:	 *	sgl = sglbuf = point to beginning of sg buffer	 *	buflist_ent = 0 = first kernel structure	 *	sg_spill = number of SGE that can be written before the first	 *		chain element.	 *	 */	sgl = sglbuf;	sg_spill = ((ioc->req_sz - sge_offset)/(sizeof(dma_addr_t) + sizeof(u32))) - 1;	while (bytes_allocd < bytes) {		this_alloc = min(alloc_sz, bytes-bytes_allocd);		buflist[buflist_ent].len = this_alloc;		buflist[buflist_ent].kptr = pci_alloc_consistent(ioc->pcidev,								 this_alloc,								 &pa);		if (buflist[buflist_ent].kptr == NULL) {			alloc_sz = alloc_sz / 2;			if (alloc_sz == 0) {				printk(MYIOC_s_WARN_FMT "-SG: No can do - "				    "not enough memory!   :-(\n", ioc->name);				printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",					ioc->name, numfrags);				goto free_and_fail;			}			continue;		} else {			dma_addr_t dma_addr;			bytes_allocd += this_alloc;			sgl->FlagsLength = (0x10000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|this_alloc);			dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir);			sgl->Address = dma_addr;			fragcnt++;			numfrags++;			sgl++;			buflist_ent++;		}		if (bytes_allocd >= bytes)			break;		/* Need to chain? */		if (fragcnt == sg_spill) {			printk(MYIOC_s_WARN_FMT			    "-SG: No can do - " "Chain required!   :-(\n", ioc->name);			printk(MYIOC_s_WARN_FMT "(freeing %d frags)\n", ioc->name, numfrags);			goto free_and_fail;		}		/* overflow check... */		if (numfrags*8 > MAX_SGL_BYTES){			/* GRRRRR... */			printk(MYIOC_s_WARN_FMT "-SG: No can do - "				"too many SG frags!   :-(\n", ioc->name);			printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n",				ioc->name, numfrags);			goto free_and_fail;		}	}	/* Last sge fixup: set LE+eol+eob bits */	sgl[-1].FlagsLength |= 0xC1000000;	*frags = numfrags;	*blp = buflist;	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "-SG: kbuf_alloc_2_sgl() - "	   "%d SG frags generated!\n", ioc->name, numfrags));	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "-SG: kbuf_alloc_2_sgl() - "	   "last (big) alloc_sz=%d\n", ioc->name, alloc_sz));	return sglbuf;free_and_fail:	if (sglbuf != NULL) {		for (i = 0; i < numfrags; i++) {			dma_addr_t dma_addr;			u8 *kptr;			int len;			if ((sglbuf[i].FlagsLength >> 24) == 0x30)				continue;			dma_addr = sglbuf[i].Address;			kptr = buflist[i].kptr;			len = buflist[i].len;			pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);		}		pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sglbuf, *sglbuf_dma);	}	kfree(buflist);	return NULL;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * Routine to free the SGL elements. */static voidkfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc){	MptSge_t	*sg = sgl;	struct buflist	*bl = buflist;	u32		 nib;	int		 dir;	int		 n = 0;	if (sg->FlagsLength & 0x04000000)		dir = PCI_DMA_TODEVICE;	else		dir = PCI_DMA_FROMDEVICE;	nib = (sg->FlagsLength & 0xF0000000) >> 28;	while (! (nib & 0x4)) { /* eob */		/* skip ignore/chain. */		if (nib == 0 || nib == 3) {			;		} else if (sg->Address) {			dma_addr_t dma_addr;			void *kptr;			int len;			dma_addr = sg->Address;			kptr = bl->kptr;			len = bl->len;			pci_unmap_single(ioc->pcidev, dma_addr, len, dir);			pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);			n++;		}		sg++;		bl++;		nib = (le32_to_cpu(sg->FlagsLength) & 0xF0000000) >> 28;	}	/* we're at eob! */	if (sg->Address) {		dma_addr_t dma_addr;		void *kptr;		int len;		dma_addr = sg->Address;		kptr = bl->kptr;		len = bl->len;		pci_unmap_single(ioc->pcidev, dma_addr, len, dir);		pci_free_consistent(ioc->pcidev, len, kptr, dma_addr);		n++;	}	pci_free_consistent(ioc->pcidev, MAX_SGL_BYTES, sgl, sgl_dma);	kfree(buflist);	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "-SG: Free'd 1 SGL buf + %d kbufs!\n",	    ioc->name, n));}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptctl_getiocinfo - Query the host adapter for IOC information. *	@arg: User space argument * * Outputs:	None. * Return:	0 if successful *		-EFAULT if data unavailable *		-ENODEV  if no such device/adapter */static intmptctl_getiocinfo (unsigned long arg, unsigned int data_size){	struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;	struct mpt_ioctl_iocinfo *karg;	MPT_ADAPTER		*ioc;	struct pci_dev		*pdev;	int			iocnum;	unsigned int		port;	int			cim_rev;	u8			revision;	struct scsi_device 	*sdev;	VirtDevice		*vdevice;	/* Add of PCI INFO results in unaligned access for	 * IA64 and Sparc. Reset long to int. Return no PCI	 * data for obsolete format.	 */	if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev0))		cim_rev = 0;	else if (data_size == sizeof(struct mpt_ioctl_iocinfo_rev1))		cim_rev = 1;	else if (data_size == sizeof(struct mpt_ioctl_iocinfo))		cim_rev = 2;	else if (data_size == (sizeof(struct mpt_ioctl_iocinfo_rev0)+12))		cim_rev = 0;	/* obsolete */	else		return -EFAULT;	karg = kmalloc(data_size, GFP_KERNEL);	if (karg == NULL) {		printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n",				__FILE__, __LINE__);		return -ENOMEM;	}	if (copy_from_user(karg, uarg, data_size)) {		printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - "			"Unable to read in mpt_ioctl_iocinfo struct @ %p\n",				__FILE__, __LINE__, uarg);		kfree(karg);		return -EFAULT;	}	if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||	    (ioc == NULL)) {		printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",				__FILE__, __LINE__, iocnum);		kfree(karg);		return -ENODEV;	}	/* Verify the data transfer size is correct. */	if (karg->hdr.maxDataSize != data_size) {		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "			"Structure size mismatch. Command not completed.\n",			ioc->name, __FILE__, __LINE__);		kfree(karg);		return -EFAULT;	}	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_getiocinfo called.\n",	    ioc->name));	/* Fill in the data and return the structure to the calling	 * program	 */	if (ioc->bus_type == SAS)		karg->adapterType = MPT_IOCTL_INTERFACE_SAS;	else if (ioc->bus_type == FC)		karg->adapterType = MPT_IOCTL_INTERFACE_FC;	else		karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;	if (karg->hdr.port > 1)		return -EINVAL;	port = karg->hdr.port;	karg->port = port;	pdev = (struct pci_dev *) ioc->pcidev;	karg->pciId = pdev->device;	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);	karg->hwRev = revision;	karg->subSystemDevice = pdev->subsystem_device;	karg->subSystemVendor = pdev->subsystem_vendor;	if (cim_rev == 1) {		/* Get the PCI bus, device, and function numbers for the IOC		 */		karg->pciInfo.u.bits.busNumber = pdev->bus->number;		karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );		karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );	} else if (cim_rev == 2) {		/* Get the PCI bus, device, function and segment ID numbers		   for the IOC */		karg->pciInfo.u.bits.busNumber = pdev->bus->number;		karg->pciInfo.u.bits.deviceNumber = PCI_SLOT( pdev->devfn );		karg->pciInfo.u.bits.functionNumber = PCI_FUNC( pdev->devfn );		karg->pciInfo.segmentID = pci_domain_nr(pdev->bus);	}	/* Get number of devices         */	karg->numDevices = 0;	if (ioc->sh) {		shost_for_each_device(sdev, ioc->sh) {			vdevice = sdev->hostdata;			if (vdevice->vtarget->tflags &			    MPT_TARGET_FLAGS_RAID_COMPONENT)				continue;			karg->numDevices++;		}	}	/* Set the BIOS and FW Version	 */	karg->FWVersion = ioc->facts.FWVersion.Word;	karg->BIOSVersion = ioc->biosVersion;	/* Set the Version Strings.	 */	strncpy (karg->driverVersion, MPT_LINUX_PACKAGE_NAME, MPT_IOCTL_VERSION_LENGTH);	karg->driverVersion[MPT_IOCTL_VERSION_LENGTH-1]='\0';	karg->busChangeEvent = 0;	karg->hostId = ioc->pfacts[port].PortSCSIID;	karg->rsvd[0] = karg->rsvd[1] = 0;	/* Copy the data from kernel memory to user memory	 */	if (copy_to_user((char __user *)arg, karg, data_size)) {		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "			"Unable to write out mpt_ioctl_iocinfo struct @ %p\n",			ioc->name, __FILE__, __LINE__, uarg);		kfree(karg);		return -EFAULT;	}	kfree(karg);	return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* *	mptctl_gettargetinfo - Query the host adapter for target information. *	@arg: User space argument * * Outputs:	None. * Return:	0 if successful *		-EFAULT if data unavailable *		-ENODEV  if no such device/adapter */static intmptctl_gettargetinfo (unsigned long arg){	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;	struct mpt_ioctl_targetinfo karg;	MPT_ADAPTER		*ioc;	VirtDevice		*vdevice;	char			*pmem;	int			*pdata;	int			iocnum;	int			numDevices = 0;	int			lun;	int			maxWordsLeft;	int			numBytes;	u8			port;	struct scsi_device 	*sdev;	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {		printk(KERN_ERR MYNAM "%s@%d::mptctl_gettargetinfo - "			"Unable to read in mpt_ioctl_targetinfo struct @ %p\n",				__FILE__, __LINE__, uarg);		return -EFAULT;	}	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||	    (ioc == NULL)) {		printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",				__FILE__, __LINE__, iocnum);		return -ENODEV;	}	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",	    ioc->name));	/* Get the port number and set the maximum number of bytes	 * in the returned structure.	 * Ignore the port setting.	 */	numBytes = karg.hdr.maxDataSize - sizeof(mpt_ioctl_header);	maxWordsLeft = numBytes/sizeof(int);	port = karg.hdr.port;	if (maxWordsLeft <= 0) {		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n",			ioc->name, __FILE__, __LINE__);		return -ENOMEM;	}	/* Fill in the data and return the structure to the calling	 * program	 */	/* struct mpt_ioctl_targetinfo does not contain sufficient space	 * for the target structures so when the IOCTL is called, there is	 * not sufficient stack space for the structure. Allocate memory,	 * populate the memory, copy back to the user, then free memory.	 * targetInfo format:	 * bits 31-24: reserved	 *      23-16: LUN	 *      15- 8: Bus Number	 *       7- 0: Target ID	 */	pmem = kzalloc(numBytes, GFP_KERNEL);

⌨️ 快捷键说明

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