linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] staging: kpc2000: kpc_dma: Few clean up and Convert to pin_user_pages()
@ 2020-06-17  2:27 Souptick Joarder
  2020-06-17  2:27 ` [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages Souptick Joarder
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17  2:27 UTC (permalink / raw)
  To: gregkh, jane.pnx9, pakki001, ldufour, harshjain32, simon, walken
  Cc: devel, linux-kernel, Souptick Joarder

This series contains few clean up, minor bug fixes and
Convert get_user_pages() to pin_user_pages().

I'm compile tested this, but unable to run-time test,
so any testing help is much appriciated.

Souptick Joarder (4):
  staging: kpc2000: Unpin partial pinned pages
  staging: kpc2000: kpc_dma: Convert set_page_dirty() -->    
    set_page_dirty_lock()
  staging: kpc2000: kpc_dma: Convert get_user_pages() -->
    pin_user_pages()
  staging: kpc2000: kpc_dma: Remove excess goto statement

 drivers/staging/kpc2000/kpc_dma/fileops.c | 33 ++++++++++++++-----------------
 1 file changed, 15 insertions(+), 18 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages
  2020-06-17  2:27 [PATCH 0/4] staging: kpc2000: kpc_dma: Few clean up and Convert to pin_user_pages() Souptick Joarder
@ 2020-06-17  2:27 ` Souptick Joarder
  2020-06-17 11:13   ` Dan Carpenter
  2020-06-17  2:27 ` [PATCH 2/4] staging: kpc2000: kpc_dma: Convert set_page_dirty() --> set_page_dirty_lock() Souptick Joarder
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17  2:27 UTC (permalink / raw)
  To: gregkh, jane.pnx9, pakki001, ldufour, harshjain32, simon, walken
  Cc: devel, linux-kernel, Souptick Joarder, John Hubbard,
	Bharath Vedartham, Dan Carpenter

There is a bug, when get_user_pages() failed but partially pinned
pages are not unpinned. Fixed it.

Also, int is more appropriate type for rv. Changed it.

Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Bharath Vedartham <linux.bhar@gmail.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
---
 drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
index 8975346..b136353 100644
--- a/drivers/staging/kpc2000/kpc_dma/fileops.c
+++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
@@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 			    unsigned long iov_base, size_t iov_len)
 {
 	unsigned int i = 0;
-	long rv = 0;
+	int rv = 0;
 	struct kpc_dma_device *ldev;
 	struct aio_cb_data *acd;
 	DECLARE_COMPLETION_ONSTACK(done);
@@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 		put_page(acd->user_pages[i]);
 
  err_get_user_pages:
+	if (rv > 0) {
+		for (i = 0; i < rv; i++)
+			put_pages(acd->user_pages[i])
+	}
 	kfree(acd->user_pages);
  err_alloc_userpages:
 	kfree(acd);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/4] staging: kpc2000: kpc_dma: Convert set_page_dirty() --> set_page_dirty_lock()
  2020-06-17  2:27 [PATCH 0/4] staging: kpc2000: kpc_dma: Few clean up and Convert to pin_user_pages() Souptick Joarder
  2020-06-17  2:27 ` [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages Souptick Joarder
@ 2020-06-17  2:27 ` Souptick Joarder
  2020-06-27 17:51   ` Souptick Joarder
  2020-06-17  2:27 ` [PATCH 3/4] staging: kpc2000: kpc_dma: Convert get_user_pages() --> pin_user_pages() Souptick Joarder
  2020-06-17  2:27 ` [PATCH 4/4] staging: kpc2000: kpc_dma: Remove excess goto statement Souptick Joarder
  3 siblings, 1 reply; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17  2:27 UTC (permalink / raw)
  To: gregkh, jane.pnx9, pakki001, ldufour, harshjain32, simon, walken
  Cc: devel, linux-kernel, Souptick Joarder, Dan Carpenter, Bharath Vedartham

First, convert set_page_dirty() to set_page_dirty_lock()

Second, there is an interval in there after set_page_dirty() and
before put_page(), in which the device could be running and setting
pages dirty. Moving set_page_dirty_lock() after dma_unmap_sg().

Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Suggested-by: John Hubbard <jhubbard@nvidia.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Bharath Vedartham <linux.bhar@gmail.com>
---
 drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
index b136353..bcce86c 100644
--- a/drivers/staging/kpc2000/kpc_dma/fileops.c
+++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
@@ -214,13 +214,13 @@ void  transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags)
 	BUG_ON(!acd->ldev);
 	BUG_ON(!acd->ldev->pldev);
 
+	dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir);
+
 	for (i = 0 ; i < acd->page_count ; i++) {
 		if (!PageReserved(acd->user_pages[i]))
-			set_page_dirty(acd->user_pages[i]);
+			set_page_dirty_lock(acd->user_pages[i]);
 	}
 
-	dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir);
-
 	for (i = 0 ; i < acd->page_count ; i++)
 		put_page(acd->user_pages[i]);
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/4] staging: kpc2000: kpc_dma: Convert get_user_pages() --> pin_user_pages()
  2020-06-17  2:27 [PATCH 0/4] staging: kpc2000: kpc_dma: Few clean up and Convert to pin_user_pages() Souptick Joarder
  2020-06-17  2:27 ` [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages Souptick Joarder
  2020-06-17  2:27 ` [PATCH 2/4] staging: kpc2000: kpc_dma: Convert set_page_dirty() --> set_page_dirty_lock() Souptick Joarder
@ 2020-06-17  2:27 ` Souptick Joarder
  2020-06-17  2:27 ` [PATCH 4/4] staging: kpc2000: kpc_dma: Remove excess goto statement Souptick Joarder
  3 siblings, 0 replies; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17  2:27 UTC (permalink / raw)
  To: gregkh, jane.pnx9, pakki001, ldufour, harshjain32, simon, walken
  Cc: devel, linux-kernel, Souptick Joarder, John Hubbard,
	Bharath Vedartham, Dan Carpenter

In 2019, we introduced pin_user_pages*() and now we are converting
get_user_pages*() to the new API as appropriate. [1] & [2] could
be referred for more information.

[1] Documentation/core-api/pin_user_pages.rst

[2] "Explicit pinning of user-space pages":
        https://lwn.net/Articles/807108/

Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Bharath Vedartham <linux.bhar@gmail.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
---
 drivers/staging/kpc2000/kpc_dma/fileops.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
index bcce86c..1f5ab81 100644
--- a/drivers/staging/kpc2000/kpc_dma/fileops.c
+++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
@@ -76,10 +76,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 
 	// Lock the user buffer pages in memory, and hold on to the page pointers (for the sglist)
 	mmap_read_lock(current->mm);      /*  get memory map semaphore */
-	rv = get_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE | FOLL_GET, acd->user_pages, NULL);
+	rv = pin_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE, acd->user_pages, NULL);
 	mmap_read_unlock(current->mm);        /*  release the semaphore */
 	if (rv != acd->page_count) {
-		dev_err(&priv->ldev->pldev->dev, "Couldn't get_user_pages (%ld)\n", rv);
+		dev_err(&priv->ldev->pldev->dev, "Couldn't pin_user_pages (%ld)\n", rv);
 		goto err_get_user_pages;
 	}
 
@@ -189,14 +189,11 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 	sg_free_table(&acd->sgt);
  err_dma_map_sg:
  err_alloc_sg_table:
-	for (i = 0 ; i < acd->page_count ; i++)
-		put_page(acd->user_pages[i]);
+	unpin_user_pages(acd->user_pages, acd->page_count);
 
  err_get_user_pages:
-	if (rv > 0) {
-		for (i = 0; i < rv; i++)
-			put_pages(acd->user_pages[i])
-	}
+	if (rv > 0)
+		unpin_user_pages(acd->user_pages, rv);
 	kfree(acd->user_pages);
  err_alloc_userpages:
 	kfree(acd);
@@ -221,8 +218,7 @@ void  transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags)
 			set_page_dirty_lock(acd->user_pages[i]);
 	}
 
-	for (i = 0 ; i < acd->page_count ; i++)
-		put_page(acd->user_pages[i]);
+	unpin_user_pages(acd->user_pages, acd->page_count);
 
 	sg_free_table(&acd->sgt);
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/4] staging: kpc2000: kpc_dma: Remove excess goto statement
  2020-06-17  2:27 [PATCH 0/4] staging: kpc2000: kpc_dma: Few clean up and Convert to pin_user_pages() Souptick Joarder
                   ` (2 preceding siblings ...)
  2020-06-17  2:27 ` [PATCH 3/4] staging: kpc2000: kpc_dma: Convert get_user_pages() --> pin_user_pages() Souptick Joarder
@ 2020-06-17  2:27 ` Souptick Joarder
  3 siblings, 0 replies; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17  2:27 UTC (permalink / raw)
  To: gregkh, jane.pnx9, pakki001, ldufour, harshjain32, simon, walken
  Cc: devel, linux-kernel, Souptick Joarder, Dan Carpenter, John Hubbard

As 3 goto level referring to same common code, those can be
accomodated with a single goto level and renameing it to
unpin_user_pages.

Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: John Hubbard <jhubbard@nvidia.com>
---
 drivers/staging/kpc2000/kpc_dma/fileops.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
index 1f5ab81..b0fcde5 100644
--- a/drivers/staging/kpc2000/kpc_dma/fileops.c
+++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
@@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 			    unsigned long iov_base, size_t iov_len)
 {
 	unsigned int i = 0;
-	int rv = 0;
+	int rv = 0, nr_pages = 0;
 	struct kpc_dma_device *ldev;
 	struct aio_cb_data *acd;
 	DECLARE_COMPLETION_ONSTACK(done);
@@ -79,22 +79,23 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 	rv = pin_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE, acd->user_pages, NULL);
 	mmap_read_unlock(current->mm);        /*  release the semaphore */
 	if (rv != acd->page_count) {
+		nr_pages = rv;
 		dev_err(&priv->ldev->pldev->dev, "Couldn't pin_user_pages (%ld)\n", rv);
-		goto err_get_user_pages;
+		goto unpin_user_pages;
 	}
-
+	nr_pages = acd->page_count;
 	// Allocate and setup the sg_table (scatterlist entries)
 	rv = sg_alloc_table_from_pages(&acd->sgt, acd->user_pages, acd->page_count, iov_base & (PAGE_SIZE - 1), iov_len, GFP_KERNEL);
 	if (rv) {
 		dev_err(&priv->ldev->pldev->dev, "Couldn't alloc sg_table (%ld)\n", rv);
-		goto err_alloc_sg_table;
+		goto unpin_user_pages;
 	}
 
 	// Setup the DMA mapping for all the sg entries
 	acd->mapped_entry_count = dma_map_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir);
 	if (acd->mapped_entry_count <= 0) {
 		dev_err(&priv->ldev->pldev->dev, "Couldn't dma_map_sg (%d)\n", acd->mapped_entry_count);
-		goto err_dma_map_sg;
+		goto unpin_user_pages;
 	}
 
 	// Calculate how many descriptors are actually needed for this transfer.
@@ -187,13 +188,9 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
 	unlock_engine(ldev);
 	dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir);
 	sg_free_table(&acd->sgt);
- err_dma_map_sg:
- err_alloc_sg_table:
-	unpin_user_pages(acd->user_pages, acd->page_count);
-
- err_get_user_pages:
-	if (rv > 0)
-		unpin_user_pages(acd->user_pages, rv);
+ unpin_user_pages:
+	if (nr_pages > 0)
+		unpin_user_pages(acd->user_pages, nr_pages);
 	kfree(acd->user_pages);
  err_alloc_userpages:
 	kfree(acd);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages
  2020-06-17  2:27 ` [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages Souptick Joarder
@ 2020-06-17 11:13   ` Dan Carpenter
  2020-06-17 17:43     ` Souptick Joarder
  0 siblings, 1 reply; 11+ messages in thread
From: Dan Carpenter @ 2020-06-17 11:13 UTC (permalink / raw)
  To: Souptick Joarder
  Cc: gregkh, jane.pnx9, pakki001, ldufour, harshjain32, simon, walken,
	devel, linux-kernel, John Hubbard, Bharath Vedartham

On Wed, Jun 17, 2020 at 07:57:20AM +0530, Souptick Joarder wrote:
> There is a bug, when get_user_pages() failed but partially pinned
> pages are not unpinned. Fixed it.
> 
> Also, int is more appropriate type for rv. Changed it.
> 
> Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
> Cc: John Hubbard <jhubbard@nvidia.com>
> Cc: Bharath Vedartham <linux.bhar@gmail.com>
> Cc: Dan Carpenter <dan.carpenter@oracle.com>
> ---
>  drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
> index 8975346..b136353 100644
> --- a/drivers/staging/kpc2000/kpc_dma/fileops.c
> +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
> @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
>  			    unsigned long iov_base, size_t iov_len)
>  {
>  	unsigned int i = 0;
> -	long rv = 0;
> +	int rv = 0;
>  	struct kpc_dma_device *ldev;
>  	struct aio_cb_data *acd;
>  	DECLARE_COMPLETION_ONSTACK(done);
> @@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
>  		put_page(acd->user_pages[i]);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  
>   err_get_user_pages:
> +	if (rv > 0) {
> +		for (i = 0; i < rv; i++)
> +			put_pages(acd->user_pages[i])
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

> +	}

This isn't a complete fix.  "rv" is the negative error code but here we
are returning a positive value on this path.  Also it's ugly to have
same put_page() loop repeated twice.

It would be better to write it like this:

	rv = get_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE | FOLL_GET, acd->user_pages, NULL);
	mmap_read_unlock(current->mm);        /*  release the semaphore */
	if (rv < 0)
		goto free_pages;
	if (rv != acd->page_count) {
		acd->page_count = rv;
		rv = -EFAULT;
		goto put_pages;
	}

	...

put_pages:
	for (i = 0 ; i < acd->page_count ; i++)
		put_pages(acd->user_pages[i]);
free_pages:
	kfree(acd->user_pages);

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages
  2020-06-17 11:13   ` Dan Carpenter
@ 2020-06-17 17:43     ` Souptick Joarder
  2020-06-17 17:59       ` Dan Carpenter
  0 siblings, 1 reply; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17 17:43 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Greg KH, jane.pnx9, pakki001, ldufour, harshjain32,
	Simon Sandström, Michel Lespinasse,
	open list:ANDROID DRIVERS, linux-kernel, John Hubbard,
	Bharath Vedartham

On Wed, Jun 17, 2020 at 4:43 PM Dan Carpenter <dan.carpenter@oracle.com> wrote:
>
> On Wed, Jun 17, 2020 at 07:57:20AM +0530, Souptick Joarder wrote:
> > There is a bug, when get_user_pages() failed but partially pinned
> > pages are not unpinned. Fixed it.
> >
> > Also, int is more appropriate type for rv. Changed it.
> >
> > Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
> > Cc: John Hubbard <jhubbard@nvidia.com>
> > Cc: Bharath Vedartham <linux.bhar@gmail.com>
> > Cc: Dan Carpenter <dan.carpenter@oracle.com>
> > ---
> >  drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++-
> >  1 file changed, 5 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > index 8975346..b136353 100644
> > --- a/drivers/staging/kpc2000/kpc_dma/fileops.c
> > +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> >                           unsigned long iov_base, size_t iov_len)
> >  {
> >       unsigned int i = 0;
> > -     long rv = 0;
> > +     int rv = 0;
> >       struct kpc_dma_device *ldev;
> >       struct aio_cb_data *acd;
> >       DECLARE_COMPLETION_ONSTACK(done);
> > @@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> >               put_page(acd->user_pages[i]);
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> >   err_get_user_pages:
> > +     if (rv > 0) {
> > +             for (i = 0; i < rv; i++)
> > +                     put_pages(acd->user_pages[i])
>                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> > +     }
>
> This isn't a complete fix.  "rv" is the negative error code but here we
> are returning a positive value on this path.

In case of error of get_user_pages(), it will return -errno, 0 and 3rd one is
(rv > 0 && rv != acd->page_count). When rv is -errno or 0 there is no need
to call put_pages() in error path. But for 3rd case partially mapped pages
need to unpin.

Correct me if I am missing anything.

>Also it's ugly to have
> same put_page() loop repeated twice.

Yes, I agree, but these are intermediate steps. Patch [4/4] of this series
finally did the same.

>
> It would be better to write it like this:
>
>         rv = get_user_pages(iov_base, acd->page_count, FOLL_TOUCH | FOLL_WRITE | FOLL_GET, acd->user_pages, NULL);
>         mmap_read_unlock(current->mm);        /*  release the semaphore */
>         if (rv < 0)
>                 goto free_pages;
>         if (rv != acd->page_count) {
>                 acd->page_count = rv;
>                 rv = -EFAULT;
>                 goto put_pages;
>         }
>
>         ...
>
> put_pages:
>         for (i = 0 ; i < acd->page_count ; i++)
>                 put_pages(acd->user_pages[i]);
> free_pages:
>         kfree(acd->user_pages);
>
> regards,
> dan carpenter
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages
  2020-06-17 17:43     ` Souptick Joarder
@ 2020-06-17 17:59       ` Dan Carpenter
  2020-06-17 19:29         ` Souptick Joarder
  0 siblings, 1 reply; 11+ messages in thread
From: Dan Carpenter @ 2020-06-17 17:59 UTC (permalink / raw)
  To: Souptick Joarder
  Cc: open list:ANDROID DRIVERS, Bharath Vedartham, harshjain32,
	John Hubbard, Greg KH, pakki001, linux-kernel,
	Simon Sandström, ldufour, Michel Lespinasse, jane.pnx9

On Wed, Jun 17, 2020 at 11:13:32PM +0530, Souptick Joarder wrote:
> On Wed, Jun 17, 2020 at 4:43 PM Dan Carpenter <dan.carpenter@oracle.com> wrote:
> >
> > On Wed, Jun 17, 2020 at 07:57:20AM +0530, Souptick Joarder wrote:
> > > There is a bug, when get_user_pages() failed but partially pinned
> > > pages are not unpinned. Fixed it.
> > >
> > > Also, int is more appropriate type for rv. Changed it.
> > >
> > > Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
> > > Cc: John Hubbard <jhubbard@nvidia.com>
> > > Cc: Bharath Vedartham <linux.bhar@gmail.com>
> > > Cc: Dan Carpenter <dan.carpenter@oracle.com>
> > > ---
> > >  drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++-
> > >  1 file changed, 5 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > index 8975346..b136353 100644
> > > --- a/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> > >                           unsigned long iov_base, size_t iov_len)
> > >  {
> > >       unsigned int i = 0;
> > > -     long rv = 0;
> > > +     int rv = 0;
> > >       struct kpc_dma_device *ldev;
> > >       struct aio_cb_data *acd;
> > >       DECLARE_COMPLETION_ONSTACK(done);
> > > @@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> > >               put_page(acd->user_pages[i]);
> >                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > >
> > >   err_get_user_pages:
> > > +     if (rv > 0) {
> > > +             for (i = 0; i < rv; i++)
> > > +                     put_pages(acd->user_pages[i])
> >                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
> > > +     }
> >
> > This isn't a complete fix.  "rv" is the negative error code but here we
> > are returning a positive value on this path.
> 
> In case of error of get_user_pages(), it will return -errno, 0 and 3rd one is
> (rv > 0 && rv != acd->page_count). When rv is -errno or 0 there is no need
> to call put_pages() in error path. But for 3rd case partially mapped pages
> need to unpin.
> 
> Correct me if I am missing anything.
>

   182                  kfree(acd);
   183          }
   184          return rv;
   185  
   186   err_descr_too_many:
   187          unlock_engine(ldev);
   188          dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir);
   189          sg_free_table(&acd->sgt);
   190   err_dma_map_sg:
   191   err_alloc_sg_table:
   192          for (i = 0 ; i < acd->page_count ; i++)
   193                  put_page(acd->user_pages[i]);
   194  
   195   err_get_user_pages:
   196          if (rv > 0) {
                    ^^^^^^
"rv" is positive.

   197                  for (i = 0; i < rv; i++)
   198                          put_pages(acd->user_pages[i])
   199          }
   200          kfree(acd->user_pages);
   201   err_alloc_userpages:
   202          kfree(acd);
   203          dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %ld\n", __func__, rv);
   204          return rv;
                       ^^
"rv" is still positive but it should be -EFAULT.

   205  }

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages
  2020-06-17 17:59       ` Dan Carpenter
@ 2020-06-17 19:29         ` Souptick Joarder
  2020-06-18 10:50           ` Dan Carpenter
  0 siblings, 1 reply; 11+ messages in thread
From: Souptick Joarder @ 2020-06-17 19:29 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: open list:ANDROID DRIVERS, Bharath Vedartham, harshjain32,
	John Hubbard, Greg KH, pakki001, linux-kernel,
	Simon Sandström, ldufour, Michel Lespinasse, jane.pnx9

On Wed, Jun 17, 2020 at 11:29 PM Dan Carpenter <dan.carpenter@oracle.com> wrote:
>
> On Wed, Jun 17, 2020 at 11:13:32PM +0530, Souptick Joarder wrote:
> > On Wed, Jun 17, 2020 at 4:43 PM Dan Carpenter <dan.carpenter@oracle.com> wrote:
> > >
> > > On Wed, Jun 17, 2020 at 07:57:20AM +0530, Souptick Joarder wrote:
> > > > There is a bug, when get_user_pages() failed but partially pinned
> > > > pages are not unpinned. Fixed it.
> > > >
> > > > Also, int is more appropriate type for rv. Changed it.
> > > >
> > > > Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
> > > > Cc: John Hubbard <jhubbard@nvidia.com>
> > > > Cc: Bharath Vedartham <linux.bhar@gmail.com>
> > > > Cc: Dan Carpenter <dan.carpenter@oracle.com>
> > > > ---
> > > >  drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++-
> > > >  1 file changed, 5 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > > index 8975346..b136353 100644
> > > > --- a/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > > +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > > @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> > > >                           unsigned long iov_base, size_t iov_len)
> > > >  {
> > > >       unsigned int i = 0;
> > > > -     long rv = 0;
> > > > +     int rv = 0;
> > > >       struct kpc_dma_device *ldev;
> > > >       struct aio_cb_data *acd;
> > > >       DECLARE_COMPLETION_ONSTACK(done);
> > > > @@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> > > >               put_page(acd->user_pages[i]);
> > >                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > >
> > > >   err_get_user_pages:
> > > > +     if (rv > 0) {
> > > > +             for (i = 0; i < rv; i++)
> > > > +                     put_pages(acd->user_pages[i])
> > >                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > >
> > > > +     }
> > >
> > > This isn't a complete fix.  "rv" is the negative error code but here we
> > > are returning a positive value on this path.
> >
> > In case of error of get_user_pages(), it will return -errno, 0 and 3rd one is
> > (rv > 0 && rv != acd->page_count). When rv is -errno or 0 there is no need
> > to call put_pages() in error path. But for 3rd case partially mapped pages
> > need to unpin.
> >
> > Correct me if I am missing anything.
> >
>
>    182                  kfree(acd);
>    183          }
>    184          return rv;
>    185
>    186   err_descr_too_many:
>    187          unlock_engine(ldev);
>    188          dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir);
>    189          sg_free_table(&acd->sgt);
>    190   err_dma_map_sg:
>    191   err_alloc_sg_table:
>    192          for (i = 0 ; i < acd->page_count ; i++)
>    193                  put_page(acd->user_pages[i]);
>    194
>    195   err_get_user_pages:
>    196          if (rv > 0) {
>                     ^^^^^^
> "rv" is positive.
>
>    197                  for (i = 0; i < rv; i++)
>    198                          put_pages(acd->user_pages[i])
>    199          }
>    200          kfree(acd->user_pages);
>    201   err_alloc_userpages:
>    202          kfree(acd);
>    203          dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %ld\n", __func__, rv);
>    204          return rv;
>                        ^^
> "rv" is still positive but it should be -EFAULT.
>

Ahh,  my mistake. Will correct it in v2.
Do other patches in the series looks good ?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages
  2020-06-17 19:29         ` Souptick Joarder
@ 2020-06-18 10:50           ` Dan Carpenter
  0 siblings, 0 replies; 11+ messages in thread
From: Dan Carpenter @ 2020-06-18 10:50 UTC (permalink / raw)
  To: Souptick Joarder
  Cc: open list:ANDROID DRIVERS, Bharath Vedartham, harshjain32,
	John Hubbard, Greg KH, Simon Sandström, linux-kernel,
	pakki001, ldufour, Michel Lespinasse, jane.pnx9

On Thu, Jun 18, 2020 at 12:59:57AM +0530, Souptick Joarder wrote:
> On Wed, Jun 17, 2020 at 11:29 PM Dan Carpenter <dan.carpenter@oracle.com> wrote:
> >
> > On Wed, Jun 17, 2020 at 11:13:32PM +0530, Souptick Joarder wrote:
> > > On Wed, Jun 17, 2020 at 4:43 PM Dan Carpenter <dan.carpenter@oracle.com> wrote:
> > > >
> > > > On Wed, Jun 17, 2020 at 07:57:20AM +0530, Souptick Joarder wrote:
> > > > > There is a bug, when get_user_pages() failed but partially pinned
> > > > > pages are not unpinned. Fixed it.
> > > > >
> > > > > Also, int is more appropriate type for rv. Changed it.
> > > > >
> > > > > Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
> > > > > Cc: John Hubbard <jhubbard@nvidia.com>
> > > > > Cc: Bharath Vedartham <linux.bhar@gmail.com>
> > > > > Cc: Dan Carpenter <dan.carpenter@oracle.com>
> > > > > ---
> > > > >  drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++++-
> > > > >  1 file changed, 5 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > > > index 8975346..b136353 100644
> > > > > --- a/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > > > +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
> > > > > @@ -35,7 +35,7 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> > > > >                           unsigned long iov_base, size_t iov_len)
> > > > >  {
> > > > >       unsigned int i = 0;
> > > > > -     long rv = 0;
> > > > > +     int rv = 0;
> > > > >       struct kpc_dma_device *ldev;
> > > > >       struct aio_cb_data *acd;
> > > > >       DECLARE_COMPLETION_ONSTACK(done);
> > > > > @@ -193,6 +193,10 @@ static int kpc_dma_transfer(struct dev_private_data *priv,
> > > > >               put_page(acd->user_pages[i]);
> > > >                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > > >
> > > > >   err_get_user_pages:
> > > > > +     if (rv > 0) {
> > > > > +             for (i = 0; i < rv; i++)
> > > > > +                     put_pages(acd->user_pages[i])
> > > >                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > >
> > > > > +     }
> > > >
> > > > This isn't a complete fix.  "rv" is the negative error code but here we
> > > > are returning a positive value on this path.
> > >
> > > In case of error of get_user_pages(), it will return -errno, 0 and 3rd one is
> > > (rv > 0 && rv != acd->page_count). When rv is -errno or 0 there is no need
> > > to call put_pages() in error path. But for 3rd case partially mapped pages
> > > need to unpin.
> > >
> > > Correct me if I am missing anything.
> > >
> >
> >    182                  kfree(acd);
> >    183          }
> >    184          return rv;
> >    185
> >    186   err_descr_too_many:
> >    187          unlock_engine(ldev);
> >    188          dma_unmap_sg(&ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, ldev->dir);
> >    189          sg_free_table(&acd->sgt);
> >    190   err_dma_map_sg:
> >    191   err_alloc_sg_table:
> >    192          for (i = 0 ; i < acd->page_count ; i++)
> >    193                  put_page(acd->user_pages[i]);
> >    194
> >    195   err_get_user_pages:
> >    196          if (rv > 0) {
> >                     ^^^^^^
> > "rv" is positive.
> >
> >    197                  for (i = 0; i < rv; i++)
> >    198                          put_pages(acd->user_pages[i])
> >    199          }
> >    200          kfree(acd->user_pages);
> >    201   err_alloc_userpages:
> >    202          kfree(acd);
> >    203          dev_dbg(&priv->ldev->pldev->dev, "%s returning with error %ld\n", __func__, rv);
> >    204          return rv;
> >                        ^^
> > "rv" is still positive but it should be -EFAULT.
> >
> 
> Ahh,  my mistake. Will correct it in v2.
> Do other patches in the series looks good ?

The others will have to be re-worked if you change patch 1/4, especially
patch 4/4.  But otherwise it seems okay with me.

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/4] staging: kpc2000: kpc_dma: Convert set_page_dirty() --> set_page_dirty_lock()
  2020-06-17  2:27 ` [PATCH 2/4] staging: kpc2000: kpc_dma: Convert set_page_dirty() --> set_page_dirty_lock() Souptick Joarder
@ 2020-06-27 17:51   ` Souptick Joarder
  0 siblings, 0 replies; 11+ messages in thread
From: Souptick Joarder @ 2020-06-27 17:51 UTC (permalink / raw)
  To: Greg KH, jane.pnx9, pakki001, ldufour, harshjain32,
	Simon Sandström, Michel Lespinasse
  Cc: open list:ANDROID DRIVERS, linux-kernel, Dan Carpenter,
	Bharath Vedartham

On Wed, Jun 17, 2020 at 7:50 AM Souptick Joarder <jrdr.linux@gmail.com> wrote:
>
> First, convert set_page_dirty() to set_page_dirty_lock()
>
> Second, there is an interval in there after set_page_dirty() and
> before put_page(), in which the device could be running and setting
> pages dirty. Moving set_page_dirty_lock() after dma_unmap_sg().
>
> Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com>
> Suggested-by: John Hubbard <jhubbard@nvidia.com>
> Cc: Dan Carpenter <dan.carpenter@oracle.com>
> Cc: Bharath Vedartham <linux.bhar@gmail.com>
> ---
>  drivers/staging/kpc2000/kpc_dma/fileops.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/staging/kpc2000/kpc_dma/fileops.c b/drivers/staging/kpc2000/kpc_dma/fileops.c
> index b136353..bcce86c 100644
> --- a/drivers/staging/kpc2000/kpc_dma/fileops.c
> +++ b/drivers/staging/kpc2000/kpc_dma/fileops.c
> @@ -214,13 +214,13 @@ void  transfer_complete_cb(struct aio_cb_data *acd, size_t xfr_count, u32 flags)
>         BUG_ON(!acd->ldev);
>         BUG_ON(!acd->ldev->pldev);
>
> +       dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir);
> +
>         for (i = 0 ; i < acd->page_count ; i++) {
>                 if (!PageReserved(acd->user_pages[i]))

Question -> is PageReserved() used with specific purpose not PageDirty() ??

> -                       set_page_dirty(acd->user_pages[i]);
> +                       set_page_dirty_lock(acd->user_pages[i]);
>         }
>
> -       dma_unmap_sg(&acd->ldev->pldev->dev, acd->sgt.sgl, acd->sgt.nents, acd->ldev->dir);
> -
>         for (i = 0 ; i < acd->page_count ; i++)
>                 put_page(acd->user_pages[i]);
>
> --
> 1.9.1
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-06-27 17:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-17  2:27 [PATCH 0/4] staging: kpc2000: kpc_dma: Few clean up and Convert to pin_user_pages() Souptick Joarder
2020-06-17  2:27 ` [PATCH 1/4] staging: kpc2000: Unpin partial pinned pages Souptick Joarder
2020-06-17 11:13   ` Dan Carpenter
2020-06-17 17:43     ` Souptick Joarder
2020-06-17 17:59       ` Dan Carpenter
2020-06-17 19:29         ` Souptick Joarder
2020-06-18 10:50           ` Dan Carpenter
2020-06-17  2:27 ` [PATCH 2/4] staging: kpc2000: kpc_dma: Convert set_page_dirty() --> set_page_dirty_lock() Souptick Joarder
2020-06-27 17:51   ` Souptick Joarder
2020-06-17  2:27 ` [PATCH 3/4] staging: kpc2000: kpc_dma: Convert get_user_pages() --> pin_user_pages() Souptick Joarder
2020-06-17  2:27 ` [PATCH 4/4] staging: kpc2000: kpc_dma: Remove excess goto statement Souptick Joarder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).