All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH for-4.8 1/2] x86/vmx: Correct the long mode check in vmx_cpuid_intercept()
From: Jan Beulich @ 2016-11-14 11:35 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Kevin Tian, Wei Liu, Jun Nakajima, Xen-devel
In-Reply-To: <1479121286-6390-1-git-send-email-andrew.cooper3@citrix.com>

>>> On 14.11.16 at 12:01, <andrew.cooper3@citrix.com> wrote:
> %cs.L may be set in a legacy mode segment, or clear in a compatibility mode
> segment; it is not the correct way to check for long mode being active.
> 
> Both of these situations result in incorrect visibility of the SYSCALL feature
> in CPUID, and by extension, incorrect behaviour in hvm_efer_valid().
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply

* Re: OE plans for morty
From: Martin Jansa @ 2016-11-14 11:34 UTC (permalink / raw)
  To: akuster808, Joe MacDonald; +Cc: openembedded-devel@lists.openembedded.org
In-Reply-To: <20161026083316.GB4096@jama>

[-- Attachment #1: Type: text/plain, Size: 5140 bytes --]

On Wed, Oct 26, 2016 at 10:33:16AM +0200, Martin Jansa wrote:
> On Mon, Oct 24, 2016 at 07:07:55PM -0700, akuster808 wrote:
> > Randy,
> > 
> > 
> > On 10/24/2016 05:51 PM, Randy MacLeod wrote:
> > >
> > >
> > > I saw that morty has been branched and there have been 38 commits
> > > made to master.  Woo-hoo and thanks Martin!
> > 
> > 
> > >
> > > Armin,
> > >
> > > Many of the master commits sh/could be cherry-picked back
> > > to morty since they are bug fixes rather than package uprevs.
> > > I have a list of commits to cherry-pick below. '?' indicates
> > > that I'm not sure from the oneline summary if it's just a bug
> > > fix as you might expect.
> > 
> > Thanks for providing commit ids you are interested in.
> > 
> > I have pushed the contrib morty-next  this morning.
> > 
> > http://cgit.openembedded.org/meta-openembedded-contrib/log/?h=akuster/morty-next
> 
> What about using current master (I've pushed bunch of commits today) +
> hopefully following in meta-networking which should be pushed by Joe
> (currently waiting in master-next):
> 
> pick 2c1d637 linux-atm: fix do_compile error
> pick bfb71d5 lowpan-tools: Fix errors found with clang
> pick 944cd7a openl2tp: Fix build with clang
> pick 9641512 libmnl, nftables: Update versions
> pick 8303d85 c-ares: update 1.11.0 -> 1.12.0
> pick 36c563d c-ares: fix metadata
> pick 7552201 lksctp-tools: 1.0.16 -> 1.0.17
> pick a0fcdac drbd-utils: 8.9.3 -> 8.9.6
> 
> This gives us almost clean bitbake world status I've sent few minutes
> ago.
> 
> I haven't merged the README update to morty yet, so we can do this sync
> with master as fast forward (and continue to do so until there is fist
> master-only change merged in master).

Joe: when are you planing to merge next batch of meta-networking
changes? At least the list mentioned above? I'm still waiting with final
morty branch update before merging first master-only changes.

Regards,

> Regards,
> 
> > > Are you going to do a dot release in the coming weeks or will
> > > it be more like early next year?
> > 
> > I am hoping to do a pull request request shortly after morty is 
> > announced by Richard.
> > 
> > Some of the commits listed below are in master-next so I need to wait 
> > for them to hit master before I  cherry-pick any additional changes.
> > 
> > Hope this is a satisfactory plan.
> > 
> > 
> > regards,
> > Armin
> > 
> > >
> > > ../Randy
> > >
> > > ec0fb46 openldap: use recommended backend mdb
> > >
> > > ? 64ebc30 android-tools: fix native build
> > > d2902a3 dhcp_%.bbappend: fix replaces original key warning
> > >
> > > ? 965d028 python-unidiff: python module for parsing diff data
> > >
> > > ? 1be8a35 joe: Fix build with clang
> > > ? 2084473 openl2tp: Fix build with clang
> > > ? 0004410 flashrom: Fix build with clang and aarch64
> > > ? 83fec86 gpm: Remove nested functions
> > > ? 9446302 lowpan-tools: Fix errors found with clang
> > >
> > > ? 5e0dc68 python-greenlet: Rename register from rX to xX for aarch64
> > > ? d8e9117 frame: Fix build with clang
> > > ? 612b2bb libplist: Squash warnings found by clang
> > > ? 2951547 libmbim: Fix build with clang
> > > ? c04bdbe libbonobo: Fix missing dep on orbit2-native and build with 
> > > clang
> > >
> > > 6b3e9ff linux-atm: fix do_compile error
> > >
> > > ? 9a83c34 adduser: always add -M option for useradd
> > >
> > > ? da12104 v4l-utils: add support for "native" build
> > >
> > >
> > > cfe1fba postgresql.inc: Fix do_configure error (could not find Python.h)
> > >
> > >
> > > ? 8ba31c9 gpsd, mongodb: use PACKAGECONFIG_CONFARGS instead of now 
> > > empty EXTRA_OECONF
> > > ? f882db6 ipmiutil: uncomment PARALLEL_MAKE
> > >
> > > ? 54c7e78 pcsc-lite: Seperate GPLV3 portions from BSD
> > > fded4cf opencv: fix packaging and install
> > >
> > >
> > > 1c072cb gvfs: fix fetch error
> > > ? 0cc3d06 leptonica: add PACKAGECONFIG for giflib
> > > ? 8eef5ab wireshark: update to 2.2.1
> > >
> > > ? 812e940 ntp : Add openssl to default PACKAGECONFIG options
> > > ? 8760099 atftp: fixes musl libc build
> > > ? 5abe6ea arptables: add the directory for default 
> > > /etc/sysconfig/arptables
> > > ? a0e2240 arptables: add arptables systemd service file
> > > 93b0d65 iscsitarget: resolve build error with linux kernel 4.8
> > > 9e8d127 squid: fix ptest failure
> > > 6f54f29 squid: specify sysconfdir and logdir
> > > 307d1c9 libtdb: fixes for deterministic builds
> > > 5175c03 libldb: fixes for deterministic builds
> > > 5291715 libtevent: fixes for deterministic builds
> > > 778a2b6 libtalloc: fixes for deterministic builds
> > > fe652f8 libldb: fix for LIC_FILES_CHKSUM
> > > f25aa3d libtdb: fix for LIC_FILES_CHKSUM
> > > d4a36f6 libtevent: fix for LIC_FILES_CHKSUM
> > > 0014397 libtalloc: fix for LIC_FILES_CHKSUM
> > >
> > > a95726d samba: replace pam packageconfig by hard dependency
> > > 3fdfdd8 samba: un-blacklist
> > >
> > 
> 
> -- 
> Martin 'JaMa' Jansa     jabber: Martin.Jansa@gmail.com



-- 
Martin 'JaMa' Jansa     jabber: Martin.Jansa@gmail.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 169 bytes --]

^ permalink raw reply

* Re: [PATCH v6 12/16] IB/pvrdma: Add Queue Pair support
From: Yuval Shaia @ 2016-11-14 11:34 UTC (permalink / raw)
  To: Adit Ranadive
  Cc: dledford-H+wXaHxf7aLQT0dZR+AlfA,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA,
	pv-drivers-pghWNbHTmq7QT0dZR+AlfA, jhansen-pghWNbHTmq7QT0dZR+AlfA,
	asarwade-pghWNbHTmq7QT0dZR+AlfA,
	georgezhang-pghWNbHTmq7QT0dZR+AlfA,
	bryantan-pghWNbHTmq7QT0dZR+AlfA
In-Reply-To: <6a643e92376856394d45638d80a90619d3abac37.1475458407.git.aditr-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>

On Sun, Oct 02, 2016 at 07:10:32PM -0700, Adit Ranadive wrote:
> This patch adds the ability to create, modify, query and destroy QPs. The
> PVRDMA device supports RC, UD and GSI QPs.
> 
> Reviewed-by: Yuval Shaia <yuval.shaia-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
> Reviewed-by: Jorgen Hansen <jhansen-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
> Reviewed-by: George Zhang <georgezhang-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
> Reviewed-by: Aditya Sarwade <asarwade-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
> Reviewed-by: Bryan Tan <bryantan-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Adit Ranadive <aditr-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
> ---
> Changes v5->v6:
>  - Removed a duplicate include of the ABI header.
> 
> Changes v4->v5:
>  - Updated include for headers in UAPI folder.
>  - Update to pvrdma_cmd_post for creating/destroying/querying/modifying QPs.
>  - Use the pvrdma_sge struct when posting WRs/allocating QP memory.
>  - Removed two set but unused variables.
> 
> Changes v3->v4:
>  - Removed an unnecessary switch case.
>  - Unified the returns in pvrdma_create_qp to use one exit point.
>  - Renamed pvrdma_flush_cqe to _pvrdma_flush_cqe since we need a lock to
>  be held when calling this.
>  - Updated to use wrapper for UAR write for QP.
>  - Updated conversion function to func_name(dst, src) format.
>  - Renamed max_gs to max_sg.
>  - Renamed cap variable to req_cap in pvrdma_set_sq/rq_size.
>  - Changed dev_warn to dev_warn_ratelimited in pvrdma_post_send/recv.
>  - Added nesting locking for flushing CQs when destroying/resetting a QP.
>  - Added missing ret value.
> 
> Changes v2->v3:
>  - Removed boolean in pvrdma_cmd_post.
> ---
>  drivers/infiniband/hw/pvrdma/pvrdma_qp.c | 972 +++++++++++++++++++++++++++++++
>  1 file changed, 972 insertions(+)
>  create mode 100644 drivers/infiniband/hw/pvrdma/pvrdma_qp.c
> 
> diff --git a/drivers/infiniband/hw/pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/pvrdma/pvrdma_qp.c
> new file mode 100644
> index 0000000..c8c01e5
> --- /dev/null
> +++ b/drivers/infiniband/hw/pvrdma/pvrdma_qp.c
> @@ -0,0 +1,972 @@
> +/*
> + * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of EITHER the GNU General Public License
> + * version 2 as published by the Free Software Foundation or the BSD
> + * 2-Clause License. This program is distributed in the hope that it
> + * will be useful, but WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
> + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
> + * See the GNU General Public License version 2 for more details at
> + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program available in the file COPYING in the main
> + * directory of this source tree.
> + *
> + * The BSD 2-Clause License
> + *
> + *     Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *      - Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *
> + *      - Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
> + * OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <asm/page.h>
> +#include <linux/io.h>
> +#include <linux/wait.h>
> +#include <rdma/ib_addr.h>
> +#include <rdma/ib_smi.h>
> +#include <rdma/ib_user_verbs.h>
> +
> +#include "pvrdma.h"
> +
> +static inline void get_cqs(struct pvrdma_qp *qp, struct pvrdma_cq **send_cq,
> +			   struct pvrdma_cq **recv_cq)
> +{
> +	*send_cq = to_vcq(qp->ibqp.send_cq);
> +	*recv_cq = to_vcq(qp->ibqp.recv_cq);
> +}
> +
> +static void pvrdma_lock_cqs(struct pvrdma_cq *scq, struct pvrdma_cq *rcq,
> +			    unsigned long *scq_flags,
> +			    unsigned long *rcq_flags)
> +	__acquires(scq->cq_lock) __acquires(rcq->cq_lock)
> +{
> +	if (scq == rcq) {
> +		spin_lock_irqsave(&scq->cq_lock, *scq_flags);
> +		__acquire(rcq->cq_lock);
> +	} else if (scq->cq_handle < rcq->cq_handle) {
> +		spin_lock_irqsave(&scq->cq_lock, *scq_flags);
> +		spin_lock_irqsave_nested(&rcq->cq_lock, *rcq_flags,
> +					 SINGLE_DEPTH_NESTING);
> +	} else {
> +		spin_lock_irqsave(&rcq->cq_lock, *rcq_flags);
> +		spin_lock_irqsave_nested(&scq->cq_lock, *scq_flags,
> +					 SINGLE_DEPTH_NESTING);
> +	}
> +}
> +
> +static void pvrdma_unlock_cqs(struct pvrdma_cq *scq, struct pvrdma_cq *rcq,
> +			      unsigned long *scq_flags,
> +			      unsigned long *rcq_flags)
> +	__releases(scq->cq_lock) __releases(rcq->cq_lock)
> +{
> +	if (scq == rcq) {
> +		__release(rcq->cq_lock);
> +		spin_unlock_irqrestore(&scq->cq_lock, *scq_flags);
> +	} else if (scq->cq_handle < rcq->cq_handle) {
> +		spin_unlock_irqrestore(&rcq->cq_lock, *rcq_flags);
> +		spin_unlock_irqrestore(&scq->cq_lock, *scq_flags);
> +	} else {
> +		spin_unlock_irqrestore(&scq->cq_lock, *scq_flags);
> +		spin_unlock_irqrestore(&rcq->cq_lock, *rcq_flags);
> +	}
> +}
> +
> +static void pvrdma_reset_qp(struct pvrdma_qp *qp)
> +{
> +	struct pvrdma_cq *scq, *rcq;
> +	unsigned long scq_flags, rcq_flags;
> +
> +	/* Clean up cqes */
> +	get_cqs(qp, &scq, &rcq);
> +	pvrdma_lock_cqs(scq, rcq, &scq_flags, &rcq_flags);
> +
> +	_pvrdma_flush_cqe(qp, scq);
> +	if (scq != rcq)
> +		_pvrdma_flush_cqe(qp, rcq);
> +
> +	pvrdma_unlock_cqs(scq, rcq, &scq_flags, &rcq_flags);
> +
> +	/*
> +	 * Reset queuepair. The checks are because usermode queuepairs won't
> +	 * have kernel ringstates.
> +	 */
> +	if (qp->rq.ring) {
> +		atomic_set(&qp->rq.ring->cons_head, 0);
> +		atomic_set(&qp->rq.ring->prod_tail, 0);
> +	}
> +	if (qp->sq.ring) {
> +		atomic_set(&qp->sq.ring->cons_head, 0);
> +		atomic_set(&qp->sq.ring->prod_tail, 0);
> +	}
> +}
> +
> +static int pvrdma_set_rq_size(struct pvrdma_dev *dev,
> +			      struct ib_qp_cap *req_cap,
> +			      struct pvrdma_qp *qp)
> +{
> +	if (req_cap->max_recv_wr > dev->dsr->caps.max_qp_wr ||
> +	    req_cap->max_recv_sge > dev->dsr->caps.max_sge) {
> +		dev_warn(&dev->pdev->dev, "recv queue size invalid\n");
> +		return -EINVAL;
> +	}
> +
> +	qp->rq.wqe_cnt = roundup_pow_of_two(max(1U, req_cap->max_recv_wr));
> +	qp->rq.max_sg = roundup_pow_of_two(max(1U, req_cap->max_recv_sge));
> +
> +	/* Write back */
> +	req_cap->max_recv_wr = qp->rq.wqe_cnt;
> +	req_cap->max_recv_sge = qp->rq.max_sg;
> +
> +	qp->rq.wqe_size = roundup_pow_of_two(sizeof(struct pvrdma_rq_wqe_hdr) +
> +					     sizeof(struct pvrdma_sge) *
> +					     qp->rq.max_sg);
> +	qp->npages_recv = (qp->rq.wqe_cnt * qp->rq.wqe_size + PAGE_SIZE - 1) /
> +			  PAGE_SIZE;
> +
> +	return 0;
> +}
> +
> +static int pvrdma_set_sq_size(struct pvrdma_dev *dev, struct ib_qp_cap *req_cap,
> +			      enum ib_qp_type type, struct pvrdma_qp *qp)
> +{
> +	if (req_cap->max_send_wr > dev->dsr->caps.max_qp_wr ||
> +	    req_cap->max_send_sge > dev->dsr->caps.max_sge) {
> +		dev_warn(&dev->pdev->dev, "send queue size invalid\n");
> +		return -EINVAL;
> +	}
> +
> +	qp->sq.wqe_cnt = roundup_pow_of_two(max(1U, req_cap->max_send_wr));
> +	qp->sq.max_sg = roundup_pow_of_two(max(1U, req_cap->max_send_sge));
> +
> +	/* Write back */
> +	req_cap->max_send_wr = qp->sq.wqe_cnt;
> +	req_cap->max_send_sge = qp->sq.max_sg;
> +
> +	qp->sq.wqe_size = roundup_pow_of_two(sizeof(struct pvrdma_sq_wqe_hdr) +
> +					     sizeof(struct pvrdma_sge) *
> +					     qp->sq.max_sg);
> +	/* Note: one extra page for the header. */
> +	qp->npages_send = 1 + (qp->sq.wqe_cnt * qp->sq.wqe_size +
> +			       PAGE_SIZE - 1) / PAGE_SIZE;
> +
> +	return 0;
> +}
> +
> +/**
> + * pvrdma_create_qp - create queue pair
> + * @pd: protection domain
> + * @init_attr: queue pair attributes
> + * @udata: user data
> + *
> + * @return: the ib_qp pointer on success, otherwise returns an errno.
> + */
> +struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
> +			       struct ib_qp_init_attr *init_attr,
> +			       struct ib_udata *udata)
> +{
> +	struct pvrdma_qp *qp = NULL;
> +	struct pvrdma_dev *dev = to_vdev(pd->device);
> +	union pvrdma_cmd_req req;
> +	union pvrdma_cmd_resp rsp;
> +	struct pvrdma_cmd_create_qp *cmd = &req.create_qp;
> +	struct pvrdma_cmd_create_qp_resp *resp = &rsp.create_qp_resp;
> +	struct pvrdma_create_qp ucmd;
> +	unsigned long flags;
> +	int ret;
> +
> +	if (init_attr->create_flags) {
> +		dev_warn(&dev->pdev->dev,
> +			 "invalid create queuepair flags %#x\n",
> +			 init_attr->create_flags);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (init_attr->qp_type != IB_QPT_RC &&
> +	    init_attr->qp_type != IB_QPT_UD &&
> +	    init_attr->qp_type != IB_QPT_GSI) {
> +		dev_warn(&dev->pdev->dev, "queuepair type %d not supported\n",
> +			 init_attr->qp_type);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	if (!atomic_add_unless(&dev->num_qps, 1, dev->dsr->caps.max_qp))
> +		return ERR_PTR(-ENOMEM);
> +
> +	switch (init_attr->qp_type) {
> +	case IB_QPT_GSI:
> +		if (init_attr->port_num == 0 ||
> +		    init_attr->port_num > pd->device->phys_port_cnt ||
> +		    udata) {
> +			dev_warn(&dev->pdev->dev, "invalid queuepair attrs\n");
> +			ret = -EINVAL;
> +			goto err_qp;
> +		}
> +		/* fall through */
> +	case IB_QPT_RC:
> +	case IB_QPT_UD:
> +		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
> +		if (!qp) {
> +			ret = -ENOMEM;
> +			goto err_qp;
> +		}
> +
> +		spin_lock_init(&qp->sq.lock);
> +		spin_lock_init(&qp->rq.lock);
> +		mutex_init(&qp->mutex);
> +		atomic_set(&qp->refcnt, 1);
> +		init_waitqueue_head(&qp->wait);
> +
> +		qp->state = IB_QPS_RESET;
> +
> +		if (pd->uobject && udata) {
> +			dev_dbg(&dev->pdev->dev,
> +				"create queuepair from user space\n");
> +
> +			if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
> +				ret = -EFAULT;
> +				goto err_qp;
> +			}
> +
> +			/* set qp->sq.wqe_cnt, shift, buf_size.. */
> +			qp->rumem = ib_umem_get(pd->uobject->context,
> +						ucmd.rbuf_addr,
> +						ucmd.rbuf_size, 0, 0);
> +			if (IS_ERR(qp->rumem)) {
> +				ret = PTR_ERR(qp->rumem);
> +				goto err_qp;
> +			}
> +
> +			qp->sumem = ib_umem_get(pd->uobject->context,
> +						ucmd.sbuf_addr,
> +						ucmd.sbuf_size, 0, 0);
> +			if (IS_ERR(qp->sumem)) {
> +				ib_umem_release(qp->rumem);
> +				ret = PTR_ERR(qp->sumem);
> +				goto err_qp;
> +			}
> +
> +			qp->npages_send = ib_umem_page_count(qp->sumem);
> +			qp->npages_recv = ib_umem_page_count(qp->rumem);
> +			qp->npages = qp->npages_send + qp->npages_recv;
> +		} else {
> +			qp->is_kernel = true;
> +
> +			ret = pvrdma_set_sq_size(to_vdev(pd->device),
> +						 &init_attr->cap,
> +						 init_attr->qp_type, qp);
> +			if (ret)
> +				goto err_qp;
> +
> +			ret = pvrdma_set_rq_size(to_vdev(pd->device),
> +						 &init_attr->cap, qp);
> +			if (ret)
> +				goto err_qp;
> +
> +			qp->npages = qp->npages_send + qp->npages_recv;
> +
> +			/* Skip header page. */
> +			qp->sq.offset = PAGE_SIZE;
> +
> +			/* Recv queue pages are after send pages. */
> +			qp->rq.offset = qp->npages_send * PAGE_SIZE;
> +		}
> +
> +		if (qp->npages < 0 || qp->npages > PVRDMA_PAGE_DIR_MAX_PAGES) {
> +			dev_warn(&dev->pdev->dev,
> +				 "overflow pages in queuepair\n");
> +			ret = -EINVAL;
> +			goto err_umem;
> +		}
> +
> +		ret = pvrdma_page_dir_init(dev, &qp->pdir, qp->npages,
> +					   qp->is_kernel);
> +		if (ret) {
> +			dev_warn(&dev->pdev->dev,
> +				 "could not allocate page directory\n");
> +			goto err_umem;
> +		}
> +
> +		if (!qp->is_kernel) {
> +			pvrdma_page_dir_insert_umem(&qp->pdir, qp->sumem, 0);
> +			pvrdma_page_dir_insert_umem(&qp->pdir, qp->rumem,
> +						    qp->npages_send);
> +		} else {
> +			/* Ring state is always the first page. */
> +			qp->sq.ring = qp->pdir.pages[0];
> +			qp->rq.ring = &qp->sq.ring[1];
> +		}
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		goto err_qp;
> +	}
> +
> +	/* Not supported */
> +	init_attr->cap.max_inline_data = 0;
> +
> +	memset(cmd, 0, sizeof(*cmd));
> +	cmd->hdr.cmd = PVRDMA_CMD_CREATE_QP;
> +	cmd->pd_handle = to_vpd(pd)->pd_handle;
> +	cmd->send_cq_handle = to_vcq(init_attr->send_cq)->cq_handle;
> +	cmd->recv_cq_handle = to_vcq(init_attr->recv_cq)->cq_handle;
> +	cmd->max_send_wr = init_attr->cap.max_send_wr;
> +	cmd->max_recv_wr = init_attr->cap.max_recv_wr;
> +	cmd->max_send_sge = init_attr->cap.max_send_sge;
> +	cmd->max_recv_sge = init_attr->cap.max_recv_sge;
> +	cmd->max_inline_data = init_attr->cap.max_inline_data;
> +	cmd->sq_sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ? 1 : 0;
> +	cmd->qp_type = ib_qp_type_to_pvrdma(init_attr->qp_type);
> +	cmd->access_flags = IB_ACCESS_LOCAL_WRITE;
> +	cmd->total_chunks = qp->npages;
> +	cmd->send_chunks = qp->npages_send - 1;
> +	cmd->pdir_dma = qp->pdir.dir_dma;
> +
> +	dev_dbg(&dev->pdev->dev, "create queuepair with %d, %d, %d, %d\n",
> +		cmd->max_send_wr, cmd->max_recv_wr, cmd->max_send_sge,
> +		cmd->max_recv_sge);
> +
> +	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_QP_RESP);
> +	if (ret < 0) {
> +		dev_warn(&dev->pdev->dev,
> +			 "could not create queuepair, error: %d\n", ret);
> +		goto err_pdir;
> +	}
> +
> +	/* max_send_wr/_recv_wr/_send_sge/_recv_sge/_inline_data */
> +	qp->qp_handle = resp->qpn;
> +	qp->port = init_attr->port_num;
> +	qp->ibqp.qp_num = resp->qpn;
> +	spin_lock_irqsave(&dev->qp_tbl_lock, flags);
> +	dev->qp_tbl[qp->qp_handle % dev->dsr->caps.max_qp] = qp;
> +	spin_unlock_irqrestore(&dev->qp_tbl_lock, flags);
> +
> +	return &qp->ibqp;
> +
> +err_pdir:
> +	pvrdma_page_dir_cleanup(dev, &qp->pdir);
> +err_umem:
> +	if (pd->uobject && udata) {
> +		if (qp->rumem)
> +			ib_umem_release(qp->rumem);
> +		if (qp->sumem)
> +			ib_umem_release(qp->sumem);
> +	}
> +err_qp:
> +	kfree(qp);
> +	atomic_dec(&dev->num_qps);
> +
> +	return ERR_PTR(ret);
> +}
> +
> +static void pvrdma_free_qp(struct pvrdma_qp *qp)
> +{
> +	struct pvrdma_dev *dev = to_vdev(qp->ibqp.device);
> +	struct pvrdma_cq *scq;
> +	struct pvrdma_cq *rcq;
> +	unsigned long flags, scq_flags, rcq_flags;
> +
> +	/* In case cq is polling */
> +	get_cqs(qp, &scq, &rcq);
> +	pvrdma_lock_cqs(scq, rcq, &scq_flags, &rcq_flags);
> +
> +	_pvrdma_flush_cqe(qp, scq);
> +	if (scq != rcq)
> +		_pvrdma_flush_cqe(qp, rcq);
> +
> +	spin_lock_irqsave(&dev->qp_tbl_lock, flags);
> +	dev->qp_tbl[qp->qp_handle] = NULL;
> +	spin_unlock_irqrestore(&dev->qp_tbl_lock, flags);
> +
> +	pvrdma_unlock_cqs(scq, rcq, &scq_flags, &rcq_flags);
> +
> +	atomic_dec(&qp->refcnt);
> +	wait_event(qp->wait, !atomic_read(&qp->refcnt));
> +
> +	pvrdma_page_dir_cleanup(dev, &qp->pdir);
> +
> +	kfree(qp);
> +
> +	atomic_dec(&dev->num_qps);
> +}
> +
> +/**
> + * pvrdma_destroy_qp - destroy a queue pair
> + * @qp: the queue pair to destroy
> + *
> + * @return: 0 on success.
> + */
> +int pvrdma_destroy_qp(struct ib_qp *qp)
> +{
> +	struct pvrdma_qp *vqp = to_vqp(qp);
> +	union pvrdma_cmd_req req;
> +	struct pvrdma_cmd_destroy_qp *cmd = &req.destroy_qp;
> +	int ret;
> +
> +	memset(cmd, 0, sizeof(*cmd));
> +	cmd->hdr.cmd = PVRDMA_CMD_DESTROY_QP;
> +	cmd->qp_handle = vqp->qp_handle;
> +
> +	ret = pvrdma_cmd_post(to_vdev(qp->device), &req, NULL, 0);
> +	if (ret < 0)
> +		dev_warn(&to_vdev(qp->device)->pdev->dev,
> +			 "destroy queuepair failed, error: %d\n", ret);
> +
> +	pvrdma_free_qp(vqp);
> +
> +	return 0;
> +}
> +
> +/**
> + * pvrdma_modify_qp - modify queue pair attributes
> + * @ibqp: the queue pair
> + * @attr: the new queue pair's attributes
> + * @attr_mask: attributes mask
> + * @udata: user data
> + *
> + * @returns 0 on success, otherwise returns an errno.
> + */
> +int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
> +		     int attr_mask, struct ib_udata *udata)
> +{
> +	struct pvrdma_dev *dev = to_vdev(ibqp->device);
> +	struct pvrdma_qp *qp = to_vqp(ibqp);
> +	union pvrdma_cmd_req req;
> +	union pvrdma_cmd_resp rsp;
> +	struct pvrdma_cmd_modify_qp *cmd = &req.modify_qp;
> +	int cur_state, next_state;
> +	int ret;
> +
> +	/* Sanity checking. Should need lock here */
> +	mutex_lock(&qp->mutex);
> +	cur_state = (attr_mask & IB_QP_CUR_STATE) ? attr->cur_qp_state :
> +		qp->state;
> +	next_state = (attr_mask & IB_QP_STATE) ? attr->qp_state : cur_state;
> +
> +	if (!ib_modify_qp_is_ok(cur_state, next_state, ibqp->qp_type,
> +				attr_mask, IB_LINK_LAYER_ETHERNET)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (attr_mask & IB_QP_PORT) {
> +		if (attr->port_num == 0 ||
> +		    attr->port_num > ibqp->device->phys_port_cnt) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
> +	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
> +		if (attr->min_rnr_timer > 31) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
> +	if (attr_mask & IB_QP_PKEY_INDEX) {
> +		if (attr->pkey_index >= dev->dsr->caps.max_pkeys) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
> +	if (attr_mask & IB_QP_QKEY)
> +		qp->qkey = attr->qkey;
> +
> +	if (cur_state == next_state && cur_state == IB_QPS_RESET) {
> +		ret = 0;
> +		goto out;
> +	}
> +
> +	qp->state = next_state;
> +	memset(cmd, 0, sizeof(*cmd));
> +	cmd->hdr.cmd = PVRDMA_CMD_MODIFY_QP;
> +	cmd->qp_handle = qp->qp_handle;
> +	cmd->attr_mask = ib_qp_attr_mask_to_pvrdma(attr_mask);
> +	cmd->attrs.qp_state = ib_qp_state_to_pvrdma(attr->qp_state);
> +	cmd->attrs.cur_qp_state =
> +		ib_qp_state_to_pvrdma(attr->cur_qp_state);
> +	cmd->attrs.path_mtu = ib_mtu_to_pvrdma(attr->path_mtu);
> +	cmd->attrs.path_mig_state =
> +		ib_mig_state_to_pvrdma(attr->path_mig_state);
> +	cmd->attrs.qkey = attr->qkey;
> +	cmd->attrs.rq_psn = attr->rq_psn;
> +	cmd->attrs.sq_psn = attr->sq_psn;
> +	cmd->attrs.dest_qp_num = attr->dest_qp_num;
> +	cmd->attrs.qp_access_flags =
> +		ib_access_flags_to_pvrdma(attr->qp_access_flags);
> +	cmd->attrs.pkey_index = attr->pkey_index;
> +	cmd->attrs.alt_pkey_index = attr->alt_pkey_index;
> +	cmd->attrs.en_sqd_async_notify = attr->en_sqd_async_notify;
> +	cmd->attrs.sq_draining = attr->sq_draining;
> +	cmd->attrs.max_rd_atomic = attr->max_rd_atomic;
> +	cmd->attrs.max_dest_rd_atomic = attr->max_dest_rd_atomic;
> +	cmd->attrs.min_rnr_timer = attr->min_rnr_timer;
> +	cmd->attrs.port_num = attr->port_num;
> +	cmd->attrs.timeout = attr->timeout;
> +	cmd->attrs.retry_cnt = attr->retry_cnt;
> +	cmd->attrs.rnr_retry = attr->rnr_retry;
> +	cmd->attrs.alt_port_num = attr->alt_port_num;
> +	cmd->attrs.alt_timeout = attr->alt_timeout;
> +	ib_qp_cap_to_pvrdma(&cmd->attrs.cap, &attr->cap);
> +	ib_ah_attr_to_pvrdma(&cmd->attrs.ah_attr, &attr->ah_attr);
> +	ib_ah_attr_to_pvrdma(&cmd->attrs.alt_ah_attr, &attr->alt_ah_attr);
> +
> +	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_MODIFY_QP_RESP);
> +	if (ret < 0) {
> +		dev_warn(&dev->pdev->dev,
> +			 "could not modify queuepair, error: %d\n", ret);
> +	} else if (rsp.hdr.err > 0) {
> +		dev_warn(&dev->pdev->dev,
> +			 "cannot modify queuepair, error: %d\n", rsp.hdr.err);
> +		ret = -EINVAL;
> +	}
> +
> +	if (ret == 0 && next_state == IB_QPS_RESET)
> +		pvrdma_reset_qp(qp);
> +
> +out:
> +	mutex_unlock(&qp->mutex);
> +
> +	return ret;
> +}
> +
> +static inline void *get_sq_wqe(struct pvrdma_qp *qp, int n)
> +{
> +	return pvrdma_page_dir_get_ptr(&qp->pdir,
> +				       qp->sq.offset + n * qp->sq.wqe_size);
> +}
> +
> +static inline void *get_rq_wqe(struct pvrdma_qp *qp, int n)
> +{
> +	return pvrdma_page_dir_get_ptr(&qp->pdir,
> +				       qp->rq.offset + n * qp->rq.wqe_size);
> +}
> +
> +static int set_reg_seg(struct pvrdma_sq_wqe_hdr *wqe_hdr, struct ib_reg_wr *wr)
> +{
> +	struct pvrdma_user_mr *mr = to_vmr(wr->mr);
> +
> +	wqe_hdr->wr.fast_reg.iova_start = mr->ibmr.iova;
> +	wqe_hdr->wr.fast_reg.pl_pdir_dma = mr->pdir.dir_dma;
> +	wqe_hdr->wr.fast_reg.page_shift = mr->page_shift;
> +	wqe_hdr->wr.fast_reg.page_list_len = mr->npages;
> +	wqe_hdr->wr.fast_reg.length = mr->ibmr.length;
> +	wqe_hdr->wr.fast_reg.access_flags = wr->access;
> +	wqe_hdr->wr.fast_reg.rkey = wr->key;
> +
> +	return pvrdma_page_dir_insert_page_list(&mr->pdir, mr->pages,
> +						mr->npages);
> +}
> +
> +/**
> + * pvrdma_post_send - post send work request entries on a QP
> + * @ibqp: the QP
> + * @wr: work request list to post
> + * @bad_wr: the first bad WR returned
> + *
> + * @return: 0 on success, otherwise errno returned.
> + */
> +int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
> +		     struct ib_send_wr **bad_wr)
> +{
> +	struct pvrdma_qp *qp = to_vqp(ibqp);
> +	struct pvrdma_dev *dev = to_vdev(ibqp->device);
> +	unsigned long flags;
> +	struct pvrdma_sq_wqe_hdr *wqe_hdr;
> +	struct pvrdma_sge *sge;
> +	int i, index;
> +	int nreq;
> +	int ret;
> +
> +	/*
> +	 * In states lower than RTS, we can fail immediately. In other states,
> +	 * just post and let the device figure it out.
> +	 */
> +	if (qp->state < IB_QPS_RTS) {
> +		*bad_wr = wr;
> +		return -EINVAL;
> +	}
> +
> +	spin_lock_irqsave(&qp->sq.lock, flags);
> +
> +	index = pvrdma_idx(&qp->sq.ring->prod_tail, qp->sq.wqe_cnt);

Not sure if it was discussed so posting "just in case".
I believe it is unlikely that index will go out of range but since
pvrdma_idx might return PVRDMA_INVALID_IDX i suggest to add a check here.
Something like:
	if (unlikely(index == PVRDMA_INVALID_IDX)) {
		*bad_wr = wr;
		return -EFAULT;
	}

Same goes with pvrdma_post_recv

> +	for (nreq = 0; wr; nreq++, wr = wr->next) {
> +		unsigned int tail;
> +
> +		if (unlikely(!pvrdma_idx_ring_has_space(
> +				qp->sq.ring, qp->sq.wqe_cnt, &tail))) {
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "send queue is full\n");
> +			*bad_wr = wr;
> +			ret = -ENOMEM;
> +			goto out;
> +		}
> +
> +		if (unlikely(wr->num_sge > qp->sq.max_sg || wr->num_sge < 0)) {
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "send SGE overflow\n");
> +			*bad_wr = wr;
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		if (unlikely(wr->opcode < 0)) {
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "invalid send opcode\n");
> +			*bad_wr = wr;
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		/*
> +		 * Only support UD, RC.
> +		 * Need to check opcode table for thorough checking.
> +		 * opcode		_UD	_UC	_RC
> +		 * _SEND		x	x	x
> +		 * _SEND_WITH_IMM	x	x	x
> +		 * _RDMA_WRITE			x	x
> +		 * _RDMA_WRITE_WITH_IMM		x	x
> +		 * _LOCAL_INV			x	x
> +		 * _SEND_WITH_INV		x	x
> +		 * _RDMA_READ				x
> +		 * _ATOMIC_CMP_AND_SWP			x
> +		 * _ATOMIC_FETCH_AND_ADD		x
> +		 * _MASK_ATOMIC_CMP_AND_SWP		x
> +		 * _MASK_ATOMIC_FETCH_AND_ADD		x
> +		 * _REG_MR				x
> +		 *
> +		 */
> +		if (qp->ibqp.qp_type != IB_QPT_UD &&
> +		    qp->ibqp.qp_type != IB_QPT_RC &&
> +			wr->opcode != IB_WR_SEND) {
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "unsupported queuepair type\n");
> +			*bad_wr = wr;
> +			ret = -EINVAL;
> +			goto out;
> +		} else if (qp->ibqp.qp_type == IB_QPT_UD ||
> +			   qp->ibqp.qp_type == IB_QPT_GSI) {
> +			if (wr->opcode != IB_WR_SEND &&
> +			    wr->opcode != IB_WR_SEND_WITH_IMM) {
> +				dev_warn_ratelimited(&dev->pdev->dev,
> +						     "invalid send opcode\n");
> +				*bad_wr = wr;
> +				ret = -EINVAL;
> +				goto out;
> +			}
> +		}
> +
> +		wqe_hdr = (struct pvrdma_sq_wqe_hdr *)get_sq_wqe(qp, index);
> +		memset(wqe_hdr, 0, sizeof(*wqe_hdr));
> +		wqe_hdr->wr_id = wr->wr_id;
> +		wqe_hdr->num_sge = wr->num_sge;
> +		wqe_hdr->opcode = ib_wr_opcode_to_pvrdma(wr->opcode);
> +		wqe_hdr->send_flags = ib_send_flags_to_pvrdma(wr->send_flags);
> +		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
> +		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
> +			wqe_hdr->ex.imm_data = wr->ex.imm_data;
> +
> +		switch (qp->ibqp.qp_type) {
> +		case IB_QPT_GSI:
> +		case IB_QPT_UD:
> +			if (unlikely(!ud_wr(wr)->ah)) {
> +				dev_warn_ratelimited(&dev->pdev->dev,
> +						     "invalid address handle\n");
> +				*bad_wr = wr;
> +				ret = -EINVAL;
> +				goto out;
> +			}
> +
> +			/*
> +			 * Use qkey from qp context if high order bit set,
> +			 * otherwise from work request.
> +			 */
> +			wqe_hdr->wr.ud.remote_qpn = ud_wr(wr)->remote_qpn;
> +			wqe_hdr->wr.ud.remote_qkey =
> +				ud_wr(wr)->remote_qkey & 0x80000000 ?
> +				qp->qkey : ud_wr(wr)->remote_qkey;
> +			wqe_hdr->wr.ud.av = to_vah(ud_wr(wr)->ah)->av;
> +
> +			break;
> +		case IB_QPT_RC:
> +			switch (wr->opcode) {
> +			case IB_WR_RDMA_READ:
> +			case IB_WR_RDMA_WRITE:
> +			case IB_WR_RDMA_WRITE_WITH_IMM:
> +				wqe_hdr->wr.rdma.remote_addr =
> +					rdma_wr(wr)->remote_addr;
> +				wqe_hdr->wr.rdma.rkey = rdma_wr(wr)->rkey;
> +				break;
> +			case IB_WR_LOCAL_INV:
> +			case IB_WR_SEND_WITH_INV:
> +				wqe_hdr->ex.invalidate_rkey =
> +					wr->ex.invalidate_rkey;
> +				break;
> +			case IB_WR_ATOMIC_CMP_AND_SWP:
> +			case IB_WR_ATOMIC_FETCH_AND_ADD:
> +				wqe_hdr->wr.atomic.remote_addr =
> +					atomic_wr(wr)->remote_addr;
> +				wqe_hdr->wr.atomic.rkey = atomic_wr(wr)->rkey;
> +				wqe_hdr->wr.atomic.compare_add =
> +					atomic_wr(wr)->compare_add;
> +				if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP)
> +					wqe_hdr->wr.atomic.swap =
> +						atomic_wr(wr)->swap;
> +				break;
> +			case IB_WR_REG_MR:
> +				ret = set_reg_seg(wqe_hdr, reg_wr(wr));
> +				if (ret < 0) {
> +					dev_warn_ratelimited(&dev->pdev->dev,
> +							     "Failed to set fast register work request\n");
> +					*bad_wr = wr;
> +					goto out;
> +				}
> +				break;
> +			default:
> +				break;
> +			}
> +
> +			break;
> +		default:
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "invalid queuepair type\n");
> +			ret = -EINVAL;
> +			*bad_wr = wr;
> +			goto out;
> +		}
> +
> +		sge = (struct pvrdma_sge *)(wqe_hdr + 1);
> +		for (i = 0; i < wr->num_sge; i++) {
> +			/* Need to check wqe_size 0 or max size */
> +			sge->addr = wr->sg_list[i].addr;
> +			sge->length = wr->sg_list[i].length;
> +			sge->lkey = wr->sg_list[i].lkey;
> +			sge++;
> +		}
> +
> +		/* Make sure wqe is written before index update */
> +		smp_wmb();
> +
> +		index++;
> +		if (unlikely(index >= qp->sq.wqe_cnt))
> +			index = 0;
> +		/* Update shared sq ring */
> +		pvrdma_idx_ring_inc(&qp->sq.ring->prod_tail,
> +				    qp->sq.wqe_cnt);
> +	}
> +
> +	ret = 0;
> +
> +out:
> +	spin_unlock_irqrestore(&qp->sq.lock, flags);
> +
> +	if (!ret)
> +		pvrdma_write_uar_qp(dev, PVRDMA_UAR_QP_SEND | qp->qp_handle);
> +
> +	return ret;
> +}
> +
> +/**
> + * pvrdma_post_receive - post receive work request entries on a QP
> + * @ibqp: the QP
> + * @wr: the work request list to post
> + * @bad_wr: the first bad WR returned
> + *
> + * @return: 0 on success, otherwise errno returned.
> + */
> +int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
> +		     struct ib_recv_wr **bad_wr)
> +{
> +	struct pvrdma_dev *dev = to_vdev(ibqp->device);
> +	unsigned long flags;
> +	struct pvrdma_qp *qp = to_vqp(ibqp);
> +	struct pvrdma_rq_wqe_hdr *wqe_hdr;
> +	struct pvrdma_sge *sge;
> +	int index, nreq;
> +	int ret = 0;
> +	int i;
> +
> +	/*
> +	 * In the RESET state, we can fail immediately. For other states,
> +	 * just post and let the device figure it out.
> +	 */
> +	if (qp->state == IB_QPS_RESET) {
> +		*bad_wr = wr;
> +		return -EINVAL;
> +	}
> +
> +	spin_lock_irqsave(&qp->rq.lock, flags);
> +
> +	index = pvrdma_idx(&qp->rq.ring->prod_tail, qp->rq.wqe_cnt);
> +	for (nreq = 0; wr; nreq++, wr = wr->next) {
> +		unsigned int tail;
> +
> +		if (unlikely(wr->num_sge > qp->rq.max_sg ||
> +			     wr->num_sge < 0)) {
> +			ret = -EINVAL;
> +			*bad_wr = wr;
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "recv SGE overflow\n");
> +			goto out;
> +		}
> +
> +		if (unlikely(!pvrdma_idx_ring_has_space(
> +				qp->rq.ring, qp->rq.wqe_cnt, &tail))) {
> +			ret = -ENOMEM;
> +			*bad_wr = wr;
> +			dev_warn_ratelimited(&dev->pdev->dev,
> +					     "recv queue full\n");
> +			goto out;
> +		}
> +
> +		wqe_hdr = (struct pvrdma_rq_wqe_hdr *)get_rq_wqe(qp, index);
> +		wqe_hdr->wr_id = wr->wr_id;
> +		wqe_hdr->num_sge = wr->num_sge;
> +		wqe_hdr->total_len = 0;
> +
> +		sge = (struct pvrdma_sge *)(wqe_hdr + 1);
> +		for (i = 0; i < wr->num_sge; i++) {
> +			sge->addr = wr->sg_list[i].addr;
> +			sge->length = wr->sg_list[i].length;
> +			sge->lkey = wr->sg_list[i].lkey;
> +			sge++;
> +		}
> +
> +		/* Make sure wqe is written before index update */
> +		smp_wmb();
> +
> +		index++;
> +		if (unlikely(index >= qp->rq.wqe_cnt))
> +			index = 0;
> +		/* Update shared rq ring */
> +		pvrdma_idx_ring_inc(&qp->rq.ring->prod_tail,
> +				    qp->rq.wqe_cnt);
> +	}
> +
> +	spin_unlock_irqrestore(&qp->rq.lock, flags);
> +
> +	pvrdma_write_uar_qp(dev, PVRDMA_UAR_QP_RECV | qp->qp_handle);
> +
> +	return ret;
> +
> +out:
> +	spin_unlock_irqrestore(&qp->rq.lock, flags);
> +
> +	return ret;
> +}
> +
> +/**
> + * pvrdma_query_qp - query a queue pair's attributes
> + * @ibqp: the queue pair to query
> + * @attr: the queue pair's attributes
> + * @attr_mask: attributes mask
> + * @init_attr: initial queue pair attributes
> + *
> + * @returns 0 on success, otherwise returns an errno.
> + */
> +int pvrdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
> +		    int attr_mask, struct ib_qp_init_attr *init_attr)
> +{
> +	struct pvrdma_dev *dev = to_vdev(ibqp->device);
> +	struct pvrdma_qp *qp = to_vqp(ibqp);
> +	union pvrdma_cmd_req req;
> +	union pvrdma_cmd_resp rsp;
> +	struct pvrdma_cmd_query_qp *cmd = &req.query_qp;
> +	struct pvrdma_cmd_query_qp_resp *resp = &rsp.query_qp_resp;
> +	int ret = 0;
> +
> +	mutex_lock(&qp->mutex);
> +
> +	if (qp->state == IB_QPS_RESET) {
> +		attr->qp_state = IB_QPS_RESET;
> +		goto out;
> +	}
> +
> +	memset(cmd, 0, sizeof(*cmd));
> +	cmd->hdr.cmd = PVRDMA_CMD_QUERY_QP;
> +	cmd->qp_handle = qp->qp_handle;
> +	cmd->attr_mask = ib_qp_attr_mask_to_pvrdma(attr_mask);
> +
> +	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_QUERY_QP_RESP);
> +	if (ret < 0) {
> +		dev_warn(&dev->pdev->dev,
> +			 "could not query queuepair, error: %d\n", ret);
> +		goto out;
> +	}
> +
> +	attr->qp_state = pvrdma_qp_state_to_ib(resp->attrs.qp_state);
> +	attr->cur_qp_state =
> +		pvrdma_qp_state_to_ib(resp->attrs.cur_qp_state);
> +	attr->path_mtu = pvrdma_mtu_to_ib(resp->attrs.path_mtu);
> +	attr->path_mig_state =
> +		pvrdma_mig_state_to_ib(resp->attrs.path_mig_state);
> +	attr->qkey = resp->attrs.qkey;
> +	attr->rq_psn = resp->attrs.rq_psn;
> +	attr->sq_psn = resp->attrs.sq_psn;
> +	attr->dest_qp_num = resp->attrs.dest_qp_num;
> +	attr->qp_access_flags =
> +		pvrdma_access_flags_to_ib(resp->attrs.qp_access_flags);
> +	attr->pkey_index = resp->attrs.pkey_index;
> +	attr->alt_pkey_index = resp->attrs.alt_pkey_index;
> +	attr->en_sqd_async_notify = resp->attrs.en_sqd_async_notify;
> +	attr->sq_draining = resp->attrs.sq_draining;
> +	attr->max_rd_atomic = resp->attrs.max_rd_atomic;
> +	attr->max_dest_rd_atomic = resp->attrs.max_dest_rd_atomic;
> +	attr->min_rnr_timer = resp->attrs.min_rnr_timer;
> +	attr->port_num = resp->attrs.port_num;
> +	attr->timeout = resp->attrs.timeout;
> +	attr->retry_cnt = resp->attrs.retry_cnt;
> +	attr->rnr_retry = resp->attrs.rnr_retry;
> +	attr->alt_port_num = resp->attrs.alt_port_num;
> +	attr->alt_timeout = resp->attrs.alt_timeout;
> +	pvrdma_qp_cap_to_ib(&attr->cap, &resp->attrs.cap);
> +	pvrdma_ah_attr_to_ib(&attr->ah_attr, &resp->attrs.ah_attr);
> +	pvrdma_ah_attr_to_ib(&attr->alt_ah_attr, &resp->attrs.alt_ah_attr);
> +
> +	qp->state = attr->qp_state;
> +
> +	ret = 0;
> +
> +out:
> +	attr->cur_qp_state = attr->qp_state;
> +
> +	init_attr->event_handler = qp->ibqp.event_handler;
> +	init_attr->qp_context = qp->ibqp.qp_context;
> +	init_attr->send_cq = qp->ibqp.send_cq;
> +	init_attr->recv_cq = qp->ibqp.recv_cq;
> +	init_attr->srq = qp->ibqp.srq;
> +	init_attr->xrcd = NULL;
> +	init_attr->cap = attr->cap;
> +	init_attr->sq_sig_type = 0;
> +	init_attr->qp_type = qp->ibqp.qp_type;
> +	init_attr->create_flags = 0;
> +	init_attr->port_num = qp->port;
> +
> +	mutex_unlock(&qp->mutex);
> +	return ret;
> +}
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [patch] alpha: silence a buffer overflow warning
From: Dan Carpenter @ 2016-11-14 11:34 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Ivan Kokshaysky, Matt Turner, linux-alpha, kernel-janitors

We check that "member" is in bounds for the first line, but we also use
it on the next line without checking which is a mistake.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 4811e54..7574377 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -1094,8 +1094,9 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
 	default: /* default to variation "0" for now */
 		break;
 	case ST_DEC_EB164:
-		if (member < ARRAY_SIZE(eb164_indices))
-			*variation_name = eb164_names[eb164_indices[member]];
+		if (member >= ARRAY_SIZE(eb164_indices))
+			break;
+		*variation_name = eb164_names[eb164_indices[member]];
 		/* PC164 may show as EB164 variation, but with EV56 CPU,
 		   so, since no true EB164 had anything but EV5... */
 		if (eb164_indices[member] == 0 && cpu == EV56_CPU)

^ permalink raw reply related

* [patch] alpha: silence a buffer overflow warning
From: Dan Carpenter @ 2016-11-14 11:34 UTC (permalink / raw)
  To: kernel-janitors

We check that "member" is in bounds for the first line, but we also use
it on the next line without checking which is a mistake.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 4811e54..7574377 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -1094,8 +1094,9 @@ get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
 	default: /* default to variation "0" for now */
 		break;
 	case ST_DEC_EB164:
-		if (member < ARRAY_SIZE(eb164_indices))
-			*variation_name = eb164_names[eb164_indices[member]];
+		if (member >= ARRAY_SIZE(eb164_indices))
+			break;
+		*variation_name = eb164_names[eb164_indices[member]];
 		/* PC164 may show as EB164 variation, but with EV56 CPU,
 		   so, since no true EB164 had anything but EV5... */
 		if (eb164_indices[member] = 0 && cpu = EV56_CPU)

^ permalink raw reply related

* Re: 答复: 答复: [PATCH] drm/amdgpu:impl vgt_flush for VI
From: Christian König @ 2016-11-14 11:33 UTC (permalink / raw)
  To: Liu, Monk, amd-gfx-CC+yJ3UmIYqDUpFQwHEjaQ@public.gmane.org
In-Reply-To: <DM5PR12MB1355412B041FD1D0B40E16FA84BC0-2J9CzHegvk+AJwmwFrlwrgdYzm3356FpvxpqHgZTriW3zl9H0oFU5g@public.gmane.org>

The callbacks are use case driven, so it doesn't matter what packets 
they use. I would really prefer not to add to many of them.

Maybe rename the emit_cntxcntl callback to just emit_context_preamble or 
something like this to make it more clear what that is good for.

Regards,
Christian.

Am 14.11.2016 um 11:01 schrieb Liu, Monk:
> Although the effect is equal, but cntxcntl uses CONTEXT_CONTROL only, while vgt-flush uses EVENT_WRITE on vgt_flush and vs_partial_flush only,
> And vgt flush only operate on tessellation category registers, I'd prefer it not mixed with CONTEXT_CONTROL package ...
> I think Put them together seems not grace ...
>
> BR Monk
>
> -----邮件原件-----
> 发件人: Christian König [mailto:deathsimple@vodafone.de]
> 发送时间: Monday, November 14, 2016 5:46 PM
> 收件人: Liu, Monk; amd-gfx@freedesktop.org
> 主题: Re: 答复: [PATCH] drm/amdgpu:impl vgt_flush for VI
>
> Am 14.11.2016 um 04:17 schrieb Liu, Monk:
>> Anyone review this patch ?
> Looks good in general, but is there any reason not to put it into the existing emit_cntxcntl callback?
>
> Regards,
> Christian.
>
>> This patch could fix tessellation bug when shadowing enabled, we
>> should always insert vgt_flush when there is a context switch
>>
>> BR Monk
>>
>> -----邮件原件-----
>> 发件人: Monk Liu [mailto:Monk.Liu@amd.com]
>> 发送时间: Friday, November 11, 2016 6:32 PM
>> 收件人: amd-gfx@freedesktop.org
>> 抄送: Liu, Monk
>> 主题: [PATCH] drm/amdgpu:impl vgt_flush for VI
>>
>> when hardware shadowing enabled, tesselation will trigger vm fault, the root cause is because VGT_FLUSH not introduced in kmd. this could fix tesselation crash issue.
>>
>> Change-Id: I77d87d93ce6580e559e734fb41d97ee8c59d245b
>> Signed-off-by: Monk Liu <Monk.Liu@amd.com>
>> ---
>>    drivers/gpu/drm/amd/amdgpu/amdgpu.h      |  1 +
>>    drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c   |  5 ++++-
>>    drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h |  1 +
>>    drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c    | 13 +++++++++++++
>>    4 files changed, 19 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> index 15015bc..f46e96b 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
>> @@ -1630,6 +1630,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring
>> *ring)  #define amdgpu_ring_emit_fence(r, addr, seq, flags)
>> (r)->funcs->emit_fence((r), (addr), (seq), (flags))  #define
>> amdgpu_ring_emit_gds_switch(r, v, db, ds, wb, ws, ab, as)
>> (r)->funcs->emit_gds_switch((r), (v), (db), (ds), (wb), (ws), (ab),
>> (as))  #define amdgpu_ring_emit_hdp_flush(r)
>> (r)->funcs->emit_hdp_flush((r))
>> +#define amdgpu_ring_emit_vgt_flush(r) (r)->funcs->emit_vgt_flush((r))
>>    #define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r))
>>    #define amdgpu_ring_emit_switch_buffer(r) (r)->funcs->emit_switch_buffer((r))
>>    #define amdgpu_ring_emit_cntxcntl(r, d)
>> (r)->funcs->emit_cntxcntl((r), (d)) diff --git
>> a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> index acf48de..c039890 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
>> @@ -175,11 +175,14 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
>>    	if (ring->funcs->emit_hdp_flush)
>>    		amdgpu_ring_emit_hdp_flush(ring);
>>    
>> +	need_ctx_switch = ring->current_ctx != fence_ctx;
>> +	if (ring->funcs->emit_vgt_flush && need_ctx_switch)
>> +		 amdgpu_ring_emit_vgt_flush(ring);
>> +
>>    	/* always set cond_exec_polling to CONTINUE */
>>    	*ring->cond_exe_cpu_addr = 1;
>>    
>>    	skip_preamble = ring->current_ctx == fence_ctx;
>> -	need_ctx_switch = ring->current_ctx != fence_ctx;
>>    	if (job && ring->funcs->emit_cntxcntl) {
>>    		if (need_ctx_switch)
>>    			status |= AMDGPU_HAVE_CTX_SWITCH; diff --git
>> a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> index 92bc89b..c3a7329 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
>> @@ -116,6 +116,7 @@ struct amdgpu_ring_funcs {
>>    	void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
>>    			      uint64_t pd_addr);
>>    	void (*emit_hdp_flush)(struct amdgpu_ring *ring);
>> +	void (*emit_vgt_flush)(struct amdgpu_ring *ring);
>>    	void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
>>    	void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
>>    				uint32_t gds_base, uint32_t gds_size, diff --git
>> a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> index 9017803..1d407d76 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
>> @@ -6187,6 +6187,18 @@ static void gfx_v8_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
>>    	amdgpu_ring_write(ring, 0x20); /* poll interval */  }
>>    
>> +static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring) {
>> +	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
>> +	amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
>> +		EVENT_INDEX(4));
>> +
>> +	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
>> +	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
>> +		EVENT_INDEX(0));
>> +}
>> +
>> +
>>    static void gfx_v8_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring)  {
>>    	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); @@ -6590,6 +6602,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
>>    	.pad_ib = amdgpu_ring_generic_pad_ib,
>>    	.emit_switch_buffer = gfx_v8_ring_emit_sb,
>>    	.emit_cntxcntl = gfx_v8_ring_emit_cntxcntl,
>> +	.emit_vgt_flush = gfx_v8_0_ring_emit_vgt_flush,
>>    };
>>    
>>    static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute =
>> {
>> --
>> 1.9.1
>>
>> _______________________________________________
>> amd-gfx mailing list
>> amd-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
>

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply

* Re: [PATCHv5 1/2] xenbus: fix deadlock on writes to /proc/xen/xenbus
From: Jan Beulich @ 2016-11-14 11:33 UTC (permalink / raw)
  To: David Vrabel; +Cc: Juergen Gross, xen-devel, Boris Ostrovsky
In-Reply-To: <1479121976-26568-2-git-send-email-david.vrabel@citrix.com>

>>> On 14.11.16 at 12:12, <david.vrabel@citrix.com> wrote:
> /proc/xen/xenbus does not work correctly.  A read blocked waiting for
> a xenstore message holds the mutex needed for atomic file position
> updates.  This blocks any writes on the same file handle, which can
> deadlock if the write is needed to unblock the read.
> 
> Clear FMODE_ATOMIC_POS when opening this device to always get
> character device like sematics.

Interesting. I'm pretty sure that back in March/April, when I had
to deal with this for our kernels, I was told the upstream kernel is
unaffected. In any event I continue to think that
https://patchwork.kernel.org/patch/8752901/
is the better (because more generic) solution here.

> --- a/drivers/xen/xenbus/xenbus_dev_frontend.c
> +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
> @@ -536,6 +536,8 @@ static int xenbus_file_open(struct inode *inode, struct file *filp)
>  	if (xen_store_evtchn == 0)
>  		return -ENOENT;
>  
> +	filp->f_mode &= ~FMODE_ATOMIC_POS; /* cdev-style semantics */
> +
>  	nonseekable_open(inode, filp);

In any event I think the adjustment should be placed after the call
to nonseekable_open(), despite it being unlikely that the function
might set the bit again.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply

* Re: [PATCH v3 12/14] drm/i915/scheduler: Support user-defined priorities
From: Tvrtko Ursulin @ 2016-11-14 11:32 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx
In-Reply-To: <20161114085703.16540-12-chris@chris-wilson.co.uk>


On 14/11/2016 08:57, Chris Wilson wrote:
> Use a priority stored in the context as the initial value when
> submitting a request. This allows us to change the default priority on a
> per-context basis, allowing different contexts to be favoured with GPU
> time at the expense of lower importance work. The user can adjust the
> context's priority via I915_CONTEXT_PARAM_PRIORITY, with more positive
> values being higher priority (they will be serviced earlier, after their
> dependencies have been resolved). Any prerequisite work for an execbuf
> will have its priority raised to match the new request as required.
>
> Normal users can specify any value in the range of -1023 to 0 [default],
> i.e. they can reduce the priority of their workloads (and temporarily
> boost it back to normal if so desired).
>
> Privileged users can specify any value in the range of -1023 to 1023,
> [default is 0], i.e. they can raise their priority above all overs and
> so potentially starve the system.
>
> Note that the existing schedulers are not fair, nor load balancing, the
> execution is strictly by priority on a first-come, first-served basis,
> and the driver may choose to boost some requests above the range
> available to users.
>
> This priority was originally based around nice(2), but evolved to allow
> clients to adjust their priority within a small range, and allow for a
> privileged high priority range.
>
> For example, this can be used to implement EGL_IMG_context_priority
> https://www.khronos.org/registry/egl/extensions/IMG/EGL_IMG_context_priority.txt
>
> 	EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
>         the context to be created. This attribute is a hint, as an
>         implementation may not support multiple contexts at some
>         priority levels and system policy may limit access to high
>         priority contexts to appropriate system privilege level. The
>         default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
>         EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
>
> so we can map
>
> 	PRIORITY_HIGH -> 1023 [privileged, will failback to 0]
> 	PRIORITY_MED -> 0 [default]
> 	PRIORITY_LOW -> -1023
>
> They also map onto the priorities used by VkQueue (and a VkQueue is
> essentially a timeline, our i915_gem_context under full-ppgtt).
>
> Testcase: igt/gem_exec_schedule
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> ---
>  drivers/gpu/drm/i915/i915_gem_context.c | 20 ++++++++++++++++++++
>  include/uapi/drm/i915_drm.h             |  3 +++
>  2 files changed, 23 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 1f94b8d6d83d..1f74ab266f6b 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -1101,6 +1101,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
>  	case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
>  		args->value = !!(ctx->flags & CONTEXT_NO_ERROR_CAPTURE);
>  		break;
> +	case I915_CONTEXT_PARAM_PRIORITY:
> +		args->value = ctx->priority;
> +		break;
>  	default:
>  		ret = -EINVAL;
>  		break;
> @@ -1156,6 +1159,23 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
>  				ctx->flags &= ~CONTEXT_NO_ERROR_CAPTURE;
>  		}
>  		break;
> +
> +	case I915_CONTEXT_PARAM_PRIORITY:
> +		{
> +			int priority = args->value;
> +
> +			if (args->size)
> +				ret = -EINVAL;
> +			else if (priority >= I915_PRIORITY_MAX ||
> +				 priority <= -I915_PRIORITY_MAX)
> +				ret = -EINVAL;
> +			else if (priority > 0 && !capable(CAP_SYS_ADMIN))
> +				ret = -EPERM;
> +			else
> +				ctx->priority = priority;
> +		}
> +		break;
> +
>  	default:
>  		ret = -EINVAL;
>  		break;
> diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
> index 1c12a350eca3..47901a8ad682 100644
> --- a/include/uapi/drm/i915_drm.h
> +++ b/include/uapi/drm/i915_drm.h
> @@ -391,6 +391,8 @@ typedef struct drm_i915_irq_wait {
>
>  /* Query whether DRM_I915_GEM_EXECBUFFER2 supports user defined execution
>   * priorities and the driver will attempt to execute batches in priority order.
> + * The initial priority for each batch is supplied by the context and is
> + * controlled via I915_CONTEXT_PARAM_PRIORITY.
>   */
>  #define I915_PARAM_HAS_SCHEDULER	 41
>
> @@ -1224,6 +1226,7 @@ struct drm_i915_gem_context_param {
>  #define I915_CONTEXT_PARAM_NO_ZEROMAP	0x2
>  #define I915_CONTEXT_PARAM_GTT_SIZE	0x3
>  #define I915_CONTEXT_PARAM_NO_ERROR_CAPTURE	0x4
> +#define I915_CONTEXT_PARAM_PRIORITY	0x5
>  	__u64 value;
>  };
>
>

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* Re: Why bluetoothd disconnect immediate follow connected event , what's wrong with my bluez ?
From: Luiz Augusto von Dentz @ 2016-11-14 11:32 UTC (permalink / raw)
  To: Trump DD; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <CABuKQijYU5Ndst=ZKjPcy0MEOrmocAgNE_BDppgYNf_L0iBmBw@mail.gmail.com>

Hi,

On Sun, Nov 13, 2016 at 11:48 AM, Trump DD <wrxzzj@gmail.com> wrote:
> Hi guys
>    I met a very strang issue about config Microsoft Designer Mouse
> (Bluetooth LE)
> I have paired and trust my devices already, and connected it success,
> all works fine.
> But after I reboot my computer,  when I click a mouse button, I see
> 'connected'  in bluetoothctl, immediate a 'disconnect' event follow.
> what's wrong with my bluetooth.
> below it's my log files
>
> bluetoothctl log:
> [NEW] Controller A4:34:D9:2B:2E:41 debian [default]
> [NEW] Device C0:11:5B:C2:55:DF Designer Mouse
> [CHG] Device C0:11:5B:C2:55:DF Connected: yes
> [CHG] Device C0:11:5B:C2:55:DF Connected: no
> [bluetooth]# info C0:11:5B:C2:55:DF
> Device C0:11:5B:C2:55:DF
>         Name: Designer Mouse
>         Alias: Designer Mouse
>         Appearance: 0x03c2
>         Icon: input-mouse
>         Paired: yes
>         Trusted: yes
>         Blocked: no
>         Connected: no
>         LegacyPairing: no
>         UUID: Generic Access Profile    (00001800-0000-1000-8000-00805f9b34fb)
>         UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb)
>         UUID: Device Information        (0000180a-0000-1000-8000-00805f9b34fb)
>         UUID: Battery Service           (0000180f-0000-1000-8000-00805f9b34fb)
>         UUID: Human Interface Device    (00001812-0000-1000-8000-00805f9b34fb)
>         Modalias: usb:v045Ep0805d0110
> [bluetooth]#
>
>
> bluetoothd log after I click mouse button:
>
> bluetoothd[552]: src/adapter.c:connected_callback() hci0 device
> C0:11:5B:C2:55:DF connected eir_len 27
> bluetoothd[552]: src/adapter.c:disconnected_callback() reason = 2
> bluetoothd[552]: src/adapter.c:dev_disconnected() Device
> C0:11:5B:C2:55:DF disconnected, reason 2
> bluetoothd[552]: src/adapter.c:adapter_remove_connection()
> bluetoothd[552]: src/adapter.c:bonding_attempt_complete() hci0 bdaddr
> C0:11:5B:C2:55:DF type 2 status 0xe
> bluetoothd[552]: src/device.c:device_bonding_complete() bonding (nil)
> status 0x0e
> bluetoothd[552]: src/device.c:device_bonding_failed() status 14
> bluetoothd[552]: src/adapter.c:resume_discovery()

Looks like there is a regression with latest git, please check with
the patch Ive just sent:

[PATCH BlueZ] core/adapter: Fix using wrong address type to listen ATT


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [patch] mmc: mmc_test: Uninitialized return value
From: Dan Carpenter @ 2016-11-14 11:31 UTC (permalink / raw)
  To: Ulf Hansson, Per Forlin
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, linux-mmc,
	linux-kernel, kernel-janitors

We never set "ret" to RESULT_OK.

Fixes: 9f9c4180f88d ("mmc: mmc_test: add test for non-blocking transfers")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index f61c812..5ba6d77 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -832,7 +832,7 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
 	struct mmc_async_req *other_areq = &test_areq[1].areq;
 	enum mmc_blk_status status;
 	int i;
-	int ret;
+	int ret = RESULT_OK;
 
 	test_areq[0].test = test;
 	test_areq[1].test = test;

^ permalink raw reply related

* [patch] mmc: mmc_test: Uninitialized return value
From: Dan Carpenter @ 2016-11-14 11:31 UTC (permalink / raw)
  To: Ulf Hansson, Per Forlin
  Cc: Adrian Hunter, Linus Walleij, Wolfram Sang, linux-mmc,
	linux-kernel, kernel-janitors

We never set "ret" to RESULT_OK.

Fixes: 9f9c4180f88d ("mmc: mmc_test: add test for non-blocking transfers")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index f61c812..5ba6d77 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -832,7 +832,7 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
 	struct mmc_async_req *other_areq = &test_areq[1].areq;
 	enum mmc_blk_status status;
 	int i;
-	int ret;
+	int ret = RESULT_OK;
 
 	test_areq[0].test = test;
 	test_areq[1].test = test;

^ permalink raw reply related

* Re: [PATCH v3 11/14] HACK drm/i915/scheduler: emulate a scheduler for guc
From: Tvrtko Ursulin @ 2016-11-14 11:31 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx
In-Reply-To: <20161114085703.16540-11-chris@chris-wilson.co.uk>


On 14/11/2016 08:57, Chris Wilson wrote:
> This emulates execlists on top of the GuC in order to defer submission of
> requests to the hardware. This deferral allows time for high priority
> requests to gazump their way to the head of the queue, however it nerfs
> the GuC by converting it back into a simple execlist (where the CPU has
> to wake up after every request to feed new commands into the GuC).

Don't know what to do with this one. It feels like it should be a 
separate patch so it can be performance evaluated properly?

It is also not clear to me why we don't need any similar limiting for 
the execlists request merging?

Regards,

Tvrtko

> ---
>  drivers/gpu/drm/i915/i915_guc_submission.c | 85 +++++++++++++++++++++++++-----
>  drivers/gpu/drm/i915/i915_irq.c            |  4 +-
>  drivers/gpu/drm/i915/intel_lrc.c           |  3 --
>  3 files changed, 76 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
> index 4462112725ef..088f5a99ecfc 100644
> --- a/drivers/gpu/drm/i915/i915_guc_submission.c
> +++ b/drivers/gpu/drm/i915/i915_guc_submission.c
> @@ -469,7 +469,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
>  	u32 freespace;
>  	int ret;
>
> -	spin_lock(&gc->wq_lock);
> +	spin_lock_irq(&gc->wq_lock);
>  	freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
>  	freespace -= gc->wq_rsvd;
>  	if (likely(freespace >= wqi_size)) {
> @@ -479,7 +479,7 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request)
>  		gc->no_wq_space++;
>  		ret = -EAGAIN;
>  	}
> -	spin_unlock(&gc->wq_lock);
> +	spin_unlock_irq(&gc->wq_lock);
>
>  	return ret;
>  }
> @@ -491,9 +491,9 @@ void i915_guc_wq_unreserve(struct drm_i915_gem_request *request)
>
>  	GEM_BUG_ON(READ_ONCE(gc->wq_rsvd) < wqi_size);
>
> -	spin_lock(&gc->wq_lock);
> +	spin_lock_irq(&gc->wq_lock);
>  	gc->wq_rsvd -= wqi_size;
> -	spin_unlock(&gc->wq_lock);
> +	spin_unlock_irq(&gc->wq_lock);
>  }
>
>  /* Construct a Work Item and append it to the GuC's Work Queue */
> @@ -644,7 +644,7 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq)
>  	rq->previous_context = engine->last_context;
>  	engine->last_context = rq->ctx;
>
> -	i915_gem_request_submit(rq);
> +	__i915_gem_request_submit(rq);
>
>  	spin_lock(&client->wq_lock);
>  	guc_wq_item_append(client, rq);
> @@ -665,6 +665,70 @@ static void i915_guc_submit(struct drm_i915_gem_request *rq)
>  	spin_unlock(&client->wq_lock);
>  }
>
> +static bool i915_guc_dequeue(struct intel_engine_cs *engine)
> +{
> +	struct execlist_port *port = engine->execlist_port;
> +	struct drm_i915_gem_request *last = port[0].request;
> +	unsigned long flags;
> +	struct rb_node *rb;
> +	bool submit = false;
> +
> +	spin_lock_irqsave(&engine->timeline->lock, flags);
> +	rb = engine->execlist_first;
> +	while (rb) {
> +		struct drm_i915_gem_request *cursor =
> +			rb_entry(rb, typeof(*cursor), priotree.node);
> +
> +		if (last && cursor->ctx != last->ctx) {
> +			if (port != engine->execlist_port)
> +				break;
> +
> +			i915_gem_request_assign(&port->request, last);
> +			dma_fence_enable_sw_signaling(&last->fence);
> +			port++;
> +		}
> +
> +		rb = rb_next(rb);
> +		rb_erase(&cursor->priotree.node, &engine->execlist_queue);
> +		RB_CLEAR_NODE(&cursor->priotree.node);
> +		cursor->priotree.priority = INT_MAX;
> +
> +		i915_guc_submit(cursor);
> +		last = cursor;
> +		submit = true;
> +	}
> +	if (submit) {
> +		i915_gem_request_assign(&port->request, last);
> +		dma_fence_enable_sw_signaling(&last->fence);
> +		engine->execlist_first = rb;
> +	}
> +	spin_unlock_irqrestore(&engine->timeline->lock, flags);
> +
> +	return submit;
> +}
> +
> +static void i915_guc_irq_handler(unsigned long data)
> +{
> +	struct intel_engine_cs *engine = (struct intel_engine_cs *)data;
> +	struct execlist_port *port = engine->execlist_port;
> +	struct drm_i915_gem_request *rq;
> +	bool submit;
> +
> +	do {
> +		rq = port[0].request;
> +		while (rq && i915_gem_request_completed(rq)) {
> +			i915_gem_request_put(rq);
> +			rq = port[1].request;
> +			port[0].request = rq;
> +			port[1].request = NULL;
> +		}
> +
> +		submit = false;
> +		if (!port[1].request)
> +			submit = i915_guc_dequeue(engine);
> +	} while (submit);
> +}
> +
>  /*
>   * Everything below here is concerned with setup & teardown, and is
>   * therefore not part of the somewhat time-critical batch-submission
> @@ -1531,16 +1595,13 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
>
>  	/* Take over from manual control of ELSP (execlists) */
>  	for_each_engine(engine, dev_priv, id) {
> -		engine->submit_request = i915_guc_submit;
> -		engine->schedule = NULL;
> +		tasklet_init(&engine->irq_tasklet,
> +			     i915_guc_irq_handler,
> +			     (unsigned long)engine);
>
>  		/* Replay the current set of previously submitted requests */
> -		list_for_each_entry(request,
> -				    &engine->timeline->requests, link) {
> +		list_for_each_entry(request, &engine->timeline->requests, link)
>  			client->wq_rsvd += sizeof(struct guc_wq_item);
> -			if (i915_sw_fence_done(&request->submit))
> -				i915_guc_submit(request);
> -		}
>  	}
>
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index cb8a75f6ca16..18dce4c66d56 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -1341,8 +1341,10 @@ static void snb_gt_irq_handler(struct drm_i915_private *dev_priv,
>  static __always_inline void
>  gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
>  {
> -	if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
> +	if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) {
> +		tasklet_schedule(&engine->irq_tasklet);
>  		notify_ring(engine);
> +	}
>  	if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
>  		tasklet_schedule(&engine->irq_tasklet);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> index d13a335ad83a..ffab255e55a7 100644
> --- a/drivers/gpu/drm/i915/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/intel_lrc.c
> @@ -1425,9 +1425,6 @@ static void reset_common_ring(struct intel_engine_cs *engine,
>  	request->ring->last_retired_head = -1;
>  	intel_ring_update_space(request->ring);
>
> -	if (i915.enable_guc_submission)
> -		return;
> -
>  	/* Catch up with any missed context-switch interrupts */
>  	I915_WRITE(RING_CONTEXT_STATUS_PTR(engine), _MASKED_FIELD(0xffff, 0));
>  	if (request->ctx != port[0].request->ctx) {
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply

* [U-Boot] [PATCH 6/7] scripts: sunxi: Build an raw SPL image
From: Hans de Goede @ 2016-11-14 11:30 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <c6a15b2c-e463-c167-79a0-552871e0d882@redhat.com>

Hi,

On 14-11-16 12:19, Hans de Goede wrote:
> Hi,
>
> On 08-11-16 17:21, Maxime Ripard wrote:
>> Introduce a new sunxi-spl-with-ecc.bin image with already the right header,
>> ECC, randomizer and padding for the BROM to be able to read it.
>>
>> It needs to be flashed using a raw access to the NAND so that the
>> controller doesn't change a thing to it, since we already have all the
>> right parameters.
>>
>> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Looks good to me:
>
> Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Scrap that, this causes all sunxi boars to fail to build:

+--page is missing
+sunxi-nand-image-builder 2016.11-rc3-00069-gabe4d57
+Usage: sunxi-nand-image-builder [OPTIONS] source-image output-image
+Creates a raw NAND image that can be read by the sunxi NAND controller.
+-h               --help               Display this help and exit
+-c <str>/<step>  --ecc=<str>/<step>   ECC config (strength/step-size)
+-p <size>        --page=<size>        Page size
+-o <size>        --oob=<size>         OOB size
+-u <size>        --usable=<size>      Usable page size
+-e <size>        --eraseblock=<size>  Erase block size
+-b               --boot0              Build a boot0 image.
+-s               --scramble           Scramble data
+  Valid ECC strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64
+  Valid ECC step size: 512 and 1024
+If you are building a boot0 image, you'll have specify extra options.
+These options should be chosen based on the layouts described here:
+  http://linux-sunxi.org/NAND#More_information_on_BROM_NAND
+  --usable should be assigned the 'Hardware page' value
+  --ecc should be assigned the 'ECC capacity'/'ECC page' values
+  --usable should be smaller than --page
+The --address option is only required for non-boot0 images that are
+meant to be programmed at a non eraseblock aligned offset.
+Examples:
+  The H27UCG8T2BTR-BC NAND exposes
+  * 16k pages
+  * 1280 OOB bytes per page
+  * 4M eraseblocks
+  * requires data scrambling
+  * expects a minimum ECC of 40bits/1024bytes
+  A normal image can be generated with
+    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -c 40/1024
+  A boot0 image can be generated with
+    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -b -u 4096 -c 64/1024
+make[2]: *** [spl/sunxi-spl-with-ecc.bin] Error 255
+make[1]: *** [spl/u-boot-spl] Error 2

I've dropped this patch.


Regards,

Hans


>
> Regards,
>
> Hans
>
>
>
>> ---
>>  Makefile             |  3 +++
>>  scripts/Makefile.spl | 12 ++++++++++++
>>  2 files changed, 15 insertions(+), 0 deletions(-)
>>
>> diff --git a/Makefile b/Makefile
>> index 37cbcb28f75e..12a248e297b5 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -1345,6 +1345,9 @@ spl/u-boot-spl: tools prepare \
>>  spl/sunxi-spl.bin: spl/u-boot-spl
>>      @:
>>
>> +spl/sunxi-spl-with-ecc.bin: spl/sunxi-spl.bin
>> +    @:
>> +
>>  spl/u-boot-spl.sfp: spl/u-boot-spl
>>      @:
>>
>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
>> index e0b0117dc9b6..b41b4e427cc5 100644
>> --- a/scripts/Makefile.spl
>> +++ b/scripts/Makefile.spl
>> @@ -168,6 +168,7 @@ endif
>>
>>  ifdef CONFIG_ARCH_SUNXI
>>  ALL-y    += $(obj)/sunxi-spl.bin
>> +ALL-y    += $(obj)/sunxi-spl-with-ecc.bin
>>  endif
>>
>>  ifeq ($(CONFIG_SYS_SOC),"at91")
>> @@ -276,6 +277,17 @@ cmd_mksunxiboot = $(objtree)/tools/mksunxiboot $< $@
>>  $(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin FORCE
>>      $(call if_changed,mksunxiboot)
>>
>> +quiet_cmd_sunxi_spl_image_builder = SUNXI_SPL_IMAGE_BUILDER $@
>> +cmd_sunxi_spl_image_builder = $(objtree)/tools/sunxi-spl-image-builder \
>> +                -c $(CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH)/$(CONFIG_NAND_SUNXI_SPL_ECC_SIZE) \
>> +                -p $(CONFIG_SYS_NAND_PAGE_SIZE) \
>> +                -o $(CONFIG_SYS_NAND_OOBSIZE) \
>> +                -u $(CONFIG_NAND_SUNXI_SPL_USABLE_PAGE_SIZE) \
>> +                -e $(CONFIG_SYS_NAND_BLOCK_SIZE) \
>> +                -s -b $< $@
>> +$(obj)/sunxi-spl-with-ecc.bin: $(obj)/sunxi-spl.bin
>> +    $(call if_changed,sunxi_spl_image_builder)
>> +
>>  # Rule to link u-boot-spl
>>  # May be overridden by arch/$(ARCH)/config.mk
>>  quiet_cmd_u-boot-spl ?= LD      $@
>>

^ permalink raw reply

* Re: [PATCH] Fix loading of module radeonfb on PowerMac
From: Tomi Valkeinen @ 2016-11-14 11:30 UTC (permalink / raw)
  To: Mathieu Malaterre, linux-fbdev
  Cc: Lennart Sorensen, Jean-Christophe Plagniol-Villard,
	Benjamin Herrenschmidt, linuxppc-dev
In-Reply-To: <1475928540-19647-1-git-send-email-malat@debian.org>


[-- Attachment #1.1: Type: text/plain, Size: 1258 bytes --]

On 08/10/16 15:09, Mathieu Malaterre wrote:
> When the linux kernel is build with (typical kernel ship with Debian
> installer):
> 
> CONFIG_FB_OF=y
> CONFIG_VT_HW_CONSOLE_BINDING=y
> CONFIG_FB_RADEON=m
> 
> The offb driver takes precedence over module radeonfb. It is then
> impossible to load the module, error reported is:
> 
> [   96.551486] radeonfb 0000:00:10.0: enabling device (0006 -> 0007)
> [   96.551526] radeonfb 0000:00:10.0: BAR 0: can't reserve [mem 0x98000000-0x9fffffff pref]
> [   96.551531] radeonfb (0000:00:10.0): cannot request region 0.
> [   96.551545] radeonfb: probe of 0000:00:10.0 failed with error -16
> 
> This patch reproduce the behavior of the module radeon, so as to make it
> possible to load radeonfb when offb is first loaded.
> 
> It should be noticed that `offb_destroy` is never called which explain the
> need to skip error detection on the radeon side.
> 
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> Link: https://bugs.debian.org/826629#57
> Suggested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
> ---
>  drivers/video/fbdev/aty/radeon_base.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)

Thanks, queued for 4.9 fixes.

 Tomi


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH 1/3] cpufreq: schedutil: enable fast switch earlier
From: Viresh Kumar @ 2016-11-14 11:30 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Rafael Wysocki, Ingo Molnar, Peter Zijlstra, Lists linaro-kernel,
	Linux PM, Linux Kernel Mailing List, Vincent Guittot, Juri Lelli,
	Robin Randhawa
In-Reply-To: <20161114040622.GA29087@vireshk-i7>

On 14-11-16, 09:36, Viresh Kumar wrote:
> On 13-11-16, 15:46, Rafael J. Wysocki wrote:
> > That's only going to happen in the next patch, though, right?  It
> > wouldn't hurt to write that in the changelog too.
> 
> Sure.
> 
> > Besides, I'm not actually sure if starting/stopping the kthread in
> > sugov_policy_alloc/free() is a good idea.  It sort of conflates the
> > allocation of memory with kthread creation.  Any chance to untangle
> > that?
> 
> Hmm, so either I can create two new routines for the thread and call
> them along with alloc/free. Or I can rename the alloc/free routines
> and keep this patch as is.

I have created separate routines in my new version (which I will send
tomorrow).

-- 
viresh

^ permalink raw reply

* [PATCH BlueZ] core/adapter: Fix using wrong address type to listen ATT
From: Luiz Augusto von Dentz @ 2016-11-14 11:30 UTC (permalink / raw)
  To: linux-bluetooth

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

bdaddr_type shall only matter for controllers supporting LE otherwise
it may cause BDADDR_BREDR to be used for things like LE ATT socket
listen breaking reconnections.
---
 src/adapter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index b81b4e8..b134709 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -8085,7 +8085,7 @@ static void read_info_complete(uint8_t status, uint16_t length,
 		}
 	} else {
 		bacpy(&adapter->bdaddr, &rp->bdaddr);
-		if (adapter->supported_settings & MGMT_SETTING_BREDR)
+		if (!(adapter->supported_settings & MGMT_SETTING_LE))
 			adapter->bdaddr_type = BDADDR_BREDR;
 		else
 			adapter->bdaddr_type = BDADDR_LE_PUBLIC;
-- 
2.7.4


^ permalink raw reply related

* Re: [PATCH] Fix loading of module radeonfb on PowerMac
From: Tomi Valkeinen @ 2016-11-14 11:30 UTC (permalink / raw)
  To: Mathieu Malaterre, linux-fbdev
  Cc: Lennart Sorensen, Jean-Christophe Plagniol-Villard,
	Benjamin Herrenschmidt, linuxppc-dev
In-Reply-To: <1475928540-19647-1-git-send-email-malat@debian.org>


[-- Attachment #1.1: Type: text/plain, Size: 1258 bytes --]

On 08/10/16 15:09, Mathieu Malaterre wrote:
> When the linux kernel is build with (typical kernel ship with Debian
> installer):
> 
> CONFIG_FB_OF=y
> CONFIG_VT_HW_CONSOLE_BINDING=y
> CONFIG_FB_RADEON=m
> 
> The offb driver takes precedence over module radeonfb. It is then
> impossible to load the module, error reported is:
> 
> [   96.551486] radeonfb 0000:00:10.0: enabling device (0006 -> 0007)
> [   96.551526] radeonfb 0000:00:10.0: BAR 0: can't reserve [mem 0x98000000-0x9fffffff pref]
> [   96.551531] radeonfb (0000:00:10.0): cannot request region 0.
> [   96.551545] radeonfb: probe of 0000:00:10.0 failed with error -16
> 
> This patch reproduce the behavior of the module radeon, so as to make it
> possible to load radeonfb when offb is first loaded.
> 
> It should be noticed that `offb_destroy` is never called which explain the
> need to skip error detection on the radeon side.
> 
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> Link: https://bugs.debian.org/826629#57
> Suggested-by: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
> ---
>  drivers/video/fbdev/aty/radeon_base.c | 22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)

Thanks, queued for 4.9 fixes.

 Tomi


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* [Buildroot] [PATCH 2/2] package/netsniff-ng: allow to build with musl
From: Tobias Klauser @ 2016-11-14 11:29 UTC (permalink / raw)
  To: buildroot
In-Reply-To: <20161114112948.13292-1-tklauser@distanz.ch>

netsniff-ng allows build with musl since version 0.5.8. With libnet now
being able to build with musl, let's enable musl for netsniff-ng as
well.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
 package/netsniff-ng/Config.in | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/package/netsniff-ng/Config.in b/package/netsniff-ng/Config.in
index e52bb25f0acd..dca016469736 100644
--- a/package/netsniff-ng/Config.in
+++ b/package/netsniff-ng/Config.in
@@ -7,8 +7,7 @@ config BR2_PACKAGE_NETSNIFF_NG
 	select BR2_PACKAGE_LIBURCU
 	select BR2_PACKAGE_LIBNET
 	# Build with uClibc fails due to missing ceill()
-	# Build with musl fails due to various header issues
-	depends on BR2_TOOLCHAIN_USES_GLIBC
+	depends on !BR2_TOOLCHAIN_USES_UCLIBC
 	depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_0
 	depends on BR2_TOOLCHAIN_HAS_THREADS
 	depends on BR2_PACKAGE_LIBURCU_ARCH_SUPPORTS
-- 
2.11.0.rc0.7.gbe5a750

^ permalink raw reply related

* [Buildroot] [PATCH 1/2] package/libnet: fix compilation with musl
From: Tobias Klauser @ 2016-11-14 11:29 UTC (permalink / raw)
  To: buildroot
In-Reply-To: <20161114112948.13292-1-tklauser@distanz.ch>

Patch taken from from upstream:
https://github.com/sam-github/libnet/commit/ffd7fab744a9ad2893169a8fb6244074604d5d0d

Adjusted the file paths manually so the patch applies to the packaged
libnet sources.

Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
---
 package/libnet/0001-support-musl-libc.patch | 50 +++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 package/libnet/0001-support-musl-libc.patch

diff --git a/package/libnet/0001-support-musl-libc.patch b/package/libnet/0001-support-musl-libc.patch
new file mode 100644
index 000000000000..0704157bb57e
--- /dev/null
+++ b/package/libnet/0001-support-musl-libc.patch
@@ -0,0 +1,50 @@
+From ffd7fab744a9ad2893169a8fb6244074604d5d0d Mon Sep 17 00:00:00 2001
+From: rofl0r <retnyg@gmx.net>
+Date: Tue, 12 Aug 2014 21:51:39 +0200
+Subject: [PATCH] Support musl libc, remove support for glibc < 2.1
+
+The workarounds for glibc < 2.1 (was released february 1999) break the
+build with musl libc.
+
+It is very unlikely that 2.0 or earlier is still in use, and if so,
+1) that's a big security hole
+2) code wouldnt compile anyway since noone tested build in the last decade
+3) user of it wouldn't expect anyway to get bleeding edge sw built on it,
+   so he would just use the latest version that works for him.
+
+Closes #52
+---
+ libnet/src/libnet_link_linux.c | 11 -----------
+ 1 file changed, 11 deletions(-)
+
+diff --git a/libnet/src/libnet_link_linux.c b/libnet/src/libnet_link_linux.c
+index 054458d..3c6df3c 100644
+--- a/src/libnet_link_linux.c
++++ b/src/libnet_link_linux.c
+@@ -30,26 +30,15 @@
+ #include <sys/time.h>
+ 
+ #include <net/if.h>
+-#if (__GLIBC__)
+ #include <netinet/if_ether.h>
+ #include <net/if_arp.h>
+-#else
+-#include <linux/if_arp.h>
+-#include <linux/if_ether.h>
+-#endif
+ 
+ #if (HAVE_PACKET_SOCKET)
+ #ifndef SOL_PACKET
+ #define SOL_PACKET 263
+ #endif  /* SOL_PACKET */
+-#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
+ #include <netpacket/packet.h>
+ #include <net/ethernet.h>     /* the L2 protocols */
+-#else
+-#include <asm/types.h>
+-#include <linux/if_packet.h>
+-#include <linux/if_ether.h>   /* The L2 protocols */
+-#endif
+ #endif  /* HAVE_PACKET_SOCKET */
+ 
+ #include "../include/libnet.h"
-- 
2.11.0.rc0.7.gbe5a750

^ permalink raw reply related

* [Buildroot] [PATCH 0/2] musl support for libnet and netsniff-ng
From: Tobias Klauser @ 2016-11-14 11:29 UTC (permalink / raw)
  To: buildroot

netsniff-ng can be build with musl since version 0.5.8, however it depends
on libnet which currently fails to build with musl. This series fixes libnet
build with musl by adding the corresponding upstream patch and then enabling
the netsniff-ng with musl as well.

Tobias Klauser (2):
  package/libnet: fix compilation with musl
  package/netsniff-ng: allow to build with musl

 package/libnet/0001-support-musl-libc.patch | 50 +++++++++++++++++++++++++++++
 package/netsniff-ng/Config.in               |  3 +-
 2 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 package/libnet/0001-support-musl-libc.patch

-- 
2.11.0.rc0.7.gbe5a750

^ permalink raw reply

* [PATCH] drm/i915: Don't touch NULL sg on i915_gem_object_get_pages_gtt() error
From: Chris Wilson @ 2016-11-14 11:29 UTC (permalink / raw)
  To: intel-gfx; +Cc: Chris Wilson, Imre Deak, stable
In-Reply-To: <20161114111455.GA13441@mwanda>

On the DMA mapping error path, sg may be NULL (it has already been
marked as the last scatterlist entry), and we should avoid dereferencing
it again.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: e227330223a7 ("drm/i915: avoid leaking DMA mappings")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Imre Deak <imre.deak@intel.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/i915/i915_gem.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 888d7f79f36d..7c57ba9ed2ea 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2383,7 +2383,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 			page = shmem_read_mapping_page(mapping, i);
 			if (IS_ERR(page)) {
 				ret = PTR_ERR(page);
-				goto err_pages;
+				goto err_sg;
 			}
 		}
 		if (!i ||
@@ -2417,8 +2417,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 
 	return st;
 
-err_pages:
+err_sg:
 	sg_mark_end(sg);
+err_pages:
 	for_each_sgt_page(page, sgt_iter, st) {
 		set_page_private(page, 0);
 		put_page(page);
-- 
2.10.2


^ permalink raw reply related

* [PATCH] drm/i915: Don't touch NULL sg on i915_gem_object_get_pages_gtt() error
From: Chris Wilson @ 2016-11-14 11:29 UTC (permalink / raw)
  To: intel-gfx; +Cc: stable
In-Reply-To: <20161114111455.GA13441@mwanda>

On the DMA mapping error path, sg may be NULL (it has already been
marked as the last scatterlist entry), and we should avoid dereferencing
it again.

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: e227330223a7 ("drm/i915: avoid leaking DMA mappings")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Imre Deak <imre.deak@intel.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/i915/i915_gem.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 888d7f79f36d..7c57ba9ed2ea 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2383,7 +2383,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 			page = shmem_read_mapping_page(mapping, i);
 			if (IS_ERR(page)) {
 				ret = PTR_ERR(page);
-				goto err_pages;
+				goto err_sg;
 			}
 		}
 		if (!i ||
@@ -2417,8 +2417,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 
 	return st;
 
-err_pages:
+err_sg:
 	sg_mark_end(sg);
+err_pages:
 	for_each_sgt_page(page, sgt_iter, st) {
 		set_page_private(page, 0);
 		put_page(page);
-- 
2.10.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related

* [U-Boot] [PATCH 4/7] tools: sunxi: Add spl image builder
From: Hans de Goede @ 2016-11-14 11:29 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <1ebeef04-9b99-9fdc-a0c7-18c3585cc806@redhat.com>

Hi,

On 14-11-16 12:18, Hans de Goede wrote:
> Hi,
>
> On 08-11-16 17:21, Maxime Ripard wrote:
>> This program generates raw SPL images that can be flashed on the NAND with
>> the ECC and randomizer properly set up.
>>
>> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>
> Looks good to me:
>
> Reviewed-by: Hans de Goede <hdegoede@redhat.com>

Note this causes a cpu_to_be32 redefine compiler warning
I've fixed this up locally.

Regards,

Hans


>
> Regards,
>
> Hans
>
>
>
>> ---
>>  tools/.gitignore                |    1 +-
>>  tools/Makefile                  |    1 +-
>>  tools/sunxi-spl-image-builder.c | 1113 ++++++++++++++++++++++++++++++++-
>>  3 files changed, 1115 insertions(+), 0 deletions(-)
>>  create mode 100644 tools/sunxi-spl-image-builder.c
>>
>> diff --git a/tools/.gitignore b/tools/.gitignore
>> index cb1e722d4575..16574467544c 100644
>> --- a/tools/.gitignore
>> +++ b/tools/.gitignore
>> @@ -15,6 +15,7 @@
>>  /mkexynosspl
>>  /mxsboot
>>  /mksunxiboot
>> +/sunxi-spl-image-builder
>>  /ncb
>>  /proftool
>>  /relocate-rela
>> diff --git a/tools/Makefile b/tools/Makefile
>> index 400588cf0f5c..dfeeb23484ce 100644
>> --- a/tools/Makefile
>> +++ b/tools/Makefile
>> @@ -171,6 +171,7 @@ hostprogs-$(CONFIG_MX28) += mxsboot
>>  HOSTCFLAGS_mxsboot.o := -pedantic
>>
>>  hostprogs-$(CONFIG_ARCH_SUNXI) += mksunxiboot
>> +hostprogs-$(CONFIG_ARCH_SUNXI) += sunxi-spl-image-builder
>>
>>  hostprogs-$(CONFIG_NETCONSOLE) += ncb
>>  hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1
>> diff --git a/tools/sunxi-spl-image-builder.c b/tools/sunxi-spl-image-builder.c
>> new file mode 100644
>> index 000000000000..0f915eb2bdf5
>> --- /dev/null
>> +++ b/tools/sunxi-spl-image-builder.c
>> @@ -0,0 +1,1113 @@
>> +/*
>> + * Generic binary BCH encoding/decoding library
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License version 2 as published by
>> + * the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful, but WITHOUT
>> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> + * more details.
>> + *
>> + * You should have received a copy of the GNU General Public License along with
>> + * this program; if not, write to the Free Software Foundation, Inc., 51
>> + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
>> + *
>> + * For the BCH implementation:
>> + *
>> + * Copyright ? 2011 Parrot S.A.
>> + *
>> + * Author: Ivan Djelic <ivan.djelic@parrot.com>
>> + *
>> + * See also:
>> + * http://lxr.free-electrons.com/source/lib/bch.c
>> + *
>> + * For the randomizer and image builder implementation:
>> + *
>> + * Copyright ? 2016 NextThing Co.
>> + * Copyright ? 2016 Free Electrons
>> + *
>> + * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
>> + *
>> + */
>> +
>> +#include <stdint.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <stdio.h>
>> +#include <linux/kernel.h>
>> +#include <linux/errno.h>
>> +#include <asm/byteorder.h>
>> +#include <endian.h>
>> +#include <getopt.h>
>> +#include <version.h>
>> +
>> +#if defined(CONFIG_BCH_CONST_PARAMS)
>> +#define GF_M(_p)               (CONFIG_BCH_CONST_M)
>> +#define GF_T(_p)               (CONFIG_BCH_CONST_T)
>> +#define GF_N(_p)               ((1 << (CONFIG_BCH_CONST_M))-1)
>> +#else
>> +#define GF_M(_p)               ((_p)->m)
>> +#define GF_T(_p)               ((_p)->t)
>> +#define GF_N(_p)               ((_p)->n)
>> +#endif
>> +
>> +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
>> +
>> +#define BCH_ECC_WORDS(_p)      DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
>> +#define BCH_ECC_BYTES(_p)      DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
>> +
>> +#ifndef dbg
>> +#define dbg(_fmt, args...)     do {} while (0)
>> +#endif
>> +
>> +#define cpu_to_be32 htobe32
>> +#define kfree free
>> +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
>> +
>> +#define BCH_PRIMITIVE_POLY    0x5803
>> +
>> +struct image_info {
>> +    int ecc_strength;
>> +    int ecc_step_size;
>> +    int page_size;
>> +    int oob_size;
>> +    int usable_page_size;
>> +    int eraseblock_size;
>> +    int scramble;
>> +    int boot0;
>> +    off_t offset;
>> +    const char *source;
>> +    const char *dest;
>> +};
>> +
>> +/**
>> + * struct bch_control - BCH control structure
>> + * @m:          Galois field order
>> + * @n:          maximum codeword size in bits (= 2^m-1)
>> + * @t:          error correction capability in bits
>> + * @ecc_bits:   ecc exact size in bits, i.e. generator polynomial degree (<=m*t)
>> + * @ecc_bytes:  ecc max size (m*t bits) in bytes
>> + * @a_pow_tab:  Galois field GF(2^m) exponentiation lookup table
>> + * @a_log_tab:  Galois field GF(2^m) log lookup table
>> + * @mod8_tab:   remainder generator polynomial lookup tables
>> + * @ecc_buf:    ecc parity words buffer
>> + * @ecc_buf2:   ecc parity words buffer
>> + * @xi_tab:     GF(2^m) base for solving degree 2 polynomial roots
>> + * @syn:        syndrome buffer
>> + * @cache:      log-based polynomial representation buffer
>> + * @elp:        error locator polynomial
>> + * @poly_2t:    temporary polynomials of degree 2t
>> + */
>> +struct bch_control {
>> +    unsigned int    m;
>> +    unsigned int    n;
>> +    unsigned int    t;
>> +    unsigned int    ecc_bits;
>> +    unsigned int    ecc_bytes;
>> +/* private: */
>> +    uint16_t       *a_pow_tab;
>> +    uint16_t       *a_log_tab;
>> +    uint32_t       *mod8_tab;
>> +    uint32_t       *ecc_buf;
>> +    uint32_t       *ecc_buf2;
>> +    unsigned int   *xi_tab;
>> +    unsigned int   *syn;
>> +    int            *cache;
>> +    struct gf_poly *elp;
>> +    struct gf_poly *poly_2t[4];
>> +};
>> +
>> +static int fls(int x)
>> +{
>> +    int r = 32;
>> +
>> +    if (!x)
>> +        return 0;
>> +    if (!(x & 0xffff0000u)) {
>> +        x <<= 16;
>> +        r -= 16;
>> +    }
>> +    if (!(x & 0xff000000u)) {
>> +        x <<= 8;
>> +        r -= 8;
>> +    }
>> +    if (!(x & 0xf0000000u)) {
>> +        x <<= 4;
>> +        r -= 4;
>> +    }
>> +    if (!(x & 0xc0000000u)) {
>> +        x <<= 2;
>> +        r -= 2;
>> +    }
>> +    if (!(x & 0x80000000u)) {
>> +        x <<= 1;
>> +        r -= 1;
>> +    }
>> +    return r;
>> +}
>> +
>> +/*
>> + * represent a polynomial over GF(2^m)
>> + */
>> +struct gf_poly {
>> +    unsigned int deg;    /* polynomial degree */
>> +    unsigned int c[0];   /* polynomial terms */
>> +};
>> +
>> +/* given its degree, compute a polynomial size in bytes */
>> +#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int))
>> +
>> +/* polynomial of degree 1 */
>> +struct gf_poly_deg1 {
>> +    struct gf_poly poly;
>> +    unsigned int   c[2];
>> +};
>> +
>> +/*
>> + * same as encode_bch(), but process input data one byte at a time
>> + */
>> +static void encode_bch_unaligned(struct bch_control *bch,
>> +                 const unsigned char *data, unsigned int len,
>> +                 uint32_t *ecc)
>> +{
>> +    int i;
>> +    const uint32_t *p;
>> +    const int l = BCH_ECC_WORDS(bch)-1;
>> +
>> +    while (len--) {
>> +        p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff);
>> +
>> +        for (i = 0; i < l; i++)
>> +            ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++);
>> +
>> +        ecc[l] = (ecc[l] << 8)^(*p);
>> +    }
>> +}
>> +
>> +/*
>> + * convert ecc bytes to aligned, zero-padded 32-bit ecc words
>> + */
>> +static void load_ecc8(struct bch_control *bch, uint32_t *dst,
>> +              const uint8_t *src)
>> +{
>> +    uint8_t pad[4] = {0, 0, 0, 0};
>> +    unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
>> +
>> +    for (i = 0; i < nwords; i++, src += 4)
>> +        dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3];
>> +
>> +    memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords);
>> +    dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3];
>> +}
>> +
>> +/*
>> + * convert 32-bit ecc words to ecc bytes
>> + */
>> +static void store_ecc8(struct bch_control *bch, uint8_t *dst,
>> +               const uint32_t *src)
>> +{
>> +    uint8_t pad[4];
>> +    unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
>> +
>> +    for (i = 0; i < nwords; i++) {
>> +        *dst++ = (src[i] >> 24);
>> +        *dst++ = (src[i] >> 16) & 0xff;
>> +        *dst++ = (src[i] >>  8) & 0xff;
>> +        *dst++ = (src[i] >>  0) & 0xff;
>> +    }
>> +    pad[0] = (src[nwords] >> 24);
>> +    pad[1] = (src[nwords] >> 16) & 0xff;
>> +    pad[2] = (src[nwords] >>  8) & 0xff;
>> +    pad[3] = (src[nwords] >>  0) & 0xff;
>> +    memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords);
>> +}
>> +
>> +/**
>> + * encode_bch - calculate BCH ecc parity of data
>> + * @bch:   BCH control structure
>> + * @data:  data to encode
>> + * @len:   data length in bytes
>> + * @ecc:   ecc parity data, must be initialized by caller
>> + *
>> + * The @ecc parity array is used both as input and output parameter, in order to
>> + * allow incremental computations. It should be of the size indicated by member
>> + * @ecc_bytes of @bch, and should be initialized to 0 before the first call.
>> + *
>> + * The exact number of computed ecc parity bits is given by member @ecc_bits of
>> + * @bch; it may be less than m*t for large values of t.
>> + */
>> +static void encode_bch(struct bch_control *bch, const uint8_t *data,
>> +        unsigned int len, uint8_t *ecc)
>> +{
>> +    const unsigned int l = BCH_ECC_WORDS(bch)-1;
>> +    unsigned int i, mlen;
>> +    unsigned long m;
>> +    uint32_t w, r[l+1];
>> +    const uint32_t * const tab0 = bch->mod8_tab;
>> +    const uint32_t * const tab1 = tab0 + 256*(l+1);
>> +    const uint32_t * const tab2 = tab1 + 256*(l+1);
>> +    const uint32_t * const tab3 = tab2 + 256*(l+1);
>> +    const uint32_t *pdata, *p0, *p1, *p2, *p3;
>> +
>> +    if (ecc) {
>> +        /* load ecc parity bytes into internal 32-bit buffer */
>> +        load_ecc8(bch, bch->ecc_buf, ecc);
>> +    } else {
>> +        memset(bch->ecc_buf, 0, sizeof(r));
>> +    }
>> +
>> +    /* process first unaligned data bytes */
>> +    m = ((uintptr_t)data) & 3;
>> +    if (m) {
>> +        mlen = (len < (4-m)) ? len : 4-m;
>> +        encode_bch_unaligned(bch, data, mlen, bch->ecc_buf);
>> +        data += mlen;
>> +        len  -= mlen;
>> +    }
>> +
>> +    /* process 32-bit aligned data words */
>> +    pdata = (uint32_t *)data;
>> +    mlen  = len/4;
>> +    data += 4*mlen;
>> +    len  -= 4*mlen;
>> +    memcpy(r, bch->ecc_buf, sizeof(r));
>> +
>> +    /*
>> +     * split each 32-bit word into 4 polynomials of weight 8 as follows:
>> +     *
>> +     * 31 ...24  23 ...16  15 ... 8  7 ... 0
>> +     * xxxxxxxx  yyyyyyyy  zzzzzzzz  tttttttt
>> +     *                               tttttttt  mod g = r0 (precomputed)
>> +     *                     zzzzzzzz  00000000  mod g = r1 (precomputed)
>> +     *           yyyyyyyy  00000000  00000000  mod g = r2 (precomputed)
>> +     * xxxxxxxx  00000000  00000000  00000000  mod g = r3 (precomputed)
>> +     * xxxxxxxx  yyyyyyyy  zzzzzzzz  tttttttt  mod g = r0^r1^r2^r3
>> +     */
>> +    while (mlen--) {
>> +        /* input data is read in big-endian format */
>> +        w = r[0]^cpu_to_be32(*pdata++);
>> +        p0 = tab0 + (l+1)*((w >>  0) & 0xff);
>> +        p1 = tab1 + (l+1)*((w >>  8) & 0xff);
>> +        p2 = tab2 + (l+1)*((w >> 16) & 0xff);
>> +        p3 = tab3 + (l+1)*((w >> 24) & 0xff);
>> +
>> +        for (i = 0; i < l; i++)
>> +            r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i];
>> +
>> +        r[l] = p0[l]^p1[l]^p2[l]^p3[l];
>> +    }
>> +    memcpy(bch->ecc_buf, r, sizeof(r));
>> +
>> +    /* process last unaligned bytes */
>> +    if (len)
>> +        encode_bch_unaligned(bch, data, len, bch->ecc_buf);
>> +
>> +    /* store ecc parity bytes into original parity buffer */
>> +    if (ecc)
>> +        store_ecc8(bch, ecc, bch->ecc_buf);
>> +}
>> +
>> +static inline int modulo(struct bch_control *bch, unsigned int v)
>> +{
>> +    const unsigned int n = GF_N(bch);
>> +    while (v >= n) {
>> +        v -= n;
>> +        v = (v & n) + (v >> GF_M(bch));
>> +    }
>> +    return v;
>> +}
>> +
>> +/*
>> + * shorter and faster modulo function, only works when v < 2N.
>> + */
>> +static inline int mod_s(struct bch_control *bch, unsigned int v)
>> +{
>> +    const unsigned int n = GF_N(bch);
>> +    return (v < n) ? v : v-n;
>> +}
>> +
>> +static inline int deg(unsigned int poly)
>> +{
>> +    /* polynomial degree is the most-significant bit index */
>> +    return fls(poly)-1;
>> +}
>> +
>> +/* Galois field basic operations: multiply, divide, inverse, etc. */
>> +
>> +static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
>> +                  unsigned int b)
>> +{
>> +    return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
>> +                           bch->a_log_tab[b])] : 0;
>> +}
>> +
>> +static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a)
>> +{
>> +    return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0;
>> +}
>> +
>> +static inline unsigned int a_pow(struct bch_control *bch, int i)
>> +{
>> +    return bch->a_pow_tab[modulo(bch, i)];
>> +}
>> +
>> +static inline int a_log(struct bch_control *bch, unsigned int x)
>> +{
>> +    return bch->a_log_tab[x];
>> +}
>> +
>> +/*
>> + * generate Galois field lookup tables
>> + */
>> +static int build_gf_tables(struct bch_control *bch, unsigned int poly)
>> +{
>> +    unsigned int i, x = 1;
>> +    const unsigned int k = 1 << deg(poly);
>> +
>> +    /* primitive polynomial must be of degree m */
>> +    if (k != (1u << GF_M(bch)))
>> +        return -1;
>> +
>> +    for (i = 0; i < GF_N(bch); i++) {
>> +        bch->a_pow_tab[i] = x;
>> +        bch->a_log_tab[x] = i;
>> +        if (i && (x == 1))
>> +            /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
>> +            return -1;
>> +        x <<= 1;
>> +        if (x & k)
>> +            x ^= poly;
>> +    }
>> +    bch->a_pow_tab[GF_N(bch)] = 1;
>> +    bch->a_log_tab[0] = 0;
>> +
>> +    return 0;
>> +}
>> +
>> +/*
>> + * compute generator polynomial remainder tables for fast encoding
>> + */
>> +static void build_mod8_tables(struct bch_control *bch, const uint32_t *g)
>> +{
>> +    int i, j, b, d;
>> +    uint32_t data, hi, lo, *tab;
>> +    const int l = BCH_ECC_WORDS(bch);
>> +    const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32);
>> +    const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32);
>> +
>> +    memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab));
>> +
>> +    for (i = 0; i < 256; i++) {
>> +        /* p(X)=i is a small polynomial of weight <= 8 */
>> +        for (b = 0; b < 4; b++) {
>> +            /* we want to compute (p(X).X^(8*b+deg(g))) mod g(X) */
>> +            tab = bch->mod8_tab + (b*256+i)*l;
>> +            data = i << (8*b);
>> +            while (data) {
>> +                d = deg(data);
>> +                /* subtract X^d.g(X) from p(X).X^(8*b+deg(g)) */
>> +                data ^= g[0] >> (31-d);
>> +                for (j = 0; j < ecclen; j++) {
>> +                    hi = (d < 31) ? g[j] << (d+1) : 0;
>> +                    lo = (j+1 < plen) ?
>> +                        g[j+1] >> (31-d) : 0;
>> +                    tab[j] ^= hi|lo;
>> +                }
>> +            }
>> +        }
>> +    }
>> +}
>> +
>> +/*
>> + * build a base for factoring degree 2 polynomials
>> + */
>> +static int build_deg2_base(struct bch_control *bch)
>> +{
>> +    const int m = GF_M(bch);
>> +    int i, j, r;
>> +    unsigned int sum, x, y, remaining, ak = 0, xi[m];
>> +
>> +    /* find k s.t. Tr(a^k) = 1 and 0 <= k < m */
>> +    for (i = 0; i < m; i++) {
>> +        for (j = 0, sum = 0; j < m; j++)
>> +            sum ^= a_pow(bch, i*(1 << j));
>> +
>> +        if (sum) {
>> +            ak = bch->a_pow_tab[i];
>> +            break;
>> +        }
>> +    }
>> +    /* find xi, i=0..m-1 such that xi^2+xi = a^i+Tr(a^i).a^k */
>> +    remaining = m;
>> +    memset(xi, 0, sizeof(xi));
>> +
>> +    for (x = 0; (x <= GF_N(bch)) && remaining; x++) {
>> +        y = gf_sqr(bch, x)^x;
>> +        for (i = 0; i < 2; i++) {
>> +            r = a_log(bch, y);
>> +            if (y && (r < m) && !xi[r]) {
>> +                bch->xi_tab[r] = x;
>> +                xi[r] = 1;
>> +                remaining--;
>> +                dbg("x%d = %x\n", r, x);
>> +                break;
>> +            }
>> +            y ^= ak;
>> +        }
>> +    }
>> +    /* should not happen but check anyway */
>> +    return remaining ? -1 : 0;
>> +}
>> +
>> +static void *bch_alloc(size_t size, int *err)
>> +{
>> +    void *ptr;
>> +
>> +    ptr = malloc(size);
>> +    if (ptr == NULL)
>> +        *err = 1;
>> +    return ptr;
>> +}
>> +
>> +/*
>> + * compute generator polynomial for given (m,t) parameters.
>> + */
>> +static uint32_t *compute_generator_polynomial(struct bch_control *bch)
>> +{
>> +    const unsigned int m = GF_M(bch);
>> +    const unsigned int t = GF_T(bch);
>> +    int n, err = 0;
>> +    unsigned int i, j, nbits, r, word, *roots;
>> +    struct gf_poly *g;
>> +    uint32_t *genpoly;
>> +
>> +    g = bch_alloc(GF_POLY_SZ(m*t), &err);
>> +    roots = bch_alloc((bch->n+1)*sizeof(*roots), &err);
>> +    genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err);
>> +
>> +    if (err) {
>> +        kfree(genpoly);
>> +        genpoly = NULL;
>> +        goto finish;
>> +    }
>> +
>> +    /* enumerate all roots of g(X) */
>> +    memset(roots , 0, (bch->n+1)*sizeof(*roots));
>> +    for (i = 0; i < t; i++) {
>> +        for (j = 0, r = 2*i+1; j < m; j++) {
>> +            roots[r] = 1;
>> +            r = mod_s(bch, 2*r);
>> +        }
>> +    }
>> +    /* build generator polynomial g(X) */
>> +    g->deg = 0;
>> +    g->c[0] = 1;
>> +    for (i = 0; i < GF_N(bch); i++) {
>> +        if (roots[i]) {
>> +            /* multiply g(X) by (X+root) */
>> +            r = bch->a_pow_tab[i];
>> +            g->c[g->deg+1] = 1;
>> +            for (j = g->deg; j > 0; j--)
>> +                g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1];
>> +
>> +            g->c[0] = gf_mul(bch, g->c[0], r);
>> +            g->deg++;
>> +        }
>> +    }
>> +    /* store left-justified binary representation of g(X) */
>> +    n = g->deg+1;
>> +    i = 0;
>> +
>> +    while (n > 0) {
>> +        nbits = (n > 32) ? 32 : n;
>> +        for (j = 0, word = 0; j < nbits; j++) {
>> +            if (g->c[n-1-j])
>> +                word |= 1u << (31-j);
>> +        }
>> +        genpoly[i++] = word;
>> +        n -= nbits;
>> +    }
>> +    bch->ecc_bits = g->deg;
>> +
>> +finish:
>> +    kfree(g);
>> +    kfree(roots);
>> +
>> +    return genpoly;
>> +}
>> +
>> +/**
>> + *  free_bch - free the BCH control structure
>> + *  @bch:    BCH control structure to release
>> + */
>> +static void free_bch(struct bch_control *bch)
>> +{
>> +    unsigned int i;
>> +
>> +    if (bch) {
>> +        kfree(bch->a_pow_tab);
>> +        kfree(bch->a_log_tab);
>> +        kfree(bch->mod8_tab);
>> +        kfree(bch->ecc_buf);
>> +        kfree(bch->ecc_buf2);
>> +        kfree(bch->xi_tab);
>> +        kfree(bch->syn);
>> +        kfree(bch->cache);
>> +        kfree(bch->elp);
>> +
>> +        for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
>> +            kfree(bch->poly_2t[i]);
>> +
>> +        kfree(bch);
>> +    }
>> +}
>> +
>> +/**
>> + * init_bch - initialize a BCH encoder/decoder
>> + * @m:          Galois field order, should be in the range 5-15
>> + * @t:          maximum error correction capability, in bits
>> + * @prim_poly:  user-provided primitive polynomial (or 0 to use default)
>> + *
>> + * Returns:
>> + *  a newly allocated BCH control structure if successful, NULL otherwise
>> + *
>> + * This initialization can take some time, as lookup tables are built for fast
>> + * encoding/decoding; make sure not to call this function from a time critical
>> + * path. Usually, init_bch() should be called on module/driver init and
>> + * free_bch() should be called to release memory on exit.
>> + *
>> + * You may provide your own primitive polynomial of degree @m in argument
>> + * @prim_poly, or let init_bch() use its default polynomial.
>> + *
>> + * Once init_bch() has successfully returned a pointer to a newly allocated
>> + * BCH control structure, ecc length in bytes is given by member @ecc_bytes of
>> + * the structure.
>> + */
>> +static struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
>> +{
>> +    int err = 0;
>> +    unsigned int i, words;
>> +    uint32_t *genpoly;
>> +    struct bch_control *bch = NULL;
>> +
>> +    const int min_m = 5;
>> +    const int max_m = 15;
>> +
>> +    /* default primitive polynomials */
>> +    static const unsigned int prim_poly_tab[] = {
>> +        0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b,
>> +        0x402b, 0x8003,
>> +    };
>> +
>> +#if defined(CONFIG_BCH_CONST_PARAMS)
>> +    if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) {
>> +        printk(KERN_ERR "bch encoder/decoder was configured to support "
>> +               "parameters m=%d, t=%d only!\n",
>> +               CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T);
>> +        goto fail;
>> +    }
>> +#endif
>> +    if ((m < min_m) || (m > max_m))
>> +        /*
>> +         * values of m greater than 15 are not currently supported;
>> +         * supporting m > 15 would require changing table base type
>> +         * (uint16_t) and a small patch in matrix transposition
>> +         */
>> +        goto fail;
>> +
>> +    /* sanity checks */
>> +    if ((t < 1) || (m*t >= ((1 << m)-1)))
>> +        /* invalid t value */
>> +        goto fail;
>> +
>> +    /* select a primitive polynomial for generating GF(2^m) */
>> +    if (prim_poly == 0)
>> +        prim_poly = prim_poly_tab[m-min_m];
>> +
>> +    bch = malloc(sizeof(*bch));
>> +    if (bch == NULL)
>> +        goto fail;
>> +
>> +    memset(bch, 0, sizeof(*bch));
>> +
>> +    bch->m = m;
>> +    bch->t = t;
>> +    bch->n = (1 << m)-1;
>> +    words  = DIV_ROUND_UP(m*t, 32);
>> +    bch->ecc_bytes = DIV_ROUND_UP(m*t, 8);
>> +    bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err);
>> +    bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err);
>> +    bch->mod8_tab  = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err);
>> +    bch->ecc_buf   = bch_alloc(words*sizeof(*bch->ecc_buf), &err);
>> +    bch->ecc_buf2  = bch_alloc(words*sizeof(*bch->ecc_buf2), &err);
>> +    bch->xi_tab    = bch_alloc(m*sizeof(*bch->xi_tab), &err);
>> +    bch->syn       = bch_alloc(2*t*sizeof(*bch->syn), &err);
>> +    bch->cache     = bch_alloc(2*t*sizeof(*bch->cache), &err);
>> +    bch->elp       = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err);
>> +
>> +    for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
>> +        bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err);
>> +
>> +    if (err)
>> +        goto fail;
>> +
>> +    err = build_gf_tables(bch, prim_poly);
>> +    if (err)
>> +        goto fail;
>> +
>> +    /* use generator polynomial for computing encoding tables */
>> +    genpoly = compute_generator_polynomial(bch);
>> +    if (genpoly == NULL)
>> +        goto fail;
>> +
>> +    build_mod8_tables(bch, genpoly);
>> +    kfree(genpoly);
>> +
>> +    err = build_deg2_base(bch);
>> +    if (err)
>> +        goto fail;
>> +
>> +    return bch;
>> +
>> +fail:
>> +    free_bch(bch);
>> +    return NULL;
>> +}
>> +
>> +static void swap_bits(uint8_t *buf, int len)
>> +{
>> +    int i, j;
>> +
>> +    for (j = 0; j < len; j++) {
>> +        uint8_t byte = buf[j];
>> +
>> +        buf[j] = 0;
>> +        for (i = 0; i < 8; i++) {
>> +            if (byte & (1 << i))
>> +                buf[j] |= (1 << (7 - i));
>> +        }
>> +    }
>> +}
>> +
>> +static uint16_t lfsr_step(uint16_t state, int count)
>> +{
>> +    state &= 0x7fff;
>> +    while (count--)
>> +        state = ((state >> 1) |
>> +             ((((state >> 0) ^ (state >> 1)) & 1) << 14)) & 0x7fff;
>> +
>> +    return state;
>> +}
>> +
>> +static uint16_t default_scrambler_seeds[] = {
>> +    0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
>> +    0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
>> +    0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
>> +    0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
>> +    0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
>> +    0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
>> +    0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
>> +    0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
>> +    0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
>> +    0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
>> +    0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
>> +    0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
>> +    0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
>> +    0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
>> +    0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
>> +    0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
>> +};
>> +
>> +static uint16_t brom_scrambler_seeds[] = { 0x4a80 };
>> +
>> +static void scramble(const struct image_info *info,
>> +             int page, uint8_t *data, int datalen)
>> +{
>> +    uint16_t state;
>> +    int i;
>> +
>> +    /* Boot0 is always scrambled no matter the command line option. */
>> +    if (info->boot0) {
>> +        state = brom_scrambler_seeds[0];
>> +    } else {
>> +        unsigned seedmod = info->eraseblock_size / info->page_size;
>> +
>> +        /* Bail out earlier if the user didn't ask for scrambling. */
>> +        if (!info->scramble)
>> +            return;
>> +
>> +        if (seedmod > ARRAY_SIZE(default_scrambler_seeds))
>> +            seedmod = ARRAY_SIZE(default_scrambler_seeds);
>> +
>> +        state = default_scrambler_seeds[page % seedmod];
>> +    }
>> +
>> +    /* Prepare the initial state... */
>> +    state = lfsr_step(state, 15);
>> +
>> +    /* and start scrambling data. */
>> +    for (i = 0; i < datalen; i++) {
>> +        data[i] ^= state;
>> +        state = lfsr_step(state, 8);
>> +    }
>> +}
>> +
>> +static int write_page(const struct image_info *info, uint8_t *buffer,
>> +              FILE *src, FILE *rnd, FILE *dst,
>> +              struct bch_control *bch, int page)
>> +{
>> +    int steps = info->usable_page_size / info->ecc_step_size;
>> +    int eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8);
>> +    off_t pos = ftell(dst);
>> +    size_t pad, cnt;
>> +    int i;
>> +
>> +    if (eccbytes % 2)
>> +        eccbytes++;
>> +
>> +    memset(buffer, 0xff, info->page_size + info->oob_size);
>> +    cnt = fread(buffer, 1, info->usable_page_size, src);
>> +    if (!cnt) {
>> +        if (!feof(src)) {
>> +            fprintf(stderr,
>> +                "Failed to read data from the source\n");
>> +            return -1;
>> +        } else {
>> +            return 0;
>> +        }
>> +    }
>> +
>> +    fwrite(buffer, info->page_size + info->oob_size, 1, dst);
>> +
>> +    for (i = 0; i < info->usable_page_size; i++) {
>> +        if (buffer[i] !=  0xff)
>> +            break;
>> +    }
>> +
>> +    /* We leave empty pages at 0xff. */
>> +    if (i == info->usable_page_size)
>> +        return 0;
>> +
>> +    /* Restore the source pointer to read it again. */
>> +    fseek(src, -cnt, SEEK_CUR);
>> +
>> +    /* Randomize unused space if scrambling is required. */
>> +    if (info->scramble) {
>> +        int offs;
>> +
>> +        if (info->boot0) {
>> +            offs = steps * (info->ecc_step_size + eccbytes + 4);
>> +            cnt = info->page_size + info->oob_size - offs;
>> +            fread(buffer + offs, 1, cnt, rnd);
>> +        } else {
>> +            offs = info->page_size + (steps * (eccbytes + 4));
>> +            cnt = info->page_size + info->oob_size - offs;
>> +            memset(buffer + offs, 0xff, cnt);
>> +            scramble(info, page, buffer + offs, cnt);
>> +        }
>> +        fseek(dst, pos + offs, SEEK_SET);
>> +        fwrite(buffer + offs, cnt, 1, dst);
>> +    }
>> +
>> +    for (i = 0; i < steps; i++) {
>> +        int ecc_offs, data_offs;
>> +        uint8_t *ecc;
>> +
>> +        memset(buffer, 0xff, info->ecc_step_size + eccbytes + 4);
>> +        ecc = buffer + info->ecc_step_size + 4;
>> +        if (info->boot0) {
>> +            data_offs = i * (info->ecc_step_size + eccbytes + 4);
>> +            ecc_offs = data_offs + info->ecc_step_size + 4;
>> +        } else {
>> +            data_offs = i * info->ecc_step_size;
>> +            ecc_offs = info->page_size + 4 + (i * (eccbytes + 4));
>> +        }
>> +
>> +        cnt = fread(buffer, 1, info->ecc_step_size, src);
>> +        if (!cnt && !feof(src)) {
>> +            fprintf(stderr,
>> +                "Failed to read data from the source\n");
>> +            return -1;
>> +        }
>> +
>> +        pad = info->ecc_step_size - cnt;
>> +        if (pad) {
>> +            if (info->scramble && info->boot0)
>> +                fread(buffer + cnt, 1, pad, rnd);
>> +            else
>> +                memset(buffer + cnt, 0xff, pad);
>> +        }
>> +
>> +        memset(ecc, 0, eccbytes);
>> +        swap_bits(buffer, info->ecc_step_size + 4);
>> +        encode_bch(bch, buffer, info->ecc_step_size + 4, ecc);
>> +        swap_bits(buffer, info->ecc_step_size + 4);
>> +        swap_bits(ecc, eccbytes);
>> +        scramble(info, page, buffer, info->ecc_step_size + 4 + eccbytes);
>> +
>> +        fseek(dst, pos + data_offs, SEEK_SET);
>> +        fwrite(buffer, info->ecc_step_size, 1, dst);
>> +        fseek(dst, pos + ecc_offs - 4, SEEK_SET);
>> +        fwrite(ecc - 4, eccbytes + 4, 1, dst);
>> +    }
>> +
>> +    /* Fix BBM. */
>> +    fseek(dst, pos + info->page_size, SEEK_SET);
>> +    memset(buffer, 0xff, 2);
>> +    fwrite(buffer, 2, 1, dst);
>> +
>> +    /* Make dst pointer point to the next page. */
>> +    fseek(dst, pos + info->page_size + info->oob_size, SEEK_SET);
>> +
>> +    return 0;
>> +}
>> +
>> +static int create_image(const struct image_info *info)
>> +{
>> +    off_t page = info->offset / info->page_size;
>> +    struct bch_control *bch;
>> +    FILE *src, *dst, *rnd;
>> +    uint8_t *buffer;
>> +
>> +    bch = init_bch(14, info->ecc_strength, BCH_PRIMITIVE_POLY);
>> +    if (!bch) {
>> +        fprintf(stderr, "Failed to init the BCH engine\n");
>> +        return -1;
>> +    }
>> +
>> +    buffer = malloc(info->page_size + info->oob_size);
>> +    if (!buffer) {
>> +        fprintf(stderr, "Failed to allocate the NAND page buffer\n");
>> +        return -1;
>> +    }
>> +
>> +    memset(buffer, 0xff, info->page_size + info->oob_size);
>> +
>> +    src = fopen(info->source, "r");
>> +    if (!src) {
>> +        fprintf(stderr, "Failed to open source file (%s)\n",
>> +            info->source);
>> +        return -1;
>> +    }
>> +
>> +    dst = fopen(info->dest, "w");
>> +    if (!dst) {
>> +        fprintf(stderr, "Failed to open dest file (%s)\n", info->dest);
>> +        return -1;
>> +    }
>> +
>> +    rnd = fopen("/dev/urandom", "r");
>> +    if (!rnd) {
>> +        fprintf(stderr, "Failed to open /dev/urandom\n");
>> +        return -1;
>> +    }
>> +
>> +    while (!feof(src)) {
>> +        int ret;
>> +
>> +        ret = write_page(info, buffer, src, rnd, dst, bch, page++);
>> +        if (ret)
>> +            return ret;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static void display_help(int status)
>> +{
>> +    fprintf(status == EXIT_SUCCESS ? stdout : stderr,
>> +        "sunxi-nand-image-builder %s\n"
>> +        "\n"
>> +        "Usage: sunxi-nand-image-builder [OPTIONS] source-image output-image\n"
>> +        "\n"
>> +        "Creates a raw NAND image that can be read by the sunxi NAND controller.\n"
>> +        "\n"
>> +        "-h               --help               Display this help and exit\n"
>> +        "-c <str>/<step>  --ecc=<str>/<step>   ECC config (strength/step-size)\n"
>> +        "-p <size>        --page=<size>        Page size\n"
>> +        "-o <size>        --oob=<size>         OOB size\n"
>> +        "-u <size>        --usable=<size>      Usable page size\n"
>> +        "-e <size>        --eraseblock=<size>  Erase block size\n"
>> +        "-b               --boot0              Build a boot0 image.\n"
>> +        "-s               --scramble           Scramble data\n"
>> +        "-a <offset>      --address=<offset>   Where the image will be programmed.\n"
>> +        "\n"
>> +        "Notes:\n"
>> +        "All the information you need to pass to this tool should be part of\n"
>> +        "the NAND datasheet.\n"
>> +        "\n"
>> +        "The NAND controller only supports the following ECC configs\n"
>> +        "  Valid ECC strengths: 16, 24, 28, 32, 40, 48, 56, 60 and 64\n"
>> +        "  Valid ECC step size: 512 and 1024\n"
>> +        "\n"
>> +        "If you are building a boot0 image, you'll have specify extra options.\n"
>> +        "These options should be chosen based on the layouts described here:\n"
>> +        "  http://linux-sunxi.org/NAND#More_information_on_BROM_NAND\n"
>> +        "\n"
>> +        "  --usable should be assigned the 'Hardware page' value\n"
>> +        "  --ecc should be assigned the 'ECC capacity'/'ECC page' values\n"
>> +        "  --usable should be smaller than --page\n"
>> +        "\n"
>> +        "The --address option is only required for non-boot0 images that are \n"
>> +        "meant to be programmed at a non eraseblock aligned offset.\n"
>> +        "\n"
>> +        "Examples:\n"
>> +        "  The H27UCG8T2BTR-BC NAND exposes\n"
>> +        "  * 16k pages\n"
>> +        "  * 1280 OOB bytes per page\n"
>> +        "  * 4M eraseblocks\n"
>> +        "  * requires data scrambling\n"
>> +        "  * expects a minimum ECC of 40bits/1024bytes\n"
>> +        "\n"
>> +        "  A normal image can be generated with\n"
>> +        "    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -c 40/1024\n"
>> +        "  A boot0 image can be generated with\n"
>> +        "    sunxi-nand-image-builder -p 16384 -o 1280 -e 0x400000 -s -b -u 4096 -c 64/1024\n",
>> +        PLAIN_VERSION);
>> +    exit(status);
>> +}
>> +
>> +static int check_image_info(struct image_info *info)
>> +{
>> +    static int valid_ecc_strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
>> +    int eccbytes, eccsteps;
>> +    unsigned i;
>> +
>> +    if (!info->page_size) {
>> +        fprintf(stderr, "--page is missing\n");
>> +        return -EINVAL;
>> +    }
>> +
>> +    if (!info->page_size) {
>> +        fprintf(stderr, "--oob is missing\n");
>> +        return -EINVAL;
>> +    }
>> +
>> +    if (!info->eraseblock_size) {
>> +        fprintf(stderr, "--eraseblock is missing\n");
>> +        return -EINVAL;
>> +    }
>> +
>> +    if (info->ecc_step_size != 512 && info->ecc_step_size != 1024) {
>> +        fprintf(stderr, "Invalid ECC step argument: %d\n",
>> +            info->ecc_step_size);
>> +        return -EINVAL;
>> +    }
>> +
>> +    for (i = 0; i < ARRAY_SIZE(valid_ecc_strengths); i++) {
>> +        if (valid_ecc_strengths[i] == info->ecc_strength)
>> +            break;
>> +    }
>> +
>> +    if (i == ARRAY_SIZE(valid_ecc_strengths)) {
>> +        fprintf(stderr, "Invalid ECC strength argument: %d\n",
>> +            info->ecc_strength);
>> +        return -EINVAL;
>> +    }
>> +
>> +    eccbytes = DIV_ROUND_UP(info->ecc_strength * 14, 8);
>> +    if (eccbytes % 2)
>> +        eccbytes++;
>> +    eccbytes += 4;
>> +
>> +    eccsteps = info->usable_page_size / info->ecc_step_size;
>> +
>> +    if (info->page_size + info->oob_size <
>> +        info->usable_page_size + (eccsteps * eccbytes)) {
>> +        fprintf(stderr,
>> +            "ECC bytes do not fit in the NAND page, choose a weaker ECC\n");
>> +        return -EINVAL;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +int main(int argc, char **argv)
>> +{
>> +    struct image_info info;
>> +
>> +    memset(&info, 0, sizeof(info));
>> +    /*
>> +     * Process user arguments
>> +     */
>> +    for (;;) {
>> +        int option_index = 0;
>> +        char *endptr = NULL;
>> +        static const struct option long_options[] = {
>> +            {"help", no_argument, 0, 'h'},
>> +            {"ecc", required_argument, 0, 'c'},
>> +            {"page", required_argument, 0, 'p'},
>> +            {"oob", required_argument, 0, 'o'},
>> +            {"usable", required_argument, 0, 'u'},
>> +            {"eraseblock", required_argument, 0, 'e'},
>> +            {"boot0", no_argument, 0, 'b'},
>> +            {"scramble", no_argument, 0, 's'},
>> +            {"address", required_argument, 0, 'a'},
>> +            {0, 0, 0, 0},
>> +        };
>> +
>> +        int c = getopt_long(argc, argv, "c:p:o:u:e:ba:sh",
>> +                long_options, &option_index);
>> +        if (c == EOF)
>> +            break;
>> +
>> +        switch (c) {
>> +        case 'h':
>> +            display_help(0);
>> +            break;
>> +        case 's':
>> +            info.scramble = 1;
>> +            break;
>> +        case 'c':
>> +            info.ecc_strength = strtol(optarg, &endptr, 0);
>> +            if (endptr || *endptr == '/')
>> +                info.ecc_step_size = strtol(endptr + 1, NULL, 0);
>> +            break;
>> +        case 'p':
>> +            info.page_size = strtol(optarg, NULL, 0);
>> +            break;
>> +        case 'o':
>> +            info.oob_size = strtol(optarg, NULL, 0);
>> +            break;
>> +        case 'u':
>> +            info.usable_page_size = strtol(optarg, NULL, 0);
>> +            break;
>> +        case 'e':
>> +            info.eraseblock_size = strtol(optarg, NULL, 0);
>> +            break;
>> +        case 'b':
>> +            info.boot0 = 1;
>> +            break;
>> +        case 'a':
>> +            info.offset = strtoull(optarg, NULL, 0);
>> +            break;
>> +        case '?':
>> +            display_help(-1);
>> +            break;
>> +        }
>> +    }
>> +
>> +    if ((argc - optind) != 2)
>> +        display_help(-1);
>> +
>> +    info.source = argv[optind];
>> +    info.dest = argv[optind + 1];
>> +
>> +    if (!info.boot0) {
>> +        info.usable_page_size = info.page_size;
>> +    } else if (!info.usable_page_size) {
>> +        if (info.page_size > 8192)
>> +            info.usable_page_size = 8192;
>> +        else if (info.page_size > 4096)
>> +            info.usable_page_size = 4096;
>> +        else
>> +            info.usable_page_size = 1024;
>> +    }
>> +
>> +    if (check_image_info(&info))
>> +        display_help(-1);
>> +
>> +    return create_image(&info);
>> +}
>>

^ permalink raw reply

* Re: [PATCH v4 3/8] media: adv7180: add support for NEWAVMODE
From: Hans Verkuil @ 2016-11-14 11:28 UTC (permalink / raw)
  To: Steve Longerbeam, lars
  Cc: mchehab, linux-media, linux-kernel, Steve Longerbeam
In-Reply-To: <1470247430-11168-4-git-send-email-steve_longerbeam@mentor.com>

On 08/03/2016 08:03 PM, Steve Longerbeam wrote:
> Parse the optional v4l2 endpoint DT node. If the bus type is
> V4L2_MBUS_BT656 and the endpoint node specifies "newavmode",
> configure the BT.656 bus in NEWAVMODE.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> 
> ---
> 
> v4: no changes
> v3:
> - the newavmode endpoint property is now private to adv7180.
> ---
>  .../devicetree/bindings/media/i2c/adv7180.txt      |  4 ++
>  drivers/media/i2c/adv7180.c                        | 46 ++++++++++++++++++++--
>  2 files changed, 47 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/media/i2c/adv7180.txt b/Documentation/devicetree/bindings/media/i2c/adv7180.txt
> index 0d50115..6c175d2 100644
> --- a/Documentation/devicetree/bindings/media/i2c/adv7180.txt
> +++ b/Documentation/devicetree/bindings/media/i2c/adv7180.txt
> @@ -15,6 +15,10 @@ Required Properties :
>  		"adi,adv7282"
>  		"adi,adv7282-m"
>  
> +Optional Endpoint Properties :
> +- newavmode: a boolean property to indicate the BT.656 bus is operating
> +  in Analog Device's NEWAVMODE. Valid for BT.656 busses only.

This is too vague.

Based on the ADV7280/ADV7281/ADV7282/ADV7283 Hardware Reference Manual I
would say something like this:

- newavmode: a boolean property to indicate the BT.656 bus is operating
  in Analog Device's NEWAVMODE. Valid for BT.656 busses only. When enabled
  the generated EAV/SAV codes are suitable for Analog Devices encoders.
  Otherwise these codes are setup according to <some standard?>
  See bit 4 of user sub map register 0x31 in the Hardware Reference Manual.

I may have asked this before, but do you actually have hardware that needs
this? If so, it may be useful to give it as an example and explain why it
is needed.

If not, then I wonder if this cannot be dropped until we DO see hardware
that needs it.

Regards,

	Hans


> +
>  Example:
>  
>  	i2c0@1c22000 {
> diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
> index 6e093c22..467953e 100644
> --- a/drivers/media/i2c/adv7180.c
> +++ b/drivers/media/i2c/adv7180.c
> @@ -31,6 +31,7 @@
>  #include <media/v4l2-event.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ctrls.h>
> +#include <media/v4l2-of.h>
>  #include <linux/mutex.h>
>  #include <linux/delay.h>
>  
> @@ -106,6 +107,7 @@
>  #define ADV7180_REG_SHAP_FILTER_CTL_1	0x0017
>  #define ADV7180_REG_CTRL_2		0x001d
>  #define ADV7180_REG_VSYNC_FIELD_CTL_1	0x0031
> +#define ADV7180_VSYNC_FIELD_CTL_1_NEWAVMODE 0x02
>  #define ADV7180_REG_MANUAL_WIN_CTL_1	0x003d
>  #define ADV7180_REG_MANUAL_WIN_CTL_2	0x003e
>  #define ADV7180_REG_MANUAL_WIN_CTL_3	0x003f
> @@ -214,6 +216,7 @@ struct adv7180_state {
>  	struct mutex		mutex; /* mutual excl. when accessing chip */
>  	int			irq;
>  	v4l2_std_id		curr_norm;
> +	bool			newavmode;
>  	bool			powered;
>  	bool			streaming;
>  	u8			input;
> @@ -864,9 +867,15 @@ static int adv7180_init(struct adv7180_state *state)
>  	if (ret < 0)
>  		return ret;
>  
> -	/* Manually set V bit end position in NTSC mode */
> -	return adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END,
> -					ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
> +	if (!state->newavmode) {
> +		/* Manually set V bit end position in NTSC mode */
> +		ret = adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END,
> +				    ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
>  }
>  
>  static int adv7180_set_std(struct adv7180_state *state, unsigned int std)
> @@ -1217,6 +1226,13 @@ static int init_device(struct adv7180_state *state)
>  	if (ret)
>  		goto out_unlock;
>  
> +	if (state->newavmode) {
> +		ret = adv7180_write(state, ADV7180_REG_VSYNC_FIELD_CTL_1,
> +				    ADV7180_VSYNC_FIELD_CTL_1_NEWAVMODE);
> +		if (ret < 0)
> +			goto out_unlock;
> +	}
> +
>  	ret = adv7180_program_std(state);
>  	if (ret)
>  		goto out_unlock;
> @@ -1257,6 +1273,28 @@ out_unlock:
>  	return ret;
>  }
>  
> +static void adv7180_of_parse(struct adv7180_state *state)
> +{
> +	struct i2c_client *client = state->client;
> +	struct device_node *np = client->dev.of_node;
> +	struct device_node *endpoint;
> +	struct v4l2_of_endpoint	ep;
> +
> +	endpoint = of_graph_get_next_endpoint(np, NULL);
> +	if (!endpoint) {
> +		v4l_warn(client, "endpoint node not found\n");
> +		return;
> +	}
> +
> +	v4l2_of_parse_endpoint(endpoint, &ep);
> +	if (ep.bus_type == V4L2_MBUS_BT656) {
> +		if (of_property_read_bool(endpoint, "newavmode"))
> +			state->newavmode = true;
> +	}
> +
> +	of_node_put(endpoint);
> +}
> +
>  static int adv7180_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
> @@ -1279,6 +1317,8 @@ static int adv7180_probe(struct i2c_client *client,
>  	state->field = V4L2_FIELD_ALTERNATE;
>  	state->chip_info = (struct adv7180_chip_info *)id->driver_data;
>  
> +	adv7180_of_parse(state);
> +
>  	if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
>  		state->csi_client = i2c_new_dummy(client->adapter,
>  				ADV7180_DEFAULT_CSI_I2C_ADDR);
> 

^ permalink raw reply

* [Bug 98638] Panic on shutdown with AMDGPU and Ubuntu Plymouth
From: bugzilla-daemon @ 2016-11-14 11:28 UTC (permalink / raw)
  To: dri-devel
In-Reply-To: <bug-98638-502@http.bugs.freedesktop.org/>


[-- Attachment #1.1: Type: text/plain, Size: 512 bytes --]

https://bugs.freedesktop.org/show_bug.cgi?id=98638

--- Comment #7 from Christian König <deathsimple@vodafone.de> ---
Try loading the amdgpu.ko module in gdb like this (Obviously please use the
correct one for your kernel version):

gdb /lib/modules/4.7.0+/kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko

And then run

l *(amdgpu_fence_wait_empty+0x2a)

This should give you a line number when debug symbols are available.

-- 
You are receiving this mail because:
You are the assignee for the bug.

[-- Attachment #1.2: Type: text/html, Size: 1301 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.