Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'samsung-drivers-exynos-mfc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into next/drivers

Topic branch for Exynos MFC changes for v4.8:
Pull s5p-mfc changes from media tree so the arm/mach-exynos code
could be removed. The bindings are converted to generic reserved memory
bindings.

* tag 'samsung-drivers-exynos-mfc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux:
ARM: dts: exynos: Enable MFC device on Exynos4412 Odroid boards
ARM: dts: exynos: Convert MFC device to generic reserved memory bindings
ARM: EXYNOS: Remove code for MFC custom reserved memory handling
media: s5p-mfc: add iommu support
media: s5p-mfc: replace custom reserved memory handling code with generic one
media: s5p-mfc: use generic reserved memory bindings
of: reserved_mem: add support for using more than one region for given device
media: set proper max seg size for devices on Exynos SoCs
media: vb2-dma-contig: add helper for setting dma max seg size
s5p-mfc: Fix race between s5p_mfc_probe() and s5p_mfc_open()
s5p-mfc: Add release callback for memory region devs
s5p-mfc: Set device name for reserved memory region devs

Signed-off-by: Olof Johansson <olof@lixom.net>

+448 -280
+31 -8
Documentation/devicetree/bindings/media/s5p-mfc.txt
··· 21 21 - clock-names : from common clock binding: must contain "mfc", 22 22 corresponding to entry in the clocks property. 23 23 24 - - samsung,mfc-r : Base address of the first memory bank used by MFC 25 - for DMA contiguous memory allocation and its size. 26 - 27 - - samsung,mfc-l : Base address of the second memory bank used by MFC 28 - for DMA contiguous memory allocation and its size. 29 - 30 24 Optional properties: 31 25 - power-domains : power-domain property defined with a phandle 32 26 to respective power domain. 27 + - memory-region : from reserved memory binding: phandles to two reserved 28 + memory regions, first is for "left" mfc memory bus interfaces, 29 + second if for the "right" mfc memory bus, used when no SYSMMU 30 + support is available 31 + 32 + Obsolete properties: 33 + - samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region 34 + property instead 35 + 33 36 34 37 Example: 35 38 SoC specific DT entry: ··· 46 43 clock-names = "mfc"; 47 44 }; 48 45 46 + Reserved memory specific DT entry for given board (see reserved memory binding 47 + for more information): 48 + 49 + reserved-memory { 50 + #address-cells = <1>; 51 + #size-cells = <1>; 52 + ranges; 53 + 54 + mfc_left: region@51000000 { 55 + compatible = "shared-dma-pool"; 56 + no-map; 57 + reg = <0x51000000 0x800000>; 58 + }; 59 + 60 + mfc_right: region@43000000 { 61 + compatible = "shared-dma-pool"; 62 + no-map; 63 + reg = <0x43000000 0x800000>; 64 + }; 65 + }; 66 + 49 67 Board specific DT entry: 50 68 51 69 codec@13400000 { 52 - samsung,mfc-r = <0x43000000 0x800000>; 53 - samsung,mfc-l = <0x51000000 0x800000>; 70 + memory-region = <&mfc_left>, <&mfc_right>; 54 71 };
+29
arch/arm/boot/dts/exynos-mfc-reserved-memory.dtsi
··· 1 + /* 2 + * Samsung's Exynos SoC MFC (Video Codec) reserved memory common definition. 3 + * 4 + * Copyright (c) 2016 Samsung Electronics Co., Ltd 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + / { 12 + reserved-memory { 13 + #address-cells = <1>; 14 + #size-cells = <1>; 15 + ranges; 16 + 17 + mfc_left: region@51000000 { 18 + compatible = "shared-dma-pool"; 19 + no-map; 20 + reg = <0x51000000 0x800000>; 21 + }; 22 + 23 + mfc_right: region@43000000 { 24 + compatible = "shared-dma-pool"; 25 + no-map; 26 + reg = <0x43000000 0x800000>; 27 + }; 28 + }; 29 + };
+2 -2
arch/arm/boot/dts/exynos4210-origen.dts
··· 18 18 #include "exynos4210.dtsi" 19 19 #include <dt-bindings/gpio/gpio.h> 20 20 #include <dt-bindings/input/input.h> 21 + #include "exynos-mfc-reserved-memory.dtsi" 21 22 22 23 / { 23 24 model = "Insignal Origen evaluation board based on Exynos4210"; ··· 289 288 }; 290 289 291 290 &mfc { 292 - samsung,mfc-r = <0x43000000 0x800000>; 293 - samsung,mfc-l = <0x51000000 0x800000>; 291 + memory-region = <&mfc_left>, <&mfc_right>; 294 292 status = "okay"; 295 293 }; 296 294
+2 -2
arch/arm/boot/dts/exynos4210-smdkv310.dts
··· 17 17 /dts-v1/; 18 18 #include "exynos4210.dtsi" 19 19 #include <dt-bindings/gpio/gpio.h> 20 + #include "exynos-mfc-reserved-memory.dtsi" 20 21 21 22 / { 22 23 model = "Samsung smdkv310 evaluation board based on Exynos4210"; ··· 134 133 }; 135 134 136 135 &mfc { 137 - samsung,mfc-r = <0x43000000 0x800000>; 138 - samsung,mfc-l = <0x51000000 0x800000>; 136 + memory-region = <&mfc_left>, <&mfc_right>; 139 137 status = "okay"; 140 138 }; 141 139
+6
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
··· 13 13 #include "exynos4412.dtsi" 14 14 #include "exynos4412-ppmu-common.dtsi" 15 15 #include <dt-bindings/gpio/gpio.h> 16 + #include "exynos-mfc-reserved-memory.dtsi" 16 17 17 18 / { 18 19 chosen { ··· 498 497 <&clock_audss EXYNOS_DOUT_AUD_BUS>, 499 498 <&clock_audss EXYNOS_SCLK_I2S>; 500 499 clock-names = "iis", "i2s_opclk0", "i2s_opclk1"; 500 + }; 501 + 502 + &mfc { 503 + memory-region = <&mfc_left>, <&mfc_right>; 504 + status = "okay"; 501 505 }; 502 506 503 507 &mixer {
+2 -2
arch/arm/boot/dts/exynos4412-origen.dts
··· 16 16 #include "exynos4412.dtsi" 17 17 #include <dt-bindings/gpio/gpio.h> 18 18 #include <dt-bindings/input/input.h> 19 + #include "exynos-mfc-reserved-memory.dtsi" 19 20 20 21 / { 21 22 model = "Insignal Origen evaluation board based on Exynos4412"; ··· 467 466 }; 468 467 469 468 &mfc { 470 - samsung,mfc-r = <0x43000000 0x800000>; 471 - samsung,mfc-l = <0x51000000 0x800000>; 469 + memory-region = <&mfc_left>, <&mfc_right>; 472 470 status = "okay"; 473 471 }; 474 472
+2 -2
arch/arm/boot/dts/exynos4412-smdk4412.dts
··· 14 14 15 15 /dts-v1/; 16 16 #include "exynos4412.dtsi" 17 + #include "exynos-mfc-reserved-memory.dtsi" 17 18 18 19 / { 19 20 model = "Samsung SMDK evaluation board based on Exynos4412"; ··· 113 112 }; 114 113 115 114 &mfc { 116 - samsung,mfc-r = <0x43000000 0x800000>; 117 - samsung,mfc-l = <0x51000000 0x800000>; 115 + memory-region = <&mfc_left>, <&mfc_right>; 118 116 status = "okay"; 119 117 }; 120 118
+2 -2
arch/arm/boot/dts/exynos5250-arndale.dts
··· 14 14 #include <dt-bindings/interrupt-controller/irq.h> 15 15 #include <dt-bindings/input/input.h> 16 16 #include "exynos5250.dtsi" 17 + #include "exynos-mfc-reserved-memory.dtsi" 17 18 18 19 / { 19 20 model = "Insignal Arndale evaluation board based on EXYNOS5250"; ··· 517 516 }; 518 517 519 518 &mfc { 520 - samsung,mfc-r = <0x43000000 0x800000>; 521 - samsung,mfc-l = <0x51000000 0x800000>; 519 + memory-region = <&mfc_left>, <&mfc_right>; 522 520 }; 523 521 524 522 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5250-smdk5250.dts
··· 13 13 #include <dt-bindings/gpio/gpio.h> 14 14 #include <dt-bindings/interrupt-controller/irq.h> 15 15 #include "exynos5250.dtsi" 16 + #include "exynos-mfc-reserved-memory.dtsi" 16 17 17 18 / { 18 19 model = "SAMSUNG SMDK5250 board based on EXYNOS5250"; ··· 345 344 }; 346 345 347 346 &mfc { 348 - samsung,mfc-r = <0x43000000 0x800000>; 349 - samsung,mfc-l = <0x51000000 0x800000>; 347 + memory-region = <&mfc_left>, <&mfc_right>; 350 348 }; 351 349 352 350 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5250-spring.dts
··· 14 14 #include <dt-bindings/interrupt-controller/irq.h> 15 15 #include <dt-bindings/input/input.h> 16 16 #include "exynos5250.dtsi" 17 + #include "exynos-mfc-reserved-memory.dtsi" 17 18 18 19 / { 19 20 model = "Google Spring"; ··· 426 425 }; 427 426 428 427 &mfc { 429 - samsung,mfc-r = <0x43000000 0x800000>; 430 - samsung,mfc-l = <0x51000000 0x800000>; 428 + memory-region = <&mfc_left>, <&mfc_right>; 431 429 }; 432 430 433 431 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5420-arndale-octa.dts
··· 16 16 #include <dt-bindings/interrupt-controller/irq.h> 17 17 #include <dt-bindings/input/input.h> 18 18 #include <dt-bindings/clock/samsung,s2mps11.h> 19 + #include "exynos-mfc-reserved-memory.dtsi" 19 20 20 21 / { 21 22 model = "Insignal Arndale Octa evaluation board based on EXYNOS5420"; ··· 348 347 }; 349 348 350 349 &mfc { 351 - samsung,mfc-r = <0x43000000 0x800000>; 352 - samsung,mfc-l = <0x51000000 0x800000>; 350 + memory-region = <&mfc_left>, <&mfc_right>; 353 351 }; 354 352 355 353 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5420-peach-pit.dts
··· 16 16 #include <dt-bindings/regulator/maxim,max77802.h> 17 17 #include "exynos5420.dtsi" 18 18 #include "exynos5420-cpus.dtsi" 19 + #include "exynos-mfc-reserved-memory.dtsi" 19 20 20 21 / { 21 22 model = "Google Peach Pit Rev 6+"; ··· 696 695 }; 697 696 698 697 &mfc { 699 - samsung,mfc-r = <0x43000000 0x800000>; 700 - samsung,mfc-l = <0x51000000 0x800000>; 698 + memory-region = <&mfc_left>, <&mfc_right>; 701 699 }; 702 700 703 701 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5420-smdk5420.dts
··· 13 13 #include "exynos5420.dtsi" 14 14 #include "exynos5420-cpus.dtsi" 15 15 #include <dt-bindings/gpio/gpio.h> 16 + #include "exynos-mfc-reserved-memory.dtsi" 16 17 17 18 / { 18 19 model = "Samsung SMDK5420 board based on EXYNOS5420"; ··· 356 355 }; 357 356 358 357 &mfc { 359 - samsung,mfc-r = <0x43000000 0x800000>; 360 - samsung,mfc-l = <0x51000000 0x800000>; 358 + memory-region = <&mfc_left>, <&mfc_right>; 361 359 }; 362 360 363 361 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
··· 17 17 #include "exynos5800.dtsi" 18 18 #include "exynos5422-cpus.dtsi" 19 19 #include "exynos5422-cpu-thermal.dtsi" 20 + #include "exynos-mfc-reserved-memory.dtsi" 20 21 21 22 / { 22 23 memory { ··· 407 406 }; 408 407 409 408 &mfc { 410 - samsung,mfc-r = <0x43000000 0x800000>; 411 - samsung,mfc-l = <0x51000000 0x800000>; 409 + memory-region = <&mfc_left>, <&mfc_right>; 412 410 }; 413 411 414 412 &mmc_0 {
+2 -2
arch/arm/boot/dts/exynos5800-peach-pi.dts
··· 16 16 #include <dt-bindings/regulator/maxim,max77802.h> 17 17 #include "exynos5800.dtsi" 18 18 #include "exynos5420-cpus.dtsi" 19 + #include "exynos-mfc-reserved-memory.dtsi" 19 20 20 21 / { 21 22 model = "Google Peach Pi Rev 10+"; ··· 671 670 }; 672 671 673 672 &mfc { 674 - samsung,mfc-r = <0x43000000 0x800000>; 675 - samsung,mfc-l = <0x51000000 0x800000>; 673 + memory-region = <&mfc_left>, <&mfc_right>; 676 674 }; 677 675 678 676 &mmc_0 {
-2
arch/arm/mach-exynos/Makefile
··· 22 22 23 23 obj-$(CONFIG_EXYNOS5420_MCPM) += mcpm-exynos.o 24 24 CFLAGS_mcpm-exynos.o += -march=armv7-a 25 - 26 - obj-$(CONFIG_S5P_DEV_MFC) += s5p-dev-mfc.o
-19
arch/arm/mach-exynos/exynos.c
··· 27 27 #include <mach/map.h> 28 28 29 29 #include "common.h" 30 - #include "mfc.h" 31 30 32 31 static struct map_desc exynos4_iodesc[] __initdata = { 33 32 { ··· 236 237 NULL 237 238 }; 238 239 239 - static void __init exynos_reserve(void) 240 - { 241 - #ifdef CONFIG_S5P_DEV_MFC 242 - int i; 243 - char *mfc_mem[] = { 244 - "samsung,mfc-v5", 245 - "samsung,mfc-v6", 246 - "samsung,mfc-v7", 247 - "samsung,mfc-v8", 248 - }; 249 - 250 - for (i = 0; i < ARRAY_SIZE(mfc_mem); i++) 251 - if (of_scan_flat_dt(s5p_fdt_alloc_mfc_mem, mfc_mem[i])) 252 - break; 253 - #endif 254 - } 255 - 256 240 static void __init exynos_dt_fixup(void) 257 241 { 258 242 /* ··· 257 275 .init_machine = exynos_dt_machine_init, 258 276 .init_late = exynos_init_late, 259 277 .dt_compat = exynos_dt_compat, 260 - .reserve = exynos_reserve, 261 278 .dt_fixup = exynos_dt_fixup, 262 279 MACHINE_END
-16
arch/arm/mach-exynos/mfc.h
··· 1 - /* 2 - * Copyright (C) 2013 Samsung Electronics Co.Ltd 3 - * 4 - * This program is free software; you can redistribute it and/or modify it 5 - * under the terms of the GNU General Public License as published by the 6 - * Free Software Foundation; either version 2 of the License, or (at your 7 - * option) any later version. 8 - */ 9 - 10 - #ifndef __MACH_EXYNOS_MFC_H 11 - #define __MACH_EXYNOS_MFC_H __FILE__ 12 - 13 - int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname, 14 - int depth, void *data); 15 - 16 - #endif /* __MACH_EXYNOS_MFC_H */
-93
arch/arm/mach-exynos/s5p-dev-mfc.c
··· 1 - /* 2 - * Copyright (C) 2010-2011 Samsung Electronics Co.Ltd 3 - * 4 - * Base S5P MFC resource and device definitions 5 - * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License version 2 as 8 - * published by the Free Software Foundation. 9 - */ 10 - 11 - #include <linux/kernel.h> 12 - #include <linux/platform_device.h> 13 - #include <linux/dma-mapping.h> 14 - #include <linux/memblock.h> 15 - #include <linux/ioport.h> 16 - #include <linux/of_fdt.h> 17 - #include <linux/of.h> 18 - 19 - static struct platform_device s5p_device_mfc_l; 20 - static struct platform_device s5p_device_mfc_r; 21 - 22 - struct s5p_mfc_dt_meminfo { 23 - unsigned long loff; 24 - unsigned long lsize; 25 - unsigned long roff; 26 - unsigned long rsize; 27 - char *compatible; 28 - }; 29 - 30 - struct s5p_mfc_reserved_mem { 31 - phys_addr_t base; 32 - unsigned long size; 33 - struct device *dev; 34 - }; 35 - 36 - static struct s5p_mfc_reserved_mem s5p_mfc_mem[2] __initdata; 37 - 38 - 39 - static void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, 40 - phys_addr_t lbase, unsigned int lsize) 41 - { 42 - int i; 43 - 44 - s5p_mfc_mem[0].dev = &s5p_device_mfc_r.dev; 45 - s5p_mfc_mem[0].base = rbase; 46 - s5p_mfc_mem[0].size = rsize; 47 - 48 - s5p_mfc_mem[1].dev = &s5p_device_mfc_l.dev; 49 - s5p_mfc_mem[1].base = lbase; 50 - s5p_mfc_mem[1].size = lsize; 51 - 52 - for (i = 0; i < ARRAY_SIZE(s5p_mfc_mem); i++) { 53 - struct s5p_mfc_reserved_mem *area = &s5p_mfc_mem[i]; 54 - if (memblock_remove(area->base, area->size)) { 55 - printk(KERN_ERR "Failed to reserve memory for MFC device (%ld bytes at 0x%08lx)\n", 56 - area->size, (unsigned long) area->base); 57 - area->base = 0; 58 - } 59 - } 60 - } 61 - 62 - int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname, 63 - int depth, void *data) 64 - { 65 - const __be32 *prop; 66 - int len; 67 - struct s5p_mfc_dt_meminfo mfc_mem; 68 - 69 - if (!data) 70 - return 0; 71 - 72 - if (!of_flat_dt_is_compatible(node, data)) 73 - return 0; 74 - 75 - prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); 76 - if (!prop || (len != 2 * sizeof(unsigned long))) 77 - return 0; 78 - 79 - mfc_mem.loff = be32_to_cpu(prop[0]); 80 - mfc_mem.lsize = be32_to_cpu(prop[1]); 81 - 82 - prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); 83 - if (!prop || (len != 2 * sizeof(unsigned long))) 84 - return 0; 85 - 86 - mfc_mem.roff = be32_to_cpu(prop[0]); 87 - mfc_mem.rsize = be32_to_cpu(prop[1]); 88 - 89 - s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, 90 - mfc_mem.loff, mfc_mem.lsize); 91 - 92 - return 1; 93 - }
+2
drivers/media/platform/exynos-gsc/gsc-core.c
··· 1124 1124 goto err_m2m; 1125 1125 1126 1126 /* Initialize continious memory allocator */ 1127 + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); 1127 1128 gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev); 1128 1129 if (IS_ERR(gsc->alloc_ctx)) { 1129 1130 ret = PTR_ERR(gsc->alloc_ctx); ··· 1154 1153 v4l2_device_unregister(&gsc->v4l2_dev); 1155 1154 1156 1155 vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx); 1156 + vb2_dma_contig_clear_max_seg_size(&pdev->dev); 1157 1157 pm_runtime_disable(&pdev->dev); 1158 1158 gsc_clk_put(gsc); 1159 1159
+2
drivers/media/platform/exynos4-is/fimc-core.c
··· 1019 1019 } 1020 1020 1021 1021 /* Initialize contiguous memory allocator */ 1022 + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); 1022 1023 fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev); 1023 1024 if (IS_ERR(fimc->alloc_ctx)) { 1024 1025 ret = PTR_ERR(fimc->alloc_ctx); ··· 1125 1124 1126 1125 fimc_unregister_capture_subdev(fimc); 1127 1126 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); 1127 + vb2_dma_contig_clear_max_seg_size(&pdev->dev); 1128 1128 1129 1129 clk_disable(fimc->clock[CLK_BUS]); 1130 1130 fimc_clk_put(fimc);
+2
drivers/media/platform/exynos4-is/fimc-is.c
··· 847 847 if (ret < 0) 848 848 goto err_pm; 849 849 850 + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); 850 851 is->alloc_ctx = vb2_dma_contig_init_ctx(dev); 851 852 if (IS_ERR(is->alloc_ctx)) { 852 853 ret = PTR_ERR(is->alloc_ctx); ··· 941 940 free_irq(is->irq, is); 942 941 fimc_is_unregister_subdevs(is); 943 942 vb2_dma_contig_cleanup_ctx(is->alloc_ctx); 943 + vb2_dma_contig_clear_max_seg_size(dev); 944 944 fimc_is_put_clocks(is); 945 945 fimc_is_debugfs_remove(is); 946 946 release_firmware(is->fw.f_w);
+2
drivers/media/platform/exynos4-is/fimc-lite.c
··· 1551 1551 goto err_sd; 1552 1552 } 1553 1553 1554 + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); 1554 1555 fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev); 1555 1556 if (IS_ERR(fimc->alloc_ctx)) { 1556 1557 ret = PTR_ERR(fimc->alloc_ctx); ··· 1653 1652 pm_runtime_set_suspended(dev); 1654 1653 fimc_lite_unregister_capture_subdev(fimc); 1655 1654 vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx); 1655 + vb2_dma_contig_clear_max_seg_size(dev); 1656 1656 fimc_lite_clk_put(fimc); 1657 1657 1658 1658 dev_info(dev, "Driver unloaded\n");
+2
drivers/media/platform/s5p-g2d/g2d.c
··· 681 681 goto put_clk_gate; 682 682 } 683 683 684 + vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); 684 685 dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 685 686 if (IS_ERR(dev->alloc_ctx)) { 686 687 ret = PTR_ERR(dev->alloc_ctx); ··· 758 757 video_unregister_device(dev->vfd); 759 758 v4l2_device_unregister(&dev->v4l2_dev); 760 759 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); 760 + vb2_dma_contig_clear_max_seg_size(&pdev->dev); 761 761 clk_unprepare(dev->gate); 762 762 clk_put(dev->gate); 763 763 clk_unprepare(dev->clk);
+2
drivers/media/platform/s5p-jpeg/jpeg-core.c
··· 2843 2843 goto device_register_rollback; 2844 2844 } 2845 2845 2846 + vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32)); 2846 2847 jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); 2847 2848 if (IS_ERR(jpeg->alloc_ctx)) { 2848 2849 v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n"); ··· 2943 2942 video_unregister_device(jpeg->vfd_decoder); 2944 2943 video_unregister_device(jpeg->vfd_encoder); 2945 2944 vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx); 2945 + vb2_dma_contig_clear_max_seg_size(&pdev->dev); 2946 2946 v4l2_m2m_release(jpeg->m2m_dev); 2947 2947 v4l2_device_unregister(&jpeg->v4l2_dev); 2948 2948
+121 -91
drivers/media/platform/s5p-mfc/s5p_mfc.c
··· 22 22 #include <media/v4l2-event.h> 23 23 #include <linux/workqueue.h> 24 24 #include <linux/of.h> 25 + #include <linux/of_reserved_mem.h> 25 26 #include <media/videobuf2-v4l2.h> 26 27 #include "s5p_mfc_common.h" 27 28 #include "s5p_mfc_ctrl.h" ··· 30 29 #include "s5p_mfc_dec.h" 31 30 #include "s5p_mfc_enc.h" 32 31 #include "s5p_mfc_intr.h" 32 + #include "s5p_mfc_iommu.h" 33 33 #include "s5p_mfc_opr.h" 34 34 #include "s5p_mfc_cmd.h" 35 35 #include "s5p_mfc_pm.h" ··· 1045 1043 .mmap = s5p_mfc_mmap, 1046 1044 }; 1047 1045 1048 - static int match_child(struct device *dev, void *data) 1046 + /* DMA memory related helper functions */ 1047 + static void s5p_mfc_memdev_release(struct device *dev) 1049 1048 { 1050 - if (!dev_name(dev)) 1051 - return 0; 1052 - return !strcmp(dev_name(dev), (char *)data); 1049 + of_reserved_mem_device_release(dev); 1050 + } 1051 + 1052 + static struct device *s5p_mfc_alloc_memdev(struct device *dev, 1053 + const char *name, unsigned int idx) 1054 + { 1055 + struct device *child; 1056 + int ret; 1057 + 1058 + child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL); 1059 + if (!child) 1060 + return NULL; 1061 + 1062 + device_initialize(child); 1063 + dev_set_name(child, "%s:%s", dev_name(dev), name); 1064 + child->parent = dev; 1065 + child->bus = dev->bus; 1066 + child->coherent_dma_mask = dev->coherent_dma_mask; 1067 + child->dma_mask = dev->dma_mask; 1068 + child->release = s5p_mfc_memdev_release; 1069 + 1070 + if (device_add(child) == 0) { 1071 + ret = of_reserved_mem_device_init_by_idx(child, dev->of_node, 1072 + idx); 1073 + if (ret == 0) 1074 + return child; 1075 + } 1076 + 1077 + put_device(child); 1078 + return NULL; 1079 + } 1080 + 1081 + static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev) 1082 + { 1083 + struct device *dev = &mfc_dev->plat_dev->dev; 1084 + 1085 + /* 1086 + * When IOMMU is available, we cannot use the default configuration, 1087 + * because of MFC firmware requirements: address space limited to 1088 + * 256M and non-zero default start address. 1089 + * This is still simplified, not optimal configuration, but for now 1090 + * IOMMU core doesn't allow to configure device's IOMMUs channel 1091 + * separately. 1092 + */ 1093 + if (exynos_is_iommu_available(dev)) { 1094 + int ret = exynos_configure_iommu(dev, S5P_MFC_IOMMU_DMA_BASE, 1095 + S5P_MFC_IOMMU_DMA_SIZE); 1096 + if (ret == 0) 1097 + mfc_dev->mem_dev_l = mfc_dev->mem_dev_r = dev; 1098 + return ret; 1099 + } 1100 + 1101 + /* 1102 + * Create and initialize virtual devices for accessing 1103 + * reserved memory regions. 1104 + */ 1105 + mfc_dev->mem_dev_l = s5p_mfc_alloc_memdev(dev, "left", 1106 + MFC_BANK1_ALLOC_CTX); 1107 + if (!mfc_dev->mem_dev_l) 1108 + return -ENODEV; 1109 + mfc_dev->mem_dev_r = s5p_mfc_alloc_memdev(dev, "right", 1110 + MFC_BANK2_ALLOC_CTX); 1111 + if (!mfc_dev->mem_dev_r) { 1112 + device_unregister(mfc_dev->mem_dev_l); 1113 + return -ENODEV; 1114 + } 1115 + 1116 + return 0; 1117 + } 1118 + 1119 + static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev) 1120 + { 1121 + struct device *dev = &mfc_dev->plat_dev->dev; 1122 + 1123 + if (exynos_is_iommu_available(dev)) { 1124 + exynos_unconfigure_iommu(dev); 1125 + return; 1126 + } 1127 + 1128 + device_unregister(mfc_dev->mem_dev_l); 1129 + device_unregister(mfc_dev->mem_dev_r); 1053 1130 } 1054 1131 1055 1132 static void *mfc_get_drv_data(struct platform_device *pdev); 1056 - 1057 - static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev) 1058 - { 1059 - unsigned int mem_info[2] = { }; 1060 - 1061 - dev->mem_dev_l = devm_kzalloc(&dev->plat_dev->dev, 1062 - sizeof(struct device), GFP_KERNEL); 1063 - if (!dev->mem_dev_l) { 1064 - mfc_err("Not enough memory\n"); 1065 - return -ENOMEM; 1066 - } 1067 - device_initialize(dev->mem_dev_l); 1068 - of_property_read_u32_array(dev->plat_dev->dev.of_node, 1069 - "samsung,mfc-l", mem_info, 2); 1070 - if (dma_declare_coherent_memory(dev->mem_dev_l, mem_info[0], 1071 - mem_info[0], mem_info[1], 1072 - DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { 1073 - mfc_err("Failed to declare coherent memory for\n" 1074 - "MFC device\n"); 1075 - return -ENOMEM; 1076 - } 1077 - 1078 - dev->mem_dev_r = devm_kzalloc(&dev->plat_dev->dev, 1079 - sizeof(struct device), GFP_KERNEL); 1080 - if (!dev->mem_dev_r) { 1081 - mfc_err("Not enough memory\n"); 1082 - return -ENOMEM; 1083 - } 1084 - device_initialize(dev->mem_dev_r); 1085 - of_property_read_u32_array(dev->plat_dev->dev.of_node, 1086 - "samsung,mfc-r", mem_info, 2); 1087 - if (dma_declare_coherent_memory(dev->mem_dev_r, mem_info[0], 1088 - mem_info[0], mem_info[1], 1089 - DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) { 1090 - pr_err("Failed to declare coherent memory for\n" 1091 - "MFC device\n"); 1092 - return -ENOMEM; 1093 - } 1094 - return 0; 1095 - } 1096 1133 1097 1134 /* MFC probe function */ 1098 1135 static int s5p_mfc_probe(struct platform_device *pdev) ··· 1158 1117 1159 1118 dev->variant = mfc_get_drv_data(pdev); 1160 1119 1161 - ret = s5p_mfc_init_pm(dev); 1162 - if (ret < 0) { 1163 - dev_err(&pdev->dev, "failed to get mfc clock source\n"); 1164 - return ret; 1165 - } 1166 - 1167 1120 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1168 1121 1169 1122 dev->regs_base = devm_ioremap_resource(&pdev->dev, res); ··· 1178 1143 goto err_res; 1179 1144 } 1180 1145 1181 - if (pdev->dev.of_node) { 1182 - ret = s5p_mfc_alloc_memdevs(dev); 1183 - if (ret < 0) 1184 - goto err_res; 1185 - } else { 1186 - dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, 1187 - "s5p-mfc-l", match_child); 1188 - if (!dev->mem_dev_l) { 1189 - mfc_err("Mem child (L) device get failed\n"); 1190 - ret = -ENODEV; 1191 - goto err_res; 1192 - } 1193 - dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, 1194 - "s5p-mfc-r", match_child); 1195 - if (!dev->mem_dev_r) { 1196 - mfc_err("Mem child (R) device get failed\n"); 1197 - ret = -ENODEV; 1198 - goto err_res; 1199 - } 1146 + ret = s5p_mfc_configure_dma_memory(dev); 1147 + if (ret < 0) { 1148 + dev_err(&pdev->dev, "failed to configure DMA memory\n"); 1149 + return ret; 1200 1150 } 1201 1151 1152 + ret = s5p_mfc_init_pm(dev); 1153 + if (ret < 0) { 1154 + dev_err(&pdev->dev, "failed to get mfc clock source\n"); 1155 + return ret; 1156 + } 1157 + 1158 + vb2_dma_contig_set_max_seg_size(dev->mem_dev_l, DMA_BIT_MASK(32)); 1202 1159 dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l); 1203 1160 if (IS_ERR(dev->alloc_ctx[0])) { 1204 1161 ret = PTR_ERR(dev->alloc_ctx[0]); 1205 1162 goto err_res; 1206 1163 } 1164 + vb2_dma_contig_set_max_seg_size(dev->mem_dev_r, DMA_BIT_MASK(32)); 1207 1165 dev->alloc_ctx[1] = vb2_dma_contig_init_ctx(dev->mem_dev_r); 1208 1166 if (IS_ERR(dev->alloc_ctx[1])) { 1209 1167 ret = PTR_ERR(dev->alloc_ctx[1]); ··· 1229 1201 vfd->vfl_dir = VFL_DIR_M2M; 1230 1202 snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME); 1231 1203 dev->vfd_dec = vfd; 1232 - ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); 1233 - if (ret) { 1234 - v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); 1235 - video_device_release(vfd); 1236 - goto err_dec_reg; 1237 - } 1238 - v4l2_info(&dev->v4l2_dev, 1239 - "decoder registered as /dev/video%d\n", vfd->num); 1240 1204 video_set_drvdata(vfd, dev); 1241 1205 1242 1206 /* encoder */ ··· 1246 1226 vfd->vfl_dir = VFL_DIR_M2M; 1247 1227 snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME); 1248 1228 dev->vfd_enc = vfd; 1249 - ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); 1250 - if (ret) { 1251 - v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); 1252 - video_device_release(vfd); 1253 - goto err_enc_reg; 1254 - } 1255 - v4l2_info(&dev->v4l2_dev, 1256 - "encoder registered as /dev/video%d\n", vfd->num); 1257 1229 video_set_drvdata(vfd, dev); 1258 1230 platform_set_drvdata(pdev, dev); 1259 1231 ··· 1262 1250 s5p_mfc_init_hw_cmds(dev); 1263 1251 s5p_mfc_init_regs(dev); 1264 1252 1253 + /* Register decoder and encoder */ 1254 + ret = video_register_device(dev->vfd_dec, VFL_TYPE_GRABBER, 0); 1255 + if (ret) { 1256 + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); 1257 + video_device_release(dev->vfd_dec); 1258 + goto err_dec_reg; 1259 + } 1260 + v4l2_info(&dev->v4l2_dev, 1261 + "decoder registered as /dev/video%d\n", dev->vfd_dec->num); 1262 + 1263 + ret = video_register_device(dev->vfd_enc, VFL_TYPE_GRABBER, 0); 1264 + if (ret) { 1265 + v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); 1266 + video_device_release(dev->vfd_enc); 1267 + goto err_enc_reg; 1268 + } 1269 + v4l2_info(&dev->v4l2_dev, 1270 + "encoder registered as /dev/video%d\n", dev->vfd_enc->num); 1271 + 1265 1272 pr_debug("%s--\n", __func__); 1266 1273 return 0; 1267 1274 1268 1275 /* Deinit MFC if probe had failed */ 1269 1276 err_enc_reg: 1270 - video_device_release(dev->vfd_enc); 1271 - err_enc_alloc: 1272 1277 video_unregister_device(dev->vfd_dec); 1273 1278 err_dec_reg: 1279 + video_device_release(dev->vfd_enc); 1280 + err_enc_alloc: 1274 1281 video_device_release(dev->vfd_dec); 1275 1282 err_dec_alloc: 1276 1283 v4l2_device_unregister(&dev->v4l2_dev); ··· 1324 1293 s5p_mfc_release_firmware(dev); 1325 1294 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]); 1326 1295 vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]); 1327 - if (pdev->dev.of_node) { 1328 - put_device(dev->mem_dev_l); 1329 - put_device(dev->mem_dev_r); 1330 - } 1296 + s5p_mfc_unconfigure_dma_memory(dev); 1297 + vb2_dma_contig_clear_max_seg_size(dev->mem_dev_l); 1298 + vb2_dma_contig_clear_max_seg_size(dev->mem_dev_r); 1331 1299 1332 1300 s5p_mfc_final_pm(dev); 1333 1301 return 0;
+79
drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
··· 1 + /* 2 + * Copyright (C) 2015 Samsung Electronics Co.Ltd 3 + * Authors: Marek Szyprowski <m.szyprowski@samsung.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License as published by the 7 + * Free Software Foundation; either version 2 of the License, or (at your 8 + * option) any later version. 9 + */ 10 + 11 + #ifndef S5P_MFC_IOMMU_H_ 12 + #define S5P_MFC_IOMMU_H_ 13 + 14 + #define S5P_MFC_IOMMU_DMA_BASE 0x20000000lu 15 + #define S5P_MFC_IOMMU_DMA_SIZE SZ_256M 16 + 17 + #ifdef CONFIG_EXYNOS_IOMMU 18 + 19 + #include <asm/dma-iommu.h> 20 + 21 + static inline bool exynos_is_iommu_available(struct device *dev) 22 + { 23 + return dev->archdata.iommu != NULL; 24 + } 25 + 26 + static inline void exynos_unconfigure_iommu(struct device *dev) 27 + { 28 + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); 29 + 30 + arm_iommu_detach_device(dev); 31 + arm_iommu_release_mapping(mapping); 32 + } 33 + 34 + static inline int exynos_configure_iommu(struct device *dev, 35 + unsigned int base, unsigned int size) 36 + { 37 + struct dma_iommu_mapping *mapping = NULL; 38 + int ret; 39 + 40 + /* Disable the default mapping created by device core */ 41 + if (to_dma_iommu_mapping(dev)) 42 + exynos_unconfigure_iommu(dev); 43 + 44 + mapping = arm_iommu_create_mapping(dev->bus, base, size); 45 + if (IS_ERR(mapping)) { 46 + pr_warn("Failed to create IOMMU mapping for device %s\n", 47 + dev_name(dev)); 48 + return PTR_ERR(mapping); 49 + } 50 + 51 + ret = arm_iommu_attach_device(dev, mapping); 52 + if (ret) { 53 + pr_warn("Failed to attached device %s to IOMMU_mapping\n", 54 + dev_name(dev)); 55 + arm_iommu_release_mapping(mapping); 56 + return ret; 57 + } 58 + 59 + return 0; 60 + } 61 + 62 + #else 63 + 64 + static inline bool exynos_is_iommu_available(struct device *dev) 65 + { 66 + return false; 67 + } 68 + 69 + static inline int exynos_configure_iommu(struct device *dev, 70 + unsigned int base, unsigned int size) 71 + { 72 + return -ENOSYS; 73 + } 74 + 75 + static inline void exynos_unconfigure_iommu(struct device *dev) { } 76 + 77 + #endif 78 + 79 + #endif /* S5P_MFC_IOMMU_H_ */
+2
drivers/media/platform/s5p-tv/mixer_video.c
··· 80 80 goto fail; 81 81 } 82 82 83 + vb2_dma_contig_set_max_seg_size(mdev->dev, DMA_BIT_MASK(32)); 83 84 mdev->alloc_ctx = vb2_dma_contig_init_ctx(mdev->dev); 84 85 if (IS_ERR(mdev->alloc_ctx)) { 85 86 mxr_err(mdev, "could not acquire vb2 allocator\n"); ··· 153 152 kfree(mdev->output[i]); 154 153 155 154 vb2_dma_contig_cleanup_ctx(mdev->alloc_ctx); 155 + vb2_dma_contig_clear_max_seg_size(mdev->dev); 156 156 v4l2_device_unregister(&mdev->v4l2_dev); 157 157 } 158 158
+53
drivers/media/v4l2-core/videobuf2-dma-contig.c
··· 753 753 } 754 754 EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx); 755 755 756 + /** 757 + * vb2_dma_contig_set_max_seg_size() - configure DMA max segment size 758 + * @dev: device for configuring DMA parameters 759 + * @size: size of DMA max segment size to set 760 + * 761 + * To allow mapping the scatter-list into a single chunk in the DMA 762 + * address space, the device is required to have the DMA max segment 763 + * size parameter set to a value larger than the buffer size. Otherwise, 764 + * the DMA-mapping subsystem will split the mapping into max segment 765 + * size chunks. This function sets the DMA max segment size 766 + * parameter to let DMA-mapping map a buffer as a single chunk in DMA 767 + * address space. 768 + * This code assumes that the DMA-mapping subsystem will merge all 769 + * scatterlist segments if this is really possible (for example when 770 + * an IOMMU is available and enabled). 771 + * Ideally, this parameter should be set by the generic bus code, but it 772 + * is left with the default 64KiB value due to historical litmiations in 773 + * other subsystems (like limited USB host drivers) and there no good 774 + * place to set it to the proper value. 775 + * This function should be called from the drivers, which are known to 776 + * operate on platforms with IOMMU and provide access to shared buffers 777 + * (either USERPTR or DMABUF). This should be done before initializing 778 + * videobuf2 queue. 779 + */ 780 + int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size) 781 + { 782 + if (!dev->dma_parms) { 783 + dev->dma_parms = kzalloc(sizeof(dev->dma_parms), GFP_KERNEL); 784 + if (!dev->dma_parms) 785 + return -ENOMEM; 786 + } 787 + if (dma_get_max_seg_size(dev) < size) 788 + return dma_set_max_seg_size(dev, size); 789 + 790 + return 0; 791 + } 792 + EXPORT_SYMBOL_GPL(vb2_dma_contig_set_max_seg_size); 793 + 794 + /* 795 + * vb2_dma_contig_clear_max_seg_size() - release resources for DMA parameters 796 + * @dev: device for configuring DMA parameters 797 + * 798 + * This function releases resources allocated to configure DMA parameters 799 + * (see vb2_dma_contig_set_max_seg_size() function). It should be called from 800 + * device drivers on driver remove. 801 + */ 802 + void vb2_dma_contig_clear_max_seg_size(struct device *dev) 803 + { 804 + kfree(dev->dma_parms); 805 + dev->dma_parms = NULL; 806 + } 807 + EXPORT_SYMBOL_GPL(vb2_dma_contig_clear_max_seg_size); 808 + 756 809 MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2"); 757 810 MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>"); 758 811 MODULE_LICENSE("GPL");
+67 -24
drivers/of/of_reserved_mem.c
··· 21 21 #include <linux/sizes.h> 22 22 #include <linux/of_reserved_mem.h> 23 23 #include <linux/sort.h> 24 + #include <linux/slab.h> 24 25 25 26 #define MAX_RESERVED_REGIONS 16 26 27 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; ··· 290 289 return NULL; 291 290 } 292 291 293 - /** 294 - * of_reserved_mem_device_init() - assign reserved memory region to given device 295 - * 296 - * This function assign memory region pointed by "memory-region" device tree 297 - * property to the given device. 298 - */ 299 - int of_reserved_mem_device_init(struct device *dev) 300 - { 292 + struct rmem_assigned_device { 293 + struct device *dev; 301 294 struct reserved_mem *rmem; 302 - struct device_node *np; 295 + struct list_head list; 296 + }; 297 + 298 + static LIST_HEAD(of_rmem_assigned_device_list); 299 + static DEFINE_MUTEX(of_rmem_assigned_device_mutex); 300 + 301 + /** 302 + * of_reserved_mem_device_init_by_idx() - assign reserved memory region to 303 + * given device 304 + * @dev: Pointer to the device to configure 305 + * @np: Pointer to the device_node with 'reserved-memory' property 306 + * @idx: Index of selected region 307 + * 308 + * This function assigns respective DMA-mapping operations based on reserved 309 + * memory region specified by 'memory-region' property in @np node to the @dev 310 + * device. When driver needs to use more than one reserved memory region, it 311 + * should allocate child devices and initialize regions by name for each of 312 + * child device. 313 + * 314 + * Returns error code or zero on success. 315 + */ 316 + int of_reserved_mem_device_init_by_idx(struct device *dev, 317 + struct device_node *np, int idx) 318 + { 319 + struct rmem_assigned_device *rd; 320 + struct device_node *target; 321 + struct reserved_mem *rmem; 303 322 int ret; 304 323 305 - np = of_parse_phandle(dev->of_node, "memory-region", 0); 306 - if (!np) 307 - return -ENODEV; 324 + if (!np || !dev) 325 + return -EINVAL; 308 326 309 - rmem = __find_rmem(np); 310 - of_node_put(np); 327 + target = of_parse_phandle(np, "memory-region", idx); 328 + if (!target) 329 + return -EINVAL; 330 + 331 + rmem = __find_rmem(target); 332 + of_node_put(target); 311 333 312 334 if (!rmem || !rmem->ops || !rmem->ops->device_init) 313 335 return -EINVAL; 314 336 337 + rd = kmalloc(sizeof(struct rmem_assigned_device), GFP_KERNEL); 338 + if (!rd) 339 + return -ENOMEM; 340 + 315 341 ret = rmem->ops->device_init(rmem, dev); 316 - if (ret == 0) 342 + if (ret == 0) { 343 + rd->dev = dev; 344 + rd->rmem = rmem; 345 + 346 + mutex_lock(&of_rmem_assigned_device_mutex); 347 + list_add(&rd->list, &of_rmem_assigned_device_list); 348 + mutex_unlock(&of_rmem_assigned_device_mutex); 349 + 317 350 dev_info(dev, "assigned reserved memory node %s\n", rmem->name); 351 + } else { 352 + kfree(rd); 353 + } 318 354 319 355 return ret; 320 356 } 321 - EXPORT_SYMBOL_GPL(of_reserved_mem_device_init); 357 + EXPORT_SYMBOL_GPL(of_reserved_mem_device_init_by_idx); 322 358 323 359 /** 324 360 * of_reserved_mem_device_release() - release reserved memory device structures 361 + * @dev: Pointer to the device to deconfigure 325 362 * 326 363 * This function releases structures allocated for memory region handling for 327 364 * the given device. 328 365 */ 329 366 void of_reserved_mem_device_release(struct device *dev) 330 367 { 331 - struct reserved_mem *rmem; 332 - struct device_node *np; 368 + struct rmem_assigned_device *rd; 369 + struct reserved_mem *rmem = NULL; 333 370 334 - np = of_parse_phandle(dev->of_node, "memory-region", 0); 335 - if (!np) 336 - return; 337 - 338 - rmem = __find_rmem(np); 339 - of_node_put(np); 371 + mutex_lock(&of_rmem_assigned_device_mutex); 372 + list_for_each_entry(rd, &of_rmem_assigned_device_list, list) { 373 + if (rd->dev == dev) { 374 + rmem = rd->rmem; 375 + list_del(&rd->list); 376 + kfree(rd); 377 + break; 378 + } 379 + } 380 + mutex_unlock(&of_rmem_assigned_device_mutex); 340 381 341 382 if (!rmem || !rmem->ops || !rmem->ops->device_release) 342 383 return;
+22 -3
include/linux/of_reserved_mem.h
··· 1 1 #ifndef __OF_RESERVED_MEM_H 2 2 #define __OF_RESERVED_MEM_H 3 3 4 - struct device; 4 + #include <linux/device.h> 5 + 5 6 struct of_phandle_args; 6 7 struct reserved_mem_ops; 7 8 ··· 29 28 _OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn) 30 29 31 30 #ifdef CONFIG_OF_RESERVED_MEM 32 - int of_reserved_mem_device_init(struct device *dev); 31 + 32 + int of_reserved_mem_device_init_by_idx(struct device *dev, 33 + struct device_node *np, int idx); 33 34 void of_reserved_mem_device_release(struct device *dev); 34 35 35 36 void fdt_init_reserved_mem(void); 36 37 void fdt_reserved_mem_save_node(unsigned long node, const char *uname, 37 38 phys_addr_t base, phys_addr_t size); 38 39 #else 39 - static inline int of_reserved_mem_device_init(struct device *dev) 40 + static inline int of_reserved_mem_device_init_by_idx(struct device *dev, 41 + struct device_node *np, int idx) 40 42 { 41 43 return -ENOSYS; 42 44 } ··· 49 45 static inline void fdt_reserved_mem_save_node(unsigned long node, 50 46 const char *uname, phys_addr_t base, phys_addr_t size) { } 51 47 #endif 48 + 49 + /** 50 + * of_reserved_mem_device_init() - assign reserved memory region to given device 51 + * @dev: Pointer to the device to configure 52 + * 53 + * This function assigns respective DMA-mapping operations based on the first 54 + * reserved memory region specified by 'memory-region' property in device tree 55 + * node of the given device. 56 + * 57 + * Returns error code or zero on success. 58 + */ 59 + static inline int of_reserved_mem_device_init(struct device *dev) 60 + { 61 + return of_reserved_mem_device_init_by_idx(dev, dev->of_node, 0); 62 + } 52 63 53 64 #endif /* __OF_RESERVED_MEM_H */
+2
include/media/videobuf2-dma-contig.h
··· 35 35 } 36 36 37 37 void vb2_dma_contig_cleanup_ctx(void *alloc_ctx); 38 + int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size); 39 + void vb2_dma_contig_clear_max_seg_size(struct device *dev); 38 40 39 41 extern const struct vb2_mem_ops vb2_dma_contig_memops; 40 42