[GIT PULL] Staging/IIO driver fixes for 5.0-rc6
The following changes since commit f17b5f06cb92ef2250513a1e154c47b78df07d40: Linux 5.0-rc4 (2019-01-27 15:18:05 -0800) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git tags/staging-5.0-rc6 for you to fetch changes up to 6d923f8fe821c0c6b5378635cbcc9da5f5ec520a: Merge tag 'iio-fixes-5.0a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-linus (2019-02-03 13:10:41 +0100) Staging/IIO driver fixes for 5.0-rc6 Here are some small iio and staging driver fixes for 5.0-rc6. Nothing big, just resolve some reported IIO driver issues, and one staging driver bug. One staging driver patch was added and then reverted as well. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman Aaro Koskinen (1): staging: octeon: fix broken phylib usage Dan Murphy (1): iio: ti-ads8688: Update buffer allocation for timestamps Gao Xiang (1): staging: erofs: keep corrupted fs from crashing kernel in erofs_namei() Greg Kroah-Hartman (2): Revert "staging: erofs: keep corrupted fs from crashing kernel in erofs_namei()" Merge tag 'iio-fixes-5.0a' of git://git.kernel.org/.../jic23/iio into staging-linus Hans de Goede (1): iio: adc: axp288: Fix TS-pin handling Martin Kelly (1): tools: iio: iio_generic_buffer: make num_loops signed Matt Ranostay (1): iio: chemical: atlas-ph-sensor: correct IIO_TEMP values to millicelsius drivers/iio/adc/axp288_adc.c | 76 +++--- drivers/iio/adc/ti-ads8688.c | 3 +- drivers/iio/chemical/atlas-ph-sensor.c | 7 ++-- drivers/staging/octeon/ethernet-mdio.c | 2 +- tools/iio/iio_generic_buffer.c | 2 +- 5 files changed, 67 insertions(+), 23 deletions(-) ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v2 0/7] binder: eliminate use of vmalloc space for binder buffers
On Wed, Jan 30, 2019 at 02:46:48PM -0800, Todd Kjos wrote: > Binder buffers have always been mapped into kernel space > via map_kernel_range_noflush() to allow the binder driver > to modify the buffer before posting to userspace for > processing. > > In recent Android releases, the number of long-running > binder processes has increased to the point that for > 32-bit systems, there is a risk of running out of > vmalloc space. > > This patch set removes the persistent mapping of the > binder buffers into kernel space. Instead, the binder > driver creates temporary mappings with kmap() or > kmap_atomic() to copy to or from the buffer only when > necessary. This patch series blows up when I apply it to my char-misc-next branch: drivers/android/binder_alloc_selftest.c: In function ‘check_buffer_pages_allocated’: drivers/android/binder_alloc_selftest.c:108:44: error: ‘struct binder_buffer’ has no member named ‘data’ end = (void *)PAGE_ALIGN((uintptr_t)buffer->data + size); ^~ Did you forget to enable CONFIG_ANDROID_BINDER_IPC_SELFTEST when doing your builds? thanks, greg k-h ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/2] staging: android: ashmem: Don't allow range_alloc() to fail.
On Wed, Feb 06, 2019 at 08:45:32AM +0900, Tetsuo Handa wrote: > Joel Fernandes wrote: > > On Tue, Feb 05, 2019 at 07:28:41PM +0900, Tetsuo Handa wrote: > > > ashmem_pin() is calling range_shrink() without checking whether > > > range_alloc() succeeded. Since memory allocation fault injection might > > > force range_alloc() to fail while range_alloc() is called for only once > > > for one ioctl() request, make range_alloc() not to fail. > > > > Why does this not need to fail? I am worried your change will introduce > > unwanted endless looping in the kernel instead of gracefully failing a > > pin/unpin request. > > This patch won't introduce endless looping in the kernel, due to a rule called > > The "too small to fail" memory-allocation rule > https://lwn.net/Articles/627419/ > > . In short, memory allocation by range_alloc() might fail only if current > thread > was killed by the OOM killer or memory allocation fault injection mechanism > forced it to fail. And this patch helps doing fuzzing test with minimal > changes. > > > > > Unless there is a good reason, I suggest to drop this patch from the series; > > but let us discuss more if you want. > > We can allocate memory for range_alloc() before holding ashmem_mutex at > ashmem_pin_unpin() if you don't want to use __GFP_NOFAIL. It is better to > avoid memory allocation with ashmem_mutex because ashmem_mutex is held by > shrinker function. But given that this module is going to be replaced shortly, > does it worth moving the memory allocation to the caller? Even if memory allocation does not fail right now, I still want to return the error code correctly via ashmem_pin_unpin() so that if in the future there are changes to the allocator algorithm, then a silent success isn't reported when a failure should be reported.. It doesn't make sense to return success when an allocation failed.. even if you are asking this code to rely on the allocator's "too small to fail" behavior.. can we guarantee this allocator behavior will always exist? Probably not. thanks, - Joel ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/3] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
On Sun, Feb 3, 2019 at 11:48 AM Steve Longerbeam wrote: > > Pass v4l2 encoding enum to the ipu_ic task init functions, and add > support for the BT.709 encoding and inverse encoding matrices. > > Reported-by: Tim Harvey > Signed-off-by: Steve Longerbeam > --- > drivers/gpu/ipu-v3/ipu-ic.c | 67 ++--- > drivers/gpu/ipu-v3/ipu-image-convert.c | 1 + > drivers/staging/media/imx/imx-ic-prpencvf.c | 4 +- > include/video/imx-ipu-v3.h | 5 +- > 4 files changed, 67 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c > index 35ae86ff0585..63362b4fff81 100644 > --- a/drivers/gpu/ipu-v3/ipu-ic.c > +++ b/drivers/gpu/ipu-v3/ipu-ic.c > @@ -199,6 +199,23 @@ static const struct ic_csc_params ic_csc_rgb2ycbcr_bt601 > = { > .scale = 1, > }; > > +/* > + * BT.709 encoding from RGB full range to YUV limited range: > + * > + * Y = R * .2126 + G * .7152 + B * .0722; > + * U = R * -.1146 + G * -.3854 + B * .5000 + 128.; > + * V = R * .5000 + G * -.4542 + B * -.0458 + 128.; > + */ > +static const struct ic_csc_params ic_csc_rgb2ycbcr_bt709 = { > + .coeff = { > + { 54, 183, 18 }, > + { 483, 413, 128 }, > + { 128, 396, 500 }, > + }, > + .offset = { 0, 512, 512 }, > + .scale = 1, > +}; > + > /* transparent RGB->RGB matrix for graphics combining */ > static const struct ic_csc_params ic_csc_rgb2rgb = { > .coeff = { > @@ -226,12 +243,31 @@ static const struct ic_csc_params > ic_csc_ycbcr2rgb_bt601 = { > .scale = 2, > }; > > +/* > + * Inverse BT.709 encoding from YUV limited range to RGB full range: > + * > + * R = (1. * (Y - 16)) + (1.5748 * (Cr - 128)); > + * G = (1. * (Y - 16)) - (0.1873 * (Cb - 128)) - (0.4681 * (Cr - 128)); > + * B = (1. * (Y - 16)) + (1.8556 * (Cb - 128); > + */ > +static const struct ic_csc_params ic_csc_ycbcr2rgb_bt709 = { > + .coeff = { > + { 128, 0, 202 }, > + { 128, 488, 452 }, > + { 128, 238, 0 }, > + }, > + .offset = { -435, 136, -507 }, > + .scale = 2, > +}; > + > static int init_csc(struct ipu_ic *ic, > enum ipu_color_space inf, > enum ipu_color_space outf, > + enum v4l2_ycbcr_encoding encoding, > int csc_index) > { > struct ipu_ic_priv *priv = ic->priv; > + const struct ic_csc_params *params_rgb2yuv, *params_yuv2rgb; > const struct ic_csc_params *params; > u32 __iomem *base; > const u16 (*c)[3]; > @@ -241,10 +277,24 @@ static int init_csc(struct ipu_ic *ic, > base = (u32 __iomem *) > (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); > > + switch (encoding) { > + case V4L2_YCBCR_ENC_601: > + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt601; > + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt601; > + break; > + case V4L2_YCBCR_ENC_709: > + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt709; > + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt709; > + break; > + default: > + dev_err(priv->ipu->dev, "Unsupported YCbCr encoding\n"); > + return -EINVAL; > + } > + Steve, This will fail for RGB to RGB with 'Unsupported YCbCr encoding. We need to account for the RGB->RGB case. How about something like: static int init_csc(struct ipu_ic *ic, enum ipu_color_space inf, enum ipu_color_space outf, + enum v4l2_ycbcr_encoding encoding, int csc_index) { struct ipu_ic_priv *priv = ic->priv; - const struct ic_csc_params *params; + const struct ic_csc_params *params = NULL; u32 __iomem *base; const u16 (*c)[3]; const u16 *a; @@ -241,13 +276,18 @@ static int init_csc(struct ipu_ic *ic, base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); - if (inf == IPUV3_COLORSPACE_YUV && outf == IPUV3_COLORSPACE_RGB) - params = &ic_csc_ycbcr2rgb_bt601; - else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_YUV) - params = &ic_csc_rgb2ycbcr_bt601; + if (inf == IPUV3_COLORSPACE_YUV && outf == IPUV3_COLORSPACE_RGB) { + params = (encoding == V4L2_YCBCR_ENC_601) ? + &ic_csc_ycbcr2rgb_bt601 : &ic_csc_ycbcr2rgb_bt709; + } + else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_YUV) { + params = (encoding == V4L2_YCBCR_ENC_601) ? + &ic_csc_rgb2ycbcr_bt601 : &ic_csc_rgb2ycbcr_bt709; + } else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_RGB) params = &ic_csc_rgb2rgb; - else { + + if (!params) { dev_err(priv->ipu->dev, "Unsupported co
Re: [PATCH v2 0/7] binder: eliminate use of vmalloc space for binder buffers
On Fri, Feb 8, 2019 at 3:26 AM Greg KH wrote: > > On Wed, Jan 30, 2019 at 02:46:48PM -0800, Todd Kjos wrote: > > Binder buffers have always been mapped into kernel space > > via map_kernel_range_noflush() to allow the binder driver > > to modify the buffer before posting to userspace for > > processing. > > > > In recent Android releases, the number of long-running > > binder processes has increased to the point that for > > 32-bit systems, there is a risk of running out of > > vmalloc space. > > > > This patch set removes the persistent mapping of the > > binder buffers into kernel space. Instead, the binder > > driver creates temporary mappings with kmap() or > > kmap_atomic() to copy to or from the buffer only when > > necessary. > > This patch series blows up when I apply it to my char-misc-next branch: > > drivers/android/binder_alloc_selftest.c: In function > ‘check_buffer_pages_allocated’: > drivers/android/binder_alloc_selftest.c:108:44: error: ‘struct binder_buffer’ > has no member named ‘data’ > end = (void *)PAGE_ALIGN((uintptr_t)buffer->data + size); > ^~ > Did you forget to enable CONFIG_ANDROID_BINDER_IPC_SELFTEST when doing your > builds? I did forget. Thanks for catching this. I'll repost with the fix. -Todd > > thanks, > > greg k-h ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v3 2/7] binder: add functions to copy to/from binder buffers
Avoid vm_area when copying to or from binder buffers. Instead, new copy functions are added that copy from kernel space to binder buffer space. These use kmap_atomic() and kunmap_atomic() to create temporary mappings and then memcpy() is used to copy within that page. Also, kmap_atomic() / kunmap_atomic() use the appropriate cache flushing to support VIVT cache architectures. Allow binder to build if CPU_CACHE_VIVT is defined. Several uses of the new functions are added here. More to follow in subsequent patches. Signed-off-by: Todd Kjos --- v2: remove casts as suggested by Dan Carpenter drivers/android/Kconfig| 2 +- drivers/android/binder.c | 119 + drivers/android/binder_alloc.c | 59 drivers/android/binder_alloc.h | 12 4 files changed, 147 insertions(+), 45 deletions(-) diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig index 4c190f8d1f4c6..6fdf2abe4598a 100644 --- a/drivers/android/Kconfig +++ b/drivers/android/Kconfig @@ -10,7 +10,7 @@ if ANDROID config ANDROID_BINDER_IPC bool "Android Binder IPC Driver" - depends on MMU && !CPU_CACHE_VIVT + depends on MMU default n ---help--- Binder is used in Android for both communication between processes, diff --git a/drivers/android/binder.c b/drivers/android/binder.c index ab0b3eec363bc..74d0c1ff874e2 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2244,14 +2244,22 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, off_end = (void *)off_start + buffer->offsets_size; for (offp = off_start; offp < off_end; offp++) { struct binder_object_header *hdr; - size_t object_size = binder_validate_object(buffer, *offp); - + size_t object_size; + binder_size_t object_offset; + binder_size_t buffer_offset = (uintptr_t)offp - + (uintptr_t)buffer->data; + + binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, + buffer, buffer_offset, + sizeof(object_offset)); + object_size = binder_validate_object(buffer, object_offset); if (object_size == 0) { pr_err("transaction release %d bad object at offset %lld, size %zd\n", - debug_id, (u64)*offp, buffer->data_size); + debug_id, (u64)object_offset, buffer->data_size); continue; } - hdr = (struct binder_object_header *)(buffer->data + *offp); + hdr = (struct binder_object_header *) + (buffer->data + object_offset); switch (hdr->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { @@ -2359,8 +2367,20 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, continue; } fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset); - for (fd_index = 0; fd_index < fda->num_fds; fd_index++) - binder_deferred_fd_close(fd_array[fd_index]); + for (fd_index = 0; fd_index < fda->num_fds; +fd_index++) { + u32 fd; + binder_size_t offset = + (uintptr_t)&fd_array[fd_index] - + (uintptr_t)buffer->data; + + binder_alloc_copy_from_buffer(&proc->alloc, + &fd, + buffer, + offset, + sizeof(fd)); + binder_deferred_fd_close(fd); + } } break; default: pr_err("transaction release %d bad object type %x\n", @@ -2496,7 +2516,7 @@ static int binder_translate_handle(struct flat_binder_object *fp, return ret; } -static int binder_translate_fd(u32 *fdp, +static int binder_translate_fd(u32 fd, binder_size_t fd_offset, struct binder_transaction *t, struct binder_thread *thread, struct binder_transaction *in_reply_to) @@ -2507,7 +2527,6 @@ static int binder_translate_fd(u32 *fdp, struct file *file; int ret = 0; bool target_allows_fd; - int fd = *fdp; if (in_reply_to) target_allows_fd = !!(in_reply_to->flags & TF_ACCEPT_FDS); @@ -2546,7 +2
[PATCH v3 3/7] binder: add function to copy binder object from buffer
When creating or tearing down a transaction, the binder driver examines objects in the buffer and takes appropriate action. To do this without needing to dereference pointers into the buffer, the local copies of the objects are needed. This patch introduces a function to validate and copy binder objects from the buffer to a local structure. Signed-off-by: Todd Kjos --- v2: remove casts as suggested by Dan Carpenter drivers/android/binder.c | 75 +++- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 74d0c1ff874e2..8063b405e4fa1 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -628,6 +628,26 @@ struct binder_transaction { spinlock_t lock; }; +/** + * struct binder_object - union of flat binder object types + * @hdr: generic object header + * @fbo: binder object (nodes and refs) + * @fdo: file descriptor object + * @bbo: binder buffer pointer + * @fdao: file descriptor array + * + * Used for type-independent object copies + */ +struct binder_object { + union { + struct binder_object_header hdr; + struct flat_binder_object fbo; + struct binder_fd_object fdo; + struct binder_buffer_object bbo; + struct binder_fd_array_object fdao; + }; +}; + /** * binder_proc_lock() - Acquire outer lock for given binder_proc * @proc: struct binder_proc to acquire @@ -2017,26 +2037,33 @@ static void binder_cleanup_transaction(struct binder_transaction *t, } /** - * binder_validate_object() - checks for a valid metadata object in a buffer. + * binder_get_object() - gets object and checks for valid metadata + * @proc: binder_proc owning the buffer * @buffer:binder_buffer that we're parsing. - * @offset:offset in the buffer at which to validate an object. + * @offset:offset in the @buffer at which to validate an object. + * @object:struct binder_object to read into * * Return: If there's a valid metadata object at @offset in @buffer, the - * size of that object. Otherwise, it returns zero. + * size of that object. Otherwise, it returns zero. The object + * is read into the struct binder_object pointed to by @object. */ -static size_t binder_validate_object(struct binder_buffer *buffer, u64 offset) +static size_t binder_get_object(struct binder_proc *proc, + struct binder_buffer *buffer, + unsigned long offset, + struct binder_object *object) { - /* Check if we can read a header first */ + size_t read_size; struct binder_object_header *hdr; size_t object_size = 0; - if (buffer->data_size < sizeof(*hdr) || - offset > buffer->data_size - sizeof(*hdr) || - !IS_ALIGNED(offset, sizeof(u32))) + read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); + if (read_size < sizeof(*hdr)) return 0; + binder_alloc_copy_from_buffer(&proc->alloc, object, buffer, + offset, read_size); - /* Ok, now see if we can read a complete object. */ - hdr = (struct binder_object_header *)(buffer->data + offset); + /* Ok, now see if we read a complete object. */ + hdr = &object->hdr; switch (hdr->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: @@ -2245,6 +2272,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, for (offp = off_start; offp < off_end; offp++) { struct binder_object_header *hdr; size_t object_size; + struct binder_object object; binder_size_t object_offset; binder_size_t buffer_offset = (uintptr_t)offp - (uintptr_t)buffer->data; @@ -2252,14 +2280,14 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, buffer, buffer_offset, sizeof(object_offset)); - object_size = binder_validate_object(buffer, object_offset); + object_size = binder_get_object(proc, buffer, + object_offset, &object); if (object_size == 0) { pr_err("transaction release %d bad object at offset %lld, size %zd\n", debug_id, (u64)object_offset, buffer->data_size); continue; } - hdr = (struct binder_object_header *) - (buffer->data + object_offset); + hdr = &object.hdr; switch (hdr->type) { case
[PATCH v3 5/7] binder: remove kernel vm_area for buffer space
Remove the kernel's vm_area and the code that maps buffer pages into it. Signed-off-by: Todd Kjos --- drivers/android/binder_alloc.c | 40 ++ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 2eebff4be83e0..d4cbe4b3947a6 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -265,16 +265,6 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, page->alloc = alloc; INIT_LIST_HEAD(&page->lru); - ret = map_kernel_range_noflush((unsigned long)page_addr, - PAGE_SIZE, PAGE_KERNEL, - &page->page_ptr); - flush_cache_vmap((unsigned long)page_addr, - (unsigned long)page_addr + PAGE_SIZE); - if (ret != 1) { - pr_err("%d: binder_alloc_buf failed to map page at %pK in kernel\n", - alloc->pid, page_addr); - goto err_map_kernel_failed; - } user_page_addr = (uintptr_t)page_addr + alloc->user_buffer_offset; ret = vm_insert_page(vma, user_page_addr, page[0].page_ptr); @@ -314,8 +304,6 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, continue; err_vm_insert_page_failed: - unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); -err_map_kernel_failed: __free_page(page->page_ptr); page->page_ptr = NULL; err_alloc_page_failed: @@ -695,7 +683,6 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, struct vm_area_struct *vma) { int ret; - struct vm_struct *area; const char *failure_string; struct binder_buffer *buffer; @@ -706,28 +693,10 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, goto err_already_mapped; } - area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC); - if (area == NULL) { - ret = -ENOMEM; - failure_string = "get_vm_area"; - goto err_get_vm_area_failed; - } - alloc->buffer = area->addr; - alloc->user_buffer_offset = - vma->vm_start - (uintptr_t)alloc->buffer; + alloc->buffer = (void *)vma->vm_start; + alloc->user_buffer_offset = 0; mutex_unlock(&binder_alloc_mmap_lock); -#ifdef CONFIG_CPU_CACHE_VIPT - if (cache_is_vipt_aliasing()) { - while (CACHE_COLOUR( - (vma->vm_start ^ (uint32_t)alloc->buffer))) { - pr_info("%s: %d %lx-%lx maps %pK bad alignment\n", - __func__, alloc->pid, vma->vm_start, - vma->vm_end, alloc->buffer); - vma->vm_start += PAGE_SIZE; - } - } -#endif alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE, sizeof(alloc->pages[0]), GFP_KERNEL); @@ -760,9 +729,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, alloc->pages = NULL; err_alloc_pages_failed: mutex_lock(&binder_alloc_mmap_lock); - vfree(alloc->buffer); alloc->buffer = NULL; -err_get_vm_area_failed: err_already_mapped: mutex_unlock(&binder_alloc_mmap_lock); binder_alloc_debug(BINDER_DEBUG_USER_ERROR, @@ -821,12 +788,10 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) "%s: %d: page %d at %pK %s\n", __func__, alloc->pid, i, page_addr, on_lru ? "on lru" : "active"); - unmap_kernel_range((unsigned long)page_addr, PAGE_SIZE); __free_page(alloc->pages[i].page_ptr); page_count++; } kfree(alloc->pages); - vfree(alloc->buffer); } mutex_unlock(&alloc->mutex); if (alloc->vma_vm_mm) @@ -988,7 +953,6 @@ enum lru_status binder_alloc_free_page(struct list_head *item, trace_binder_unmap_kernel_start(alloc, index); - unmap_kernel_range(page_addr, PAGE_SIZE); __free_page(page->page_ptr); page->page_ptr = NULL; -- 2.20.1.791.gb4d0f1c61a-goog ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v3 6/7] binder: remove user_buffer_offset
Remove user_buffer_offset since there is no kernel buffer pointer anymore. Signed-off-by: Todd Kjos --- v2: remove casts as suggested by Dan Carpenter drivers/android/binder.c | 39 ++ drivers/android/binder_alloc.c | 16 ++ drivers/android/binder_alloc.h | 23 3 files changed, 13 insertions(+), 65 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 98163bf5f35c7..b3d609b5935a6 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2380,7 +2380,6 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_fd_array_object *fda; struct binder_buffer_object *parent; struct binder_object ptr_object; - uintptr_t parent_buffer; u32 *fd_array; size_t fd_index; binder_size_t fd_buf_size; @@ -2405,14 +2404,6 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id); continue; } - /* -* Since the parent was already fixed up, convert it -* back to kernel address space to access it -*/ - parent_buffer = parent->buffer - - binder_alloc_get_user_buffer_offset( - &proc->alloc); - fd_buf_size = sizeof(u32) * fda->num_fds; if (fda->num_fds >= SIZE_MAX / sizeof(u32)) { pr_err("transaction release %d invalid number of fds (%lld)\n", @@ -2426,7 +2417,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id, (u64)fda->num_fds); continue; } - fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset); + fd_array = (u32 *)(uintptr_t) + (parent->buffer + fda->parent_offset); for (fd_index = 0; fd_index < fda->num_fds; fd_index++) { u32 fd; @@ -2646,7 +2638,6 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, struct binder_transaction *in_reply_to) { binder_size_t fdi, fd_buf_size; - uintptr_t parent_buffer; u32 *fd_array; struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; @@ -2664,13 +2655,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, proc->pid, thread->pid, (u64)fda->num_fds); return -EINVAL; } - /* -* Since the parent was already fixed up, convert it -* back to the kernel address space to access it -*/ - parent_buffer = parent->buffer - - binder_alloc_get_user_buffer_offset(&target_proc->alloc); - fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset); + fd_array = (u32 *)(uintptr_t)(parent->buffer + fda->parent_offset); if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) { binder_user_error("%d:%d parent offset not aligned correctly.\n", proc->pid, thread->pid); @@ -2703,7 +2688,6 @@ static int binder_fixup_parent(struct binder_transaction *t, binder_size_t last_fixup_min_off) { struct binder_buffer_object *parent; - u8 *parent_buffer; struct binder_buffer *b = t->buffer; struct binder_proc *proc = thread->proc; struct binder_proc *target_proc = t->to_proc; @@ -2739,11 +2723,8 @@ static int binder_fixup_parent(struct binder_transaction *t, proc->pid, thread->pid); return -EINVAL; } - parent_buffer = (u8 *)((uintptr_t)parent->buffer - - binder_alloc_get_user_buffer_offset( - &target_proc->alloc)); buffer_offset = bp->parent_offset + - (uintptr_t)parent_buffer - (uintptr_t)b->data; + (uintptr_t)parent->buffer - (uintptr_t)b->data; binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset, &bp->buffer, sizeof(bp->buffer)); @@ -3159,10 +3140,8 @@ static void binder_transaction(struct binder_proc *proc, ALIGN(tr->offsets_size, sizeof(void *)) + ALIGN(extra_buffers_size, sizeof(void *)) - AL
[PATCH v3 1/7] binder: create userspace-to-binder-buffer copy function
The binder driver uses a vm_area to map the per-process binder buffer space. For 32-bit android devices, this is now taking too much vmalloc space. This patch removes the use of vm_area when copying the transaction data from the sender to the buffer space. Instead of using copy_from_user() for multi-page copies, it now uses binder_alloc_copy_user_to_buffer() which uses kmap() and kunmap() to map each page, and uses copy_from_user() for copying to that page. Signed-off-by: Todd Kjos --- v2: remove casts as suggested by Dan Carpenter drivers/android/binder.c | 29 +++-- drivers/android/binder_alloc.c | 113 + drivers/android/binder_alloc.h | 8 +++ 3 files changed, 143 insertions(+), 7 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 5f6ef5e63b91e..ab0b3eec363bc 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3078,8 +3078,12 @@ static void binder_transaction(struct binder_proc *proc, ALIGN(tr->data_size, sizeof(void *))); offp = off_start; - if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t) - tr->data.ptr.buffer, tr->data_size)) { + if (binder_alloc_copy_user_to_buffer( + &target_proc->alloc, + t->buffer, 0, + (const void __user *) + (uintptr_t)tr->data.ptr.buffer, + tr->data_size)) { binder_user_error("%d:%d got transaction with invalid data ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; @@ -3087,8 +3091,13 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_copy_data_failed; } - if (copy_from_user(offp, (const void __user *)(uintptr_t) - tr->data.ptr.offsets, tr->offsets_size)) { + if (binder_alloc_copy_user_to_buffer( + &target_proc->alloc, + t->buffer, + ALIGN(tr->data_size, sizeof(void *)), + (const void __user *) + (uintptr_t)tr->data.ptr.offsets, + tr->offsets_size)) { binder_user_error("%d:%d got transaction with invalid offsets ptr\n", proc->pid, thread->pid); return_error = BR_FAILED_REPLY; @@ -3217,6 +3226,8 @@ static void binder_transaction(struct binder_proc *proc, struct binder_buffer_object *bp = to_binder_buffer_object(hdr); size_t buf_left = sg_buf_end - sg_bufp; + binder_size_t sg_buf_offset = (uintptr_t)sg_bufp - + (uintptr_t)t->buffer->data; if (bp->length > buf_left) { binder_user_error("%d:%d got transaction with too large buffer\n", @@ -3226,9 +3237,13 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_bad_offset; } - if (copy_from_user(sg_bufp, - (const void __user *)(uintptr_t) - bp->buffer, bp->length)) { + if (binder_alloc_copy_user_to_buffer( + &target_proc->alloc, + t->buffer, + sg_buf_offset, + (const void __user *) + (uintptr_t)bp->buffer, + bp->length)) { binder_user_error("%d:%d got transaction with invalid offsets ptr\n", proc->pid, thread->pid); return_error_param = -EFAULT; diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 022cd80e80cc3..94c0d85c4e75b 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "binder_alloc.h" #include "binder_trace.h" @@ -1053,3 +1055,114 @@ int binder_alloc_shrinker_init(void) } return ret; } + +/** + * check_buffer() - verify that buffer/offset is safe to access + * @alloc: binder_alloc for this proc + * @buffer: binder buffer to be accessed + * @offset: offset into @buffer data + * @bytes: bytes to access from offset + * + * Check
[PATCH v3 4/7] binder: avoid kernel vm_area for buffer fixups
Refactor the functions to validate and fixup struct binder_buffer pointer objects to avoid using vm_area pointers. Instead copy to/from kernel space using binder_alloc_copy_to_buffer() and binder_alloc_copy_from_buffer(). The following functions were refactored: refactor binder_validate_ptr() binder_validate_fixup() binder_fixup_parent() Signed-off-by: Todd Kjos --- drivers/android/binder.c | 146 ++- 1 file changed, 97 insertions(+), 49 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 8063b405e4fa1..98163bf5f35c7 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2092,10 +2092,13 @@ static size_t binder_get_object(struct binder_proc *proc, /** * binder_validate_ptr() - validates binder_buffer_object in a binder_buffer. + * @proc: binder_proc owning the buffer * @b: binder_buffer containing the object + * @object:struct binder_object to read into * @index: index in offset array at which the binder_buffer_object is * located - * @start: points to the start of the offset array + * @start_offset: points to the start of the offset array + * @object_offsetp: offset of @object read from @b * @num_valid: the number of valid offsets in the offset array * * Return: If @index is within the valid range of the offset array @@ -2106,34 +2109,46 @@ static size_t binder_get_object(struct binder_proc *proc, * Note that the offset found in index @index itself is not * verified; this function assumes that @num_valid elements * from @start were previously verified to have valid offsets. + * If @object_offsetp is non-NULL, then the offset within + * @b is written to it. */ -static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer *b, - binder_size_t index, - binder_size_t *start, - binder_size_t num_valid) +static struct binder_buffer_object *binder_validate_ptr( + struct binder_proc *proc, + struct binder_buffer *b, + struct binder_object *object, + binder_size_t index, + binder_size_t start_offset, + binder_size_t *object_offsetp, + binder_size_t num_valid) { - struct binder_buffer_object *buffer_obj; - binder_size_t *offp; + size_t object_size; + binder_size_t object_offset; + unsigned long buffer_offset; if (index >= num_valid) return NULL; - offp = start + index; - buffer_obj = (struct binder_buffer_object *)(b->data + *offp); - if (buffer_obj->hdr.type != BINDER_TYPE_PTR) + buffer_offset = start_offset + sizeof(binder_size_t) * index; + binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, + b, buffer_offset, sizeof(object_offset)); + object_size = binder_get_object(proc, b, object_offset, object); + if (!object_size || object->hdr.type != BINDER_TYPE_PTR) return NULL; + if (object_offsetp) + *object_offsetp = object_offset; - return buffer_obj; + return &object->bbo; } /** * binder_validate_fixup() - validates pointer/fd fixups happen in order. + * @proc: binder_proc owning the buffer * @b: transaction buffer - * @objects_start start of objects buffer - * @buffer:binder_buffer_object in which to fix up - * @offset:start offset in @buffer to fix up - * @last_obj: last binder_buffer_object that we fixed up in - * @last_min_offset: minimum fixup offset in @last_obj + * @objects_start_offset: offset to start of objects buffer + * @buffer_obj_offset: offset to binder_buffer_object in which to fix up + * @fixup_offset: start offset in @buffer to fix up + * @last_obj_offset: offset to last binder_buffer_object that we fixed + * @last_min_offset: minimum fixup offset in object at @last_obj_offset * * Return: %true if a fixup in buffer @buffer at offset @offset is * allowed. @@ -2164,28 +2179,41 @@ static struct binder_buffer_object *binder_validate_ptr(struct binder_buffer *b, * C (parent = A, offset = 16) * D (parent = B, offset = 0) // B is not A or any of A's parents */ -static bool binder_validate_fixup(struct binder_buffer *b, - binder_size_t *objects_start, - struct binder_buffer_object *buffer
[PATCH v3 7/7] binder: use userspace pointer as base of buffer space
Now that alloc->buffer points to the userspace vm_area rename buffer->data to buffer->user_data and rename local pointers that hold user addresses. Also use the "__user" tag to annotate all user pointers so sparse can flag cases where user pointer vaues are copied to kernel pointers. Refactor code to use offsets instead of user pointers. Signed-off-by: Todd Kjos --- v2: remove casts as suggested by Dan Carpenter v3: fix build-break when CONFIG_ANDROID_BINDER_IPC_SELFTEST enabled drivers/android/binder.c| 118 ++-- drivers/android/binder_alloc.c | 87 - drivers/android/binder_alloc.h | 6 +- drivers/android/binder_alloc_selftest.c | 4 +- drivers/android/binder_trace.h | 2 +- 5 files changed, 118 insertions(+), 99 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index b3d609b5935a6..25491eceb7503 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2278,33 +2278,30 @@ static void binder_deferred_fd_close(int fd) static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, - binder_size_t *failed_at) + binder_size_t failed_at, + bool is_failure) { - binder_size_t *offp, *off_start, *off_end; int debug_id = buffer->debug_id; - binder_size_t off_start_offset; + binder_size_t off_start_offset, buffer_offset, off_end_offset; binder_debug(BINDER_DEBUG_TRANSACTION, -"%d buffer release %d, size %zd-%zd, failed at %pK\n", +"%d buffer release %d, size %zd-%zd, failed at %llx\n", proc->pid, buffer->debug_id, -buffer->data_size, buffer->offsets_size, failed_at); +buffer->data_size, buffer->offsets_size, +(unsigned long long)failed_at); if (buffer->target_node) binder_dec_node(buffer->target_node, 1, 0); off_start_offset = ALIGN(buffer->data_size, sizeof(void *)); - off_start = (binder_size_t *)(buffer->data + off_start_offset); - if (failed_at) - off_end = failed_at; - else - off_end = (void *)off_start + buffer->offsets_size; - for (offp = off_start; offp < off_end; offp++) { + off_end_offset = is_failure ? failed_at : + off_start_offset + buffer->offsets_size; + for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; +buffer_offset += sizeof(binder_size_t)) { struct binder_object_header *hdr; size_t object_size; struct binder_object object; binder_size_t object_offset; - binder_size_t buffer_offset = (uintptr_t)offp - - (uintptr_t)buffer->data; binder_alloc_copy_from_buffer(&proc->alloc, &object_offset, buffer, buffer_offset, @@ -2380,9 +2377,10 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_fd_array_object *fda; struct binder_buffer_object *parent; struct binder_object ptr_object; - u32 *fd_array; + binder_size_t fda_offset; size_t fd_index; binder_size_t fd_buf_size; + binder_size_t num_valid; if (proc->tsk != current->group_leader) { /* @@ -2393,12 +2391,14 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, continue; } + num_valid = (buffer_offset - off_start_offset) / + sizeof(binder_size_t); fda = to_binder_fd_array_object(hdr); parent = binder_validate_ptr(proc, buffer, &ptr_object, fda->parent, off_start_offset, NULL, -offp - off_start); +num_valid); if (!parent) { pr_err("transaction release %d bad parent offset\n", debug_id); @@ -2417,14 +2417,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id, (u64)fda->num_fds); continue;
[PATCH v3 0/7] binder: eliminate use of vmalloc space for binder buffers
Binder buffers have always been mapped into kernel space via map_kernel_range_noflush() to allow the binder driver to modify the buffer before posting to userspace for processing. In recent Android releases, the number of long-running binder processes has increased to the point that for 32-bit systems, there is a risk of running out of vmalloc space. This patch set removes the persistent mapping of the binder buffers into kernel space. Instead, the binder driver creates temporary mappings with kmap() or kmap_atomic() to copy to or from the buffer only when necessary. Todd Kjos (7): binder: create userspace-to-binder-buffer copy function binder: add functions to copy to/from binder buffers binder: add function to copy binder object from buffer binder: avoid kernel vm_area for buffer fixups binder: remove kernel vm_area for buffer space binder: remove user_buffer_offset binder: use userspace pointer as base of buffer space v2: remove casts as suggested by Dan Carpenter v3: fix build-break when CONFIG_ANDROID_BINDER_IPC_SELFTEST enabled drivers/android/Kconfig | 2 +- drivers/android/binder.c| 460 ++ drivers/android/binder_alloc.c | 299 +-- drivers/android/binder_alloc.h | 47 drivers/android/binder_alloc_selftest.c | 4 +- drivers/android/binder_trace.h | 2 +- 6 files changed, 536 insertions(+), 278 deletions(-) ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/3] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
On 2/8/19 8:24 AM, Tim Harvey wrote: On Sun, Feb 3, 2019 at 11:48 AM Steve Longerbeam wrote: Pass v4l2 encoding enum to the ipu_ic task init functions, and add support for the BT.709 encoding and inverse encoding matrices. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- drivers/gpu/ipu-v3/ipu-ic.c | 67 ++--- drivers/gpu/ipu-v3/ipu-image-convert.c | 1 + drivers/staging/media/imx/imx-ic-prpencvf.c | 4 +- include/video/imx-ipu-v3.h | 5 +- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c index 35ae86ff0585..63362b4fff81 100644 --- a/drivers/gpu/ipu-v3/ipu-ic.c +++ b/drivers/gpu/ipu-v3/ipu-ic.c @@ -199,6 +199,23 @@ static const struct ic_csc_params ic_csc_rgb2ycbcr_bt601 = { .scale = 1, }; +/* + * BT.709 encoding from RGB full range to YUV limited range: + * + * Y = R * .2126 + G * .7152 + B * .0722; + * U = R * -.1146 + G * -.3854 + B * .5000 + 128.; + * V = R * .5000 + G * -.4542 + B * -.0458 + 128.; + */ +static const struct ic_csc_params ic_csc_rgb2ycbcr_bt709 = { + .coeff = { + { 54, 183, 18 }, + { 483, 413, 128 }, + { 128, 396, 500 }, + }, + .offset = { 0, 512, 512 }, + .scale = 1, +}; + /* transparent RGB->RGB matrix for graphics combining */ static const struct ic_csc_params ic_csc_rgb2rgb = { .coeff = { @@ -226,12 +243,31 @@ static const struct ic_csc_params ic_csc_ycbcr2rgb_bt601 = { .scale = 2, }; +/* + * Inverse BT.709 encoding from YUV limited range to RGB full range: + * + * R = (1. * (Y - 16)) + (1.5748 * (Cr - 128)); + * G = (1. * (Y - 16)) - (0.1873 * (Cb - 128)) - (0.4681 * (Cr - 128)); + * B = (1. * (Y - 16)) + (1.8556 * (Cb - 128); + */ +static const struct ic_csc_params ic_csc_ycbcr2rgb_bt709 = { + .coeff = { + { 128, 0, 202 }, + { 128, 488, 452 }, + { 128, 238, 0 }, + }, + .offset = { -435, 136, -507 }, + .scale = 2, +}; + static int init_csc(struct ipu_ic *ic, enum ipu_color_space inf, enum ipu_color_space outf, + enum v4l2_ycbcr_encoding encoding, int csc_index) { struct ipu_ic_priv *priv = ic->priv; + const struct ic_csc_params *params_rgb2yuv, *params_yuv2rgb; const struct ic_csc_params *params; u32 __iomem *base; const u16 (*c)[3]; @@ -241,10 +277,24 @@ static int init_csc(struct ipu_ic *ic, base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); + switch (encoding) { + case V4L2_YCBCR_ENC_601: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt601; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt601; + break; + case V4L2_YCBCR_ENC_709: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt709; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt709; + break; + default: + dev_err(priv->ipu->dev, "Unsupported YCbCr encoding\n"); + return -EINVAL; + } + Steve, This will fail for RGB to RGB with 'Unsupported YCbCr encoding. We need to account for the RGB->RGB case. How about something like: Thanks for reporting Tim I rather keep the check for supported encoding, and instead get rid of "Unsupported color space conversion" error, because that is the YUV->YUV case which can be allowed using the identity matrix. Steve static int init_csc(struct ipu_ic *ic, enum ipu_color_space inf, enum ipu_color_space outf, + enum v4l2_ycbcr_encoding encoding, int csc_index) { struct ipu_ic_priv *priv = ic->priv; - const struct ic_csc_params *params; + const struct ic_csc_params *params = NULL; u32 __iomem *base; const u16 (*c)[3]; const u16 *a; @@ -241,13 +276,18 @@ static int init_csc(struct ipu_ic *ic, base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); - if (inf == IPUV3_COLORSPACE_YUV && outf == IPUV3_COLORSPACE_RGB) - params = &ic_csc_ycbcr2rgb_bt601; - else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_YUV) - params = &ic_csc_rgb2ycbcr_bt601; + if (inf == IPUV3_COLORSPACE_YUV && outf == IPUV3_COLORSPACE_RGB) { + params = (encoding == V4L2_YCBCR_ENC_601) ? + &ic_csc_ycbcr2rgb_bt601 : &ic_csc_ycbcr2rgb_bt709; + } + else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_YUV) { + params = (encoding == V4L2_YCBCR_ENC_601) ? + &ic_csc_rgb2ycbcr_bt601 : &ic_csc_rgb2ycbcr_bt709; + } else if (inf == IPUV3_COLORSPACE_RGB && outf == IPUV3_COLORSPACE_RGB)
[PATCH v2 4/4] media: imx: Allow BT.709 encoding for IC routes
From: Steve Longerbeam The IC now supports BT.709 Y'CbCr encoding, in addition to existing BT.601 encoding, so allow both, for pipelines that route through the IC. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v2: - move ic_route check above default colorimetry checks, and fill default colorimetry for ic_route, otherwise it's not possible to set BT.709 encoding for ic routes. --- drivers/staging/media/imx/imx-media-utils.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 5f110d90a4ef..dde0e47550d7 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -544,6 +544,19 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, if (tryfmt->field == V4L2_FIELD_ANY) tryfmt->field = fmt->field; + if (ic_route) { + if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) + tryfmt->colorspace = fmt->colorspace; + + tryfmt->quantization = is_rgb ? + V4L2_QUANTIZATION_FULL_RANGE : + V4L2_QUANTIZATION_LIM_RANGE; + + if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 && + tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709) + tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; + } + /* fill colorimetry if necessary */ if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) { tryfmt->colorspace = fmt->colorspace; @@ -566,13 +579,6 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, tryfmt->ycbcr_enc); } } - - if (ic_route) { - tryfmt->quantization = is_rgb ? - V4L2_QUANTIZATION_FULL_RANGE : - V4L2_QUANTIZATION_LIM_RANGE; - tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; - } } EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v2 3/4] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
From: Steve Longerbeam Pass v4l2 encoding enum to the ipu_ic task init functions, and add support for the BT.709 encoding and inverse encoding matrices. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v2: - only return "Unsupported YCbCr encoding" error if inf != outf, since if inf == outf, the identity matrix can be used. Reported by Tim Harvey. --- drivers/gpu/ipu-v3/ipu-ic.c | 71 +++-- drivers/gpu/ipu-v3/ipu-image-convert.c | 1 + drivers/staging/media/imx/imx-ic-prpencvf.c | 4 +- include/video/imx-ipu-v3.h | 5 +- 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c index e459615a49a1..0d57ca7ba18e 100644 --- a/drivers/gpu/ipu-v3/ipu-ic.c +++ b/drivers/gpu/ipu-v3/ipu-ic.c @@ -212,6 +212,23 @@ static const struct ic_csc_params ic_csc_identity = { .scale = 2, }; +/* + * BT.709 encoding from RGB full range to YUV limited range: + * + * Y = R * .2126 + G * .7152 + B * .0722; + * U = R * -.1146 + G * -.3854 + B * .5000 + 128.; + * V = R * .5000 + G * -.4542 + B * -.0458 + 128.; + */ +static const struct ic_csc_params ic_csc_rgb2ycbcr_bt709 = { + .coeff = { + { 54, 183, 18 }, + { 483, 413, 128 }, + { 128, 396, 500 }, + }, + .offset = { 0, 512, 512 }, + .scale = 1, +}; + /* * Inverse BT.601 encoding from YUV limited range to RGB full range: * @@ -229,12 +246,31 @@ static const struct ic_csc_params ic_csc_ycbcr2rgb_bt601 = { .scale = 2, }; +/* + * Inverse BT.709 encoding from YUV limited range to RGB full range: + * + * R = (1. * (Y - 16)) + (1.5748 * (Cr - 128)); + * G = (1. * (Y - 16)) - (0.1873 * (Cb - 128)) - (0.4681 * (Cr - 128)); + * B = (1. * (Y - 16)) + (1.8556 * (Cb - 128); + */ +static const struct ic_csc_params ic_csc_ycbcr2rgb_bt709 = { + .coeff = { + { 128, 0, 202 }, + { 128, 488, 452 }, + { 128, 238, 0 }, + }, + .offset = { -435, 136, -507 }, + .scale = 2, +}; + static int init_csc(struct ipu_ic *ic, enum ipu_color_space inf, enum ipu_color_space outf, + enum v4l2_ycbcr_encoding encoding, int csc_index) { struct ipu_ic_priv *priv = ic->priv; + const struct ic_csc_params *params_rgb2yuv, *params_yuv2rgb; const struct ic_csc_params *params; u32 __iomem *base; const u16 (*c)[3]; @@ -244,12 +280,30 @@ static int init_csc(struct ipu_ic *ic, base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); + switch (encoding) { + case V4L2_YCBCR_ENC_601: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt601; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt601; + break; + case V4L2_YCBCR_ENC_709: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt709; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt709; + break; + default: + if (inf != outf) { + dev_err(priv->ipu->dev, + "Unsupported YCbCr encoding\n"); + return -EINVAL; + } + break; + } + if (inf == outf) params = &ic_csc_identity; else if (inf == IPUV3_COLORSPACE_YUV) - params = &ic_csc_ycbcr2rgb_bt601; + params = &ic_csc_ycbcr2rgb; else - params = &ic_csc_rgb2ycbcr_bt601; + params = &ic_csc_rgb2ycbcr; /* Cast to unsigned */ c = (const u16 (*)[3])params->coeff; @@ -390,6 +444,7 @@ EXPORT_SYMBOL_GPL(ipu_ic_task_disable); int ipu_ic_task_graphics_init(struct ipu_ic *ic, enum ipu_color_space in_g_cs, + enum v4l2_ycbcr_encoding encoding, bool galpha_en, u32 galpha, bool colorkey_en, u32 colorkey) { @@ -408,7 +463,7 @@ int ipu_ic_task_graphics_init(struct ipu_ic *ic, if (!(ic_conf & ic->bit->ic_conf_csc1_en)) { /* need transparent CSC1 conversion */ ret = init_csc(ic, IPUV3_COLORSPACE_RGB, - IPUV3_COLORSPACE_RGB, 0); + IPUV3_COLORSPACE_RGB, encoding, 0); if (ret) goto unlock; } @@ -416,7 +471,7 @@ int ipu_ic_task_graphics_init(struct ipu_ic *ic, ic->g_in_cs = in_g_cs; if (ic->g_in_cs != ic->out_cs) { - ret = init_csc(ic, ic->g_in_cs, ic->out_cs, 1); + ret = init_csc(ic, ic->g_in_cs, ic->out_cs, encoding, 1); if (ret) goto unlock; } @@ -450,6 +505,7 @@ int ipu_ic_task_init_rsc(struct ipu_ic *ic, int out_widt
[PATCH v3 4/4] media: imx: Allow BT.709 encoding for IC routes
The IC now supports BT.709 Y'CbCr encoding, in addition to existing BT.601 encoding, so allow both, for pipelines that route through the IC. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v2: - move ic_route check above default colorimetry checks, and fill default colorimetry for ic_route, otherwise it's not possible to set BT.709 encoding for ic routes. --- drivers/staging/media/imx/imx-media-utils.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 5f110d90a4ef..dde0e47550d7 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -544,6 +544,19 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, if (tryfmt->field == V4L2_FIELD_ANY) tryfmt->field = fmt->field; + if (ic_route) { + if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) + tryfmt->colorspace = fmt->colorspace; + + tryfmt->quantization = is_rgb ? + V4L2_QUANTIZATION_FULL_RANGE : + V4L2_QUANTIZATION_LIM_RANGE; + + if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 && + tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709) + tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; + } + /* fill colorimetry if necessary */ if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) { tryfmt->colorspace = fmt->colorspace; @@ -566,13 +579,6 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, tryfmt->ycbcr_enc); } } - - if (ic_route) { - tryfmt->quantization = is_rgb ? - V4L2_QUANTIZATION_FULL_RANGE : - V4L2_QUANTIZATION_LIM_RANGE; - tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; - } } EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v3 3/4] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
Pass v4l2 encoding enum to the ipu_ic task init functions, and add support for the BT.709 encoding and inverse encoding matrices. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v2: - only return "Unsupported YCbCr encoding" error if inf != outf, since if inf == outf, the identity matrix can be used. Reported by Tim Harvey. --- drivers/gpu/ipu-v3/ipu-ic.c | 71 +++-- drivers/gpu/ipu-v3/ipu-image-convert.c | 1 + drivers/staging/media/imx/imx-ic-prpencvf.c | 4 +- include/video/imx-ipu-v3.h | 5 +- 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c index e459615a49a1..0d57ca7ba18e 100644 --- a/drivers/gpu/ipu-v3/ipu-ic.c +++ b/drivers/gpu/ipu-v3/ipu-ic.c @@ -212,6 +212,23 @@ static const struct ic_csc_params ic_csc_identity = { .scale = 2, }; +/* + * BT.709 encoding from RGB full range to YUV limited range: + * + * Y = R * .2126 + G * .7152 + B * .0722; + * U = R * -.1146 + G * -.3854 + B * .5000 + 128.; + * V = R * .5000 + G * -.4542 + B * -.0458 + 128.; + */ +static const struct ic_csc_params ic_csc_rgb2ycbcr_bt709 = { + .coeff = { + { 54, 183, 18 }, + { 483, 413, 128 }, + { 128, 396, 500 }, + }, + .offset = { 0, 512, 512 }, + .scale = 1, +}; + /* * Inverse BT.601 encoding from YUV limited range to RGB full range: * @@ -229,12 +246,31 @@ static const struct ic_csc_params ic_csc_ycbcr2rgb_bt601 = { .scale = 2, }; +/* + * Inverse BT.709 encoding from YUV limited range to RGB full range: + * + * R = (1. * (Y - 16)) + (1.5748 * (Cr - 128)); + * G = (1. * (Y - 16)) - (0.1873 * (Cb - 128)) - (0.4681 * (Cr - 128)); + * B = (1. * (Y - 16)) + (1.8556 * (Cb - 128); + */ +static const struct ic_csc_params ic_csc_ycbcr2rgb_bt709 = { + .coeff = { + { 128, 0, 202 }, + { 128, 488, 452 }, + { 128, 238, 0 }, + }, + .offset = { -435, 136, -507 }, + .scale = 2, +}; + static int init_csc(struct ipu_ic *ic, enum ipu_color_space inf, enum ipu_color_space outf, + enum v4l2_ycbcr_encoding encoding, int csc_index) { struct ipu_ic_priv *priv = ic->priv; + const struct ic_csc_params *params_rgb2yuv, *params_yuv2rgb; const struct ic_csc_params *params; u32 __iomem *base; const u16 (*c)[3]; @@ -244,12 +280,30 @@ static int init_csc(struct ipu_ic *ic, base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); + switch (encoding) { + case V4L2_YCBCR_ENC_601: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt601; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt601; + break; + case V4L2_YCBCR_ENC_709: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt709; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt709; + break; + default: + if (inf != outf) { + dev_err(priv->ipu->dev, + "Unsupported YCbCr encoding\n"); + return -EINVAL; + } + break; + } + if (inf == outf) params = &ic_csc_identity; else if (inf == IPUV3_COLORSPACE_YUV) - params = &ic_csc_ycbcr2rgb_bt601; + params = &ic_csc_ycbcr2rgb; else - params = &ic_csc_rgb2ycbcr_bt601; + params = &ic_csc_rgb2ycbcr; /* Cast to unsigned */ c = (const u16 (*)[3])params->coeff; @@ -390,6 +444,7 @@ EXPORT_SYMBOL_GPL(ipu_ic_task_disable); int ipu_ic_task_graphics_init(struct ipu_ic *ic, enum ipu_color_space in_g_cs, + enum v4l2_ycbcr_encoding encoding, bool galpha_en, u32 galpha, bool colorkey_en, u32 colorkey) { @@ -408,7 +463,7 @@ int ipu_ic_task_graphics_init(struct ipu_ic *ic, if (!(ic_conf & ic->bit->ic_conf_csc1_en)) { /* need transparent CSC1 conversion */ ret = init_csc(ic, IPUV3_COLORSPACE_RGB, - IPUV3_COLORSPACE_RGB, 0); + IPUV3_COLORSPACE_RGB, encoding, 0); if (ret) goto unlock; } @@ -416,7 +471,7 @@ int ipu_ic_task_graphics_init(struct ipu_ic *ic, ic->g_in_cs = in_g_cs; if (ic->g_in_cs != ic->out_cs) { - ret = init_csc(ic, ic->g_in_cs, ic->out_cs, 1); + ret = init_csc(ic, ic->g_in_cs, ic->out_cs, encoding, 1); if (ret) goto unlock; } @@ -450,6 +505,7 @@ int ipu_ic_task_init_rsc(struct ipu_ic *ic, int out_width, int out_height,
Re: [GIT PULL] Staging/IIO driver fixes for 5.0-rc6
The pull request you sent on Fri, 8 Feb 2019 09:38:35 +0100: > git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git > tags/staging-5.0-rc6 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/e464f50c057a1fbefae6c6078f9bd5511f84f199 Thank you! -- Deet-doot-dot, I am a bot. https://korg.wiki.kernel.org/userdoc/prtracker ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 0/2] Drivers: hv: vmbus: Fix sysfs functions that display monitor id and page data
Some of the monitor id and monitor page data sysfs files display incorrect data. This patchset provides the following changes: 1) Change the monitor_pages index in server_monitor_pending_show() to '0', which is the correct index for the server. 2) If monitor pages are not allocated to a channel, display nothing in the channel's monitor id and monitor page data sysfs files. The data that is currently shown in sysfs is incorrect. Kimberly Brown (2): Drivers: hv: vmbus: Change server monitor_pages index to 0 Drivers: hv: vmbus: Display nothing in sysfs if monitor_allocated not set Documentation/ABI/stable/sysfs-bus-vmbus | 9 -- drivers/hv/vmbus_drv.c | 39 +++- 2 files changed, 44 insertions(+), 4 deletions(-) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 1/2] Drivers: hv: vmbus: Change server monitor_pages index to 0
Change the monitor_pages index in server_monitor_pending_show() to '0'. '0' is the correct monitor_pages index for the server. A comment for the monitor_pages field in the vmbus_connection struct definition indicates that the 1st page is for parent->child notifications. In addition, the server_monitor_latency_show() and server_monitor_conn_id_show() functions use monitor_pages index '0'. Signed-off-by: Kimberly Brown --- drivers/hv/vmbus_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 403fee01572c..f2a79f5129d7 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -234,7 +234,7 @@ static ssize_t server_monitor_pending_show(struct device *dev, return -ENODEV; return sprintf(buf, "%d\n", channel_pending(hv_dev->channel, - vmbus_connection.monitor_pages[1])); + vmbus_connection.monitor_pages[0])); } static DEVICE_ATTR_RO(server_monitor_pending); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH 2/2] Drivers: hv: vmbus: Display nothing in sysfs if monitor_allocated not set
If monitor pages are not allocated to a channel, the channel does not have a valid monitor id or valid monitor page data. In these cases, some of the "_show" functions display incorrect data. The "_show" functions that display monitor page data access and display data that is beyond the bounds of the hv_monitor_page array fields, which is obviously incorrect. The "_show" functions that display the monitor id display an invalid monitor id. The "channel->offermsg.monitor_allocated" value can be used to determine whether monitor pages have been allocated to a channel. In the affected "_show" functions, verify that "channel->offermsg.monitor_allocated" is set before accessing the monitor id or the monitor_page data. If "channel->offermsg.monitor_allocated" is not set, display nothing. Signed-off-by: Kimberly Brown --- Documentation/ABI/stable/sysfs-bus-vmbus | 9 -- drivers/hv/vmbus_drv.c | 37 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 3fed8fdb873d..af52be4ffc5d 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus @@ -81,7 +81,8 @@ What: /sys/bus/vmbus/devices//channels//latency Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger -Description: Channel signaling latency +Description: Channel signaling latency. If monitor pages are not allocated + to the channel, nothing is displayed. Users: Debugging tools What: /sys/bus/vmbus/devices//channels//out_mask @@ -95,7 +96,8 @@ What: /sys/bus/vmbus/devices//channels//pending Date: September. 2017 KernelVersion: 4.14 Contact: Stephen Hemminger -Description: Channel interrupt pending state +Description: Channel interrupt pending state. If monitor pages are not + allocated to the channel, nothing is displayed. Users: Debugging tools What: /sys/bus/vmbus/devices//channels//read_avail @@ -137,7 +139,8 @@ What: /sys/bus/vmbus/devices//channels//monitor_id Date: January. 2018 KernelVersion: 4.16 Contact: Stephen Hemminger -Description: Monitor bit associated with channel +Description: Monitor bit associated with channel. If monitor pages are not + allocated to the channel, nothing is displayed. Users: Debugging tools and userspace drivers What: /sys/bus/vmbus/devices//channels//ring diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index f2a79f5129d7..c88a3623be56 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -171,6 +171,10 @@ static ssize_t monitor_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; + + if (!hv_dev->channel->offermsg.monitor_allocated) + return sprintf(buf, "\n"); + return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid); } static DEVICE_ATTR_RO(monitor_id); @@ -232,6 +236,10 @@ static ssize_t server_monitor_pending_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; + + if (!hv_dev->channel->offermsg.monitor_allocated) + return sprintf(buf, "\n"); + return sprintf(buf, "%d\n", channel_pending(hv_dev->channel, vmbus_connection.monitor_pages[0])); @@ -246,6 +254,10 @@ static ssize_t client_monitor_pending_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; + + if (!hv_dev->channel->offermsg.monitor_allocated) + return sprintf(buf, "\n"); + return sprintf(buf, "%d\n", channel_pending(hv_dev->channel, vmbus_connection.monitor_pages[1])); @@ -260,6 +272,10 @@ static ssize_t server_monitor_latency_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; + + if (!hv_dev->channel->offermsg.monitor_allocated) + return sprintf(buf, "\n"); + return sprintf(buf, "%d\n", channel_latency(hv_dev->channel, vmbus_connection.monitor_pages[0])); @@ -274,6 +290,10 @@ static ssize_t client_monitor_latency_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; + + if (!hv_dev->channel->offermsg.monitor_allocated) + return sprintf(buf, "\n"); + return sprintf(buf, "%d\n", channel_latency(hv_dev->channel, vmbus_connection.monitor_pages[1])); @@ -288,6 +308,10 @@ static ssize_t server_monitor_conn_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; + + if (!hv_dev->channel->offermsg.monitor_allocated)
Re: [PATCH 1/2] Drivers: hv: vmbus: Change server monitor_pages index to 0
On Fri, 8 Feb 2019 04:58:52 -0500 Kimberly Brown wrote: > Change the monitor_pages index in server_monitor_pending_show() to '0'. > '0' is the correct monitor_pages index for the server. A comment for the > monitor_pages field in the vmbus_connection struct definition indicates > that the 1st page is for parent->child notifications. In addition, the > server_monitor_latency_show() and server_monitor_conn_id_show() > functions use monitor_pages index '0'. > > Signed-off-by: Kimberly Brown > --- > drivers/hv/vmbus_drv.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c > index 403fee01572c..f2a79f5129d7 100644 > --- a/drivers/hv/vmbus_drv.c > +++ b/drivers/hv/vmbus_drv.c > @@ -234,7 +234,7 @@ static ssize_t server_monitor_pending_show(struct device > *dev, > return -ENODEV; > return sprintf(buf, "%d\n", > channel_pending(hv_dev->channel, > -vmbus_connection.monitor_pages[1])); > +vmbus_connection.monitor_pages[0])); > } > static DEVICE_ATTR_RO(server_monitor_pending); Looks good. I wonder if ever gets used though since it returned incorrect data... Acked-by: Stephen Hemminger ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/2] Drivers: hv: vmbus: Display nothing in sysfs if monitor_allocated not set
On Fri, 8 Feb 2019 05:01:12 -0500 Kimberly Brown wrote: You are right, the current behavior is broken. It would be good to add a description of under what conditions monitor is not used. Is this some part of a project emulating Hyper-V? > + > + if (!hv_dev->channel->offermsg.monitor_allocated) > + return sprintf(buf, "\n"); If monitor is not used, why not return an error instead of empty data. Any program (or user) would have to handle that already. ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v3 3/4] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
On Fri, Feb 8, 2019 at 11:28 AM Steve Longerbeam wrote: > > Pass v4l2 encoding enum to the ipu_ic task init functions, and add > support for the BT.709 encoding and inverse encoding matrices. > > Reported-by: Tim Harvey > Signed-off-by: Steve Longerbeam > --- > Changes in v2: > - only return "Unsupported YCbCr encoding" error if inf != outf, > since if inf == outf, the identity matrix can be used. Reported > by Tim Harvey. > --- > drivers/gpu/ipu-v3/ipu-ic.c | 71 +++-- > drivers/gpu/ipu-v3/ipu-image-convert.c | 1 + > drivers/staging/media/imx/imx-ic-prpencvf.c | 4 +- > include/video/imx-ipu-v3.h | 5 +- > 4 files changed, 71 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c > index e459615a49a1..0d57ca7ba18e 100644 > --- a/drivers/gpu/ipu-v3/ipu-ic.c > +++ b/drivers/gpu/ipu-v3/ipu-ic.c > @@ -212,6 +212,23 @@ static const struct ic_csc_params ic_csc_identity = { > .scale = 2, > }; > > +/* > + * BT.709 encoding from RGB full range to YUV limited range: > + * > + * Y = R * .2126 + G * .7152 + B * .0722; > + * U = R * -.1146 + G * -.3854 + B * .5000 + 128.; > + * V = R * .5000 + G * -.4542 + B * -.0458 + 128.; > + */ > +static const struct ic_csc_params ic_csc_rgb2ycbcr_bt709 = { > + .coeff = { > + { 54, 183, 18 }, > + { 483, 413, 128 }, > + { 128, 396, 500 }, > + }, > + .offset = { 0, 512, 512 }, > + .scale = 1, > +}; > + > /* > * Inverse BT.601 encoding from YUV limited range to RGB full range: > * > @@ -229,12 +246,31 @@ static const struct ic_csc_params > ic_csc_ycbcr2rgb_bt601 = { > .scale = 2, > }; > > +/* > + * Inverse BT.709 encoding from YUV limited range to RGB full range: > + * > + * R = (1. * (Y - 16)) + (1.5748 * (Cr - 128)); > + * G = (1. * (Y - 16)) - (0.1873 * (Cb - 128)) - (0.4681 * (Cr - 128)); > + * B = (1. * (Y - 16)) + (1.8556 * (Cb - 128); > + */ > +static const struct ic_csc_params ic_csc_ycbcr2rgb_bt709 = { > + .coeff = { > + { 128, 0, 202 }, > + { 128, 488, 452 }, > + { 128, 238, 0 }, > + }, > + .offset = { -435, 136, -507 }, > + .scale = 2, > +}; > + > static int init_csc(struct ipu_ic *ic, > enum ipu_color_space inf, > enum ipu_color_space outf, > + enum v4l2_ycbcr_encoding encoding, > int csc_index) > { > struct ipu_ic_priv *priv = ic->priv; > + const struct ic_csc_params *params_rgb2yuv, *params_yuv2rgb; > const struct ic_csc_params *params; > u32 __iomem *base; > const u16 (*c)[3]; > @@ -244,12 +280,30 @@ static int init_csc(struct ipu_ic *ic, > base = (u32 __iomem *) > (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); > > + switch (encoding) { > + case V4L2_YCBCR_ENC_601: > + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt601; > + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt601; > + break; > + case V4L2_YCBCR_ENC_709: > + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt709; > + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt709; > + break; > + default: > + if (inf != outf) { > + dev_err(priv->ipu->dev, > + "Unsupported YCbCr encoding\n"); > + return -EINVAL; > + } > + break; > + } > + > if (inf == outf) > params = &ic_csc_identity; > else if (inf == IPUV3_COLORSPACE_YUV) > - params = &ic_csc_ycbcr2rgb_bt601; > + params = &ic_csc_ycbcr2rgb; Steve, compile issue... params = params_yuv2rgb; > else > - params = &ic_csc_rgb2ycbcr_bt601; > + params = &ic_csc_rgb2ycbcr; params = params_rgb2yuv; But, I'm still failing when using the mem2mem element (gst-launch-1.0 v4l2src device=/dev/video4 ! v4l2video8convert output-io-mode=dmabuf-import ! fbdevsink) with 'Unsupported YCbCr encoding' because of inf=IPU_COLORSPACE_YCBCR outf=IPU_COLORSPACE_RGB and a seemingly unset encoding being passed in. It looks like maybe something in the mem2mem driver isn't defaulting encoding. The call path is (v4l2_m2m_streamon -> device_run -> ipu_image_convert_queue -> convert_start -> ipu_ic_task_init_rsc -> init_csc). Tim ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 00/16] net: Remove switchdev_ops
Hi all, This patch series finishes by the removal of switchdev_ops. To get there we need to do a few things: - get rid of the one and only call to switchdev_port_attr_get() which is used to fetch the device's bridge port flags capabilities, instead we can just check what flags are being programmed during the prepare phase - once we get rid of getting switchdev port attributes we convert the setting of such attributes using a blocking notifier And then remove switchdev_ops completely. Please review and let me know what you think! Florian Fainelli (16): Documentation: networking: switchdev: Update port parent ID section mlxsw: spectrum: Check bridge flags during prepare phase staging: fsl-dpaa2: ethsw: Check bridge port flags during set net: dsa: Add setter for SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS rocker: Check bridge flags during prepare phase net: bridge: Stop calling switchdev_port_attr_get() net: Remove SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT net: Get rid of switchdev_port_attr_get() switchdev: Add SWITCHDEV_PORT_ATTR_SET rocker: Handle SWITCHDEV_PORT_ATTR_SET net: dsa: Handle SWITCHDEV_PORT_ATTR_SET mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_ATTR_SET net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_SET staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_ATTR_SET net: switchdev: Replace port attr set SDO with a notification net: Remove switchdev_ops Documentation/networking/switchdev.txt| 15 ++- .../net/ethernet/mellanox/mlxsw/spectrum.c| 12 --- .../net/ethernet/mellanox/mlxsw/spectrum.h| 2 - .../mellanox/mlxsw/spectrum_switchdev.c | 72 +- drivers/net/ethernet/mscc/ocelot.c| 25 - drivers/net/ethernet/rocker/rocker_main.c | 99 +-- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 52 +- include/linux/netdevice.h | 3 - include/net/switchdev.h | 37 ++- net/bridge/br_switchdev.c | 20 +--- net/dsa/dsa_priv.h| 3 + net/dsa/port.c| 10 ++ net/dsa/slave.c | 44 + net/switchdev/switchdev.c | 92 + 14 files changed, 190 insertions(+), 296 deletions(-) -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 04/16] net: dsa: Add setter for SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS
In preparation for removing SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, add support for a function that processes the SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS attribute and returns not supported for any flag set, since DSA does not currently support toggling those bridge port attributes (yet). Signed-off-by: Florian Fainelli --- net/dsa/dsa_priv.h | 3 +++ net/dsa/port.c | 10 ++ net/dsa/slave.c| 4 3 files changed, 17 insertions(+) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1f4972dab9f2..97594f0b6efb 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -150,6 +150,9 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans); int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, struct switchdev_trans *trans); +int dsa_port_bridge_port_flags_set(struct dsa_port *dp, + unsigned long brport_flags, + struct switchdev_trans *trans); int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid); int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, diff --git a/net/dsa/port.c b/net/dsa/port.c index 2d7e01b23572..2ce3752203cf 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -177,6 +177,16 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info); } +int dsa_port_bridge_port_flags_set(struct dsa_port *dp, + unsigned long brport_flags, + struct switchdev_trans *trans) +{ + if (brport_flags) + return -EOPNOTSUPP; + + return 0; +} + int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid) { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 70395a0ae52e..212fc1cc27fc 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -292,6 +292,10 @@ static int dsa_slave_port_attr_set(struct net_device *dev, case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: ret = dsa_port_ageing_time(dp, attr->u.ageing_time, trans); break; + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: + ret = dsa_port_bridge_port_flags_set(dp, attr->u.brport_flags, +trans); + break; default: ret = -EOPNOTSUPP; break; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 06/16] net: bridge: Stop calling switchdev_port_attr_get()
Now that all switchdev drivers have been converted to checking the bridge port flags during the prepare phase of the switchdev_port_attr_set(), we can move straight to trying to set the desired flag through SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS. Signed-off-by: Florian Fainelli --- net/bridge/br_switchdev.c | 20 +++- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index db9e8ab96d48..939f300522c5 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -64,29 +64,15 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, { struct switchdev_attr attr = { .orig_dev = p->dev, - .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, + .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, + .flags = SWITCHDEV_F_DEFER, + .u.brport_flags = flags, }; int err; if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD) return 0; - err = switchdev_port_attr_get(p->dev, &attr); - if (err == -EOPNOTSUPP) - return 0; - if (err) - return err; - - /* Check if specific bridge flag attribute offload is supported */ - if (!(attr.u.brport_flags_support & mask)) { - br_warn(p->br, "bridge flag offload is not supported %u(%s)\n", - (unsigned int)p->port_no, p->dev->name); - return -EOPNOTSUPP; - } - - attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS; - attr.flags = SWITCHDEV_F_DEFER; - attr.u.brport_flags = flags; err = switchdev_port_attr_set(p->dev, &attr); if (err) { br_warn(p->br, "error setting offload flag on port %u(%s)\n", -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 05/16] rocker: Check bridge flags during prepare phase
In preparation for getting rid of switchdev_port_attr_get(), have rocker check for the bridge flags being set through switchdev_port_attr_set() with the SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS attribute identifier. Signed-off-by: Florian Fainelli --- drivers/net/ethernet/rocker/rocker_main.c | 40 ++- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 66f72f8c46e5..8657313b6f30 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1565,18 +1565,42 @@ static int rocker_world_port_attr_stp_state_set(struct rocker_port *rocker_port, return wops->port_attr_stp_state_set(rocker_port, state); } +static int +rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port * + rocker_port, + unsigned long * + p_brport_flags_support) +{ + struct rocker_world_ops *wops = rocker_port->rocker->wops; + + if (!wops->port_attr_bridge_flags_support_get) + return -EOPNOTSUPP; + return wops->port_attr_bridge_flags_support_get(rocker_port, + p_brport_flags_support); +} + static int rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, unsigned long brport_flags, struct switchdev_trans *trans) { struct rocker_world_ops *wops = rocker_port->rocker->wops; + unsigned long brport_flags_s; + int err; if (!wops->port_attr_bridge_flags_set) return -EOPNOTSUPP; - if (switchdev_trans_ph_prepare(trans)) + if (switchdev_trans_ph_prepare(trans)) { + err = rocker_world_port_attr_bridge_flags_support_get(rocker_port, + &brport_flags_s); + if (err) + return err; + + if (brport_flags & ~brport_flags_s) + return -EOPNOTSUPP; return 0; + } return wops->port_attr_bridge_flags_set(rocker_port, brport_flags, trans); @@ -1593,20 +1617,6 @@ rocker_world_port_attr_bridge_flags_get(const struct rocker_port *rocker_port, return wops->port_attr_bridge_flags_get(rocker_port, p_brport_flags); } -static int -rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port * - rocker_port, - unsigned long * - p_brport_flags_support) -{ - struct rocker_world_ops *wops = rocker_port->rocker->wops; - - if (!wops->port_attr_bridge_flags_support_get) - return -EOPNOTSUPP; - return wops->port_attr_bridge_flags_support_get(rocker_port, - p_brport_flags_support); -} - static int rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port, u32 ageing_time, -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 02/16] mlxsw: spectrum: Check bridge flags during prepare phase
In preparation for getting rid of switchdev_port_attr_get(), have mlxsw check for the bridge flags being set through switchdev_port_attr_set() with the SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS attribute identifier. Signed-off-by: Florian Fainelli --- drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 95e37de3e48f..468a6d513074 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -623,8 +623,11 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_bridge_port *bridge_port; int err; - if (switchdev_trans_ph_prepare(trans)) + if (switchdev_trans_ph_prepare(trans)) { + if (brport_flags & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) + return -EOPNOTSUPP; return 0; + } bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp_port->mlxsw_sp->bridge, orig_dev); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 03/16] staging: fsl-dpaa2: ethsw: Check bridge port flags during set
In preparation for removing SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, have ethsw check that the bridge port flags that are being set are supported. Signed-off-by: Florian Fainelli --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index e559f4c25cf7..6228c4375835 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -680,8 +680,11 @@ static int port_attr_br_flags_set(struct net_device *netdev, struct ethsw_port_priv *port_priv = netdev_priv(netdev); int err = 0; - if (switchdev_trans_ph_prepare(trans)) + if (switchdev_trans_ph_prepare(trans)) { + if (flags & ~(BR_LEARNING | BR_FLOOD)) + return -EOPNOTSUPP; return 0; + } /* Learning is enabled per switch */ err = ethsw_set_learning(port_priv->ethsw_data, flags & BR_LEARNING); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 09/16] switchdev: Add SWITCHDEV_PORT_ATTR_SET
In preparation for allowing switchdev enabled drivers to veto specific attribute settings from within the context of the caller, introduce a new switchdev notifier type for port attributes. Suggested-by: Ido Schimmel Signed-off-by: Florian Fainelli --- include/net/switchdev.h | 9 + 1 file changed, 9 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 96cd3e795f7f..4c5f7e5430cf 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -141,6 +141,8 @@ enum switchdev_notifier_type { SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE, SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE, SWITCHDEV_VXLAN_FDB_OFFLOADED, + + SWITCHDEV_PORT_ATTR_SET, /* Blocking. */ }; struct switchdev_notifier_info { @@ -163,6 +165,13 @@ struct switchdev_notifier_port_obj_info { bool handled; }; +struct switchdev_notifier_port_attr_info { + struct switchdev_notifier_info info; /* must be first */ + const struct switchdev_attr *attr; + struct switchdev_trans *trans; + bool handled; +}; + static inline struct net_device * switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) { -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 08/16] net: Get rid of switchdev_port_attr_get()
With the bridge no longer calling switchdev_port_attr_get() to obtain the supported bridge port flags from a driver but instead trying to set the bridge port flags directly and relying on driver to reject unsupported configurations, we can effectively get rid of switchdev_port_attr_get() entirely since this was the only place where it was called. Signed-off-by: Florian Fainelli --- Documentation/networking/switchdev.txt| 5 ++- .../mellanox/mlxsw/spectrum_switchdev.c | 32 --- drivers/net/ethernet/rocker/rocker_main.c | 30 - drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 19 --- include/net/switchdev.h | 8 - net/dsa/slave.c | 7 6 files changed, 2 insertions(+), 99 deletions(-) diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index 2842f63ad47b..0d9530bf745b 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -233,9 +233,8 @@ the bridge's FDB. It's possible, but not optimal, to enable learning on the device port and on the bridge port, and disable learning_sync. To support learning and learning_sync port attributes, the driver implements -switchdev op switchdev_port_attr_get/set for -SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. The driver should initialize the attributes -to the hardware defaults. +switchdev op switchdev_port_attr_set for SWITCHDEV_ATTR_PORT_ID_BRIDGE_FLAGS. +The driver should initialize the attributes to the hardware defaults. FDB Ageing ^^ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 8242a373f6e7..6b09d68671cf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -431,37 +431,6 @@ static void mlxsw_sp_bridge_vlan_put(struct mlxsw_sp_bridge_vlan *bridge_vlan) mlxsw_sp_bridge_vlan_destroy(bridge_vlan); } -static void mlxsw_sp_port_bridge_flags_get(struct mlxsw_sp_bridge *bridge, - struct net_device *dev, - unsigned long *brport_flags) -{ - struct mlxsw_sp_bridge_port *bridge_port; - - bridge_port = mlxsw_sp_bridge_port_find(bridge, dev); - if (WARN_ON(!bridge_port)) - return; - - memcpy(brport_flags, &bridge_port->flags, sizeof(*brport_flags)); -} - -static int mlxsw_sp_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev, - &attr->u.brport_flags); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - static int mlxsw_sp_port_bridge_vlan_stp_set(struct mlxsw_sp_port *mlxsw_sp_port, struct mlxsw_sp_bridge_vlan *bridge_vlan, @@ -1957,7 +1926,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, } static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { - .switchdev_port_attr_get= mlxsw_sp_port_attr_get, .switchdev_port_attr_set= mlxsw_sp_port_attr_set, }; diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 375c4c908bea..ff3f14504f4f 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1606,17 +1606,6 @@ rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, trans); } -static int -rocker_world_port_attr_bridge_flags_get(const struct rocker_port *rocker_port, - unsigned long *p_brport_flags) -{ - struct rocker_world_ops *wops = rocker_port->rocker->wops; - - if (!wops->port_attr_bridge_flags_get) - return -EOPNOTSUPP; - return wops->port_attr_bridge_flags_get(rocker_port, p_brport_flags); -} - static int rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port, u32 ageing_time, @@ -2064,24 +2053,6 @@ static const struct net_device_ops rocker_port_netdev_ops = { * swdev interface / -static int rocker_port_attr_get(struct net_device *dev, - struct switchdev_attr *attr) -{ - const struct rocker_port *rocker_port = netdev_priv(dev); - int err = 0; - - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: - er
[PATCH net-next 01/16] Documentation: networking: switchdev: Update port parent ID section
Update the section about switchdev drivers having to implement a switchdev_port_attr_get() function to return SWITCHDEV_ATTR_ID_PORT_PARENT_ID since that is no longer valid after commit bccb30254a4a ("net: Get rid of SWITCHDEV_ATTR_ID_PORT_PARENT_ID"). Fixes: bccb30254a4a ("net: Get rid of SWITCHDEV_ATTR_ID_PORT_PARENT_ID") Signed-off-by: Florian Fainelli --- Documentation/networking/switchdev.txt | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/networking/switchdev.txt b/Documentation/networking/switchdev.txt index f3244d87512a..2842f63ad47b 100644 --- a/Documentation/networking/switchdev.txt +++ b/Documentation/networking/switchdev.txt @@ -92,11 +92,11 @@ device. Switch ID ^ -The switchdev driver must implement the switchdev op switchdev_port_attr_get -for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same -physical ID for each port of a switch. The ID must be unique between switches -on the same system. The ID does not need to be unique between switches on -different systems. +The switchdev driver must implement the net_device operation +ndo_get_port_parent_id for each port netdev, returning the same physical ID +for each port of a switch. The ID must be unique between switches on the same +system. The ID does not need to be unique between switches on different +systems. The switch ID is used to locate ports on a switch and to know if aggregated ports belong to the same switch. -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 14/16] staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_ATTR_SET
Following patches will change the way we communicate getting or setting a port's attribute and use a blocking notifier to perform those tasks. Prepare ethsw to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and simply translate that into the existing swdev_port_attr_set() call. Signed-off-by: Florian Fainelli --- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index b195b09e0d1d..d40bdcadd569 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -1092,6 +1092,24 @@ ethsw_switchdev_port_obj_event(unsigned long event, struct net_device *netdev, return notifier_from_errno(err); } +static int +ethsw_switchdev_port_attr_event(unsigned long event, + struct net_device *netdev, + struct switchdev_notifier_port_attr_info *port_attr_info) +{ + int err = -EOPNOTSUPP; + + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: + err = swdev_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); + break; + } + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + static int port_switchdev_blocking_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -1104,6 +1122,8 @@ static int port_switchdev_blocking_event(struct notifier_block *unused, case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ case SWITCHDEV_PORT_OBJ_DEL: return ethsw_switchdev_port_obj_event(event, dev, ptr); + case SWITCHDEV_PORT_ATTR_SET: + return ethsw_switchdev_port_attr_event(event, dev, ptr); } return NOTIFY_DONE; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 07/16] net: Remove SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT
Now that we have converted the bridge code and the drivers to check for bridge port(s) flags at the time we try to set them, there is no need for a get() -> set() sequence anymore and SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT therefore becomes unused. Signed-off-by: Florian Fainelli --- .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 4 drivers/net/ethernet/rocker/rocker_main.c | 4 drivers/staging/fsl-dpaa2/ethsw/ethsw.c| 3 --- include/net/switchdev.h| 2 -- net/dsa/slave.c| 10 +- 5 files changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 468a6d513074..8242a373f6e7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -455,10 +455,6 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev, mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev, &attr->u.brport_flags); break; - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD | - BR_MCAST_FLOOD; - break; default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 8657313b6f30..375c4c908bea 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2075,10 +2075,6 @@ static int rocker_port_attr_get(struct net_device *dev, err = rocker_world_port_attr_bridge_flags_get(rocker_port, &attr->u.brport_flags); break; - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - err = rocker_world_port_attr_bridge_flags_support_get(rocker_port, - &attr->u.brport_flags_support); - break; default: return -EOPNOTSUPP; } diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index 6228c4375835..79635d1091df 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -651,9 +651,6 @@ static int swdev_port_attr_get(struct net_device *netdev, (port_priv->ethsw_data->learning ? BR_LEARNING : 0) | (port_priv->flood ? BR_FLOOD : 0); break; - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD; - break; default: return -EOPNOTSUPP; } diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 5e87b54c5dc5..e2083824e577 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -45,7 +45,6 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, - SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, @@ -62,7 +61,6 @@ struct switchdev_attr { union { u8 stp_state; /* PORT_STP_STATE */ unsigned long brport_flags; /* PORT_BRIDGE_FLAGS */ - unsigned long brport_flags_support; /* PORT_BRIDGE_FLAGS_SUPPORT */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time;/* BRIDGE_AGEING_TIME */ bool vlan_filtering;/* BRIDGE_VLAN_FILTERING */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 212fc1cc27fc..5797da954e77 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -382,15 +382,7 @@ static int dsa_slave_get_port_parent_id(struct net_device *dev, static int dsa_slave_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { - switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT: - attr->u.brport_flags_support = 0; - break; - default: - return -EOPNOTSUPP; - } - - return 0; + return -EOPNOTSUPP; } static inline netdev_tx_t dsa_slave_netpoll_send_skb(struct net_device *dev, -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 12/16] mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_ATTR_SET
Following patches will change the way we communicate getting or setting a port's attribute and use a blocking notifier to perform those tasks. Prepare mlxsw to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and simply translate that into the existing mlxsw_sp_port_attr_set() call. Signed-off-by: Florian Fainelli --- .../mellanox/mlxsw/spectrum_switchdev.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 6b09d68671cf..29ffb5cac777 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -3410,6 +3410,23 @@ mlxsw_sp_switchdev_handle_vxlan_obj_del(struct net_device *vxlan_dev, } } +static int +mlxsw_sp_switchdev_port_attr_event(unsigned long event, struct net_device *dev, + struct switchdev_notifier_port_attr_info *port_attr_info) +{ + int err = -EOPNOTSUPP; + + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: + err = mlxsw_sp_port_attr_set(dev, port_attr_info->attr, +port_attr_info->trans); + break; + } + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -3433,6 +3450,8 @@ static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused, mlxsw_sp_port_dev_check, mlxsw_sp_port_obj_del); return notifier_from_errno(err); + case SWITCHDEV_PORT_ATTR_SET: + return mlxsw_sp_switchdev_port_attr_event(event, dev, ptr); } return NOTIFY_DONE; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 10/16] rocker: Handle SWITCHDEV_PORT_ATTR_SET
Following patches will change the way we communicate getting or setting a port's attribute and use a blocking notifier to perform those tasks. Prepare rocker to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and simply translate that into the existing rocker_port_attr_set call. Signed-off-by: Florian Fainelli --- drivers/net/ethernet/rocker/rocker_main.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index ff3f14504f4f..f10e4888ecff 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2811,6 +2811,24 @@ rocker_switchdev_port_obj_event(unsigned long event, struct net_device *netdev, return notifier_from_errno(err); } +static int +rocker_switchdev_port_attr_event(unsigned long event, struct net_device *netdev, +struct switchdev_notifier_port_attr_info +*port_attr_info) +{ + int err = -EOPNOTSUPP; + + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: + err = rocker_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); + break; + } + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + static int rocker_switchdev_blocking_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -2823,6 +2841,8 @@ static int rocker_switchdev_blocking_event(struct notifier_block *unused, case SWITCHDEV_PORT_OBJ_ADD: case SWITCHDEV_PORT_OBJ_DEL: return rocker_switchdev_port_obj_event(event, dev, ptr); + case SWITCHDEV_PORT_ATTR_SET: + return rocker_switchdev_port_attr_event(event, dev, ptr); } return NOTIFY_DONE; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 13/16] net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_SET
Following patches will change the way we communicate getting or setting a port's attribute and use a blocking notifier to perform those tasks. Prepare ocelot to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and simply translate that into the existing ocelot_port_attr_set() call. Signed-off-by: Florian Fainelli --- drivers/net/ethernet/mscc/ocelot.c | 24 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 195306d05bcd..adab478d36f1 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1324,10 +1324,6 @@ static int ocelot_port_obj_del(struct net_device *dev, return ret; } -static const struct switchdev_ops ocelot_port_switchdev_ops = { - .switchdev_port_attr_set= ocelot_port_attr_set, -}; - static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port, struct net_device *bridge) { @@ -1582,6 +1578,24 @@ struct notifier_block ocelot_netdevice_nb __read_mostly = { }; EXPORT_SYMBOL(ocelot_netdevice_nb); +static int +ocelot_switchdev_port_attr_event(unsigned long event, + struct net_device *netdev, + struct switchdev_notifier_port_attr_info *port_attr_info) +{ + int err = -EOPNOTSUPP; + + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: + err = ocelot_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); + break; + } + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + static int ocelot_switchdev_blocking_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -1600,6 +1614,8 @@ static int ocelot_switchdev_blocking_event(struct notifier_block *unused, ocelot_netdevice_dev_check, ocelot_port_obj_del); return notifier_from_errno(err); + case SWITCHDEV_PORT_ATTR_SET: + return ocelot_switchdev_port_attr_event(event, dev, ptr); } return NOTIFY_DONE; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 15/16] net: switchdev: Replace port attr set SDO with a notification
Drop switchdev_ops.switchdev_port_attr_set. Drop the uses of this field from all clients, which were migrated to use switchdev notification in the previous patches. Add a new function switchdev_port_attr_notify() that sends the switchdev notifications SWITCHDEV_PORT_ATTR_SET. Drop __switchdev_port_attr_set() and update switchdev_port_attr_set() likewise. Signed-off-by: Florian Fainelli --- include/net/switchdev.h | 18 net/switchdev/switchdev.c | 92 ++- 2 files changed, 22 insertions(+), 88 deletions(-) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 4c5f7e5430cf..5387ff6f41c5 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -111,21 +111,6 @@ void *switchdev_trans_item_dequeue(struct switchdev_trans *trans); typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); -/** - * struct switchdev_ops - switchdev operations - * - * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr). - * - * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). - */ -struct switchdev_ops { - int (*switchdev_port_attr_get)(struct net_device *dev, - struct switchdev_attr *attr); - int (*switchdev_port_attr_set)(struct net_device *dev, - const struct switchdev_attr *attr, - struct switchdev_trans *trans); -}; - enum switchdev_notifier_type { SWITCHDEV_FDB_ADD_TO_BRIDGE = 1, SWITCHDEV_FDB_DEL_TO_BRIDGE, @@ -224,7 +209,6 @@ int switchdev_handle_port_obj_del(struct net_device *dev, int (*del_cb)(struct net_device *dev, const struct switchdev_obj *obj)); -#define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops)) #else static inline void switchdev_deferred_process(void) @@ -311,8 +295,6 @@ switchdev_handle_port_obj_del(struct net_device *dev, return 0; } -#define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0) - #endif #endif /* _LINUX_SWITCHDEV_H_ */ diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 7e1357db33d7..5a053e20363e 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -174,81 +174,31 @@ static int switchdev_deferred_enqueue(struct net_device *dev, return 0; } -/** - * switchdev_port_attr_get - Get port attribute - * - * @dev: port device - * @attr: attribute to get - */ -int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) +static int switchdev_port_attr_notify(enum switchdev_notifier_type nt, + struct net_device *dev, + struct switchdev_attr *attr, + struct switchdev_trans *trans) { - const struct switchdev_ops *ops = dev->switchdev_ops; - struct net_device *lower_dev; - struct list_head *iter; - struct switchdev_attr first = { - .id = SWITCHDEV_ATTR_ID_UNDEFINED - }; - int err = -EOPNOTSUPP; + int err; + int rc; - if (ops && ops->switchdev_port_attr_get) - return ops->switchdev_port_attr_get(dev, attr); + struct switchdev_notifier_port_attr_info attr_info = { + .attr = attr, + .trans = trans, + .handled = false, + }; - if (attr->flags & SWITCHDEV_F_NO_RECURSE) + rc = call_switchdev_blocking_notifiers(nt, dev, &attr_info.info, NULL); + err = notifier_to_errno(rc); + if (err) { + WARN_ON(!attr_info.handled); return err; - - /* Switch device port(s) may be stacked under -* bond/team/vlan dev, so recurse down to get attr on -* each port. Return -ENODATA if attr values don't -* compare across ports. -*/ - - netdev_for_each_lower_dev(dev, lower_dev, iter) { - err = switchdev_port_attr_get(lower_dev, attr); - if (err) - break; - if (first.id == SWITCHDEV_ATTR_ID_UNDEFINED) - first = *attr; - else if (memcmp(&first, attr, sizeof(*attr))) - return -ENODATA; } - return err; -} -EXPORT_SYMBOL_GPL(switchdev_port_attr_get); - -static int __switchdev_port_attr_set(struct net_device *dev, -const struct switchdev_attr *attr, -struct switchdev_trans *trans) -{ - const struct switchdev_ops *ops = dev->switchdev_ops; - struct net_device *lower_dev; - struct list_head *iter; - int err = -EOPNOTSUPP; - - if (ops && ops->switchdev_port_attr_set) { - err = ops->switchdev_port_attr_set(dev, attr, trans); - goto done; - } - - if (attr->flags & SWITCH
[PATCH net-next 11/16] net: dsa: Handle SWITCHDEV_PORT_ATTR_SET
Following patches will change the way we communicate getting or setting a port's attribute and use a blocking notifier to perform those tasks. Prepare DSA to support receiving notifier events targeting SWITCHDEV_PORT_ATTR_SET and simply translate that into the existing dsa_slave_port_attr_set() call. Signed-off-by: Florian Fainelli --- net/dsa/slave.c | 20 1 file changed, 20 insertions(+) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index ae34be949d79..f8c7c1b2cd2f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1544,6 +1544,24 @@ dsa_slave_switchdev_port_obj_event(unsigned long event, return notifier_from_errno(err); } +static int +dsa_slave_switchdev_port_attr_event(unsigned long event, + struct net_device *netdev, + struct switchdev_notifier_port_attr_info *port_attr_info) +{ + int err = -EOPNOTSUPP; + + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: + err = dsa_slave_port_attr_set(netdev, port_attr_info->attr, + port_attr_info->trans); + break; + } + + port_attr_info->handled = true; + return notifier_from_errno(err); +} + static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, unsigned long event, void *ptr) { @@ -1556,6 +1574,8 @@ static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ case SWITCHDEV_PORT_OBJ_DEL: return dsa_slave_switchdev_port_obj_event(event, dev, ptr); + case SWITCHDEV_PORT_ATTR_SET: /* fallthrough */ + return dsa_slave_switchdev_port_attr_event(event, dev, ptr); } return NOTIFY_DONE; -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH net-next 16/16] net: Remove switchdev_ops
Now that we have converted all possible callers to using a switchdev notifier for attributes we do not have a need for implementing switchdev_ops anymore, and this can be removed from all drivers the net_device structure. Signed-off-by: Florian Fainelli --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 12 drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 -- .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 drivers/net/ethernet/mscc/ocelot.c | 1 - drivers/net/ethernet/rocker/rocker_main.c| 5 - drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 5 - include/linux/netdevice.h| 3 --- net/dsa/slave.c | 5 - 8 files changed, 45 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 8dd808b7f931..18b56afbd5d7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3220,7 +3220,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, } mlxsw_sp_port->default_vlan = mlxsw_sp_port_vlan; - mlxsw_sp_port_switchdev_init(mlxsw_sp_port); mlxsw_sp->ports[local_port] = mlxsw_sp_port; err = register_netdev(dev); if (err) { @@ -3237,7 +3236,6 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port, err_register_netdev: mlxsw_sp->ports[local_port] = NULL; - mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_vlan_destroy(mlxsw_sp_port_vlan); err_port_vlan_create: err_port_pvid_set: @@ -3280,7 +3278,6 @@ static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port) mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp); unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */ mlxsw_sp->ports[local_port] = NULL; - mlxsw_sp_port_switchdev_fini(mlxsw_sp_port); mlxsw_sp_port_vlan_flush(mlxsw_sp_port, true); mlxsw_sp_port_nve_fini(mlxsw_sp_port); mlxsw_sp_tc_qdisc_fini(mlxsw_sp_port); @@ -4001,12 +3998,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, goto err_span_init; } - err = mlxsw_sp_switchdev_init(mlxsw_sp); - if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize switchdev\n"); - goto err_switchdev_init; - } - err = mlxsw_sp_counter_pool_init(mlxsw_sp); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to init counter pool\n"); @@ -4077,8 +4068,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, err_afa_init: mlxsw_sp_counter_pool_fini(mlxsw_sp); err_counter_pool_init: - mlxsw_sp_switchdev_fini(mlxsw_sp); -err_switchdev_init: mlxsw_sp_span_fini(mlxsw_sp); err_span_init: mlxsw_sp_lag_fini(mlxsw_sp); @@ -4141,7 +4130,6 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core) mlxsw_sp_nve_fini(mlxsw_sp); mlxsw_sp_afa_fini(mlxsw_sp); mlxsw_sp_counter_pool_fini(mlxsw_sp); - mlxsw_sp_switchdev_fini(mlxsw_sp); mlxsw_sp_span_fini(mlxsw_sp); mlxsw_sp_lag_fini(mlxsw_sp); mlxsw_sp_buffers_fini(mlxsw_sp); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4fe0996c7cdd..76f51087e35a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -375,8 +375,6 @@ u32 mlxsw_sp_bytes_cells(const struct mlxsw_sp *mlxsw_sp, u32 bytes); /* spectrum_switchdev.c */ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp); -void mlxsw_sp_port_switchdev_init(struct mlxsw_sp_port *mlxsw_sp_port); -void mlxsw_sp_port_switchdev_fini(struct mlxsw_sp_port *mlxsw_sp_port); int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid, bool adding); void diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 29ffb5cac777..9951cfe0b244 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1925,10 +1925,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp, return NULL; } -static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = { - .switchdev_port_attr_set= mlxsw_sp_port_attr_set, -}; - static int mlxsw_sp_bridge_8021q_port_join(struct mlxsw_sp_bridge_device *bridge_device, struct mlxsw_sp_bridge_port *bridge_port, @@ -3539,11 +3535,3 @@ void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp) kfree(mlxsw_sp->bridge); } -void mlxsw_sp_port_swi
Re: [PATCH net-next 15/16] net: switchdev: Replace port attr set SDO with a notification
On 2/8/19 4:32 PM, Florian Fainelli wrote: > Drop switchdev_ops.switchdev_port_attr_set. Drop the uses of this field > from all clients, which were migrated to use switchdev notification in > the previous patches. > > Add a new function switchdev_port_attr_notify() that sends the switchdev > notifications SWITCHDEV_PORT_ATTR_SET. > > Drop __switchdev_port_attr_set() and update switchdev_port_attr_set() > likewise. > > Signed-off-by: Florian Fainelli > --- > include/net/switchdev.h | 18 > net/switchdev/switchdev.c | 92 ++- > 2 files changed, 22 insertions(+), 88 deletions(-) > > diff --git a/include/net/switchdev.h b/include/net/switchdev.h > index 4c5f7e5430cf..5387ff6f41c5 100644 > --- a/include/net/switchdev.h > +++ b/include/net/switchdev.h > @@ -111,21 +111,6 @@ void *switchdev_trans_item_dequeue(struct > switchdev_trans *trans); > > typedef int switchdev_obj_dump_cb_t(struct switchdev_obj *obj); > > -/** > - * struct switchdev_ops - switchdev operations > - * > - * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr). > - * > - * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr). > - */ > -struct switchdev_ops { > - int (*switchdev_port_attr_get)(struct net_device *dev, > -struct switchdev_attr *attr); > - int (*switchdev_port_attr_set)(struct net_device *dev, > -const struct switchdev_attr *attr, > -struct switchdev_trans *trans); > -}; > - This and the hunk below bisection, I will move that into patch #16 after receiving feedback on this. -- Florian ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH v3 3/4] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
On 2/8/19 4:20 PM, Tim Harvey wrote: On Fri, Feb 8, 2019 at 11:28 AM Steve Longerbeam wrote: if (inf == outf) params = &ic_csc_identity; else if (inf == IPUV3_COLORSPACE_YUV) - params = &ic_csc_ycbcr2rgb_bt601; + params = &ic_csc_ycbcr2rgb; Steve, compile issue... params = params_yuv2rgb; else - params = &ic_csc_rgb2ycbcr_bt601; + params = &ic_csc_rgb2ycbcr; params = params_rgb2yuv; Wow, did I not even compile test that? Must be my head cold :-/ Sending v4. But, I'm still failing when using the mem2mem element (gst-launch-1.0 v4l2src device=/dev/video4 ! v4l2video8convert output-io-mode=dmabuf-import ! fbdevsink) with 'Unsupported YCbCr encoding' because of inf=IPU_COLORSPACE_YCBCR outf=IPU_COLORSPACE_RGB and a seemingly unset encoding being passed in. It looks like maybe something in the mem2mem driver isn't defaulting encoding. The call path is (v4l2_m2m_streamon -> device_run -> ipu_image_convert_queue -> convert_start -> ipu_ic_task_init_rsc -> init_csc). Looking at v7 of the mem2mem driver, it will set ycbcr_enc at the output side to V4L2_YCBCR_ENC_DEFAULT if colorspace is default. So colorspace will need to be set to something non-default in addition to setting ycbcr_enc, at the output side. I don't know whether gstreamer v4l2videoNconvertelement will do this, but you could hack the driver for now to get around it, and let Philipp know this may need a workaround in mem2mem for v8. Steve ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v4 4/4] media: imx: Allow BT.709 encoding for IC routes
The IC now supports BT.709 Y'CbCr encoding, in addition to existing BT.601 encoding, so allow both, for pipelines that route through the IC. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v2: - move ic_route check above default colorimetry checks, and fill default colorimetry for ic_route, otherwise it's not possible to set BT.709 encoding for ic routes. --- drivers/staging/media/imx/imx-media-utils.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 5f110d90a4ef..dde0e47550d7 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -544,6 +544,19 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, if (tryfmt->field == V4L2_FIELD_ANY) tryfmt->field = fmt->field; + if (ic_route) { + if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) + tryfmt->colorspace = fmt->colorspace; + + tryfmt->quantization = is_rgb ? + V4L2_QUANTIZATION_FULL_RANGE : + V4L2_QUANTIZATION_LIM_RANGE; + + if (tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_601 && + tryfmt->ycbcr_enc != V4L2_YCBCR_ENC_709) + tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; + } + /* fill colorimetry if necessary */ if (tryfmt->colorspace == V4L2_COLORSPACE_DEFAULT) { tryfmt->colorspace = fmt->colorspace; @@ -566,13 +579,6 @@ void imx_media_fill_default_mbus_fields(struct v4l2_mbus_framefmt *tryfmt, tryfmt->ycbcr_enc); } } - - if (ic_route) { - tryfmt->quantization = is_rgb ? - V4L2_QUANTIZATION_FULL_RANGE : - V4L2_QUANTIZATION_LIM_RANGE; - tryfmt->ycbcr_enc = V4L2_YCBCR_ENC_601; - } } EXPORT_SYMBOL_GPL(imx_media_fill_default_mbus_fields); -- 2.17.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH v4 3/4] gpu: ipu-v3: ipu-ic: Add support for BT.709 encoding
Pass v4l2 encoding enum to the ipu_ic task init functions, and add support for the BT.709 encoding and inverse encoding matrices. Reported-by: Tim Harvey Signed-off-by: Steve Longerbeam --- Changes in v4: - fix compile error. Chnges in v3: - none. Changes in v2: - only return "Unsupported YCbCr encoding" error if inf != outf, since if inf == outf, the identity matrix can be used. Reported by Tim Harvey. --- drivers/gpu/ipu-v3/ipu-ic.c | 71 +++-- drivers/gpu/ipu-v3/ipu-image-convert.c | 1 + drivers/staging/media/imx/imx-ic-prpencvf.c | 4 +- include/video/imx-ipu-v3.h | 5 +- 4 files changed, 71 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/ipu-v3/ipu-ic.c b/drivers/gpu/ipu-v3/ipu-ic.c index e459615a49a1..c5f83d7e357f 100644 --- a/drivers/gpu/ipu-v3/ipu-ic.c +++ b/drivers/gpu/ipu-v3/ipu-ic.c @@ -212,6 +212,23 @@ static const struct ic_csc_params ic_csc_identity = { .scale = 2, }; +/* + * BT.709 encoding from RGB full range to YUV limited range: + * + * Y = R * .2126 + G * .7152 + B * .0722; + * U = R * -.1146 + G * -.3854 + B * .5000 + 128.; + * V = R * .5000 + G * -.4542 + B * -.0458 + 128.; + */ +static const struct ic_csc_params ic_csc_rgb2ycbcr_bt709 = { + .coeff = { + { 54, 183, 18 }, + { 483, 413, 128 }, + { 128, 396, 500 }, + }, + .offset = { 0, 512, 512 }, + .scale = 1, +}; + /* * Inverse BT.601 encoding from YUV limited range to RGB full range: * @@ -229,12 +246,31 @@ static const struct ic_csc_params ic_csc_ycbcr2rgb_bt601 = { .scale = 2, }; +/* + * Inverse BT.709 encoding from YUV limited range to RGB full range: + * + * R = (1. * (Y - 16)) + (1.5748 * (Cr - 128)); + * G = (1. * (Y - 16)) - (0.1873 * (Cb - 128)) - (0.4681 * (Cr - 128)); + * B = (1. * (Y - 16)) + (1.8556 * (Cb - 128); + */ +static const struct ic_csc_params ic_csc_ycbcr2rgb_bt709 = { + .coeff = { + { 128, 0, 202 }, + { 128, 488, 452 }, + { 128, 238, 0 }, + }, + .offset = { -435, 136, -507 }, + .scale = 2, +}; + static int init_csc(struct ipu_ic *ic, enum ipu_color_space inf, enum ipu_color_space outf, + enum v4l2_ycbcr_encoding encoding, int csc_index) { struct ipu_ic_priv *priv = ic->priv; + const struct ic_csc_params *params_rgb2yuv, *params_yuv2rgb; const struct ic_csc_params *params; u32 __iomem *base; const u16 (*c)[3]; @@ -244,12 +280,30 @@ static int init_csc(struct ipu_ic *ic, base = (u32 __iomem *) (priv->tpmem_base + ic->reg->tpmem_csc[csc_index]); + switch (encoding) { + case V4L2_YCBCR_ENC_601: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt601; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt601; + break; + case V4L2_YCBCR_ENC_709: + params_rgb2yuv = &ic_csc_rgb2ycbcr_bt709; + params_yuv2rgb = &ic_csc_ycbcr2rgb_bt709; + break; + default: + if (inf != outf) { + dev_err(priv->ipu->dev, + "Unsupported YCbCr encoding\n"); + return -EINVAL; + } + break; + } + if (inf == outf) params = &ic_csc_identity; else if (inf == IPUV3_COLORSPACE_YUV) - params = &ic_csc_ycbcr2rgb_bt601; + params = params_yuv2rgb; else - params = &ic_csc_rgb2ycbcr_bt601; + params = params_rgb2yuv; /* Cast to unsigned */ c = (const u16 (*)[3])params->coeff; @@ -390,6 +444,7 @@ EXPORT_SYMBOL_GPL(ipu_ic_task_disable); int ipu_ic_task_graphics_init(struct ipu_ic *ic, enum ipu_color_space in_g_cs, + enum v4l2_ycbcr_encoding encoding, bool galpha_en, u32 galpha, bool colorkey_en, u32 colorkey) { @@ -408,7 +463,7 @@ int ipu_ic_task_graphics_init(struct ipu_ic *ic, if (!(ic_conf & ic->bit->ic_conf_csc1_en)) { /* need transparent CSC1 conversion */ ret = init_csc(ic, IPUV3_COLORSPACE_RGB, - IPUV3_COLORSPACE_RGB, 0); + IPUV3_COLORSPACE_RGB, encoding, 0); if (ret) goto unlock; } @@ -416,7 +471,7 @@ int ipu_ic_task_graphics_init(struct ipu_ic *ic, ic->g_in_cs = in_g_cs; if (ic->g_in_cs != ic->out_cs) { - ret = init_csc(ic, ic->g_in_cs, ic->out_cs, 1); + ret = init_csc(ic, ic->g_in_cs, ic->out_cs, encoding, 1); if (ret) goto unlock; } @@ -450,6 +505,7 @@ int ipu_ic_task_init_rsc(struct ipu_ic *ic,
Re: [PATCH 2/2] staging: android: ashmem: Don't allow range_alloc() to fail.
On 2019/02/08 23:45, Joel Fernandes wrote: > On Wed, Feb 06, 2019 at 08:45:32AM +0900, Tetsuo Handa wrote: >> Joel Fernandes wrote: >>> On Tue, Feb 05, 2019 at 07:28:41PM +0900, Tetsuo Handa wrote: ashmem_pin() is calling range_shrink() without checking whether range_alloc() succeeded. Since memory allocation fault injection might force range_alloc() to fail while range_alloc() is called for only once for one ioctl() request, make range_alloc() not to fail. >>> >>> Why does this not need to fail? I am worried your change will introduce >>> unwanted endless looping in the kernel instead of gracefully failing a >>> pin/unpin request. >> >> This patch won't introduce endless looping in the kernel, due to a rule >> called >> >> The "too small to fail" memory-allocation rule >> https://lwn.net/Articles/627419/ >> >> . In short, memory allocation by range_alloc() might fail only if current >> thread >> was killed by the OOM killer or memory allocation fault injection mechanism >> forced it to fail. And this patch helps doing fuzzing test with minimal >> changes. >> >>> >>> Unless there is a good reason, I suggest to drop this patch from the series; >>> but let us discuss more if you want. >> >> We can allocate memory for range_alloc() before holding ashmem_mutex at >> ashmem_pin_unpin() if you don't want to use __GFP_NOFAIL. It is better to >> avoid memory allocation with ashmem_mutex because ashmem_mutex is held by >> shrinker function. But given that this module is going to be replaced >> shortly, >> does it worth moving the memory allocation to the caller? > > Even if memory allocation does not fail right now, I still want to return the > error code correctly via ashmem_pin_unpin() so that if in the future there > are changes to the allocator algorithm, then a silent success isn't reported > when a failure should be reported.. > > It doesn't make sense to return success when an allocation failed.. even if > you are asking this code to rely on the allocator's "too small to fail" > behavior.. can we guarantee this allocator behavior will always exist? > Probably not. > Does always exist. Small GFP_KERNEL allocation without __GFP_NORETRY or __GFP_RETRY_MAYFAIL won't fail unless current thread was killed by the OOM killer or memory allocation fault injection mechanism forced it to fail. Failing such allocation instead of invoking the OOM killer is effectively equivalent to sending SIGKILL to current thread. If current thread got SIGKILL, current thread can't receive the error code of ioctl() from ashmem_pin_unpin() because userspace code is no longer executed. MM people want to make !GFP_KERNEL memory allocations fail rather than retry forever. But failing small GFP_KERNEL memory allocations is such a horrible idea. Anyway, here is an updated patch... >From f2c8a098ebf69122fc440d9e9ca3c9cd786cce8a Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 9 Feb 2019 11:07:07 +0900 Subject: [PATCH] staging: android: ashmem: Avoid range_alloc() allocation with ashmem_mutex held. ashmem_pin() is calling range_shrink() without checking whether range_alloc() succeeded. Also, doing memory allocation with ashmem_mutex held should be avoided because ashmem_shrink_scan() tries to hold it. Therefore, move memory allocation for range_alloc() to ashmem_pin_unpin() and make range_alloc() not to fail. Signed-off-by: Tetsuo Handa --- drivers/staging/android/ashmem.c | 42 +++- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index ade8438..910826d 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -171,19 +171,15 @@ static inline void lru_del(struct ashmem_range *range) * @end: The ending page (inclusive) * * This function is protected by ashmem_mutex. - * - * Return: 0 if successful, or -ENOMEM if there is an error */ -static int range_alloc(struct ashmem_area *asma, - struct ashmem_range *prev_range, unsigned int purged, - size_t start, size_t end) +static void range_alloc(struct ashmem_area *asma, + struct ashmem_range *prev_range, unsigned int purged, + size_t start, size_t end, + struct ashmem_range **new_range) { - struct ashmem_range *range; - - range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL); - if (!range) - return -ENOMEM; + struct ashmem_range *range = *new_range; + *new_range = NULL; range->asma = asma; range->pgstart = start; range->pgend = end; @@ -193,8 +189,6 @@ static int range_alloc(struct ashmem_area *asma, if (range_on_lru(range)) lru_add(range); - - return 0; } /** @@ -596,7 +590,8 @@ static int get_name(struct ashmem_area *asma, void __user *name) * * Caller must hold ashm