Re: [PATCH v2 4/4] media: pxa_camera: conversion to dmaengine

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Guennadi Liakhovetski <g.liakhovetski@xxxxxx> writes:

> Hi Robert,
>
> On Sun, 19 Jul 2015, Robert Jarzmik wrote:
> In principle, yes, it doesn't look all that horrible to me. You first 
> split the global SG list into up to 3 per-channel ones, then you 
> initialise your channels, what's wrong with that? Just have to add some 
> polish to it here and there... This is a preliminary review, I'll do a 
> proper one, once you fix these and send me anew version, not based on top 
> of patch 4/4.
Ok.
>> +struct sg_splitter {
>> +	struct scatterlist *in_sg0;
>> +	int nents;
>> +	off_t skip_sg0;
>> +	size_t len_last_sg;
>> +	struct scatterlist *out_sg;
>> +};
>> +
>> +static struct sg_splitter *
>> +sg_calculate_split(struct scatterlist *in, off_t skip,
>
> You don't need "skip," you only call this function once with skip == 0.
In the specific pxa_camera case, that's true.

But I made this code for the broader case, where :
 - skip != 0 is possible
 - the sum of sizes is smaller that total sg span

My goal is after this submission to try to move this code to the more generic
lib/sglist.c, hence the genericity.

> Besides I usually prefer all the keywords before the function name, the 
> function name, the opening parenthesis and at least the first argument on 
> the same line. So far pxa_camera.c follows this, let's keep it this way. 
> It makes grepping for functions easier. And no, I don't care about 80 
> chars...
As you wish.

>> +	int i, nents;
>> +	size_t size, len;
>> +	struct sg_splitter *splitters, *curr;
>> +	struct scatterlist *sg;
>> +
>> +	splitters = kcalloc(nb_splits, sizeof(*splitters), gfp_mask);
>
> This is an array of at most 3 elements, 20 bytes each. I'd just allocate 
> it on stack in the calling function and avoid this kcalloc(). Then you can 
> make this function return the total number of sg elements, which is 
> actually at most original number of elements + 2, right? Then you can use 
> that total number to allocate all new sg elements in one go to reduce the 
> number of allocations.

You think pxa_camera specific, I think sglist generic. I think I should try to
submit the generic sglist code first, if I get turned down, specialize the code
for pxa_camera, don't you think ?

> I would put these in initialisation:
>
> +	int i, nents = 0;
> +	size_t size = sizes[0], len;
Ok.
>> +	size = *sizes;
>> +	curr = splitters;
>> +	for_each_sg(in, sg, sg_nents(in), i) {
>> +		if (skip > sg_dma_len(sg)) {
>> +			skip -= sg_dma_len(sg);
>> +			continue;
>> +		}
>> +		len = min_t(size_t, size, sg_dma_len(sg) - skip);
>> +		if (!curr->in_sg0) {
>> +			curr->in_sg0 = sg;
>> +			curr->skip_sg0 = sg_dma_len(sg) - len;
>>  		}
>> -		if (xfer_len > 0) {
>> -			(*new_sg_len)++;
>> -			remain -= xfer_len;
>> +		size -= len;
>> +		nents++;
>> +		if (!size) {
>> +			curr->nents = nents;
>> +			curr->len_last_sg = len;
>> +			nents = 0;
>> +			size = *(++sizes);
>> +
>> +			if (!--nb_splits)
>> +				break;
>
> This break won't be needed, because:
It is needed (in the generic case) if I choose to split in 3 4k pages an sg of
4 pages. In that case, without this break, the for_each_sg() loop will continue,
and curr will be out of bounds.
>
>> +
>> +			if (len < curr->len_last_sg) {
>
> How is this possible? You just did
>
> +			curr->len_last_sg = len;
Ah yes, it's indeed wrong.
This test was to take care of the case when an sg is split as :
 - partly as the last sg entry of splitters[n]->in_sg0
 - partly as the first sg entry of splitter[n+1]->in_sg0
I must rework that condition to :
 - if (len < dma_sg_len(sg))

> In general I like pointer arithmetics and use it always when I need a 
> _pointer_, but in such cases I'd normally just write splitters[1].in_sg0, 
> don't you think that would look better? Ditto everywhere below.
Ok.

>
>> +				(splitters + 1)->skip_sg0 = 0;
>> +			}
>> +			curr++;
>>  		}
>> -		if (remain <= 0)
>> -			break;
>>  	}
>> -	WARN_ON(nfirst >= sglen);
>>  
>> -	sg0 = kmalloc_array(*new_sg_len, sizeof(struct scatterlist),
>> -			    GFP_KERNEL);
>> -	if (!sg0)
>> -		return NULL;
>> +	return splitters;
>> +}
>>  
>> -	remain = size;
>> -	for_each_sg(sg_first, sg, *new_sg_len, i) {
>> -		dma_len = sg_dma_len(sg);
>> -		sg0[i] = *sg;
>> +	for (i = 0; i < nb_splits; i++) {
>
> Maybe
>
> +	for (i = 0, split = splitters; i < nb_splits; i++, split++) {
Yes.

>
>> +		split = splitters + i;
>> +		in_sg = split->in_sg0;
>> +		out_sg = split->out_sg;
>> +		out[i] = out_sg;
>> +		for (j = 0; j < split->nents; j++) {
>
> +		for (j = 0; j < split->nents; j++, out_sg++) {
Yes.

>> @@ -458,6 +500,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
>>  	struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
>>  	int ret;
>>  	int size_y, size_u = 0, size_v = 0;
>> +	size_t sizes[3];
>>  
>>  	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
>>  		vb, vb->baddr, vb->bsize);
>> @@ -513,6 +556,16 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
>>  			size_y = size;
>>  		}
>>  
>> +		sizes[0] = size_y;
>> +		sizes[1] = size_u;
>> +		sizes[2] = size_v;
>> +		ret = sg_split(dma->sglist, pcdev->channels, sizes, buf->sg,
>> +			       GFP_KERNEL);
>> +		if (ret) {
>
> In most places pxa_camera.c checks for (ret < 0), but no longer in all 
> anyway.
Oh you're right, and I like things to remain homogenous, so I'll fix that.

Cheers.

-- 
Robert
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux