void __kernel_map_pages(struct page *page, int numpages, int enable) { set_memory_valid((unsigned long)page_address(page), numpages, enable); }
/* * Set up the grant operations for this fragment. If it's a flipping * interface, we also set up the unmap request from here. */ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, struct netrx_pending_operations *npo, struct page *page, unsigned long size, unsigned long offset, int *head) { struct gnttab_copy *copy_gop; struct netbk_rx_meta *meta; /* * These variables are used iff get_page_ext returns true, * in which case they are guaranteed to be initialized. */ unsigned int uninitialized_var(group), uninitialized_var(idx); int foreign = get_page_ext(page, &group, &idx); unsigned long bytes; /* Data must not cross a page boundary. */ BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); meta = npo->meta + npo->meta_prod - 1; /* Skip unused frames from start of page */ page += offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; while (size > 0) { BUG_ON(offset >= PAGE_SIZE); BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); bytes = PAGE_SIZE - offset; if (bytes > size) bytes = size; if (start_new_rx_buffer(npo->copy_off, bytes, *head)) { /* * Netfront requires there to be some data in the head * buffer. */ BUG_ON(*head); meta = get_next_rx_buffer(vif, npo); } if (npo->copy_off + bytes > MAX_BUFFER_OFFSET) bytes = MAX_BUFFER_OFFSET - npo->copy_off; copy_gop = npo->copy + npo->copy_prod++; copy_gop->flags = GNTCOPY_dest_gref; if (foreign) { struct xen_netbk *netbk = &xen_netbk[group]; struct pending_tx_info *src_pend; src_pend = &netbk->pending_tx_info[idx]; copy_gop->source.domid = src_pend->vif->domid; copy_gop->source.u.ref = src_pend->req.gref; copy_gop->flags |= GNTCOPY_source_gref; } else { void *vaddr = page_address(page); copy_gop->source.domid = DOMID_SELF; copy_gop->source.u.gmfn = virt_to_mfn(vaddr); } copy_gop->source.offset = offset; copy_gop->dest.domid = vif->domid; copy_gop->dest.offset = npo->copy_off; copy_gop->dest.u.ref = npo->copy_gref; copy_gop->len = bytes; npo->copy_off += bytes; meta->size += bytes; offset += bytes; size -= bytes; /* Next frame */ if (offset == PAGE_SIZE && size) { BUG_ON(!PageCompound(page)); page++; offset = 0; } /* Leave a gap for the GSO descriptor. */ if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix) vif->rx.req_cons++; *head = 0; /* There must be something in this buffer now. */ } }
int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6, struct rt6_info *rt, unsigned int flags, int dontfrag) { struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct inet_cork *cork; struct sk_buff *skb, *skb_prev = NULL; unsigned int maxfraglen, fragheaderlen, mtu; int exthdrlen; int dst_exthdrlen; int hh_len; int copy; int err; int offset = 0; __u8 tx_flags = 0; if (flags&MSG_PROBE) return 0; cork = &inet->cork.base; if (skb_queue_empty(&sk->sk_write_queue)) { /* * setup for corking */ if (opt) { if (WARN_ON(np->cork.opt)) return -EINVAL; np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation); if (unlikely(np->cork.opt == NULL)) return -ENOBUFS; np->cork.opt->tot_len = opt->tot_len; np->cork.opt->opt_flen = opt->opt_flen; np->cork.opt->opt_nflen = opt->opt_nflen; np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, sk->sk_allocation); if (opt->dst0opt && !np->cork.opt->dst0opt) return -ENOBUFS; np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, sk->sk_allocation); if (opt->dst1opt && !np->cork.opt->dst1opt) return -ENOBUFS; np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, sk->sk_allocation); if (opt->hopopt && !np->cork.opt->hopopt) return -ENOBUFS; np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, sk->sk_allocation); if (opt->srcrt && !np->cork.opt->srcrt) return -ENOBUFS; /* need source address above miyazawa*/ } dst_hold(&rt->dst); cork->dst = &rt->dst; inet->cork.fl.u.ip6 = *fl6; np->cork.hop_limit = hlimit; np->cork.tclass = tclass; if (rt->dst.flags & DST_XFRM_TUNNEL) mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? rt->dst.dev->mtu : dst_mtu(&rt->dst); else mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? rt->dst.dev->mtu : dst_mtu(rt->dst.path); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; } cork->fragsize = mtu; if (dst_allfrag(rt->dst.path)) cork->flags |= IPCORK_ALLFRAG; cork->length = 0; exthdrlen = (opt ? opt->opt_flen : 0); length += exthdrlen; transhdrlen += exthdrlen; dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; } else { rt = (struct rt6_info *)cork->dst; fl6 = &inet->cork.fl.u.ip6; opt = np->cork.opt; transhdrlen = 0; exthdrlen = 0; dst_exthdrlen = 0; mtu = cork->fragsize; } hh_len = LL_RESERVED_SPACE(rt->dst.dev); fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len + (opt ? opt->opt_nflen : 0); maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); return -EMSGSIZE; } } /* For UDP, check if TX timestamp is enabled */ if (sk->sk_type == SOCK_DGRAM) sock_tx_timestamp(sk, &tx_flags); /* * Let's try using as much space as possible. * Use MTU if total length of the message fits into the MTU. * Otherwise, we need to reserve fragment header and * fragment alignment (= 8-15 octects, in total). * * Note that we may need to "move" the data from the tail of * of the buffer to the new fragment when we split * the message. * * FIXME: It may be fragmented into multiple chunks * at once if non-fragmentable extension headers * are too large. * --yoshfuji */ cork->length += length; if (length > mtu) { int proto = sk->sk_protocol; if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); return -EMSGSIZE; } if (proto == IPPROTO_UDP && (rt->dst.dev->features & NETIF_F_UFO)) { err = ip6_ufo_append_data(sk, getfrag, from, length, hh_len, fragheaderlen, transhdrlen, mtu, flags, rt); if (err) goto error; return 0; } } if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) goto alloc_new_skb; while (length > 0) { /* Check if the remaining data fits into current packet. */ copy = (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len; if (copy < length) copy = maxfraglen - skb->len; if (copy <= 0) { char *data; unsigned int datalen; unsigned int fraglen; unsigned int fraggap; unsigned int alloclen; alloc_new_skb: /* There's no room in the current skb */ if (skb) fraggap = skb->len - maxfraglen; else fraggap = 0; /* update mtu and maxfraglen if necessary */ if (skb == NULL || skb_prev == NULL) ip6_append_data_mtu(&mtu, &maxfraglen, fragheaderlen, skb, rt, np->pmtudisc == IPV6_PMTUDISC_PROBE); skb_prev = skb; /* * If remaining data exceeds the mtu, * we know we need more fragment(s). */ datalen = length + fraggap; if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len; if ((flags & MSG_MORE) && !(rt->dst.dev->features&NETIF_F_SG)) alloclen = mtu; else alloclen = datalen + fragheaderlen; alloclen += dst_exthdrlen; if (datalen != length + fraggap) { /* * this is not the last fragment, the trailer * space is regarded as data space. */ datalen += rt->dst.trailer_len; } alloclen += rt->dst.trailer_len; fraglen = datalen + fragheaderlen; /* * We just reserve space for fragment header. * Note: this may be overallocation if the message * (without MSG_MORE) fits into the MTU. */ alloclen += sizeof(struct frag_hdr); if (transhdrlen) { skb = sock_alloc_send_skb(sk, alloclen + hh_len, (flags & MSG_DONTWAIT), &err); } else { skb = NULL; if (atomic_read(&sk->sk_wmem_alloc) <= 2 * sk->sk_sndbuf) skb = sock_wmalloc(sk, alloclen + hh_len, 1, sk->sk_allocation); if (unlikely(skb == NULL)) err = -ENOBUFS; else { /* Only the initial fragment * is time stamped. */ tx_flags = 0; } } if (skb == NULL) goto error; /* * Fill in the control structures */ skb->ip_summed = CHECKSUM_NONE; skb->csum = 0; /* reserve for fragmentation and ipsec header */ skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + dst_exthdrlen); if (sk->sk_type == SOCK_DGRAM) skb_shinfo(skb)->tx_flags = tx_flags; /* * Find where to start putting bytes */ data = skb_put(skb, fraglen); skb_set_network_header(skb, exthdrlen); data += fragheaderlen; skb->transport_header = (skb->network_header + fragheaderlen); if (fraggap) { skb->csum = skb_copy_and_csum_bits( skb_prev, maxfraglen, data + transhdrlen, fraggap, 0); skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; pskb_trim_unique(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; if (copy < 0) { err = -EINVAL; kfree_skb(skb); goto error; } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) { err = -EFAULT; kfree_skb(skb); goto error; } offset += copy; length -= datalen - fraggap; transhdrlen = 0; exthdrlen = 0; dst_exthdrlen = 0; /* * Put the packet on the pending queue */ __skb_queue_tail(&sk->sk_write_queue, skb); continue; } if (copy > length) copy = length; if (!(rt->dst.dev->features&NETIF_F_SG)) { unsigned int off; off = skb->len; if (getfrag(from, skb_put(skb, copy), offset, copy, off, skb) < 0) { __skb_trim(skb, off); err = -EFAULT; goto error; } } else { int i = skb_shinfo(skb)->nr_frags; struct page_frag *pfrag = sk_page_frag(sk); err = -ENOMEM; if (!sk_page_frag_refill(sk, pfrag)) goto error; if (!skb_can_coalesce(skb, i, pfrag->page, pfrag->offset)) { err = -EMSGSIZE; if (i == MAX_SKB_FRAGS) goto error; __skb_fill_page_desc(skb, i, pfrag->page, pfrag->offset, 0); skb_shinfo(skb)->nr_frags = ++i; get_page(pfrag->page); } copy = min_t(int, copy, pfrag->size - pfrag->offset); if (getfrag(from, page_address(pfrag->page) + pfrag->offset, offset, copy, skb->len, skb) < 0) goto error_efault; pfrag->offset += copy; skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); skb->len += copy; skb->data_len += copy; skb->truesize += copy; atomic_add(copy, &sk->sk_wmem_alloc); } offset += copy; length -= copy; } return 0; error_efault: err = -EFAULT; error: cork->length -= length; IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); return err; }
static inline int write_all_xattrs(struct inode *inode, __u32 hsize, void *txattr_addr, struct page *ipage) { struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); size_t inline_size = 0; void *xattr_addr; struct page *xpage; nid_t new_nid = 0; int err; inline_size = inline_xattr_size(inode); if (hsize > inline_size && !F2FS_I(inode)->i_xattr_nid) if (!alloc_nid(sbi, &new_nid)) return -ENOSPC; /* write to inline xattr */ if (inline_size) { struct page *page = NULL; void *inline_addr; if (ipage) { inline_addr = inline_xattr_addr(ipage); } else { page = get_node_page(sbi, inode->i_ino); if (IS_ERR(page)) { alloc_nid_failed(sbi, new_nid); return PTR_ERR(page); } inline_addr = inline_xattr_addr(page); } memcpy(inline_addr, txattr_addr, inline_size); f2fs_put_page(page, 1); /* no need to use xattr node block */ if (hsize <= inline_size) { err = truncate_xattr_node(inode, ipage); alloc_nid_failed(sbi, new_nid); return err; } } /* write to xattr node block */ if (F2FS_I(inode)->i_xattr_nid) { xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); if (IS_ERR(xpage)) { alloc_nid_failed(sbi, new_nid); return PTR_ERR(xpage); } f2fs_bug_on(new_nid); } else { struct dnode_of_data dn; set_new_dnode(&dn, inode, NULL, NULL, new_nid); xpage = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); if (IS_ERR(xpage)) { alloc_nid_failed(sbi, new_nid); return PTR_ERR(xpage); } alloc_nid_done(sbi, new_nid); } xattr_addr = page_address(xpage); memcpy(xattr_addr, txattr_addr + inline_size, PAGE_SIZE - sizeof(struct node_footer)); set_page_dirty(xpage); f2fs_put_page(xpage, 1); /* need to checkpoint during fsync */ F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi)); return 0; }
/* * This is called when a page-cache page is about to be mapped into a * user process' address space. It offers an opportunity for a * port to ensure d-cache/i-cache coherency if necessary. * * Not entirely sure why this is necessary on SH3 with 32K cache but * without it we get occasional "Memory fault" when loading a program. */ void flush_icache_page(struct vm_area_struct *vma, struct page *page) { __flush_purge_region(page_address(page), PAGE_SIZE); }
int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsigned end) { /* Actually commit the write from the page cache page we're looking at. * For now, we write the full page out each time. It sucks, but it's simple */ struct inode *inode = pg->mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_raw_inode *ri; int ret = 0; uint32_t writtenlen = 0; D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); if (!start && end == PAGE_CACHE_SIZE) { /* We need to avoid deadlock with page_cache_read() in jffs2_garbage_collect_pass(). So we have to mark the page up to date, to prevent page_cache_read() from trying to re-lock it. */ SetPageUptodate(pg); } ri = jffs2_alloc_raw_inode(); if (!ri) { D1(printk(KERN_DEBUG "jffs2_commit_write(): Allocation of raw inode failed\n")); return -ENOMEM; } /* Set the fields that the generic jffs2_write_inode_range() code can't find */ ri->ino = cpu_to_je32(inode->i_ino); ri->mode = cpu_to_jemode(inode->i_mode); ri->uid = cpu_to_je16(inode->i_uid); ri->gid = cpu_to_je16(inode->i_gid); ri->isize = cpu_to_je32((uint32_t)inode->i_size); ri->atime = ri->ctime = ri->mtime = cpu_to_je32(get_seconds()); /* In 2.4, it was already kmapped by generic_file_write(). Doesn't hurt to do it again. The alternative is ifdefs, which are ugly. */ kmap(pg); ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start, (pg->index << PAGE_CACHE_SHIFT) + start, end - start, &writtenlen); kunmap(pg); if (ret) { /* There was an error writing. */ SetPageError(pg); } if (writtenlen) { if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; inode->i_blocks = (inode->i_size + 511) >> 9; inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); } }
static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, char *buf, unsigned long blksize) { int err; size_t sz, rbytes, wbytes; unsigned char all_zero; char *p, *zp; struct mutex *h_mtx; /* reduce stack usage */ struct iattr *ia; zp = page_address(ZERO_PAGE(0)); if (unlikely(!zp)) return -ENOMEM; /* possible? */ err = 0; all_zero = 0; while (len) { AuDbg("len %lld\n", len); sz = blksize; if (len < blksize) sz = len; rbytes = 0; /* todo: signal_pending? */ while (!rbytes || err == -EAGAIN || err == -EINTR) { rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); err = rbytes; } if (unlikely(err < 0)) break; all_zero = 0; if (len >= rbytes && rbytes == blksize) all_zero = !memcmp(buf, zp, rbytes); if (!all_zero) { wbytes = rbytes; p = buf; while (wbytes) { size_t b; b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); err = b; /* todo: signal_pending? */ if (unlikely(err == -EAGAIN || err == -EINTR)) continue; if (unlikely(err < 0)) break; wbytes -= b; p += b; } } else { loff_t res; AuLabel(hole); res = vfsub_llseek(dst, rbytes, SEEK_CUR); err = res; if (unlikely(res < 0)) break; } len -= rbytes; err = 0; } /* the last block may be a hole */ if (!err && all_zero) { AuLabel(last hole); err = 1; if (au_test_nfs(dst->f_dentry->d_sb)) { /* nfs requires this step to make last hole */ /* is this only nfs? */ do { /* todo: signal_pending? */ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); } while (err == -EAGAIN || err == -EINTR); if (err == 1) dst->f_pos--; } if (err == 1) { ia = (void *)buf; ia->ia_size = dst->f_pos; ia->ia_valid = ATTR_SIZE | ATTR_FILE; ia->ia_file = dst; h_mtx = &dst->f_dentry->d_inode->i_mutex; mutex_lock_nested(h_mtx, AuLsc_I_CHILD2); err = vfsub_notify_change(&dst->f_path, ia); mutex_unlock(h_mtx); } } return err; }
static int intel_setup_irq_remapping(struct intel_iommu *iommu) { struct ir_table *ir_table; struct fwnode_handle *fn; unsigned long *bitmap; struct page *pages; if (iommu->ir_table) return 0; ir_table = kzalloc(sizeof(struct ir_table), GFP_KERNEL); if (!ir_table) return -ENOMEM; pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER); if (!pages) { pr_err("IR%d: failed to allocate pages of order %d\n", iommu->seq_id, INTR_REMAP_PAGE_ORDER); goto out_free_table; } bitmap = bitmap_zalloc(INTR_REMAP_TABLE_ENTRIES, GFP_ATOMIC); if (bitmap == NULL) { pr_err("IR%d: failed to allocate bitmap\n", iommu->seq_id); goto out_free_pages; } fn = irq_domain_alloc_named_id_fwnode("INTEL-IR", iommu->seq_id); if (!fn) goto out_free_bitmap; iommu->ir_domain = irq_domain_create_hierarchy(arch_get_ir_parent_domain(), 0, INTR_REMAP_TABLE_ENTRIES, fn, &intel_ir_domain_ops, iommu); irq_domain_free_fwnode(fn); if (!iommu->ir_domain) { pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id); goto out_free_bitmap; } iommu->ir_msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain, "INTEL-IR-MSI", iommu->seq_id); ir_table->base = page_address(pages); ir_table->bitmap = bitmap; iommu->ir_table = ir_table; /* * If the queued invalidation is already initialized, * shouldn't disable it. */ if (!iommu->qi) { /* * Clear previous faults. */ dmar_fault(-1, iommu); dmar_disable_qi(iommu); if (dmar_enable_qi(iommu)) { pr_err("Failed to enable queued invalidation\n"); goto out_free_bitmap; } } init_ir_status(iommu); if (ir_pre_enabled(iommu)) { if (!is_kdump_kernel()) { pr_warn("IRQ remapping was enabled on %s but we are not in kdump mode\n", iommu->name); clear_ir_pre_enabled(iommu); iommu_disable_irq_remapping(iommu); } else if (iommu_load_old_irte(iommu)) pr_err("Failed to copy IR table for %s from previous kernel\n", iommu->name); else pr_info("Copied IR table for %s from previous kernel\n", iommu->name); } iommu_set_irq_remapping(iommu, eim_mode); return 0; out_free_bitmap: bitmap_free(bitmap); out_free_pages: __free_pages(pages, INTR_REMAP_PAGE_ORDER); out_free_table: kfree(ir_table); iommu->ir_table = NULL; return -ENOMEM; }
static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req) { struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req); struct ablkcipher_request *subreq; crypto_completion_t complete; void *data; struct scatterlist *osrc, *odst; struct scatterlist *dst; struct page *srcp; struct page *dstp; u8 *giv; u8 *vsrc; u8 *vdst; __be64 seq; unsigned int ivsize; unsigned int len; int err; subreq = (void *)(reqctx->tail + ctx->reqoff); ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); giv = req->giv; complete = req->creq.base.complete; data = req->creq.base.data; osrc = req->creq.src; odst = req->creq.dst; srcp = sg_page(osrc); dstp = sg_page(odst); vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + osrc->offset; vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + odst->offset; ivsize = crypto_ablkcipher_ivsize(geniv); if (vsrc != giv + ivsize && vdst != giv + ivsize) { giv = PTR_ALIGN((u8 *)reqctx->tail, crypto_ablkcipher_alignmask(geniv) + 1); complete = eseqiv_complete; data = req; } ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete, data); sg_init_table(reqctx->src, 2); sg_set_buf(reqctx->src, giv, ivsize); eseqiv_chain(reqctx->src, osrc, vsrc == giv + ivsize); dst = reqctx->src; if (osrc != odst) { sg_init_table(reqctx->dst, 2); sg_set_buf(reqctx->dst, giv, ivsize); eseqiv_chain(reqctx->dst, odst, vdst == giv + ivsize); dst = reqctx->dst; } ablkcipher_request_set_crypt(subreq, reqctx->src, dst, req->creq.nbytes + ivsize, req->creq.info); memcpy(req->creq.info, ctx->salt, ivsize); len = ivsize; if (ivsize > sizeof(u64)) { memset(req->giv, 0, ivsize - sizeof(u64)); len = sizeof(u64); } seq = cpu_to_be64(req->seq); memcpy(req->giv + ivsize - len, &seq, len); err = crypto_ablkcipher_encrypt(subreq); if (err) goto out; if (giv != req->giv) eseqiv_complete2(req); out: return err; }
static void xennet_alloc_rx_buffers(struct net_device *dev) { unsigned short id; struct netfront_info *np = netdev_priv(dev); struct sk_buff *skb; struct page *page; int i, batch_target, notify; RING_IDX req_prod = np->rx.req_prod_pvt; grant_ref_t ref; unsigned long pfn; void *vaddr; struct xen_netif_rx_request *req; if (unlikely(!netif_carrier_ok(dev))) return; /* * Allocate skbuffs greedily, even though we batch updates to the * receive ring. This creates a less bursty demand on the memory * allocator, so should reduce the chance of failed allocation requests * both for ourself and for other kernel subsystems. */ batch_target = np->rx_target - (req_prod - np->rx.rsp_cons); for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD + NET_IP_ALIGN, GFP_ATOMIC | __GFP_NOWARN); if (unlikely(!skb)) goto no_skb; /* Align ip header to a 16 bytes boundary */ skb_reserve(skb, NET_IP_ALIGN); page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); if (!page) { kfree_skb(skb); no_skb: /* Any skbuffs queued for refill? Force them out. */ if (i != 0) goto refill; /* Could not allocate any skbuffs. Try again later. */ mod_timer(&np->rx_refill_timer, jiffies + (HZ/10)); break; } __skb_fill_page_desc(skb, 0, page, 0, 0); skb_shinfo(skb)->nr_frags = 1; __skb_queue_tail(&np->rx_batch, skb); } /* Is the batch large enough to be worthwhile? */ if (i < (np->rx_target/2)) { if (req_prod > np->rx.sring->req_prod) goto push; return; } /* Adjust our fill target if we risked running out of buffers. */ if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) && ((np->rx_target *= 2) > np->rx_max_target)) np->rx_target = np->rx_max_target; refill: for (i = 0; ; i++) { skb = __skb_dequeue(&np->rx_batch); if (skb == NULL) break; skb->dev = dev; id = xennet_rxidx(req_prod + i); BUG_ON(np->rx_skbs[id]); np->rx_skbs[id] = skb; ref = gnttab_claim_grant_reference(&np->gref_rx_head); BUG_ON((signed short)ref < 0); np->grant_rx_ref[id] = ref; pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0])); vaddr = page_address(skb_frag_page(&skb_shinfo(skb)->frags[0])); req = RING_GET_REQUEST(&np->rx, req_prod + i); gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, pfn_to_mfn(pfn), 0); req->id = id; req->gref = ref; } wmb(); /* barrier so backend seens requests */ /* Above is a suitable barrier to ensure backend will see requests. */ np->rx.req_prod_pvt = req_prod + i; push: RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify); if (notify) notify_remote_via_irq(np->netdev->irq); }
/** * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them * @rxb: Rx buffer to reclaim * @handler_status: return value of the handler of the command * (put in setup_rx_handlers) * * If an Rx buffer has an async callback associated with it the callback * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb, int handler_status) { struct iwl_rx_packet *pkt = rxb_addr(rxb); u16 sequence = le16_to_cpu(pkt->hdr.sequence); int txq_id = SEQ_TO_QUEUE(sequence); int index = SEQ_TO_INDEX(sequence); int cmd_index; struct iwl_device_cmd *cmd; struct iwl_cmd_meta *meta; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced * in the queue management code. */ if (WARN(txq_id != trans_pcie->cmd_queue, "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n", txq_id, trans_pcie->cmd_queue, sequence, trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr, trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) { iwl_print_hex_error(trans, pkt, 32); return; } spin_lock(&txq->lock); cmd_index = get_cmd_index(&txq->q, index); cmd = txq->cmd[cmd_index]; meta = &txq->meta[cmd_index]; txq->time_stamp = jiffies; iwlagn_unmap_tfd(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); /* Input error checking is done when commands are added to queue. */ if (meta->flags & CMD_WANT_SKB) { struct page *p = rxb_steal_page(rxb); meta->source->resp_pkt = pkt; meta->source->_rx_page_addr = (unsigned long)page_address(p); meta->source->_rx_page_order = hw_params(trans).rx_page_order; meta->source->handler_status = handler_status; } iwl_hcmd_queue_reclaim(trans, txq_id, index); if (!(meta->flags & CMD_ASYNC)) { if (!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) { IWL_WARN(trans, "HCMD_ACTIVE already clear for command %s\n", get_cmd_string(cmd->hdr.cmd)); } clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status); IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n", get_cmd_string(cmd->hdr.cmd)); wake_up(&trans->wait_command_queue); } meta->flags = 0; spin_unlock(&txq->lock); }
/** * async_syndrome_val - asynchronously validate a raid6 syndrome * @blocks: source blocks from idx 0..disks-3, P @ disks-2 and Q @ disks-1 * @offset: common offset into each block (src and dest) to start transaction * @disks: number of blocks (including missing P or Q, see below) * @len: length of operation in bytes * @pqres: on val failure SUM_CHECK_P_RESULT and/or SUM_CHECK_Q_RESULT are set * @spare: temporary result buffer for the synchronous case * @submit: submission / completion modifiers * * The same notes from async_gen_syndrome apply to the 'blocks', * and 'disks' parameters of this routine. The synchronous path * requires a temporary result buffer and submit->scribble to be * specified. */ struct dma_async_tx_descriptor * async_syndrome_val(struct page **blocks, unsigned int offset, int disks, size_t len, enum sum_check_flags *pqres, struct page *spare, struct async_submit_ctl *submit) { struct dma_chan *chan = pq_val_chan(submit, blocks, disks, len); struct dma_device *device = chan ? chan->device : NULL; struct dma_async_tx_descriptor *tx; unsigned char coefs[disks-2]; enum dma_ctrl_flags dma_flags = submit->cb_fn ? DMA_PREP_INTERRUPT : 0; struct dmaengine_unmap_data *unmap = NULL; BUG_ON(disks < 4); if (device) unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOWAIT); if (unmap && disks <= dma_maxpq(device, 0) && is_dma_pq_aligned(device, offset, 0, len)) { struct device *dev = device->dev; dma_addr_t pq[2]; int i, j = 0, src_cnt = 0; pr_debug("%s: (async) disks: %d len: %zu\n", __func__, disks, len); unmap->len = len; for (i = 0; i < disks-2; i++) if (likely(blocks[i])) { unmap->addr[j] = dma_map_page(dev, blocks[i], offset, len, DMA_TO_DEVICE); coefs[j] = raid6_gfexp[i]; unmap->to_cnt++; src_cnt++; j++; } if (!P(blocks, disks)) { pq[0] = 0; dma_flags |= DMA_PREP_PQ_DISABLE_P; } else { pq[0] = dma_map_page(dev, P(blocks, disks), offset, len, DMA_TO_DEVICE); unmap->addr[j++] = pq[0]; unmap->to_cnt++; } if (!Q(blocks, disks)) { pq[1] = 0; dma_flags |= DMA_PREP_PQ_DISABLE_Q; } else { pq[1] = dma_map_page(dev, Q(blocks, disks), offset, len, DMA_TO_DEVICE); unmap->addr[j++] = pq[1]; unmap->to_cnt++; } if (submit->flags & ASYNC_TX_FENCE) dma_flags |= DMA_PREP_FENCE; for (;;) { tx = device->device_prep_dma_pq_val(chan, pq, unmap->addr, src_cnt, coefs, len, pqres, dma_flags); if (likely(tx)) break; async_tx_quiesce(&submit->depend_tx); dma_async_issue_pending(chan); } dma_set_unmap(tx, unmap); async_tx_submit(chan, tx, submit); return tx; } else { struct page *p_src = P(blocks, disks); struct page *q_src = Q(blocks, disks); enum async_tx_flags flags_orig = submit->flags; dma_async_tx_callback cb_fn_orig = submit->cb_fn; void *scribble = submit->scribble; void *cb_param_orig = submit->cb_param; void *p, *q, *s; pr_debug("%s: (sync) disks: %d len: %zu\n", __func__, disks, len); /* caller must provide a temporary result buffer and * allow the input parameters to be preserved */ BUG_ON(!spare || !scribble); /* wait for any prerequisite operations */ async_tx_quiesce(&submit->depend_tx); /* recompute p and/or q into the temporary buffer and then * check to see the result matches the current value */ tx = NULL; *pqres = 0; if (p_src) { init_async_submit(submit, ASYNC_TX_XOR_ZERO_DST, NULL, NULL, NULL, scribble); tx = async_xor(spare, blocks, offset, disks-2, len, submit); async_tx_quiesce(&tx); p = page_address(p_src) + offset; s = page_address(spare) + offset; *pqres |= !!memcmp(p, s, len) << SUM_CHECK_P; } if (q_src) { P(blocks, disks) = NULL; Q(blocks, disks) = spare; init_async_submit(submit, 0, NULL, NULL, NULL, scribble); tx = async_gen_syndrome(blocks, offset, disks, len, submit); async_tx_quiesce(&tx); q = page_address(q_src) + offset; s = page_address(spare) + offset; *pqres |= !!memcmp(q, s, len) << SUM_CHECK_Q; } /* restore P, Q and submit */ P(blocks, disks) = p_src; Q(blocks, disks) = q_src; submit->cb_fn = cb_fn_orig; submit->cb_param = cb_param_orig; submit->flags = flags_orig; async_tx_sync_epilog(submit); return NULL; } }
/* * pollux_sdi_request() * Callback function for command processing */ static void pollux_sdi_request(struct mmc_host *mmc, struct mmc_request *mrq) { int ret; struct pollux_sdi_host *host = mmc_priv(mmc); struct scatterlist *obsg; struct MES_SDHC_RegisterSet *p = host->sdi; struct device *dev = mmc_dev(host->mmc); // 2.6.20-rc1 u32 sdi_imsk = 0; u32 timeout; struct mmc_request mrq_s; //hyun_debug if(host->cd_state != SD_INSERTED) mrq->cmd->retries = 0; host->mrq = mrq; START_CMD: host->cmdflags = 0; host->complete_what = COMPLETION_CMDDONE; ret = sdi_set_command_flag(host); if(ret < 0 ) { dprintk("Command error occurred\n"); goto request_done; } sdi_imsk = SDI_INTMSK_HLE|SDI_INTMSK_CD|SDI_INTMSK_RE; if (host->mrq->data) { host->bytes_process = 0; obsg = &mrq->data->sg[0]; host->length = host->mrq->data->blocks * host->mrq->data->blksz; MES_SDHC_SetByteCount( host->channel, host->length); host->buffer = page_address(sg_page(obsg)) + obsg->offset; if(mrq->data->flags & MMC_DATA_READ) { host->complete_what = COMPLETION_XFERFINISH_RSPFIN; sdi_imsk |= (SDI_INTMSK_RXDR|SDI_INTMSK_DTO|SDI_INTMSK_HTO|SDI_INTMSK_FRUN); } else if(mrq->data->flags & MMC_DATA_WRITE) { host->complete_what = COMPLETION_XFERFINISH_RSPFIN; sdi_imsk |= (SDI_INTMSK_TXDR|SDI_INTMSK_DTO|SDI_INTMSK_HTO|SDI_INTMSK_FRUN); } } init_completion(&host->complete_request); p->RINTSTS = 0xFFFFFFFF; // all interrupt pend clear p->INTMASK = sdi_imsk; // interrupt enable setting(1로 write한 것은 enable) p->CMDARG = host->mrq->cmd->arg; p->CMD = (host->mrq->cmd->opcode & 0xff)|(host->cmdflags); timeout = 3000; // 3000ms = 3sec ret = wait_for_completion_timeout(&host->complete_request, msecs_to_jiffies(timeout)); if(!ret) { printk("Timeout occurred during waiting for the interrupt\n"); host->mrq->cmd->error = MMC_ERR_TIMEOUT; ret = -MMC_ERR_TIMEOUT; goto request_done; } //Cleanup controller p->RINTSTS = 0xFFFFFFFF; // all interrupt pend clear p->INTMASK = 0; p->CMDARG = 0; p->CMD = 0; // Read response if( host->mrq->cmd->flags & MMC_RSP_136 ) { mrq->cmd->resp[0] = p->RESP3; mrq->cmd->resp[1] = p->RESP2; mrq->cmd->resp[2] = p->RESP1; mrq->cmd->resp[3] = p->RESP0; } else { mrq->cmd->resp[0] = p->RESP0; mrq->cmd->resp[1] = p->RESP1; } // If we have no data transfer we are finished here if(!host->mrq->data){ host->mrq = NULL; goto request_done; } // Calulate the amout of bytes transfer, but only if there was no error if(mrq->data->error == MMC_ERR_NONE) { mrq->data->bytes_xfered = (mrq->data->blocks * mrq->data->blksz); } else { mrq->data->bytes_xfered = 0; } // If we had an error while transfering data we reset the FIFO to clear out any garbage if(mrq->data->error != MMC_ERR_NONE) { printk("mrq->data->error processing\n"); MES_SDHC_ResetFIFO(host->channel); // Reest the FIFO. while (MES_SDHC_IsResetFIFO(host->channel)); // Wait until the FIFO reset is completed. } /* Issue stop command, if required */ if(host->mrq->data->stop) { #if 0 mmc_wait_for_cmd(mmc, mrq->data->stop, 3); #else mrq_s.cmd = mrq->data->stop; mrq_s.cmd->retries = 0; mrq_s.data = NULL; host->mrq = &mrq_s; goto START_CMD; #endif } host->mrq = NULL; request_done: /* Notify end of the request processing by calling mmc_request_done() */ mmc_request_done(host->mmc, mrq); }
static int page_is_zero(struct page *p, unsigned int offset, size_t len) { return !memchr_inv(page_address(p) + offset, 0, len); }
/* * inode->i_mutex: down */ int reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th, struct inode *inode, const char *name, const void *buffer, size_t buffer_size, int flags) { int err = 0; struct dentry *dentry; struct page *page; char *data; size_t file_pos = 0; size_t buffer_pos = 0; size_t new_size; __u32 xahash = 0; if (get_inode_sd_version(inode) == STAT_DATA_V1) return -EOPNOTSUPP; reiserfs_write_unlock(inode->i_sb); if (!buffer) { err = lookup_and_delete_xattr(inode, name); reiserfs_write_lock(inode->i_sb); return err; } dentry = xattr_lookup(inode, name, flags); if (IS_ERR(dentry)) { reiserfs_write_lock(inode->i_sb); return PTR_ERR(dentry); } down_write(&REISERFS_I(inode)->i_xattr_sem); reiserfs_write_lock(inode->i_sb); xahash = xattr_hash(buffer, buffer_size); while (buffer_pos < buffer_size || buffer_pos == 0) { size_t chunk; size_t skip = 0; size_t page_offset = (file_pos & (PAGE_CACHE_SIZE - 1)); if (buffer_size - buffer_pos > PAGE_CACHE_SIZE) chunk = PAGE_CACHE_SIZE; else chunk = buffer_size - buffer_pos; page = reiserfs_get_page(dentry->d_inode, file_pos); if (IS_ERR(page)) { err = PTR_ERR(page); goto out_unlock; } lock_page(page); data = page_address(page); if (file_pos == 0) { struct reiserfs_xattr_header *rxh; skip = file_pos = sizeof(struct reiserfs_xattr_header); if (chunk + skip > PAGE_CACHE_SIZE) chunk = PAGE_CACHE_SIZE - skip; rxh = (struct reiserfs_xattr_header *)data; rxh->h_magic = cpu_to_le32(REISERFS_XATTR_MAGIC); rxh->h_hash = cpu_to_le32(xahash); } err = __reiserfs_write_begin(page, page_offset, chunk + skip); if (!err) { if (buffer) memcpy(data + skip, buffer + buffer_pos, chunk); err = reiserfs_commit_write(NULL, page, page_offset, page_offset + chunk + skip); } unlock_page(page); reiserfs_put_page(page); buffer_pos += chunk; file_pos += chunk; skip = 0; if (err || buffer_size == 0 || !buffer) break; } new_size = buffer_size + sizeof(struct reiserfs_xattr_header); if (!err && new_size < i_size_read(dentry->d_inode)) { struct iattr newattrs = { .ia_ctime = current_fs_time(inode->i_sb), .ia_size = new_size, .ia_valid = ATTR_SIZE | ATTR_CTIME, }; reiserfs_write_unlock(inode->i_sb); mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_XATTR); inode_dio_wait(dentry->d_inode); reiserfs_write_lock(inode->i_sb); err = reiserfs_setattr(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); } else update_ctime(inode); out_unlock: up_write(&REISERFS_I(inode)->i_xattr_sem); dput(dentry); return err; }
int f2fs_setxattr(struct inode *inode, int name_index, const char *name, const void *value, size_t value_len, struct page *ipage) { struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); struct f2fs_inode_info *fi = F2FS_I(inode); struct f2fs_xattr_header *header = NULL; struct f2fs_xattr_entry *here, *last; struct page *page; void *base_addr; int error, found, free, newsize; size_t name_len; char *pval; int ilock; if (name == NULL) return -EINVAL; if (value == NULL) value_len = 0; name_len = strlen(name); if (name_len > F2FS_NAME_LEN || value_len > MAX_VALUE_LEN) return -ERANGE; f2fs_balance_fs(sbi); ilock = mutex_lock_op(sbi); if (!fi->i_xattr_nid) { /* Allocate new attribute block */ struct dnode_of_data dn; if (!alloc_nid(sbi, &fi->i_xattr_nid)) { error = -ENOSPC; goto exit; } set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); mark_inode_dirty(inode); page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); if (IS_ERR(page)) { alloc_nid_failed(sbi, fi->i_xattr_nid); fi->i_xattr_nid = 0; error = PTR_ERR(page); goto exit; } alloc_nid_done(sbi, fi->i_xattr_nid); base_addr = page_address(page); header = XATTR_HDR(base_addr); header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC); header->h_refcount = cpu_to_le32(1); } else { /* The inode already has an extended attribute block. */ page = get_node_page(sbi, fi->i_xattr_nid); if (IS_ERR(page)) { error = PTR_ERR(page); goto exit; } base_addr = page_address(page); header = XATTR_HDR(base_addr); } if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) { error = -EIO; goto cleanup; } /* find entry with wanted name. */ found = 0; list_for_each_xattr(here, base_addr) { if (here->e_name_index != name_index) continue; if (here->e_name_len != name_len) continue; if (!memcmp(here->e_name, name, name_len)) { found = 1; break; } } last = here; while (!IS_XATTR_LAST_ENTRY(last)) last = XATTR_NEXT_ENTRY(last); newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + name_len + value_len); /* 1. Check space */ if (value) { /* If value is NULL, it is remove operation. * In case of update operation, we caculate free. */ free = MIN_OFFSET - ((char *)last - (char *)header); if (found) free = free - ENTRY_SIZE(here); if (free < newsize) { error = -ENOSPC; goto cleanup; } } /* 2. Remove old entry */ if (found) { /* If entry is found, remove old entry. * If not found, remove operation is not needed. */ struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here); int oldsize = ENTRY_SIZE(here); memmove(here, next, (char *)last - (char *)next); last = (struct f2fs_xattr_entry *)((char *)last - oldsize); memset(last, 0, oldsize); } /* 3. Write new entry */ if (value) { /* Before we come here, old entry is removed. * We just write new entry. */ memset(last, 0, newsize); last->e_name_index = name_index; last->e_name_len = name_len; memcpy(last->e_name, name, name_len); pval = last->e_name + name_len; memcpy(pval, value, value_len); last->e_value_size = cpu_to_le16(value_len); } set_page_dirty(page); f2fs_put_page(page, 1); if (is_inode_flag_set(fi, FI_ACL_MODE)) { inode->i_mode = fi->i_acl_mode; inode->i_ctime = CURRENT_TIME; clear_inode_flag(fi, FI_ACL_MODE); } if (ipage) update_inode(inode, ipage); else update_inode_page(inode); mutex_unlock_op(sbi, ilock); return 0; cleanup: f2fs_put_page(page, 1); exit: mutex_unlock_op(sbi, ilock); return error; }
/* * inode->i_mutex: down */ int reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer, size_t buffer_size) { ssize_t err = 0; struct dentry *dentry; size_t isize; size_t file_pos = 0; size_t buffer_pos = 0; struct page *page; __u32 hash = 0; if (name == NULL) return -EINVAL; /* We can't have xattrs attached to v1 items since they don't have * generation numbers */ if (get_inode_sd_version(inode) == STAT_DATA_V1) return -EOPNOTSUPP; dentry = xattr_lookup(inode, name, XATTR_REPLACE); if (IS_ERR(dentry)) { err = PTR_ERR(dentry); goto out; } down_read(&REISERFS_I(inode)->i_xattr_sem); isize = i_size_read(dentry->d_inode); /* Just return the size needed */ if (buffer == NULL) { err = isize - sizeof(struct reiserfs_xattr_header); goto out_unlock; } if (buffer_size < isize - sizeof(struct reiserfs_xattr_header)) { err = -ERANGE; goto out_unlock; } while (file_pos < isize) { size_t chunk; char *data; size_t skip = 0; if (isize - file_pos > PAGE_CACHE_SIZE) chunk = PAGE_CACHE_SIZE; else chunk = isize - file_pos; page = reiserfs_get_page(dentry->d_inode, file_pos); if (IS_ERR(page)) { err = PTR_ERR(page); goto out_unlock; } lock_page(page); data = page_address(page); if (file_pos == 0) { struct reiserfs_xattr_header *rxh = (struct reiserfs_xattr_header *)data; skip = file_pos = sizeof(struct reiserfs_xattr_header); chunk -= skip; /* Magic doesn't match up.. */ if (rxh->h_magic != cpu_to_le32(REISERFS_XATTR_MAGIC)) { unlock_page(page); reiserfs_put_page(page); reiserfs_warning(inode->i_sb, "jdm-20001", "Invalid magic for xattr (%s) " "associated with %k", name, INODE_PKEY(inode)); err = -EIO; goto out_unlock; } hash = le32_to_cpu(rxh->h_hash); } memcpy(buffer + buffer_pos, data + skip, chunk); unlock_page(page); reiserfs_put_page(page); file_pos += chunk; buffer_pos += chunk; skip = 0; } err = isize - sizeof(struct reiserfs_xattr_header); if (xattr_hash(buffer, isize - sizeof(struct reiserfs_xattr_header)) != hash) { reiserfs_warning(inode->i_sb, "jdm-20002", "Invalid hash for xattr (%s) associated " "with %k", name, INODE_PKEY(inode)); err = -EIO; } out_unlock: up_read(&REISERFS_I(inode)->i_xattr_sem); dput(dentry); out: return err; }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; int signal; unsigned long address = 0; #ifdef CONFIG_MMU pmd_t *pmdp; pte_t *ptep; #endif frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; if (info) err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->r1), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* minus 8 is offset to cater for "rtsd r15,8" */ if (ka->sa.sa_flags & SA_RESTORER) { regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; } else { /* addi r12, r0, __NR_sigreturn */ err |= __put_user(0x31800000 | __NR_rt_sigreturn , frame->tramp + 0); /* brki r14, 0x8 */ err |= __put_user(0xb9cc0008, frame->tramp + 1); /* Return from sighandler will jump to the tramp. Negative 8 offset because return is rtsd r15, 8 */ regs->r15 = ((unsigned long)frame->tramp)-8; address = ((unsigned long)frame->tramp); #ifdef CONFIG_MMU pmdp = pmd_offset(pud_offset( pgd_offset(current->mm, address), address), address); preempt_disable(); ptep = pte_offset_map(pmdp, address); if (pte_present(*ptep)) { address = (unsigned long) page_address(pte_page(*ptep)); /* MS: I need add offset in page */ address += ((unsigned long)frame->tramp) & ~PAGE_MASK; /* MS address is virtual */ address = virt_to_phys(address); invalidate_icache_range(address, address + 8); flush_dcache_range(address, address + 8); } pte_unmap(ptep); preempt_enable(); #else invalidate_icache_range(address, address + 8); flush_dcache_range(address, address + 8); #endif } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE; /* Signal handler args: */ regs->r5 = signal; /* arg 0: signum */ regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */ regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */ /* Offset to handle microblaze rtid r14, 0 */ regs->pc = (unsigned long)ka->sa.sa_handler; set_fs(USER_DS); /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); #ifdef DEBUG_SIG printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", current->comm, current->pid, frame, regs->pc); #endif return; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); }
/* ION CMA heap operations functions */ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len, unsigned long align, unsigned long flags) { struct ion_cma_heap *cma_heap = to_cma_heap(heap); struct device *dev = cma_heap->dev; struct ion_cma_buffer_info *info; dev_dbg(dev, "Request buffer allocation len %ld\n", len); if (buffer->flags & ION_FLAG_CACHED) return -EINVAL; if (align > PAGE_SIZE) return -EINVAL; if (!ion_is_heap_available(heap, flags, NULL)) return -EPERM; info = kzalloc(sizeof(struct ion_cma_buffer_info), GFP_KERNEL); if (!info) { dev_err(dev, "Can't allocate buffer info\n"); return ION_CMA_ALLOCATE_FAILED; } info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle), GFP_HIGHUSER | __GFP_ZERO); if (!info->cpu_addr) { dev_err(dev, "Fail to allocate buffer\n"); goto err; } info->table = kmalloc(sizeof(struct sg_table), GFP_KERNEL); if (!info->table) { dev_err(dev, "Fail to allocate sg table\n"); goto free_mem; } if (ion_cma_get_sgtable (dev, info->table, info->cpu_addr, info->handle, len)) goto free_table; /* keep this for memory release */ buffer->priv_virt = info; #ifdef CONFIG_ARM64 if (!ion_buffer_cached(buffer) && !(buffer->flags & ION_FLAG_PROTECTED)) { if (ion_buffer_need_flush_all(buffer)) flush_all_cpu_caches(); else __flush_dcache_area(page_address(sg_page(info->table->sgl)), len); } #else if (!ion_buffer_cached(buffer) && !(buffer->flags & ION_FLAG_PROTECTED)) { if (ion_buffer_need_flush_all(buffer)) flush_all_cpu_caches(); else dmac_flush_range(page_address(sg_page(info->table->sgl), len, DMA_BIDIRECTIONAL)); } #endif if ((buffer->flags & ION_FLAG_PROTECTED) && ion_secure_protect(heap)) goto free_table; dev_dbg(dev, "Allocate buffer %p\n", buffer); return 0; free_table: kfree(info->table); free_mem: dma_free_coherent(dev, len, info->cpu_addr, info->handle); err: kfree(info); return ION_CMA_ALLOCATE_FAILED; }
static void rx_complete(struct urb *req) { struct net_device *dev = req->context; struct usbpn_dev *pnd = netdev_priv(dev); struct page *page = virt_to_page(req->transfer_buffer); struct sk_buff *skb; unsigned long flags; switch (req->status) { case 0: spin_lock_irqsave(&pnd->rx_lock, flags); skb = pnd->rx_skb; if (!skb) { skb = pnd->rx_skb = netdev_alloc_skb(dev, 12); if (likely(skb)) { /* Can't use pskb_pull() on page in IRQ */ memcpy(skb_put(skb, 1), page_address(page), 1); skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 1, req->actual_length); page = NULL; } } else { skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0, req->actual_length); page = NULL; } if (req->actual_length < PAGE_SIZE) pnd->rx_skb = NULL; /* Last fragment */ else skb = NULL; spin_unlock_irqrestore(&pnd->rx_lock, flags); if (skb) { skb->protocol = htons(ETH_P_PHONET); skb_reset_mac_header(skb); __skb_pull(skb, 1); skb->dev = dev; dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; netif_rx(skb); } goto resubmit; case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: req = NULL; break; case -EOVERFLOW: dev->stats.rx_over_errors++; dev_dbg(&dev->dev, "RX overflow\n"); break; case -EILSEQ: dev->stats.rx_crc_errors++; break; } dev->stats.rx_errors++; resubmit: if (page) netdev_free_page(dev, page); if (req) rx_submit(pnd, req, GFP_ATOMIC); }
int svc_rdma_sendto(struct svc_rqst *rqstp) { struct svc_xprt *xprt = rqstp->rq_xprt; struct svcxprt_rdma *rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt); struct rpcrdma_msg *rdma_argp; struct rpcrdma_msg *rdma_resp; struct rpcrdma_write_array *reply_ary; enum rpcrdma_proc reply_type; int ret; int inline_bytes; struct page *res_page; struct svc_rdma_op_ctxt *ctxt; struct svc_rdma_req_map *vec; dprintk("svcrdma: sending response for rqstp=%p\n", rqstp); /* Get the RDMA request header. */ rdma_argp = xdr_start(&rqstp->rq_arg); /* Build an req vec for the XDR */ ctxt = svc_rdma_get_context(rdma); ctxt->direction = DMA_TO_DEVICE; vec = svc_rdma_get_req_map(); ret = map_xdr(rdma, &rqstp->rq_res, vec); if (ret) goto err0; inline_bytes = rqstp->rq_res.len; /* Create the RDMA response header */ res_page = svc_rdma_get_page(); rdma_resp = page_address(res_page); reply_ary = svc_rdma_get_reply_array(rdma_argp); if (reply_ary) reply_type = RDMA_NOMSG; else reply_type = RDMA_MSG; svc_rdma_xdr_encode_reply_header(rdma, rdma_argp, rdma_resp, reply_type); /* Send any write-chunk data and build resp write-list */ ret = send_write_chunks(rdma, rdma_argp, rdma_resp, rqstp, vec); if (ret < 0) { printk(KERN_ERR "svcrdma: failed to send write chunks, rc=%d\n", ret); goto err1; } inline_bytes -= ret; /* Send any reply-list data and update resp reply-list */ ret = send_reply_chunks(rdma, rdma_argp, rdma_resp, rqstp, vec); if (ret < 0) { printk(KERN_ERR "svcrdma: failed to send reply chunks, rc=%d\n", ret); goto err1; } inline_bytes -= ret; ret = send_reply(rdma, rqstp, res_page, rdma_resp, ctxt, vec, inline_bytes); svc_rdma_put_req_map(vec); dprintk("svcrdma: send_reply returns %d\n", ret); return ret; err1: put_page(res_page); err0: svc_rdma_put_req_map(vec); svc_rdma_put_context(ctxt, 0); return ret; }
/* * Read data of @inode from @block_start to @block_end and uncompress * to one zisofs block. Store the data in the @pages array with @pcount * entries. Start storing at offset @poffset of the first page. */ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start, loff_t block_end, int pcount, struct page **pages, unsigned poffset, int *errp) { unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1]; unsigned int bufsize = ISOFS_BUFFER_SIZE(inode); unsigned int bufshift = ISOFS_BUFFER_BITS(inode); unsigned int bufmask = bufsize - 1; int i, block_size = block_end - block_start; z_stream stream = { .total_out = 0, .avail_in = 0, .avail_out = 0, }; int zerr; int needblocks = (block_size + (block_start & bufmask) + bufmask) >> bufshift; int haveblocks; blkcnt_t blocknum; struct buffer_head *bhs[needblocks + 1]; int curbh, curpage; if (block_size > deflateBound(1UL << zisofs_block_shift)) { *errp = -EIO; return 0; } /* Empty block? */ if (block_size == 0) { for ( i = 0 ; i < pcount ; i++ ) { if (!pages[i]) continue; memset(page_address(pages[i]), 0, PAGE_CACHE_SIZE); flush_dcache_page(pages[i]); SetPageUptodate(pages[i]); } return ((loff_t)pcount) << PAGE_CACHE_SHIFT; } /* Because zlib is not thread-safe, do all the I/O at the top. */ blocknum = block_start >> bufshift; memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *)); haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks); ll_rw_block(READ, haveblocks, bhs); curbh = 0; curpage = 0; /* * First block is special since it may be fractional. We also wait for * it before grabbing the zlib mutex; odds are that the subsequent * blocks are going to come in in short order so we don't hold the zlib * mutex longer than necessary. */ if (!bhs[0]) goto b_eio; wait_on_buffer(bhs[0]); if (!buffer_uptodate(bhs[0])) { *errp = -EIO; goto b_eio; } stream.workspace = zisofs_zlib_workspace; mutex_lock(&zisofs_zlib_lock); zerr = zlib_inflateInit(&stream); if (zerr != Z_OK) { if (zerr == Z_MEM_ERROR) *errp = -ENOMEM; else *errp = -EIO; pr_debug("zisofs_inflateInit returned %d\n", zerr); goto z_eio; } while (curpage < pcount && curbh < haveblocks && zerr != Z_STREAM_END) { if (!stream.avail_out) { if (pages[curpage]) { stream.next_out = page_address(pages[curpage]) + poffset; stream.avail_out = PAGE_CACHE_SIZE - poffset; poffset = 0; } else { stream.next_out = (void *)&zisofs_sink_page; stream.avail_out = PAGE_CACHE_SIZE; } } if (!stream.avail_in) { wait_on_buffer(bhs[curbh]); if (!buffer_uptodate(bhs[curbh])) { *errp = -EIO; break; } stream.next_in = bhs[curbh]->b_data + (block_start & bufmask); stream.avail_in = min_t(unsigned, bufsize - (block_start & bufmask), block_size); block_size -= stream.avail_in; block_start = 0; } while (stream.avail_out && stream.avail_in) { zerr = zlib_inflate(&stream, Z_SYNC_FLUSH); if (zerr == Z_BUF_ERROR && stream.avail_in == 0) break; if (zerr == Z_STREAM_END) break; if (zerr != Z_OK) { /* EOF, error, or trying to read beyond end of input */ if (zerr == Z_MEM_ERROR) *errp = -ENOMEM; else { pr_debug( "zisofs: zisofs_inflate returned" " %d, inode = %lu," " page idx = %d, bh idx = %d," " avail_in = %ld," " avail_out = %ld\n", zerr, inode->i_ino, curpage, curbh, stream.avail_in, stream.avail_out); *errp = -EIO; } goto inflate_out; } } if (!stream.avail_out) { /* This page completed */ if (pages[curpage]) { flush_dcache_page(pages[curpage]); SetPageUptodate(pages[curpage]); } curpage++; } if (!stream.avail_in) curbh++; } inflate_out: zlib_inflateEnd(&stream); z_eio: mutex_unlock(&zisofs_zlib_lock); b_eio: for (i = 0; i < haveblocks; i++) brelse(bhs[i]); return stream.total_out; }
static int page_is_zero(struct page *p, unsigned int offset, size_t len) { char *a = page_address(p) + offset; return ((*(u32 *) a) == 0 && memcmp(a, a + 4, len - 4) == 0); }
static inline void *sg_virt(struct scatterlist *sg) { return page_address(sg->page) + sg->offset; }
/* * Must not be called with IRQs off. This should only be used on the * slow path. * * Copy a foreign granted page to local memory. */ int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep) { struct gnttab_unmap_and_replace unmap; mmu_update_t mmu; struct page *page; struct page *new_page; void *new_addr; void *addr; paddr_t pfn; maddr_t mfn; maddr_t new_mfn; int err; page = *pagep; if (!get_page_unless_zero(page)) return -ENOENT; err = -ENOMEM; new_page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); if (!new_page) goto out; new_addr = page_address(new_page); addr = page_address(page); memcpy(new_addr, addr, PAGE_SIZE); pfn = page_to_pfn(page); mfn = pfn_to_mfn(pfn); new_mfn = virt_to_mfn(new_addr); write_seqlock_bh(&gnttab_dma_lock); /* Make seq visible before checking page_mapped. */ smp_mb(); /* Has the page been DMA-mapped? */ if (unlikely(page_mapped(page))) { write_sequnlock_bh(&gnttab_dma_lock); put_page(new_page); err = -EBUSY; goto out; } if (!xen_feature(XENFEAT_auto_translated_physmap)) set_phys_to_machine(pfn, new_mfn); gnttab_set_replace_op(&unmap, (unsigned long)addr, (unsigned long)new_addr, ref); err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_and_replace, &unmap, 1); BUG_ON(err); BUG_ON(unmap.status); write_sequnlock_bh(&gnttab_dma_lock); if (!xen_feature(XENFEAT_auto_translated_physmap)) { set_phys_to_machine(page_to_pfn(new_page), INVALID_P2M_ENTRY); mmu.ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; mmu.val = pfn; err = HYPERVISOR_mmu_update(&mmu, 1, NULL, DOMID_SELF); BUG_ON(err); } new_page->mapping = page->mapping; new_page->index = page->index; set_bit(PG_foreign, &new_page->flags); if (PageReserved(page)) SetPageReserved(new_page); *pagep = new_page; SetPageForeign(page, gnttab_page_free); page->mapping = NULL; out: put_page(page); return err; }
/* * Add a new chunk of uncached memory pages to the specified pool. * * @pool: pool to add new chunk of uncached memory to * @nid: node id of node to allocate memory from, or -1 * * This is accomplished by first allocating a granule of cached memory pages * and then converting them to uncached memory pages. */ static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid) { struct page *page; int status, i, nchunks_added = uc_pool->nchunks_added; unsigned long c_addr, uc_addr; if (mutex_lock_interruptible(&uc_pool->add_chunk_mutex) != 0) return -1; /* interrupted by a signal */ if (uc_pool->nchunks_added > nchunks_added) { /* someone added a new chunk while we were waiting */ mutex_unlock(&uc_pool->add_chunk_mutex); return 0; } if (uc_pool->nchunks_added >= MAX_CONVERTED_CHUNKS_PER_NODE) { mutex_unlock(&uc_pool->add_chunk_mutex); return -1; } /* attempt to allocate a granule's worth of cached memory pages */ page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, IA64_GRANULE_SHIFT-PAGE_SHIFT); if (!page) { mutex_unlock(&uc_pool->add_chunk_mutex); return -1; } /* convert the memory pages from cached to uncached */ c_addr = (unsigned long)page_address(page); uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET; /* * There's a small race here where it's possible for someone to * access the page through /dev/mem halfway through the conversion * to uncached - not sure it's really worth bothering about */ for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) SetPageUncached(&page[i]); flush_tlb_kernel_range(uc_addr, uc_addr + IA64_GRANULE_SIZE); status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL); if (status == PAL_VISIBILITY_OK_REMOTE_NEEDED) { atomic_set(&uc_pool->status, 0); status = smp_call_function(uncached_ipi_visibility, uc_pool, 1); if (status || atomic_read(&uc_pool->status)) goto failed; } else if (status != PAL_VISIBILITY_OK) goto failed; preempt_disable(); if (ia64_platform_is("sn2")) sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE); else flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE); /* flush the just introduced uncached translation from the TLB */ local_flush_tlb_all(); preempt_enable(); status = ia64_pal_mc_drain(); if (status != PAL_STATUS_SUCCESS) goto failed; atomic_set(&uc_pool->status, 0); status = smp_call_function(uncached_ipi_mc_drain, uc_pool, 1); if (status || atomic_read(&uc_pool->status)) goto failed; /* * The chunk of memory pages has been converted to uncached so now we * can add it to the pool. */ status = gen_pool_add(uc_pool->pool, uc_addr, IA64_GRANULE_SIZE, nid); if (status) goto failed; uc_pool->nchunks_added++; mutex_unlock(&uc_pool->add_chunk_mutex); return 0; /* failed to convert or add the chunk so give it back to the kernel */ failed: for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++) ClearPageUncached(&page[i]); free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT); mutex_unlock(&uc_pool->add_chunk_mutex); return -1; }
static struct xpc_gru_mq_uv * xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, irq_handler_t irq_handler) { enum xp_retval xp_ret; int ret; int nid; int nasid; int pg_order; struct page *page; struct xpc_gru_mq_uv *mq; struct uv_IO_APIC_route_entry *mmr_value; mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL); if (mq == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " "a xpc_gru_mq_uv structure\n"); ret = -ENOMEM; goto out_0; } mq->gru_mq_desc = kzalloc(sizeof(struct gru_message_queue_desc), GFP_KERNEL); if (mq->gru_mq_desc == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " "a gru_message_queue_desc structure\n"); ret = -ENOMEM; goto out_1; } pg_order = get_order(mq_size); mq->order = pg_order + PAGE_SHIFT; mq_size = 1UL << mq->order; mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); page = __alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); ret = -ENOMEM; goto out_2; } mq->address = page_address(page); /* enable generation of irq when GRU mq operation occurs to this mq */ ret = xpc_gru_mq_watchlist_alloc_uv(mq); if (ret != 0) goto out_3; ret = xpc_get_gru_mq_irq_uv(mq, cpu, irq_name); if (ret != 0) goto out_4; ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL); if (ret != 0) { dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n", mq->irq, -ret); goto out_5; } nasid = UV_PNODE_TO_NASID(uv_cpu_to_pnode(cpu)); mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value; ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size, nasid, mmr_value->vector, mmr_value->dest); if (ret != 0) { dev_err(xpc_part, "gru_create_message_queue() returned " "error=%d\n", ret); ret = -EINVAL; goto out_6; } /* allow other partitions to access this GRU mq */ xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size); if (xp_ret != xpSuccess) { ret = -EACCES; goto out_6; } return mq; /* something went wrong */ out_6: free_irq(mq->irq, NULL); out_5: xpc_release_gru_mq_irq_uv(mq); out_4: xpc_gru_mq_watchlist_free_uv(mq); out_3: free_pages((unsigned long)mq->address, pg_order); out_2: kfree(mq->gru_mq_desc); out_1: kfree(mq); out_0: return ERR_PTR(ret); }
int g2d_mem_request(__u32 size) { #ifdef __FPGA_DEBUG_G2D__ if (g2d_size ==0){ __s32 sel; struct page *page; unsigned map_size = 0; sel = g2d_get_free_mem_index(); if(sel < 0) { ERR("g2d_get_free_mem_index fail!\n"); return -EINVAL; } map_size = (size + 4095) & 0xfffff000;//4k align page = alloc_pages(GFP_KERNEL,get_order(map_size)); if(page != NULL) { g2d_mem[sel].virt_addr = page_address(page); if(g2d_mem[sel].virt_addr == 0) { free_pages((unsigned long)(page),get_order(map_size)); ERR("line %d:fail to alloc memory!\n",__LINE__); return -ENOMEM; } memset(g2d_mem[sel].virt_addr,0,size); g2d_mem[sel].phy_addr = virt_to_phys(g2d_mem[sel].virt_addr); g2d_mem[sel].mem_len = size; g2d_mem[sel].b_used = 1; INFO("map_g2d_memory[%d]: pa=%08lx va=%p size:%x\n",sel,g2d_mem[sel].phy_addr, g2d_mem[sel].virt_addr, size); return sel; } else { ERR("fail to alloc memory!\n"); return -ENOMEM; } } #endif __s32 sel; __u32 ret = 0; __u32 phy_addr; sel = g2d_get_free_mem_index(); if(sel < 0) { ERR("g2d_get_free_mem_index fail!\n"); return -EINVAL; } ret = (__u32)g2d_malloc(size,&phy_addr); if(ret != 0) { g2d_mem[sel].virt_addr = (void*)ret; memset(g2d_mem[sel].virt_addr,0,size); g2d_mem[sel].phy_addr = phy_addr; #ifdef __FPGA_DEBUG_G2D__ g2d_mem[sel].phy_addr = g2d_virt_to_phys(g2d_mem[sel].virt_addr); #endif g2d_mem[sel].mem_len = size; g2d_mem[sel].b_used = 1; INFO("map_g2d_memory[%d]: pa=%08lx va=%p size:%x\n",sel,g2d_mem[sel].phy_addr, g2d_mem[sel].virt_addr, size); return sel; } else { ERR("fail to alloc reserved memory!\n"); return -ENOMEM; } }
/* * Write back & invalidate the D-cache of the page. * (To avoid "alias" issues) */ void flush_dcache_page(struct page *page) { if (test_bit(PG_mapped, &page->flags)) __flush_dcache_page(PHYSADDR(page_address(page))); }
/* filemap_write_and_wait(inode->i_mapping); */ if ( inode->i_mapping->nrpages && filemap_fdatawrite(inode->i_mapping) != -EIO) filemap_fdatawait(inode->i_mapping); #endif rc = vboxCallClose(&client_handle, &sf_g->map, sf_r->handle); if (RT_FAILURE(rc)) LogFunc(("vboxCallClose failed rc=%Rrc\n", rc)); kfree(sf_r); sf_i->file = NULL; sf_i->handle = SHFL_HANDLE_NIL; file->private_data = NULL; return 0; } #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) static int sf_reg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vaddr, int *type) # define SET_TYPE(t) *type = (t) #else /* LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0) */ static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vaddr, int unused) # define SET_TYPE(t) #endif { struct page *page; char *buf; loff_t off; uint32_t nread = PAGE_SIZE; int err; struct file *file = vma->vm_file; struct inode *inode = file->f_dentry->d_inode; struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb); struct sf_reg_info *sf_r = file->private_data; TRACE(); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) if (vmf->pgoff > vma->vm_end) return VM_FAULT_SIGBUS; #else if (vaddr > vma->vm_end) { SET_TYPE(VM_FAULT_SIGBUS); return NOPAGE_SIGBUS; } #endif /* Don't use GFP_HIGHUSER as long as sf_reg_read_aux() calls vboxCallRead() * which works on virtual addresses. On Linux cannot reliably determine the * physical address for high memory, see rtR0MemObjNativeLockKernel(). */ page = alloc_page(GFP_USER); if (!page) { LogRelFunc(("failed to allocate page\n")); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) return VM_FAULT_OOM; #else SET_TYPE(VM_FAULT_OOM); return NOPAGE_OOM; #endif } buf = kmap(page); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) off = (vmf->pgoff << PAGE_SHIFT); #else off = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); #endif err = sf_reg_read_aux(__func__, sf_g, sf_r, buf, &nread, off); if (err) { kunmap(page); put_page(page); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) return VM_FAULT_SIGBUS; #else SET_TYPE(VM_FAULT_SIGBUS); return NOPAGE_SIGBUS; #endif } BUG_ON (nread > PAGE_SIZE); if (!nread) { #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) clear_user_page(page_address(page), vmf->pgoff, page); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) clear_user_page(page_address(page), vaddr, page); #else clear_user_page(page_address(page), vaddr); #endif } else memset(buf + nread, 0, PAGE_SIZE - nread); flush_dcache_page(page); kunmap(page); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) vmf->page = page; return 0; #else SET_TYPE(VM_FAULT_MAJOR); return page; #endif }