From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756236AbbA2ORC (ORCPT ); Thu, 29 Jan 2015 09:17:02 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:50010 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753216AbbA2ORA (ORCPT ); Thu, 29 Jan 2015 09:17:00 -0500 Message-ID: <54CA40D1.4000701@canonical.com> Date: Thu, 29 Jan 2015 15:16:49 +0100 From: Maarten Lankhorst User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Sumit Semwal , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org CC: linaro-kernel@lists.linaro.org, stanislawski.tomasz@googlemail.com, robin.murphy@arm.com, m.szyprowski@samsung.com Subject: Re: [RFCv3 2/2] dma-buf: add helpers for sharing attacher constraints with dma-parms References: <1422347154-15258-1-git-send-email-sumit.semwal@linaro.org> <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> In-Reply-To: <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Op 27-01-15 om 09:25 schreef Sumit Semwal: > Add some helpers to share the constraints of devices while attaching > to the dmabuf buffer. > > At each attach, the constraints are calculated based on the following: > - max_segment_size, max_segment_count, segment_boundary_mask from > device_dma_parameters. > > In case the attaching device's constraints don't match up, attach() fails. > > At detach, the constraints are recalculated based on the remaining > attached devices. > > Two helpers are added: > - dma_buf_get_constraints - which gives the current constraints as calculated > during each attach on the buffer till the time, > - dma_buf_recalc_constraints - which recalculates the constraints for all > currently attached devices for the 'paranoid' ones amongst us. > > The idea of this patch is largely taken from Rob Clark's RFC at > https://lkml.org/lkml/2012/7/19/285, and the comments received on it. > > Cc: Rob Clark > Signed-off-by: Sumit Semwal > --- > v3: > - Thanks to Russell's comment, remove dma_mask and coherent_dma_mask from > constraints' calculation; has a nice side effect of letting us use > device_dma_parameters directly to list constraints. > - update the debugfs output to show constraint info as well. > > v2: split constraints-sharing and allocation helpers > > drivers/dma-buf/dma-buf.c | 126 +++++++++++++++++++++++++++++++++++++++++++++- > include/linux/dma-buf.h | 7 +++ > 2 files changed, 132 insertions(+), 1 deletion(-) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index 5be225c2ba98..f363f1440803 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -264,6 +264,66 @@ static inline int is_dma_buf_file(struct file *file) > return file->f_op == &dma_buf_fops; > } > > +static inline void init_constraints(struct device_dma_parameters *cons) > +{ > + cons->max_segment_count = (unsigned int)-1; > + cons->max_segment_size = (unsigned int)-1; > + cons->segment_boundary_mask = (unsigned long)-1; > +} Use DMA_SEGMENTS_MAX_SEG_COUNT or UINT/ULONG_MAX here instead? Patches look sane, Reviewed-By: Maarten Lankhorst > +/* > + * calc_constraints - calculates if the new attaching device's constraints > + * match, with the constraints of already attached devices; if yes, returns > + * the constraints; else return ERR_PTR(-EINVAL) > + */ > +static int calc_constraints(struct device *dev, > + struct device_dma_parameters *calc_cons) > +{ > + struct device_dma_parameters cons = *calc_cons; > + > + cons.max_segment_count = min(cons.max_segment_count, > + dma_get_max_seg_count(dev)); > + cons.max_segment_size = min(cons.max_segment_size, > + dma_get_max_seg_size(dev)); > + cons.segment_boundary_mask &= dma_get_seg_boundary(dev); > + > + if (!cons.max_segment_count || > + !cons.max_segment_size || > + !cons.segment_boundary_mask) { > + pr_err("Dev: %s's constraints don't match\n", dev_name(dev)); > + return -EINVAL; > + } > + > + *calc_cons = cons; > + > + return 0; > +} > + > +/* > + * recalc_constraints - recalculates constraints for all attached devices; > + * useful for detach() recalculation, and for dma_buf_recalc_constraints() > + * helper. > + * Returns recalculated constraints in recalc_cons, or error in the unlikely > + * case when constraints of attached devices might have changed. > + */ > +static int recalc_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *recalc_cons) > +{ > + struct device_dma_parameters calc_cons; > + struct dma_buf_attachment *attach; > + int ret = 0; > + > + init_constraints(&calc_cons); > + > + list_for_each_entry(attach, &dmabuf->attachments, node) { > + ret = calc_constraints(attach->dev, &calc_cons); > + if (ret) > + return ret; > + } > + *recalc_cons = calc_cons; > + return 0; > +} > + > /** > * dma_buf_export_named - Creates a new dma_buf, and associates an anon file > * with this buffer, so it can be exported. > @@ -313,6 +373,9 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops, > dmabuf->ops = ops; > dmabuf->size = size; > dmabuf->exp_name = exp_name; > + > + init_constraints(&dmabuf->constraints); > + > init_waitqueue_head(&dmabuf->poll); > dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll; > dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0; > @@ -422,7 +485,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > struct device *dev) > { > struct dma_buf_attachment *attach; > - int ret; > + int ret = 0; > > if (WARN_ON(!dmabuf || !dev)) > return ERR_PTR(-EINVAL); > @@ -436,6 +499,9 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > > mutex_lock(&dmabuf->lock); > > + if (calc_constraints(dev, &dmabuf->constraints)) > + goto err_constraints; > + > if (dmabuf->ops->attach) { > ret = dmabuf->ops->attach(dmabuf, dev, attach); > if (ret) > @@ -448,6 +514,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > > err_attach: > kfree(attach); > +err_constraints: > mutex_unlock(&dmabuf->lock); > return ERR_PTR(ret); > } > @@ -470,6 +537,8 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) > if (dmabuf->ops->detach) > dmabuf->ops->detach(dmabuf, attach); > > + recalc_constraints(dmabuf, &dmabuf->constraints); > + > mutex_unlock(&dmabuf->lock); > kfree(attach); > } > @@ -770,6 +839,56 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) > } > EXPORT_SYMBOL_GPL(dma_buf_vunmap); > > +/** > + * dma_buf_get_constraints - get the *current* constraints of the dmabuf, > + * as calculated during each attach(); returns error on invalid inputs > + * > + * @dmabuf: [in] buffer to get constraints of > + * @constraints: [out] current constraints are returned in this > + */ > +int dma_buf_get_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *constraints) > +{ > + if (WARN_ON(!dmabuf || !constraints)) > + return -EINVAL; > + > + mutex_lock(&dmabuf->lock); > + *constraints = dmabuf->constraints; > + mutex_unlock(&dmabuf->lock); > + return 0; > +} > +EXPORT_SYMBOL_GPL(dma_buf_get_constraints); > + > +/** > + * dma_buf_recalc_constraints - *recalculate* the constraints for the buffer > + * afresh, from the list of currently attached devices; this could be useful > + * cross-check the current constraints, for exporters that might want to be > + * 'paranoid' about the device constraints. > + * > + * returns error on invalid inputs > + * > + * @dmabuf: [in] buffer to get constraints of > + * @constraints: [out] recalculated constraints are returned in this > + */ > +int dma_buf_recalc_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *constraints) > +{ > + struct device_dma_parameters calc_cons; > + int ret = 0; > + > + if (WARN_ON(!dmabuf || !constraints)) > + return -EINVAL; > + > + mutex_lock(&dmabuf->lock); > + ret = recalc_constraints(dmabuf, &calc_cons); > + if (!ret) > + *constraints = calc_cons; > + > + mutex_unlock(&dmabuf->lock); > + return ret; > +} > +EXPORT_SYMBOL_GPL(dma_buf_recalc_constraints); > + > #ifdef CONFIG_DEBUG_FS > static int dma_buf_describe(struct seq_file *s) > { > @@ -801,6 +920,11 @@ static int dma_buf_describe(struct seq_file *s) > buf_obj->file->f_flags, buf_obj->file->f_mode, > file_count(buf_obj->file), > buf_obj->exp_name); > + seq_printf(s, "\tConstraints: Seg Count: %08u, Seg Size: %08u", > + buf_obj->constraints.max_segment_count, > + buf_obj->constraints.max_segment_size); > + seq_printf(s, " seg boundary mask: %08lx\n", > + buf_obj->constraints.segment_boundary_mask); > > seq_puts(s, "\tAttached Devices:\n"); > attach_count = 0; > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > index 694e1fe1c4b4..489ad9b2e5ae 100644 > --- a/include/linux/dma-buf.h > +++ b/include/linux/dma-buf.h > @@ -34,6 +34,7 @@ > #include > > struct device; > +struct device_dma_parameters; > struct dma_buf; > struct dma_buf_attachment; > > @@ -116,6 +117,7 @@ struct dma_buf_ops { > * @ops: dma_buf_ops associated with this buffer object. > * @exp_name: name of the exporter; useful for debugging. > * @list_node: node for dma_buf accounting and debugging. > + * @constraints: calculated constraints of attached devices. > * @priv: exporter specific private data for this buffer object. > * @resv: reservation object linked to this dma-buf > */ > @@ -130,6 +132,7 @@ struct dma_buf { > void *vmap_ptr; > const char *exp_name; > struct list_head list_node; > + struct device_dma_parameters constraints; > void *priv; > struct reservation_object *resv; > > @@ -211,4 +214,8 @@ void *dma_buf_vmap(struct dma_buf *); > void dma_buf_vunmap(struct dma_buf *, void *vaddr); > int dma_buf_debugfs_create_file(const char *name, > int (*write)(struct seq_file *)); > + > +int dma_buf_get_constraints(struct dma_buf *, struct device_dma_parameters *); > +int dma_buf_recalc_constraints(struct dma_buf *, > + struct device_dma_parameters *); > #endif /* __DMA_BUF_H__ */ From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wi0-f169.google.com (mail-wi0-f169.google.com [209.85.212.169]) by kanga.kvack.org (Postfix) with ESMTP id 3091F6B0038 for ; Thu, 29 Jan 2015 09:17:00 -0500 (EST) Received: by mail-wi0-f169.google.com with SMTP id h11so10655721wiw.0 for ; Thu, 29 Jan 2015 06:16:59 -0800 (PST) Received: from youngberry.canonical.com (youngberry.canonical.com. [91.189.89.112]) by mx.google.com with ESMTPS id hd10si1448838wib.37.2015.01.29.06.16.57 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 29 Jan 2015 06:16:58 -0800 (PST) Message-ID: <54CA40D1.4000701@canonical.com> Date: Thu, 29 Jan 2015 15:16:49 +0100 From: Maarten Lankhorst MIME-Version: 1.0 Subject: Re: [RFCv3 2/2] dma-buf: add helpers for sharing attacher constraints with dma-parms References: <1422347154-15258-1-git-send-email-sumit.semwal@linaro.org> <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> In-Reply-To: <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Sender: owner-linux-mm@kvack.org List-ID: To: Sumit Semwal , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Cc: linaro-kernel@lists.linaro.org, stanislawski.tomasz@googlemail.com, robin.murphy@arm.com, m.szyprowski@samsung.com Op 27-01-15 om 09:25 schreef Sumit Semwal: > Add some helpers to share the constraints of devices while attaching > to the dmabuf buffer. > > At each attach, the constraints are calculated based on the following: > - max_segment_size, max_segment_count, segment_boundary_mask from > device_dma_parameters. > > In case the attaching device's constraints don't match up, attach() fails. > > At detach, the constraints are recalculated based on the remaining > attached devices. > > Two helpers are added: > - dma_buf_get_constraints - which gives the current constraints as calculated > during each attach on the buffer till the time, > - dma_buf_recalc_constraints - which recalculates the constraints for all > currently attached devices for the 'paranoid' ones amongst us. > > The idea of this patch is largely taken from Rob Clark's RFC at > https://lkml.org/lkml/2012/7/19/285, and the comments received on it. > > Cc: Rob Clark > Signed-off-by: Sumit Semwal > --- > v3: > - Thanks to Russell's comment, remove dma_mask and coherent_dma_mask from > constraints' calculation; has a nice side effect of letting us use > device_dma_parameters directly to list constraints. > - update the debugfs output to show constraint info as well. > > v2: split constraints-sharing and allocation helpers > > drivers/dma-buf/dma-buf.c | 126 +++++++++++++++++++++++++++++++++++++++++++++- > include/linux/dma-buf.h | 7 +++ > 2 files changed, 132 insertions(+), 1 deletion(-) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index 5be225c2ba98..f363f1440803 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -264,6 +264,66 @@ static inline int is_dma_buf_file(struct file *file) > return file->f_op == &dma_buf_fops; > } > > +static inline void init_constraints(struct device_dma_parameters *cons) > +{ > + cons->max_segment_count = (unsigned int)-1; > + cons->max_segment_size = (unsigned int)-1; > + cons->segment_boundary_mask = (unsigned long)-1; > +} Use DMA_SEGMENTS_MAX_SEG_COUNT or UINT/ULONG_MAX here instead? Patches look sane, Reviewed-By: Maarten Lankhorst > +/* > + * calc_constraints - calculates if the new attaching device's constraints > + * match, with the constraints of already attached devices; if yes, returns > + * the constraints; else return ERR_PTR(-EINVAL) > + */ > +static int calc_constraints(struct device *dev, > + struct device_dma_parameters *calc_cons) > +{ > + struct device_dma_parameters cons = *calc_cons; > + > + cons.max_segment_count = min(cons.max_segment_count, > + dma_get_max_seg_count(dev)); > + cons.max_segment_size = min(cons.max_segment_size, > + dma_get_max_seg_size(dev)); > + cons.segment_boundary_mask &= dma_get_seg_boundary(dev); > + > + if (!cons.max_segment_count || > + !cons.max_segment_size || > + !cons.segment_boundary_mask) { > + pr_err("Dev: %s's constraints don't match\n", dev_name(dev)); > + return -EINVAL; > + } > + > + *calc_cons = cons; > + > + return 0; > +} > + > +/* > + * recalc_constraints - recalculates constraints for all attached devices; > + * useful for detach() recalculation, and for dma_buf_recalc_constraints() > + * helper. > + * Returns recalculated constraints in recalc_cons, or error in the unlikely > + * case when constraints of attached devices might have changed. > + */ > +static int recalc_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *recalc_cons) > +{ > + struct device_dma_parameters calc_cons; > + struct dma_buf_attachment *attach; > + int ret = 0; > + > + init_constraints(&calc_cons); > + > + list_for_each_entry(attach, &dmabuf->attachments, node) { > + ret = calc_constraints(attach->dev, &calc_cons); > + if (ret) > + return ret; > + } > + *recalc_cons = calc_cons; > + return 0; > +} > + > /** > * dma_buf_export_named - Creates a new dma_buf, and associates an anon file > * with this buffer, so it can be exported. > @@ -313,6 +373,9 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops, > dmabuf->ops = ops; > dmabuf->size = size; > dmabuf->exp_name = exp_name; > + > + init_constraints(&dmabuf->constraints); > + > init_waitqueue_head(&dmabuf->poll); > dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll; > dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0; > @@ -422,7 +485,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > struct device *dev) > { > struct dma_buf_attachment *attach; > - int ret; > + int ret = 0; > > if (WARN_ON(!dmabuf || !dev)) > return ERR_PTR(-EINVAL); > @@ -436,6 +499,9 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > > mutex_lock(&dmabuf->lock); > > + if (calc_constraints(dev, &dmabuf->constraints)) > + goto err_constraints; > + > if (dmabuf->ops->attach) { > ret = dmabuf->ops->attach(dmabuf, dev, attach); > if (ret) > @@ -448,6 +514,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > > err_attach: > kfree(attach); > +err_constraints: > mutex_unlock(&dmabuf->lock); > return ERR_PTR(ret); > } > @@ -470,6 +537,8 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) > if (dmabuf->ops->detach) > dmabuf->ops->detach(dmabuf, attach); > > + recalc_constraints(dmabuf, &dmabuf->constraints); > + > mutex_unlock(&dmabuf->lock); > kfree(attach); > } > @@ -770,6 +839,56 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) > } > EXPORT_SYMBOL_GPL(dma_buf_vunmap); > > +/** > + * dma_buf_get_constraints - get the *current* constraints of the dmabuf, > + * as calculated during each attach(); returns error on invalid inputs > + * > + * @dmabuf: [in] buffer to get constraints of > + * @constraints: [out] current constraints are returned in this > + */ > +int dma_buf_get_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *constraints) > +{ > + if (WARN_ON(!dmabuf || !constraints)) > + return -EINVAL; > + > + mutex_lock(&dmabuf->lock); > + *constraints = dmabuf->constraints; > + mutex_unlock(&dmabuf->lock); > + return 0; > +} > +EXPORT_SYMBOL_GPL(dma_buf_get_constraints); > + > +/** > + * dma_buf_recalc_constraints - *recalculate* the constraints for the buffer > + * afresh, from the list of currently attached devices; this could be useful > + * cross-check the current constraints, for exporters that might want to be > + * 'paranoid' about the device constraints. > + * > + * returns error on invalid inputs > + * > + * @dmabuf: [in] buffer to get constraints of > + * @constraints: [out] recalculated constraints are returned in this > + */ > +int dma_buf_recalc_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *constraints) > +{ > + struct device_dma_parameters calc_cons; > + int ret = 0; > + > + if (WARN_ON(!dmabuf || !constraints)) > + return -EINVAL; > + > + mutex_lock(&dmabuf->lock); > + ret = recalc_constraints(dmabuf, &calc_cons); > + if (!ret) > + *constraints = calc_cons; > + > + mutex_unlock(&dmabuf->lock); > + return ret; > +} > +EXPORT_SYMBOL_GPL(dma_buf_recalc_constraints); > + > #ifdef CONFIG_DEBUG_FS > static int dma_buf_describe(struct seq_file *s) > { > @@ -801,6 +920,11 @@ static int dma_buf_describe(struct seq_file *s) > buf_obj->file->f_flags, buf_obj->file->f_mode, > file_count(buf_obj->file), > buf_obj->exp_name); > + seq_printf(s, "\tConstraints: Seg Count: %08u, Seg Size: %08u", > + buf_obj->constraints.max_segment_count, > + buf_obj->constraints.max_segment_size); > + seq_printf(s, " seg boundary mask: %08lx\n", > + buf_obj->constraints.segment_boundary_mask); > > seq_puts(s, "\tAttached Devices:\n"); > attach_count = 0; > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > index 694e1fe1c4b4..489ad9b2e5ae 100644 > --- a/include/linux/dma-buf.h > +++ b/include/linux/dma-buf.h > @@ -34,6 +34,7 @@ > #include > > struct device; > +struct device_dma_parameters; > struct dma_buf; > struct dma_buf_attachment; > > @@ -116,6 +117,7 @@ struct dma_buf_ops { > * @ops: dma_buf_ops associated with this buffer object. > * @exp_name: name of the exporter; useful for debugging. > * @list_node: node for dma_buf accounting and debugging. > + * @constraints: calculated constraints of attached devices. > * @priv: exporter specific private data for this buffer object. > * @resv: reservation object linked to this dma-buf > */ > @@ -130,6 +132,7 @@ struct dma_buf { > void *vmap_ptr; > const char *exp_name; > struct list_head list_node; > + struct device_dma_parameters constraints; > void *priv; > struct reservation_object *resv; > > @@ -211,4 +214,8 @@ void *dma_buf_vmap(struct dma_buf *); > void dma_buf_vunmap(struct dma_buf *, void *vaddr); > int dma_buf_debugfs_create_file(const char *name, > int (*write)(struct seq_file *)); > + > +int dma_buf_get_constraints(struct dma_buf *, struct device_dma_parameters *); > +int dma_buf_recalc_constraints(struct dma_buf *, > + struct device_dma_parameters *); > #endif /* __DMA_BUF_H__ */ -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org From mboxrd@z Thu Jan 1 00:00:00 1970 From: maarten.lankhorst@canonical.com (Maarten Lankhorst) Date: Thu, 29 Jan 2015 15:16:49 +0100 Subject: [RFCv3 2/2] dma-buf: add helpers for sharing attacher constraints with dma-parms In-Reply-To: <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> References: <1422347154-15258-1-git-send-email-sumit.semwal@linaro.org> <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> Message-ID: <54CA40D1.4000701@canonical.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Op 27-01-15 om 09:25 schreef Sumit Semwal: > Add some helpers to share the constraints of devices while attaching > to the dmabuf buffer. > > At each attach, the constraints are calculated based on the following: > - max_segment_size, max_segment_count, segment_boundary_mask from > device_dma_parameters. > > In case the attaching device's constraints don't match up, attach() fails. > > At detach, the constraints are recalculated based on the remaining > attached devices. > > Two helpers are added: > - dma_buf_get_constraints - which gives the current constraints as calculated > during each attach on the buffer till the time, > - dma_buf_recalc_constraints - which recalculates the constraints for all > currently attached devices for the 'paranoid' ones amongst us. > > The idea of this patch is largely taken from Rob Clark's RFC at > https://lkml.org/lkml/2012/7/19/285, and the comments received on it. > > Cc: Rob Clark > Signed-off-by: Sumit Semwal > --- > v3: > - Thanks to Russell's comment, remove dma_mask and coherent_dma_mask from > constraints' calculation; has a nice side effect of letting us use > device_dma_parameters directly to list constraints. > - update the debugfs output to show constraint info as well. > > v2: split constraints-sharing and allocation helpers > > drivers/dma-buf/dma-buf.c | 126 +++++++++++++++++++++++++++++++++++++++++++++- > include/linux/dma-buf.h | 7 +++ > 2 files changed, 132 insertions(+), 1 deletion(-) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index 5be225c2ba98..f363f1440803 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -264,6 +264,66 @@ static inline int is_dma_buf_file(struct file *file) > return file->f_op == &dma_buf_fops; > } > > +static inline void init_constraints(struct device_dma_parameters *cons) > +{ > + cons->max_segment_count = (unsigned int)-1; > + cons->max_segment_size = (unsigned int)-1; > + cons->segment_boundary_mask = (unsigned long)-1; > +} Use DMA_SEGMENTS_MAX_SEG_COUNT or UINT/ULONG_MAX here instead? Patches look sane, Reviewed-By: Maarten Lankhorst > +/* > + * calc_constraints - calculates if the new attaching device's constraints > + * match, with the constraints of already attached devices; if yes, returns > + * the constraints; else return ERR_PTR(-EINVAL) > + */ > +static int calc_constraints(struct device *dev, > + struct device_dma_parameters *calc_cons) > +{ > + struct device_dma_parameters cons = *calc_cons; > + > + cons.max_segment_count = min(cons.max_segment_count, > + dma_get_max_seg_count(dev)); > + cons.max_segment_size = min(cons.max_segment_size, > + dma_get_max_seg_size(dev)); > + cons.segment_boundary_mask &= dma_get_seg_boundary(dev); > + > + if (!cons.max_segment_count || > + !cons.max_segment_size || > + !cons.segment_boundary_mask) { > + pr_err("Dev: %s's constraints don't match\n", dev_name(dev)); > + return -EINVAL; > + } > + > + *calc_cons = cons; > + > + return 0; > +} > + > +/* > + * recalc_constraints - recalculates constraints for all attached devices; > + * useful for detach() recalculation, and for dma_buf_recalc_constraints() > + * helper. > + * Returns recalculated constraints in recalc_cons, or error in the unlikely > + * case when constraints of attached devices might have changed. > + */ > +static int recalc_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *recalc_cons) > +{ > + struct device_dma_parameters calc_cons; > + struct dma_buf_attachment *attach; > + int ret = 0; > + > + init_constraints(&calc_cons); > + > + list_for_each_entry(attach, &dmabuf->attachments, node) { > + ret = calc_constraints(attach->dev, &calc_cons); > + if (ret) > + return ret; > + } > + *recalc_cons = calc_cons; > + return 0; > +} > + > /** > * dma_buf_export_named - Creates a new dma_buf, and associates an anon file > * with this buffer, so it can be exported. > @@ -313,6 +373,9 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops, > dmabuf->ops = ops; > dmabuf->size = size; > dmabuf->exp_name = exp_name; > + > + init_constraints(&dmabuf->constraints); > + > init_waitqueue_head(&dmabuf->poll); > dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll; > dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0; > @@ -422,7 +485,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > struct device *dev) > { > struct dma_buf_attachment *attach; > - int ret; > + int ret = 0; > > if (WARN_ON(!dmabuf || !dev)) > return ERR_PTR(-EINVAL); > @@ -436,6 +499,9 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > > mutex_lock(&dmabuf->lock); > > + if (calc_constraints(dev, &dmabuf->constraints)) > + goto err_constraints; > + > if (dmabuf->ops->attach) { > ret = dmabuf->ops->attach(dmabuf, dev, attach); > if (ret) > @@ -448,6 +514,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, > > err_attach: > kfree(attach); > +err_constraints: > mutex_unlock(&dmabuf->lock); > return ERR_PTR(ret); > } > @@ -470,6 +537,8 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) > if (dmabuf->ops->detach) > dmabuf->ops->detach(dmabuf, attach); > > + recalc_constraints(dmabuf, &dmabuf->constraints); > + > mutex_unlock(&dmabuf->lock); > kfree(attach); > } > @@ -770,6 +839,56 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) > } > EXPORT_SYMBOL_GPL(dma_buf_vunmap); > > +/** > + * dma_buf_get_constraints - get the *current* constraints of the dmabuf, > + * as calculated during each attach(); returns error on invalid inputs > + * > + * @dmabuf: [in] buffer to get constraints of > + * @constraints: [out] current constraints are returned in this > + */ > +int dma_buf_get_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *constraints) > +{ > + if (WARN_ON(!dmabuf || !constraints)) > + return -EINVAL; > + > + mutex_lock(&dmabuf->lock); > + *constraints = dmabuf->constraints; > + mutex_unlock(&dmabuf->lock); > + return 0; > +} > +EXPORT_SYMBOL_GPL(dma_buf_get_constraints); > + > +/** > + * dma_buf_recalc_constraints - *recalculate* the constraints for the buffer > + * afresh, from the list of currently attached devices; this could be useful > + * cross-check the current constraints, for exporters that might want to be > + * 'paranoid' about the device constraints. > + * > + * returns error on invalid inputs > + * > + * @dmabuf: [in] buffer to get constraints of > + * @constraints: [out] recalculated constraints are returned in this > + */ > +int dma_buf_recalc_constraints(struct dma_buf *dmabuf, > + struct device_dma_parameters *constraints) > +{ > + struct device_dma_parameters calc_cons; > + int ret = 0; > + > + if (WARN_ON(!dmabuf || !constraints)) > + return -EINVAL; > + > + mutex_lock(&dmabuf->lock); > + ret = recalc_constraints(dmabuf, &calc_cons); > + if (!ret) > + *constraints = calc_cons; > + > + mutex_unlock(&dmabuf->lock); > + return ret; > +} > +EXPORT_SYMBOL_GPL(dma_buf_recalc_constraints); > + > #ifdef CONFIG_DEBUG_FS > static int dma_buf_describe(struct seq_file *s) > { > @@ -801,6 +920,11 @@ static int dma_buf_describe(struct seq_file *s) > buf_obj->file->f_flags, buf_obj->file->f_mode, > file_count(buf_obj->file), > buf_obj->exp_name); > + seq_printf(s, "\tConstraints: Seg Count: %08u, Seg Size: %08u", > + buf_obj->constraints.max_segment_count, > + buf_obj->constraints.max_segment_size); > + seq_printf(s, " seg boundary mask: %08lx\n", > + buf_obj->constraints.segment_boundary_mask); > > seq_puts(s, "\tAttached Devices:\n"); > attach_count = 0; > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > index 694e1fe1c4b4..489ad9b2e5ae 100644 > --- a/include/linux/dma-buf.h > +++ b/include/linux/dma-buf.h > @@ -34,6 +34,7 @@ > #include > > struct device; > +struct device_dma_parameters; > struct dma_buf; > struct dma_buf_attachment; > > @@ -116,6 +117,7 @@ struct dma_buf_ops { > * @ops: dma_buf_ops associated with this buffer object. > * @exp_name: name of the exporter; useful for debugging. > * @list_node: node for dma_buf accounting and debugging. > + * @constraints: calculated constraints of attached devices. > * @priv: exporter specific private data for this buffer object. > * @resv: reservation object linked to this dma-buf > */ > @@ -130,6 +132,7 @@ struct dma_buf { > void *vmap_ptr; > const char *exp_name; > struct list_head list_node; > + struct device_dma_parameters constraints; > void *priv; > struct reservation_object *resv; > > @@ -211,4 +214,8 @@ void *dma_buf_vmap(struct dma_buf *); > void dma_buf_vunmap(struct dma_buf *, void *vaddr); > int dma_buf_debugfs_create_file(const char *name, > int (*write)(struct seq_file *)); > + > +int dma_buf_get_constraints(struct dma_buf *, struct device_dma_parameters *); > +int dma_buf_recalc_constraints(struct dma_buf *, > + struct device_dma_parameters *); > #endif /* __DMA_BUF_H__ */ From mboxrd@z Thu Jan 1 00:00:00 1970 From: Maarten Lankhorst Subject: Re: [RFCv3 2/2] dma-buf: add helpers for sharing attacher constraints with dma-parms Date: Thu, 29 Jan 2015 15:16:49 +0100 Message-ID: <54CA40D1.4000701@canonical.com> References: <1422347154-15258-1-git-send-email-sumit.semwal@linaro.org> <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by gabe.freedesktop.org (Postfix) with ESMTP id E991A6E798 for ; Thu, 29 Jan 2015 06:16:58 -0800 (PST) In-Reply-To: <1422347154-15258-2-git-send-email-sumit.semwal@linaro.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Sumit Semwal , linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Cc: robin.murphy@arm.com, linaro-kernel@lists.linaro.org, stanislawski.tomasz@googlemail.com, m.szyprowski@samsung.com List-Id: dri-devel@lists.freedesktop.org T3AgMjctMDEtMTUgb20gMDk6MjUgc2NocmVlZiBTdW1pdCBTZW13YWw6Cj4gQWRkIHNvbWUgaGVs cGVycyB0byBzaGFyZSB0aGUgY29uc3RyYWludHMgb2YgZGV2aWNlcyB3aGlsZSBhdHRhY2hpbmcK PiB0byB0aGUgZG1hYnVmIGJ1ZmZlci4KPgo+IEF0IGVhY2ggYXR0YWNoLCB0aGUgY29uc3RyYWlu dHMgYXJlIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGZvbGxvd2luZzoKPiAtIG1heF9zZWdtZW50 X3NpemUsIG1heF9zZWdtZW50X2NvdW50LCBzZWdtZW50X2JvdW5kYXJ5X21hc2sgZnJvbQo+ICAg IGRldmljZV9kbWFfcGFyYW1ldGVycy4KPgo+IEluIGNhc2UgdGhlIGF0dGFjaGluZyBkZXZpY2Un cyBjb25zdHJhaW50cyBkb24ndCBtYXRjaCB1cCwgYXR0YWNoKCkgZmFpbHMuCj4KPiBBdCBkZXRh Y2gsIHRoZSBjb25zdHJhaW50cyBhcmUgcmVjYWxjdWxhdGVkIGJhc2VkIG9uIHRoZSByZW1haW5p bmcKPiBhdHRhY2hlZCBkZXZpY2VzLgo+Cj4gVHdvIGhlbHBlcnMgYXJlIGFkZGVkOgo+IC0gZG1h X2J1Zl9nZXRfY29uc3RyYWludHMgLSB3aGljaCBnaXZlcyB0aGUgY3VycmVudCBjb25zdHJhaW50 cyBhcyBjYWxjdWxhdGVkCj4gICAgICAgZHVyaW5nIGVhY2ggYXR0YWNoIG9uIHRoZSBidWZmZXIg dGlsbCB0aGUgdGltZSwKPiAtIGRtYV9idWZfcmVjYWxjX2NvbnN0cmFpbnRzIC0gd2hpY2ggcmVj YWxjdWxhdGVzIHRoZSBjb25zdHJhaW50cyBmb3IgYWxsCj4gICAgICAgY3VycmVudGx5IGF0dGFj aGVkIGRldmljZXMgZm9yIHRoZSAncGFyYW5vaWQnIG9uZXMgYW1vbmdzdCB1cy4KPgo+IFRoZSBp ZGVhIG9mIHRoaXMgcGF0Y2ggaXMgbGFyZ2VseSB0YWtlbiBmcm9tIFJvYiBDbGFyaydzIFJGQyBh dAo+IGh0dHBzOi8vbGttbC5vcmcvbGttbC8yMDEyLzcvMTkvMjg1LCBhbmQgdGhlIGNvbW1lbnRz IHJlY2VpdmVkIG9uIGl0Lgo+Cj4gQ2M6IFJvYiBDbGFyayA8cm9iZGNsYXJrQGdtYWlsLmNvbT4K PiBTaWduZWQtb2ZmLWJ5OiBTdW1pdCBTZW13YWwgPHN1bWl0LnNlbXdhbEBsaW5hcm8ub3JnPgo+ IC0tLQo+IHYzOiAKPiAtIFRoYW5rcyB0byBSdXNzZWxsJ3MgY29tbWVudCwgcmVtb3ZlIGRtYV9t YXNrIGFuZCBjb2hlcmVudF9kbWFfbWFzayBmcm9tCj4gICBjb25zdHJhaW50cycgY2FsY3VsYXRp b247IGhhcyBhIG5pY2Ugc2lkZSBlZmZlY3Qgb2YgbGV0dGluZyB1cyB1c2UKPiAgIGRldmljZV9k bWFfcGFyYW1ldGVycyBkaXJlY3RseSB0byBsaXN0IGNvbnN0cmFpbnRzLgo+IC0gdXBkYXRlIHRo ZSBkZWJ1Z2ZzIG91dHB1dCB0byBzaG93IGNvbnN0cmFpbnQgaW5mbyBhcyB3ZWxsLgo+ICAgCj4g djI6IHNwbGl0IGNvbnN0cmFpbnRzLXNoYXJpbmcgYW5kIGFsbG9jYXRpb24gaGVscGVycwo+Cj4g IGRyaXZlcnMvZG1hLWJ1Zi9kbWEtYnVmLmMgfCAxMjYgKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrLQo+ICBpbmNsdWRlL2xpbnV4L2RtYS1idWYuaCAgIHwgICA3 ICsrKwo+ICAyIGZpbGVzIGNoYW5nZWQsIDEzMiBpbnNlcnRpb25zKCspLCAxIGRlbGV0aW9uKC0p Cj4KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEtYnVmL2RtYS1idWYuYyBiL2RyaXZlcnMvZG1h LWJ1Zi9kbWEtYnVmLmMKPiBpbmRleCA1YmUyMjVjMmJhOTguLmYzNjNmMTQ0MDgwMyAxMDA2NDQK PiAtLS0gYS9kcml2ZXJzL2RtYS1idWYvZG1hLWJ1Zi5jCj4gKysrIGIvZHJpdmVycy9kbWEtYnVm L2RtYS1idWYuYwo+IEBAIC0yNjQsNiArMjY0LDY2IEBAIHN0YXRpYyBpbmxpbmUgaW50IGlzX2Rt YV9idWZfZmlsZShzdHJ1Y3QgZmlsZSAqZmlsZSkKPiAgCXJldHVybiBmaWxlLT5mX29wID09ICZk bWFfYnVmX2ZvcHM7Cj4gIH0KPiAgCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBpbml0X2NvbnN0cmFp bnRzKHN0cnVjdCBkZXZpY2VfZG1hX3BhcmFtZXRlcnMgKmNvbnMpCj4gK3sKPiArCWNvbnMtPm1h eF9zZWdtZW50X2NvdW50ID0gKHVuc2lnbmVkIGludCktMTsKPiArCWNvbnMtPm1heF9zZWdtZW50 X3NpemUgPSAodW5zaWduZWQgaW50KS0xOwo+ICsJY29ucy0+c2VnbWVudF9ib3VuZGFyeV9tYXNr ID0gKHVuc2lnbmVkIGxvbmcpLTE7Cj4gK30KVXNlIERNQV9TRUdNRU5UU19NQVhfU0VHX0NPVU5U IG9yIFVJTlQvVUxPTkdfTUFYIGhlcmUgaW5zdGVhZD8KClBhdGNoZXMgbG9vayBzYW5lLApSZXZp ZXdlZC1CeTogTWFhcnRlbiBMYW5raG9yc3QgPG1hYXJ0ZW4ubGFua2hvcnN0QGNhbm9uaWNhbC5j b20+Cj4gKy8qCj4gKyAqIGNhbGNfY29uc3RyYWludHMgLSBjYWxjdWxhdGVzIGlmIHRoZSBuZXcg YXR0YWNoaW5nIGRldmljZSdzIGNvbnN0cmFpbnRzCj4gKyAqIG1hdGNoLCB3aXRoIHRoZSBjb25z dHJhaW50cyBvZiBhbHJlYWR5IGF0dGFjaGVkIGRldmljZXM7IGlmIHllcywgcmV0dXJucwo+ICsg KiB0aGUgY29uc3RyYWludHM7IGVsc2UgcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCkKPiArICovCj4g K3N0YXRpYyBpbnQgY2FsY19jb25zdHJhaW50cyhzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCSAg ICBzdHJ1Y3QgZGV2aWNlX2RtYV9wYXJhbWV0ZXJzICpjYWxjX2NvbnMpCj4gK3sKPiArCXN0cnVj dCBkZXZpY2VfZG1hX3BhcmFtZXRlcnMgY29ucyA9ICpjYWxjX2NvbnM7Cj4gKwo+ICsJY29ucy5t YXhfc2VnbWVudF9jb3VudCA9IG1pbihjb25zLm1heF9zZWdtZW50X2NvdW50LAo+ICsJCQkJCWRt YV9nZXRfbWF4X3NlZ19jb3VudChkZXYpKTsKPiArCWNvbnMubWF4X3NlZ21lbnRfc2l6ZSA9IG1p bihjb25zLm1heF9zZWdtZW50X3NpemUsCj4gKwkJCQkJZG1hX2dldF9tYXhfc2VnX3NpemUoZGV2 KSk7Cj4gKwljb25zLnNlZ21lbnRfYm91bmRhcnlfbWFzayAmPSBkbWFfZ2V0X3NlZ19ib3VuZGFy eShkZXYpOwo+ICsKPiArCWlmICghY29ucy5tYXhfc2VnbWVudF9jb3VudCB8fAo+ICsJICAgICFj b25zLm1heF9zZWdtZW50X3NpemUgfHwKPiArCSAgICAhY29ucy5zZWdtZW50X2JvdW5kYXJ5X21h c2spIHsKPiArCQlwcl9lcnIoIkRldjogJXMncyBjb25zdHJhaW50cyBkb24ndCBtYXRjaFxuIiwg ZGV2X25hbWUoZGV2KSk7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJKmNhbGNf Y29ucyA9IGNvbnM7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gKy8qCj4gKyAqIHJlY2Fs Y19jb25zdHJhaW50cyAtIHJlY2FsY3VsYXRlcyBjb25zdHJhaW50cyBmb3IgYWxsIGF0dGFjaGVk IGRldmljZXM7Cj4gKyAqICB1c2VmdWwgZm9yIGRldGFjaCgpIHJlY2FsY3VsYXRpb24sIGFuZCBm b3IgZG1hX2J1Zl9yZWNhbGNfY29uc3RyYWludHMoKQo+ICsgKiAgaGVscGVyLgo+ICsgKiAgUmV0 dXJucyByZWNhbGN1bGF0ZWQgY29uc3RyYWludHMgaW4gcmVjYWxjX2NvbnMsIG9yIGVycm9yIGlu IHRoZSB1bmxpa2VseQo+ICsgKiAgY2FzZSB3aGVuIGNvbnN0cmFpbnRzIG9mIGF0dGFjaGVkIGRl dmljZXMgbWlnaHQgaGF2ZSBjaGFuZ2VkLgo+ICsgKi8KPiArc3RhdGljIGludCByZWNhbGNfY29u c3RyYWludHMoc3RydWN0IGRtYV9idWYgKmRtYWJ1ZiwKPiArCQkJICAgICAgc3RydWN0IGRldmlj ZV9kbWFfcGFyYW1ldGVycyAqcmVjYWxjX2NvbnMpCj4gK3sKPiArCXN0cnVjdCBkZXZpY2VfZG1h X3BhcmFtZXRlcnMgY2FsY19jb25zOwo+ICsJc3RydWN0IGRtYV9idWZfYXR0YWNobWVudCAqYXR0 YWNoOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJaW5pdF9jb25zdHJhaW50cygmY2FsY19jb25z KTsKPiArCj4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGF0dGFjaCwgJmRtYWJ1Zi0+YXR0YWNobWVu dHMsIG5vZGUpIHsKPiArCQlyZXQgPSBjYWxjX2NvbnN0cmFpbnRzKGF0dGFjaC0+ZGV2LCAmY2Fs Y19jb25zKTsKPiArCQlpZiAocmV0KQo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJKnJlY2Fs Y19jb25zID0gY2FsY19jb25zOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gIC8qKgo+ICAgKiBk bWFfYnVmX2V4cG9ydF9uYW1lZCAtIENyZWF0ZXMgYSBuZXcgZG1hX2J1ZiwgYW5kIGFzc29jaWF0 ZXMgYW4gYW5vbiBmaWxlCj4gICAqIHdpdGggdGhpcyBidWZmZXIsIHNvIGl0IGNhbiBiZSBleHBv cnRlZC4KPiBAQCAtMzEzLDYgKzM3Myw5IEBAIHN0cnVjdCBkbWFfYnVmICpkbWFfYnVmX2V4cG9y dF9uYW1lZCh2b2lkICpwcml2LCBjb25zdCBzdHJ1Y3QgZG1hX2J1Zl9vcHMgKm9wcywKPiAgCWRt YWJ1Zi0+b3BzID0gb3BzOwo+ICAJZG1hYnVmLT5zaXplID0gc2l6ZTsKPiAgCWRtYWJ1Zi0+ZXhw X25hbWUgPSBleHBfbmFtZTsKPiArCj4gKwlpbml0X2NvbnN0cmFpbnRzKCZkbWFidWYtPmNvbnN0 cmFpbnRzKTsKPiArCj4gIAlpbml0X3dhaXRxdWV1ZV9oZWFkKCZkbWFidWYtPnBvbGwpOwo+ICAJ ZG1hYnVmLT5jYl9leGNsLnBvbGwgPSBkbWFidWYtPmNiX3NoYXJlZC5wb2xsID0gJmRtYWJ1Zi0+ cG9sbDsKPiAgCWRtYWJ1Zi0+Y2JfZXhjbC5hY3RpdmUgPSBkbWFidWYtPmNiX3NoYXJlZC5hY3Rp dmUgPSAwOwo+IEBAIC00MjIsNyArNDg1LDcgQEAgc3RydWN0IGRtYV9idWZfYXR0YWNobWVudCAq ZG1hX2J1Zl9hdHRhY2goc3RydWN0IGRtYV9idWYgKmRtYWJ1ZiwKPiAgCQkJCQkgIHN0cnVjdCBk ZXZpY2UgKmRldikKPiAgewo+ICAJc3RydWN0IGRtYV9idWZfYXR0YWNobWVudCAqYXR0YWNoOwo+ IC0JaW50IHJldDsKPiArCWludCByZXQgPSAwOwo+ICAKPiAgCWlmIChXQVJOX09OKCFkbWFidWYg fHwgIWRldikpCj4gIAkJcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7Cj4gQEAgLTQzNiw2ICs0OTks OSBAQCBzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICpkbWFfYnVmX2F0dGFjaChzdHJ1Y3QgZG1h X2J1ZiAqZG1hYnVmLAo+ICAKPiAgCW11dGV4X2xvY2soJmRtYWJ1Zi0+bG9jayk7Cj4gIAo+ICsJ aWYgKGNhbGNfY29uc3RyYWludHMoZGV2LCAmZG1hYnVmLT5jb25zdHJhaW50cykpCj4gKwkJZ290 byBlcnJfY29uc3RyYWludHM7Cj4gKwo+ICAJaWYgKGRtYWJ1Zi0+b3BzLT5hdHRhY2gpIHsKPiAg CQlyZXQgPSBkbWFidWYtPm9wcy0+YXR0YWNoKGRtYWJ1ZiwgZGV2LCBhdHRhY2gpOwo+ICAJCWlm IChyZXQpCj4gQEAgLTQ0OCw2ICs1MTQsNyBAQCBzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICpk bWFfYnVmX2F0dGFjaChzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmLAo+ICAKPiAgZXJyX2F0dGFjaDoK PiAgCWtmcmVlKGF0dGFjaCk7Cj4gK2Vycl9jb25zdHJhaW50czoKPiAgCW11dGV4X3VubG9jaygm ZG1hYnVmLT5sb2NrKTsKPiAgCXJldHVybiBFUlJfUFRSKHJldCk7Cj4gIH0KPiBAQCAtNDcwLDYg KzUzNyw4IEBAIHZvaWQgZG1hX2J1Zl9kZXRhY2goc3RydWN0IGRtYV9idWYgKmRtYWJ1Ziwgc3Ry dWN0IGRtYV9idWZfYXR0YWNobWVudCAqYXR0YWNoKQo+ICAJaWYgKGRtYWJ1Zi0+b3BzLT5kZXRh Y2gpCj4gIAkJZG1hYnVmLT5vcHMtPmRldGFjaChkbWFidWYsIGF0dGFjaCk7Cj4gIAo+ICsJcmVj YWxjX2NvbnN0cmFpbnRzKGRtYWJ1ZiwgJmRtYWJ1Zi0+Y29uc3RyYWludHMpOwo+ICsKPiAgCW11 dGV4X3VubG9jaygmZG1hYnVmLT5sb2NrKTsKPiAgCWtmcmVlKGF0dGFjaCk7Cj4gIH0KPiBAQCAt NzcwLDYgKzgzOSw1NiBAQCB2b2lkIGRtYV9idWZfdnVubWFwKHN0cnVjdCBkbWFfYnVmICpkbWFi dWYsIHZvaWQgKnZhZGRyKQo+ICB9Cj4gIEVYUE9SVF9TWU1CT0xfR1BMKGRtYV9idWZfdnVubWFw KTsKPiAgCj4gKy8qKgo+ICsgKiBkbWFfYnVmX2dldF9jb25zdHJhaW50cyAtIGdldCB0aGUgKmN1 cnJlbnQqIGNvbnN0cmFpbnRzIG9mIHRoZSBkbWFidWYsCj4gKyAqICBhcyBjYWxjdWxhdGVkIGR1 cmluZyBlYWNoIGF0dGFjaCgpOyByZXR1cm5zIGVycm9yIG9uIGludmFsaWQgaW5wdXRzCj4gKyAq Cj4gKyAqIEBkbWFidWY6CQlbaW5dCWJ1ZmZlciB0byBnZXQgY29uc3RyYWludHMgb2YKPiArICog QGNvbnN0cmFpbnRzOglbb3V0XQljdXJyZW50IGNvbnN0cmFpbnRzIGFyZSByZXR1cm5lZCBpbiB0 aGlzCj4gKyAqLwo+ICtpbnQgZG1hX2J1Zl9nZXRfY29uc3RyYWludHMoc3RydWN0IGRtYV9idWYg KmRtYWJ1ZiwKPiArCQkJICAgIHN0cnVjdCBkZXZpY2VfZG1hX3BhcmFtZXRlcnMgKmNvbnN0cmFp bnRzKQo+ICt7Cj4gKwlpZiAoV0FSTl9PTighZG1hYnVmIHx8ICFjb25zdHJhaW50cykpCj4gKwkJ cmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJbXV0ZXhfbG9jaygmZG1hYnVmLT5sb2NrKTsKPiArCSpj b25zdHJhaW50cyA9IGRtYWJ1Zi0+Y29uc3RyYWludHM7Cj4gKwltdXRleF91bmxvY2soJmRtYWJ1 Zi0+bG9jayk7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICtFWFBPUlRfU1lNQk9MX0dQTChkbWFfYnVm X2dldF9jb25zdHJhaW50cyk7Cj4gKwo+ICsvKioKPiArICogZG1hX2J1Zl9yZWNhbGNfY29uc3Ry YWludHMgLSAqcmVjYWxjdWxhdGUqIHRoZSBjb25zdHJhaW50cyBmb3IgdGhlIGJ1ZmZlcgo+ICsg KiAgYWZyZXNoLCBmcm9tIHRoZSBsaXN0IG9mIGN1cnJlbnRseSBhdHRhY2hlZCBkZXZpY2VzOyB0 aGlzIGNvdWxkIGJlIHVzZWZ1bAo+ICsgKiAgY3Jvc3MtY2hlY2sgdGhlIGN1cnJlbnQgY29uc3Ry YWludHMsIGZvciBleHBvcnRlcnMgdGhhdCBtaWdodCB3YW50IHRvIGJlCj4gKyAqICAncGFyYW5v aWQnIGFib3V0IHRoZSBkZXZpY2UgY29uc3RyYWludHMuCj4gKyAqCj4gKyAqICByZXR1cm5zIGVy cm9yIG9uIGludmFsaWQgaW5wdXRzCj4gKyAqCj4gKyAqIEBkbWFidWY6CQlbaW5dCWJ1ZmZlciB0 byBnZXQgY29uc3RyYWludHMgb2YKPiArICogQGNvbnN0cmFpbnRzOglbb3V0XQlyZWNhbGN1bGF0 ZWQgY29uc3RyYWludHMgYXJlIHJldHVybmVkIGluIHRoaXMKPiArICovCj4gK2ludCBkbWFfYnVm X3JlY2FsY19jb25zdHJhaW50cyhzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmLAo+ICsJCQkgICAgc3Ry dWN0IGRldmljZV9kbWFfcGFyYW1ldGVycyAqY29uc3RyYWludHMpCj4gK3sKPiArCXN0cnVjdCBk ZXZpY2VfZG1hX3BhcmFtZXRlcnMgY2FsY19jb25zOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJ aWYgKFdBUk5fT04oIWRtYWJ1ZiB8fCAhY29uc3RyYWludHMpKQo+ICsJCXJldHVybiAtRUlOVkFM Owo+ICsKPiArCW11dGV4X2xvY2soJmRtYWJ1Zi0+bG9jayk7Cj4gKwlyZXQgPSByZWNhbGNfY29u c3RyYWludHMoZG1hYnVmLCAmY2FsY19jb25zKTsKPiArCWlmICghcmV0KQo+ICsJCSpjb25zdHJh aW50cyA9IGNhbGNfY29uczsKPiArCj4gKwltdXRleF91bmxvY2soJmRtYWJ1Zi0+bG9jayk7Cj4g KwlyZXR1cm4gcmV0Owo+ICt9Cj4gK0VYUE9SVF9TWU1CT0xfR1BMKGRtYV9idWZfcmVjYWxjX2Nv bnN0cmFpbnRzKTsKPiArCj4gICNpZmRlZiBDT05GSUdfREVCVUdfRlMKPiAgc3RhdGljIGludCBk bWFfYnVmX2Rlc2NyaWJlKHN0cnVjdCBzZXFfZmlsZSAqcykKPiAgewo+IEBAIC04MDEsNiArOTIw LDExIEBAIHN0YXRpYyBpbnQgZG1hX2J1Zl9kZXNjcmliZShzdHJ1Y3Qgc2VxX2ZpbGUgKnMpCj4g IAkJCQlidWZfb2JqLT5maWxlLT5mX2ZsYWdzLCBidWZfb2JqLT5maWxlLT5mX21vZGUsCj4gIAkJ CQlmaWxlX2NvdW50KGJ1Zl9vYmotPmZpbGUpLAo+ICAJCQkJYnVmX29iai0+ZXhwX25hbWUpOwo+ ICsJCXNlcV9wcmludGYocywgIlx0Q29uc3RyYWludHM6IFNlZyBDb3VudDogJTA4dSwgU2VnIFNp emU6ICUwOHUiLAo+ICsJCQkJYnVmX29iai0+Y29uc3RyYWludHMubWF4X3NlZ21lbnRfY291bnQs Cj4gKwkJCQlidWZfb2JqLT5jb25zdHJhaW50cy5tYXhfc2VnbWVudF9zaXplKTsKPiArCQlzZXFf cHJpbnRmKHMsICIgc2VnIGJvdW5kYXJ5IG1hc2s6ICUwOGx4XG4iLAo+ICsJCQkJYnVmX29iai0+ Y29uc3RyYWludHMuc2VnbWVudF9ib3VuZGFyeV9tYXNrKTsKPiAgCj4gIAkJc2VxX3B1dHMocywg Ilx0QXR0YWNoZWQgRGV2aWNlczpcbiIpOwo+ICAJCWF0dGFjaF9jb3VudCA9IDA7Cj4gZGlmZiAt LWdpdCBhL2luY2x1ZGUvbGludXgvZG1hLWJ1Zi5oIGIvaW5jbHVkZS9saW51eC9kbWEtYnVmLmgK PiBpbmRleCA2OTRlMWZlMWM0YjQuLjQ4OWFkOWIyZTVhZSAxMDA2NDQKPiAtLS0gYS9pbmNsdWRl L2xpbnV4L2RtYS1idWYuaAo+ICsrKyBiL2luY2x1ZGUvbGludXgvZG1hLWJ1Zi5oCj4gQEAgLTM0 LDYgKzM0LDcgQEAKPiAgI2luY2x1ZGUgPGxpbnV4L3dhaXQuaD4KPiAgCj4gIHN0cnVjdCBkZXZp Y2U7Cj4gK3N0cnVjdCBkZXZpY2VfZG1hX3BhcmFtZXRlcnM7Cj4gIHN0cnVjdCBkbWFfYnVmOwo+ ICBzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50Owo+ICAKPiBAQCAtMTE2LDYgKzExNyw3IEBAIHN0 cnVjdCBkbWFfYnVmX29wcyB7Cj4gICAqIEBvcHM6IGRtYV9idWZfb3BzIGFzc29jaWF0ZWQgd2l0 aCB0aGlzIGJ1ZmZlciBvYmplY3QuCj4gICAqIEBleHBfbmFtZTogbmFtZSBvZiB0aGUgZXhwb3J0 ZXI7IHVzZWZ1bCBmb3IgZGVidWdnaW5nLgo+ICAgKiBAbGlzdF9ub2RlOiBub2RlIGZvciBkbWFf YnVmIGFjY291bnRpbmcgYW5kIGRlYnVnZ2luZy4KPiArICogQGNvbnN0cmFpbnRzOiBjYWxjdWxh dGVkIGNvbnN0cmFpbnRzIG9mIGF0dGFjaGVkIGRldmljZXMuCj4gICAqIEBwcml2OiBleHBvcnRl ciBzcGVjaWZpYyBwcml2YXRlIGRhdGEgZm9yIHRoaXMgYnVmZmVyIG9iamVjdC4KPiAgICogQHJl c3Y6IHJlc2VydmF0aW9uIG9iamVjdCBsaW5rZWQgdG8gdGhpcyBkbWEtYnVmCj4gICAqLwo+IEBA IC0xMzAsNiArMTMyLDcgQEAgc3RydWN0IGRtYV9idWYgewo+ICAJdm9pZCAqdm1hcF9wdHI7Cj4g IAljb25zdCBjaGFyICpleHBfbmFtZTsKPiAgCXN0cnVjdCBsaXN0X2hlYWQgbGlzdF9ub2RlOwo+ ICsJc3RydWN0IGRldmljZV9kbWFfcGFyYW1ldGVycyBjb25zdHJhaW50czsKPiAgCXZvaWQgKnBy aXY7Cj4gIAlzdHJ1Y3QgcmVzZXJ2YXRpb25fb2JqZWN0ICpyZXN2Owo+ICAKPiBAQCAtMjExLDQg KzIxNCw4IEBAIHZvaWQgKmRtYV9idWZfdm1hcChzdHJ1Y3QgZG1hX2J1ZiAqKTsKPiAgdm9pZCBk bWFfYnVmX3Z1bm1hcChzdHJ1Y3QgZG1hX2J1ZiAqLCB2b2lkICp2YWRkcik7Cj4gIGludCBkbWFf YnVmX2RlYnVnZnNfY3JlYXRlX2ZpbGUoY29uc3QgY2hhciAqbmFtZSwKPiAgCQkJCWludCAoKndy aXRlKShzdHJ1Y3Qgc2VxX2ZpbGUgKikpOwo+ICsKPiAraW50IGRtYV9idWZfZ2V0X2NvbnN0cmFp bnRzKHN0cnVjdCBkbWFfYnVmICosIHN0cnVjdCBkZXZpY2VfZG1hX3BhcmFtZXRlcnMgKik7Cj4g K2ludCBkbWFfYnVmX3JlY2FsY19jb25zdHJhaW50cyhzdHJ1Y3QgZG1hX2J1ZiAqLAo+ICsJCQkJ CXN0cnVjdCBkZXZpY2VfZG1hX3BhcmFtZXRlcnMgKik7Cj4gICNlbmRpZiAvKiBfX0RNQV9CVUZf SF9fICovCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpk cmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0 cDovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAo=