mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Michael Zoran <mzoran@crowfest.net>
To: Eric Anholt <eric@anholt.net>, gregkh@linuxfoundation.org
Cc: daniels@collabora.com, noralf@tronnes.org, popcornmix@gmail.com,
	devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] staging: vc04_services: Replace dmac_map_area with dmac_map_sg
Date: Tue, 25 Oct 2016 08:00:43 -0700	[thread overview]
Message-ID: <1477407643.4618.3.camel@crowfest.net> (raw)
In-Reply-To: <878ttdslfb.fsf@eliezer.anholt.net>

On Mon, 2016-10-24 at 10:31 -0700, Eric Anholt wrote:
> mzoran@crowfest.net writes:
> 
> >  */
> >  
> >  static int
> >  create_pagelist(char __user *buf, size_t count, unsigned short
> > type,
> > -	struct task_struct *task, PAGELIST_T ** ppagelist)
> > +		struct task_struct *task, PAGELIST_T **ppagelist,
> > +		dma_addr_t *dma_addr)
> >  {
> >  	PAGELIST_T *pagelist;
> >  	struct page **pages;
> > -	unsigned long *addrs;
> > -	unsigned int num_pages, offset, i;
> > -	char *addr, *base_addr, *next_addr;
> > -	int run, addridx, actual_pages;
> > +	u32 *addrs;
> > +	unsigned int num_pages, offset, i, j, k;
> > +	int actual_pages;
> >          unsigned long *need_release;
> > +	size_t pagelist_size;
> > +	struct scatterlist *scatterlist;
> > +	int dma_buffers;
> > +	int dir;
> >  
> > -	offset = (unsigned int)buf & (PAGE_SIZE - 1);
> > +	offset = ((unsigned int)(unsigned long)buf & (PAGE_SIZE -
> > 1));
> >  	num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE;
> >  
> > +	pagelist_size = sizeof(PAGELIST_T) +
> > +			(num_pages * sizeof(unsigned long)) +
> > +			sizeof(unsigned long) +
> > +			(num_pages * sizeof(pages[0]) +
> > +			(num_pages * sizeof(struct scatterlist)));
> > +
> >  	*ppagelist = NULL;
> >  
> > +	dir = (type == PAGELIST_WRITE) ? DMA_TO_DEVICE :
> > DMA_FROM_DEVICE;
> > +
> >  	/* Allocate enough storage to hold the page pointers and
> > the page
> >  	** list
> >  	*/
> > -	pagelist = kmalloc(sizeof(PAGELIST_T) +
> > -                           (num_pages * sizeof(unsigned long)) +
> > -                           sizeof(unsigned long) +
> > -                           (num_pages * sizeof(pages[0])),
> > -                           GFP_KERNEL);
> > +	pagelist = dma_zalloc_coherent(g_dev,
> > +				       pagelist_size,
> > +				       dma_addr,
> > +				       GFP_KERNEL);
> >  
> >  	vchiq_log_trace(vchiq_arm_log_level, "create_pagelist -
> > %pK",
> >  			pagelist);
> > @@ -394,10 +399,9 @@ create_pagelist(char __user *buf, size_t
> > count, unsigned short type,
> >  	addrs = pagelist->addrs;
> >          need_release = (unsigned long *)(addrs + num_pages);
> >  	pages = (struct page **)(addrs + num_pages + 1);
> > +	scatterlist = (struct scatterlist *)(pages + num_pages);
> >  
> >  	if (is_vmalloc_addr(buf)) {
> > -		int dir = (type == PAGELIST_WRITE) ?
> > -			DMA_TO_DEVICE : DMA_FROM_DEVICE;
> >  		unsigned long length = count;
> >  		unsigned int off = offset;
> >  
> > @@ -410,7 +414,6 @@ create_pagelist(char __user *buf, size_t count,
> > unsigned short type,
> >  			if (bytes > length)
> >  				bytes = length;
> >  			pages[actual_pages] = pg;
> > -			dmac_map_area(page_address(pg) + off,
> > bytes, dir);
> >  			length -= bytes;
> >  			off = 0;
> >  		}
> > @@ -438,7 +441,8 @@ create_pagelist(char __user *buf, size_t count,
> > unsigned short type,
> >  				actual_pages--;
> >  				put_page(pages[actual_pages]);
> >  			}
> > -			kfree(pagelist);
> > +			dma_free_coherent(g_dev, pagelist_size,
> > +					  pagelist, *dma_addr);
> >  			if (actual_pages == 0)
> >  				actual_pages = -ENOMEM;
> >  			return actual_pages;
> > @@ -450,29 +454,38 @@ create_pagelist(char __user *buf, size_t
> > count, unsigned short type,
> >  	pagelist->type = type;
> >  	pagelist->offset = offset;
> >  
> > -	/* Group the pages into runs of contiguous pages */
> > -
> > -	base_addr = VCHIQ_ARM_ADDRESS(page_address(pages[0]));
> > -	next_addr = base_addr + PAGE_SIZE;
> > -	addridx = 0;
> > -	run = 0;
> > -
> > -	for (i = 1; i < num_pages; i++) {
> > -		addr = VCHIQ_ARM_ADDRESS(page_address(pages[i]));
> > -		if ((addr == next_addr) && (run < (PAGE_SIZE -
> > 1))) {
> > -			next_addr += PAGE_SIZE;
> > -			run++;
> > -		} else {
> > -			addrs[addridx] = (unsigned long)base_addr
> > + run;
> > -			addridx++;
> > -			base_addr = addr;
> > -			next_addr = addr + PAGE_SIZE;
> > -			run = 0;
> > -		}
> > +	for (i = 0; i < num_pages; i++)
> > +		sg_set_page(scatterlist + i, pages[i], PAGE_SIZE,
> > 0);
> > +
> > +	dma_buffers = dma_map_sg(g_dev,
> > +				 scatterlist,
> > +				 num_pages,
> > +				 dir);
> > +
> > +	if (dma_buffers == 0) {
> > +		dma_free_coherent(g_dev, pagelist_size,
> > +				  pagelist, *dma_addr);
> > +
> > +		return -EINTR;
> >  	}
> >  
> > -	addrs[addridx] = (unsigned long)base_addr + run;
> > -	addridx++;
> > +	k = 0;
> > +	for (i = 0; i < dma_buffers;) {
> > +		u32 section_length = 0;
> > +
> > +		for (j = i + 1; j < dma_buffers; j++) {
> > +			if (sg_dma_address(scatterlist + j) !=
> > +			    sg_dma_address(scatterlist + j - 1) +
> > PAGE_SIZE) {
> > +				break;
> > +			}
> > +			section_length++;
> > +		}
> > +
> > +		addrs[k] = (u32)sg_dma_address(scatterlist + i) |
> > +				section_length;
> 
> It looks like scatterlist may not be just an array, so I think this
> whole loop wants to be something like:
> 
> for_each_sg(scatterlist, sg, num_pages, i) {
> 	u32 len = sg_dma_len(sg);
>         u32 addr = sg_dma_address(sg);
> 
>         if (k > 0 && addrs[k - 1] & PAGE_MASK +
>             (addrs[k - 1] & ~PAGE_MASK) << PAGE_SHIFT) == addr) {
>         	addrs[k - 1] += len;
>         } else {
>         	addrs[k++] = addr | len;
>         }
> }
> 
> Note the use of sg_dma_len(), since sg entries may be more than one
> page.  I don't think any merging is actually happening on our
> platform
> currently, thus why I left the inner loop.
> 
> Thanks for taking on doing this conversion!  This code's going to be
> so
> much nicer when you're done.

Thanks for looking at this.  

While I understand the use of sg_dma_len, I don't understand totally
the need for "for_each_sg". The scatterlist can be part of a scatter
table with all kinds of complex chaining, but in this case it is
directly allocated as an array at the top of the function.

Also note that the addrs[] list is passed to the firmware and it
requires all the items of the list be paged aligned and be a multiple
of the page size.  So I'm also a bit confused about the need for
handling scatterlists that are not page aligned or a multiple of pages.



 

  reply	other threads:[~2016-10-25 15:10 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-24  5:29 mzoran
2016-10-24 13:24 ` Greg KH
2016-10-24 14:01   ` Michael Zoran
2016-10-24 16:56   ` Eric Anholt
2016-10-24 17:31 ` Eric Anholt
2016-10-25 15:00   ` Michael Zoran [this message]
2016-10-25 15:07     ` Michael Zoran
2016-10-25 16:16       ` Eric Anholt
2016-10-25 16:30         ` Michael Zoran

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1477407643.4618.3.camel@crowfest.net \
    --to=mzoran@crowfest.net \
    --cc=daniels@collabora.com \
    --cc=devel@driverdev.osuosl.org \
    --cc=eric@anholt.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=noralf@tronnes.org \
    --cc=popcornmix@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®