📄 mptctl.c
字号:
ret = -EMLINK; goto fwdl_out; } dprintk((KERN_INFO "DbG: sgl buffer = %p, sgfrags = %d\n", sgl, numfrags)); /* * Parse SG list, copying sgl itself, * plus f/w image hunks from user space as we go... */ ret = -EFAULT; sgIn = sgl; bl = buflist; for (i=0; i < numfrags; i++) { nib = (le32_to_cpu(sgIn->FlagsLength) & 0xF0000000) >> 28; /* skip ignore/chain. */ if (nib == 0 || nib == 3) { ; } else if (sgIn->Address) { *sgOut = *sgIn; n++; if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { printk(KERN_ERR "%s@%d::_ioctl_fwdl - " "Unable to copy f/w buffer hunk#%d @ %p\n", __FILE__, __LINE__, n, (void*)ufwbuf); goto fwdl_out; } fw_bytes_copied += bl->len; } sgIn++; bl++; sgOut++; }#ifdef MPT_DEBUG { u32 *m = (u32 *)mf; printk(KERN_INFO MYNAM ": F/W download request:\n" KERN_INFO " "); for (i=0; i < 7+numfrags*2; i++) printk(" %08x", le32_to_cpu(m[i])); printk("\n"); }#endif /* * Finally, perform firmware download. */ ReplyMsg = NULL; mpt_put_msg_frame(mptctl_id, ioc, mf); /* * Wait until the reply has been received */ { int foo = 0; while (ReplyMsg == NULL) { if (!(foo%1000000)) { dprintk((KERN_INFO "DbG::_do_fwdl: " "In ReplyMsg loop - iteration %d\n", foo)); //tc } ret = -ETIME; if (++foo > 60000000) goto fwdl_out; mb(); schedule(); barrier(); } } if (sgl) kfree_sgl(sgl, sgl_dma, buflist, iocp); iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; if (iocstat == MPI_IOCSTATUS_SUCCESS) { printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name); return 0; } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) { printk(KERN_WARNING MYNAM ": ?Hmmm... %s says it doesn't support F/W download!?!\n", iocp->name); printk(KERN_WARNING MYNAM ": (time to go bang on somebodies door)\n"); return -EBADRQC; } else if (iocstat == MPI_IOCSTATUS_BUSY) { printk(KERN_WARNING MYNAM ": Warning! %s says: IOC_BUSY!\n", iocp->name); printk(KERN_WARNING MYNAM ": (try again later?)\n"); return -EBUSY; } else { printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR! %s returned [bad] status = %04xh\n", iocp->name, iocstat); printk(KERN_WARNING MYNAM ": (bad VooDoo)\n"); return -ENOMSG; } return 0;fwdl_out: kfree_sgl(sgl, sgl_dma, buflist, iocp); return ret;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* * NEW rwperf (read/write performance) stuff starts here... *//*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static SGESimple32_t *kbuf_alloc_2_sgl(int bytes, u32 sgdir, int *frags, struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc){ SGESimple32_t *sglbuf = NULL; struct buflist *buflist = NULL; 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; SGESimple32_t *sgl; u32 pa; // phys addr SGEChain32_t *last_chain = NULL; SGEChain32_t *old_chain = NULL; int chaincnt = 0; int i, buflist_ent; int sg_spill = MAX_FRAGS_SPILL1; int dir; *frags = 0; *blp = NULL; i = MAX_SGL_BYTES / 8; buflist = kmalloc(i, GFP_USER); if (buflist == NULL) return NULL; memset(buflist, 0, i); buflist_ent = 0; 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; sgl = sglbuf; 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(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; /* Write one SIMPLE sge */ sgl->FlagsLength = cpu_to_le32(0x10000000|sgdir|this_alloc); dma_addr = pci_map_single(ioc->pcidev, buflist[buflist_ent].kptr, this_alloc, dir); sgl->Address = cpu_to_le32(dma_addr); fragcnt++; numfrags++; sgl++; buflist_ent++; } if (bytes_allocd >= bytes) break; /* Need to chain? */ if (fragcnt == sg_spill) { dma_addr_t chain_link; if (last_chain != NULL) last_chain->NextChainOffset = 0x1E; fragcnt = 0; sg_spill = MAX_FRAGS_SPILL2; /* fixup previous SIMPLE sge */ sgl[-1].FlagsLength |= cpu_to_le32(0x80000000); chain_link = (*sglbuf_dma) + ((u8 *)(sgl+1) - (u8 *)sglbuf); /* Write one CHAIN sge */ sgl->FlagsLength = cpu_to_le32(0x30000080); sgl->Address = cpu_to_le32(chain_link); old_chain = last_chain; last_chain = (SGEChain32_t*)sgl; chaincnt++; numfrags++; sgl++; } /* 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 |= cpu_to_le32(0xC1000000); /* Chain fixup needed? */ if (last_chain != NULL && fragcnt < 16) last_chain->Length = cpu_to_le16(fragcnt * 8); *frags = numfrags; *blp = buflist; dprintk((KERN_INFO MYNAM "-SG: kbuf_alloc_2_sgl() - " "%d SG frags generated! (%d CHAIN%s)\n", numfrags, chaincnt, chaincnt>1?"s":"")); dprintk((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 ((le32_to_cpu(sglbuf[i].FlagsLength) >> 24) == 0x30) continue; dma_addr = le32_to_cpu(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;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static voidkfree_sgl(SGESimple32_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTER *ioc){ SGESimple32_t *sg = sgl; struct buflist *bl = buflist; u32 nib; int dir; int n = 0; if (le32_to_cpu(sg->FlagsLength) & 0x04000000) dir = PCI_DMA_TODEVICE; else dir = PCI_DMA_FROMDEVICE; nib = (le32_to_cpu(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 = le32_to_cpu(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 = le32_to_cpu(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); dprintk((KERN_INFO MYNAM "-SG: Free'd 1 SGL buf + %d kbufs!\n", n));}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmpt_ioctl_rwperf_init(struct mpt_raw_r_w *dest, unsigned long src, char *caller, MPT_ADAPTER **iocpp){ char *myname = "_rwperf_init()"; int ioc; /* get copy of structure passed from user space */ if (copy_from_user(dest, (void*)src, sizeof(*dest))) { printk(KERN_ERR MYNAM "::%s() @%d - Can't copy mpt_raw_r_w data @ %p\n", myname, __LINE__, (void*)src); return -EFAULT; /* (-14) Bad address */ } else { dprintk((KERN_INFO MYNAM "-perf: PerfInfo.{ioc,targ,qd,iters,nblks}" ": %d %d %d %d %d\n", dest->iocnum, dest->target, (int)dest->qdepth, dest->iters, dest->nblks )); dprintk((KERN_INFO MYNAM "-perf: PerfInfo.{cache,skip,range,rdwr,seqran}" ": %d %d %d %d %d\n", dest->cache_sz, dest->skip, dest->range, dest->rdwr, dest->seqran )); /* Get the MPT adapter id. */ if ((ioc = mpt_verify_adapter(dest->iocnum, iocpp)) < 0) { printk(KERN_ERR MYNAM "::%s() @%d - ioc%d not found!\n", myname, __LINE__, dest->iocnum); return -ENXIO; /* (-6) No such device or address */ } else { dprintk((MYNAM "-perf: %s using mpt/ioc%x, target %02xh\n", caller, dest->iocnum, dest->target)); } } return ioc;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*//* Treat first N blocks of disk as sacred! */#define SACRED_BLOCKS 100/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static intmpt_ioctl_rwperf(unsigned long arg){ struct mpt_raw_r_w kPerfInfo; /* NOTE: local copy, on stack==KERNEL_SPACE! */ u8 target, targetM; u8 lun, lunM; u8 scsiop; int qdepth; int iters; int cache_sz; u32 xferbytes; u32 scsidir; u32 qtag; u32 scsictl; u32 sgdir; u32 blkno; u32 sbphys; SGESimple32_t *sgl; dma_addr_t sgl_dma; struct buflist *buflist; SGESimple32_t *sgOut, *sgIn; int numfrags; u32 *msg; int i; int ioc; MPT_FRAME_HDR *mf; MPT_ADAPTER *iocp; int sgfragcpycnt; int blklo, blkhi; u8 nextchainoffset; u8 *SenseBuf; dma_addr_t SenseBufDMA; char *myname = "_rwperf()"; dprintk((KERN_INFO "%s - starting...\n", myname)); /* Validate target device */ if ((ioc = mpt_ioctl_rwperf_init(&kPerfInfo, arg, myname, &iocp)) < 0) return ioc; /* Allocate DMA'able memory for the sense buffer. */ SenseBuf = pci_alloc_consistent(iocp->pcidev, 256, &SenseBufDMA); /* set perf parameters from input */ target = kPerfInfo.target & 0x0FF; targetM = target & myMAX_T_MASK; lun = kPerfInfo.lun & 0x1F; // LUN=31 max lunM = lun & myMAX_L_MASK; qdepth = kPerfInfo.qdepth; iters = kPerfInfo.iters; xferbytes = ((u32)kPerfInfo.nblks)<<9; DevInUse[targetM][lunM] = 1; DevIosCount[targetM][lunM] = 0; cache_sz = kPerfInfo.cache_sz * 1024; // CacheSz in kB! /* ToDo: */ /* get capacity (?) */ // pre-build, one time, everything we can for speed in the loops below... scsiop = 0x28; // default to SCSI READ! scsidir = MPI_SCSIIO_CONTROL_READ; // DATA IN (host<--ioc<--dev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -