📄 mptctl.c
字号:
alloc_sz = alloc_sz / 2; if (alloc_sz == 0) { printk(KERN_WARNING MYNAM "-SG: No can do - " "not enough memory! :-(\n"); printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", 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(KERN_WARNING MYNAM "-SG: No can do - " "Chain required! :-(\n"); printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags); goto free_and_fail; } /* overflow check... */ if (numfrags*8 > MAX_SGL_BYTES){ /* GRRRRR... */ printk(KERN_WARNING MYNAM "-SG: No can do - " "too many SG frags! :-(\n"); printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", numfrags); goto free_and_fail; } } /* Last sge fixup: set LE+eol+eob bits */ sgl[-1].FlagsLength |= 0xC1000000; *frags = numfrags; *blp = buflist; dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " "%d SG frags generated!\n", numfrags)); dctlprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " "last (big) alloc_sz=%d\n", alloc_sz)); return sglbuf;free_and_fail: if (sglbuf != NULL) { int i; 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((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", 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; struct Scsi_Host *sh; MPT_SCSI_HOST *hd; int iocnum; int numDevices = 0; unsigned int max_id; int ii; unsigned int port; int cim_rev; u8 revision; dctlprintk((": mptctl_getiocinfo called.\n")); /* 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 "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } if (copy_from_user(karg, uarg, data_size)) { printk(KERN_ERR "%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)) { dctlprintk((KERN_ERR "%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(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", __FILE__, __LINE__); kfree(karg); return -EFAULT; } /* Fill in the data and return the structure to the calling * program */ 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.u.bits.functionNumber = PCI_FUNC( pdev->devfn ); karg->pciInfo.segmentID = pci_domain_nr(pdev->bus); } /* Get number of devices */ if ((sh = ioc->sh) != NULL) { /* sh->max_id = maximum target ID + 1 */ max_id = sh->max_id - 1; hd = (MPT_SCSI_HOST *) sh->hostdata; /* Check all of the target structures and * keep a counter. */ if (hd && hd->Targets) { for (ii = 0; ii <= max_id; ii++) { if (hd->Targets[ii]) numDevices++; } } } karg->numDevices = 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(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", __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; struct Scsi_Host *sh; MPT_SCSI_HOST *hd; VirtDevice *vdev; char *pmem; int *pdata; IOCPage2_t *pIoc2; IOCPage3_t *pIoc3; int iocnum; int numDevices = 0; unsigned int max_id; int id, jj, indexed_lun, lun_index; u32 lun; int maxWordsLeft; int numBytes; u8 port, devType, bus_id; dctlprintk(("mptctl_gettargetinfo called.\n")); if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { printk(KERN_ERR "%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)) { dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } /* 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(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", __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 = kmalloc(numBytes, GFP_KERNEL); if (pmem == NULL) { printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } memset(pmem, 0, numBytes); pdata = (int *) pmem; /* Get number of devices */ if ((sh = ioc->sh) != NULL) { max_id = sh->max_id - 1; hd = (MPT_SCSI_HOST *) sh->hostdata; /* Check all of the target structures. * Save the Id and increment the counter, * if ptr non-null. * sh->max_id = maximum target ID + 1 */ if (hd && hd->Targets) { mpt_findImVolumes(ioc); pIoc2 = ioc->raid_data.pIocPg2; for ( id = 0; id <= max_id; ) { if ( pIoc2 && pIoc2->NumActiveVolumes ) { if ( id == pIoc2->RaidVolume[0].VolumeID ) { if (maxWordsLeft <= 0) { printk(KERN_ERR "mptctl_gettargetinfo - " "buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices); goto data_space_full; } if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 ) devType = 0x80; else devType = 0xC0; bus_id = pIoc2->RaidVolume[0].VolumeBus; numDevices++; *pdata = ( (devType << 24) | (bus_id << 8) | id ); dctlprintk((KERN_ERR "mptctl_gettargetinfo - " "volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); pdata++; --maxWordsLeft; goto next_id; } else { pIoc3 = ioc->raid_data.pIocPg3; for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) goto next_id; } } } if ( (vdev = hd->Targets[id]) ) { for (jj = 0; jj <= MPT_LAST_LUN; jj++) { lun_index = (jj >> 5); indexed_lun = (jj % 32); lun = (1 << indexed_lun); if (vdev->luns[lun_index] & lun) { if (maxWordsLeft <= 0) { printk(KERN_ERR "mptctl_gettargetinfo - " "buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices); goto data_space_full; } bus_id = vdev->bus_id; numDevices++; *pdata = ( (jj << 16) | (bus_id << 8) | id ); dctlprintk((KERN_ERR "mptctl_gettargetinfo - " "target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata)); pdata++; --maxWordsLeft; } } }next_id: id++; } } }data_space_full: karg.numDevices = numDevices; /* Copy part of the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_targetinfo))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -