From 700496fa11441b733c9e10a247e3a287d9b5a6e6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 23 Oct 2019 16:49:53 +0200 Subject: drm/todo: Add entry to remove load/unload hooks They're midlayer, broken, and because of the old gunk, we can't fix them. For examples see the various checks in drm_mode_object.c against dev->registered, which cannot be enforced if the driver still uses the load hook. Unfortunately our biggest driver still uses load/unload, so this would be really great to get fixed. Cc: Alex Deucher Cc: Harry Wentland Reviewed-by: Thierry Reding Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191023144953.28190-2-daniel.vetter@ffwll.ch --- Documentation/gpu/todo.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'Documentation') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 6792fa9b6b6b..b3c0d517db93 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -351,6 +351,23 @@ connector register/unregister fixes Level: Intermediate +Remove load/unload callbacks from all non-DRIVER_LEGACY drivers +--------------------------------------------------------------- + +The load/unload callbacks in struct &drm_driver are very much midlayers, plus +for historical reasons they get the ordering wrong (and we can't fix that) +between setting up the &drm_driver structure and calling drm_dev_register(). + +- Rework drivers to no longer use the load/unload callbacks, directly coding the + load/unload sequence into the driver's probe function. + +- Once all non-DRIVER_LEGACY drivers are converted, disallow the load/unload + callbacks for all modern drivers. + +Contact: Daniel Vetter + +Level: Intermediate + Core refactorings ================= -- cgit v1.2.3 From 8a537de0f3d8b655cb901c948ed863bf0b23277b Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Tue, 29 Oct 2019 22:12:11 -0300 Subject: drm/doc: Update IGT documentation The IGT documentation in this page is telling us to build it using make. According to commit 67993c1 ("automake: Point builders at meson") from the IGT project, this is deprecated and IGT should be built with meson. Instead of having a documentation for IGT in this page, point to their GitLab README, which should always be up to date. Signed-off-by: Leandro Ribeiro Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191030011211.47942-1-leandrohr@riseup.net --- Documentation/gpu/drm-uapi.rst | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 94f90521f58c..996f7354e05c 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -254,36 +254,8 @@ Validating changes with IGT There's a collection of tests that aims to cover the whole functionality of DRM drivers and that can be used to check that changes to DRM drivers or the core don't regress existing functionality. This test suite is called IGT and -its code can be found in https://cgit.freedesktop.org/drm/igt-gpu-tools/. - -To build IGT, start by installing its build dependencies. In Debian-based -systems:: - - # apt-get build-dep intel-gpu-tools - -And in Fedora-based systems:: - - # dnf builddep intel-gpu-tools - -Then clone the repository:: - - $ git clone git://anongit.freedesktop.org/drm/igt-gpu-tools - -Configure the build system and start the build:: - - $ cd igt-gpu-tools && ./autogen.sh && make -j6 - -Download the piglit dependency:: - - $ ./scripts/run-tests.sh -d - -And run the tests:: - - $ ./scripts/run-tests.sh -t kms -t core -s - -run-tests.sh is a wrapper around piglit that will execute the tests matching -the -t options. A report in HTML format will be available in -./results/html/index.html. Results can be compared with piglit. +its code and instructions to build and run can be found in +https://gitlab.freedesktop.org/drm/igt-gpu-tools/. Display CRC Support ------------------- -- cgit v1.2.3 From 80ae0369d3e4b8559c04e2b4de2b86640908f2fd Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 6 Nov 2019 13:47:26 +0100 Subject: drm/todo: Convert drivers to generic fbdev emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This replaces the original TODO item for drm_fb_helper_fbdev_setup() and _teardown(), which are deprecated. v2: * remove driver-specific comments * list some basic requirements * keep a TODO item on drm_fb_helper_init() Signed-off-by: Thomas Zimmermann Reviewed-by: Noralf Trønnes Link: https://patchwork.freedesktop.org/patch/msgid/20191106124727.11641-2-tzimmermann@suse.de --- Documentation/gpu/todo.rst | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index b3c0d517db93..3ec509381fc5 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -171,21 +171,12 @@ Contact: Maintainer of the driver you plan to convert Level: Intermediate -Convert drivers to use drm_fb_helper_fbdev_setup/teardown() ------------------------------------------------------------ +Convert drivers to use drm_fbdev_generic_setup() +------------------------------------------------ -Most drivers can use drm_fb_helper_fbdev_setup() except maybe: - -- amdgpu which has special logic to decide whether to call - drm_helper_disable_unused_functions() - -- armada which isn't atomic and doesn't call - drm_helper_disable_unused_functions() - -- i915 which calls drm_fb_helper_initial_config() in a worker - -Drivers that use drm_framebuffer_remove() to clean up the fbdev framebuffer can -probably use drm_fb_helper_fbdev_teardown(). +Most drivers can use drm_fbdev_generic_setup(). Driver have to implement +atomic modesetting and GEM vmap support. Current generic fbdev emulation +expects the framebuffer in system memory (or system-like memory). Contact: Maintainer of the driver you plan to convert @@ -328,8 +319,8 @@ drm_fb_helper tasks these igt tests need to be fixed: kms_fbcon_fbt@psr and kms_fbcon_fbt@psr-suspend. -- The max connector argument for drm_fb_helper_init() and - drm_fb_helper_fbdev_setup() isn't used anymore and can be removed. +- The max connector argument for drm_fb_helper_init() isn't used anymore and + can be removed. - The helper doesn't keep an array of connectors anymore so these can be removed: drm_fb_helper_single_add_all_connectors(), -- cgit v1.2.3 From 6b81141deb7358dbd64ce3e793cd1e3f5939f807 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Fri, 8 Nov 2019 23:45:56 -0500 Subject: XArray: Improve documentation of search marks Move most of the mark-related documentation to its own section to make it easier to understand. Add clarification that you can't search for an unset mark, and you can't yet search for combinations of marks. Signed-off-by: Matthew Wilcox (Oracle) --- Documentation/core-api/xarray.rst | 60 +++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'Documentation') diff --git a/Documentation/core-api/xarray.rst b/Documentation/core-api/xarray.rst index fcedc5349ace..39b61ade7355 100644 --- a/Documentation/core-api/xarray.rst +++ b/Documentation/core-api/xarray.rst @@ -25,10 +25,6 @@ good performance with large indices. If your index can be larger than ``ULONG_MAX`` then the XArray is not the data type for you. The most important user of the XArray is the page cache. -Each non-``NULL`` entry in the array has three bits associated with -it called marks. Each mark may be set or cleared independently of -the others. You can iterate over entries which are marked. - Normal pointers may be stored in the XArray directly. They must be 4-byte aligned, which is true for any pointer returned from kmalloc() and alloc_page(). It isn't true for arbitrary user-space pointers, @@ -41,12 +37,11 @@ When you retrieve an entry from the XArray, you can check whether it is a value entry by calling xa_is_value(), and convert it back to an integer by calling xa_to_value(). -Some users want to store tagged pointers instead of using the marks -described above. They can call xa_tag_pointer() to create an -entry with a tag, xa_untag_pointer() to turn a tagged entry -back into an untagged pointer and xa_pointer_tag() to retrieve -the tag of an entry. Tagged pointers use the same bits that are used -to distinguish value entries from normal pointers, so each user must +Some users want to tag the pointers they store in the XArray. You can +call xa_tag_pointer() to create an entry with a tag, xa_untag_pointer() +to turn a tagged entry back into an untagged pointer and xa_pointer_tag() +to retrieve the tag of an entry. Tagged pointers use the same bits that +are used to distinguish value entries from normal pointers, so you must decide whether they want to store value entries or tagged pointers in any particular XArray. @@ -56,10 +51,9 @@ conflict with value entries or internal entries. An unusual feature of the XArray is the ability to create entries which occupy a range of indices. Once stored to, looking up any index in the range will return the same entry as looking up any other index in -the range. Setting a mark on one index will set it on all of them. -Storing to any index will store to all of them. Multi-index entries can -be explicitly split into smaller entries, or storing ``NULL`` into any -entry will cause the XArray to forget about the range. +the range. Storing to any index will store to all of them. Multi-index +entries can be explicitly split into smaller entries, or storing ``NULL`` +into any entry will cause the XArray to forget about the range. Normal API ========== @@ -87,12 +81,6 @@ If you want to only store a new entry to an index if the current entry at that index is ``NULL``, you can use xa_insert() which returns ``-EBUSY`` if the entry is not empty. -You can enquire whether a mark is set on an entry by using -xa_get_mark(). If the entry is not ``NULL``, you can set a mark -on it by using xa_set_mark() and remove the mark from an entry by -calling xa_clear_mark(). You can ask whether any entry in the -XArray has a particular mark set by calling xa_marked(). - You can copy entries out of the XArray into a plain array by calling xa_extract(). Or you can iterate over the present entries in the XArray by calling xa_for_each(). You may prefer to use @@ -124,6 +112,31 @@ xa_destroy(). If the XArray entries are pointers, you may wish to free the entries first. You can do this by iterating over all present entries in the XArray using the xa_for_each() iterator. +Search Marks +------------ + +Each entry in the array has three bits associated with it called marks. +Each mark may be set or cleared independently of the others. You can +iterate over marked entries by using the xa_for_each_marked() iterator. + +You can enquire whether a mark is set on an entry by using +xa_get_mark(). If the entry is not ``NULL``, you can set a mark on it +by using xa_set_mark() and remove the mark from an entry by calling +xa_clear_mark(). You can ask whether any entry in the XArray has a +particular mark set by calling xa_marked(). Erasing an entry from the +XArray causes all marks associated with that entry to be cleared. + +Setting or clearing a mark on any index of a multi-index entry will +affect all indices covered by that entry. Querying the mark on any +index will return the same result. + +There is no way to iterate over entries which are not marked; the data +structure does not allow this to be implemented efficiently. There are +not currently iterators to search for logical combinations of bits (eg +iterate over all entries which have both ``XA_MARK_1`` and ``XA_MARK_2`` +set, or iterate over all entries which have ``XA_MARK_0`` or ``XA_MARK_2`` +set). It would be possible to add these if a user arises. + Allocating XArrays ------------------ @@ -419,10 +432,9 @@ you last processed. If you have interrupts disabled while iterating, then it is good manners to pause the iteration and reenable interrupts every ``XA_CHECK_SCHED`` entries. -The xas_get_mark(), xas_set_mark() and -xas_clear_mark() functions require the xa_state cursor to have -been moved to the appropriate location in the xarray; they will do -nothing if you have called xas_pause() or xas_set() +The xas_get_mark(), xas_set_mark() and xas_clear_mark() functions require +the xa_state cursor to have been moved to the appropriate location in the +XArray; they will do nothing if you have called xas_pause() or xas_set() immediately before. You can call xas_set_update() to have a callback function -- cgit v1.2.3 From 8d938df2056253218555800ea39a6ec391669f18 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 14 Nov 2019 14:15:24 +0100 Subject: drm/panel: Add DT bindings for Sony ACX424AKP This adds device tree bindings for the Sony ACX424AKP panel. Let's use YAML. Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20191114131525.3988-1-linus.walleij@linaro.org --- .../bindings/display/panel/sony,acx424akp.yaml | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml b/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml new file mode 100644 index 000000000000..185dcc8fd1f9 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/sony,acx424akp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Sony ACX424AKP 4" 480x864 AMOLED panel + +maintainers: + - Linus Walleij + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: sony,acx424akp + reg: true + reset-gpios: true + vddi-supply: + description: regulator that supplies the vddi voltage + enforce-video-mode: true + +required: + - compatible + - reg + - reset-gpios + +additionalProperties: false + +examples: + - | + #include + + dsi-controller@a0351000 { + compatible = "ste,mcde-dsi"; + reg = <0xa0351000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "sony,acx424akp"; + reg = <0>; + vddi-supply = <&foo>; + reset-gpios = <&foo_gpio 0 GPIO_ACTIVE_LOW>; + }; + }; + +... -- cgit v1.2.3 From a00140b93340557c2d48d04fad3c6d31b06b1de8 Mon Sep 17 00:00:00 2001 From: Beniamin Bia Date: Fri, 15 Nov 2019 15:57:22 +0200 Subject: dt-binding: iio: Add documentation for AD7091R5 Documentation for AD7091R5 ADC was added. Signed-off-by: Beniamin Bia Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/adc/adi,ad7091r5.yaml | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml new file mode 100644 index 000000000000..31ffa275f5fa --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7091r5.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad7091r5.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD7091R5 4-Channel 12-Bit ADC + +maintainers: + - Beniamin Bia + +description: | + Analog Devices AD7091R5 4-Channel 12-Bit ADC + https://www.analog.com/media/en/technical-documentation/data-sheets/ad7091r-5.pdf + +properties: + compatible: + enum: + - adi,ad7091r5 + + reg: + maxItems: 1 + + vref-supply: + description: + Phandle to the vref power supply + + interrupts: + maxItems: 1 + + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + adc@2f { + compatible = "adi,ad7091r5"; + reg = <0x2f>; + + interrupts = <25 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + }; + }; +... -- cgit v1.2.3 From 3f6bba19071eac393a7f39755e235b286a7bb09a Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:49 +0100 Subject: Documentation: ABI: document IIO in_temp_filter_notch_center_frequency file max31856 IIO driver introduced a new attribute "in_temp_filter_notch_center_frequency". This patch adds it to the list of documented ABI for sysfs-bus-iio Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index faaa2166d741..94f7eb675108 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1726,3 +1726,10 @@ Contact: linux-iio@vger.kernel.org Description: List of valid periods (in seconds) for which the light intensity must be above the threshold level before interrupt is asserted. + +What: /sys/bus/iio/devices/iio:deviceX/in_filter_notch_center_frequency +KernelVersion: 5.5 +Contact: linux-iio@vger.kernel.org +Description: + Center frequency in Hz for a notch filter. Used i.e. for line + noise suppression. -- cgit v1.2.3 From 83b9af6f283e95e9a9c2b5dc684d054278ac4728 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:53 +0100 Subject: Documentation: ABI: document IIO thermocouple_type file IIO core layer gained a new sysfs standard attribute "thermocouple_type". This patch adds it to the list of documented ABI for sysfs-bus-iio Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Signed-off-by: Andrea Merello Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 94f7eb675108..d3e53a6d8331 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1733,3 +1733,9 @@ Contact: linux-iio@vger.kernel.org Description: Center frequency in Hz for a notch filter. Used i.e. for line noise suppression. + +What: /sys/bus/iio/devices/iio:deviceX/in_temp_thermocouple_type +KernelVersion: 5.5 +Contact: linux-iio@vger.kernel.org +Description: + One of the following thermocouple types: B, E, J, K, N, R, S, T. -- cgit v1.2.3 From 3922f930de9d83fab3dcdc432ac046d79583e430 Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Wed, 20 Nov 2019 15:47:56 +0100 Subject: dt-bindings: iio: maxim_thermocouple: document new 'compatible' strings Now the maxim_thermocouple has new, more specific, 'compatible' strings for better distinguish the various supported chips. This patch updates the DT bindings documentation accordingly Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald-Stadler Cc: Colin Ian King Cc: Patrick Havelange Cc: Matt Weber Cc: Matt Ranostay Cc: Chuhong Yuan Cc: Daniel Gomez Cc: linux-iio@vger.kernel.org Cc: Rob Herring Cc: Mark Rutland Cc: devicetree@vger.kernel.org Signed-off-by: Andrea Merello Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/temperature/maxim_thermocouple.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt index 28bc5c4d965b..bb85cd0e039c 100644 --- a/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt +++ b/Documentation/devicetree/bindings/iio/temperature/maxim_thermocouple.txt @@ -5,7 +5,10 @@ Maxim thermocouple support Required properties: - - compatible: must be "maxim,max31855" or "maxim,max6675" + - compatible: must be "maxim,max6675" or one of the following: + "maxim,max31855k", "maxim,max31855j", "maxim,max31855n", + "maxim,max31855s", "maxim,max31855t", "maxim,max31855e", + "maxim,max31855r"; the generic "max,max31855" is deprecated. - reg: SPI chip select number for the device - spi-max-frequency: must be 4300000 - spi-cpha: must be defined for max6675 to enable SPI mode 1 @@ -15,7 +18,7 @@ Required properties: Example: max31855@0 { - compatible = "maxim,max31855"; + compatible = "maxim,max31855k"; reg = <0>; spi-max-frequency = <4300000>; }; -- cgit v1.2.3 From 3e9769624bd6c86744f72ab43b0a098f23478454 Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 18 Nov 2019 08:35:55 +0100 Subject: dt-bindings: add vendor prefix parallax Add new vendor prefix parallax for newly created ping iio sensors. Signed-off-by: Andreas Klinger Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 967e78c5ec0a..d3f9690e1e4b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -713,6 +713,8 @@ patternProperties: description: Panasonic Corporation "^parade,.*": description: Parade Technologies Inc. + "^parallax,.*": + description: Parallax Inc. "^pda,.*": description: Precision Design Associates, Inc. "^pericom,.*": -- cgit v1.2.3 From b7f35e7dc8aa880751711a4f1171f7ee6b9f26c7 Mon Sep 17 00:00:00 2001 From: Andreas Klinger Date: Mon, 18 Nov 2019 08:36:12 +0100 Subject: dt-bindings: add parallax ping sensors Add dt-bindings for parallax PING))) and LaserPING iio sensors, which are used for measuring distances. Signed-off-by: Andreas Klinger Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/proximity/parallax-ping.yaml | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml b/Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml new file mode 100644 index 000000000000..a079c9921af6 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/parallax-ping.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/proximity/parallax-ping.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Parallax PING))) and LaserPING range finder + +maintainers: + - Andreas Klinger + +description: | + Bit-banging driver using one GPIO: + - ping-gpios is raised by the driver to start measurement + - direction of ping-gpio is then switched into input with an interrupt + for receiving distance value as PWM signal + + Specifications about the devices can be found at: + http://parallax.com/sites/default/files/downloads/28041-LaserPING-2m-Rangefinder-Guide.pdf + http://parallax.com/sites/default/files/downloads/28015-PING-Documentation-v1.6.pdf + +properties: + compatible: + enum: + - parallax,ping + - parallax,laserping + + ping-gpios: + description: + Definition of the GPIO for the triggering and echo (output and input) + This GPIO is set for about 5 us by the driver to tell the device it + should initiate the measurement cycle. Afterwards the GPIO is switched + to input direction with an interrupt. The device sets it and the + length of the input signal corresponds to the measured distance. + It needs to be an GPIO which is able to deliver an interrupt because + the time between two interrupts is measured in the driver. + See Documentation/devicetree/bindings/gpio/gpio.txt for information + on how to specify a consumer gpio. + maxItems: 1 + +required: + - compatible + - ping-gpios + +examples: + - | + #include + proximity { + compatible = "parallax,laserping"; + ping-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + }; -- cgit v1.2.3 From dae0978d4174422b4a2aa08a96252a1e60d40ef5 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 15 Nov 2019 11:28:25 +0200 Subject: dt: bindings: net: add qcom,ath11k.yaml ath11k is a driver for Qualcomm IEEE 802.11ax devices. Add a bindings document for the driver, first documenting IPQ8074 which is the only device ath11k currently supports. Signed-off-by: Anilkumar Kolli Reviewed-by: Rob Herring Signed-off-by: Kalle Valo --- .../bindings/net/wireless/qcom,ath11k.yaml | 273 +++++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml new file mode 100644 index 000000000000..a1717db36dba --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml @@ -0,0 +1,273 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/wireless/qcom,ath11k.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Technologies ath11k wireless devices Generic Binding + +maintainers: + - Kalle Valo + +description: | + These are dt entries for Qualcomm Technologies, Inc. IEEE 802.11ax + devices, for example like AHB based IPQ8074. + +properties: + compatible: + const: qcom,ipq8074-wifi + + reg: + maxItems: 1 + + interrupts: + items: + - description: misc-pulse1 interrupt events + - description: misc-latch interrupt events + - description: sw exception interrupt events + - description: watchdog interrupt events + - description: interrupt event for ring CE0 + - description: interrupt event for ring CE1 + - description: interrupt event for ring CE2 + - description: interrupt event for ring CE3 + - description: interrupt event for ring CE4 + - description: interrupt event for ring CE5 + - description: interrupt event for ring CE6 + - description: interrupt event for ring CE7 + - description: interrupt event for ring CE8 + - description: interrupt event for ring CE9 + - description: interrupt event for ring CE10 + - description: interrupt event for ring CE11 + - description: interrupt event for ring host2wbm-desc-feed + - description: interrupt event for ring host2reo-re-injection + - description: interrupt event for ring host2reo-command + - description: interrupt event for ring host2rxdma-monitor-ring3 + - description: interrupt event for ring host2rxdma-monitor-ring2 + - description: interrupt event for ring host2rxdma-monitor-ring1 + - description: interrupt event for ring reo2ost-exception + - description: interrupt event for ring wbm2host-rx-release + - description: interrupt event for ring reo2host-status + - description: interrupt event for ring reo2host-destination-ring4 + - description: interrupt event for ring reo2host-destination-ring3 + - description: interrupt event for ring reo2host-destination-ring2 + - description: interrupt event for ring reo2host-destination-ring1 + - description: interrupt event for ring rxdma2host-monitor-destination-mac3 + - description: interrupt event for ring rxdma2host-monitor-destination-mac2 + - description: interrupt event for ring rxdma2host-monitor-destination-mac1 + - description: interrupt event for ring ppdu-end-interrupts-mac3 + - description: interrupt event for ring ppdu-end-interrupts-mac2 + - description: interrupt event for ring ppdu-end-interrupts-mac1 + - description: interrupt event for ring rxdma2host-monitor-status-ring-mac3 + - description: interrupt event for ring rxdma2host-monitor-status-ring-mac2 + - description: interrupt event for ring rxdma2host-monitor-status-ring-mac1 + - description: interrupt event for ring host2rxdma-host-buf-ring-mac3 + - description: interrupt event for ring host2rxdma-host-buf-ring-mac2 + - description: interrupt event for ring host2rxdma-host-buf-ring-mac1 + - description: interrupt event for ring rxdma2host-destination-ring-mac3 + - description: interrupt event for ring rxdma2host-destination-ring-mac2 + - description: interrupt event for ring rxdma2host-destination-ring-mac1 + - description: interrupt event for ring host2tcl-input-ring4 + - description: interrupt event for ring host2tcl-input-ring3 + - description: interrupt event for ring host2tcl-input-ring2 + - description: interrupt event for ring host2tcl-input-ring1 + - description: interrupt event for ring wbm2host-tx-completions-ring3 + - description: interrupt event for ring wbm2host-tx-completions-ring2 + - description: interrupt event for ring wbm2host-tx-completions-ring1 + - description: interrupt event for ring tcl2host-status-ring + + + interrupt-names: + items: + - const: misc-pulse1 + - const: misc-latch + - const: sw-exception + - const: watchdog + - const: ce0 + - const: ce1 + - const: ce2 + - const: ce3 + - const: ce4 + - const: ce5 + - const: ce6 + - const: ce7 + - const: ce8 + - const: ce9 + - const: ce10 + - const: ce11 + - const: host2wbm-desc-feed + - const: host2reo-re-injection + - const: host2reo-command + - const: host2rxdma-monitor-ring3 + - const: host2rxdma-monitor-ring2 + - const: host2rxdma-monitor-ring1 + - const: reo2ost-exception + - const: wbm2host-rx-release + - const: reo2host-status + - const: reo2host-destination-ring4 + - const: reo2host-destination-ring3 + - const: reo2host-destination-ring2 + - const: reo2host-destination-ring1 + - const: rxdma2host-monitor-destination-mac3 + - const: rxdma2host-monitor-destination-mac2 + - const: rxdma2host-monitor-destination-mac1 + - const: ppdu-end-interrupts-mac3 + - const: ppdu-end-interrupts-mac2 + - const: ppdu-end-interrupts-mac1 + - const: rxdma2host-monitor-status-ring-mac3 + - const: rxdma2host-monitor-status-ring-mac2 + - const: rxdma2host-monitor-status-ring-mac1 + - const: host2rxdma-host-buf-ring-mac3 + - const: host2rxdma-host-buf-ring-mac2 + - const: host2rxdma-host-buf-ring-mac1 + - const: rxdma2host-destination-ring-mac3 + - const: rxdma2host-destination-ring-mac2 + - const: rxdma2host-destination-ring-mac1 + - const: host2tcl-input-ring4 + - const: host2tcl-input-ring3 + - const: host2tcl-input-ring2 + - const: host2tcl-input-ring1 + - const: wbm2host-tx-completions-ring3 + - const: wbm2host-tx-completions-ring2 + - const: wbm2host-tx-completions-ring1 + - const: tcl2host-status-ring + + qcom,rproc: + $ref: /schemas/types.yaml#definitions/phandle + description: + DT entry of q6v5-wcss remoteproc driver. + Phandle to a node that can contain the following properties + * compatible + * reg + * reg-names + +required: + - compatible + - reg + - interrupts + - interrupt-names + - qcom,rproc + +additionalProperties: false + +examples: + - | + + q6v5_wcss: q6v5_wcss@CD00000 { + compatible = "qcom,ipq8074-wcss-pil"; + reg = <0xCD00000 0x4040>, + <0x4AB000 0x20>; + reg-names = "qdsp6", + "rmb"; + }; + + wifi0: wifi@c000000 { + compatible = "qcom,ipq8074-wifi"; + reg = <0xc000000 0x2000000>; + interrupts = <0 320 1>, + <0 319 1>, + <0 318 1>, + <0 317 1>, + <0 316 1>, + <0 315 1>, + <0 314 1>, + <0 311 1>, + <0 310 1>, + <0 411 1>, + <0 410 1>, + <0 40 1>, + <0 39 1>, + <0 302 1>, + <0 301 1>, + <0 37 1>, + <0 36 1>, + <0 296 1>, + <0 295 1>, + <0 294 1>, + <0 293 1>, + <0 292 1>, + <0 291 1>, + <0 290 1>, + <0 289 1>, + <0 288 1>, + <0 239 1>, + <0 236 1>, + <0 235 1>, + <0 234 1>, + <0 233 1>, + <0 232 1>, + <0 231 1>, + <0 230 1>, + <0 229 1>, + <0 228 1>, + <0 224 1>, + <0 223 1>, + <0 203 1>, + <0 183 1>, + <0 180 1>, + <0 179 1>, + <0 178 1>, + <0 177 1>, + <0 176 1>, + <0 163 1>, + <0 162 1>, + <0 160 1>, + <0 159 1>, + <0 158 1>, + <0 157 1>, + <0 156 1>; + interrupt-names = "misc-pulse1", + "misc-latch", + "sw-exception", + "watchdog", + "ce0", + "ce1", + "ce2", + "ce3", + "ce4", + "ce5", + "ce6", + "ce7", + "ce8", + "ce9", + "ce10", + "ce11", + "host2wbm-desc-feed", + "host2reo-re-injection", + "host2reo-command", + "host2rxdma-monitor-ring3", + "host2rxdma-monitor-ring2", + "host2rxdma-monitor-ring1", + "reo2ost-exception", + "wbm2host-rx-release", + "reo2host-status", + "reo2host-destination-ring4", + "reo2host-destination-ring3", + "reo2host-destination-ring2", + "reo2host-destination-ring1", + "rxdma2host-monitor-destination-mac3", + "rxdma2host-monitor-destination-mac2", + "rxdma2host-monitor-destination-mac1", + "ppdu-end-interrupts-mac3", + "ppdu-end-interrupts-mac2", + "ppdu-end-interrupts-mac1", + "rxdma2host-monitor-status-ring-mac3", + "rxdma2host-monitor-status-ring-mac2", + "rxdma2host-monitor-status-ring-mac1", + "host2rxdma-host-buf-ring-mac3", + "host2rxdma-host-buf-ring-mac2", + "host2rxdma-host-buf-ring-mac1", + "rxdma2host-destination-ring-mac3", + "rxdma2host-destination-ring-mac2", + "rxdma2host-destination-ring-mac1", + "host2tcl-input-ring4", + "host2tcl-input-ring3", + "host2tcl-input-ring2", + "host2tcl-input-ring1", + "wbm2host-tx-completions-ring3", + "wbm2host-tx-completions-ring2", + "wbm2host-tx-completions-ring1", + "tcl2host-status-ring"; + qcom,rproc = <&q6v5_wcss>; + }; -- cgit v1.2.3 From 6fc0e19036d6198b9287bb74c0c9df7c17ec8c2e Mon Sep 17 00:00:00 2001 From: Abhishek Pandit-Subedi Date: Tue, 26 Nov 2019 08:17:31 +0100 Subject: dt-bindings: net: bluetooth: update broadcom-bluetooth Add documentation for brcm,bt-pcm-int-params vendor specific configuration of the SCO PCM settings. Signed-off-by: Abhishek Pandit-Subedi Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- Documentation/devicetree/bindings/net/broadcom-bluetooth.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt index f16b99571af1..b02a53275c98 100644 --- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt +++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt @@ -30,6 +30,12 @@ Optional properties: - "lpo": external low power 32.768 kHz clock - vbat-supply: phandle to regulator supply for VBAT - vddio-supply: phandle to regulator supply for VDDIO + - brcm,bt-pcm-int-params: configure PCM parameters via a 5-byte array + - sco-routing: 0 = PCM, 1 = Transport, 2 = Codec, 3 = I2S + - pcm-interface-rate: 128KBps, 256KBps, 512KBps, 1024KBps, 2048KBps + - pcm-frame-type: short, long + - pcm-sync-mode: slave, master + - pcm-clock-mode: slave, master Example: @@ -41,5 +47,6 @@ Example: bluetooth { compatible = "brcm,bcm43438-bt"; max-speed = <921600>; + brcm,bt-pcm-int-params = [1 2 0 1 1]; }; }; -- cgit v1.2.3 From 3cd9d35ee5f7a23203443f1a0d3c344f034c0dc7 Mon Sep 17 00:00:00 2001 From: Abhishek Pandit-Subedi Date: Wed, 27 Nov 2019 14:45:09 -0800 Subject: dt-bindings: net: bluetooth: Minor fix in broadcom-bluetooth The example for brcm,bt-pcm-int-params should be a bytestring and all values need to be two hex characters. Signed-off-by: Abhishek Pandit-Subedi Signed-off-by: Marcel Holtmann --- Documentation/devicetree/bindings/net/broadcom-bluetooth.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt index b02a53275c98..b5eadee4a9a7 100644 --- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt +++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt @@ -47,6 +47,6 @@ Example: bluetooth { compatible = "brcm,bcm43438-bt"; max-speed = <921600>; - brcm,bt-pcm-int-params = [1 2 0 1 1]; + brcm,bt-pcm-int-params = [01 02 00 01 01]; }; }; -- cgit v1.2.3 From 2c81bdc8024ef6f81dfecab86bcb97a8694dcd1e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 27 Nov 2019 19:00:35 +0100 Subject: drm/todo: Add entry for fb funcs related cleanups We're doing a great job for really simple drivers right now, but still a lot of boilerplate for the bigger ones. Acked-by: Thomas Zimmermann Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191127180035.416209-3-daniel.vetter@ffwll.ch --- Documentation/gpu/todo.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'Documentation') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 3ec509381fc5..2d85f37284a1 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -182,6 +182,32 @@ Contact: Maintainer of the driver you plan to convert Level: Intermediate +drm_framebuffer_funcs and drm_mode_config_funcs.fb_create cleanup +----------------------------------------------------------------- + +A lot more drivers could be switched over to the drm_gem_framebuffer helpers. +Various hold-ups: + +- Need to switch over to the generic dirty tracking code using + drm_atomic_helper_dirtyfb first (e.g. qxl). + +- Need to switch to drm_fbdev_generic_setup(), otherwise a lot of the custom fb + setup code can't be deleted. + +- Many drivers wrap drm_gem_fb_create() only to check for valid formats. For + atomic drivers we could check for valid formats by calling + drm_plane_check_pixel_format() against all planes, and pass if any plane + supports the format. For non-atomic that's not possible since like the format + list for the primary plane is fake and we'd therefor reject valid formats. + +- Many drivers subclass drm_framebuffer, we'd need a embedding compatible + version of the varios drm_gem_fb_create functions. Maybe called + drm_gem_fb_create/_with_dirty/_with_funcs as needed. + +Contact: Daniel Vetter + +Level: Intermediate + Clean up mmap forwarding ------------------------ -- cgit v1.2.3 From 65b2f7c43c6f087784db309e8a75bae3d2266520 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 8 Nov 2019 15:56:54 +0200 Subject: drm: Inline drm_color_lut_extract() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This thing can get called several thousand times per LUT so seems like we want to inline it to: - avoid the function call overhead - allow constant folding A quick synthetic test (w/o any hardware interaction) with a ridiculously large LUT size shows about 50% reduction in runtime on my HSW and BSW boxes. Slightly less with more reasonable LUT size but still easily measurable in tens of microseconds. v2: Include drm_color_mgmt.h in the .rst (Daniel) Cc: Daniel Vetter Signed-off-by: Ville Syrjälä Reviewed-by: Nicholas Kazlauskas Link: https://patchwork.freedesktop.org/patch/msgid/20191108135654.12907-1-ville.syrjala@linux.intel.com --- Documentation/gpu/drm-kms.rst | 3 +++ drivers/gpu/drm/drm_color_mgmt.c | 24 ------------------------ include/drm/drm_color_mgmt.h | 24 +++++++++++++++++++++++- 3 files changed, 26 insertions(+), 25 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 23a3c986ef6d..c68588ce4090 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -479,6 +479,9 @@ Color Management Properties .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c :export: +.. kernel-doc:: include/drm/drm_color_mgmt.h + :internal: + Tile Group Property ------------------- diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index ba71e3b827f1..c93123ff7c21 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -108,30 +108,6 @@ * standard enum values supported by the DRM plane. */ -/** - * drm_color_lut_extract - clamp and round LUT entries - * @user_input: input value - * @bit_precision: number of bits the hw LUT supports - * - * Extract a degamma/gamma LUT value provided by user (in the form of - * &drm_color_lut entries) and round it to the precision supported by the - * hardware. - */ -uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision) -{ - uint32_t val = user_input; - uint32_t max = 0xffff >> (16 - bit_precision); - - /* Round only if we're not using full precision. */ - if (bit_precision < 16) { - val += 1UL << (16 - bit_precision - 1); - val >>= 16 - bit_precision; - } - - return clamp_val(val, 0, max); -} -EXPORT_SYMBOL(drm_color_lut_extract); - /** * drm_color_ctm_s31_32_to_qm_n * diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 997a42ab29f5..81c298488b0c 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -29,7 +29,29 @@ struct drm_crtc; struct drm_plane; -uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision); +/** + * drm_color_lut_extract - clamp and round LUT entries + * @user_input: input value + * @bit_precision: number of bits the hw LUT supports + * + * Extract a degamma/gamma LUT value provided by user (in the form of + * &drm_color_lut entries) and round it to the precision supported by the + * hardware. + */ +static inline u32 drm_color_lut_extract(u32 user_input, int bit_precision) +{ + u32 val = user_input; + u32 max = 0xffff >> (16 - bit_precision); + + /* Round only if we're not using full precision. */ + if (bit_precision < 16) { + val += 1UL << (16 - bit_precision - 1); + val >>= 16 - bit_precision; + } + + return clamp_val(val, 0, max); +} + u64 drm_color_ctm_s31_32_to_qm_n(u64 user_input, u32 m, u32 n); void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, -- cgit v1.2.3 From 621dab99847821d671e46509c4775d905c72a763 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 16 Oct 2019 08:51:46 -0500 Subject: dt-bindings: Add Logic PD Type 28 display panel This patch adds documentation of device tree bindings for the WVGA panel Logic PD Type 28 display. Signed-off-by: Adam Ford Reviewed-by: Rob Herring Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191016135147.7743-2-aford173@gmail.com --- .../bindings/display/panel/logicpd,type28.yaml | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/logicpd,type28.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/logicpd,type28.yaml b/Documentation/devicetree/bindings/display/panel/logicpd,type28.yaml new file mode 100644 index 000000000000..2834287b8d88 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/logicpd,type28.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/logicpd,type28.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Logic PD Type 28 4.3" WQVGA TFT LCD panel + +maintainers: + - Adam Ford + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: logicpd,type28 + + power-supply: true + enable-gpios: true + backlight: true + port: true + +required: + - compatible + +additionalProperties: false + +examples: + - | + lcd0: display { + compatible = "logicpd,type28"; + enable-gpios = <&gpio5 27 0>; + backlight = <&backlight>; + port { + lcd_in: endpoint { + remote-endpoint = <&dpi_out>; + }; + }; + }; + +... -- cgit v1.2.3 From dc190678534ee0f9042a65db1613ab1e59582bff Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 28 Nov 2019 10:07:26 +0100 Subject: drm/panel: Add generic DSI display controller YAML bindings This adds a starting point for processing and defining generic bindings used by DSI display controllers and panels attached to the virtual DSI ports. Cc: Stephan Gerhold Cc: devicetree@vger.kernel.org Suggested-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20191128090726.51107-1-linus.walleij@linaro.org Reviewed-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/display/dsi-controller.yaml | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/dsi-controller.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/dsi-controller.yaml b/Documentation/devicetree/bindings/display/dsi-controller.yaml new file mode 100644 index 000000000000..fd986c36c737 --- /dev/null +++ b/Documentation/devicetree/bindings/display/dsi-controller.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/dsi-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Common Properties for DSI Display Panels + +maintainers: + - Linus Walleij + +description: | + This document defines device tree properties common to DSI, Display + Serial Interface controllers and attached panels. It doesn't constitute + a device tree binding specification by itself but is meant to be referenced + by device tree bindings. + + When referenced from panel device tree bindings the properties defined in + this document are defined as follows. The panel device tree bindings are + responsible for defining whether each property is required or optional. + + Notice: this binding concerns DSI panels connected directly to a master + without any intermediate port graph to the panel. Each DSI master + can control one to four virtual channels to one panel. Each virtual + channel should have a node "panel" for their virtual channel with their + reg-property set to the virtual channel number, usually there is just + one virtual channel, number 0. + +properties: + $nodename: + pattern: "^dsi-controller(@.*)?$" + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^panel@[0-3]$": + description: Panels connected to the DSI link + type: object + + properties: + reg: + minimum: 0 + maximum: 3 + description: + The virtual channel number of a DSI peripheral. Must be in the range + from 0 to 3, as DSI uses a 2-bit addressing scheme. Some DSI + peripherals respond to more than a single virtual channel. In that + case the reg property can take multiple entries, one for each virtual + channel that the peripheral responds to. + + clock-master: + type: boolean + description: + Should be enabled if the host is being used in conjunction with + another DSI host to drive the same peripheral. Hardware supporting + such a configuration generally requires the data on both the busses + to be driven by the same clock. Only the DSI host instance + controlling this clock should contain this property. + + enforce-video-mode: + type: boolean + description: + The best option is usually to run a panel in command mode, as this + gives better control over the panel hardware. However for different + reasons like broken hardware, missing features or testing, it may be + useful to be able to force a command mode-capable panel into video + mode. + + required: + - reg + +examples: + - | + #include + dsi-controller@a0351000 { + reg = <0xa0351000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + panel@0 { + compatible = "sony,acx424akp"; + reg = <0>; + vddi-supply = <&ab8500_ldo_aux1_reg>; + reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; + }; + }; + +... -- cgit v1.2.3 From 6f91f44dea701c7504dfe8af920f493ea0eed9cf Mon Sep 17 00:00:00 2001 From: Gabriela Bittencourt Date: Mon, 4 Nov 2019 13:27:05 -0300 Subject: drm/doc: Add VKMS module description and use to "Testing and Validation" Add a description on VKMS module and the cases in which it should be used. There's a brief explanation on how to set it and use it in a VM, along with an example of running an igt-test. Changes since V3: Rodrigo: - Change the log message to imperative - Fix some bad spelling/writing - Add a blank line before enumeration Changes since V2: Andre: - Avoid repetition of words in the same sentence; - Make the explanation on 'setting the kernel' shorter, eliminate the 'make menuconfig' command; - Add tab on enumeration to have one line per item; - Clarify from each machine igt-tests commands should be ran on. Reviewed-by: Rodrigo Siqueira Signed-off-by: Gabriela Bittencourt Signed-off-by: Rodrigo Siqueira Link: https://patchwork.freedesktop.org/patch/msgid/20191104162705.19735-1-gabrielabittencourt00@gmail.com --- Documentation/gpu/drm-uapi.rst | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'Documentation') diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 996f7354e05c..56fec6ed1ad8 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -257,6 +257,43 @@ core don't regress existing functionality. This test suite is called IGT and its code and instructions to build and run can be found in https://gitlab.freedesktop.org/drm/igt-gpu-tools/. +Using VKMS to test DRM API +-------------------------- + +VKMS is a software-only model of a KMS driver that is useful for testing +and for running compositors. VKMS aims to enable a virtual display without +the need for a hardware display capability. These characteristics made VKMS +a perfect tool for validating the DRM core behavior and also support the +compositor developer. VKMS makes it possible to test DRM functions in a +virtual machine without display, simplifying the validation of some of the +core changes. + +To Validate changes in DRM API with VKMS, start setting the kernel: make +sure to enable VKMS module; compile the kernel with the VKMS enabled and +install it in the target machine. VKMS can be run in a Virtual Machine +(QEMU, virtme or similar). It's recommended the use of KVM with the minimum +of 1GB of RAM and four cores. + +It's possible to run the IGT-tests in a VM in two ways: + + 1. Use IGT inside a VM + 2. Use IGT from the host machine and write the results in a shared directory. + +As follow, there is an example of using a VM with a shared directory with +the host machine to run igt-tests. As an example it's used virtme:: + + $ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto + +Run the igt-tests in the guest machine, as example it's ran the 'kms_flip' +tests:: + + $ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v + +In this example, instead of build the igt_runner, Piglit is used +(-p option); it's created html summary of the tests results and it's saved +in the folder "igt-gpu-tools/results"; it's executed only the igt-tests +matching the -t option. + Display CRC Support ------------------- -- cgit v1.2.3 From a1433ca47e2657f42c4c8d6c5e75824eef03d2e9 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 7 Nov 2019 09:56:04 +0800 Subject: dt-bindings: arm: imx: Add the i.MX6SX-SDB Rev-A board Add board binding for i.MX6SX-SDB Rev-A board which is already supported. Signed-off-by: Anson Huang Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index f79683a628f0..2f7beda4a961 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -172,6 +172,7 @@ properties: - enum: - fsl,imx6sx-sabreauto # i.MX6 SoloX Sabre Auto Board - fsl,imx6sx-sdb # i.MX6 SoloX SDB Board + - fsl,imx6sx-sdb-reva # i.MX6 SoloX SDB Rev-A Board - const: fsl,imx6sx - description: i.MX6UL based Boards -- cgit v1.2.3 From 7bd9f52628f035a0a9cb3ac5e8ed115c2002c2ef Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Thu, 7 Nov 2019 10:14:53 +0800 Subject: dt-bindings: arm: imx: Add the i.MX7D-SDB Rev-A board Add board binding for i.MX7D-SDB Rev-A board which is already supported. Signed-off-by: Anson Huang Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 2f7beda4a961..5dfea27c7dd2 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -240,6 +240,7 @@ properties: items: - enum: - fsl,imx7d-sdb # i.MX7 SabreSD Board + - fsl,imx7d-sdb-reva # i.MX7 SabreSD Rev-A Board - novtech,imx7d-meerkat96 # i.MX7 Meerkat96 Board - toradex,colibri-imx7d # Colibri iMX7 Dual Module - toradex,colibri-imx7d-emmc # Colibri iMX7 Dual 1GB (eMMC) Module -- cgit v1.2.3 From 5780c958da06397ba0b492c73726f4636705a64d Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Fri, 8 Nov 2019 12:18:33 +0100 Subject: dt-bindings: arm: fsl: add compatible string for Tolino Shine 3 This adds a compatible string for the Tolino Shine 3 eBook reader. Signed-off-by: Andreas Kemnade Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 5dfea27c7dd2..b5497ae276bc 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -158,6 +158,7 @@ properties: items: - enum: - fsl,imx6sl-evk # i.MX6 SoloLite EVK Board + - kobo,tolino-shine3 - const: fsl,imx6sl - description: i.MX6SLL based Boards -- cgit v1.2.3 From c4ed20f74c79cb070f9e2a1cb2acb4f53dfb95a9 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Mon, 23 Sep 2019 15:30:52 +0100 Subject: dt-bindings: timer: renesas: tmu: Document r8a774b1 bindings Document RZ/G2N (R8A774B1) SoC in the Renesas TMU bindings. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/1569249052-1037-1-git-send-email-biju.das@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/timer/renesas,tmu.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/timer/renesas,tmu.txt b/Documentation/devicetree/bindings/timer/renesas,tmu.txt index 9dff7e5cae6a..29159f4e65ab 100644 --- a/Documentation/devicetree/bindings/timer/renesas,tmu.txt +++ b/Documentation/devicetree/bindings/timer/renesas,tmu.txt @@ -11,6 +11,7 @@ Required Properties: - compatible: must contain one or more of the following: - "renesas,tmu-r8a7740" for the r8a7740 TMU - "renesas,tmu-r8a774a1" for the r8a774A1 TMU + - "renesas,tmu-r8a774b1" for the r8a774B1 TMU - "renesas,tmu-r8a774c0" for the r8a774C0 TMU - "renesas,tmu-r8a7778" for the r8a7778 TMU - "renesas,tmu-r8a7779" for the r8a7779 TMU -- cgit v1.2.3 From 8f2b841a00b50766794a7426f22258c77f29b21d Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 12 Nov 2019 15:53:28 +0100 Subject: media: dt-bindings: media: cal: update binding to use syscon Update Device Tree bindings for the CAL driver to use syscon to access the phy config register instead of trying to map it directly. Signed-off-by: Benoit Parrot Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt index ae9b52f37576..93096d924786 100644 --- a/Documentation/devicetree/bindings/media/ti-cal.txt +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -10,9 +10,14 @@ Required properties: - compatible: must be "ti,dra72-cal" - reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX control address space -- reg-names: cal_top, cal_rx_core0, cal_rx_core1, and camerrx_control +- reg-names: cal_top, cal_rx_core0, cal_rx_core1 and camerrx_control registers - interrupts: should contain IRQ line for the CAL; +- ti,camerrx-control: phandle to the device control module and offset to + the control_camerarx_core register. + This node is meant to replace the "camerrx_control" + reg entry above but "camerrx_control" is still + handled for backward compatibility. CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes should contain a 'port' child node with child 'endpoint' node. Please @@ -25,13 +30,12 @@ Example: ti,hwmods = "cal"; reg = <0x4845B000 0x400>, <0x4845B800 0x40>, - <0x4845B900 0x40>, - <0x4A002e94 0x4>; + <0x4845B900 0x40>; reg-names = "cal_top", "cal_rx_core0", - "cal_rx_core1", - "camerrx_control"; + "cal_rx_core1"; interrupts = ; + ti,camerrx-control = <&scm_conf 0xE94>; #address-cells = <1>; #size-cells = <0>; -- cgit v1.2.3 From b99c35a40ca04c1eb1706e6c02d36231f67c0b43 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 12 Nov 2019 15:53:29 +0100 Subject: media: dt-bindings: media: cal: update binding example Update binding example to show proper endpoint properties and linkage. Signed-off-by: Benoit Parrot Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt index 93096d924786..7e960cf26e23 100644 --- a/Documentation/devicetree/bindings/media/ti-cal.txt +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -27,7 +27,6 @@ Documentation/devicetree/bindings/media/video-interfaces.txt. Example: cal: cal@4845b000 { compatible = "ti,dra72-cal"; - ti,hwmods = "cal"; reg = <0x4845B000 0x400>, <0x4845B800 0x40>, <0x4845B900 0x40>; @@ -45,9 +44,10 @@ Example: csi2_0: port@0 { reg = <0>; - endpoint { - slave-mode; - remote-endpoint = <&ar0330_1>; + csi2_phy0: endpoint { + remote-endpoint = <&csi2_cam0>; + clock-lanes = <0>; + data-lanes = <1 2>; }; }; csi2_1: port@1 { @@ -57,19 +57,20 @@ Example: }; i2c5: i2c@4807c000 { - ar0330@10 { - compatible = "ti,ar0330"; - reg = <0x10>; + clock-frequency = <400000>; - port { - #address-cells = <1>; - #size-cells = <0>; + camera-sensor@3c { + compatible = "ovti,ov5640"; + reg = <0x3c>; + + clocks = <&clk_fixed>; + clock-names = "xclk"; - ar0330_1: endpoint { - reg = <0>; - clock-lanes = <1>; - data-lanes = <0 2 3 4>; - remote-endpoint = <&csi2_0>; + port { + csi2_cam0: endpoint { + remote-endpoint = <&csi2_phy0>; + clock-lanes = <0>; + data-lanes = <1 2>; }; }; }; -- cgit v1.2.3 From 03ea2e032e799b7b76a40be3f4fa1eae66cf8fde Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 12 Nov 2019 15:53:34 +0100 Subject: media: dt-bindings: media: cal: update binding to add PHY LDO errata support Update Device Tree bindings for the CAL driver to add support for the CSI2 PHY LDO errata workaround for pre-es2 devices. Signed-off-by: Benoit Parrot Signed-off-by: Jyri Sarha Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt index 7e960cf26e23..cb2dc50a24fb 100644 --- a/Documentation/devicetree/bindings/media/ti-cal.txt +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -7,7 +7,9 @@ processing capability to connect CSI2 image-sensor modules to the DRA72x device. Required properties: -- compatible: must be "ti,dra72-cal" +- compatible: + Should be "ti,dra72-cal", for DRA72 controllers + Should be "ti,dra72-pre-es2-cal", for DRA72 controllers pre ES2.0 - reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX control address space - reg-names: cal_top, cal_rx_core0, cal_rx_core1 and camerrx_control -- cgit v1.2.3 From 3337fba37308ab7a7b74f304758f2b64e46499ae Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 12 Nov 2019 15:53:39 +0100 Subject: media: dt-bindings: media: cal: update binding to add DRA76x support Update Device Tree bindings for the CAL driver to add DRA76x support. Signed-off-by: Benoit Parrot Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt index cb2dc50a24fb..eca28a779370 100644 --- a/Documentation/devicetree/bindings/media/ti-cal.txt +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -10,6 +10,7 @@ Required properties: - compatible: Should be "ti,dra72-cal", for DRA72 controllers Should be "ti,dra72-pre-es2-cal", for DRA72 controllers pre ES2.0 + Should be "ti,dra76-cal", for DRA76 controllers - reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX control address space - reg-names: cal_top, cal_rx_core0, cal_rx_core1 and camerrx_control -- cgit v1.2.3 From 5fa3144be4fceb0d9eace26de404738a7d68f302 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 12 Nov 2019 15:53:41 +0100 Subject: media: dt-bindings: media: cal: update binding to add AM654 support Update Device Tree bindings for the CAL driver to add AM654 support. Signed-off-by: Benoit Parrot Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt index eca28a779370..2deb256e7032 100644 --- a/Documentation/devicetree/bindings/media/ti-cal.txt +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -11,6 +11,7 @@ Required properties: Should be "ti,dra72-cal", for DRA72 controllers Should be "ti,dra72-pre-es2-cal", for DRA72 controllers pre ES2.0 Should be "ti,dra76-cal", for DRA76 controllers + Should be "ti,am654-cal", for AM654 controllers - reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX control address space - reg-names: cal_top, cal_rx_core0, cal_rx_core1 and camerrx_control -- cgit v1.2.3 From 2099ef02c6c024751e4d16ace67dd6b910c875e4 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Tue, 12 Nov 2019 15:53:47 +0100 Subject: media: dt-bindings: media: cal: convert binding to yaml Convert ti-cal.txt to ti,cal.yaml. Add ti,cal.yaml to the MAINTAINERS file. Signed-off-by: Benoit Parrot Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/ti,cal.yaml | 202 +++++++++++++++++++++ Documentation/devicetree/bindings/media/ti-cal.txt | 81 --------- MAINTAINERS | 1 + 3 files changed, 203 insertions(+), 81 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/ti,cal.yaml delete mode 100644 Documentation/devicetree/bindings/media/ti-cal.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/ti,cal.yaml b/Documentation/devicetree/bindings/media/ti,cal.yaml new file mode 100644 index 000000000000..1ea784179536 --- /dev/null +++ b/Documentation/devicetree/bindings/media/ti,cal.yaml @@ -0,0 +1,202 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/ti,cal.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments DRA72x CAMERA ADAPTATION LAYER (CAL) Device Tree Bindings + +maintainers: + - Benoit Parrot + +description: |- + The Camera Adaptation Layer (CAL) is a key component for image capture + applications. The capture module provides the system interface and the + processing capability to connect CSI2 image-sensor modules to the + DRA72x device. + + CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes + should contain a 'port' child node with child 'endpoint' node. Please + refer to the bindings defined in + Documentation/devicetree/bindings/media/video-interfaces.txt. + +properties: + compatible: + enum: + # for DRA72 controllers + - ti,dra72-cal + # for DRA72 controllers pre ES2.0 + - ti,dra72-pre-es2-cal + # for DRA76 controllers + - ti,dra76-cal + # for AM654 controllers + - ti,am654-cal + + reg: + minItems: 2 + items: + - description: The CAL main register region + - description: The RX Core0 (DPHY0) register region + - description: The RX Core1 (DPHY1) register region + + reg-names: + minItems: 2 + items: + - const: cal_top + - const: cal_rx_core0 + - const: cal_rx_core1 + + interrupts: + maxItems: 1 + + ti,camerrx-control: + $ref: "/schemas/types.yaml#/definitions/phandle-array" + description: + phandle to the device control module and offset to the + control_camerarx_core register + + clocks: + maxItems: 1 + + clock-names: + const: fck + + power-domains: + description: + List of phandle and PM domain specifier as documented in + Documentation/devicetree/bindings/power/power_domain.txt + maxItems: 1 + + # See ./video-interfaces.txt for details + ports: + type: object + additionalProperties: false + + properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + port@0: + type: object + additionalProperties: false + + properties: + reg: + const: 0 + description: CSI2 Port #0 + + patternProperties: + endpoint: + type: object + additionalProperties: false + + properties: + clock-lanes: + maxItems: 1 + + data-lanes: + minItems: 1 + maxItems: 4 + + remote-endpoint: true + + required: + - reg + + port@1: + type: object + additionalProperties: false + + properties: + reg: + const: 1 + description: CSI2 Port #1 + + patternProperties: + endpoint: + type: object + additionalProperties: false + + properties: + clock-lanes: + maxItems: 1 + + data-lanes: + minItems: 1 + maxItems: 4 + + remote-endpoint: true + + required: + - reg + + required: + - "#address-cells" + - "#size-cells" + - port@0 + +required: + - compatible + - reg + - reg-names + - interrupts + - ti,camerrx-control + +additionalProperties: false + +examples: + - | + #include + + cal: cal@4845b000 { + compatible = "ti,dra72-cal"; + reg = <0x4845B000 0x400>, + <0x4845B800 0x40>, + <0x4845B900 0x40>; + reg-names = "cal_top", + "cal_rx_core0", + "cal_rx_core1"; + interrupts = ; + ti,camerrx-control = <&scm_conf 0xE94>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csi2_0: port@0 { + reg = <0>; + csi2_phy0: endpoint { + remote-endpoint = <&csi2_cam0>; + clock-lanes = <0>; + data-lanes = <1 2>; + }; + }; + }; + }; + + i2c5: i2c@4807c000 { + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; + + camera-sensor@3c { + compatible = "ovti,ov5640"; + reg = <0x3c>; + + clocks = <&clk_ov5640_fixed>; + clock-names = "xclk"; + + port { + csi2_cam0: endpoint { + remote-endpoint = <&csi2_phy0>; + clock-lanes = <0>; + data-lanes = <1 2>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt deleted file mode 100644 index 2deb256e7032..000000000000 --- a/Documentation/devicetree/bindings/media/ti-cal.txt +++ /dev/null @@ -1,81 +0,0 @@ -Texas Instruments DRA72x CAMERA ADAPTATION LAYER (CAL) ------------------------------------------------------- - -The Camera Adaptation Layer (CAL) is a key component for image capture -applications. The capture module provides the system interface and the -processing capability to connect CSI2 image-sensor modules to the -DRA72x device. - -Required properties: -- compatible: - Should be "ti,dra72-cal", for DRA72 controllers - Should be "ti,dra72-pre-es2-cal", for DRA72 controllers pre ES2.0 - Should be "ti,dra76-cal", for DRA76 controllers - Should be "ti,am654-cal", for AM654 controllers -- reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX - control address space -- reg-names: cal_top, cal_rx_core0, cal_rx_core1 and camerrx_control - registers -- interrupts: should contain IRQ line for the CAL; -- ti,camerrx-control: phandle to the device control module and offset to - the control_camerarx_core register. - This node is meant to replace the "camerrx_control" - reg entry above but "camerrx_control" is still - handled for backward compatibility. - -CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes -should contain a 'port' child node with child 'endpoint' node. Please -refer to the bindings defined in -Documentation/devicetree/bindings/media/video-interfaces.txt. - -Example: - cal: cal@4845b000 { - compatible = "ti,dra72-cal"; - reg = <0x4845B000 0x400>, - <0x4845B800 0x40>, - <0x4845B900 0x40>; - reg-names = "cal_top", - "cal_rx_core0", - "cal_rx_core1"; - interrupts = ; - ti,camerrx-control = <&scm_conf 0xE94>; - #address-cells = <1>; - #size-cells = <0>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - csi2_0: port@0 { - reg = <0>; - csi2_phy0: endpoint { - remote-endpoint = <&csi2_cam0>; - clock-lanes = <0>; - data-lanes = <1 2>; - }; - }; - csi2_1: port@1 { - reg = <1>; - }; - }; - }; - - i2c5: i2c@4807c000 { - clock-frequency = <400000>; - - camera-sensor@3c { - compatible = "ovti,ov5640"; - reg = <0x3c>; - - clocks = <&clk_fixed>; - clock-names = "xclk"; - - port { - csi2_cam0: endpoint { - remote-endpoint = <&csi2_phy0>; - clock-lanes = <0>; - data-lanes = <1 2>; - }; - }; - }; - }; diff --git a/MAINTAINERS b/MAINTAINERS index bd5847e802de..eefa1e066655 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16555,6 +16555,7 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ S: Maintained F: drivers/media/platform/ti-vpe/ F: Documentation/devicetree/bindings/media/ti,vpe.yaml + Documentation/devicetree/bindings/media/ti,cal.yaml TI WILINK WIRELESS DRIVERS L: linux-wireless@vger.kernel.org -- cgit v1.2.3 From 6cfeb611b4714b4cc66df7ef36111e33ed551f22 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 20 Nov 2019 19:18:57 +0100 Subject: dt-bindings: arm: Document compatibles for Ux500 boards The device-specific compatible values used by the Ux500 boards were not documented so far. Add a new simple schema to document them. Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20191120181857.97174-4-stephan@gerhold.net Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/arm/ux500.yaml | 31 ++++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/ux500.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/ux500.yaml b/Documentation/devicetree/bindings/arm/ux500.yaml new file mode 100644 index 000000000000..006cb4a5f331 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/ux500.yaml @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/ux500.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ux500 platforms device tree bindings + +maintainers: + - Linus Walleij + +properties: + $nodename: + const: '/' + compatible: + oneOf: + + - description: ST-Ericsson HREF (pre-v60) + items: + - const: st-ericsson,mop500 + - const: st-ericsson,u8500 + + - description: ST-Ericsson HREF (v60+) + items: + - const: st-ericsson,hrefv60+ + - const: st-ericsson,u8500 + + - description: Calao Systems Snowball + items: + - const: calaosystems,snowball-a9500 + - const: st-ericsson,u9500 diff --git a/MAINTAINERS b/MAINTAINERS index bd5847e802de..e6db3889cb19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2058,6 +2058,7 @@ F: drivers/rtc/rtc-pl031.c F: drivers/watchdog/coh901327_wdt.c F: Documentation/devicetree/bindings/arm/ste-* F: Documentation/devicetree/bindings/arm/ux500/ +F: Documentation/devicetree/bindings/arm/ux500.yaml T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git ARM/NUVOTON NPCM ARCHITECTURE -- cgit v1.2.3 From e54ea45a4955e8a2901c74ab43870f2a56ed647b Mon Sep 17 00:00:00 2001 From: Dilip Kota Date: Mon, 9 Dec 2019 11:20:04 +0800 Subject: dt-bindings: PCI: intel: Add YAML schemas for the PCIe RC controller Add YAML schemas for PCIe RC controller on Intel Gateway SoCs which is Synopsys DesignWare based PCIe core. Signed-off-by: Dilip Kota Signed-off-by: Lorenzo Pieralisi Reviewed-by: Andrew Murray Reviewed-by: Rob Herring --- .../devicetree/bindings/pci/intel-gw-pcie.yaml | 138 +++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml b/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml new file mode 100644 index 000000000000..db605d8a387d --- /dev/null +++ b/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml @@ -0,0 +1,138 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pci/intel-gw-pcie.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: PCIe RC controller on Intel Gateway SoCs + +maintainers: + - Dilip Kota + +properties: + compatible: + items: + - const: intel,lgm-pcie + - const: snps,dw-pcie + + device_type: + const: pci + + "#address-cells": + const: 3 + + "#size-cells": + const: 2 + + reg: + items: + - description: Controller control and status registers. + - description: PCIe configuration registers. + - description: Controller application registers. + + reg-names: + items: + - const: dbi + - const: config + - const: app + + ranges: + maxItems: 1 + + resets: + maxItems: 1 + + clocks: + maxItems: 1 + + phys: + maxItems: 1 + + phy-names: + const: pcie + + reset-gpios: + maxItems: 1 + + linux,pci-domain: true + + num-lanes: + maximum: 2 + description: Number of lanes to use for this port. + + '#interrupt-cells': + const: 1 + + interrupt-map-mask: + description: Standard PCI IRQ mapping properties. + + interrupt-map: + description: Standard PCI IRQ mapping properties. + + max-link-speed: + description: Specify PCI Gen for link capability. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [ 1, 2, 3, 4 ] + - default: 1 + + bus-range: + description: Range of bus numbers associated with this controller. + + reset-assert-ms: + description: | + Delay after asserting reset to the PCIe device. + maximum: 500 + default: 100 + +required: + - compatible + - device_type + - "#address-cells" + - "#size-cells" + - reg + - reg-names + - ranges + - resets + - clocks + - phys + - phy-names + - reset-gpios + - '#interrupt-cells' + - interrupt-map + - interrupt-map-mask + +additionalProperties: false + +examples: + - | + #include + #include + pcie10: pcie@d0e00000 { + compatible = "intel,lgm-pcie", "snps,dw-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + reg = <0xd0e00000 0x1000>, + <0xd2000000 0x800000>, + <0xd0a41000 0x1000>; + reg-names = "dbi", "config", "app"; + linux,pci-domain = <0>; + max-link-speed = <4>; + bus-range = <0x00 0x08>; + interrupt-parent = <&ioapic1>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &ioapic1 27 1>, + <0 0 0 2 &ioapic1 28 1>, + <0 0 0 3 &ioapic1 29 1>, + <0 0 0 4 &ioapic1 30 1>; + ranges = <0x02000000 0 0xd4000000 0xd4000000 0 0x04000000>; + resets = <&rcu0 0x50 0>; + clocks = <&cgu0 LGM_GCLK_PCIE10>; + phys = <&cb0phy0>; + phy-names = "pcie"; + reset-assert-ms = <500>; + reset-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + num-lanes = <2>; + }; -- cgit v1.2.3 From 681700c38f3e989a3da940d0120b0268c25c54d8 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 22 Nov 2019 11:45:35 +0100 Subject: dt-bindings: regulator: Convert stm32 booster bindings to json-schema Convert the STM32 regulator booster binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard CC: Fabrice Gasnier Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191122104536.20283-1-benjamin.gaignard@st.com Signed-off-by: Mark Brown --- .../bindings/regulator/st,stm32-booster.txt | 18 --------- .../bindings/regulator/st,stm32-booster.yaml | 46 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 18 deletions(-) delete mode 100644 Documentation/devicetree/bindings/regulator/st,stm32-booster.txt create mode 100644 Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-booster.txt b/Documentation/devicetree/bindings/regulator/st,stm32-booster.txt deleted file mode 100644 index 479ad4c8758e..000000000000 --- a/Documentation/devicetree/bindings/regulator/st,stm32-booster.txt +++ /dev/null @@ -1,18 +0,0 @@ -STM32 BOOSTER - Booster for ADC analog input switches - -Some STM32 devices embed a 3.3V booster supplied by Vdda, that can be used -to supply ADC analog input switches. - -Required properties: -- compatible: Should be one of: - "st,stm32h7-booster" - "st,stm32mp1-booster" -- st,syscfg: Phandle to system configuration controller. -- vdda-supply: Phandle to the vdda input analog voltage. - -Example: - booster: regulator-booster { - compatible = "st,stm32mp1-booster"; - st,syscfg = <&syscfg>; - vdda-supply = <&vdda>; - }; diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml b/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml new file mode 100644 index 000000000000..64f1183ce841 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/st,stm32-booster.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 booster for ADC analog input switches bindings + +maintainers: + - Fabrice Gasnier + +description: | + Some STM32 devices embed a 3.3V booster supplied by Vdda, that can be used + to supply ADC analog input switches. + +allOf: + - $ref: "regulator.yaml#" + +properties: + compatible: + enum: + - st,stm32h7-booster + - st,stm32mp1-booster + + st,syscfg: + allOf: + - $ref: "/schemas/types.yaml#/definitions/phandle-array" + description: phandle to system configuration controller. + + vdda-supply: + description: phandle to the vdda input analog voltage. + +required: + - compatible + - st,syscfg + - vdda-supply + +examples: + - | + regulator-booster { + compatible = "st,stm32mp1-booster"; + st,syscfg = <&syscfg>; + vdda-supply = <&vdda>; + }; + +... -- cgit v1.2.3 From 21b2c47161449c44e5a70eab646260aaeceb331c Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Fri, 22 Nov 2019 11:45:36 +0100 Subject: dt-bindings: regulator: Convert stm32 vrefbuf bindings to json-schema Convert the STM32 regulator vrefbuf binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard CC: Fabrice Gasnier Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191122104536.20283-2-benjamin.gaignard@st.com Signed-off-by: Mark Brown --- .../bindings/regulator/st,stm32-vrefbuf.txt | 20 --------- .../bindings/regulator/st,stm32-vrefbuf.yaml | 52 ++++++++++++++++++++++ 2 files changed, 52 insertions(+), 20 deletions(-) delete mode 100644 Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txt create mode 100644 Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txt b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txt deleted file mode 100644 index 5ddb8500a929..000000000000 --- a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.txt +++ /dev/null @@ -1,20 +0,0 @@ -STM32 VREFBUF - Voltage reference buffer - -Some STM32 devices embed a voltage reference buffer which can be used as -voltage reference for ADCs, DACs and also as voltage reference for external -components through the dedicated VREF+ pin. - -Required properties: -- compatible: Must be "st,stm32-vrefbuf". -- reg: Offset and length of VREFBUF register set. -- clocks: Must contain an entry for peripheral clock. - -Example: - vrefbuf: regulator@58003c00 { - compatible = "st,stm32-vrefbuf"; - reg = <0x58003C00 0x8>; - clocks = <&rcc VREF_CK>; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <2500000>; - vdda-supply = <&vdda>; - }; diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml new file mode 100644 index 000000000000..33cdaeb25aee --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/st,stm32-vrefbuf.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Voltage reference buffer bindings + +description: | + Some STM32 devices embed a voltage reference buffer which can be used as + voltage reference for ADCs, DACs and also as voltage reference for external + components through the dedicated VREF+ pin. + +maintainers: + - Fabrice Gasnier + +allOf: + - $ref: "regulator.yaml#" + +properties: + compatible: + const: st,stm32-vrefbuf + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + vdda-supply: + description: phandle to the vdda input analog voltage. + +required: + - compatible + - reg + - clocks + - vdda-supply + +examples: + - | + #include + vrefbuf@50025000 { + compatible = "st,stm32-vrefbuf"; + reg = <0x50025000 0x8>; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2500000>; + clocks = <&rcc VREF>; + vdda-supply = <&vdda>; + }; + +... + -- cgit v1.2.3 From c963e34f5ac6fab4913e3806e97bfdf089cb4cc6 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Tue, 12 Nov 2019 07:19:54 +0000 Subject: dt-bindings: ARM: at91: Document SAMA5D27 WLSOM1 and Evaluation Kit Document device tree binding of SAMA5D27 WLSOM1 - Wireless module; and SAMA5D27 WLSOM1 EK - Wireless module evaluation kit, from Microchip. Signed-off-by: Eugen Hristev Link: https://lore.kernel.org/r/1573543139-8533-3-git-send-email-eugen.hristev@microchip.com Reviewed-by: Rob Herring Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/arm/atmel-at91.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.yaml b/Documentation/devicetree/bindings/arm/atmel-at91.yaml index 6dd8be401673..7b512be280ce 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.yaml +++ b/Documentation/devicetree/bindings/arm/atmel-at91.yaml @@ -52,6 +52,21 @@ properties: - const: atmel,sama5d2 - const: atmel,sama5 + - description: Microchip SAMA5D27 WLSOM1 + items: + - const: microchip,sama5d27-wlsom1 + - const: atmel,sama5d27 + - const: atmel,sama5d2 + - const: atmel,sama5 + + - description: Microchip SAMA5D27 WLSOM1 Evaluation Kit + items: + - const: microchip,sama5d27-wlsom1-ek + - const: microchip,sama5d27-wlsom1 + - const: atmel,sama5d27 + - const: atmel,sama5d2 + - const: atmel,sama5 + - items: - const: atmel,sama5d27 - const: atmel,sama5d2 -- cgit v1.2.3 From 3c9abe886a95d91b3d1e1cc16af4322a1abe31d5 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Thu, 5 Dec 2019 14:02:42 -0800 Subject: drm/i915/guc: kill the GuC client We now only use 1 client without any plan to add more. The client is also only holding information about the WQ and the process desc, so we can just move those in the intel_guc structure and always use stage_id 0. v2: fix comment (John) v3: fix the comment for real, fix kerneldoc Signed-off-by: Daniele Ceraolo Spurio Cc: Michal Wajdeczko Cc: John Harrison Cc: Matthew Brost Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20191205220243.27403-4-daniele.ceraolospurio@intel.com --- Documentation/gpu/i915.rst | 3 - drivers/gpu/drm/i915/gt/intel_reset.c | 6 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 8 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 1 - drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 276 ++++++---------------- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h | 45 +--- drivers/gpu/drm/i915/i915_debugfs.c | 11 - 7 files changed, 89 insertions(+), 261 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index d0947c5c4ab8..e539c42a3e78 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -466,9 +466,6 @@ GuC-based command submission .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c :doc: GuC-based command submission -.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c - :internal: - HuC --- .. kernel-doc:: drivers/gpu/drm/i915/gt/uc/intel_huc.c diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 0e94b720c993..8408cb84e52c 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -21,6 +21,7 @@ #include "intel_reset.h" #include "uc/intel_guc.h" +#include "uc/intel_guc_submission.h" #define RESET_MAX_RETRIES 3 @@ -1085,6 +1086,7 @@ static inline int intel_gt_reset_engine(struct intel_engine_cs *engine) int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) { struct intel_gt *gt = engine->gt; + bool uses_guc = intel_engine_in_guc_submission_mode(engine); int ret; GEM_TRACE("%s flags=%lx\n", engine->name, gt->reset.flags); @@ -1100,14 +1102,14 @@ int intel_engine_reset(struct intel_engine_cs *engine, const char *msg) "Resetting %s for %s\n", engine->name, msg); atomic_inc(&engine->i915->gpu_error.reset_engine_count[engine->uabi_class]); - if (!engine->gt->uc.guc.execbuf_client) + if (!uses_guc) ret = intel_gt_reset_engine(engine); else ret = intel_guc_reset_engine(&engine->gt->uc.guc, engine); if (ret) { /* If we fail here, we expect to fallback to a global reset */ DRM_DEBUG_DRIVER("%sFailed to reset %s, ret=%d\n", - engine->gt->uc.guc.execbuf_client ? "GuC " : "", + uses_guc ? "GuC " : "", engine->name, ret); goto out; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index b2d1766e689a..cd09c912e361 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -46,9 +46,13 @@ struct intel_guc { struct i915_vma *stage_desc_pool; void *stage_desc_pool_vaddr; - struct ida stage_ids; - struct intel_guc_client *execbuf_client; + struct i915_vma *workqueue; + void *workqueue_vaddr; + spinlock_t wq_lock; + + struct i915_vma *proc_desc; + void *proc_desc_vaddr; /* Control params for fw initialization */ u32 params[GUC_CTL_MAX_DWORDS]; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 1e8e4af7d9ca..a6b733c146c9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -31,7 +31,6 @@ #define GUC_DOORBELL_INVALID 256 -#define GUC_PD_SIZE (PAGE_SIZE) #define GUC_WQ_SIZE (PAGE_SIZE * 2) /* Work queue item header definitions */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 334bd4ded642..172220e83079 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -27,24 +27,13 @@ * code) matches the old submission model and will be updated as part of the * upgrade to the new flow. * - * GuC client: - * A intel_guc_client refers to a submission path through GuC. Currently, there - * is only one client, which is charged with all submissions to the GuC. This - * struct is the owner of a process descriptor and a workqueue (both of them - * inside a single gem object that contains all required pages for these - * elements). - * * GuC stage descriptor: * During initialization, the driver allocates a static pool of 1024 such - * descriptors, and shares them with the GuC. - * Currently, there exists a 1:1 mapping between a intel_guc_client and a - * guc_stage_desc (via the client's stage_id), so effectively only one - * gets used. This stage descriptor lets the GuC know about the workqueue and + * descriptors, and shares them with the GuC. Currently, we only use one + * descriptor. This stage descriptor lets the GuC know about the workqueue and * process descriptor. Theoretically, it also lets the GuC know about our HW * contexts (context ID, etc...), but we actually employ a kind of submission - * where the GuC uses the LRCA sent via the work item instead (the single - * guc_stage_desc associated to execbuf client contains information about the - * default kernel context only, but this is essentially unused). This is called + * where the GuC uses the LRCA sent via the work item instead. This is called * a "proxy" submission. * * The Scratch registers: @@ -71,33 +60,45 @@ static inline struct i915_priolist *to_priolist(struct rb_node *rb) return rb_entry(rb, struct i915_priolist, node); } -static inline bool is_high_priority(struct intel_guc_client *client) +static struct guc_stage_desc *__get_stage_desc(struct intel_guc *guc, u32 id) { - return (client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH || - client->priority == GUC_CLIENT_PRIORITY_HIGH); + struct guc_stage_desc *base = guc->stage_desc_pool_vaddr; + + return &base[id]; } -static struct guc_stage_desc *__get_stage_desc(struct intel_guc_client *client) +static int guc_workqueue_create(struct intel_guc *guc) { - struct guc_stage_desc *base = client->guc->stage_desc_pool_vaddr; - - return &base[client->stage_id]; + return intel_guc_allocate_and_map_vma(guc, GUC_WQ_SIZE, &guc->workqueue, + &guc->workqueue_vaddr); } -static inline struct guc_process_desc * -__get_process_desc(struct intel_guc_client *client) +static void guc_workqueue_destroy(struct intel_guc *guc) { - return client->vaddr; + i915_vma_unpin_and_release(&guc->workqueue, I915_VMA_RELEASE_MAP); } /* * Initialise the process descriptor shared with the GuC firmware. */ -static void guc_proc_desc_init(struct intel_guc_client *client) +static int guc_proc_desc_create(struct intel_guc *guc) +{ + const u32 size = PAGE_ALIGN(sizeof(struct guc_process_desc)); + + return intel_guc_allocate_and_map_vma(guc, size, &guc->proc_desc, + &guc->proc_desc_vaddr); +} + +static void guc_proc_desc_destroy(struct intel_guc *guc) +{ + i915_vma_unpin_and_release(&guc->proc_desc, I915_VMA_RELEASE_MAP); +} + +static void guc_proc_desc_init(struct intel_guc *guc) { struct guc_process_desc *desc; - desc = memset(__get_process_desc(client), 0, sizeof(*desc)); + desc = memset(guc->proc_desc_vaddr, 0, sizeof(*desc)); /* * XXX: pDoorbell and WQVBaseAddress are pointers in process address @@ -108,39 +109,27 @@ static void guc_proc_desc_init(struct intel_guc_client *client) desc->wq_base_addr = 0; desc->db_base_addr = 0; - desc->stage_id = client->stage_id; desc->wq_size_bytes = GUC_WQ_SIZE; desc->wq_status = WQ_STATUS_ACTIVE; - desc->priority = client->priority; + desc->priority = GUC_CLIENT_PRIORITY_KMD_NORMAL; } -static void guc_proc_desc_fini(struct intel_guc_client *client) +static void guc_proc_desc_fini(struct intel_guc *guc) { - struct guc_process_desc *desc; - - desc = __get_process_desc(client); - memset(desc, 0, sizeof(*desc)); + memset(guc->proc_desc_vaddr, 0, sizeof(struct guc_process_desc)); } static int guc_stage_desc_pool_create(struct intel_guc *guc) { u32 size = PAGE_ALIGN(sizeof(struct guc_stage_desc) * GUC_MAX_STAGE_DESCRIPTORS); - int ret; - - ret = intel_guc_allocate_and_map_vma(guc, size, &guc->stage_desc_pool, - &guc->stage_desc_pool_vaddr); - if (ret) - return ret; - - ida_init(&guc->stage_ids); - return 0; + return intel_guc_allocate_and_map_vma(guc, size, &guc->stage_desc_pool, + &guc->stage_desc_pool_vaddr); } static void guc_stage_desc_pool_destroy(struct intel_guc *guc) { - ida_destroy(&guc->stage_ids); i915_vma_unpin_and_release(&guc->stage_desc_pool, I915_VMA_RELEASE_MAP); } @@ -148,58 +137,49 @@ static void guc_stage_desc_pool_destroy(struct intel_guc *guc) * Initialise/clear the stage descriptor shared with the GuC firmware. * * This descriptor tells the GuC where (in GGTT space) to find the important - * data structures relating to this client (process descriptor, write queue, + * data structures related to work submission (process descriptor, write queue, * etc). */ -static void guc_stage_desc_init(struct intel_guc_client *client) +static void guc_stage_desc_init(struct intel_guc *guc) { - struct intel_guc *guc = client->guc; struct guc_stage_desc *desc; - u32 gfx_addr; - desc = __get_stage_desc(client); + /* we only use 1 stage desc, so hardcode it to 0 */ + desc = __get_stage_desc(guc, 0); memset(desc, 0, sizeof(*desc)); desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL; - if (is_high_priority(client)) - desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT; - desc->stage_id = client->stage_id; - desc->priority = client->priority; - /* - * The process descriptor and workqueue are all parts of the client - * object, which the GuC will reference via the GGTT - */ - gfx_addr = intel_guc_ggtt_offset(guc, client->vma); - desc->process_desc = gfx_addr; - desc->wq_addr = gfx_addr + GUC_PD_SIZE; - desc->wq_size = GUC_WQ_SIZE; + desc->stage_id = 0; + desc->priority = GUC_CLIENT_PRIORITY_KMD_NORMAL; - desc->desc_private = ptr_to_u64(client); + desc->process_desc = intel_guc_ggtt_offset(guc, guc->proc_desc); + desc->wq_addr = intel_guc_ggtt_offset(guc, guc->workqueue); + desc->wq_size = GUC_WQ_SIZE; } -static void guc_stage_desc_fini(struct intel_guc_client *client) +static void guc_stage_desc_fini(struct intel_guc *guc) { struct guc_stage_desc *desc; - desc = __get_stage_desc(client); + desc = __get_stage_desc(guc, 0); memset(desc, 0, sizeof(*desc)); } /* Construct a Work Item and append it to the GuC's Work Queue */ -static void guc_wq_item_append(struct intel_guc_client *client, +static void guc_wq_item_append(struct intel_guc *guc, u32 target_engine, u32 context_desc, u32 ring_tail, u32 fence_id) { /* wqi_len is in DWords, and does not include the one-word header */ const size_t wqi_size = sizeof(struct guc_wq_item); const u32 wqi_len = wqi_size / sizeof(u32) - 1; - struct guc_process_desc *desc = __get_process_desc(client); + struct guc_process_desc *desc = guc->proc_desc_vaddr; struct guc_wq_item *wqi; u32 wq_off; - lockdep_assert_held(&client->wq_lock); + lockdep_assert_held(&guc->wq_lock); /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we * should not have the case where structure wqi is across page, neither @@ -219,8 +199,7 @@ static void guc_wq_item_append(struct intel_guc_client *client, GUC_WQ_SIZE) < wqi_size); GEM_BUG_ON(wq_off & (wqi_size - 1)); - /* WQ starts from the page after process_desc */ - wqi = client->vaddr + wq_off + GUC_PD_SIZE; + wqi = guc->workqueue_vaddr + wq_off; /* Now fill in the 4-word work queue item */ wqi->header = WQ_TYPE_INORDER | @@ -238,12 +217,11 @@ static void guc_wq_item_append(struct intel_guc_client *client, static void guc_add_request(struct intel_guc *guc, struct i915_request *rq) { - struct intel_guc_client *client = guc->execbuf_client; struct intel_engine_cs *engine = rq->engine; u32 ctx_desc = lower_32_bits(rq->hw_context->lrc_desc); u32 ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); - guc_wq_item_append(client, engine->guc_id, ctx_desc, + guc_wq_item_append(guc, engine->guc_id, ctx_desc, ring_tail, rq->fence.seqno); } @@ -266,9 +244,8 @@ static void guc_submit(struct intel_engine_cs *engine, struct i915_request **end) { struct intel_guc *guc = &engine->gt->uc.guc; - struct intel_guc_client *client = guc->execbuf_client; - spin_lock(&client->wq_lock); + spin_lock(&guc->wq_lock); do { struct i915_request *rq = *out++; @@ -277,7 +254,7 @@ static void guc_submit(struct intel_engine_cs *engine, guc_add_request(guc, rq); } while (out != end); - spin_unlock(&client->wq_lock); + spin_unlock(&guc->wq_lock); } static inline int rq_prio(const struct i915_request *rq) @@ -528,126 +505,6 @@ static void guc_reset_finish(struct intel_engine_cs *engine) * path of guc_submit() above. */ -/** - * guc_client_alloc() - Allocate an intel_guc_client - * @guc: the intel_guc structure - * @priority: four levels priority _CRITICAL, _HIGH, _NORMAL and _LOW - * The kernel client to replace ExecList submission is created with - * NORMAL priority. Priority of a client for scheduler can be HIGH, - * while a preemption context can use CRITICAL. - * - * Return: An intel_guc_client object if success, else NULL. - */ -static struct intel_guc_client * -guc_client_alloc(struct intel_guc *guc, u32 priority) -{ - struct intel_guc_client *client; - struct i915_vma *vma; - void *vaddr; - int ret; - - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) - return ERR_PTR(-ENOMEM); - - client->guc = guc; - client->priority = priority; - spin_lock_init(&client->wq_lock); - - ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, - GFP_KERNEL); - if (ret < 0) - goto err_client; - - client->stage_id = ret; - - /* The first page is proc_desc. Two following pages are wq. */ - vma = intel_guc_allocate_vma(guc, GUC_PD_SIZE + GUC_WQ_SIZE); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto err_id; - } - - /* We'll keep just the first (doorbell/proc) page permanently kmap'd. */ - client->vma = vma; - - vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - goto err_vma; - } - client->vaddr = vaddr; - - DRM_DEBUG_DRIVER("new priority %u client %p: stage_id %u\n", - priority, client, client->stage_id); - - return client; - -err_vma: - i915_vma_unpin_and_release(&client->vma, 0); -err_id: - ida_simple_remove(&guc->stage_ids, client->stage_id); -err_client: - kfree(client); - return ERR_PTR(ret); -} - -static void guc_client_free(struct intel_guc_client *client) -{ - i915_vma_unpin_and_release(&client->vma, I915_VMA_RELEASE_MAP); - ida_simple_remove(&client->guc->stage_ids, client->stage_id); - kfree(client); -} - -static int guc_clients_create(struct intel_guc *guc) -{ - struct intel_guc_client *client; - - GEM_BUG_ON(guc->execbuf_client); - - client = guc_client_alloc(guc, GUC_CLIENT_PRIORITY_KMD_NORMAL); - if (IS_ERR(client)) { - DRM_ERROR("Failed to create GuC client for submission!\n"); - return PTR_ERR(client); - } - guc->execbuf_client = client; - - return 0; -} - -static void guc_clients_destroy(struct intel_guc *guc) -{ - struct intel_guc_client *client; - - client = fetch_and_zero(&guc->execbuf_client); - if (client) - guc_client_free(client); -} - -static void __guc_client_enable(struct intel_guc_client *client) -{ - guc_proc_desc_init(client); - guc_stage_desc_init(client); -} - -static void __guc_client_disable(struct intel_guc_client *client) -{ - /* Note: By the time we're here, GuC may have already been reset */ - guc_stage_desc_fini(client); - guc_proc_desc_fini(client); -} - -static void guc_clients_enable(struct intel_guc *guc) -{ - __guc_client_enable(guc->execbuf_client); -} - -static void guc_clients_disable(struct intel_guc *guc) -{ - if (guc->execbuf_client) - __guc_client_disable(guc->execbuf_client); -} - /* * Set up the memory resources to be shared with the GuC (via the GGTT) * at firmware loading time. @@ -668,12 +525,20 @@ int intel_guc_submission_init(struct intel_guc *guc) */ GEM_BUG_ON(!guc->stage_desc_pool); - ret = guc_clients_create(guc); + ret = guc_workqueue_create(guc); if (ret) goto err_pool; + ret = guc_proc_desc_create(guc); + if (ret) + goto err_workqueue; + + spin_lock_init(&guc->wq_lock); + return 0; +err_workqueue: + guc_workqueue_destroy(guc); err_pool: guc_stage_desc_pool_destroy(guc); return ret; @@ -681,10 +546,11 @@ err_pool: void intel_guc_submission_fini(struct intel_guc *guc) { - guc_clients_destroy(guc); - - if (guc->stage_desc_pool) + if (guc->stage_desc_pool) { + guc_proc_desc_destroy(guc); + guc_workqueue_destroy(guc); guc_stage_desc_pool_destroy(guc); + } } static void guc_interrupts_capture(struct intel_gt *gt) @@ -770,9 +636,8 @@ void intel_guc_submission_enable(struct intel_guc *guc) sizeof(struct guc_wq_item) * I915_NUM_ENGINES > GUC_WQ_SIZE); - GEM_BUG_ON(!guc->execbuf_client); - - guc_clients_enable(guc); + guc_proc_desc_init(guc); + guc_stage_desc_init(guc); /* Take over from manual control of ELSP (execlists) */ guc_interrupts_capture(gt); @@ -789,8 +654,12 @@ void intel_guc_submission_disable(struct intel_guc *guc) GEM_BUG_ON(gt->awake); /* GT should be parked first */ + /* Note: By the time we're here, GuC may have already been reset */ + guc_interrupts_release(gt); - guc_clients_disable(guc); + + guc_stage_desc_fini(guc); + guc_proc_desc_fini(guc); } static bool __guc_submission_support(struct intel_guc *guc) @@ -808,3 +677,8 @@ void intel_guc_submission_init_early(struct intel_guc *guc) { guc->submission_supported = __guc_submission_support(guc); } + +bool intel_engine_in_guc_submission_mode(const struct intel_engine_cs *engine) +{ + return engine->set_default_submission == guc_set_default_submission; +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h index e2deb4e6f42a..e402a2932592 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.h @@ -6,48 +6,10 @@ #ifndef _INTEL_GUC_SUBMISSION_H_ #define _INTEL_GUC_SUBMISSION_H_ -#include +#include -#include "gt/intel_engine_types.h" - -#include "i915_gem.h" -#include "i915_selftest.h" - -struct drm_i915_private; - -/* - * This structure primarily describes the GEM object shared with the GuC. - * The specs sometimes refer to this object as a "GuC context", but we use - * the term "client" to avoid confusion with hardware contexts. This - * GEM object is held for the entire lifetime of our interaction with - * the GuC, being allocated before the GuC is loaded with its firmware. - * Because there's no way to update the address used by the GuC after - * initialisation, the shared object must stay pinned into the GGTT as - * long as the GuC is in use. We also keep the first page (only) mapped - * into kernel address space, as it includes shared data that must be - * updated on every request submission. - * - * The single GEM object described here is actually made up of several - * separate areas, as far as the GuC is concerned. The first page (kept - * kmap'd) includes the "process descriptor" which holds sequence data for - * the doorbell, and one cacheline which actually *is* the doorbell; a - * write to this will "ring the doorbell" (i.e. send an interrupt to the - * GuC). The subsequent pages of the client object constitute the work - * queue (a circular array of work items), again described in the process - * descriptor. Work queue pages are mapped momentarily as required. - */ -struct intel_guc_client { - struct i915_vma *vma; - void *vaddr; - struct intel_guc *guc; - - /* bitmap of (host) engine ids */ - u32 priority; - u32 stage_id; - - /* Protects GuC client's WQ access */ - spinlock_t wq_lock; -}; +struct intel_guc; +struct intel_engine_cs; void intel_guc_submission_init_early(struct intel_guc *guc); int intel_guc_submission_init(struct intel_guc *guc); @@ -56,5 +18,6 @@ void intel_guc_submission_disable(struct intel_guc *guc); void intel_guc_submission_fini(struct intel_guc *guc); int intel_guc_preempt_work_create(struct intel_guc *guc); void intel_guc_preempt_work_destroy(struct intel_guc *guc); +bool intel_engine_in_guc_submission_mode(const struct intel_engine_cs *engine); #endif diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 3e563384e84d..6cb149ba1905 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1792,23 +1792,12 @@ static void i915_guc_log_info(struct seq_file *m, static int i915_guc_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - const struct intel_guc *guc = &dev_priv->gt.uc.guc; - struct intel_guc_client *client = guc->execbuf_client; if (!USES_GUC(dev_priv)) return -ENODEV; i915_guc_log_info(m, dev_priv); - if (!USES_GUC_SUBMISSION(dev_priv)) - return 0; - - GEM_BUG_ON(!guc->execbuf_client); - - seq_printf(m, "\nGuC execbuf client @ %p:\n", client); - seq_printf(m, "\tPriority %d, GuC stage index: %u\n", - client->priority, - client->stage_id); /* Add more as required ... */ return 0; -- cgit v1.2.3 From 56f11874451856edb740b32d4a748db4f92551fd Mon Sep 17 00:00:00 2001 From: Mohammad Rasim Date: Sat, 30 Nov 2019 22:53:33 +0300 Subject: dt-bindings: Add vendor prefix for Videostrong Videostrong Technology Co., Ltd., A manufacturer of Android Players & STB (Android with DVB Hybrid box & DVB-T2/S2/C/ISDB-T/DTMB-TH/ATSC) as well as HD media players. Acked-by: Martin Blumenstingl Signed-off-by: Mohammad Rasim Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6046f4555852..5c0577625ba9 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1012,6 +1012,8 @@ patternProperties: description: Variscite Ltd. "^via,.*": description: VIA Technologies, Inc. + "^videostrong,.*": + description: Videostrong Technology Co., Ltd. "^virtio,.*": description: Virtual I/O Device Specification, developed by the OASIS consortium "^vishay,.*": -- cgit v1.2.3 From 206e4d6f4ccd4563c825c73c7c55321b0807f20a Mon Sep 17 00:00:00 2001 From: Mohammad Rasim Date: Sat, 30 Nov 2019 22:53:34 +0300 Subject: dt-bindings: arm: amlogic: add Videostrong KII Pro bindings Add the compatible for the Amlogic gxbb(s905) based kii pro Signed-off-by: Mohammad Rasim Reviewed-by: Martin Blumenstingl Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/arm/amlogic.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index c6a443352ef8..8e693c6e0cc4 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -59,6 +59,7 @@ properties: - friendlyarm,nanopi-k2 - hardkernel,odroid-c2 - nexbox,a95x + - videostrong,kii-pro - wetek,hub - wetek,play2 - const: amlogic,meson-gxbb -- cgit v1.2.3 From 65e6d90168f3593df0ae598502bcbf20d78ff0fb Mon Sep 17 00:00:00 2001 From: "Kevin(Yudong) Yang" Date: Mon, 9 Dec 2019 14:19:59 -0500 Subject: net-tcp: Disable TCP ssthresh metrics cache by default This patch introduces a sysctl knob "net.ipv4.tcp_no_ssthresh_metrics_save" that disables TCP ssthresh metrics cache by default. Other parts of TCP metrics cache, e.g. rtt, cwnd, remain unchanged. As modern networks becoming more and more dynamic, TCP metrics cache today often causes more harm than benefits. For example, the same IP address is often shared by different subscribers behind NAT in residential networks. Even if the IP address is not shared by different users, caching the slow-start threshold of a previous short flow using loss-based congestion control (e.g. cubic) often causes the future longer flows of the same network path to exit slow-start prematurely with abysmal throughput. Caching ssthresh is very risky and can lead to terrible performance. Therefore it makes sense to make disabling ssthresh caching by default and opt-in for specific networks by the administrators. This practice also has worked well for several years of deployment with CUBIC congestion control at Google. Acked-by: Eric Dumazet Acked-by: Neal Cardwell Acked-by: Yuchung Cheng Signed-off-by: Kevin(Yudong) Yang Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 4 ++++ include/net/netns/ipv4.h | 1 + net/ipv4/sysctl_net_ipv4.c | 9 +++++++++ net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_metrics.c | 13 +++++++++---- 5 files changed, 24 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index fd26788e8c96..90b8f14bc41a 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -479,6 +479,10 @@ tcp_no_metrics_save - BOOLEAN degradation. If set, TCP will not cache metrics on closing connections. +tcp_no_ssthresh_metrics_save - BOOLEAN + Controls whether TCP saves ssthresh metrics in the route cache. + Default is 1, which disables ssthresh metrics. + tcp_orphan_retries - INTEGER This value influences the timeout of a locally closed TCP connection, when RTO retransmissions remain unacknowledged. diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index c0c0791b1912..08b98414d94e 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -154,6 +154,7 @@ struct netns_ipv4 { int sysctl_tcp_adv_win_scale; int sysctl_tcp_frto; int sysctl_tcp_nometrics_save; + int sysctl_tcp_no_ssthresh_metrics_save; int sysctl_tcp_moderate_rcvbuf; int sysctl_tcp_tso_win_divisor; int sysctl_tcp_workaround_signed_windows; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index fcb2cd167f64..9684af02e0a5 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -1192,6 +1192,15 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, + { + .procname = "tcp_no_ssthresh_metrics_save", + .data = &init_net.ipv4.sysctl_tcp_no_ssthresh_metrics_save, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, { .procname = "tcp_moderate_rcvbuf", .data = &init_net.ipv4.sysctl_tcp_moderate_rcvbuf, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 92282f98dc82..26637fce324d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2674,6 +2674,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT; net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX; net->ipv4.sysctl_tcp_tw_reuse = 2; + net->ipv4.sysctl_tcp_no_ssthresh_metrics_save = 1; cnt = tcp_hashinfo.ehash_mask + 1; net->ipv4.tcp_death_row.sysctl_max_tw_buckets = cnt / 2; diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index c4848e7a0aad..279db8822439 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -385,7 +385,8 @@ void tcp_update_metrics(struct sock *sk) if (tcp_in_initial_slowstart(tp)) { /* Slow start still did not finish. */ - if (!tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) { + if (!net->ipv4.sysctl_tcp_no_ssthresh_metrics_save && + !tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) { val = tcp_metric_get(tm, TCP_METRIC_SSTHRESH); if (val && (tp->snd_cwnd >> 1) > val) tcp_metric_set(tm, TCP_METRIC_SSTHRESH, @@ -400,7 +401,8 @@ void tcp_update_metrics(struct sock *sk) } else if (!tcp_in_slow_start(tp) && icsk->icsk_ca_state == TCP_CA_Open) { /* Cong. avoidance phase, cwnd is reliable. */ - if (!tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) + if (!net->ipv4.sysctl_tcp_no_ssthresh_metrics_save && + !tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) tcp_metric_set(tm, TCP_METRIC_SSTHRESH, max(tp->snd_cwnd >> 1, tp->snd_ssthresh)); if (!tcp_metric_locked(tm, TCP_METRIC_CWND)) { @@ -416,7 +418,8 @@ void tcp_update_metrics(struct sock *sk) tcp_metric_set(tm, TCP_METRIC_CWND, (val + tp->snd_ssthresh) >> 1); } - if (!tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) { + if (!net->ipv4.sysctl_tcp_no_ssthresh_metrics_save && + !tcp_metric_locked(tm, TCP_METRIC_SSTHRESH)) { val = tcp_metric_get(tm, TCP_METRIC_SSTHRESH); if (val && tp->snd_ssthresh > val) tcp_metric_set(tm, TCP_METRIC_SSTHRESH, @@ -441,6 +444,7 @@ void tcp_init_metrics(struct sock *sk) { struct dst_entry *dst = __sk_dst_get(sk); struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); struct tcp_metrics_block *tm; u32 val, crtt = 0; /* cached RTT scaled by 8 */ @@ -458,7 +462,8 @@ void tcp_init_metrics(struct sock *sk) if (tcp_metric_locked(tm, TCP_METRIC_CWND)) tp->snd_cwnd_clamp = tcp_metric_get(tm, TCP_METRIC_CWND); - val = tcp_metric_get(tm, TCP_METRIC_SSTHRESH); + val = net->ipv4.sysctl_tcp_no_ssthresh_metrics_save ? + 0 : tcp_metric_get(tm, TCP_METRIC_SSTHRESH); if (val) { tp->snd_ssthresh = val; if (tp->snd_ssthresh > tp->snd_cwnd_clamp) -- cgit v1.2.3 From 96ae38af9d2992073f553d14d3a85f3e4ad56250 Mon Sep 17 00:00:00 2001 From: Dan Murphy Date: Mon, 9 Dec 2019 14:10:24 -0600 Subject: dt-bindings: dp83867: Convert fifo-depth to common fifo-depth and make optional Convert the ti,fifo-depth from a TI specific property to the common tx-fifo-depth property. Also add support for the rx-fifo-depth. These are optional properties for this device and if these are not available then the fifo depths are set to device default values. Signed-off-by: Dan Murphy Reported-by: Adrian Bunk CC: Rob Herring Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/ti,dp83867.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/ti,dp83867.txt b/Documentation/devicetree/bindings/net/ti,dp83867.txt index 388ff48f53ae..44e2a4fab29e 100644 --- a/Documentation/devicetree/bindings/net/ti,dp83867.txt +++ b/Documentation/devicetree/bindings/net/ti,dp83867.txt @@ -8,8 +8,6 @@ Required properties: - ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h for applicable values. Required only if interface type is PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID - - ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h - for applicable values Note: If the interface type is PHY_INTERFACE_MODE_RGMII the TX/RX clock delays will be left at their default values, as set by the PHY's pin strapping. @@ -42,6 +40,14 @@ Optional property: Some MACs work with differential SGMII clock. See data manual for details. + - ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h + for applicable values (deprecated) + + -tx-fifo-depth - As defined in the ethernet-controller.yaml. Values for + the depth can be found in dt-bindings/net/ti-dp83867.h + -rx-fifo-depth - As defined in the ethernet-controller.yaml. Values for + the depth can be found in dt-bindings/net/ti-dp83867.h + Note: ti,min-output-impedance and ti,max-output-impedance are mutually exclusive. When both properties are present ti,max-output-impedance takes precedence. @@ -55,7 +61,7 @@ Example: reg = <0>; ti,rx-internal-delay = ; ti,tx-internal-delay = ; - ti,fifo-depth = ; + tx-fifo-depth = ; }; Datasheet can be found: -- cgit v1.2.3 From c64738d6810be367c977b25c8077dd1918666951 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:37:36 +0100 Subject: dt-bindings: dmaengine: rcar-dmac: Document r8a77961 support Document support for the system DMA controller in the Renesas R-Car M3-W+ (R8A77961) SoC. No driver update is needed. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20191205133736.5934-1-geert+renesas@glider.be Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt index 5551e929fd99..b7f81c63be8b 100644 --- a/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt +++ b/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt @@ -30,6 +30,7 @@ Required Properties: - "renesas,dmac-r8a7794" (R-Car E2) - "renesas,dmac-r8a7795" (R-Car H3) - "renesas,dmac-r8a7796" (R-Car M3-W) + - "renesas,dmac-r8a77961" (R-Car M3-W+) - "renesas,dmac-r8a77965" (R-Car M3-N) - "renesas,dmac-r8a77970" (R-Car V3M) - "renesas,dmac-r8a77980" (R-Car V3H) -- cgit v1.2.3 From 3d7349846225de2588d2d2bb410d9de51fee7c32 Mon Sep 17 00:00:00 2001 From: Georgii Staroselskii Date: Tue, 12 Nov 2019 19:15:20 +0300 Subject: dt-bindings: arm: sunxi: add Neutis N5H3 Adds bindings for the new Emlid Neutis N5H3 board. Signed-off-by: Georgii Staroselskii Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 8a1e38a1d7ab..dd2ac556ef10 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -470,6 +470,12 @@ properties: - const: emlid,neutis-n5 - const: allwinner,sun50i-h5 + - description: Emlid Neutis N5H3 Developper Board + items: + - const: emlid,neutis-n5h3-devboard + - const: emlid,neutis-n5h3 + - const: allwinner,sun8i-h3 + - description: NextThing Co. CHIP items: - const: nextthing,chip -- cgit v1.2.3 From 24e9f61c1411858587d2af254ce2c1eb7c9c9e28 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Thu, 14 Nov 2019 15:47:32 +0000 Subject: arm64: dts: allwinner: sun50i-h6-pine-h64: state that the DT supports the modelA The current sun50i-h6-pine-h64 DT does not specify which model (A or B) it supports. When this file was created, only modelA was existing, but now both model exists and with the time, this DT drifted to support the model B since it is the most common one. Furtheremore, some part of the model A does not work with it like ethernet and HDMI connector (as confirmed by Jernej on IRC). So it is time to settle the issue, and the easiest way was to state that this DT is for model B. Easiest since only a small name changes is required. Doing the opposite (stating this file is for model A) will add changes (for ethernet and HDMI) and so, will break too many setup. But as asked by the maintainer this patch state this file is for model A. In the process this patch adds the missing compoments to made it work on model A. Signed-off-by: Corentin Labbe Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 2 +- arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index dd2ac556ef10..2325cfafd23f 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -605,7 +605,7 @@ properties: - const: pine64,pine64-plus - const: allwinner,sun50i-a64 - - description: Pine64 PineH64 + - description: Pine64 PineH64 model A items: - const: pine64,pine-h64 - const: allwinner,sun50i-h6 diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts index 74899ede00fb..4fcda71f1688 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts @@ -10,7 +10,7 @@ #include / { - model = "Pine H64"; + model = "Pine H64 model A"; compatible = "pine64,pine-h64", "allwinner,sun50i-h6"; aliases { @@ -22,9 +22,10 @@ stdout-path = "serial0:115200n8"; }; - connector { + hdmi_connector: connector { compatible = "hdmi-connector"; type = "a"; + ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ port { hdmi_con_in: endpoint { @@ -52,6 +53,16 @@ }; }; + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc-gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <100000>; + gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + reg_usb_vbus: vbus { compatible = "regulator-fixed"; regulator-name = "usb-vbus"; @@ -68,7 +79,7 @@ pinctrl-0 = <&ext_rgmii_pins>; phy-mode = "rgmii"; phy-handle = <&ext_rgmii_phy>; - phy-supply = <®_aldo2>; + phy-supply = <®_gmac_3v3>; allwinner,rx-delay-ps = <200>; allwinner,tx-delay-ps = <200>; status = "okay"; -- cgit v1.2.3 From f33a911750297992ccdcdeaa6908f50c64d58783 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Thu, 14 Nov 2019 15:47:33 +0000 Subject: arm64: dts: allwinner: add pineh64 model B This patch adds the model B of the PineH64. The model B is smaller than the pine64 model A and has no PCIE slot. The only devicetree difference with the pineH64 model A, is the PHY regulator and the HDMI connector node. Signed-off-by: Corentin Labbe Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++ arch/arm64/boot/dts/allwinner/Makefile | 1 + .../dts/allwinner/sun50i-h6-pine-h64-model-b.dts | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index 2325cfafd23f..eaa042fc090f 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -610,6 +610,11 @@ properties: - const: pine64,pine-h64 - const: allwinner,sun50i-h6 + - description: Pine64 PineH64 model B + items: + - const: pine64,pine-h64-model-b + - const: allwinner,sun50i-h6 + - description: Pine64 LTS items: - const: pine64,pine64-lts diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index d2418021768b..62bc43f187bf 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -26,4 +26,5 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-3.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-lite2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts new file mode 100644 index 000000000000..f4c8966a6497 --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +/* + * Copyright (C) 2019 Corentin LABBE + */ + +#include "sun50i-h6-pine-h64.dts" + +/ { + model = "Pine H64 model B"; + compatible = "pine64,pine-h64-model-b", "allwinner,sun50i-h6"; + + /delete-node/ reg_gmac_3v3; +}; + +&hdmi_connector { + /delete-property/ ddc-en-gpios; +}; + +&emac { + phy-supply = <®_aldo2>; +}; -- cgit v1.2.3 From d2fccf94495e57ef443521a2a1cd0930d028b9f3 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sun, 17 Nov 2019 14:00:57 +0100 Subject: media: dt-bindings: media: add new rc map name Add new entry for rc-tanix-tx5max in linux,rc-map-name Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/media/rc.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/rc.yaml b/Documentation/devicetree/bindings/media/rc.yaml index d11380794ff4..a64ee038d235 100644 --- a/Documentation/devicetree/bindings/media/rc.yaml +++ b/Documentation/devicetree/bindings/media/rc.yaml @@ -123,6 +123,7 @@ properties: - rc-su3000 - rc-tango - rc-tanix-tx3mini + - rc-tanix-tx5max - rc-tbs-nec - rc-technisat-ts35 - rc-technisat-usb2 -- cgit v1.2.3 From dbb7a6b48d07b5268ac9dfd6cef8d1bcbc35b303 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 28 Nov 2019 13:43:58 +0000 Subject: dt-bindings: connector: Improve the english of the initial description The description lacks a few indefinite articles when reading and as a result is a bit clunky to read. Introduce a few indefinite articles to appease the grammar gods. Cc: Andrzej Hajda Cc: Rob Herring Cc: Chanwoo Choi Cc: linux-usb@vger.kernel.org Cc: devicetree@vger.kernel.org Signed-off-by: Bryan O'Donoghue Link: https://lore.kernel.org/r/20191128134358.3880498-3-bryan.odonoghue@linaro.org Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/connector/usb-connector.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index d357987181ee..88578ac1a8a7 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt @@ -1,8 +1,8 @@ USB Connector ============= -USB connector node represents physical USB connector. It should be -a child of USB interface controller. +A USB connector node represents a physical USB connector. It should be +a child of a USB interface controller. Required properties: - compatible: describes type of the connector, must be one of: -- cgit v1.2.3 From f1cbee2d8732a20b094dda5ef62ce9b8d29070cb Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 8 Nov 2019 14:58:12 +0530 Subject: dt-bindings: qcom: Add SC7180 bindings Add a SoC string 'sc7180' for the qualcomm SC7180 SoC. Also add a new board type 'idp' While at it, also sort the SoC and board names in alphabetical order, and also fix the weird space and tab combinations found in the file. Signed-off-by: Rajendra Nayak Reviewed-by: Vinod Koul Reviewed-by: Rob Herring Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20191108092824.9773-2-rnayak@codeaurora.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/qcom.yaml | 44 ++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml index e39d8f02e33c..529d924931f1 100644 --- a/Documentation/devicetree/bindings/arm/qcom.yaml +++ b/Documentation/devicetree/bindings/arm/qcom.yaml @@ -24,28 +24,30 @@ description: | The 'SoC' element must be one of the following strings: - apq8016 - apq8074 - apq8084 - apq8096 - msm8916 - msm8974 - msm8992 - msm8994 - msm8996 - mdm9615 - ipq8074 - sdm845 + apq8016 + apq8074 + apq8084 + apq8096 + ipq8074 + mdm9615 + msm8916 + msm8974 + msm8992 + msm8994 + msm8996 + sc7180 + sdm845 The 'board' element must be one of the following strings: - cdp - liquid - dragonboard - mtp - sbc - hk01 - qrd + cdp + dragonboard + hk01 + idp + liquid + mtp + qrd + sbc The 'soc_version' and 'board_version' elements take the form of v. where the minor number may be omitted when it's zero, i.e. v1.0 is the same @@ -144,4 +146,8 @@ properties: - qcom,ipq8074-hk01 - const: qcom,ipq8074 + - items: + - enum: + - qcom,sc7180-idp + - const: qcom,sc7180 ... -- cgit v1.2.3 From 0380c6846a4be705b2d5c964b01ba1e5aaa3f5df Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 4 Dec 2019 11:00:11 +0100 Subject: drm/atomic: Update docs around locking and commit sequencing Both locking and especially sequencing of nonblocking commits have evolved a lot. The details are all there, but I noticed that the big picture and connections have fallen behind a bit. Apply polish. Motivated by some review discussions with Thierry. v2: Review from Thierry Reviewed-by: Thierry Reding Cc: Thierry Reding Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191204100011.859468-1-daniel.vetter@ffwll.ch --- Documentation/gpu/drm-kms.rst | 11 ++++++++- drivers/gpu/drm/drm_atomic.c | 10 ++++---- drivers/gpu/drm/drm_atomic_helper.c | 46 +++++++++++++++++++++++-------------- include/drm/drm_atomic.h | 13 +++++++++-- 4 files changed, 56 insertions(+), 24 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index c68588ce4090..b9330343d1bc 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -260,7 +260,8 @@ Taken all together there's two consequences for the atomic design: drm_connector_state ` for connectors. These are the only objects with userspace-visible and settable state. For internal state drivers can subclass these structures through embeddeding, or add entirely new state - structures for their globally shared hardware functions. + structures for their globally shared hardware functions, see :c:type:`struct + drm_private_state`. - An atomic update is assembled and validated as an entirely free-standing pile of structures within the :c:type:`drm_atomic_state ` @@ -269,6 +270,14 @@ Taken all together there's two consequences for the atomic design: to the driver and modeset objects. This way rolling back an update boils down to releasing memory and unreferencing objects like framebuffers. +Locking of atomic state structures is internally using :c:type:`struct +drm_modeset_lock `. As a general rule the locking shouldn't be +exposed to drivers, instead the right locks should be automatically acquired by +any function that duplicates or peeks into a state, like e.g. +:c:func:`drm_atomic_get_crtc_state()`. Locking only protects the software data +structure, ordering of committing state changes to hardware is sequenced using +:c:type:`struct drm_crtc_commit `. + Read on in this chapter, and also in :ref:`drm_atomic_helper` for more detailed coverage of specific topics. diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 14aeaf736321..ab4508f25986 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -688,10 +688,12 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, * associated state struct &drm_private_state. * * Similar to userspace-exposed objects, private state structures can be - * acquired by calling drm_atomic_get_private_obj_state(). Since this function - * does not take care of locking, drivers should wrap it for each type of - * private state object they have with the required call to drm_modeset_lock() - * for the corresponding &drm_modeset_lock. + * acquired by calling drm_atomic_get_private_obj_state(). This also takes care + * of locking, hence drivers should not have a need to call drm_modeset_lock() + * directly. Sequence of the actual hardware state commit is not handled, + * drivers might need to keep track of struct drm_crtc_commit within subclassed + * structure of &drm_private_state as necessary, e.g. similar to + * &drm_plane_state.commit. See also &drm_atomic_state.fake_commit. * * All private state structures contained in a &drm_atomic_state update can be * iterated using for_each_oldnew_private_obj_in_state(), diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 29c3115bf9e2..57a84555a6bd 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1832,17 +1832,21 @@ EXPORT_SYMBOL(drm_atomic_helper_commit); /** * DOC: implementing nonblocking commit * - * Nonblocking atomic commits have to be implemented in the following sequence: + * Nonblocking atomic commits should use struct &drm_crtc_commit to sequence + * different operations against each another. Locks, especially struct + * &drm_modeset_lock, should not be held in worker threads or any other + * asynchronous context used to commit the hardware state. * - * 1. Run drm_atomic_helper_prepare_planes() first. This is the only function - * which commit needs to call which can fail, so we want to run it first and + * drm_atomic_helper_commit() implements the recommended sequence for + * nonblocking commits, using drm_atomic_helper_setup_commit() internally: + * + * 1. Run drm_atomic_helper_prepare_planes(). Since this can fail and we + * need to propagate out of memory/VRAM errors to userspace, it must be called * synchronously. * * 2. Synchronize with any outstanding nonblocking commit worker threads which - * might be affected the new state update. This can be done by either cancelling - * or flushing the work items, depending upon whether the driver can deal with - * cancelled updates. Note that it is important to ensure that the framebuffer - * cleanup is still done when cancelling. + * might be affected by the new state update. This is handled by + * drm_atomic_helper_setup_commit(). * * Asynchronous workers need to have sufficient parallelism to be able to run * different atomic commits on different CRTCs in parallel. The simplest way to @@ -1853,21 +1857,29 @@ EXPORT_SYMBOL(drm_atomic_helper_commit); * must be done as one global operation, and enabling or disabling a CRTC can * take a long time. But even that is not required. * + * IMPORTANT: A &drm_atomic_state update for multiple CRTCs is sequenced + * against all CRTCs therein. Therefore for atomic state updates which only flip + * planes the driver must not get the struct &drm_crtc_state of unrelated CRTCs + * in its atomic check code: This would prevent committing of atomic updates to + * multiple CRTCs in parallel. In general, adding additional state structures + * should be avoided as much as possible, because this reduces parallelism in + * (nonblocking) commits, both due to locking and due to commit sequencing + * requirements. + * * 3. The software state is updated synchronously with * drm_atomic_helper_swap_state(). Doing this under the protection of all modeset - * locks means concurrent callers never see inconsistent state. And doing this - * while it's guaranteed that no relevant nonblocking worker runs means that - * nonblocking workers do not need grab any locks. Actually they must not grab - * locks, for otherwise the work flushing will deadlock. + * locks means concurrent callers never see inconsistent state. Note that commit + * workers do not hold any locks; their access is only coordinated through + * ordering. If workers would access state only through the pointers in the + * free-standing state objects (currently not the case for any driver) then even + * multiple pending commits could be in-flight at the same time. * * 4. Schedule a work item to do all subsequent steps, using the split-out * commit helpers: a) pre-plane commit b) plane commit c) post-plane commit and * then cleaning up the framebuffers after the old framebuffer is no longer - * being displayed. - * - * The above scheme is implemented in the atomic helper libraries in - * drm_atomic_helper_commit() using a bunch of helper functions. See - * drm_atomic_helper_setup_commit() for a starting point. + * being displayed. The scheduled work should synchronize against other workers + * using the &drm_crtc_commit infrastructure as needed. See + * drm_atomic_helper_setup_commit() for more details. */ static int stall_checks(struct drm_crtc *crtc, bool nonblock) @@ -2096,7 +2108,7 @@ EXPORT_SYMBOL(drm_atomic_helper_setup_commit); * * This function waits for all preceeding commits that touch the same CRTC as * @old_state to both be committed to the hardware (as signalled by - * drm_atomic_helper_commit_hw_done) and executed by the hardware (as signalled + * drm_atomic_helper_commit_hw_done()) and executed by the hardware (as signalled * by calling drm_crtc_send_vblank_event() on the &drm_crtc_state.event). * * This is part of the atomic helper support for nonblocking commits, see diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index b6c73fd9f55a..5923819dcd68 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -60,8 +60,8 @@ * wait for flip_done <---- * clean up atomic state * - * The important bit to know is that cleanup_done is the terminal event, but the - * ordering between flip_done and hw_done is entirely up to the specific driver + * The important bit to know is that &cleanup_done is the terminal event, but the + * ordering between &flip_done and &hw_done is entirely up to the specific driver * and modeset state change. * * For an implementation of how to use this look at @@ -92,6 +92,9 @@ struct drm_crtc_commit { * commit is sent to userspace, or when an out-fence is singalled. Note * that for most hardware, in most cases this happens after @hw_done is * signalled. + * + * Completion of this stage is signalled implicitly by calling + * drm_crtc_send_vblank_event() on &drm_crtc_state.event. */ struct completion flip_done; @@ -107,6 +110,9 @@ struct drm_crtc_commit { * Note that this does not need to include separately reference-counted * resources like backing storage buffer pinning, or runtime pm * management. + * + * Drivers should call drm_atomic_helper_commit_hw_done() to signal + * completion of this stage. */ struct completion hw_done; @@ -118,6 +124,9 @@ struct drm_crtc_commit { * a vblank wait completed it might be a bit later. This completion is * useful to throttle updates and avoid hardware updates getting ahead * of the buffer cleanup too much. + * + * Drivers should call drm_atomic_helper_commit_cleanup_done() to signal + * completion of this stage. */ struct completion cleanup_done; -- cgit v1.2.3 From 6acc942c5eecad34a7623e01317f3d03d1e05462 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 4 Dec 2019 11:19:33 +0100 Subject: drm/doc: Drop :c:func: markup Kernel sphinx has learned how to do that in commit d74b0d31dddeac2b44c715588d53d9a1e5b1158e Author: Jonathan Corbet Date: Thu Apr 25 07:55:07 2019 -0600 Docs: An initial automarkup extension for sphinx Unfortunately it hasn't learned that yet for structures, so we're stuck with the :c:type: noise for now still. Reviewed-by: Thierry Reding Cc: Jonathan Corbet Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191204101933.861169-1-daniel.vetter@ffwll.ch --- Documentation/gpu/drm-internals.rst | 4 +-- Documentation/gpu/drm-kms.rst | 7 ++-- Documentation/gpu/drm-mm.rst | 68 +++++++++++++++++-------------------- 3 files changed, 36 insertions(+), 43 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/drm-internals.rst b/Documentation/gpu/drm-internals.rst index 966bd2d9f0cc..a73320576ca9 100644 --- a/Documentation/gpu/drm-internals.rst +++ b/Documentation/gpu/drm-internals.rst @@ -24,9 +24,9 @@ Driver Initialization At the core of every DRM driver is a :c:type:`struct drm_driver ` structure. Drivers typically statically initialize a drm_driver structure, and then pass it to -:c:func:`drm_dev_alloc()` to allocate a device instance. After the +drm_dev_alloc() to allocate a device instance. After the device instance is fully initialized it can be registered (which makes -it accessible from userspace) using :c:func:`drm_dev_register()`. +it accessible from userspace) using drm_dev_register(). The :c:type:`struct drm_driver ` structure contains static information that describes the driver and features it diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index b9330343d1bc..906771e03103 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -3,7 +3,7 @@ Kernel Mode Setting (KMS) ========================= Drivers must initialize the mode setting core by calling -:c:func:`drm_mode_config_init()` on the DRM device. The function +drm_mode_config_init() on the DRM device. The function initializes the :c:type:`struct drm_device ` mode_config field and never fails. Once done, mode configuration must be setup by initializing the following fields. @@ -181,8 +181,7 @@ Setting`_). The somewhat surprising part here is that properties are not directly instantiated on each object, but free-standing mode objects themselves, represented by :c:type:`struct drm_property `, which only specify the type and value range of a property. Any given property can be attached -multiple times to different objects using :c:func:`drm_object_attach_property() -`. +multiple times to different objects using drm_object_attach_property(). .. kernel-doc:: include/drm/drm_mode_object.h :internal: @@ -274,7 +273,7 @@ Locking of atomic state structures is internally using :c:type:`struct drm_modeset_lock `. As a general rule the locking shouldn't be exposed to drivers, instead the right locks should be automatically acquired by any function that duplicates or peeks into a state, like e.g. -:c:func:`drm_atomic_get_crtc_state()`. Locking only protects the software data +drm_atomic_get_crtc_state(). Locking only protects the software data structure, ordering of committing state changes to hardware is sequenced using :c:type:`struct drm_crtc_commit `. diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index 59619296c84b..c77b32601260 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -149,19 +149,19 @@ struct :c:type:`struct drm_gem_object `. To create a GEM object, a driver allocates memory for an instance of its specific GEM object type and initializes the embedded struct :c:type:`struct drm_gem_object ` with a call -to :c:func:`drm_gem_object_init()`. The function takes a pointer +to drm_gem_object_init(). The function takes a pointer to the DRM device, a pointer to the GEM object and the buffer object size in bytes. GEM uses shmem to allocate anonymous pageable memory. -:c:func:`drm_gem_object_init()` will create an shmfs file of the +drm_gem_object_init() will create an shmfs file of the requested size and store it into the struct :c:type:`struct drm_gem_object ` filp field. The memory is used as either main storage for the object when the graphics hardware uses system memory directly or as a backing store otherwise. Drivers are responsible for the actual physical pages allocation by -calling :c:func:`shmem_read_mapping_page_gfp()` for each page. +calling shmem_read_mapping_page_gfp() for each page. Note that they can decide to allocate pages when initializing the GEM object, or to delay allocation until the memory is needed (for instance when a page fault occurs as a result of a userspace memory access or @@ -170,20 +170,18 @@ when the driver needs to start a DMA transfer involving the memory). Anonymous pageable memory allocation is not always desired, for instance when the hardware requires physically contiguous system memory as is often the case in embedded devices. Drivers can create GEM objects with -no shmfs backing (called private GEM objects) by initializing them with -a call to :c:func:`drm_gem_private_object_init()` instead of -:c:func:`drm_gem_object_init()`. Storage for private GEM objects -must be managed by drivers. +no shmfs backing (called private GEM objects) by initializing them with a call +to drm_gem_private_object_init() instead of drm_gem_object_init(). Storage for +private GEM objects must be managed by drivers. GEM Objects Lifetime -------------------- All GEM objects are reference-counted by the GEM core. References can be -acquired and release by :c:func:`calling drm_gem_object_get()` and -:c:func:`drm_gem_object_put()` respectively. The caller must hold the -:c:type:`struct drm_device ` struct_mutex lock when calling -:c:func:`drm_gem_object_get()`. As a convenience, GEM provides -:c:func:`drm_gem_object_put_unlocked()` functions that can be called without +acquired and release by calling drm_gem_object_get() and drm_gem_object_put() +respectively. The caller must hold the :c:type:`struct drm_device ` +struct_mutex lock when calling drm_gem_object_get(). As a convenience, GEM +provides drm_gem_object_put_unlocked() functions that can be called without holding the lock. When the last reference to a GEM object is released the GEM core calls @@ -194,7 +192,7 @@ free the GEM object and all associated resources. void (\*gem_free_object) (struct drm_gem_object \*obj); Drivers are responsible for freeing all GEM object resources. This includes the resources created by the GEM core, which need to be released with -:c:func:`drm_gem_object_release()`. +drm_gem_object_release(). GEM Objects Naming ------------------ @@ -210,13 +208,11 @@ to the GEM object in other standard or driver-specific ioctls. Closing a DRM file handle frees all its GEM handles and dereferences the associated GEM objects. -To create a handle for a GEM object drivers call -:c:func:`drm_gem_handle_create()`. The function takes a pointer -to the DRM file and the GEM object and returns a locally unique handle. -When the handle is no longer needed drivers delete it with a call to -:c:func:`drm_gem_handle_delete()`. Finally the GEM object -associated with a handle can be retrieved by a call to -:c:func:`drm_gem_object_lookup()`. +To create a handle for a GEM object drivers call drm_gem_handle_create(). The +function takes a pointer to the DRM file and the GEM object and returns a +locally unique handle. When the handle is no longer needed drivers delete it +with a call to drm_gem_handle_delete(). Finally the GEM object associated with a +handle can be retrieved by a call to drm_gem_object_lookup(). Handles don't take ownership of GEM objects, they only take a reference to the object that will be dropped when the handle is destroyed. To @@ -258,7 +254,7 @@ The mmap system call can't be used directly to map GEM objects, as they don't have their own file handle. Two alternative methods currently co-exist to map GEM objects to userspace. The first method uses a driver-specific ioctl to perform the mapping operation, calling -:c:func:`do_mmap()` under the hood. This is often considered +do_mmap() under the hood. This is often considered dubious, seems to be discouraged for new GEM-enabled drivers, and will thus not be described here. @@ -267,23 +263,22 @@ The second method uses the mmap system call on the DRM file handle. void offset); DRM identifies the GEM object to be mapped by a fake offset passed through the mmap offset argument. Prior to being mapped, a GEM object must thus be associated with a fake offset. To do so, drivers -must call :c:func:`drm_gem_create_mmap_offset()` on the object. +must call drm_gem_create_mmap_offset() on the object. Once allocated, the fake offset value must be passed to the application in a driver-specific way and can then be used as the mmap offset argument. -The GEM core provides a helper method :c:func:`drm_gem_mmap()` to +The GEM core provides a helper method drm_gem_mmap() to handle object mapping. The method can be set directly as the mmap file operation handler. It will look up the GEM object based on the offset value and set the VMA operations to the :c:type:`struct drm_driver -` gem_vm_ops field. Note that -:c:func:`drm_gem_mmap()` doesn't map memory to userspace, but -relies on the driver-provided fault handler to map pages individually. +` gem_vm_ops field. Note that drm_gem_mmap() doesn't map memory to +userspace, but relies on the driver-provided fault handler to map pages +individually. -To use :c:func:`drm_gem_mmap()`, drivers must fill the struct -:c:type:`struct drm_driver ` gem_vm_ops field -with a pointer to VM operations. +To use drm_gem_mmap(), drivers must fill the struct :c:type:`struct drm_driver +` gem_vm_ops field with a pointer to VM operations. The VM operations is a :c:type:`struct vm_operations_struct ` made up of several fields, the more interesting ones being: @@ -298,9 +293,8 @@ made up of several fields, the more interesting ones being: The open and close operations must update the GEM object reference -count. Drivers can use the :c:func:`drm_gem_vm_open()` and -:c:func:`drm_gem_vm_close()` helper functions directly as open -and close handlers. +count. Drivers can use the drm_gem_vm_open() and drm_gem_vm_close() helper +functions directly as open and close handlers. The fault operation handler is responsible for mapping individual pages to userspace when a page fault occurs. Depending on the memory @@ -312,12 +306,12 @@ Drivers that want to map the GEM object upfront instead of handling page faults can implement their own mmap file operation handler. For platforms without MMU the GEM core provides a helper method -:c:func:`drm_gem_cma_get_unmapped_area`. The mmap() routines will call -this to get a proposed address for the mapping. +drm_gem_cma_get_unmapped_area(). The mmap() routines will call this to get a +proposed address for the mapping. -To use :c:func:`drm_gem_cma_get_unmapped_area`, drivers must fill the -struct :c:type:`struct file_operations ` get_unmapped_area -field with a pointer on :c:func:`drm_gem_cma_get_unmapped_area`. +To use drm_gem_cma_get_unmapped_area(), drivers must fill the struct +:c:type:`struct file_operations ` get_unmapped_area field with +a pointer on drm_gem_cma_get_unmapped_area(). More detailed information about get_unmapped_area can be found in Documentation/nommu-mmap.txt -- cgit v1.2.3 From ca866ee825911cb70e64ad5b33ac73d4ab924c1f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 9 Dec 2019 21:04:01 -0800 Subject: nfp: add support for TLV device stats Device stats are currently hard coded in the PCI BAR0 layout. Add a ability to read them from the TLV area instead. Names for the stats are maintained by the driver, and their meaning documented. This allows us to more easily add and remove device stats. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- .../networking/device_drivers/netronome/nfp.rst | 116 +++++++++++++++++++++ drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c | 9 ++ drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h | 16 +++ .../net/ethernet/netronome/nfp/nfp_net_ethtool.c | 108 +++++++++++++++++-- 4 files changed, 242 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/device_drivers/netronome/nfp.rst b/Documentation/networking/device_drivers/netronome/nfp.rst index 6c08ac8b5147..ada611fb427c 100644 --- a/Documentation/networking/device_drivers/netronome/nfp.rst +++ b/Documentation/networking/device_drivers/netronome/nfp.rst @@ -131,3 +131,119 @@ abi_drv_reset abi_drv_load_ifc Defines a list of PF devices allowed to load FW on the device. This variable is not currently user configurable. + +Statistics +========== + +Following device statistics are available through the ``ethtool -S`` interface: + +.. flat-table:: NFP device statistics + :header-rows: 1 + :widths: 3 1 11 + + * - Name + - ID + - Meaning + + * - dev_rx_discards + - 1 + - Packet can be discarded on the RX path for one of the following reasons: + + * The NIC is not in promisc mode, and the destination MAC address + doesn't match the interfaces' MAC address. + * The received packet is larger than the max buffer size on the host. + I.e. it exceeds the Layer 3 MRU. + * There is no freelist descriptor available on the host for the packet. + It is likely that the NIC couldn't cache one in time. + * A BPF program discarded the packet. + * The datapath drop action was executed. + * The MAC discarded the packet due to lack of ingress buffer space + on the NIC. + + * - dev_rx_errors + - 2 + - A packet can be counted (and dropped) as RX error for the following + reasons: + + * A problem with the VEB lookup (only when SR-IOV is used). + * A physical layer problem that causes Ethernet errors, like FCS or + alignment errors. The cause is usually faulty cables or SFPs. + + * - dev_rx_bytes + - 3 + - Total number of bytes received. + + * - dev_rx_uc_bytes + - 4 + - Unicast bytes received. + + * - dev_rx_mc_bytes + - 5 + - Multicast bytes received. + + * - dev_rx_bc_bytes + - 6 + - Broadcast bytes received. + + * - dev_rx_pkts + - 7 + - Total number of packets received. + + * - dev_rx_mc_pkts + - 8 + - Multicast packets received. + + * - dev_rx_bc_pkts + - 9 + - Broadcast packets received. + + * - dev_tx_discards + - 10 + - A packet can be discarded in the TX direction if the MAC is + being flow controlled and the NIC runs out of TX queue space. + + * - dev_tx_errors + - 11 + - A packet can be counted as TX error (and dropped) for one for the + following reasons: + + * The packet is an LSO segment, but the Layer 3 or Layer 4 offset + could not be determined. Therefore LSO could not continue. + * An invalid packet descriptor was received over PCIe. + * The packet Layer 3 length exceeds the device MTU. + * An error on the MAC/physical layer. Usually due to faulty cables or + SFPs. + * A CTM buffer could not be allocated. + * The packet offset was incorrect and could not be fixed by the NIC. + + * - dev_tx_bytes + - 12 + - Total number of bytes transmitted. + + * - dev_tx_uc_bytes + - 13 + - Unicast bytes transmitted. + + * - dev_tx_mc_bytes + - 14 + - Multicast bytes transmitted. + + * - dev_tx_bc_bytes + - 15 + - Broadcast bytes transmitted. + + * - dev_tx_pkts + - 16 + - Total number of packets transmitted. + + * - dev_tx_mc_pkts + - 17 + - Multicast packets transmitted. + + * - dev_tx_bc_pkts + - 18 + - Broadcast packets transmitted. + +Note that statistics unknown to the driver will be displayed as +``dev_unknown_stat$ID``, where ``$ID`` refers to the second column +above. diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c index d835c14b7257..45756648a85c 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c @@ -114,6 +114,15 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem, caps->crypto_ops = readl(data); caps->crypto_enable_off = data - ctrl_mem + 16; break; + case NFP_NET_CFG_TLV_TYPE_VNIC_STATS: + if ((data - ctrl_mem) % 8) { + dev_warn(dev, "VNIC STATS TLV misaligned, ignoring offset:%u len:%u\n", + offset, length); + break; + } + caps->vnic_stats_off = data - ctrl_mem; + caps->vnic_stats_cnt = length / 10; + break; default: if (!FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr)) break; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h index ee6b24e4eacd..c38cc36a2a70 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h @@ -479,6 +479,17 @@ * 8 words, bitmaps of supported and enabled crypto operations. * First 16B (4 words) contains a bitmap of supported crypto operations, * and next 16B contain the enabled operations. + * + * %NFP_NET_CFG_TLV_TYPE_VNIC_STATS: + * Variable, per-vNIC statistics, data should be 8B aligned (FW should insert + * zero-length RESERVED TLV to pad). + * TLV data has two sections. First is an array of statistics' IDs (2B each). + * Second 8B statistics themselves. Statistics are 8B aligned, meaning there + * may be a padding between sections. + * Number of statistics can be determined as floor(tlv.length / (2 + 8)). + * This TLV overwrites %NFP_NET_CFG_STATS_* values (statistics in this TLV + * duplicate the old ones, so driver should be careful not to unnecessarily + * render both). */ #define NFP_NET_CFG_TLV_TYPE_UNKNOWN 0 #define NFP_NET_CFG_TLV_TYPE_RESERVED 1 @@ -490,6 +501,7 @@ #define NFP_NET_CFG_TLV_TYPE_REPR_CAP 7 #define NFP_NET_CFG_TLV_TYPE_MBOX_CMSG_TYPES 10 #define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS 11 /* see crypto/fw.h */ +#define NFP_NET_CFG_TLV_TYPE_VNIC_STATS 12 struct device; @@ -502,6 +514,8 @@ struct device; * @mbox_cmsg_types: cmsgs which can be passed through the mailbox * @crypto_ops: supported crypto operations * @crypto_enable_off: offset of crypto ops enable region + * @vnic_stats_off: offset of vNIC stats area + * @vnic_stats_cnt: number of vNIC stats */ struct nfp_net_tlv_caps { u32 me_freq_mhz; @@ -511,6 +525,8 @@ struct nfp_net_tlv_caps { u32 mbox_cmsg_types; u32 crypto_ops; unsigned int crypto_enable_off; + unsigned int vnic_stats_off; + unsigned int vnic_stats_cnt; }; int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem, diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 1b840ee47339..b386a221c599 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -148,6 +148,28 @@ static const struct nfp_et_stat nfp_mac_et_stats[] = { { "tx_pause_frames_class7", NFP_MAC_STATS_TX_PAUSE_FRAMES_CLASS7, }, }; +static const char nfp_tlv_stat_names[][ETH_GSTRING_LEN] = { + [1] = "dev_rx_discards", + [2] = "dev_rx_errors", + [3] = "dev_rx_bytes", + [4] = "dev_rx_uc_bytes", + [5] = "dev_rx_mc_bytes", + [6] = "dev_rx_bc_bytes", + [7] = "dev_rx_pkts", + [8] = "dev_rx_mc_pkts", + [9] = "dev_rx_bc_pkts", + + [10] = "dev_tx_discards", + [11] = "dev_tx_errors", + [12] = "dev_tx_bytes", + [13] = "dev_tx_uc_bytes", + [14] = "dev_tx_mc_bytes", + [15] = "dev_tx_bc_bytes", + [16] = "dev_tx_pkts", + [17] = "dev_tx_mc_pkts", + [18] = "dev_tx_bc_pkts", +}; + #define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats) #define NN_ET_SWITCH_STATS_LEN 9 #define NN_RVEC_GATHER_STATS 13 @@ -560,6 +582,65 @@ nfp_vnic_get_hw_stats(u64 *data, u8 __iomem *mem, unsigned int num_vecs) return data; } +static unsigned int nfp_vnic_get_tlv_stats_count(struct nfp_net *nn) +{ + return nn->tlv_caps.vnic_stats_cnt + nn->max_r_vecs * 4; +} + +static u8 *nfp_vnic_get_tlv_stats_strings(struct nfp_net *nn, u8 *data) +{ + unsigned int i, id; + u8 __iomem *mem; + u64 id_word = 0; + + mem = nn->dp.ctrl_bar + nn->tlv_caps.vnic_stats_off; + for (i = 0; i < nn->tlv_caps.vnic_stats_cnt; i++) { + if (!(i % 4)) + id_word = readq(mem + i * 2); + + id = (u16)id_word; + id_word >>= 16; + + if (id < ARRAY_SIZE(nfp_tlv_stat_names) && + nfp_tlv_stat_names[id][0]) { + memcpy(data, nfp_tlv_stat_names[id], ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } else { + data = nfp_pr_et(data, "dev_unknown_stat%u", id); + } + } + + for (i = 0; i < nn->max_r_vecs; i++) { + data = nfp_pr_et(data, "rxq_%u_pkts", i); + data = nfp_pr_et(data, "rxq_%u_bytes", i); + data = nfp_pr_et(data, "txq_%u_pkts", i); + data = nfp_pr_et(data, "txq_%u_bytes", i); + } + + return data; +} + +static u64 *nfp_vnic_get_tlv_stats(struct nfp_net *nn, u64 *data) +{ + u8 __iomem *mem; + unsigned int i; + + mem = nn->dp.ctrl_bar + nn->tlv_caps.vnic_stats_off; + mem += roundup(2 * nn->tlv_caps.vnic_stats_cnt, 8); + for (i = 0; i < nn->tlv_caps.vnic_stats_cnt; i++) + *data++ = readq(mem + i * 8); + + mem = nn->dp.ctrl_bar; + for (i = 0; i < nn->max_r_vecs; i++) { + *data++ = readq(mem + NFP_NET_CFG_RXR_STATS(i)); + *data++ = readq(mem + NFP_NET_CFG_RXR_STATS(i) + 8); + *data++ = readq(mem + NFP_NET_CFG_TXR_STATS(i)); + *data++ = readq(mem + NFP_NET_CFG_TXR_STATS(i) + 8); + } + + return data; +} + static unsigned int nfp_mac_get_stats_count(struct net_device *netdev) { struct nfp_port *port; @@ -609,8 +690,12 @@ static void nfp_net_get_strings(struct net_device *netdev, switch (stringset) { case ETH_SS_STATS: data = nfp_vnic_get_sw_stats_strings(netdev, data); - data = nfp_vnic_get_hw_stats_strings(data, nn->max_r_vecs, - false); + if (!nn->tlv_caps.vnic_stats_off) + data = nfp_vnic_get_hw_stats_strings(data, + nn->max_r_vecs, + false); + else + data = nfp_vnic_get_tlv_stats_strings(nn, data); data = nfp_mac_get_stats_strings(netdev, data); data = nfp_app_port_get_stats_strings(nn->port, data); break; @@ -624,7 +709,11 @@ nfp_net_get_stats(struct net_device *netdev, struct ethtool_stats *stats, struct nfp_net *nn = netdev_priv(netdev); data = nfp_vnic_get_sw_stats(netdev, data); - data = nfp_vnic_get_hw_stats(data, nn->dp.ctrl_bar, nn->max_r_vecs); + if (!nn->tlv_caps.vnic_stats_off) + data = nfp_vnic_get_hw_stats(data, nn->dp.ctrl_bar, + nn->max_r_vecs); + else + data = nfp_vnic_get_tlv_stats(nn, data); data = nfp_mac_get_stats(netdev, data); data = nfp_app_port_get_stats(nn->port, data); } @@ -632,13 +721,18 @@ nfp_net_get_stats(struct net_device *netdev, struct ethtool_stats *stats, static int nfp_net_get_sset_count(struct net_device *netdev, int sset) { struct nfp_net *nn = netdev_priv(netdev); + unsigned int cnt; switch (sset) { case ETH_SS_STATS: - return nfp_vnic_get_sw_stats_count(netdev) + - nfp_vnic_get_hw_stats_count(nn->max_r_vecs) + - nfp_mac_get_stats_count(netdev) + - nfp_app_port_get_stats_count(nn->port); + cnt = nfp_vnic_get_sw_stats_count(netdev); + if (!nn->tlv_caps.vnic_stats_off) + cnt += nfp_vnic_get_hw_stats_count(nn->max_r_vecs); + else + cnt += nfp_vnic_get_tlv_stats_count(nn); + cnt += nfp_mac_get_stats_count(netdev); + cnt += nfp_app_port_get_stats_count(nn->port); + return cnt; default: return -EOPNOTSUPP; } -- cgit v1.2.3 From 8c8d09e24d4556517a53cbe6cfd0e545fdbcde22 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Mon, 25 Nov 2019 15:50:06 +0100 Subject: dt-bindings: mxsfb: Add compatible for iMX8MQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NXP's iMX8MQ has an LCDIF as well. Signed-off-by: Guido Günther Reviewed-by: Fabio Estevam Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/display/mxsfb.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/mxsfb.txt b/Documentation/devicetree/bindings/display/mxsfb.txt index 472e1ea6c591..c985871c46b3 100644 --- a/Documentation/devicetree/bindings/display/mxsfb.txt +++ b/Documentation/devicetree/bindings/display/mxsfb.txt @@ -6,6 +6,7 @@ Required properties: - compatible: Should be "fsl,imx23-lcdif" for i.MX23. Should be "fsl,imx28-lcdif" for i.MX28. Should be "fsl,imx6sx-lcdif" for i.MX6SX. + Should be "fsl,imx8mq-lcdif" for i.MX8MQ. - reg: Address and length of the register set for LCDIF - interrupts: Should contain LCDIF interrupt - clocks: A list of phandle + clock-specifier pairs, one for each -- cgit v1.2.3 From 838f8ed9a09422358c9a5c9750c576bacaa8cc29 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 2 Dec 2019 10:13:17 -0300 Subject: dt-bindings: arm: fsl: Document i.MX7ULP Embedded Artists COM board Add an entry for the Embedded Artists i.MX7ULP COM board. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index b5497ae276bc..6f241a3b5a20 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -266,6 +266,7 @@ properties: - description: i.MX7ULP based Boards items: - enum: + - ea,imx7ulp-com # i.MX7ULP Embedded Artists COM Board - fsl,imx7ulp-evk # i.MX7ULP Evaluation Kit - const: fsl,imx7ulp -- cgit v1.2.3 From 9ffdd7982417e2e227e295c4dea9cec652a71983 Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Tue, 29 Oct 2019 01:54:17 +0530 Subject: doc: Convert arrayRCU.txt to arrayRCU.rst This patch converts arrayRCU from .txt to .rst format, and also adds it to the index.rst file. Signed-off-by: Madhuparna Bhowmik [ paulmck: Trimmed trailing whitespace. ] Tested-by: Phong Tran Tested-by: Amol Grover Signed-off-by: Paul E. McKenney --- Documentation/RCU/arrayRCU.rst | 165 +++++++++++++++++++++++++++++++++++++++++ Documentation/RCU/arrayRCU.txt | 153 -------------------------------------- Documentation/RCU/index.rst | 1 + 3 files changed, 166 insertions(+), 153 deletions(-) create mode 100644 Documentation/RCU/arrayRCU.rst delete mode 100644 Documentation/RCU/arrayRCU.txt (limited to 'Documentation') diff --git a/Documentation/RCU/arrayRCU.rst b/Documentation/RCU/arrayRCU.rst new file mode 100644 index 000000000000..4051ea3871ef --- /dev/null +++ b/Documentation/RCU/arrayRCU.rst @@ -0,0 +1,165 @@ +.. _array_rcu_doc: + +Using RCU to Protect Read-Mostly Arrays +======================================= + +Although RCU is more commonly used to protect linked lists, it can +also be used to protect arrays. Three situations are as follows: + +1. :ref:`Hash Tables ` + +2. :ref:`Static Arrays ` + +3. :ref:`Resizable Arrays ` + +Each of these three situations involves an RCU-protected pointer to an +array that is separately indexed. It might be tempting to consider use +of RCU to instead protect the index into an array, however, this use +case is **not** supported. The problem with RCU-protected indexes into +arrays is that compilers can play way too many optimization games with +integers, which means that the rules governing handling of these indexes +are far more trouble than they are worth. If RCU-protected indexes into +arrays prove to be particularly valuable (which they have not thus far), +explicit cooperation from the compiler will be required to permit them +to be safely used. + +That aside, each of the three RCU-protected pointer situations are +described in the following sections. + +.. _hash_tables: + +Situation 1: Hash Tables +------------------------ + +Hash tables are often implemented as an array, where each array entry +has a linked-list hash chain. Each hash chain can be protected by RCU +as described in the listRCU.txt document. This approach also applies +to other array-of-list situations, such as radix trees. + +.. _static_arrays: + +Situation 2: Static Arrays +-------------------------- + +Static arrays, where the data (rather than a pointer to the data) is +located in each array element, and where the array is never resized, +have not been used with RCU. Rik van Riel recommends using seqlock in +this situation, which would also have minimal read-side overhead as long +as updates are rare. + +Quick Quiz: + Why is it so important that updates be rare when using seqlock? + +:ref:`Answer to Quick Quiz ` + +.. _resizable_arrays: + +Situation 3: Resizable Arrays +------------------------------ + +Use of RCU for resizable arrays is demonstrated by the grow_ary() +function formerly used by the System V IPC code. The array is used +to map from semaphore, message-queue, and shared-memory IDs to the data +structure that represents the corresponding IPC construct. The grow_ary() +function does not acquire any locks; instead its caller must hold the +ids->sem semaphore. + +The grow_ary() function, shown below, does some limit checks, allocates a +new ipc_id_ary, copies the old to the new portion of the new, initializes +the remainder of the new, updates the ids->entries pointer to point to +the new array, and invokes ipc_rcu_putref() to free up the old array. +Note that rcu_assign_pointer() is used to update the ids->entries pointer, +which includes any memory barriers required on whatever architecture +you are running on:: + + static int grow_ary(struct ipc_ids* ids, int newsize) + { + struct ipc_id_ary* new; + struct ipc_id_ary* old; + int i; + int size = ids->entries->size; + + if(newsize > IPCMNI) + newsize = IPCMNI; + if(newsize <= size) + return newsize; + + new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize + + sizeof(struct ipc_id_ary)); + if(new == NULL) + return size; + new->size = newsize; + memcpy(new->p, ids->entries->p, + sizeof(struct kern_ipc_perm *)*size + + sizeof(struct ipc_id_ary)); + for(i=size;ip[i] = NULL; + } + old = ids->entries; + + /* + * Use rcu_assign_pointer() to make sure the memcpyed + * contents of the new array are visible before the new + * array becomes visible. + */ + rcu_assign_pointer(ids->entries, new); + + ipc_rcu_putref(old); + return newsize; + } + +The ipc_rcu_putref() function decrements the array's reference count +and then, if the reference count has dropped to zero, uses call_rcu() +to free the array after a grace period has elapsed. + +The array is traversed by the ipc_lock() function. This function +indexes into the array under the protection of rcu_read_lock(), +using rcu_dereference() to pick up the pointer to the array so +that it may later safely be dereferenced -- memory barriers are +required on the Alpha CPU. Since the size of the array is stored +with the array itself, there can be no array-size mismatches, so +a simple check suffices. The pointer to the structure corresponding +to the desired IPC object is placed in "out", with NULL indicating +a non-existent entry. After acquiring "out->lock", the "out->deleted" +flag indicates whether the IPC object is in the process of being +deleted, and, if not, the pointer is returned:: + + struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id) + { + struct kern_ipc_perm* out; + int lid = id % SEQ_MULTIPLIER; + struct ipc_id_ary* entries; + + rcu_read_lock(); + entries = rcu_dereference(ids->entries); + if(lid >= entries->size) { + rcu_read_unlock(); + return NULL; + } + out = entries->p[lid]; + if(out == NULL) { + rcu_read_unlock(); + return NULL; + } + spin_lock(&out->lock); + + /* ipc_rmid() may have already freed the ID while ipc_lock + * was spinning: here verify that the structure is still valid + */ + if (out->deleted) { + spin_unlock(&out->lock); + rcu_read_unlock(); + return NULL; + } + return out; + } + +.. _answer_quick_quiz_seqlock: + +Answer to Quick Quiz: + Why is it so important that updates be rare when using seqlock? + + The reason that it is important that updates be rare when + using seqlock is that frequent updates can livelock readers. + One way to avoid this problem is to assign a seqlock for + each array entry rather than to the entire array. diff --git a/Documentation/RCU/arrayRCU.txt b/Documentation/RCU/arrayRCU.txt deleted file mode 100644 index f05a9afb2c39..000000000000 --- a/Documentation/RCU/arrayRCU.txt +++ /dev/null @@ -1,153 +0,0 @@ -Using RCU to Protect Read-Mostly Arrays - - -Although RCU is more commonly used to protect linked lists, it can -also be used to protect arrays. Three situations are as follows: - -1. Hash Tables - -2. Static Arrays - -3. Resizeable Arrays - -Each of these three situations involves an RCU-protected pointer to an -array that is separately indexed. It might be tempting to consider use -of RCU to instead protect the index into an array, however, this use -case is -not- supported. The problem with RCU-protected indexes into -arrays is that compilers can play way too many optimization games with -integers, which means that the rules governing handling of these indexes -are far more trouble than they are worth. If RCU-protected indexes into -arrays prove to be particularly valuable (which they have not thus far), -explicit cooperation from the compiler will be required to permit them -to be safely used. - -That aside, each of the three RCU-protected pointer situations are -described in the following sections. - - -Situation 1: Hash Tables - -Hash tables are often implemented as an array, where each array entry -has a linked-list hash chain. Each hash chain can be protected by RCU -as described in the listRCU.txt document. This approach also applies -to other array-of-list situations, such as radix trees. - - -Situation 2: Static Arrays - -Static arrays, where the data (rather than a pointer to the data) is -located in each array element, and where the array is never resized, -have not been used with RCU. Rik van Riel recommends using seqlock in -this situation, which would also have minimal read-side overhead as long -as updates are rare. - -Quick Quiz: Why is it so important that updates be rare when - using seqlock? - - -Situation 3: Resizeable Arrays - -Use of RCU for resizeable arrays is demonstrated by the grow_ary() -function formerly used by the System V IPC code. The array is used -to map from semaphore, message-queue, and shared-memory IDs to the data -structure that represents the corresponding IPC construct. The grow_ary() -function does not acquire any locks; instead its caller must hold the -ids->sem semaphore. - -The grow_ary() function, shown below, does some limit checks, allocates a -new ipc_id_ary, copies the old to the new portion of the new, initializes -the remainder of the new, updates the ids->entries pointer to point to -the new array, and invokes ipc_rcu_putref() to free up the old array. -Note that rcu_assign_pointer() is used to update the ids->entries pointer, -which includes any memory barriers required on whatever architecture -you are running on. - - static int grow_ary(struct ipc_ids* ids, int newsize) - { - struct ipc_id_ary* new; - struct ipc_id_ary* old; - int i; - int size = ids->entries->size; - - if(newsize > IPCMNI) - newsize = IPCMNI; - if(newsize <= size) - return newsize; - - new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize + - sizeof(struct ipc_id_ary)); - if(new == NULL) - return size; - new->size = newsize; - memcpy(new->p, ids->entries->p, - sizeof(struct kern_ipc_perm *)*size + - sizeof(struct ipc_id_ary)); - for(i=size;ip[i] = NULL; - } - old = ids->entries; - - /* - * Use rcu_assign_pointer() to make sure the memcpyed - * contents of the new array are visible before the new - * array becomes visible. - */ - rcu_assign_pointer(ids->entries, new); - - ipc_rcu_putref(old); - return newsize; - } - -The ipc_rcu_putref() function decrements the array's reference count -and then, if the reference count has dropped to zero, uses call_rcu() -to free the array after a grace period has elapsed. - -The array is traversed by the ipc_lock() function. This function -indexes into the array under the protection of rcu_read_lock(), -using rcu_dereference() to pick up the pointer to the array so -that it may later safely be dereferenced -- memory barriers are -required on the Alpha CPU. Since the size of the array is stored -with the array itself, there can be no array-size mismatches, so -a simple check suffices. The pointer to the structure corresponding -to the desired IPC object is placed in "out", with NULL indicating -a non-existent entry. After acquiring "out->lock", the "out->deleted" -flag indicates whether the IPC object is in the process of being -deleted, and, if not, the pointer is returned. - - struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id) - { - struct kern_ipc_perm* out; - int lid = id % SEQ_MULTIPLIER; - struct ipc_id_ary* entries; - - rcu_read_lock(); - entries = rcu_dereference(ids->entries); - if(lid >= entries->size) { - rcu_read_unlock(); - return NULL; - } - out = entries->p[lid]; - if(out == NULL) { - rcu_read_unlock(); - return NULL; - } - spin_lock(&out->lock); - - /* ipc_rmid() may have already freed the ID while ipc_lock - * was spinning: here verify that the structure is still valid - */ - if (out->deleted) { - spin_unlock(&out->lock); - rcu_read_unlock(); - return NULL; - } - return out; - } - - -Answer to Quick Quiz: - - The reason that it is important that updates be rare when - using seqlock is that frequent updates can livelock readers. - One way to avoid this problem is to assign a seqlock for - each array entry rather than to the entire array. diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst index 5c99185710fa..8d20d44f8fd4 100644 --- a/Documentation/RCU/index.rst +++ b/Documentation/RCU/index.rst @@ -7,6 +7,7 @@ RCU concepts .. toctree:: :maxdepth: 3 + arrayRCU rcu listRCU UP -- cgit v1.2.3 From 6705cae433cffc37b183ded6ca9fe5c6d8ae8a9d Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Tue, 29 Oct 2019 03:12:52 +0530 Subject: doc: Converted NMI-RCU.txt to NMI-RCU.rst. This patch converts NMI-RCU from txt to rst format. Also adds NMI-RCU in the index.rst file. Signed-off-by: Madhuparna Bhowmik [ paulmck: Apply feedback from Phong Tran. ] Tested-by: Phong Tran Signed-off-by: Paul E. McKenney --- Documentation/RCU/NMI-RCU.rst | 124 ++++++++++++++++++++++++++++++++++++++++++ Documentation/RCU/NMI-RCU.txt | 121 ----------------------------------------- Documentation/RCU/index.rst | 1 + 3 files changed, 125 insertions(+), 121 deletions(-) create mode 100644 Documentation/RCU/NMI-RCU.rst delete mode 100644 Documentation/RCU/NMI-RCU.txt (limited to 'Documentation') diff --git a/Documentation/RCU/NMI-RCU.rst b/Documentation/RCU/NMI-RCU.rst new file mode 100644 index 000000000000..180958388ff9 --- /dev/null +++ b/Documentation/RCU/NMI-RCU.rst @@ -0,0 +1,124 @@ +.. _NMI_rcu_doc: + +Using RCU to Protect Dynamic NMI Handlers +========================================= + + +Although RCU is usually used to protect read-mostly data structures, +it is possible to use RCU to provide dynamic non-maskable interrupt +handlers, as well as dynamic irq handlers. This document describes +how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer +work in "arch/x86/oprofile/nmi_timer_int.c" and in +"arch/x86/kernel/traps.c". + +The relevant pieces of code are listed below, each followed by a +brief explanation:: + + static int dummy_nmi_callback(struct pt_regs *regs, int cpu) + { + return 0; + } + +The dummy_nmi_callback() function is a "dummy" NMI handler that does +nothing, but returns zero, thus saying that it did nothing, allowing +the NMI handler to take the default machine-specific action:: + + static nmi_callback_t nmi_callback = dummy_nmi_callback; + +This nmi_callback variable is a global function pointer to the current +NMI handler:: + + void do_nmi(struct pt_regs * regs, long error_code) + { + int cpu; + + nmi_enter(); + + cpu = smp_processor_id(); + ++nmi_count(cpu); + + if (!rcu_dereference_sched(nmi_callback)(regs, cpu)) + default_do_nmi(regs); + + nmi_exit(); + } + +The do_nmi() function processes each NMI. It first disables preemption +in the same way that a hardware irq would, then increments the per-CPU +count of NMIs. It then invokes the NMI handler stored in the nmi_callback +function pointer. If this handler returns zero, do_nmi() invokes the +default_do_nmi() function to handle a machine-specific NMI. Finally, +preemption is restored. + +In theory, rcu_dereference_sched() is not needed, since this code runs +only on i386, which in theory does not need rcu_dereference_sched() +anyway. However, in practice it is a good documentation aid, particularly +for anyone attempting to do something similar on Alpha or on systems +with aggressive optimizing compilers. + +Quick Quiz: + Why might the rcu_dereference_sched() be necessary on Alpha, given that the code referenced by the pointer is read-only? + +:ref:`Answer to Quick Quiz ` + +Back to the discussion of NMI and RCU:: + + void set_nmi_callback(nmi_callback_t callback) + { + rcu_assign_pointer(nmi_callback, callback); + } + +The set_nmi_callback() function registers an NMI handler. Note that any +data that is to be used by the callback must be initialized up -before- +the call to set_nmi_callback(). On architectures that do not order +writes, the rcu_assign_pointer() ensures that the NMI handler sees the +initialized values:: + + void unset_nmi_callback(void) + { + rcu_assign_pointer(nmi_callback, dummy_nmi_callback); + } + +This function unregisters an NMI handler, restoring the original +dummy_nmi_handler(). However, there may well be an NMI handler +currently executing on some other CPU. We therefore cannot free +up any data structures used by the old NMI handler until execution +of it completes on all other CPUs. + +One way to accomplish this is via synchronize_rcu(), perhaps as +follows:: + + unset_nmi_callback(); + synchronize_rcu(); + kfree(my_nmi_data); + +This works because (as of v4.20) synchronize_rcu() blocks until all +CPUs complete any preemption-disabled segments of code that they were +executing. +Since NMI handlers disable preemption, synchronize_rcu() is guaranteed +not to return until all ongoing NMI handlers exit. It is therefore safe +to free up the handler's data as soon as synchronize_rcu() returns. + +Important note: for this to work, the architecture in question must +invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively. + +.. _answer_quick_quiz_NMI: + +Answer to Quick Quiz: + Why might the rcu_dereference_sched() be necessary on Alpha, given that the code referenced by the pointer is read-only? + + The caller to set_nmi_callback() might well have + initialized some data that is to be used by the new NMI + handler. In this case, the rcu_dereference_sched() would + be needed, because otherwise a CPU that received an NMI + just after the new handler was set might see the pointer + to the new NMI handler, but the old pre-initialized + version of the handler's data. + + This same sad story can happen on other CPUs when using + a compiler with aggressive pointer-value speculation + optimizations. + + More important, the rcu_dereference_sched() makes it + clear to someone reading the code that the pointer is + being protected by RCU-sched. diff --git a/Documentation/RCU/NMI-RCU.txt b/Documentation/RCU/NMI-RCU.txt deleted file mode 100644 index 881353fd5bff..000000000000 --- a/Documentation/RCU/NMI-RCU.txt +++ /dev/null @@ -1,121 +0,0 @@ -Using RCU to Protect Dynamic NMI Handlers - - -Although RCU is usually used to protect read-mostly data structures, -it is possible to use RCU to provide dynamic non-maskable interrupt -handlers, as well as dynamic irq handlers. This document describes -how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer -work in "arch/x86/oprofile/nmi_timer_int.c" and in -"arch/x86/kernel/traps.c". - -The relevant pieces of code are listed below, each followed by a -brief explanation. - - static int dummy_nmi_callback(struct pt_regs *regs, int cpu) - { - return 0; - } - -The dummy_nmi_callback() function is a "dummy" NMI handler that does -nothing, but returns zero, thus saying that it did nothing, allowing -the NMI handler to take the default machine-specific action. - - static nmi_callback_t nmi_callback = dummy_nmi_callback; - -This nmi_callback variable is a global function pointer to the current -NMI handler. - - void do_nmi(struct pt_regs * regs, long error_code) - { - int cpu; - - nmi_enter(); - - cpu = smp_processor_id(); - ++nmi_count(cpu); - - if (!rcu_dereference_sched(nmi_callback)(regs, cpu)) - default_do_nmi(regs); - - nmi_exit(); - } - -The do_nmi() function processes each NMI. It first disables preemption -in the same way that a hardware irq would, then increments the per-CPU -count of NMIs. It then invokes the NMI handler stored in the nmi_callback -function pointer. If this handler returns zero, do_nmi() invokes the -default_do_nmi() function to handle a machine-specific NMI. Finally, -preemption is restored. - -In theory, rcu_dereference_sched() is not needed, since this code runs -only on i386, which in theory does not need rcu_dereference_sched() -anyway. However, in practice it is a good documentation aid, particularly -for anyone attempting to do something similar on Alpha or on systems -with aggressive optimizing compilers. - -Quick Quiz: Why might the rcu_dereference_sched() be necessary on Alpha, - given that the code referenced by the pointer is read-only? - - -Back to the discussion of NMI and RCU... - - void set_nmi_callback(nmi_callback_t callback) - { - rcu_assign_pointer(nmi_callback, callback); - } - -The set_nmi_callback() function registers an NMI handler. Note that any -data that is to be used by the callback must be initialized up -before- -the call to set_nmi_callback(). On architectures that do not order -writes, the rcu_assign_pointer() ensures that the NMI handler sees the -initialized values. - - void unset_nmi_callback(void) - { - rcu_assign_pointer(nmi_callback, dummy_nmi_callback); - } - -This function unregisters an NMI handler, restoring the original -dummy_nmi_handler(). However, there may well be an NMI handler -currently executing on some other CPU. We therefore cannot free -up any data structures used by the old NMI handler until execution -of it completes on all other CPUs. - -One way to accomplish this is via synchronize_rcu(), perhaps as -follows: - - unset_nmi_callback(); - synchronize_rcu(); - kfree(my_nmi_data); - -This works because (as of v4.20) synchronize_rcu() blocks until all -CPUs complete any preemption-disabled segments of code that they were -executing. -Since NMI handlers disable preemption, synchronize_rcu() is guaranteed -not to return until all ongoing NMI handlers exit. It is therefore safe -to free up the handler's data as soon as synchronize_rcu() returns. - -Important note: for this to work, the architecture in question must -invoke nmi_enter() and nmi_exit() on NMI entry and exit, respectively. - - -Answer to Quick Quiz - - Why might the rcu_dereference_sched() be necessary on Alpha, given - that the code referenced by the pointer is read-only? - - Answer: The caller to set_nmi_callback() might well have - initialized some data that is to be used by the new NMI - handler. In this case, the rcu_dereference_sched() would - be needed, because otherwise a CPU that received an NMI - just after the new handler was set might see the pointer - to the new NMI handler, but the old pre-initialized - version of the handler's data. - - This same sad story can happen on other CPUs when using - a compiler with aggressive pointer-value speculation - optimizations. - - More important, the rcu_dereference_sched() makes it - clear to someone reading the code that the pointer is - being protected by RCU-sched. diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst index 8d20d44f8fd4..627128c230dc 100644 --- a/Documentation/RCU/index.rst +++ b/Documentation/RCU/index.rst @@ -10,6 +10,7 @@ RCU concepts arrayRCU rcu listRCU + NMI-RCU UP Design/Memory-Ordering/Tree-RCU-Memory-Ordering -- cgit v1.2.3 From 5e1bc932818f74082e8331b59aa550101ead08e0 Mon Sep 17 00:00:00 2001 From: Phong Tran Date: Wed, 6 Nov 2019 20:09:50 +0700 Subject: doc: Convert whatisRCU.txt to .rst This commit updates whatisRCU.txt to the new .rst format. This change includes: - Formatting bullet lists - Adding literal blocks - Links from table of contents to corresponding sections - Links to external documents - Reformat quick quizzes Signed-off-by: Phong Tran Tested-by: Madhuparna Bhowmik [ tranmanphong: Apply Amol Grover feedback. ] Reviewed-by: Amol Grover Signed-off-by: Paul E. McKenney --- Documentation/RCU/index.rst | 1 + Documentation/RCU/whatisRCU.rst | 1149 +++++++++++++++++++++++++++++++++++++++ Documentation/RCU/whatisRCU.txt | 1079 ------------------------------------ 3 files changed, 1150 insertions(+), 1079 deletions(-) create mode 100644 Documentation/RCU/whatisRCU.rst delete mode 100644 Documentation/RCU/whatisRCU.txt (limited to 'Documentation') diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst index 627128c230dc..b9b11481c727 100644 --- a/Documentation/RCU/index.rst +++ b/Documentation/RCU/index.rst @@ -8,6 +8,7 @@ RCU concepts :maxdepth: 3 arrayRCU + whatisRCU rcu listRCU NMI-RCU diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst new file mode 100644 index 000000000000..2f6f6ebbc8b0 --- /dev/null +++ b/Documentation/RCU/whatisRCU.rst @@ -0,0 +1,1149 @@ +.. _whatisrcu_doc: + +What is RCU? -- "Read, Copy, Update" +====================================== + +Please note that the "What is RCU?" LWN series is an excellent place +to start learning about RCU: + +| 1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ +| 2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ +| 3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ +| 4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ +| 2010 Big API Table http://lwn.net/Articles/419086/ +| 5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ +| 2014 Big API Table http://lwn.net/Articles/609973/ + + +What is RCU? + +RCU is a synchronization mechanism that was added to the Linux kernel +during the 2.5 development effort that is optimized for read-mostly +situations. Although RCU is actually quite simple once you understand it, +getting there can sometimes be a challenge. Part of the problem is that +most of the past descriptions of RCU have been written with the mistaken +assumption that there is "one true way" to describe RCU. Instead, +the experience has been that different people must take different paths +to arrive at an understanding of RCU. This document provides several +different paths, as follows: + +:ref:`1. RCU OVERVIEW <1_whatisRCU>` + +:ref:`2. WHAT IS RCU'S CORE API? <2_whatisRCU>` + +:ref:`3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? <3_whatisRCU>` + +:ref:`4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? <4_whatisRCU>` + +:ref:`5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? <5_whatisRCU>` + +:ref:`6. ANALOGY WITH READER-WRITER LOCKING <6_whatisRCU>` + +:ref:`7. FULL LIST OF RCU APIs <7_whatisRCU>` + +:ref:`8. ANSWERS TO QUICK QUIZZES <8_whatisRCU>` + +People who prefer starting with a conceptual overview should focus on +Section 1, though most readers will profit by reading this section at +some point. People who prefer to start with an API that they can then +experiment with should focus on Section 2. People who prefer to start +with example uses should focus on Sections 3 and 4. People who need to +understand the RCU implementation should focus on Section 5, then dive +into the kernel source code. People who reason best by analogy should +focus on Section 6. Section 7 serves as an index to the docbook API +documentation, and Section 8 is the traditional answer key. + +So, start with the section that makes the most sense to you and your +preferred method of learning. If you need to know everything about +everything, feel free to read the whole thing -- but if you are really +that type of person, you have perused the source code and will therefore +never need this document anyway. ;-) + +.. _1_whatisRCU: + +1. RCU OVERVIEW +---------------- + +The basic idea behind RCU is to split updates into "removal" and +"reclamation" phases. The removal phase removes references to data items +within a data structure (possibly by replacing them with references to +new versions of these data items), and can run concurrently with readers. +The reason that it is safe to run the removal phase concurrently with +readers is the semantics of modern CPUs guarantee that readers will see +either the old or the new version of the data structure rather than a +partially updated reference. The reclamation phase does the work of reclaiming +(e.g., freeing) the data items removed from the data structure during the +removal phase. Because reclaiming data items can disrupt any readers +concurrently referencing those data items, the reclamation phase must +not start until readers no longer hold references to those data items. + +Splitting the update into removal and reclamation phases permits the +updater to perform the removal phase immediately, and to defer the +reclamation phase until all readers active during the removal phase have +completed, either by blocking until they finish or by registering a +callback that is invoked after they finish. Only readers that are active +during the removal phase need be considered, because any reader starting +after the removal phase will be unable to gain a reference to the removed +data items, and therefore cannot be disrupted by the reclamation phase. + +So the typical RCU update sequence goes something like the following: + +a. Remove pointers to a data structure, so that subsequent + readers cannot gain a reference to it. + +b. Wait for all previous readers to complete their RCU read-side + critical sections. + +c. At this point, there cannot be any readers who hold references + to the data structure, so it now may safely be reclaimed + (e.g., kfree()d). + +Step (b) above is the key idea underlying RCU's deferred destruction. +The ability to wait until all readers are done allows RCU readers to +use much lighter-weight synchronization, in some cases, absolutely no +synchronization at all. In contrast, in more conventional lock-based +schemes, readers must use heavy-weight synchronization in order to +prevent an updater from deleting the data structure out from under them. +This is because lock-based updaters typically update data items in place, +and must therefore exclude readers. In contrast, RCU-based updaters +typically take advantage of the fact that writes to single aligned +pointers are atomic on modern CPUs, allowing atomic insertion, removal, +and replacement of data items in a linked structure without disrupting +readers. Concurrent RCU readers can then continue accessing the old +versions, and can dispense with the atomic operations, memory barriers, +and communications cache misses that are so expensive on present-day +SMP computer systems, even in absence of lock contention. + +In the three-step procedure shown above, the updater is performing both +the removal and the reclamation step, but it is often helpful for an +entirely different thread to do the reclamation, as is in fact the case +in the Linux kernel's directory-entry cache (dcache). Even if the same +thread performs both the update step (step (a) above) and the reclamation +step (step (c) above), it is often helpful to think of them separately. +For example, RCU readers and updaters need not communicate at all, +but RCU provides implicit low-overhead communication between readers +and reclaimers, namely, in step (b) above. + +So how the heck can a reclaimer tell when a reader is done, given +that readers are not doing any sort of synchronization operations??? +Read on to learn about how RCU's API makes this easy. + +.. _2_whatisRCU: + +2. WHAT IS RCU'S CORE API? +--------------------------- + +The core RCU API is quite small: + +a. rcu_read_lock() +b. rcu_read_unlock() +c. synchronize_rcu() / call_rcu() +d. rcu_assign_pointer() +e. rcu_dereference() + +There are many other members of the RCU API, but the rest can be +expressed in terms of these five, though most implementations instead +express synchronize_rcu() in terms of the call_rcu() callback API. + +The five core RCU APIs are described below, the other 18 will be enumerated +later. See the kernel docbook documentation for more info, or look directly +at the function header comments. + +rcu_read_lock() +^^^^^^^^^^^^^^^ + void rcu_read_lock(void); + + Used by a reader to inform the reclaimer that the reader is + entering an RCU read-side critical section. It is illegal + to block while in an RCU read-side critical section, though + kernels built with CONFIG_PREEMPT_RCU can preempt RCU + read-side critical sections. Any RCU-protected data structure + accessed during an RCU read-side critical section is guaranteed to + remain unreclaimed for the full duration of that critical section. + Reference counts may be used in conjunction with RCU to maintain + longer-term references to data structures. + +rcu_read_unlock() +^^^^^^^^^^^^^^^^^ + void rcu_read_unlock(void); + + Used by a reader to inform the reclaimer that the reader is + exiting an RCU read-side critical section. Note that RCU + read-side critical sections may be nested and/or overlapping. + +synchronize_rcu() +^^^^^^^^^^^^^^^^^ + void synchronize_rcu(void); + + Marks the end of updater code and the beginning of reclaimer + code. It does this by blocking until all pre-existing RCU + read-side critical sections on all CPUs have completed. + Note that synchronize_rcu() will **not** necessarily wait for + any subsequent RCU read-side critical sections to complete. + For example, consider the following sequence of events:: + + CPU 0 CPU 1 CPU 2 + ----------------- ------------------------- --------------- + 1. rcu_read_lock() + 2. enters synchronize_rcu() + 3. rcu_read_lock() + 4. rcu_read_unlock() + 5. exits synchronize_rcu() + 6. rcu_read_unlock() + + To reiterate, synchronize_rcu() waits only for ongoing RCU + read-side critical sections to complete, not necessarily for + any that begin after synchronize_rcu() is invoked. + + Of course, synchronize_rcu() does not necessarily return + **immediately** after the last pre-existing RCU read-side critical + section completes. For one thing, there might well be scheduling + delays. For another thing, many RCU implementations process + requests in batches in order to improve efficiencies, which can + further delay synchronize_rcu(). + + Since synchronize_rcu() is the API that must figure out when + readers are done, its implementation is key to RCU. For RCU + to be useful in all but the most read-intensive situations, + synchronize_rcu()'s overhead must also be quite small. + + The call_rcu() API is a callback form of synchronize_rcu(), + and is described in more detail in a later section. Instead of + blocking, it registers a function and argument which are invoked + after all ongoing RCU read-side critical sections have completed. + This callback variant is particularly useful in situations where + it is illegal to block or where update-side performance is + critically important. + + However, the call_rcu() API should not be used lightly, as use + of the synchronize_rcu() API generally results in simpler code. + In addition, the synchronize_rcu() API has the nice property + of automatically limiting update rate should grace periods + be delayed. This property results in system resilience in face + of denial-of-service attacks. Code using call_rcu() should limit + update rate in order to gain this same sort of resilience. See + checklist.txt for some approaches to limiting the update rate. + +rcu_assign_pointer() +^^^^^^^^^^^^^^^^^^^^ + void rcu_assign_pointer(p, typeof(p) v); + + Yes, rcu_assign_pointer() **is** implemented as a macro, though it + would be cool to be able to declare a function in this manner. + (Compiler experts will no doubt disagree.) + + The updater uses this function to assign a new value to an + RCU-protected pointer, in order to safely communicate the change + in value from the updater to the reader. This macro does not + evaluate to an rvalue, but it does execute any memory-barrier + instructions required for a given CPU architecture. + + Perhaps just as important, it serves to document (1) which + pointers are protected by RCU and (2) the point at which a + given structure becomes accessible to other CPUs. That said, + rcu_assign_pointer() is most frequently used indirectly, via + the _rcu list-manipulation primitives such as list_add_rcu(). + +rcu_dereference() +^^^^^^^^^^^^^^^^^ + typeof(p) rcu_dereference(p); + + Like rcu_assign_pointer(), rcu_dereference() must be implemented + as a macro. + + The reader uses rcu_dereference() to fetch an RCU-protected + pointer, which returns a value that may then be safely + dereferenced. Note that rcu_dereference() does not actually + dereference the pointer, instead, it protects the pointer for + later dereferencing. It also executes any needed memory-barrier + instructions for a given CPU architecture. Currently, only Alpha + needs memory barriers within rcu_dereference() -- on other CPUs, + it compiles to nothing, not even a compiler directive. + + Common coding practice uses rcu_dereference() to copy an + RCU-protected pointer to a local variable, then dereferences + this local variable, for example as follows:: + + p = rcu_dereference(head.next); + return p->data; + + However, in this case, one could just as easily combine these + into one statement:: + + return rcu_dereference(head.next)->data; + + If you are going to be fetching multiple fields from the + RCU-protected structure, using the local variable is of + course preferred. Repeated rcu_dereference() calls look + ugly, do not guarantee that the same pointer will be returned + if an update happened while in the critical section, and incur + unnecessary overhead on Alpha CPUs. + + Note that the value returned by rcu_dereference() is valid + only within the enclosing RCU read-side critical section [1]_. + For example, the following is **not** legal:: + + rcu_read_lock(); + p = rcu_dereference(head.next); + rcu_read_unlock(); + x = p->address; /* BUG!!! */ + rcu_read_lock(); + y = p->data; /* BUG!!! */ + rcu_read_unlock(); + + Holding a reference from one RCU read-side critical section + to another is just as illegal as holding a reference from + one lock-based critical section to another! Similarly, + using a reference outside of the critical section in which + it was acquired is just as illegal as doing so with normal + locking. + + As with rcu_assign_pointer(), an important function of + rcu_dereference() is to document which pointers are protected by + RCU, in particular, flagging a pointer that is subject to changing + at any time, including immediately after the rcu_dereference(). + And, again like rcu_assign_pointer(), rcu_dereference() is + typically used indirectly, via the _rcu list-manipulation + primitives, such as list_for_each_entry_rcu() [2]_. + +.. [1] The variant rcu_dereference_protected() can be used outside + of an RCU read-side critical section as long as the usage is + protected by locks acquired by the update-side code. This variant + avoids the lockdep warning that would happen when using (for + example) rcu_dereference() without rcu_read_lock() protection. + Using rcu_dereference_protected() also has the advantage + of permitting compiler optimizations that rcu_dereference() + must prohibit. The rcu_dereference_protected() variant takes + a lockdep expression to indicate which locks must be acquired + by the caller. If the indicated protection is not provided, + a lockdep splat is emitted. See Documentation/RCU/Design/Requirements/Requirements.rst + and the API's code comments for more details and example usage. + +.. [2] If the list_for_each_entry_rcu() instance might be used by + update-side code as well as by RCU readers, then an additional + lockdep expression can be added to its list of arguments. + For example, given an additional "lock_is_held(&mylock)" argument, + the RCU lockdep code would complain only if this instance was + invoked outside of an RCU read-side critical section and without + the protection of mylock. + +The following diagram shows how each API communicates among the +reader, updater, and reclaimer. +:: + + + rcu_assign_pointer() + +--------+ + +---------------------->| reader |---------+ + | +--------+ | + | | | + | | | Protect: + | | | rcu_read_lock() + | | | rcu_read_unlock() + | rcu_dereference() | | + +---------+ | | + | updater |<----------------+ | + +---------+ V + | +-----------+ + +----------------------------------->| reclaimer | + +-----------+ + Defer: + synchronize_rcu() & call_rcu() + + +The RCU infrastructure observes the time sequence of rcu_read_lock(), +rcu_read_unlock(), synchronize_rcu(), and call_rcu() invocations in +order to determine when (1) synchronize_rcu() invocations may return +to their callers and (2) call_rcu() callbacks may be invoked. Efficient +implementations of the RCU infrastructure make heavy use of batching in +order to amortize their overhead over many uses of the corresponding APIs. + +There are at least three flavors of RCU usage in the Linux kernel. The diagram +above shows the most common one. On the updater side, the rcu_assign_pointer(), +sychronize_rcu() and call_rcu() primitives used are the same for all three +flavors. However for protection (on the reader side), the primitives used vary +depending on the flavor: + +a. rcu_read_lock() / rcu_read_unlock() + rcu_dereference() + +b. rcu_read_lock_bh() / rcu_read_unlock_bh() + local_bh_disable() / local_bh_enable() + rcu_dereference_bh() + +c. rcu_read_lock_sched() / rcu_read_unlock_sched() + preempt_disable() / preempt_enable() + local_irq_save() / local_irq_restore() + hardirq enter / hardirq exit + NMI enter / NMI exit + rcu_dereference_sched() + +These three flavors are used as follows: + +a. RCU applied to normal data structures. + +b. RCU applied to networking data structures that may be subjected + to remote denial-of-service attacks. + +c. RCU applied to scheduler and interrupt/NMI-handler tasks. + +Again, most uses will be of (a). The (b) and (c) cases are important +for specialized uses, but are relatively uncommon. + +.. _3_whatisRCU: + +3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? +----------------------------------------------- + +This section shows a simple use of the core RCU API to protect a +global pointer to a dynamically allocated structure. More-typical +uses of RCU may be found in :ref:`listRCU.rst `, +:ref:`arrayRCU.rst `, and :ref:`NMI-RCU.rst `. +:: + + struct foo { + int a; + char b; + long c; + }; + DEFINE_SPINLOCK(foo_mutex); + + struct foo __rcu *gbl_foo; + + /* + * Create a new struct foo that is the same as the one currently + * pointed to by gbl_foo, except that field "a" is replaced + * with "new_a". Points gbl_foo to the new structure, and + * frees up the old structure after a grace period. + * + * Uses rcu_assign_pointer() to ensure that concurrent readers + * see the initialized version of the new structure. + * + * Uses synchronize_rcu() to ensure that any readers that might + * have references to the old structure complete before freeing + * the old structure. + */ + void foo_update_a(int new_a) + { + struct foo *new_fp; + struct foo *old_fp; + + new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL); + spin_lock(&foo_mutex); + old_fp = rcu_dereference_protected(gbl_foo, lockdep_is_held(&foo_mutex)); + *new_fp = *old_fp; + new_fp->a = new_a; + rcu_assign_pointer(gbl_foo, new_fp); + spin_unlock(&foo_mutex); + synchronize_rcu(); + kfree(old_fp); + } + + /* + * Return the value of field "a" of the current gbl_foo + * structure. Use rcu_read_lock() and rcu_read_unlock() + * to ensure that the structure does not get deleted out + * from under us, and use rcu_dereference() to ensure that + * we see the initialized version of the structure (important + * for DEC Alpha and for people reading the code). + */ + int foo_get_a(void) + { + int retval; + + rcu_read_lock(); + retval = rcu_dereference(gbl_foo)->a; + rcu_read_unlock(); + return retval; + } + +So, to sum up: + +- Use rcu_read_lock() and rcu_read_unlock() to guard RCU + read-side critical sections. + +- Within an RCU read-side critical section, use rcu_dereference() + to dereference RCU-protected pointers. + +- Use some solid scheme (such as locks or semaphores) to + keep concurrent updates from interfering with each other. + +- Use rcu_assign_pointer() to update an RCU-protected pointer. + This primitive protects concurrent readers from the updater, + **not** concurrent updates from each other! You therefore still + need to use locking (or something similar) to keep concurrent + rcu_assign_pointer() primitives from interfering with each other. + +- Use synchronize_rcu() **after** removing a data element from an + RCU-protected data structure, but **before** reclaiming/freeing + the data element, in order to wait for the completion of all + RCU read-side critical sections that might be referencing that + data item. + +See checklist.txt for additional rules to follow when using RCU. +And again, more-typical uses of RCU may be found in :ref:`listRCU.rst +`, :ref:`arrayRCU.rst `, and :ref:`NMI-RCU.rst +`. + +.. _4_whatisRCU: + +4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? +-------------------------------------------- + +In the example above, foo_update_a() blocks until a grace period elapses. +This is quite simple, but in some cases one cannot afford to wait so +long -- there might be other high-priority work to be done. + +In such cases, one uses call_rcu() rather than synchronize_rcu(). +The call_rcu() API is as follows:: + + void call_rcu(struct rcu_head * head, + void (*func)(struct rcu_head *head)); + +This function invokes func(head) after a grace period has elapsed. +This invocation might happen from either softirq or process context, +so the function is not permitted to block. The foo struct needs to +have an rcu_head structure added, perhaps as follows:: + + struct foo { + int a; + char b; + long c; + struct rcu_head rcu; + }; + +The foo_update_a() function might then be written as follows:: + + /* + * Create a new struct foo that is the same as the one currently + * pointed to by gbl_foo, except that field "a" is replaced + * with "new_a". Points gbl_foo to the new structure, and + * frees up the old structure after a grace period. + * + * Uses rcu_assign_pointer() to ensure that concurrent readers + * see the initialized version of the new structure. + * + * Uses call_rcu() to ensure that any readers that might have + * references to the old structure complete before freeing the + * old structure. + */ + void foo_update_a(int new_a) + { + struct foo *new_fp; + struct foo *old_fp; + + new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL); + spin_lock(&foo_mutex); + old_fp = rcu_dereference_protected(gbl_foo, lockdep_is_held(&foo_mutex)); + *new_fp = *old_fp; + new_fp->a = new_a; + rcu_assign_pointer(gbl_foo, new_fp); + spin_unlock(&foo_mutex); + call_rcu(&old_fp->rcu, foo_reclaim); + } + +The foo_reclaim() function might appear as follows:: + + void foo_reclaim(struct rcu_head *rp) + { + struct foo *fp = container_of(rp, struct foo, rcu); + + foo_cleanup(fp->a); + + kfree(fp); + } + +The container_of() primitive is a macro that, given a pointer into a +struct, the type of the struct, and the pointed-to field within the +struct, returns a pointer to the beginning of the struct. + +The use of call_rcu() permits the caller of foo_update_a() to +immediately regain control, without needing to worry further about the +old version of the newly updated element. It also clearly shows the +RCU distinction between updater, namely foo_update_a(), and reclaimer, +namely foo_reclaim(). + +The summary of advice is the same as for the previous section, except +that we are now using call_rcu() rather than synchronize_rcu(): + +- Use call_rcu() **after** removing a data element from an + RCU-protected data structure in order to register a callback + function that will be invoked after the completion of all RCU + read-side critical sections that might be referencing that + data item. + +If the callback for call_rcu() is not doing anything more than calling +kfree() on the structure, you can use kfree_rcu() instead of call_rcu() +to avoid having to write your own callback:: + + kfree_rcu(old_fp, rcu); + +Again, see checklist.txt for additional rules governing the use of RCU. + +.. _5_whatisRCU: + +5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? +------------------------------------------------ + +One of the nice things about RCU is that it has extremely simple "toy" +implementations that are a good first step towards understanding the +production-quality implementations in the Linux kernel. This section +presents two such "toy" implementations of RCU, one that is implemented +in terms of familiar locking primitives, and another that more closely +resembles "classic" RCU. Both are way too simple for real-world use, +lacking both functionality and performance. However, they are useful +in getting a feel for how RCU works. See kernel/rcu/update.c for a +production-quality implementation, and see: + + http://www.rdrop.com/users/paulmck/RCU + +for papers describing the Linux kernel RCU implementation. The OLS'01 +and OLS'02 papers are a good introduction, and the dissertation provides +more details on the current implementation as of early 2004. + + +5A. "TOY" IMPLEMENTATION #1: LOCKING +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This section presents a "toy" RCU implementation that is based on +familiar locking primitives. Its overhead makes it a non-starter for +real-life use, as does its lack of scalability. It is also unsuitable +for realtime use, since it allows scheduling latency to "bleed" from +one read-side critical section to another. It also assumes recursive +reader-writer locks: If you try this with non-recursive locks, and +you allow nested rcu_read_lock() calls, you can deadlock. + +However, it is probably the easiest implementation to relate to, so is +a good starting point. + +It is extremely simple:: + + static DEFINE_RWLOCK(rcu_gp_mutex); + + void rcu_read_lock(void) + { + read_lock(&rcu_gp_mutex); + } + + void rcu_read_unlock(void) + { + read_unlock(&rcu_gp_mutex); + } + + void synchronize_rcu(void) + { + write_lock(&rcu_gp_mutex); + smp_mb__after_spinlock(); + write_unlock(&rcu_gp_mutex); + } + +[You can ignore rcu_assign_pointer() and rcu_dereference() without missing +much. But here are simplified versions anyway. And whatever you do, +don't forget about them when submitting patches making use of RCU!]:: + + #define rcu_assign_pointer(p, v) \ + ({ \ + smp_store_release(&(p), (v)); \ + }) + + #define rcu_dereference(p) \ + ({ \ + typeof(p) _________p1 = READ_ONCE(p); \ + (_________p1); \ + }) + + +The rcu_read_lock() and rcu_read_unlock() primitive read-acquire +and release a global reader-writer lock. The synchronize_rcu() +primitive write-acquires this same lock, then releases it. This means +that once synchronize_rcu() exits, all RCU read-side critical sections +that were in progress before synchronize_rcu() was called are guaranteed +to have completed -- there is no way that synchronize_rcu() would have +been able to write-acquire the lock otherwise. The smp_mb__after_spinlock() +promotes synchronize_rcu() to a full memory barrier in compliance with +the "Memory-Barrier Guarantees" listed in: + + Documentation/RCU/Design/Requirements/Requirements.rst + +It is possible to nest rcu_read_lock(), since reader-writer locks may +be recursively acquired. Note also that rcu_read_lock() is immune +from deadlock (an important property of RCU). The reason for this is +that the only thing that can block rcu_read_lock() is a synchronize_rcu(). +But synchronize_rcu() does not acquire any locks while holding rcu_gp_mutex, +so there can be no deadlock cycle. + +.. _quiz_1: + +Quick Quiz #1: + Why is this argument naive? How could a deadlock + occur when using this algorithm in a real-world Linux + kernel? How could this deadlock be avoided? + +:ref:`Answers to Quick Quiz <8_whatisRCU>` + +5B. "TOY" EXAMPLE #2: CLASSIC RCU +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This section presents a "toy" RCU implementation that is based on +"classic RCU". It is also short on performance (but only for updates) and +on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT +kernels. The definitions of rcu_dereference() and rcu_assign_pointer() +are the same as those shown in the preceding section, so they are omitted. +:: + + void rcu_read_lock(void) { } + + void rcu_read_unlock(void) { } + + void synchronize_rcu(void) + { + int cpu; + + for_each_possible_cpu(cpu) + run_on(cpu); + } + +Note that rcu_read_lock() and rcu_read_unlock() do absolutely nothing. +This is the great strength of classic RCU in a non-preemptive kernel: +read-side overhead is precisely zero, at least on non-Alpha CPUs. +And there is absolutely no way that rcu_read_lock() can possibly +participate in a deadlock cycle! + +The implementation of synchronize_rcu() simply schedules itself on each +CPU in turn. The run_on() primitive can be implemented straightforwardly +in terms of the sched_setaffinity() primitive. Of course, a somewhat less +"toy" implementation would restore the affinity upon completion rather +than just leaving all tasks running on the last CPU, but when I said +"toy", I meant **toy**! + +So how the heck is this supposed to work??? + +Remember that it is illegal to block while in an RCU read-side critical +section. Therefore, if a given CPU executes a context switch, we know +that it must have completed all preceding RCU read-side critical sections. +Once **all** CPUs have executed a context switch, then **all** preceding +RCU read-side critical sections will have completed. + +So, suppose that we remove a data item from its structure and then invoke +synchronize_rcu(). Once synchronize_rcu() returns, we are guaranteed +that there are no RCU read-side critical sections holding a reference +to that data item, so we can safely reclaim it. + +.. _quiz_2: + +Quick Quiz #2: + Give an example where Classic RCU's read-side + overhead is **negative**. + +:ref:`Answers to Quick Quiz <8_whatisRCU>` + +.. _quiz_3: + +Quick Quiz #3: + If it is illegal to block in an RCU read-side + critical section, what the heck do you do in + PREEMPT_RT, where normal spinlocks can block??? + +:ref:`Answers to Quick Quiz <8_whatisRCU>` + +.. _6_whatisRCU: + +6. ANALOGY WITH READER-WRITER LOCKING +-------------------------------------- + +Although RCU can be used in many different ways, a very common use of +RCU is analogous to reader-writer locking. The following unified +diff shows how closely related RCU and reader-writer locking can be. +:: + + @@ -5,5 +5,5 @@ struct el { + int data; + /* Other data fields */ + }; + -rwlock_t listmutex; + +spinlock_t listmutex; + struct el head; + + @@ -13,15 +14,15 @@ + struct list_head *lp; + struct el *p; + + - read_lock(&listmutex); + - list_for_each_entry(p, head, lp) { + + rcu_read_lock(); + + list_for_each_entry_rcu(p, head, lp) { + if (p->key == key) { + *result = p->data; + - read_unlock(&listmutex); + + rcu_read_unlock(); + return 1; + } + } + - read_unlock(&listmutex); + + rcu_read_unlock(); + return 0; + } + + @@ -29,15 +30,16 @@ + { + struct el *p; + + - write_lock(&listmutex); + + spin_lock(&listmutex); + list_for_each_entry(p, head, lp) { + if (p->key == key) { + - list_del(&p->list); + - write_unlock(&listmutex); + + list_del_rcu(&p->list); + + spin_unlock(&listmutex); + + synchronize_rcu(); + kfree(p); + return 1; + } + } + - write_unlock(&listmutex); + + spin_unlock(&listmutex); + return 0; + } + +Or, for those who prefer a side-by-side listing:: + + 1 struct el { 1 struct el { + 2 struct list_head list; 2 struct list_head list; + 3 long key; 3 long key; + 4 spinlock_t mutex; 4 spinlock_t mutex; + 5 int data; 5 int data; + 6 /* Other data fields */ 6 /* Other data fields */ + 7 }; 7 }; + 8 rwlock_t listmutex; 8 spinlock_t listmutex; + 9 struct el head; 9 struct el head; + +:: + + 1 int search(long key, int *result) 1 int search(long key, int *result) + 2 { 2 { + 3 struct list_head *lp; 3 struct list_head *lp; + 4 struct el *p; 4 struct el *p; + 5 5 + 6 read_lock(&listmutex); 6 rcu_read_lock(); + 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, head, lp) { + 8 if (p->key == key) { 8 if (p->key == key) { + 9 *result = p->data; 9 *result = p->data; + 10 read_unlock(&listmutex); 10 rcu_read_unlock(); + 11 return 1; 11 return 1; + 12 } 12 } + 13 } 13 } + 14 read_unlock(&listmutex); 14 rcu_read_unlock(); + 15 return 0; 15 return 0; + 16 } 16 } + +:: + + 1 int delete(long key) 1 int delete(long key) + 2 { 2 { + 3 struct el *p; 3 struct el *p; + 4 4 + 5 write_lock(&listmutex); 5 spin_lock(&listmutex); + 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, lp) { + 7 if (p->key == key) { 7 if (p->key == key) { + 8 list_del(&p->list); 8 list_del_rcu(&p->list); + 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); + 10 synchronize_rcu(); + 10 kfree(p); 11 kfree(p); + 11 return 1; 12 return 1; + 12 } 13 } + 13 } 14 } + 14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); + 15 return 0; 16 return 0; + 16 } 17 } + +Either way, the differences are quite small. Read-side locking moves +to rcu_read_lock() and rcu_read_unlock, update-side locking moves from +a reader-writer lock to a simple spinlock, and a synchronize_rcu() +precedes the kfree(). + +However, there is one potential catch: the read-side and update-side +critical sections can now run concurrently. In many cases, this will +not be a problem, but it is necessary to check carefully regardless. +For example, if multiple independent list updates must be seen as +a single atomic update, converting to RCU will require special care. + +Also, the presence of synchronize_rcu() means that the RCU version of +delete() can now block. If this is a problem, there is a callback-based +mechanism that never blocks, namely call_rcu() or kfree_rcu(), that can +be used in place of synchronize_rcu(). + +.. _7_whatisRCU: + +7. FULL LIST OF RCU APIs +------------------------- + +The RCU APIs are documented in docbook-format header comments in the +Linux-kernel source code, but it helps to have a full list of the +APIs, since there does not appear to be a way to categorize them +in docbook. Here is the list, by category. + +RCU list traversal:: + + list_entry_rcu + list_first_entry_rcu + list_next_rcu + list_for_each_entry_rcu + list_for_each_entry_continue_rcu + list_for_each_entry_from_rcu + hlist_first_rcu + hlist_next_rcu + hlist_pprev_rcu + hlist_for_each_entry_rcu + hlist_for_each_entry_rcu_bh + hlist_for_each_entry_from_rcu + hlist_for_each_entry_continue_rcu + hlist_for_each_entry_continue_rcu_bh + hlist_nulls_first_rcu + hlist_nulls_for_each_entry_rcu + hlist_bl_first_rcu + hlist_bl_for_each_entry_rcu + +RCU pointer/list udate:: + + rcu_assign_pointer + list_add_rcu + list_add_tail_rcu + list_del_rcu + list_replace_rcu + hlist_add_behind_rcu + hlist_add_before_rcu + hlist_add_head_rcu + hlist_del_rcu + hlist_del_init_rcu + hlist_replace_rcu + list_splice_init_rcu() + hlist_nulls_del_init_rcu + hlist_nulls_del_rcu + hlist_nulls_add_head_rcu + hlist_bl_add_head_rcu + hlist_bl_del_init_rcu + hlist_bl_del_rcu + hlist_bl_set_first_rcu + +RCU:: + + Critical sections Grace period Barrier + + rcu_read_lock synchronize_net rcu_barrier + rcu_read_unlock synchronize_rcu + rcu_dereference synchronize_rcu_expedited + rcu_read_lock_held call_rcu + rcu_dereference_check kfree_rcu + rcu_dereference_protected + +bh:: + + Critical sections Grace period Barrier + + rcu_read_lock_bh call_rcu rcu_barrier + rcu_read_unlock_bh synchronize_rcu + [local_bh_disable] synchronize_rcu_expedited + [and friends] + rcu_dereference_bh + rcu_dereference_bh_check + rcu_dereference_bh_protected + rcu_read_lock_bh_held + +sched:: + + Critical sections Grace period Barrier + + rcu_read_lock_sched call_rcu rcu_barrier + rcu_read_unlock_sched synchronize_rcu + [preempt_disable] synchronize_rcu_expedited + [and friends] + rcu_read_lock_sched_notrace + rcu_read_unlock_sched_notrace + rcu_dereference_sched + rcu_dereference_sched_check + rcu_dereference_sched_protected + rcu_read_lock_sched_held + + +SRCU:: + + Critical sections Grace period Barrier + + srcu_read_lock call_srcu srcu_barrier + srcu_read_unlock synchronize_srcu + srcu_dereference synchronize_srcu_expedited + srcu_dereference_check + srcu_read_lock_held + +SRCU: Initialization/cleanup:: + + DEFINE_SRCU + DEFINE_STATIC_SRCU + init_srcu_struct + cleanup_srcu_struct + +All: lockdep-checked RCU-protected pointer access:: + + rcu_access_pointer + rcu_dereference_raw + RCU_LOCKDEP_WARN + rcu_sleep_check + RCU_NONIDLE + +See the comment headers in the source code (or the docbook generated +from them) for more information. + +However, given that there are no fewer than four families of RCU APIs +in the Linux kernel, how do you choose which one to use? The following +list can be helpful: + +a. Will readers need to block? If so, you need SRCU. + +b. What about the -rt patchset? If readers would need to block + in an non-rt kernel, you need SRCU. If readers would block + in a -rt kernel, but not in a non-rt kernel, SRCU is not + necessary. (The -rt patchset turns spinlocks into sleeplocks, + hence this distinction.) + +c. Do you need to treat NMI handlers, hardirq handlers, + and code segments with preemption disabled (whether + via preempt_disable(), local_irq_save(), local_bh_disable(), + or some other mechanism) as if they were explicit RCU readers? + If so, RCU-sched is the only choice that will work for you. + +d. Do you need RCU grace periods to complete even in the face + of softirq monopolization of one or more of the CPUs? For + example, is your code subject to network-based denial-of-service + attacks? If so, you should disable softirq across your readers, + for example, by using rcu_read_lock_bh(). + +e. Is your workload too update-intensive for normal use of + RCU, but inappropriate for other synchronization mechanisms? + If so, consider SLAB_TYPESAFE_BY_RCU (which was originally + named SLAB_DESTROY_BY_RCU). But please be careful! + +f. Do you need read-side critical sections that are respected + even though they are in the middle of the idle loop, during + user-mode execution, or on an offlined CPU? If so, SRCU is the + only choice that will work for you. + +g. Otherwise, use RCU. + +Of course, this all assumes that you have determined that RCU is in fact +the right tool for your job. + +.. _8_whatisRCU: + +8. ANSWERS TO QUICK QUIZZES +---------------------------- + +Quick Quiz #1: + Why is this argument naive? How could a deadlock + occur when using this algorithm in a real-world Linux + kernel? [Referring to the lock-based "toy" RCU + algorithm.] + +Answer: + Consider the following sequence of events: + + 1. CPU 0 acquires some unrelated lock, call it + "problematic_lock", disabling irq via + spin_lock_irqsave(). + + 2. CPU 1 enters synchronize_rcu(), write-acquiring + rcu_gp_mutex. + + 3. CPU 0 enters rcu_read_lock(), but must wait + because CPU 1 holds rcu_gp_mutex. + + 4. CPU 1 is interrupted, and the irq handler + attempts to acquire problematic_lock. + + The system is now deadlocked. + + One way to avoid this deadlock is to use an approach like + that of CONFIG_PREEMPT_RT, where all normal spinlocks + become blocking locks, and all irq handlers execute in + the context of special tasks. In this case, in step 4 + above, the irq handler would block, allowing CPU 1 to + release rcu_gp_mutex, avoiding the deadlock. + + Even in the absence of deadlock, this RCU implementation + allows latency to "bleed" from readers to other + readers through synchronize_rcu(). To see this, + consider task A in an RCU read-side critical section + (thus read-holding rcu_gp_mutex), task B blocked + attempting to write-acquire rcu_gp_mutex, and + task C blocked in rcu_read_lock() attempting to + read_acquire rcu_gp_mutex. Task A's RCU read-side + latency is holding up task C, albeit indirectly via + task B. + + Realtime RCU implementations therefore use a counter-based + approach where tasks in RCU read-side critical sections + cannot be blocked by tasks executing synchronize_rcu(). + +:ref:`Back to Quick Quiz #1 ` + +Quick Quiz #2: + Give an example where Classic RCU's read-side + overhead is **negative**. + +Answer: + Imagine a single-CPU system with a non-CONFIG_PREEMPT + kernel where a routing table is used by process-context + code, but can be updated by irq-context code (for example, + by an "ICMP REDIRECT" packet). The usual way of handling + this would be to have the process-context code disable + interrupts while searching the routing table. Use of + RCU allows such interrupt-disabling to be dispensed with. + Thus, without RCU, you pay the cost of disabling interrupts, + and with RCU you don't. + + One can argue that the overhead of RCU in this + case is negative with respect to the single-CPU + interrupt-disabling approach. Others might argue that + the overhead of RCU is merely zero, and that replacing + the positive overhead of the interrupt-disabling scheme + with the zero-overhead RCU scheme does not constitute + negative overhead. + + In real life, of course, things are more complex. But + even the theoretical possibility of negative overhead for + a synchronization primitive is a bit unexpected. ;-) + +:ref:`Back to Quick Quiz #2 ` + +Quick Quiz #3: + If it is illegal to block in an RCU read-side + critical section, what the heck do you do in + PREEMPT_RT, where normal spinlocks can block??? + +Answer: + Just as PREEMPT_RT permits preemption of spinlock + critical sections, it permits preemption of RCU + read-side critical sections. It also permits + spinlocks blocking while in RCU read-side critical + sections. + + Why the apparent inconsistency? Because it is + possible to use priority boosting to keep the RCU + grace periods short if need be (for example, if running + short of memory). In contrast, if blocking waiting + for (say) network reception, there is no way to know + what should be boosted. Especially given that the + process we need to boost might well be a human being + who just went out for a pizza or something. And although + a computer-operated cattle prod might arouse serious + interest, it might also provoke serious objections. + Besides, how does the computer know what pizza parlor + the human being went to??? + +:ref:`Back to Quick Quiz #3 ` + +ACKNOWLEDGEMENTS + +My thanks to the people who helped make this human-readable, including +Jon Walpole, Josh Triplett, Serge Hallyn, Suzanne Wood, and Alan Stern. + + +For more information, see http://www.rdrop.com/users/paulmck/RCU. diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt deleted file mode 100644 index 58ba05c4d97f..000000000000 --- a/Documentation/RCU/whatisRCU.txt +++ /dev/null @@ -1,1079 +0,0 @@ -What is RCU? -- "Read, Copy, Update" - -Please note that the "What is RCU?" LWN series is an excellent place -to start learning about RCU: - -1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/ -2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/ -3. RCU part 3: the RCU API http://lwn.net/Articles/264090/ -4. The RCU API, 2010 Edition http://lwn.net/Articles/418853/ - 2010 Big API Table http://lwn.net/Articles/419086/ -5. The RCU API, 2014 Edition http://lwn.net/Articles/609904/ - 2014 Big API Table http://lwn.net/Articles/609973/ - - -What is RCU? - -RCU is a synchronization mechanism that was added to the Linux kernel -during the 2.5 development effort that is optimized for read-mostly -situations. Although RCU is actually quite simple once you understand it, -getting there can sometimes be a challenge. Part of the problem is that -most of the past descriptions of RCU have been written with the mistaken -assumption that there is "one true way" to describe RCU. Instead, -the experience has been that different people must take different paths -to arrive at an understanding of RCU. This document provides several -different paths, as follows: - -1. RCU OVERVIEW -2. WHAT IS RCU'S CORE API? -3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? -4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? -5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? -6. ANALOGY WITH READER-WRITER LOCKING -7. FULL LIST OF RCU APIs -8. ANSWERS TO QUICK QUIZZES - -People who prefer starting with a conceptual overview should focus on -Section 1, though most readers will profit by reading this section at -some point. People who prefer to start with an API that they can then -experiment with should focus on Section 2. People who prefer to start -with example uses should focus on Sections 3 and 4. People who need to -understand the RCU implementation should focus on Section 5, then dive -into the kernel source code. People who reason best by analogy should -focus on Section 6. Section 7 serves as an index to the docbook API -documentation, and Section 8 is the traditional answer key. - -So, start with the section that makes the most sense to you and your -preferred method of learning. If you need to know everything about -everything, feel free to read the whole thing -- but if you are really -that type of person, you have perused the source code and will therefore -never need this document anyway. ;-) - - -1. RCU OVERVIEW - -The basic idea behind RCU is to split updates into "removal" and -"reclamation" phases. The removal phase removes references to data items -within a data structure (possibly by replacing them with references to -new versions of these data items), and can run concurrently with readers. -The reason that it is safe to run the removal phase concurrently with -readers is the semantics of modern CPUs guarantee that readers will see -either the old or the new version of the data structure rather than a -partially updated reference. The reclamation phase does the work of reclaiming -(e.g., freeing) the data items removed from the data structure during the -removal phase. Because reclaiming data items can disrupt any readers -concurrently referencing those data items, the reclamation phase must -not start until readers no longer hold references to those data items. - -Splitting the update into removal and reclamation phases permits the -updater to perform the removal phase immediately, and to defer the -reclamation phase until all readers active during the removal phase have -completed, either by blocking until they finish or by registering a -callback that is invoked after they finish. Only readers that are active -during the removal phase need be considered, because any reader starting -after the removal phase will be unable to gain a reference to the removed -data items, and therefore cannot be disrupted by the reclamation phase. - -So the typical RCU update sequence goes something like the following: - -a. Remove pointers to a data structure, so that subsequent - readers cannot gain a reference to it. - -b. Wait for all previous readers to complete their RCU read-side - critical sections. - -c. At this point, there cannot be any readers who hold references - to the data structure, so it now may safely be reclaimed - (e.g., kfree()d). - -Step (b) above is the key idea underlying RCU's deferred destruction. -The ability to wait until all readers are done allows RCU readers to -use much lighter-weight synchronization, in some cases, absolutely no -synchronization at all. In contrast, in more conventional lock-based -schemes, readers must use heavy-weight synchronization in order to -prevent an updater from deleting the data structure out from under them. -This is because lock-based updaters typically update data items in place, -and must therefore exclude readers. In contrast, RCU-based updaters -typically take advantage of the fact that writes to single aligned -pointers are atomic on modern CPUs, allowing atomic insertion, removal, -and replacement of data items in a linked structure without disrupting -readers. Concurrent RCU readers can then continue accessing the old -versions, and can dispense with the atomic operations, memory barriers, -and communications cache misses that are so expensive on present-day -SMP computer systems, even in absence of lock contention. - -In the three-step procedure shown above, the updater is performing both -the removal and the reclamation step, but it is often helpful for an -entirely different thread to do the reclamation, as is in fact the case -in the Linux kernel's directory-entry cache (dcache). Even if the same -thread performs both the update step (step (a) above) and the reclamation -step (step (c) above), it is often helpful to think of them separately. -For example, RCU readers and updaters need not communicate at all, -but RCU provides implicit low-overhead communication between readers -and reclaimers, namely, in step (b) above. - -So how the heck can a reclaimer tell when a reader is done, given -that readers are not doing any sort of synchronization operations??? -Read on to learn about how RCU's API makes this easy. - - -2. WHAT IS RCU'S CORE API? - -The core RCU API is quite small: - -a. rcu_read_lock() -b. rcu_read_unlock() -c. synchronize_rcu() / call_rcu() -d. rcu_assign_pointer() -e. rcu_dereference() - -There are many other members of the RCU API, but the rest can be -expressed in terms of these five, though most implementations instead -express synchronize_rcu() in terms of the call_rcu() callback API. - -The five core RCU APIs are described below, the other 18 will be enumerated -later. See the kernel docbook documentation for more info, or look directly -at the function header comments. - -rcu_read_lock() - - void rcu_read_lock(void); - - Used by a reader to inform the reclaimer that the reader is - entering an RCU read-side critical section. It is illegal - to block while in an RCU read-side critical section, though - kernels built with CONFIG_PREEMPT_RCU can preempt RCU - read-side critical sections. Any RCU-protected data structure - accessed during an RCU read-side critical section is guaranteed to - remain unreclaimed for the full duration of that critical section. - Reference counts may be used in conjunction with RCU to maintain - longer-term references to data structures. - -rcu_read_unlock() - - void rcu_read_unlock(void); - - Used by a reader to inform the reclaimer that the reader is - exiting an RCU read-side critical section. Note that RCU - read-side critical sections may be nested and/or overlapping. - -synchronize_rcu() - - void synchronize_rcu(void); - - Marks the end of updater code and the beginning of reclaimer - code. It does this by blocking until all pre-existing RCU - read-side critical sections on all CPUs have completed. - Note that synchronize_rcu() will -not- necessarily wait for - any subsequent RCU read-side critical sections to complete. - For example, consider the following sequence of events: - - CPU 0 CPU 1 CPU 2 - ----------------- ------------------------- --------------- - 1. rcu_read_lock() - 2. enters synchronize_rcu() - 3. rcu_read_lock() - 4. rcu_read_unlock() - 5. exits synchronize_rcu() - 6. rcu_read_unlock() - - To reiterate, synchronize_rcu() waits only for ongoing RCU - read-side critical sections to complete, not necessarily for - any that begin after synchronize_rcu() is invoked. - - Of course, synchronize_rcu() does not necessarily return - -immediately- after the last pre-existing RCU read-side critical - section completes. For one thing, there might well be scheduling - delays. For another thing, many RCU implementations process - requests in batches in order to improve efficiencies, which can - further delay synchronize_rcu(). - - Since synchronize_rcu() is the API that must figure out when - readers are done, its implementation is key to RCU. For RCU - to be useful in all but the most read-intensive situations, - synchronize_rcu()'s overhead must also be quite small. - - The call_rcu() API is a callback form of synchronize_rcu(), - and is described in more detail in a later section. Instead of - blocking, it registers a function and argument which are invoked - after all ongoing RCU read-side critical sections have completed. - This callback variant is particularly useful in situations where - it is illegal to block or where update-side performance is - critically important. - - However, the call_rcu() API should not be used lightly, as use - of the synchronize_rcu() API generally results in simpler code. - In addition, the synchronize_rcu() API has the nice property - of automatically limiting update rate should grace periods - be delayed. This property results in system resilience in face - of denial-of-service attacks. Code using call_rcu() should limit - update rate in order to gain this same sort of resilience. See - checklist.txt for some approaches to limiting the update rate. - -rcu_assign_pointer() - - void rcu_assign_pointer(p, typeof(p) v); - - Yes, rcu_assign_pointer() -is- implemented as a macro, though it - would be cool to be able to declare a function in this manner. - (Compiler experts will no doubt disagree.) - - The updater uses this function to assign a new value to an - RCU-protected pointer, in order to safely communicate the change - in value from the updater to the reader. This macro does not - evaluate to an rvalue, but it does execute any memory-barrier - instructions required for a given CPU architecture. - - Perhaps just as important, it serves to document (1) which - pointers are protected by RCU and (2) the point at which a - given structure becomes accessible to other CPUs. That said, - rcu_assign_pointer() is most frequently used indirectly, via - the _rcu list-manipulation primitives such as list_add_rcu(). - -rcu_dereference() - - typeof(p) rcu_dereference(p); - - Like rcu_assign_pointer(), rcu_dereference() must be implemented - as a macro. - - The reader uses rcu_dereference() to fetch an RCU-protected - pointer, which returns a value that may then be safely - dereferenced. Note that rcu_dereference() does not actually - dereference the pointer, instead, it protects the pointer for - later dereferencing. It also executes any needed memory-barrier - instructions for a given CPU architecture. Currently, only Alpha - needs memory barriers within rcu_dereference() -- on other CPUs, - it compiles to nothing, not even a compiler directive. - - Common coding practice uses rcu_dereference() to copy an - RCU-protected pointer to a local variable, then dereferences - this local variable, for example as follows: - - p = rcu_dereference(head.next); - return p->data; - - However, in this case, one could just as easily combine these - into one statement: - - return rcu_dereference(head.next)->data; - - If you are going to be fetching multiple fields from the - RCU-protected structure, using the local variable is of - course preferred. Repeated rcu_dereference() calls look - ugly, do not guarantee that the same pointer will be returned - if an update happened while in the critical section, and incur - unnecessary overhead on Alpha CPUs. - - Note that the value returned by rcu_dereference() is valid - only within the enclosing RCU read-side critical section [1]. - For example, the following is -not- legal: - - rcu_read_lock(); - p = rcu_dereference(head.next); - rcu_read_unlock(); - x = p->address; /* BUG!!! */ - rcu_read_lock(); - y = p->data; /* BUG!!! */ - rcu_read_unlock(); - - Holding a reference from one RCU read-side critical section - to another is just as illegal as holding a reference from - one lock-based critical section to another! Similarly, - using a reference outside of the critical section in which - it was acquired is just as illegal as doing so with normal - locking. - - As with rcu_assign_pointer(), an important function of - rcu_dereference() is to document which pointers are protected by - RCU, in particular, flagging a pointer that is subject to changing - at any time, including immediately after the rcu_dereference(). - And, again like rcu_assign_pointer(), rcu_dereference() is - typically used indirectly, via the _rcu list-manipulation - primitives, such as list_for_each_entry_rcu() [2]. - - [1] The variant rcu_dereference_protected() can be used outside - of an RCU read-side critical section as long as the usage is - protected by locks acquired by the update-side code. This variant - avoids the lockdep warning that would happen when using (for - example) rcu_dereference() without rcu_read_lock() protection. - Using rcu_dereference_protected() also has the advantage - of permitting compiler optimizations that rcu_dereference() - must prohibit. The rcu_dereference_protected() variant takes - a lockdep expression to indicate which locks must be acquired - by the caller. If the indicated protection is not provided, - a lockdep splat is emitted. See Documentation/RCU/Design/Requirements/Requirements.rst - and the API's code comments for more details and example usage. - - [2] If the list_for_each_entry_rcu() instance might be used by - update-side code as well as by RCU readers, then an additional - lockdep expression can be added to its list of arguments. - For example, given an additional "lock_is_held(&mylock)" argument, - the RCU lockdep code would complain only if this instance was - invoked outside of an RCU read-side critical section and without - the protection of mylock. - -The following diagram shows how each API communicates among the -reader, updater, and reclaimer. - - - rcu_assign_pointer() - +--------+ - +---------------------->| reader |---------+ - | +--------+ | - | | | - | | | Protect: - | | | rcu_read_lock() - | | | rcu_read_unlock() - | rcu_dereference() | | - +---------+ | | - | updater |<----------------+ | - +---------+ V - | +-----------+ - +----------------------------------->| reclaimer | - +-----------+ - Defer: - synchronize_rcu() & call_rcu() - - -The RCU infrastructure observes the time sequence of rcu_read_lock(), -rcu_read_unlock(), synchronize_rcu(), and call_rcu() invocations in -order to determine when (1) synchronize_rcu() invocations may return -to their callers and (2) call_rcu() callbacks may be invoked. Efficient -implementations of the RCU infrastructure make heavy use of batching in -order to amortize their overhead over many uses of the corresponding APIs. - -There are at least three flavors of RCU usage in the Linux kernel. The diagram -above shows the most common one. On the updater side, the rcu_assign_pointer(), -sychronize_rcu() and call_rcu() primitives used are the same for all three -flavors. However for protection (on the reader side), the primitives used vary -depending on the flavor: - -a. rcu_read_lock() / rcu_read_unlock() - rcu_dereference() - -b. rcu_read_lock_bh() / rcu_read_unlock_bh() - local_bh_disable() / local_bh_enable() - rcu_dereference_bh() - -c. rcu_read_lock_sched() / rcu_read_unlock_sched() - preempt_disable() / preempt_enable() - local_irq_save() / local_irq_restore() - hardirq enter / hardirq exit - NMI enter / NMI exit - rcu_dereference_sched() - -These three flavors are used as follows: - -a. RCU applied to normal data structures. - -b. RCU applied to networking data structures that may be subjected - to remote denial-of-service attacks. - -c. RCU applied to scheduler and interrupt/NMI-handler tasks. - -Again, most uses will be of (a). The (b) and (c) cases are important -for specialized uses, but are relatively uncommon. - - -3. WHAT ARE SOME EXAMPLE USES OF CORE RCU API? - -This section shows a simple use of the core RCU API to protect a -global pointer to a dynamically allocated structure. More-typical -uses of RCU may be found in listRCU.txt, arrayRCU.txt, and NMI-RCU.txt. - - struct foo { - int a; - char b; - long c; - }; - DEFINE_SPINLOCK(foo_mutex); - - struct foo __rcu *gbl_foo; - - /* - * Create a new struct foo that is the same as the one currently - * pointed to by gbl_foo, except that field "a" is replaced - * with "new_a". Points gbl_foo to the new structure, and - * frees up the old structure after a grace period. - * - * Uses rcu_assign_pointer() to ensure that concurrent readers - * see the initialized version of the new structure. - * - * Uses synchronize_rcu() to ensure that any readers that might - * have references to the old structure complete before freeing - * the old structure. - */ - void foo_update_a(int new_a) - { - struct foo *new_fp; - struct foo *old_fp; - - new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL); - spin_lock(&foo_mutex); - old_fp = rcu_dereference_protected(gbl_foo, lockdep_is_held(&foo_mutex)); - *new_fp = *old_fp; - new_fp->a = new_a; - rcu_assign_pointer(gbl_foo, new_fp); - spin_unlock(&foo_mutex); - synchronize_rcu(); - kfree(old_fp); - } - - /* - * Return the value of field "a" of the current gbl_foo - * structure. Use rcu_read_lock() and rcu_read_unlock() - * to ensure that the structure does not get deleted out - * from under us, and use rcu_dereference() to ensure that - * we see the initialized version of the structure (important - * for DEC Alpha and for people reading the code). - */ - int foo_get_a(void) - { - int retval; - - rcu_read_lock(); - retval = rcu_dereference(gbl_foo)->a; - rcu_read_unlock(); - return retval; - } - -So, to sum up: - -o Use rcu_read_lock() and rcu_read_unlock() to guard RCU - read-side critical sections. - -o Within an RCU read-side critical section, use rcu_dereference() - to dereference RCU-protected pointers. - -o Use some solid scheme (such as locks or semaphores) to - keep concurrent updates from interfering with each other. - -o Use rcu_assign_pointer() to update an RCU-protected pointer. - This primitive protects concurrent readers from the updater, - -not- concurrent updates from each other! You therefore still - need to use locking (or something similar) to keep concurrent - rcu_assign_pointer() primitives from interfering with each other. - -o Use synchronize_rcu() -after- removing a data element from an - RCU-protected data structure, but -before- reclaiming/freeing - the data element, in order to wait for the completion of all - RCU read-side critical sections that might be referencing that - data item. - -See checklist.txt for additional rules to follow when using RCU. -And again, more-typical uses of RCU may be found in listRCU.txt, -arrayRCU.txt, and NMI-RCU.txt. - - -4. WHAT IF MY UPDATING THREAD CANNOT BLOCK? - -In the example above, foo_update_a() blocks until a grace period elapses. -This is quite simple, but in some cases one cannot afford to wait so -long -- there might be other high-priority work to be done. - -In such cases, one uses call_rcu() rather than synchronize_rcu(). -The call_rcu() API is as follows: - - void call_rcu(struct rcu_head * head, - void (*func)(struct rcu_head *head)); - -This function invokes func(head) after a grace period has elapsed. -This invocation might happen from either softirq or process context, -so the function is not permitted to block. The foo struct needs to -have an rcu_head structure added, perhaps as follows: - - struct foo { - int a; - char b; - long c; - struct rcu_head rcu; - }; - -The foo_update_a() function might then be written as follows: - - /* - * Create a new struct foo that is the same as the one currently - * pointed to by gbl_foo, except that field "a" is replaced - * with "new_a". Points gbl_foo to the new structure, and - * frees up the old structure after a grace period. - * - * Uses rcu_assign_pointer() to ensure that concurrent readers - * see the initialized version of the new structure. - * - * Uses call_rcu() to ensure that any readers that might have - * references to the old structure complete before freeing the - * old structure. - */ - void foo_update_a(int new_a) - { - struct foo *new_fp; - struct foo *old_fp; - - new_fp = kmalloc(sizeof(*new_fp), GFP_KERNEL); - spin_lock(&foo_mutex); - old_fp = rcu_dereference_protected(gbl_foo, lockdep_is_held(&foo_mutex)); - *new_fp = *old_fp; - new_fp->a = new_a; - rcu_assign_pointer(gbl_foo, new_fp); - spin_unlock(&foo_mutex); - call_rcu(&old_fp->rcu, foo_reclaim); - } - -The foo_reclaim() function might appear as follows: - - void foo_reclaim(struct rcu_head *rp) - { - struct foo *fp = container_of(rp, struct foo, rcu); - - foo_cleanup(fp->a); - - kfree(fp); - } - -The container_of() primitive is a macro that, given a pointer into a -struct, the type of the struct, and the pointed-to field within the -struct, returns a pointer to the beginning of the struct. - -The use of call_rcu() permits the caller of foo_update_a() to -immediately regain control, without needing to worry further about the -old version of the newly updated element. It also clearly shows the -RCU distinction between updater, namely foo_update_a(), and reclaimer, -namely foo_reclaim(). - -The summary of advice is the same as for the previous section, except -that we are now using call_rcu() rather than synchronize_rcu(): - -o Use call_rcu() -after- removing a data element from an - RCU-protected data structure in order to register a callback - function that will be invoked after the completion of all RCU - read-side critical sections that might be referencing that - data item. - -If the callback for call_rcu() is not doing anything more than calling -kfree() on the structure, you can use kfree_rcu() instead of call_rcu() -to avoid having to write your own callback: - - kfree_rcu(old_fp, rcu); - -Again, see checklist.txt for additional rules governing the use of RCU. - - -5. WHAT ARE SOME SIMPLE IMPLEMENTATIONS OF RCU? - -One of the nice things about RCU is that it has extremely simple "toy" -implementations that are a good first step towards understanding the -production-quality implementations in the Linux kernel. This section -presents two such "toy" implementations of RCU, one that is implemented -in terms of familiar locking primitives, and another that more closely -resembles "classic" RCU. Both are way too simple for real-world use, -lacking both functionality and performance. However, they are useful -in getting a feel for how RCU works. See kernel/rcu/update.c for a -production-quality implementation, and see: - - http://www.rdrop.com/users/paulmck/RCU - -for papers describing the Linux kernel RCU implementation. The OLS'01 -and OLS'02 papers are a good introduction, and the dissertation provides -more details on the current implementation as of early 2004. - - -5A. "TOY" IMPLEMENTATION #1: LOCKING - -This section presents a "toy" RCU implementation that is based on -familiar locking primitives. Its overhead makes it a non-starter for -real-life use, as does its lack of scalability. It is also unsuitable -for realtime use, since it allows scheduling latency to "bleed" from -one read-side critical section to another. It also assumes recursive -reader-writer locks: If you try this with non-recursive locks, and -you allow nested rcu_read_lock() calls, you can deadlock. - -However, it is probably the easiest implementation to relate to, so is -a good starting point. - -It is extremely simple: - - static DEFINE_RWLOCK(rcu_gp_mutex); - - void rcu_read_lock(void) - { - read_lock(&rcu_gp_mutex); - } - - void rcu_read_unlock(void) - { - read_unlock(&rcu_gp_mutex); - } - - void synchronize_rcu(void) - { - write_lock(&rcu_gp_mutex); - smp_mb__after_spinlock(); - write_unlock(&rcu_gp_mutex); - } - -[You can ignore rcu_assign_pointer() and rcu_dereference() without missing -much. But here are simplified versions anyway. And whatever you do, -don't forget about them when submitting patches making use of RCU!] - - #define rcu_assign_pointer(p, v) \ - ({ \ - smp_store_release(&(p), (v)); \ - }) - - #define rcu_dereference(p) \ - ({ \ - typeof(p) _________p1 = READ_ONCE(p); \ - (_________p1); \ - }) - - -The rcu_read_lock() and rcu_read_unlock() primitive read-acquire -and release a global reader-writer lock. The synchronize_rcu() -primitive write-acquires this same lock, then releases it. This means -that once synchronize_rcu() exits, all RCU read-side critical sections -that were in progress before synchronize_rcu() was called are guaranteed -to have completed -- there is no way that synchronize_rcu() would have -been able to write-acquire the lock otherwise. The smp_mb__after_spinlock() -promotes synchronize_rcu() to a full memory barrier in compliance with -the "Memory-Barrier Guarantees" listed in: - - Documentation/RCU/Design/Requirements/Requirements.rst - -It is possible to nest rcu_read_lock(), since reader-writer locks may -be recursively acquired. Note also that rcu_read_lock() is immune -from deadlock (an important property of RCU). The reason for this is -that the only thing that can block rcu_read_lock() is a synchronize_rcu(). -But synchronize_rcu() does not acquire any locks while holding rcu_gp_mutex, -so there can be no deadlock cycle. - -Quick Quiz #1: Why is this argument naive? How could a deadlock - occur when using this algorithm in a real-world Linux - kernel? How could this deadlock be avoided? - - -5B. "TOY" EXAMPLE #2: CLASSIC RCU - -This section presents a "toy" RCU implementation that is based on -"classic RCU". It is also short on performance (but only for updates) and -on features such as hotplug CPU and the ability to run in CONFIG_PREEMPT -kernels. The definitions of rcu_dereference() and rcu_assign_pointer() -are the same as those shown in the preceding section, so they are omitted. - - void rcu_read_lock(void) { } - - void rcu_read_unlock(void) { } - - void synchronize_rcu(void) - { - int cpu; - - for_each_possible_cpu(cpu) - run_on(cpu); - } - -Note that rcu_read_lock() and rcu_read_unlock() do absolutely nothing. -This is the great strength of classic RCU in a non-preemptive kernel: -read-side overhead is precisely zero, at least on non-Alpha CPUs. -And there is absolutely no way that rcu_read_lock() can possibly -participate in a deadlock cycle! - -The implementation of synchronize_rcu() simply schedules itself on each -CPU in turn. The run_on() primitive can be implemented straightforwardly -in terms of the sched_setaffinity() primitive. Of course, a somewhat less -"toy" implementation would restore the affinity upon completion rather -than just leaving all tasks running on the last CPU, but when I said -"toy", I meant -toy-! - -So how the heck is this supposed to work??? - -Remember that it is illegal to block while in an RCU read-side critical -section. Therefore, if a given CPU executes a context switch, we know -that it must have completed all preceding RCU read-side critical sections. -Once -all- CPUs have executed a context switch, then -all- preceding -RCU read-side critical sections will have completed. - -So, suppose that we remove a data item from its structure and then invoke -synchronize_rcu(). Once synchronize_rcu() returns, we are guaranteed -that there are no RCU read-side critical sections holding a reference -to that data item, so we can safely reclaim it. - -Quick Quiz #2: Give an example where Classic RCU's read-side - overhead is -negative-. - -Quick Quiz #3: If it is illegal to block in an RCU read-side - critical section, what the heck do you do in - PREEMPT_RT, where normal spinlocks can block??? - - -6. ANALOGY WITH READER-WRITER LOCKING - -Although RCU can be used in many different ways, a very common use of -RCU is analogous to reader-writer locking. The following unified -diff shows how closely related RCU and reader-writer locking can be. - - @@ -5,5 +5,5 @@ struct el { - int data; - /* Other data fields */ - }; - -rwlock_t listmutex; - +spinlock_t listmutex; - struct el head; - - @@ -13,15 +14,15 @@ - struct list_head *lp; - struct el *p; - - - read_lock(&listmutex); - - list_for_each_entry(p, head, lp) { - + rcu_read_lock(); - + list_for_each_entry_rcu(p, head, lp) { - if (p->key == key) { - *result = p->data; - - read_unlock(&listmutex); - + rcu_read_unlock(); - return 1; - } - } - - read_unlock(&listmutex); - + rcu_read_unlock(); - return 0; - } - - @@ -29,15 +30,16 @@ - { - struct el *p; - - - write_lock(&listmutex); - + spin_lock(&listmutex); - list_for_each_entry(p, head, lp) { - if (p->key == key) { - - list_del(&p->list); - - write_unlock(&listmutex); - + list_del_rcu(&p->list); - + spin_unlock(&listmutex); - + synchronize_rcu(); - kfree(p); - return 1; - } - } - - write_unlock(&listmutex); - + spin_unlock(&listmutex); - return 0; - } - -Or, for those who prefer a side-by-side listing: - - 1 struct el { 1 struct el { - 2 struct list_head list; 2 struct list_head list; - 3 long key; 3 long key; - 4 spinlock_t mutex; 4 spinlock_t mutex; - 5 int data; 5 int data; - 6 /* Other data fields */ 6 /* Other data fields */ - 7 }; 7 }; - 8 rwlock_t listmutex; 8 spinlock_t listmutex; - 9 struct el head; 9 struct el head; - - 1 int search(long key, int *result) 1 int search(long key, int *result) - 2 { 2 { - 3 struct list_head *lp; 3 struct list_head *lp; - 4 struct el *p; 4 struct el *p; - 5 5 - 6 read_lock(&listmutex); 6 rcu_read_lock(); - 7 list_for_each_entry(p, head, lp) { 7 list_for_each_entry_rcu(p, head, lp) { - 8 if (p->key == key) { 8 if (p->key == key) { - 9 *result = p->data; 9 *result = p->data; -10 read_unlock(&listmutex); 10 rcu_read_unlock(); -11 return 1; 11 return 1; -12 } 12 } -13 } 13 } -14 read_unlock(&listmutex); 14 rcu_read_unlock(); -15 return 0; 15 return 0; -16 } 16 } - - 1 int delete(long key) 1 int delete(long key) - 2 { 2 { - 3 struct el *p; 3 struct el *p; - 4 4 - 5 write_lock(&listmutex); 5 spin_lock(&listmutex); - 6 list_for_each_entry(p, head, lp) { 6 list_for_each_entry(p, head, lp) { - 7 if (p->key == key) { 7 if (p->key == key) { - 8 list_del(&p->list); 8 list_del_rcu(&p->list); - 9 write_unlock(&listmutex); 9 spin_unlock(&listmutex); - 10 synchronize_rcu(); -10 kfree(p); 11 kfree(p); -11 return 1; 12 return 1; -12 } 13 } -13 } 14 } -14 write_unlock(&listmutex); 15 spin_unlock(&listmutex); -15 return 0; 16 return 0; -16 } 17 } - -Either way, the differences are quite small. Read-side locking moves -to rcu_read_lock() and rcu_read_unlock, update-side locking moves from -a reader-writer lock to a simple spinlock, and a synchronize_rcu() -precedes the kfree(). - -However, there is one potential catch: the read-side and update-side -critical sections can now run concurrently. In many cases, this will -not be a problem, but it is necessary to check carefully regardless. -For example, if multiple independent list updates must be seen as -a single atomic update, converting to RCU will require special care. - -Also, the presence of synchronize_rcu() means that the RCU version of -delete() can now block. If this is a problem, there is a callback-based -mechanism that never blocks, namely call_rcu() or kfree_rcu(), that can -be used in place of synchronize_rcu(). - - -7. FULL LIST OF RCU APIs - -The RCU APIs are documented in docbook-format header comments in the -Linux-kernel source code, but it helps to have a full list of the -APIs, since there does not appear to be a way to categorize them -in docbook. Here is the list, by category. - -RCU list traversal: - - list_entry_rcu - list_first_entry_rcu - list_next_rcu - list_for_each_entry_rcu - list_for_each_entry_continue_rcu - list_for_each_entry_from_rcu - hlist_first_rcu - hlist_next_rcu - hlist_pprev_rcu - hlist_for_each_entry_rcu - hlist_for_each_entry_rcu_bh - hlist_for_each_entry_from_rcu - hlist_for_each_entry_continue_rcu - hlist_for_each_entry_continue_rcu_bh - hlist_nulls_first_rcu - hlist_nulls_for_each_entry_rcu - hlist_bl_first_rcu - hlist_bl_for_each_entry_rcu - -RCU pointer/list update: - - rcu_assign_pointer - list_add_rcu - list_add_tail_rcu - list_del_rcu - list_replace_rcu - hlist_add_behind_rcu - hlist_add_before_rcu - hlist_add_head_rcu - hlist_del_rcu - hlist_del_init_rcu - hlist_replace_rcu - list_splice_init_rcu() - hlist_nulls_del_init_rcu - hlist_nulls_del_rcu - hlist_nulls_add_head_rcu - hlist_bl_add_head_rcu - hlist_bl_del_init_rcu - hlist_bl_del_rcu - hlist_bl_set_first_rcu - -RCU: Critical sections Grace period Barrier - - rcu_read_lock synchronize_net rcu_barrier - rcu_read_unlock synchronize_rcu - rcu_dereference synchronize_rcu_expedited - rcu_read_lock_held call_rcu - rcu_dereference_check kfree_rcu - rcu_dereference_protected - -bh: Critical sections Grace period Barrier - - rcu_read_lock_bh call_rcu rcu_barrier - rcu_read_unlock_bh synchronize_rcu - [local_bh_disable] synchronize_rcu_expedited - [and friends] - rcu_dereference_bh - rcu_dereference_bh_check - rcu_dereference_bh_protected - rcu_read_lock_bh_held - -sched: Critical sections Grace period Barrier - - rcu_read_lock_sched call_rcu rcu_barrier - rcu_read_unlock_sched synchronize_rcu - [preempt_disable] synchronize_rcu_expedited - [and friends] - rcu_read_lock_sched_notrace - rcu_read_unlock_sched_notrace - rcu_dereference_sched - rcu_dereference_sched_check - rcu_dereference_sched_protected - rcu_read_lock_sched_held - - -SRCU: Critical sections Grace period Barrier - - srcu_read_lock call_srcu srcu_barrier - srcu_read_unlock synchronize_srcu - srcu_dereference synchronize_srcu_expedited - srcu_dereference_check - srcu_read_lock_held - -SRCU: Initialization/cleanup - DEFINE_SRCU - DEFINE_STATIC_SRCU - init_srcu_struct - cleanup_srcu_struct - -All: lockdep-checked RCU-protected pointer access - - rcu_access_pointer - rcu_dereference_raw - RCU_LOCKDEP_WARN - rcu_sleep_check - RCU_NONIDLE - -See the comment headers in the source code (or the docbook generated -from them) for more information. - -However, given that there are no fewer than four families of RCU APIs -in the Linux kernel, how do you choose which one to use? The following -list can be helpful: - -a. Will readers need to block? If so, you need SRCU. - -b. What about the -rt patchset? If readers would need to block - in an non-rt kernel, you need SRCU. If readers would block - in a -rt kernel, but not in a non-rt kernel, SRCU is not - necessary. (The -rt patchset turns spinlocks into sleeplocks, - hence this distinction.) - -c. Do you need to treat NMI handlers, hardirq handlers, - and code segments with preemption disabled (whether - via preempt_disable(), local_irq_save(), local_bh_disable(), - or some other mechanism) as if they were explicit RCU readers? - If so, RCU-sched is the only choice that will work for you. - -d. Do you need RCU grace periods to complete even in the face - of softirq monopolization of one or more of the CPUs? For - example, is your code subject to network-based denial-of-service - attacks? If so, you should disable softirq across your readers, - for example, by using rcu_read_lock_bh(). - -e. Is your workload too update-intensive for normal use of - RCU, but inappropriate for other synchronization mechanisms? - If so, consider SLAB_TYPESAFE_BY_RCU (which was originally - named SLAB_DESTROY_BY_RCU). But please be careful! - -f. Do you need read-side critical sections that are respected - even though they are in the middle of the idle loop, during - user-mode execution, or on an offlined CPU? If so, SRCU is the - only choice that will work for you. - -g. Otherwise, use RCU. - -Of course, this all assumes that you have determined that RCU is in fact -the right tool for your job. - - -8. ANSWERS TO QUICK QUIZZES - -Quick Quiz #1: Why is this argument naive? How could a deadlock - occur when using this algorithm in a real-world Linux - kernel? [Referring to the lock-based "toy" RCU - algorithm.] - -Answer: Consider the following sequence of events: - - 1. CPU 0 acquires some unrelated lock, call it - "problematic_lock", disabling irq via - spin_lock_irqsave(). - - 2. CPU 1 enters synchronize_rcu(), write-acquiring - rcu_gp_mutex. - - 3. CPU 0 enters rcu_read_lock(), but must wait - because CPU 1 holds rcu_gp_mutex. - - 4. CPU 1 is interrupted, and the irq handler - attempts to acquire problematic_lock. - - The system is now deadlocked. - - One way to avoid this deadlock is to use an approach like - that of CONFIG_PREEMPT_RT, where all normal spinlocks - become blocking locks, and all irq handlers execute in - the context of special tasks. In this case, in step 4 - above, the irq handler would block, allowing CPU 1 to - release rcu_gp_mutex, avoiding the deadlock. - - Even in the absence of deadlock, this RCU implementation - allows latency to "bleed" from readers to other - readers through synchronize_rcu(). To see this, - consider task A in an RCU read-side critical section - (thus read-holding rcu_gp_mutex), task B blocked - attempting to write-acquire rcu_gp_mutex, and - task C blocked in rcu_read_lock() attempting to - read_acquire rcu_gp_mutex. Task A's RCU read-side - latency is holding up task C, albeit indirectly via - task B. - - Realtime RCU implementations therefore use a counter-based - approach where tasks in RCU read-side critical sections - cannot be blocked by tasks executing synchronize_rcu(). - -Quick Quiz #2: Give an example where Classic RCU's read-side - overhead is -negative-. - -Answer: Imagine a single-CPU system with a non-CONFIG_PREEMPT - kernel where a routing table is used by process-context - code, but can be updated by irq-context code (for example, - by an "ICMP REDIRECT" packet). The usual way of handling - this would be to have the process-context code disable - interrupts while searching the routing table. Use of - RCU allows such interrupt-disabling to be dispensed with. - Thus, without RCU, you pay the cost of disabling interrupts, - and with RCU you don't. - - One can argue that the overhead of RCU in this - case is negative with respect to the single-CPU - interrupt-disabling approach. Others might argue that - the overhead of RCU is merely zero, and that replacing - the positive overhead of the interrupt-disabling scheme - with the zero-overhead RCU scheme does not constitute - negative overhead. - - In real life, of course, things are more complex. But - even the theoretical possibility of negative overhead for - a synchronization primitive is a bit unexpected. ;-) - -Quick Quiz #3: If it is illegal to block in an RCU read-side - critical section, what the heck do you do in - PREEMPT_RT, where normal spinlocks can block??? - -Answer: Just as PREEMPT_RT permits preemption of spinlock - critical sections, it permits preemption of RCU - read-side critical sections. It also permits - spinlocks blocking while in RCU read-side critical - sections. - - Why the apparent inconsistency? Because it is - possible to use priority boosting to keep the RCU - grace periods short if need be (for example, if running - short of memory). In contrast, if blocking waiting - for (say) network reception, there is no way to know - what should be boosted. Especially given that the - process we need to boost might well be a human being - who just went out for a pizza or something. And although - a computer-operated cattle prod might arouse serious - interest, it might also provoke serious objections. - Besides, how does the computer know what pizza parlor - the human being went to??? - - -ACKNOWLEDGEMENTS - -My thanks to the people who helped make this human-readable, including -Jon Walpole, Josh Triplett, Serge Hallyn, Suzanne Wood, and Alan Stern. - - -For more information, see http://www.rdrop.com/users/paulmck/RCU. -- cgit v1.2.3 From b00aedf978aa5c9a3c2d734fda5e51acfbceb5d6 Mon Sep 17 00:00:00 2001 From: Amol Grover Date: Sat, 2 Nov 2019 13:31:07 +0530 Subject: doc: Convert to rcu_dereference.txt to rcu_dereference.rst This patch converts rcu_dereference.txt to rcu_dereference.rst and adds it to index.rst Signed-off-by: Amol Grover Signed-off-by: Paul E. McKenney --- Documentation/RCU/index.rst | 1 + Documentation/RCU/rcu_dereference.rst | 463 ++++++++++++++++++++++++++++++++++ Documentation/RCU/rcu_dereference.txt | 456 --------------------------------- 3 files changed, 464 insertions(+), 456 deletions(-) create mode 100644 Documentation/RCU/rcu_dereference.rst delete mode 100644 Documentation/RCU/rcu_dereference.txt (limited to 'Documentation') diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst index b9b11481c727..c81d0e4fd999 100644 --- a/Documentation/RCU/index.rst +++ b/Documentation/RCU/index.rst @@ -8,6 +8,7 @@ RCU concepts :maxdepth: 3 arrayRCU + rcu_dereference whatisRCU rcu listRCU diff --git a/Documentation/RCU/rcu_dereference.rst b/Documentation/RCU/rcu_dereference.rst new file mode 100644 index 000000000000..c9667eb0d444 --- /dev/null +++ b/Documentation/RCU/rcu_dereference.rst @@ -0,0 +1,463 @@ +.. _rcu_dereference_doc: + +PROPER CARE AND FEEDING OF RETURN VALUES FROM rcu_dereference() +=============================================================== + +Most of the time, you can use values from rcu_dereference() or one of +the similar primitives without worries. Dereferencing (prefix "*"), +field selection ("->"), assignment ("="), address-of ("&"), addition and +subtraction of constants, and casts all work quite naturally and safely. + +It is nevertheless possible to get into trouble with other operations. +Follow these rules to keep your RCU code working properly: + +- You must use one of the rcu_dereference() family of primitives + to load an RCU-protected pointer, otherwise CONFIG_PROVE_RCU + will complain. Worse yet, your code can see random memory-corruption + bugs due to games that compilers and DEC Alpha can play. + Without one of the rcu_dereference() primitives, compilers + can reload the value, and won't your code have fun with two + different values for a single pointer! Without rcu_dereference(), + DEC Alpha can load a pointer, dereference that pointer, and + return data preceding initialization that preceded the store of + the pointer. + + In addition, the volatile cast in rcu_dereference() prevents the + compiler from deducing the resulting pointer value. Please see + the section entitled "EXAMPLE WHERE THE COMPILER KNOWS TOO MUCH" + for an example where the compiler can in fact deduce the exact + value of the pointer, and thus cause misordering. + +- You are only permitted to use rcu_dereference on pointer values. + The compiler simply knows too much about integral values to + trust it to carry dependencies through integer operations. + There are a very few exceptions, namely that you can temporarily + cast the pointer to uintptr_t in order to: + + - Set bits and clear bits down in the must-be-zero low-order + bits of that pointer. This clearly means that the pointer + must have alignment constraints, for example, this does + -not- work in general for char* pointers. + + - XOR bits to translate pointers, as is done in some + classic buddy-allocator algorithms. + + It is important to cast the value back to pointer before + doing much of anything else with it. + +- Avoid cancellation when using the "+" and "-" infix arithmetic + operators. For example, for a given variable "x", avoid + "(x-(uintptr_t)x)" for char* pointers. The compiler is within its + rights to substitute zero for this sort of expression, so that + subsequent accesses no longer depend on the rcu_dereference(), + again possibly resulting in bugs due to misordering. + + Of course, if "p" is a pointer from rcu_dereference(), and "a" + and "b" are integers that happen to be equal, the expression + "p+a-b" is safe because its value still necessarily depends on + the rcu_dereference(), thus maintaining proper ordering. + +- If you are using RCU to protect JITed functions, so that the + "()" function-invocation operator is applied to a value obtained + (directly or indirectly) from rcu_dereference(), you may need to + interact directly with the hardware to flush instruction caches. + This issue arises on some systems when a newly JITed function is + using the same memory that was used by an earlier JITed function. + +- Do not use the results from relational operators ("==", "!=", + ">", ">=", "<", or "<=") when dereferencing. For example, + the following (quite strange) code is buggy:: + + int *p; + int *q; + + ... + + p = rcu_dereference(gp) + q = &global_q; + q += p > &oom_p; + r1 = *q; /* BUGGY!!! */ + + As before, the reason this is buggy is that relational operators + are often compiled using branches. And as before, although + weak-memory machines such as ARM or PowerPC do order stores + after such branches, but can speculate loads, which can again + result in misordering bugs. + +- Be very careful about comparing pointers obtained from + rcu_dereference() against non-NULL values. As Linus Torvalds + explained, if the two pointers are equal, the compiler could + substitute the pointer you are comparing against for the pointer + obtained from rcu_dereference(). For example:: + + p = rcu_dereference(gp); + if (p == &default_struct) + do_default(p->a); + + Because the compiler now knows that the value of "p" is exactly + the address of the variable "default_struct", it is free to + transform this code into the following:: + + p = rcu_dereference(gp); + if (p == &default_struct) + do_default(default_struct.a); + + On ARM and Power hardware, the load from "default_struct.a" + can now be speculated, such that it might happen before the + rcu_dereference(). This could result in bugs due to misordering. + + However, comparisons are OK in the following cases: + + - The comparison was against the NULL pointer. If the + compiler knows that the pointer is NULL, you had better + not be dereferencing it anyway. If the comparison is + non-equal, the compiler is none the wiser. Therefore, + it is safe to compare pointers from rcu_dereference() + against NULL pointers. + + - The pointer is never dereferenced after being compared. + Since there are no subsequent dereferences, the compiler + cannot use anything it learned from the comparison + to reorder the non-existent subsequent dereferences. + This sort of comparison occurs frequently when scanning + RCU-protected circular linked lists. + + Note that if checks for being within an RCU read-side + critical section are not required and the pointer is never + dereferenced, rcu_access_pointer() should be used in place + of rcu_dereference(). + + - The comparison is against a pointer that references memory + that was initialized "a long time ago." The reason + this is safe is that even if misordering occurs, the + misordering will not affect the accesses that follow + the comparison. So exactly how long ago is "a long + time ago"? Here are some possibilities: + + - Compile time. + + - Boot time. + + - Module-init time for module code. + + - Prior to kthread creation for kthread code. + + - During some prior acquisition of the lock that + we now hold. + + - Before mod_timer() time for a timer handler. + + There are many other possibilities involving the Linux + kernel's wide array of primitives that cause code to + be invoked at a later time. + + - The pointer being compared against also came from + rcu_dereference(). In this case, both pointers depend + on one rcu_dereference() or another, so you get proper + ordering either way. + + That said, this situation can make certain RCU usage + bugs more likely to happen. Which can be a good thing, + at least if they happen during testing. An example + of such an RCU usage bug is shown in the section titled + "EXAMPLE OF AMPLIFIED RCU-USAGE BUG". + + - All of the accesses following the comparison are stores, + so that a control dependency preserves the needed ordering. + That said, it is easy to get control dependencies wrong. + Please see the "CONTROL DEPENDENCIES" section of + Documentation/memory-barriers.txt for more details. + + - The pointers are not equal -and- the compiler does + not have enough information to deduce the value of the + pointer. Note that the volatile cast in rcu_dereference() + will normally prevent the compiler from knowing too much. + + However, please note that if the compiler knows that the + pointer takes on only one of two values, a not-equal + comparison will provide exactly the information that the + compiler needs to deduce the value of the pointer. + +- Disable any value-speculation optimizations that your compiler + might provide, especially if you are making use of feedback-based + optimizations that take data collected from prior runs. Such + value-speculation optimizations reorder operations by design. + + There is one exception to this rule: Value-speculation + optimizations that leverage the branch-prediction hardware are + safe on strongly ordered systems (such as x86), but not on weakly + ordered systems (such as ARM or Power). Choose your compiler + command-line options wisely! + + +EXAMPLE OF AMPLIFIED RCU-USAGE BUG +---------------------------------- + +Because updaters can run concurrently with RCU readers, RCU readers can +see stale and/or inconsistent values. If RCU readers need fresh or +consistent values, which they sometimes do, they need to take proper +precautions. To see this, consider the following code fragment:: + + struct foo { + int a; + int b; + int c; + }; + struct foo *gp1; + struct foo *gp2; + + void updater(void) + { + struct foo *p; + + p = kmalloc(...); + if (p == NULL) + deal_with_it(); + p->a = 42; /* Each field in its own cache line. */ + p->b = 43; + p->c = 44; + rcu_assign_pointer(gp1, p); + p->b = 143; + p->c = 144; + rcu_assign_pointer(gp2, p); + } + + void reader(void) + { + struct foo *p; + struct foo *q; + int r1, r2; + + p = rcu_dereference(gp2); + if (p == NULL) + return; + r1 = p->b; /* Guaranteed to get 143. */ + q = rcu_dereference(gp1); /* Guaranteed non-NULL. */ + if (p == q) { + /* The compiler decides that q->c is same as p->c. */ + r2 = p->c; /* Could get 44 on weakly order system. */ + } + do_something_with(r1, r2); + } + +You might be surprised that the outcome (r1 == 143 && r2 == 44) is possible, +but you should not be. After all, the updater might have been invoked +a second time between the time reader() loaded into "r1" and the time +that it loaded into "r2". The fact that this same result can occur due +to some reordering from the compiler and CPUs is beside the point. + +But suppose that the reader needs a consistent view? + +Then one approach is to use locking, for example, as follows:: + + struct foo { + int a; + int b; + int c; + spinlock_t lock; + }; + struct foo *gp1; + struct foo *gp2; + + void updater(void) + { + struct foo *p; + + p = kmalloc(...); + if (p == NULL) + deal_with_it(); + spin_lock(&p->lock); + p->a = 42; /* Each field in its own cache line. */ + p->b = 43; + p->c = 44; + spin_unlock(&p->lock); + rcu_assign_pointer(gp1, p); + spin_lock(&p->lock); + p->b = 143; + p->c = 144; + spin_unlock(&p->lock); + rcu_assign_pointer(gp2, p); + } + + void reader(void) + { + struct foo *p; + struct foo *q; + int r1, r2; + + p = rcu_dereference(gp2); + if (p == NULL) + return; + spin_lock(&p->lock); + r1 = p->b; /* Guaranteed to get 143. */ + q = rcu_dereference(gp1); /* Guaranteed non-NULL. */ + if (p == q) { + /* The compiler decides that q->c is same as p->c. */ + r2 = p->c; /* Locking guarantees r2 == 144. */ + } + spin_unlock(&p->lock); + do_something_with(r1, r2); + } + +As always, use the right tool for the job! + + +EXAMPLE WHERE THE COMPILER KNOWS TOO MUCH +----------------------------------------- + +If a pointer obtained from rcu_dereference() compares not-equal to some +other pointer, the compiler normally has no clue what the value of the +first pointer might be. This lack of knowledge prevents the compiler +from carrying out optimizations that otherwise might destroy the ordering +guarantees that RCU depends on. And the volatile cast in rcu_dereference() +should prevent the compiler from guessing the value. + +But without rcu_dereference(), the compiler knows more than you might +expect. Consider the following code fragment:: + + struct foo { + int a; + int b; + }; + static struct foo variable1; + static struct foo variable2; + static struct foo *gp = &variable1; + + void updater(void) + { + initialize_foo(&variable2); + rcu_assign_pointer(gp, &variable2); + /* + * The above is the only store to gp in this translation unit, + * and the address of gp is not exported in any way. + */ + } + + int reader(void) + { + struct foo *p; + + p = gp; + barrier(); + if (p == &variable1) + return p->a; /* Must be variable1.a. */ + else + return p->b; /* Must be variable2.b. */ + } + +Because the compiler can see all stores to "gp", it knows that the only +possible values of "gp" are "variable1" on the one hand and "variable2" +on the other. The comparison in reader() therefore tells the compiler +the exact value of "p" even in the not-equals case. This allows the +compiler to make the return values independent of the load from "gp", +in turn destroying the ordering between this load and the loads of the +return values. This can result in "p->b" returning pre-initialization +garbage values. + +In short, rcu_dereference() is -not- optional when you are going to +dereference the resulting pointer. + + +WHICH MEMBER OF THE rcu_dereference() FAMILY SHOULD YOU USE? +------------------------------------------------------------ + +First, please avoid using rcu_dereference_raw() and also please avoid +using rcu_dereference_check() and rcu_dereference_protected() with a +second argument with a constant value of 1 (or true, for that matter). +With that caution out of the way, here is some guidance for which +member of the rcu_dereference() to use in various situations: + +1. If the access needs to be within an RCU read-side critical + section, use rcu_dereference(). With the new consolidated + RCU flavors, an RCU read-side critical section is entered + using rcu_read_lock(), anything that disables bottom halves, + anything that disables interrupts, or anything that disables + preemption. + +2. If the access might be within an RCU read-side critical section + on the one hand, or protected by (say) my_lock on the other, + use rcu_dereference_check(), for example:: + + p1 = rcu_dereference_check(p->rcu_protected_pointer, + lockdep_is_held(&my_lock)); + + +3. If the access might be within an RCU read-side critical section + on the one hand, or protected by either my_lock or your_lock on + the other, again use rcu_dereference_check(), for example:: + + p1 = rcu_dereference_check(p->rcu_protected_pointer, + lockdep_is_held(&my_lock) || + lockdep_is_held(&your_lock)); + +4. If the access is on the update side, so that it is always protected + by my_lock, use rcu_dereference_protected():: + + p1 = rcu_dereference_protected(p->rcu_protected_pointer, + lockdep_is_held(&my_lock)); + + This can be extended to handle multiple locks as in #3 above, + and both can be extended to check other conditions as well. + +5. If the protection is supplied by the caller, and is thus unknown + to this code, that is the rare case when rcu_dereference_raw() + is appropriate. In addition, rcu_dereference_raw() might be + appropriate when the lockdep expression would be excessively + complex, except that a better approach in that case might be to + take a long hard look at your synchronization design. Still, + there are data-locking cases where any one of a very large number + of locks or reference counters suffices to protect the pointer, + so rcu_dereference_raw() does have its place. + + However, its place is probably quite a bit smaller than one + might expect given the number of uses in the current kernel. + Ditto for its synonym, rcu_dereference_check( ... , 1), and + its close relative, rcu_dereference_protected(... , 1). + + +SPARSE CHECKING OF RCU-PROTECTED POINTERS +----------------------------------------- + +The sparse static-analysis tool checks for direct access to RCU-protected +pointers, which can result in "interesting" bugs due to compiler +optimizations involving invented loads and perhaps also load tearing. +For example, suppose someone mistakenly does something like this:: + + p = q->rcu_protected_pointer; + do_something_with(p->a); + do_something_else_with(p->b); + +If register pressure is high, the compiler might optimize "p" out +of existence, transforming the code to something like this:: + + do_something_with(q->rcu_protected_pointer->a); + do_something_else_with(q->rcu_protected_pointer->b); + +This could fatally disappoint your code if q->rcu_protected_pointer +changed in the meantime. Nor is this a theoretical problem: Exactly +this sort of bug cost Paul E. McKenney (and several of his innocent +colleagues) a three-day weekend back in the early 1990s. + +Load tearing could of course result in dereferencing a mashup of a pair +of pointers, which also might fatally disappoint your code. + +These problems could have been avoided simply by making the code instead +read as follows:: + + p = rcu_dereference(q->rcu_protected_pointer); + do_something_with(p->a); + do_something_else_with(p->b); + +Unfortunately, these sorts of bugs can be extremely hard to spot during +review. This is where the sparse tool comes into play, along with the +"__rcu" marker. If you mark a pointer declaration, whether in a structure +or as a formal parameter, with "__rcu", which tells sparse to complain if +this pointer is accessed directly. It will also cause sparse to complain +if a pointer not marked with "__rcu" is accessed using rcu_dereference() +and friends. For example, ->rcu_protected_pointer might be declared as +follows:: + + struct foo __rcu *rcu_protected_pointer; + +Use of "__rcu" is opt-in. If you choose not to use it, then you should +ignore the sparse warnings. diff --git a/Documentation/RCU/rcu_dereference.txt b/Documentation/RCU/rcu_dereference.txt deleted file mode 100644 index bf699e8cfc75..000000000000 --- a/Documentation/RCU/rcu_dereference.txt +++ /dev/null @@ -1,456 +0,0 @@ -PROPER CARE AND FEEDING OF RETURN VALUES FROM rcu_dereference() - -Most of the time, you can use values from rcu_dereference() or one of -the similar primitives without worries. Dereferencing (prefix "*"), -field selection ("->"), assignment ("="), address-of ("&"), addition and -subtraction of constants, and casts all work quite naturally and safely. - -It is nevertheless possible to get into trouble with other operations. -Follow these rules to keep your RCU code working properly: - -o You must use one of the rcu_dereference() family of primitives - to load an RCU-protected pointer, otherwise CONFIG_PROVE_RCU - will complain. Worse yet, your code can see random memory-corruption - bugs due to games that compilers and DEC Alpha can play. - Without one of the rcu_dereference() primitives, compilers - can reload the value, and won't your code have fun with two - different values for a single pointer! Without rcu_dereference(), - DEC Alpha can load a pointer, dereference that pointer, and - return data preceding initialization that preceded the store of - the pointer. - - In addition, the volatile cast in rcu_dereference() prevents the - compiler from deducing the resulting pointer value. Please see - the section entitled "EXAMPLE WHERE THE COMPILER KNOWS TOO MUCH" - for an example where the compiler can in fact deduce the exact - value of the pointer, and thus cause misordering. - -o You are only permitted to use rcu_dereference on pointer values. - The compiler simply knows too much about integral values to - trust it to carry dependencies through integer operations. - There are a very few exceptions, namely that you can temporarily - cast the pointer to uintptr_t in order to: - - o Set bits and clear bits down in the must-be-zero low-order - bits of that pointer. This clearly means that the pointer - must have alignment constraints, for example, this does - -not- work in general for char* pointers. - - o XOR bits to translate pointers, as is done in some - classic buddy-allocator algorithms. - - It is important to cast the value back to pointer before - doing much of anything else with it. - -o Avoid cancellation when using the "+" and "-" infix arithmetic - operators. For example, for a given variable "x", avoid - "(x-(uintptr_t)x)" for char* pointers. The compiler is within its - rights to substitute zero for this sort of expression, so that - subsequent accesses no longer depend on the rcu_dereference(), - again possibly resulting in bugs due to misordering. - - Of course, if "p" is a pointer from rcu_dereference(), and "a" - and "b" are integers that happen to be equal, the expression - "p+a-b" is safe because its value still necessarily depends on - the rcu_dereference(), thus maintaining proper ordering. - -o If you are using RCU to protect JITed functions, so that the - "()" function-invocation operator is applied to a value obtained - (directly or indirectly) from rcu_dereference(), you may need to - interact directly with the hardware to flush instruction caches. - This issue arises on some systems when a newly JITed function is - using the same memory that was used by an earlier JITed function. - -o Do not use the results from relational operators ("==", "!=", - ">", ">=", "<", or "<=") when dereferencing. For example, - the following (quite strange) code is buggy: - - int *p; - int *q; - - ... - - p = rcu_dereference(gp) - q = &global_q; - q += p > &oom_p; - r1 = *q; /* BUGGY!!! */ - - As before, the reason this is buggy is that relational operators - are often compiled using branches. And as before, although - weak-memory machines such as ARM or PowerPC do order stores - after such branches, but can speculate loads, which can again - result in misordering bugs. - -o Be very careful about comparing pointers obtained from - rcu_dereference() against non-NULL values. As Linus Torvalds - explained, if the two pointers are equal, the compiler could - substitute the pointer you are comparing against for the pointer - obtained from rcu_dereference(). For example: - - p = rcu_dereference(gp); - if (p == &default_struct) - do_default(p->a); - - Because the compiler now knows that the value of "p" is exactly - the address of the variable "default_struct", it is free to - transform this code into the following: - - p = rcu_dereference(gp); - if (p == &default_struct) - do_default(default_struct.a); - - On ARM and Power hardware, the load from "default_struct.a" - can now be speculated, such that it might happen before the - rcu_dereference(). This could result in bugs due to misordering. - - However, comparisons are OK in the following cases: - - o The comparison was against the NULL pointer. If the - compiler knows that the pointer is NULL, you had better - not be dereferencing it anyway. If the comparison is - non-equal, the compiler is none the wiser. Therefore, - it is safe to compare pointers from rcu_dereference() - against NULL pointers. - - o The pointer is never dereferenced after being compared. - Since there are no subsequent dereferences, the compiler - cannot use anything it learned from the comparison - to reorder the non-existent subsequent dereferences. - This sort of comparison occurs frequently when scanning - RCU-protected circular linked lists. - - Note that if checks for being within an RCU read-side - critical section are not required and the pointer is never - dereferenced, rcu_access_pointer() should be used in place - of rcu_dereference(). - - o The comparison is against a pointer that references memory - that was initialized "a long time ago." The reason - this is safe is that even if misordering occurs, the - misordering will not affect the accesses that follow - the comparison. So exactly how long ago is "a long - time ago"? Here are some possibilities: - - o Compile time. - - o Boot time. - - o Module-init time for module code. - - o Prior to kthread creation for kthread code. - - o During some prior acquisition of the lock that - we now hold. - - o Before mod_timer() time for a timer handler. - - There are many other possibilities involving the Linux - kernel's wide array of primitives that cause code to - be invoked at a later time. - - o The pointer being compared against also came from - rcu_dereference(). In this case, both pointers depend - on one rcu_dereference() or another, so you get proper - ordering either way. - - That said, this situation can make certain RCU usage - bugs more likely to happen. Which can be a good thing, - at least if they happen during testing. An example - of such an RCU usage bug is shown in the section titled - "EXAMPLE OF AMPLIFIED RCU-USAGE BUG". - - o All of the accesses following the comparison are stores, - so that a control dependency preserves the needed ordering. - That said, it is easy to get control dependencies wrong. - Please see the "CONTROL DEPENDENCIES" section of - Documentation/memory-barriers.txt for more details. - - o The pointers are not equal -and- the compiler does - not have enough information to deduce the value of the - pointer. Note that the volatile cast in rcu_dereference() - will normally prevent the compiler from knowing too much. - - However, please note that if the compiler knows that the - pointer takes on only one of two values, a not-equal - comparison will provide exactly the information that the - compiler needs to deduce the value of the pointer. - -o Disable any value-speculation optimizations that your compiler - might provide, especially if you are making use of feedback-based - optimizations that take data collected from prior runs. Such - value-speculation optimizations reorder operations by design. - - There is one exception to this rule: Value-speculation - optimizations that leverage the branch-prediction hardware are - safe on strongly ordered systems (such as x86), but not on weakly - ordered systems (such as ARM or Power). Choose your compiler - command-line options wisely! - - -EXAMPLE OF AMPLIFIED RCU-USAGE BUG - -Because updaters can run concurrently with RCU readers, RCU readers can -see stale and/or inconsistent values. If RCU readers need fresh or -consistent values, which they sometimes do, they need to take proper -precautions. To see this, consider the following code fragment: - - struct foo { - int a; - int b; - int c; - }; - struct foo *gp1; - struct foo *gp2; - - void updater(void) - { - struct foo *p; - - p = kmalloc(...); - if (p == NULL) - deal_with_it(); - p->a = 42; /* Each field in its own cache line. */ - p->b = 43; - p->c = 44; - rcu_assign_pointer(gp1, p); - p->b = 143; - p->c = 144; - rcu_assign_pointer(gp2, p); - } - - void reader(void) - { - struct foo *p; - struct foo *q; - int r1, r2; - - p = rcu_dereference(gp2); - if (p == NULL) - return; - r1 = p->b; /* Guaranteed to get 143. */ - q = rcu_dereference(gp1); /* Guaranteed non-NULL. */ - if (p == q) { - /* The compiler decides that q->c is same as p->c. */ - r2 = p->c; /* Could get 44 on weakly order system. */ - } - do_something_with(r1, r2); - } - -You might be surprised that the outcome (r1 == 143 && r2 == 44) is possible, -but you should not be. After all, the updater might have been invoked -a second time between the time reader() loaded into "r1" and the time -that it loaded into "r2". The fact that this same result can occur due -to some reordering from the compiler and CPUs is beside the point. - -But suppose that the reader needs a consistent view? - -Then one approach is to use locking, for example, as follows: - - struct foo { - int a; - int b; - int c; - spinlock_t lock; - }; - struct foo *gp1; - struct foo *gp2; - - void updater(void) - { - struct foo *p; - - p = kmalloc(...); - if (p == NULL) - deal_with_it(); - spin_lock(&p->lock); - p->a = 42; /* Each field in its own cache line. */ - p->b = 43; - p->c = 44; - spin_unlock(&p->lock); - rcu_assign_pointer(gp1, p); - spin_lock(&p->lock); - p->b = 143; - p->c = 144; - spin_unlock(&p->lock); - rcu_assign_pointer(gp2, p); - } - - void reader(void) - { - struct foo *p; - struct foo *q; - int r1, r2; - - p = rcu_dereference(gp2); - if (p == NULL) - return; - spin_lock(&p->lock); - r1 = p->b; /* Guaranteed to get 143. */ - q = rcu_dereference(gp1); /* Guaranteed non-NULL. */ - if (p == q) { - /* The compiler decides that q->c is same as p->c. */ - r2 = p->c; /* Locking guarantees r2 == 144. */ - } - spin_unlock(&p->lock); - do_something_with(r1, r2); - } - -As always, use the right tool for the job! - - -EXAMPLE WHERE THE COMPILER KNOWS TOO MUCH - -If a pointer obtained from rcu_dereference() compares not-equal to some -other pointer, the compiler normally has no clue what the value of the -first pointer might be. This lack of knowledge prevents the compiler -from carrying out optimizations that otherwise might destroy the ordering -guarantees that RCU depends on. And the volatile cast in rcu_dereference() -should prevent the compiler from guessing the value. - -But without rcu_dereference(), the compiler knows more than you might -expect. Consider the following code fragment: - - struct foo { - int a; - int b; - }; - static struct foo variable1; - static struct foo variable2; - static struct foo *gp = &variable1; - - void updater(void) - { - initialize_foo(&variable2); - rcu_assign_pointer(gp, &variable2); - /* - * The above is the only store to gp in this translation unit, - * and the address of gp is not exported in any way. - */ - } - - int reader(void) - { - struct foo *p; - - p = gp; - barrier(); - if (p == &variable1) - return p->a; /* Must be variable1.a. */ - else - return p->b; /* Must be variable2.b. */ - } - -Because the compiler can see all stores to "gp", it knows that the only -possible values of "gp" are "variable1" on the one hand and "variable2" -on the other. The comparison in reader() therefore tells the compiler -the exact value of "p" even in the not-equals case. This allows the -compiler to make the return values independent of the load from "gp", -in turn destroying the ordering between this load and the loads of the -return values. This can result in "p->b" returning pre-initialization -garbage values. - -In short, rcu_dereference() is -not- optional when you are going to -dereference the resulting pointer. - - -WHICH MEMBER OF THE rcu_dereference() FAMILY SHOULD YOU USE? - -First, please avoid using rcu_dereference_raw() and also please avoid -using rcu_dereference_check() and rcu_dereference_protected() with a -second argument with a constant value of 1 (or true, for that matter). -With that caution out of the way, here is some guidance for which -member of the rcu_dereference() to use in various situations: - -1. If the access needs to be within an RCU read-side critical - section, use rcu_dereference(). With the new consolidated - RCU flavors, an RCU read-side critical section is entered - using rcu_read_lock(), anything that disables bottom halves, - anything that disables interrupts, or anything that disables - preemption. - -2. If the access might be within an RCU read-side critical section - on the one hand, or protected by (say) my_lock on the other, - use rcu_dereference_check(), for example: - - p1 = rcu_dereference_check(p->rcu_protected_pointer, - lockdep_is_held(&my_lock)); - - -3. If the access might be within an RCU read-side critical section - on the one hand, or protected by either my_lock or your_lock on - the other, again use rcu_dereference_check(), for example: - - p1 = rcu_dereference_check(p->rcu_protected_pointer, - lockdep_is_held(&my_lock) || - lockdep_is_held(&your_lock)); - -4. If the access is on the update side, so that it is always protected - by my_lock, use rcu_dereference_protected(): - - p1 = rcu_dereference_protected(p->rcu_protected_pointer, - lockdep_is_held(&my_lock)); - - This can be extended to handle multiple locks as in #3 above, - and both can be extended to check other conditions as well. - -5. If the protection is supplied by the caller, and is thus unknown - to this code, that is the rare case when rcu_dereference_raw() - is appropriate. In addition, rcu_dereference_raw() might be - appropriate when the lockdep expression would be excessively - complex, except that a better approach in that case might be to - take a long hard look at your synchronization design. Still, - there are data-locking cases where any one of a very large number - of locks or reference counters suffices to protect the pointer, - so rcu_dereference_raw() does have its place. - - However, its place is probably quite a bit smaller than one - might expect given the number of uses in the current kernel. - Ditto for its synonym, rcu_dereference_check( ... , 1), and - its close relative, rcu_dereference_protected(... , 1). - - -SPARSE CHECKING OF RCU-PROTECTED POINTERS - -The sparse static-analysis tool checks for direct access to RCU-protected -pointers, which can result in "interesting" bugs due to compiler -optimizations involving invented loads and perhaps also load tearing. -For example, suppose someone mistakenly does something like this: - - p = q->rcu_protected_pointer; - do_something_with(p->a); - do_something_else_with(p->b); - -If register pressure is high, the compiler might optimize "p" out -of existence, transforming the code to something like this: - - do_something_with(q->rcu_protected_pointer->a); - do_something_else_with(q->rcu_protected_pointer->b); - -This could fatally disappoint your code if q->rcu_protected_pointer -changed in the meantime. Nor is this a theoretical problem: Exactly -this sort of bug cost Paul E. McKenney (and several of his innocent -colleagues) a three-day weekend back in the early 1990s. - -Load tearing could of course result in dereferencing a mashup of a pair -of pointers, which also might fatally disappoint your code. - -These problems could have been avoided simply by making the code instead -read as follows: - - p = rcu_dereference(q->rcu_protected_pointer); - do_something_with(p->a); - do_something_else_with(p->b); - -Unfortunately, these sorts of bugs can be extremely hard to spot during -review. This is where the sparse tool comes into play, along with the -"__rcu" marker. If you mark a pointer declaration, whether in a structure -or as a formal parameter, with "__rcu", which tells sparse to complain if -this pointer is accessed directly. It will also cause sparse to complain -if a pointer not marked with "__rcu" is accessed using rcu_dereference() -and friends. For example, ->rcu_protected_pointer might be declared as -follows: - - struct foo __rcu *rcu_protected_pointer; - -Use of "__rcu" is opt-in. If you choose not to use it, then you should -ignore the sparse warnings. -- cgit v1.2.3 From 4af498306ffd8e29ed5c1ae544d01bc8c09c3f8e Mon Sep 17 00:00:00 2001 From: Amol Grover Date: Thu, 7 Nov 2019 12:02:41 +0530 Subject: doc: Convert to rcubarrier.txt to ReST Convert rcubarrier.txt to rcubarrier.rst and add it to index.rst. Format file according to reST - Add headings and sub-headings - Add code segments - Add cross-references to quizes and answers Signed-off-by: Amol Grover Tested-by: Phong Tran Signed-off-by: Paul E. McKenney --- Documentation/RCU/index.rst | 1 + Documentation/RCU/rcubarrier.rst | 353 +++++++++++++++++++++++++++++++++++++++ Documentation/RCU/rcubarrier.txt | 325 ----------------------------------- 3 files changed, 354 insertions(+), 325 deletions(-) create mode 100644 Documentation/RCU/rcubarrier.rst delete mode 100644 Documentation/RCU/rcubarrier.txt (limited to 'Documentation') diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst index c81d0e4fd999..81a0a1e5f767 100644 --- a/Documentation/RCU/index.rst +++ b/Documentation/RCU/index.rst @@ -8,6 +8,7 @@ RCU concepts :maxdepth: 3 arrayRCU + rcubarrier rcu_dereference whatisRCU rcu diff --git a/Documentation/RCU/rcubarrier.rst b/Documentation/RCU/rcubarrier.rst new file mode 100644 index 000000000000..f64f4413a47c --- /dev/null +++ b/Documentation/RCU/rcubarrier.rst @@ -0,0 +1,353 @@ +.. _rcu_barrier: + +RCU and Unloadable Modules +========================== + +[Originally published in LWN Jan. 14, 2007: http://lwn.net/Articles/217484/] + +RCU (read-copy update) is a synchronization mechanism that can be thought +of as a replacement for read-writer locking (among other things), but with +very low-overhead readers that are immune to deadlock, priority inversion, +and unbounded latency. RCU read-side critical sections are delimited +by rcu_read_lock() and rcu_read_unlock(), which, in non-CONFIG_PREEMPT +kernels, generate no code whatsoever. + +This means that RCU writers are unaware of the presence of concurrent +readers, so that RCU updates to shared data must be undertaken quite +carefully, leaving an old version of the data structure in place until all +pre-existing readers have finished. These old versions are needed because +such readers might hold a reference to them. RCU updates can therefore be +rather expensive, and RCU is thus best suited for read-mostly situations. + +How can an RCU writer possibly determine when all readers are finished, +given that readers might well leave absolutely no trace of their +presence? There is a synchronize_rcu() primitive that blocks until all +pre-existing readers have completed. An updater wishing to delete an +element p from a linked list might do the following, while holding an +appropriate lock, of course:: + + list_del_rcu(p); + synchronize_rcu(); + kfree(p); + +But the above code cannot be used in IRQ context -- the call_rcu() +primitive must be used instead. This primitive takes a pointer to an +rcu_head struct placed within the RCU-protected data structure and +another pointer to a function that may be invoked later to free that +structure. Code to delete an element p from the linked list from IRQ +context might then be as follows:: + + list_del_rcu(p); + call_rcu(&p->rcu, p_callback); + +Since call_rcu() never blocks, this code can safely be used from within +IRQ context. The function p_callback() might be defined as follows:: + + static void p_callback(struct rcu_head *rp) + { + struct pstruct *p = container_of(rp, struct pstruct, rcu); + + kfree(p); + } + + +Unloading Modules That Use call_rcu() +------------------------------------- + +But what if p_callback is defined in an unloadable module? + +If we unload the module while some RCU callbacks are pending, +the CPUs executing these callbacks are going to be severely +disappointed when they are later invoked, as fancifully depicted at +http://lwn.net/images/ns/kernel/rcu-drop.jpg. + +We could try placing a synchronize_rcu() in the module-exit code path, +but this is not sufficient. Although synchronize_rcu() does wait for a +grace period to elapse, it does not wait for the callbacks to complete. + +One might be tempted to try several back-to-back synchronize_rcu() +calls, but this is still not guaranteed to work. If there is a very +heavy RCU-callback load, then some of the callbacks might be deferred +in order to allow other processing to proceed. Such deferral is required +in realtime kernels in order to avoid excessive scheduling latencies. + + +rcu_barrier() +------------- + +We instead need the rcu_barrier() primitive. Rather than waiting for +a grace period to elapse, rcu_barrier() waits for all outstanding RCU +callbacks to complete. Please note that rcu_barrier() does **not** imply +synchronize_rcu(), in particular, if there are no RCU callbacks queued +anywhere, rcu_barrier() is within its rights to return immediately, +without waiting for a grace period to elapse. + +Pseudo-code using rcu_barrier() is as follows: + + 1. Prevent any new RCU callbacks from being posted. + 2. Execute rcu_barrier(). + 3. Allow the module to be unloaded. + +There is also an srcu_barrier() function for SRCU, and you of course +must match the flavor of rcu_barrier() with that of call_rcu(). If your +module uses multiple flavors of call_rcu(), then it must also use multiple +flavors of rcu_barrier() when unloading that module. For example, if +it uses call_rcu(), call_srcu() on srcu_struct_1, and call_srcu() on +srcu_struct_2, then the following three lines of code will be required +when unloading:: + + 1 rcu_barrier(); + 2 srcu_barrier(&srcu_struct_1); + 3 srcu_barrier(&srcu_struct_2); + +The rcutorture module makes use of rcu_barrier() in its exit function +as follows:: + + 1 static void + 2 rcu_torture_cleanup(void) + 3 { + 4 int i; + 5 + 6 fullstop = 1; + 7 if (shuffler_task != NULL) { + 8 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task"); + 9 kthread_stop(shuffler_task); + 10 } + 11 shuffler_task = NULL; + 12 + 13 if (writer_task != NULL) { + 14 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task"); + 15 kthread_stop(writer_task); + 16 } + 17 writer_task = NULL; + 18 + 19 if (reader_tasks != NULL) { + 20 for (i = 0; i < nrealreaders; i++) { + 21 if (reader_tasks[i] != NULL) { + 22 VERBOSE_PRINTK_STRING( + 23 "Stopping rcu_torture_reader task"); + 24 kthread_stop(reader_tasks[i]); + 25 } + 26 reader_tasks[i] = NULL; + 27 } + 28 kfree(reader_tasks); + 29 reader_tasks = NULL; + 30 } + 31 rcu_torture_current = NULL; + 32 + 33 if (fakewriter_tasks != NULL) { + 34 for (i = 0; i < nfakewriters; i++) { + 35 if (fakewriter_tasks[i] != NULL) { + 36 VERBOSE_PRINTK_STRING( + 37 "Stopping rcu_torture_fakewriter task"); + 38 kthread_stop(fakewriter_tasks[i]); + 39 } + 40 fakewriter_tasks[i] = NULL; + 41 } + 42 kfree(fakewriter_tasks); + 43 fakewriter_tasks = NULL; + 44 } + 45 + 46 if (stats_task != NULL) { + 47 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task"); + 48 kthread_stop(stats_task); + 49 } + 50 stats_task = NULL; + 51 + 52 /* Wait for all RCU callbacks to fire. */ + 53 rcu_barrier(); + 54 + 55 rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ + 56 + 57 if (cur_ops->cleanup != NULL) + 58 cur_ops->cleanup(); + 59 if (atomic_read(&n_rcu_torture_error)) + 60 rcu_torture_print_module_parms("End of test: FAILURE"); + 61 else + 62 rcu_torture_print_module_parms("End of test: SUCCESS"); + 63 } + +Line 6 sets a global variable that prevents any RCU callbacks from +re-posting themselves. This will not be necessary in most cases, since +RCU callbacks rarely include calls to call_rcu(). However, the rcutorture +module is an exception to this rule, and therefore needs to set this +global variable. + +Lines 7-50 stop all the kernel tasks associated with the rcutorture +module. Therefore, once execution reaches line 53, no more rcutorture +RCU callbacks will be posted. The rcu_barrier() call on line 53 waits +for any pre-existing callbacks to complete. + +Then lines 55-62 print status and do operation-specific cleanup, and +then return, permitting the module-unload operation to be completed. + +.. _rcubarrier_quiz_1: + +Quick Quiz #1: + Is there any other situation where rcu_barrier() might + be required? + +:ref:`Answer to Quick Quiz #1 ` + +Your module might have additional complications. For example, if your +module invokes call_rcu() from timers, you will need to first cancel all +the timers, and only then invoke rcu_barrier() to wait for any remaining +RCU callbacks to complete. + +Of course, if you module uses call_rcu(), you will need to invoke +rcu_barrier() before unloading. Similarly, if your module uses +call_srcu(), you will need to invoke srcu_barrier() before unloading, +and on the same srcu_struct structure. If your module uses call_rcu() +**and** call_srcu(), then you will need to invoke rcu_barrier() **and** +srcu_barrier(). + + +Implementing rcu_barrier() +-------------------------- + +Dipankar Sarma's implementation of rcu_barrier() makes use of the fact +that RCU callbacks are never reordered once queued on one of the per-CPU +queues. His implementation queues an RCU callback on each of the per-CPU +callback queues, and then waits until they have all started executing, at +which point, all earlier RCU callbacks are guaranteed to have completed. + +The original code for rcu_barrier() was as follows:: + + 1 void rcu_barrier(void) + 2 { + 3 BUG_ON(in_interrupt()); + 4 /* Take cpucontrol mutex to protect against CPU hotplug */ + 5 mutex_lock(&rcu_barrier_mutex); + 6 init_completion(&rcu_barrier_completion); + 7 atomic_set(&rcu_barrier_cpu_count, 0); + 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1); + 9 wait_for_completion(&rcu_barrier_completion); + 10 mutex_unlock(&rcu_barrier_mutex); + 11 } + +Line 3 verifies that the caller is in process context, and lines 5 and 10 +use rcu_barrier_mutex to ensure that only one rcu_barrier() is using the +global completion and counters at a time, which are initialized on lines +6 and 7. Line 8 causes each CPU to invoke rcu_barrier_func(), which is +shown below. Note that the final "1" in on_each_cpu()'s argument list +ensures that all the calls to rcu_barrier_func() will have completed +before on_each_cpu() returns. Line 9 then waits for the completion. + +This code was rewritten in 2008 and several times thereafter, but this +still gives the general idea. + +The rcu_barrier_func() runs on each CPU, where it invokes call_rcu() +to post an RCU callback, as follows:: + + 1 static void rcu_barrier_func(void *notused) + 2 { + 3 int cpu = smp_processor_id(); + 4 struct rcu_data *rdp = &per_cpu(rcu_data, cpu); + 5 struct rcu_head *head; + 6 + 7 head = &rdp->barrier; + 8 atomic_inc(&rcu_barrier_cpu_count); + 9 call_rcu(head, rcu_barrier_callback); + 10 } + +Lines 3 and 4 locate RCU's internal per-CPU rcu_data structure, +which contains the struct rcu_head that needed for the later call to +call_rcu(). Line 7 picks up a pointer to this struct rcu_head, and line +8 increments a global counter. This counter will later be decremented +by the callback. Line 9 then registers the rcu_barrier_callback() on +the current CPU's queue. + +The rcu_barrier_callback() function simply atomically decrements the +rcu_barrier_cpu_count variable and finalizes the completion when it +reaches zero, as follows:: + + 1 static void rcu_barrier_callback(struct rcu_head *notused) + 2 { + 3 if (atomic_dec_and_test(&rcu_barrier_cpu_count)) + 4 complete(&rcu_barrier_completion); + 5 } + +.. _rcubarrier_quiz_2: + +Quick Quiz #2: + What happens if CPU 0's rcu_barrier_func() executes + immediately (thus incrementing rcu_barrier_cpu_count to the + value one), but the other CPU's rcu_barrier_func() invocations + are delayed for a full grace period? Couldn't this result in + rcu_barrier() returning prematurely? + +:ref:`Answer to Quick Quiz #2 ` + +The current rcu_barrier() implementation is more complex, due to the need +to avoid disturbing idle CPUs (especially on battery-powered systems) +and the need to minimally disturb non-idle CPUs in real-time systems. +However, the code above illustrates the concepts. + + +rcu_barrier() Summary +--------------------- + +The rcu_barrier() primitive has seen relatively little use, since most +code using RCU is in the core kernel rather than in modules. However, if +you are using RCU from an unloadable module, you need to use rcu_barrier() +so that your module may be safely unloaded. + + +Answers to Quick Quizzes +------------------------ + +.. _answer_rcubarrier_quiz_1: + +Quick Quiz #1: + Is there any other situation where rcu_barrier() might + be required? + +Answer: Interestingly enough, rcu_barrier() was not originally + implemented for module unloading. Nikita Danilov was using + RCU in a filesystem, which resulted in a similar situation at + filesystem-unmount time. Dipankar Sarma coded up rcu_barrier() + in response, so that Nikita could invoke it during the + filesystem-unmount process. + + Much later, yours truly hit the RCU module-unload problem when + implementing rcutorture, and found that rcu_barrier() solves + this problem as well. + +:ref:`Back to Quick Quiz #1 ` + +.. _answer_rcubarrier_quiz_2: + +Quick Quiz #2: + What happens if CPU 0's rcu_barrier_func() executes + immediately (thus incrementing rcu_barrier_cpu_count to the + value one), but the other CPU's rcu_barrier_func() invocations + are delayed for a full grace period? Couldn't this result in + rcu_barrier() returning prematurely? + +Answer: This cannot happen. The reason is that on_each_cpu() has its last + argument, the wait flag, set to "1". This flag is passed through + to smp_call_function() and further to smp_call_function_on_cpu(), + causing this latter to spin until the cross-CPU invocation of + rcu_barrier_func() has completed. This by itself would prevent + a grace period from completing on non-CONFIG_PREEMPT kernels, + since each CPU must undergo a context switch (or other quiescent + state) before the grace period can complete. However, this is + of no use in CONFIG_PREEMPT kernels. + + Therefore, on_each_cpu() disables preemption across its call + to smp_call_function() and also across the local call to + rcu_barrier_func(). This prevents the local CPU from context + switching, again preventing grace periods from completing. This + means that all CPUs have executed rcu_barrier_func() before + the first rcu_barrier_callback() can possibly execute, in turn + preventing rcu_barrier_cpu_count from prematurely reaching zero. + + Currently, -rt implementations of RCU keep but a single global + queue for RCU callbacks, and thus do not suffer from this + problem. However, when the -rt RCU eventually does have per-CPU + callback queues, things will have to change. One simple change + is to add an rcu_read_lock() before line 8 of rcu_barrier() + and an rcu_read_unlock() after line 8 of this same function. If + you can think of a better change, please let me know! + +:ref:`Back to Quick Quiz #2 ` diff --git a/Documentation/RCU/rcubarrier.txt b/Documentation/RCU/rcubarrier.txt deleted file mode 100644 index a2782df69732..000000000000 --- a/Documentation/RCU/rcubarrier.txt +++ /dev/null @@ -1,325 +0,0 @@ -RCU and Unloadable Modules - -[Originally published in LWN Jan. 14, 2007: http://lwn.net/Articles/217484/] - -RCU (read-copy update) is a synchronization mechanism that can be thought -of as a replacement for read-writer locking (among other things), but with -very low-overhead readers that are immune to deadlock, priority inversion, -and unbounded latency. RCU read-side critical sections are delimited -by rcu_read_lock() and rcu_read_unlock(), which, in non-CONFIG_PREEMPT -kernels, generate no code whatsoever. - -This means that RCU writers are unaware of the presence of concurrent -readers, so that RCU updates to shared data must be undertaken quite -carefully, leaving an old version of the data structure in place until all -pre-existing readers have finished. These old versions are needed because -such readers might hold a reference to them. RCU updates can therefore be -rather expensive, and RCU is thus best suited for read-mostly situations. - -How can an RCU writer possibly determine when all readers are finished, -given that readers might well leave absolutely no trace of their -presence? There is a synchronize_rcu() primitive that blocks until all -pre-existing readers have completed. An updater wishing to delete an -element p from a linked list might do the following, while holding an -appropriate lock, of course: - - list_del_rcu(p); - synchronize_rcu(); - kfree(p); - -But the above code cannot be used in IRQ context -- the call_rcu() -primitive must be used instead. This primitive takes a pointer to an -rcu_head struct placed within the RCU-protected data structure and -another pointer to a function that may be invoked later to free that -structure. Code to delete an element p from the linked list from IRQ -context might then be as follows: - - list_del_rcu(p); - call_rcu(&p->rcu, p_callback); - -Since call_rcu() never blocks, this code can safely be used from within -IRQ context. The function p_callback() might be defined as follows: - - static void p_callback(struct rcu_head *rp) - { - struct pstruct *p = container_of(rp, struct pstruct, rcu); - - kfree(p); - } - - -Unloading Modules That Use call_rcu() - -But what if p_callback is defined in an unloadable module? - -If we unload the module while some RCU callbacks are pending, -the CPUs executing these callbacks are going to be severely -disappointed when they are later invoked, as fancifully depicted at -http://lwn.net/images/ns/kernel/rcu-drop.jpg. - -We could try placing a synchronize_rcu() in the module-exit code path, -but this is not sufficient. Although synchronize_rcu() does wait for a -grace period to elapse, it does not wait for the callbacks to complete. - -One might be tempted to try several back-to-back synchronize_rcu() -calls, but this is still not guaranteed to work. If there is a very -heavy RCU-callback load, then some of the callbacks might be deferred -in order to allow other processing to proceed. Such deferral is required -in realtime kernels in order to avoid excessive scheduling latencies. - - -rcu_barrier() - -We instead need the rcu_barrier() primitive. Rather than waiting for -a grace period to elapse, rcu_barrier() waits for all outstanding RCU -callbacks to complete. Please note that rcu_barrier() does -not- imply -synchronize_rcu(), in particular, if there are no RCU callbacks queued -anywhere, rcu_barrier() is within its rights to return immediately, -without waiting for a grace period to elapse. - -Pseudo-code using rcu_barrier() is as follows: - - 1. Prevent any new RCU callbacks from being posted. - 2. Execute rcu_barrier(). - 3. Allow the module to be unloaded. - -There is also an srcu_barrier() function for SRCU, and you of course -must match the flavor of rcu_barrier() with that of call_rcu(). If your -module uses multiple flavors of call_rcu(), then it must also use multiple -flavors of rcu_barrier() when unloading that module. For example, if -it uses call_rcu(), call_srcu() on srcu_struct_1, and call_srcu() on -srcu_struct_2(), then the following three lines of code will be required -when unloading: - - 1 rcu_barrier(); - 2 srcu_barrier(&srcu_struct_1); - 3 srcu_barrier(&srcu_struct_2); - -The rcutorture module makes use of rcu_barrier() in its exit function -as follows: - - 1 static void - 2 rcu_torture_cleanup(void) - 3 { - 4 int i; - 5 - 6 fullstop = 1; - 7 if (shuffler_task != NULL) { - 8 VERBOSE_PRINTK_STRING("Stopping rcu_torture_shuffle task"); - 9 kthread_stop(shuffler_task); -10 } -11 shuffler_task = NULL; -12 -13 if (writer_task != NULL) { -14 VERBOSE_PRINTK_STRING("Stopping rcu_torture_writer task"); -15 kthread_stop(writer_task); -16 } -17 writer_task = NULL; -18 -19 if (reader_tasks != NULL) { -20 for (i = 0; i < nrealreaders; i++) { -21 if (reader_tasks[i] != NULL) { -22 VERBOSE_PRINTK_STRING( -23 "Stopping rcu_torture_reader task"); -24 kthread_stop(reader_tasks[i]); -25 } -26 reader_tasks[i] = NULL; -27 } -28 kfree(reader_tasks); -29 reader_tasks = NULL; -30 } -31 rcu_torture_current = NULL; -32 -33 if (fakewriter_tasks != NULL) { -34 for (i = 0; i < nfakewriters; i++) { -35 if (fakewriter_tasks[i] != NULL) { -36 VERBOSE_PRINTK_STRING( -37 "Stopping rcu_torture_fakewriter task"); -38 kthread_stop(fakewriter_tasks[i]); -39 } -40 fakewriter_tasks[i] = NULL; -41 } -42 kfree(fakewriter_tasks); -43 fakewriter_tasks = NULL; -44 } -45 -46 if (stats_task != NULL) { -47 VERBOSE_PRINTK_STRING("Stopping rcu_torture_stats task"); -48 kthread_stop(stats_task); -49 } -50 stats_task = NULL; -51 -52 /* Wait for all RCU callbacks to fire. */ -53 rcu_barrier(); -54 -55 rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ -56 -57 if (cur_ops->cleanup != NULL) -58 cur_ops->cleanup(); -59 if (atomic_read(&n_rcu_torture_error)) -60 rcu_torture_print_module_parms("End of test: FAILURE"); -61 else -62 rcu_torture_print_module_parms("End of test: SUCCESS"); -63 } - -Line 6 sets a global variable that prevents any RCU callbacks from -re-posting themselves. This will not be necessary in most cases, since -RCU callbacks rarely include calls to call_rcu(). However, the rcutorture -module is an exception to this rule, and therefore needs to set this -global variable. - -Lines 7-50 stop all the kernel tasks associated with the rcutorture -module. Therefore, once execution reaches line 53, no more rcutorture -RCU callbacks will be posted. The rcu_barrier() call on line 53 waits -for any pre-existing callbacks to complete. - -Then lines 55-62 print status and do operation-specific cleanup, and -then return, permitting the module-unload operation to be completed. - -Quick Quiz #1: Is there any other situation where rcu_barrier() might - be required? - -Your module might have additional complications. For example, if your -module invokes call_rcu() from timers, you will need to first cancel all -the timers, and only then invoke rcu_barrier() to wait for any remaining -RCU callbacks to complete. - -Of course, if you module uses call_rcu(), you will need to invoke -rcu_barrier() before unloading. Similarly, if your module uses -call_srcu(), you will need to invoke srcu_barrier() before unloading, -and on the same srcu_struct structure. If your module uses call_rcu() --and- call_srcu(), then you will need to invoke rcu_barrier() -and- -srcu_barrier(). - - -Implementing rcu_barrier() - -Dipankar Sarma's implementation of rcu_barrier() makes use of the fact -that RCU callbacks are never reordered once queued on one of the per-CPU -queues. His implementation queues an RCU callback on each of the per-CPU -callback queues, and then waits until they have all started executing, at -which point, all earlier RCU callbacks are guaranteed to have completed. - -The original code for rcu_barrier() was as follows: - - 1 void rcu_barrier(void) - 2 { - 3 BUG_ON(in_interrupt()); - 4 /* Take cpucontrol mutex to protect against CPU hotplug */ - 5 mutex_lock(&rcu_barrier_mutex); - 6 init_completion(&rcu_barrier_completion); - 7 atomic_set(&rcu_barrier_cpu_count, 0); - 8 on_each_cpu(rcu_barrier_func, NULL, 0, 1); - 9 wait_for_completion(&rcu_barrier_completion); -10 mutex_unlock(&rcu_barrier_mutex); -11 } - -Line 3 verifies that the caller is in process context, and lines 5 and 10 -use rcu_barrier_mutex to ensure that only one rcu_barrier() is using the -global completion and counters at a time, which are initialized on lines -6 and 7. Line 8 causes each CPU to invoke rcu_barrier_func(), which is -shown below. Note that the final "1" in on_each_cpu()'s argument list -ensures that all the calls to rcu_barrier_func() will have completed -before on_each_cpu() returns. Line 9 then waits for the completion. - -This code was rewritten in 2008 and several times thereafter, but this -still gives the general idea. - -The rcu_barrier_func() runs on each CPU, where it invokes call_rcu() -to post an RCU callback, as follows: - - 1 static void rcu_barrier_func(void *notused) - 2 { - 3 int cpu = smp_processor_id(); - 4 struct rcu_data *rdp = &per_cpu(rcu_data, cpu); - 5 struct rcu_head *head; - 6 - 7 head = &rdp->barrier; - 8 atomic_inc(&rcu_barrier_cpu_count); - 9 call_rcu(head, rcu_barrier_callback); -10 } - -Lines 3 and 4 locate RCU's internal per-CPU rcu_data structure, -which contains the struct rcu_head that needed for the later call to -call_rcu(). Line 7 picks up a pointer to this struct rcu_head, and line -8 increments a global counter. This counter will later be decremented -by the callback. Line 9 then registers the rcu_barrier_callback() on -the current CPU's queue. - -The rcu_barrier_callback() function simply atomically decrements the -rcu_barrier_cpu_count variable and finalizes the completion when it -reaches zero, as follows: - - 1 static void rcu_barrier_callback(struct rcu_head *notused) - 2 { - 3 if (atomic_dec_and_test(&rcu_barrier_cpu_count)) - 4 complete(&rcu_barrier_completion); - 5 } - -Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes - immediately (thus incrementing rcu_barrier_cpu_count to the - value one), but the other CPU's rcu_barrier_func() invocations - are delayed for a full grace period? Couldn't this result in - rcu_barrier() returning prematurely? - -The current rcu_barrier() implementation is more complex, due to the need -to avoid disturbing idle CPUs (especially on battery-powered systems) -and the need to minimally disturb non-idle CPUs in real-time systems. -However, the code above illustrates the concepts. - - -rcu_barrier() Summary - -The rcu_barrier() primitive has seen relatively little use, since most -code using RCU is in the core kernel rather than in modules. However, if -you are using RCU from an unloadable module, you need to use rcu_barrier() -so that your module may be safely unloaded. - - -Answers to Quick Quizzes - -Quick Quiz #1: Is there any other situation where rcu_barrier() might - be required? - -Answer: Interestingly enough, rcu_barrier() was not originally - implemented for module unloading. Nikita Danilov was using - RCU in a filesystem, which resulted in a similar situation at - filesystem-unmount time. Dipankar Sarma coded up rcu_barrier() - in response, so that Nikita could invoke it during the - filesystem-unmount process. - - Much later, yours truly hit the RCU module-unload problem when - implementing rcutorture, and found that rcu_barrier() solves - this problem as well. - -Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes - immediately (thus incrementing rcu_barrier_cpu_count to the - value one), but the other CPU's rcu_barrier_func() invocations - are delayed for a full grace period? Couldn't this result in - rcu_barrier() returning prematurely? - -Answer: This cannot happen. The reason is that on_each_cpu() has its last - argument, the wait flag, set to "1". This flag is passed through - to smp_call_function() and further to smp_call_function_on_cpu(), - causing this latter to spin until the cross-CPU invocation of - rcu_barrier_func() has completed. This by itself would prevent - a grace period from completing on non-CONFIG_PREEMPT kernels, - since each CPU must undergo a context switch (or other quiescent - state) before the grace period can complete. However, this is - of no use in CONFIG_PREEMPT kernels. - - Therefore, on_each_cpu() disables preemption across its call - to smp_call_function() and also across the local call to - rcu_barrier_func(). This prevents the local CPU from context - switching, again preventing grace periods from completing. This - means that all CPUs have executed rcu_barrier_func() before - the first rcu_barrier_callback() can possibly execute, in turn - preventing rcu_barrier_cpu_count from prematurely reaching zero. - - Currently, -rt implementations of RCU keep but a single global - queue for RCU callbacks, and thus do not suffer from this - problem. However, when the -rt RCU eventually does have per-CPU - callback queues, things will have to change. One simple change - is to add an rcu_read_lock() before line 8 of rcu_barrier() - and an rcu_read_unlock() after line 8 of this same function. If - you can think of a better change, please let me know! -- cgit v1.2.3 From 17f0da13873ba393a72f14d41ffc8ff388e38723 Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Mon, 11 Nov 2019 23:41:22 +0530 Subject: doc: Updated full list of RCU API in whatisRCU.rst This patch updates the list of RCU API in whatisRCU.rst. Signed-off-by: Madhuparna Bhowmik Tested-by: Amol Grover Tested-by: Phong Tran Signed-off-by: Paul E. McKenney --- Documentation/RCU/whatisRCU.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/RCU/whatisRCU.rst b/Documentation/RCU/whatisRCU.rst index 2f6f6ebbc8b0..c7f147b8034f 100644 --- a/Documentation/RCU/whatisRCU.rst +++ b/Documentation/RCU/whatisRCU.rst @@ -884,11 +884,14 @@ in docbook. Here is the list, by category. RCU list traversal:: list_entry_rcu + list_entry_lockless list_first_entry_rcu list_next_rcu list_for_each_entry_rcu list_for_each_entry_continue_rcu list_for_each_entry_from_rcu + list_first_or_null_rcu + list_next_or_null_rcu hlist_first_rcu hlist_next_rcu hlist_pprev_rcu @@ -902,7 +905,7 @@ RCU list traversal:: hlist_bl_first_rcu hlist_bl_for_each_entry_rcu -RCU pointer/list udate:: +RCU pointer/list update:: rcu_assign_pointer list_add_rcu @@ -912,10 +915,12 @@ RCU pointer/list udate:: hlist_add_behind_rcu hlist_add_before_rcu hlist_add_head_rcu + hlist_add_tail_rcu hlist_del_rcu hlist_del_init_rcu hlist_replace_rcu - list_splice_init_rcu() + list_splice_init_rcu + list_splice_tail_init_rcu hlist_nulls_del_init_rcu hlist_nulls_del_rcu hlist_nulls_add_head_rcu -- cgit v1.2.3 From 6e6eca2ee79a23329093cdf8d1cc0bd86128981f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 13 Nov 2019 09:12:59 -0800 Subject: doc: Fix typo "deference" to "dereference" Reported-by: Jens Axboe Signed-off-by: Paul E. McKenney --- Documentation/RCU/lockdep-splat.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/RCU/lockdep-splat.txt b/Documentation/RCU/lockdep-splat.txt index 9c015976b174..b8096316fd11 100644 --- a/Documentation/RCU/lockdep-splat.txt +++ b/Documentation/RCU/lockdep-splat.txt @@ -99,7 +99,7 @@ With this change, the rcu_dereference() is always within an RCU read-side critical section, which again would have suppressed the above lockdep-RCU splat. -But in this particular case, we don't actually deference the pointer +But in this particular case, we don't actually dereference the pointer returned from rcu_dereference(). Instead, that pointer is just compared to the cic pointer, which means that the rcu_dereference() can be replaced by rcu_access_pointer() as follows: -- cgit v1.2.3 From 813dede18088402825c63f751a99b65f28a18155 Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Fri, 15 Nov 2019 16:29:11 +0530 Subject: dt-bindings: msm: Rename cache-controller to system-cache-controller DT schema checks for the node name 'cache-controller' and enforces that there has to be a cache-level associated with it. But LLCC is a system cache and does not have a cache-level property and hence the dt binding check fails. So let us rename the LLCC cache-controller to system-cache-controller which is the proper description and also makes the schema happy. Acked-by: Rob Herring Reviewed-by: Stephen Boyd Suggested-by: Stephen Boyd Signed-off-by: Sai Prakash Ranjan Link: https://lore.kernel.org/r/83394ae827ce7c123228b749bcae2a2c470e88a4.1573814758.git.saiprakash.ranjan@codeaurora.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml index 558749065b97..79902f470e4b 100644 --- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml +++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml @@ -47,7 +47,7 @@ examples: - | #include - cache-controller@1100000 { + system-cache-controller@1100000 { compatible = "qcom,sdm845-llcc"; reg = <0x1100000 0x200000>, <0x1300000 0x50000> ; reg-names = "llcc_base", "llcc_broadcast_base"; -- cgit v1.2.3 From f10870b05d5edc0652701c6a92eafcab5044795f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Dec 2019 21:59:15 +0100 Subject: staging: remove isdn capi drivers As described in drivers/staging/isdn/TODO, the drivers are all assumed to be unmaintained and unused now, with gigaset being the last one to stop being maintained after Paul Bolle lost access to an ISDN network. The CAPI subsystem remains for now, as it is still required by bluetooth/cmtp. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191210210455.3475361-1-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- Documentation/isdn/avmb1.rst | 246 -- Documentation/isdn/gigaset.rst | 465 ---- Documentation/isdn/hysdn.rst | 196 -- Documentation/isdn/index.rst | 3 - Documentation/userspace-api/ioctl/ioctl-number.rst | 1 - MAINTAINERS | 3 +- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/isdn/Kconfig | 12 - drivers/staging/isdn/Makefile | 8 - drivers/staging/isdn/TODO | 22 - drivers/staging/isdn/avm/Kconfig | 65 - drivers/staging/isdn/avm/Makefile | 12 - drivers/staging/isdn/avm/avm_cs.c | 166 -- drivers/staging/isdn/avm/avmcard.h | 581 ----- drivers/staging/isdn/avm/b1.c | 819 ------ drivers/staging/isdn/avm/b1dma.c | 981 ------- drivers/staging/isdn/avm/b1isa.c | 243 -- drivers/staging/isdn/avm/b1pci.c | 416 --- drivers/staging/isdn/avm/b1pcmcia.c | 224 -- drivers/staging/isdn/avm/c4.c | 1317 ---------- drivers/staging/isdn/avm/t1isa.c | 594 ----- drivers/staging/isdn/avm/t1pci.c | 259 -- drivers/staging/isdn/gigaset/Kconfig | 62 - drivers/staging/isdn/gigaset/Makefile | 17 - drivers/staging/isdn/gigaset/asyncdata.c | 606 ----- drivers/staging/isdn/gigaset/bas-gigaset.c | 2672 -------------------- drivers/staging/isdn/gigaset/capi.c | 2517 ------------------ drivers/staging/isdn/gigaset/common.c | 1153 --------- drivers/staging/isdn/gigaset/dummyll.c | 74 - drivers/staging/isdn/gigaset/ev-layer.c | 1910 -------------- drivers/staging/isdn/gigaset/gigaset.h | 827 ------ drivers/staging/isdn/gigaset/interface.c | 613 ----- drivers/staging/isdn/gigaset/isocdata.c | 1006 -------- drivers/staging/isdn/gigaset/proc.c | 77 - drivers/staging/isdn/gigaset/ser-gigaset.c | 796 ------ drivers/staging/isdn/gigaset/usb-gigaset.c | 946 ------- drivers/staging/isdn/hysdn/Kconfig | 15 - drivers/staging/isdn/hysdn/Makefile | 12 - drivers/staging/isdn/hysdn/boardergo.c | 445 ---- drivers/staging/isdn/hysdn/boardergo.h | 100 - drivers/staging/isdn/hysdn/hycapi.c | 785 ------ drivers/staging/isdn/hysdn/hysdn_boot.c | 400 --- drivers/staging/isdn/hysdn/hysdn_defs.h | 282 --- drivers/staging/isdn/hysdn/hysdn_init.c | 213 -- drivers/staging/isdn/hysdn/hysdn_net.c | 330 --- drivers/staging/isdn/hysdn/hysdn_pof.h | 78 - drivers/staging/isdn/hysdn/hysdn_procconf.c | 411 --- drivers/staging/isdn/hysdn/hysdn_proclog.c | 357 --- drivers/staging/isdn/hysdn/hysdn_sched.c | 197 -- drivers/staging/isdn/hysdn/ince1pc.h | 134 - include/linux/b1pcmcia.h | 21 - include/uapi/linux/gigaset_dev.h | 39 - include/uapi/linux/hysdn_if.h | 34 - 54 files changed, 1 insertion(+), 23764 deletions(-) delete mode 100644 Documentation/isdn/avmb1.rst delete mode 100644 Documentation/isdn/gigaset.rst delete mode 100644 Documentation/isdn/hysdn.rst delete mode 100644 drivers/staging/isdn/Kconfig delete mode 100644 drivers/staging/isdn/Makefile delete mode 100644 drivers/staging/isdn/TODO delete mode 100644 drivers/staging/isdn/avm/Kconfig delete mode 100644 drivers/staging/isdn/avm/Makefile delete mode 100644 drivers/staging/isdn/avm/avm_cs.c delete mode 100644 drivers/staging/isdn/avm/avmcard.h delete mode 100644 drivers/staging/isdn/avm/b1.c delete mode 100644 drivers/staging/isdn/avm/b1dma.c delete mode 100644 drivers/staging/isdn/avm/b1isa.c delete mode 100644 drivers/staging/isdn/avm/b1pci.c delete mode 100644 drivers/staging/isdn/avm/b1pcmcia.c delete mode 100644 drivers/staging/isdn/avm/c4.c delete mode 100644 drivers/staging/isdn/avm/t1isa.c delete mode 100644 drivers/staging/isdn/avm/t1pci.c delete mode 100644 drivers/staging/isdn/gigaset/Kconfig delete mode 100644 drivers/staging/isdn/gigaset/Makefile delete mode 100644 drivers/staging/isdn/gigaset/asyncdata.c delete mode 100644 drivers/staging/isdn/gigaset/bas-gigaset.c delete mode 100644 drivers/staging/isdn/gigaset/capi.c delete mode 100644 drivers/staging/isdn/gigaset/common.c delete mode 100644 drivers/staging/isdn/gigaset/dummyll.c delete mode 100644 drivers/staging/isdn/gigaset/ev-layer.c delete mode 100644 drivers/staging/isdn/gigaset/gigaset.h delete mode 100644 drivers/staging/isdn/gigaset/interface.c delete mode 100644 drivers/staging/isdn/gigaset/isocdata.c delete mode 100644 drivers/staging/isdn/gigaset/proc.c delete mode 100644 drivers/staging/isdn/gigaset/ser-gigaset.c delete mode 100644 drivers/staging/isdn/gigaset/usb-gigaset.c delete mode 100644 drivers/staging/isdn/hysdn/Kconfig delete mode 100644 drivers/staging/isdn/hysdn/Makefile delete mode 100644 drivers/staging/isdn/hysdn/boardergo.c delete mode 100644 drivers/staging/isdn/hysdn/boardergo.h delete mode 100644 drivers/staging/isdn/hysdn/hycapi.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_boot.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_defs.h delete mode 100644 drivers/staging/isdn/hysdn/hysdn_init.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_net.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_pof.h delete mode 100644 drivers/staging/isdn/hysdn/hysdn_procconf.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_proclog.c delete mode 100644 drivers/staging/isdn/hysdn/hysdn_sched.c delete mode 100644 drivers/staging/isdn/hysdn/ince1pc.h delete mode 100644 include/linux/b1pcmcia.h delete mode 100644 include/uapi/linux/gigaset_dev.h delete mode 100644 include/uapi/linux/hysdn_if.h (limited to 'Documentation') diff --git a/Documentation/isdn/avmb1.rst b/Documentation/isdn/avmb1.rst deleted file mode 100644 index de3961e67553..000000000000 --- a/Documentation/isdn/avmb1.rst +++ /dev/null @@ -1,246 +0,0 @@ -================================ -Driver for active AVM Controller -================================ - -The driver provides a kernel capi2.0 Interface (kernelcapi) and -on top of this a User-Level-CAPI2.0-interface (capi) -and a driver to connect isdn4linux with CAPI2.0 (capidrv). -The lowlevel interface can be used to implement a CAPI2.0 -also for passive cards since July 1999. - -The author can be reached at calle@calle.in-berlin.de. -The command avmcapictrl is part of the isdn4k-utils. -t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware - -Currently supported cards: - - - B1 ISA (all versions) - - B1 PCI - - T1/T1B (HEMA card) - - M1 - - M2 - - B1 PCMCIA - -Installing ----------- - -You need at least /dev/capi20 to load the firmware. - -:: - - mknod /dev/capi20 c 68 0 - mknod /dev/capi20.00 c 68 1 - mknod /dev/capi20.01 c 68 2 - . - . - . - mknod /dev/capi20.19 c 68 20 - -Running -------- - -To use the card you need the t4-files to download the firmware. -AVM GmbH provides several t4-files for the different D-channel -protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn. - -if you configure as modules load the modules this way:: - - insmod /lib/modules/current/misc/capiutil.o - insmod /lib/modules/current/misc/b1.o - insmod /lib/modules/current/misc/kernelcapi.o - insmod /lib/modules/current/misc/capidrv.o - insmod /lib/modules/current/misc/capi.o - -if you have an B1-PCI card load the module b1pci.o:: - - insmod /lib/modules/current/misc/b1pci.o - -and load the firmware with:: - - avmcapictrl load /lib/isdn/b1.t4 1 - -if you have an B1-ISA card load the module b1isa.o -and add the card by calling:: - - avmcapictrl add 0x150 15 - -and load the firmware by calling:: - - avmcapictrl load /lib/isdn/b1.t4 1 - -if you have an T1-ISA card load the module t1isa.o -and add the card by calling:: - - avmcapictrl add 0x450 15 T1 0 - -and load the firmware by calling:: - - avmcapictrl load /lib/isdn/t1.t4 1 - -if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o -before you insert the card. - -Leased Lines with B1 --------------------- - -Init card and load firmware. - -For an D64S use "FV: 1" as phone number - -For an D64S2 use "FV: 1" and "FV: 2" for multilink -or "FV: 1,2" to use CAPI channel bundling. - -/proc-Interface ------------------ - -/proc/capi:: - - dr-xr-xr-x 2 root root 0 Jul 1 14:03 . - dr-xr-xr-x 82 root root 0 Jun 30 19:08 .. - -r--r--r-- 1 root root 0 Jul 1 14:03 applications - -r--r--r-- 1 root root 0 Jul 1 14:03 applstats - -r--r--r-- 1 root root 0 Jul 1 14:03 capi20 - -r--r--r-- 1 root root 0 Jul 1 14:03 capidrv - -r--r--r-- 1 root root 0 Jul 1 14:03 controller - -r--r--r-- 1 root root 0 Jul 1 14:03 contrstats - -r--r--r-- 1 root root 0 Jul 1 14:03 driver - -r--r--r-- 1 root root 0 Jul 1 14:03 ncci - -r--r--r-- 1 root root 0 Jul 1 14:03 users - -/proc/capi/applications: - applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen - level3cnt: - capi_register parameter - datablkcnt: - capi_register parameter - ncci-cnt: - current number of nccis (connections) - recvqueuelen: - number of messages on receive queue - - for example:: - - 1 -2 16 2048 1 0 - 2 2 7 2048 1 0 - -/proc/capi/applstats: - applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg - recvctlmsg: - capi messages received without DATA_B3_IND - recvdatamsg: - capi DATA_B3_IND received - sentctlmsg: - capi messages sent without DATA_B3_REQ - sentdatamsg: - capi DATA_B3_REQ sent - - for example:: - - 1 2057 1699 1721 1699 - -/proc/capi/capi20: statistics of capi.o (/dev/capi20) - minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - minor: - minor device number of capi device - nopen: - number of calls to devices open - nrecvdropmsg: - capi messages dropped (messages in recvqueue in close) - nrecvctlmsg: - capi messages received without DATA_B3_IND - nrecvdatamsg: - capi DATA_B3_IND received - nsentctlmsg: - capi messages sent without DATA_B3_REQ - nsentdatamsg: - capi DATA_B3_REQ sent - - for example:: - - 1 2 18 0 16 2 - -/proc/capi/capidrv: statistics of capidrv.o (capi messages) - nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: - capi messages received without DATA_B3_IND - nrecvdatamsg: - capi DATA_B3_IND received - nsentctlmsg: - capi messages sent without DATA_B3_REQ - nsentdatamsg: - capi DATA_B3_REQ sent - - for example: - 2780 2226 2256 2226 - -/proc/capi/controller: - controller drivername state cardname controllerinfo - - for example:: - - 1 b1pci running b1pci-e000 B1 3.07-01 0xe000 19 - 2 t1isa running t1isa-450 B1 3.07-01 0x450 11 0 - 3 b1pcmcia running m2-150 B1 3.07-01 0x150 5 - -/proc/capi/contrstats: - controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: - capi messages received without DATA_B3_IND - nrecvdatamsg: - capi DATA_B3_IND received - nsentctlmsg: - capi messages sent without DATA_B3_REQ - nsentdatamsg: - capi DATA_B3_REQ sent - - for example:: - - 1 2845 2272 2310 2274 - 2 2 0 2 0 - 3 2 0 2 0 - -/proc/capi/driver: - drivername ncontroller - - for example:: - - b1pci 1 - t1isa 1 - b1pcmcia 1 - b1isa 0 - -/proc/capi/ncci: - apllid ncci winsize sendwindow - - for example:: - - 1 0x10101 8 0 - -/proc/capi/users: kernelmodules that use the kernelcapi. - name - - for example:: - - capidrv - capi20 - -Questions ---------- - -Check out the FAQ (ftp.isdn4linux.de) or subscribe to the -linux-avmb1@calle.in-berlin.de mailing list by sending -a mail to majordomo@calle.in-berlin.de with -subscribe linux-avmb1 -in the body. - -German documentation and several scripts can be found at -ftp://ftp.avm.de/cardware/b1/linux/ - -Bugs ----- - -If you find any please let me know. - -Enjoy, - -Carsten Paeth (calle@calle.in-berlin.de) diff --git a/Documentation/isdn/gigaset.rst b/Documentation/isdn/gigaset.rst deleted file mode 100644 index 98b4ec521c51..000000000000 --- a/Documentation/isdn/gigaset.rst +++ /dev/null @@ -1,465 +0,0 @@ -========================== -GigaSet 307x Device Driver -========================== - -1. Requirements -================= - -1.1. Hardware -------------- - - This driver supports the connection of the Gigaset 307x/417x family of - ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB - connection. The following devices are reported to be compatible: - - Bases: - - Siemens Gigaset 3070/3075 isdn - - Siemens Gigaset 4170/4175 isdn - - Siemens Gigaset SX205/255 - - Siemens Gigaset SX353 - - T-Com Sinus 45 [AB] isdn - - T-Com Sinus 721X[A] [SE] - - Vox Chicago 390 ISDN (KPN Telecom) - - RS232 data boxes: - - Siemens Gigaset M101 Data - - T-Com Sinus 45 Data 1 - - USB data boxes: - - Siemens Gigaset M105 Data - - Siemens Gigaset USB Adapter DECT - - T-Com Sinus 45 Data 2 - - T-Com Sinus 721 data - - Chicago 390 USB (KPN) - - See also http://www.erbze.info/sinus_gigaset.htm - (archived at https://web.archive.org/web/20100717020421/http://www.erbze.info:80/sinus_gigaset.htm ) and - http://gigaset307x.sourceforge.net/ - - We had also reports from users of Gigaset M105 who could use the drivers - with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.5.) - If you have another device that works with our driver, please let us know. - - Chances of getting an USB device to work are good if the output of:: - - lsusb - - at the command line contains one of the following:: - - ID 0681:0001 - ID 0681:0002 - ID 0681:0009 - ID 0681:0021 - ID 0681:0022 - -1.2. Software -------------- - - The driver works with the Kernel CAPI subsystem and can be used with any - software which is able to use CAPI 2.0 for ISDN connections (voice or data). - - There are some user space tools available at - https://sourceforge.net/projects/gigaset307x/ - which provide access to additional device specific functions like SMS, - phonebook or call journal. - - -2. How to use the driver -========================== - -2.1. Modules ------------- - - For the devices to work, the proper kernel modules have to be loaded. - This normally happens automatically when the system detects the USB - device (base, M105) or when the line discipline is attached (M101). It - can also be triggered manually using the modprobe(8) command, for example - for troubleshooting or to pass module parameters. - - The module ser_gigaset provides a serial line discipline N_GIGASET_M101 - which uses the regular serial port driver to access the device, and must - therefore be attached to the serial device to which the M101 is connected. - The ldattach(8) command (included in util-linux-ng release 2.14 or later) - can be used for that purpose, for example:: - - ldattach GIGASET_M101 /dev/ttyS1 - - This will open the device file, attach the line discipline to it, and - then sleep in the background, keeping the device open so that the line - discipline remains active. To deactivate it, kill the daemon, for example - with:: - - killall ldattach - - before disconnecting the device. To have this happen automatically at - system startup/shutdown on an LSB compatible system, create and activate - an appropriate LSB startup script /etc/init.d/gigaset. (The init name - 'gigaset' is officially assigned to this project by LANANA.) - Alternatively, just add the 'ldattach' command line to /etc/rc.local. - - The modules accept the following parameters: - - =============== ========== ========================================== - Module Parameter Meaning - - gigaset debug debug level (see section 3.2.) - - startmode initial operation mode (see section 2.5.): - bas_gigaset ) 1=CAPI (default), 0=Unimodem - ser_gigaset ) - usb_gigaset ) cidmode initial Call-ID mode setting (see section - 2.5.): 1=on (default), 0=off - - =============== ========== ========================================== - - Depending on your distribution you may want to create a separate module - configuration file like /etc/modprobe.d/gigaset.conf for these. - -2.2. Device nodes for user space programs ------------------------------------------ - - The device can be accessed from user space (eg. by the user space tools - mentioned in 1.2.) through the device nodes: - - - /dev/ttyGS0 for M101 (RS232 data boxes) - - /dev/ttyGU0 for M105 (USB data boxes) - - /dev/ttyGB0 for the base driver (direct USB connection) - - If you connect more than one device of a type, they will get consecutive - device nodes, eg. /dev/ttyGU1 for a second M105. - - You can also set a "default device" for the user space tools to use when - no device node is given as parameter, by creating a symlink /dev/ttyG to - one of them, eg.:: - - ln -s /dev/ttyGB0 /dev/ttyG - - The devices accept the following device specific ioctl calls - (defined in gigaset_dev.h): - - ``ioctl(int fd, GIGASET_REDIR, int *cmd);`` - - If cmd==1, the device is set to be controlled exclusively through the - character device node; access from the ISDN subsystem is blocked. - - If cmd==0, the device is set to be used from the ISDN subsystem and does - not communicate through the character device node. - - ``ioctl(int fd, GIGASET_CONFIG, int *cmd);`` - - (ser_gigaset and usb_gigaset only) - - If cmd==1, the device is set to adapter configuration mode where commands - are interpreted by the M10x DECT adapter itself instead of being - forwarded to the base station. In this mode, the device accepts the - commands described in Siemens document "AT-Kommando Alignment M10x Data" - for setting the operation mode, associating with a base station and - querying parameters like field strengh and signal quality. - - Note that there is no ioctl command for leaving adapter configuration - mode and returning to regular operation. In order to leave adapter - configuration mode, write the command ATO to the device. - - ``ioctl(int fd, GIGASET_BRKCHARS, unsigned char brkchars[6]);`` - - (usb_gigaset only) - - Set the break characters on an M105's internal serial adapter to the six - bytes stored in brkchars[]. Unused bytes should be set to zero. - - ioctl(int fd, GIGASET_VERSION, unsigned version[4]); - Retrieve version information from the driver. version[0] must be set to - one of: - - - GIGVER_DRIVER: retrieve driver version - - GIGVER_COMPAT: retrieve interface compatibility version - - GIGVER_FWBASE: retrieve the firmware version of the base - - Upon return, version[] is filled with the requested version information. - -2.3. CAPI ---------- - - The devices will show up as CAPI controllers as soon as the - corresponding driver module is loaded, and can then be used with - CAPI 2.0 kernel and user space applications. For user space access, - the module capi.ko must be loaded. - - Most distributions handle loading and unloading of the various CAPI - modules automatically via the command capiinit(1) from the capi4k-utils - package or a similar mechanism. Note that capiinit(1) cannot unload the - Gigaset drivers because it doesn't support more than one module per - driver. - -2.5. Unimodem mode ------------------- - - In this mode the device works like a modem connected to a serial port - (the /dev/ttyGU0, ... mentioned above) which understands the commands:: - - ATZ init, reset - => OK or ERROR - ATD - ATDT dial - => OK, CONNECT, - BUSY, - NO DIAL TONE, - NO CARRIER, - NO ANSWER - +++ change to command mode when connected - ATH hangup - - You can use some configuration tool of your distribution to configure this - "modem" or configure pppd/wvdial manually. There are some example ppp - configuration files and chat scripts in the gigaset-VERSION/ppp directory - in the driver packages from https://sourceforge.net/projects/gigaset307x/. - Please note that the USB drivers are not able to change the state of the - control lines. This means you must use "Stupid Mode" if you are using - wvdial or you should use the nocrtscts option of pppd. - You must also assure that the ppp_async module is loaded with the parameter - flag_time=0. You can do this e.g. by adding a line like:: - - options ppp_async flag_time=0 - - to an appropriate module configuration file, like:: - - /etc/modprobe.d/gigaset.conf. - - Unimodem mode is needed for making some devices [e.g. SX100] work which - do not support the regular Gigaset command set. If debug output (see - section 3.2.) shows something like this when dialing:: - - CMD Received: ERROR - Available Params: 0 - Connection State: 0, Response: -1 - gigaset_process_response: resp_code -1 in ConState 0 ! - Timeout occurred - - then switching to unimodem mode may help. - - If you have installed the command line tool gigacontr, you can enter - unimodem mode using:: - - gigacontr --mode unimodem - - You can switch back using:: - - gigacontr --mode isdn - - You can also put the driver directly into Unimodem mode when it's loaded, - by passing the module parameter startmode=0 to the hardware specific - module, e.g.:: - - modprobe usb_gigaset startmode=0 - - or by adding a line like:: - - options usb_gigaset startmode=0 - - to an appropriate module configuration file, like:: - - /etc/modprobe.d/gigaset.conf - -2.6. Call-ID (CID) mode ------------------------ - - Call-IDs are numbers used to tag commands to, and responses from, the - Gigaset base in order to support the simultaneous handling of multiple - ISDN calls. Their use can be enabled ("CID mode") or disabled ("Unimodem - mode"). Without Call-IDs (in Unimodem mode), only a very limited set of - functions is available. It allows outgoing data connections only, but - does not signal incoming calls or other base events. - - DECT cordless data devices (M10x) permanently occupy the cordless - connection to the base while Call-IDs are activated. As the Gigaset - bases only support one DECT data connection at a time, this prevents - other DECT cordless data devices from accessing the base. - - During active operation, the driver switches to the necessary mode - automatically. However, for the reasons above, the mode chosen when - the device is not in use (idle) can be selected by the user. - - - If you want to receive incoming calls, you can use the default - settings (CID mode). - - If you have several DECT data devices (M10x) which you want to use - in turn, select Unimodem mode by passing the parameter "cidmode=0" to - the appropriate driver module (ser_gigaset or usb_gigaset). - - If you want both of these at once, you are out of luck. - - You can also use the tty class parameter "cidmode" of the device to - change its CID mode while the driver is loaded, eg.:: - - echo 0 > /sys/class/tty/ttyGU0/cidmode - -2.7. Dialing Numbers --------------------- -provided by an application for dialing out must - be a public network number according to the local dialing plan, without - any dial prefix for getting an outside line. - - Internal calls can be made by providing an internal extension number - prefixed with ``**`` (two asterisks) as the called party number. So to dial - eg. the first registered DECT handset, give ``**11`` as the called party - number. Dialing ``***`` (three asterisks) calls all extensions - simultaneously (global call). - - Unimodem mode does not support internal calls. - -2.8. Unregistered Wireless Devices (M101/M105) ----------------------------------------------- - - The main purpose of the ser_gigaset and usb_gigaset drivers is to allow - the M101 and M105 wireless devices to be used as ISDN devices for ISDN - connections through a Gigaset base. Therefore they assume that the device - is registered to a DECT base. - - If the M101/M105 device is not registered to a base, initialization of - the device fails, and a corresponding error message is logged by the - driver. In that situation, a restricted set of functions is available - which includes, in particular, those necessary for registering the device - to a base or for switching it between Fixed Part and Portable Part - modes. See the gigacontr(8) manpage for details. - -3. Troubleshooting -==================== - -3.1. Solutions to frequently reported problems ----------------------------------------------- - - Problem: - You have a slow provider and isdn4linux gives up dialing too early. - Solution: - Load the isdn module using the dialtimeout option. You can do this e.g. - by adding a line like:: - - options isdn dialtimeout=15 - - to /etc/modprobe.d/gigaset.conf or a similar file. - - Problem: - The isdnlog program emits error messages or just doesn't work. - Solution: - Isdnlog supports only the HiSax driver. Do not attempt to use it with - other drivers such as Gigaset. - - Problem: - You have two or more DECT data adapters (M101/M105) and only the - first one you turn on works. - Solution: - Select Unimodem mode for all DECT data adapters. (see section 2.5.) - - Problem: - Messages like this:: - - usb_gigaset 3-2:1.0: Could not initialize the device. - - appear in your syslog. - Solution: - Check whether your M10x wireless device is correctly registered to the - Gigaset base. (see section 2.7.) - -3.2. Telling the driver to provide more information ---------------------------------------------------- - Building the driver with the "Gigaset debugging" kernel configuration - option (CONFIG_GIGASET_DEBUG) gives it the ability to produce additional - information useful for debugging. - - You can control the amount of debugging information the driver produces by - writing an appropriate value to /sys/module/gigaset/parameters/debug, - e.g.:: - - echo 0 > /sys/module/gigaset/parameters/debug - - switches off debugging output completely, - - :: - - echo 0x302020 > /sys/module/gigaset/parameters/debug - - enables a reasonable set of debugging output messages. These values are - bit patterns where every bit controls a certain type of debugging output. - See the constants DEBUG_* in the source file gigaset.h for details. - - The initial value can be set using the debug parameter when loading the - module "gigaset", e.g. by adding a line:: - - options gigaset debug=0 - - to your module configuration file, eg. /etc/modprobe.d/gigaset.conf - - Generated debugging information can be found - - as output of the command:: - - dmesg - - - in system log files written by your syslog daemon, usually - in /var/log/, e.g. /var/log/messages. - -3.3. Reporting problems and bugs --------------------------------- - If you can't solve problems with the driver on your own, feel free to - use one of the forums, bug trackers, or mailing lists on - - https://sourceforge.net/projects/gigaset307x - - or write an electronic mail to the maintainers. - - Try to provide as much information as possible, such as - - - distribution - - kernel version (uname -r) - - gcc version (gcc --version) - - hardware architecture (uname -m, ...) - - type and firmware version of your device (base and wireless module, - if any) - - output of "lsusb -v" (if using an USB device) - - error messages - - relevant system log messages (it would help if you activate debug - output as described in 3.2.) - - For help with general configuration problems not specific to our driver, - such as isdn4linux and network configuration issues, please refer to the - appropriate forums and newsgroups. - -3.4. Reporting problem solutions --------------------------------- - If you solved a problem with our drivers, wrote startup scripts for your - distribution, ... feel free to contact us (using one of the places - mentioned in 3.3.). We'd like to add scripts, hints, documentation - to the driver and/or the project web page. - - -4. Links, other software -========================== - - - Sourceforge project developing this driver and associated tools - https://sourceforge.net/projects/gigaset307x - - Yahoo! Group on the Siemens Gigaset family of devices - https://de.groups.yahoo.com/group/Siemens-Gigaset - - Siemens Gigaset/T-Sinus compatibility table - http://www.erbze.info/sinus_gigaset.htm - (archived at https://web.archive.org/web/20100717020421/http://www.erbze.info:80/sinus_gigaset.htm ) - - -5. Credits -============ - - Thanks to - - Karsten Keil - for his help with isdn4linux - Deti Fliegl - for his base driver code - Dennis Dietrich - for his kernel 2.6 patches - Andreas Rummel - for his work and logs to get unimodem mode working - Andreas Degert - for his logs and patches to get cx 100 working - Dietrich Feist - for his generous donation of one M105 and two M101 cordless adapters - Christoph Schweers - for his generous donation of a M34 device - - and all the other people who sent logs and other information. diff --git a/Documentation/isdn/hysdn.rst b/Documentation/isdn/hysdn.rst deleted file mode 100644 index 0a168d1cbffc..000000000000 --- a/Documentation/isdn/hysdn.rst +++ /dev/null @@ -1,196 +0,0 @@ -============ -Hysdn Driver -============ - -The hysdn driver has been written by -Werner Cornelius (werner@isdn4linux.de or werner@titro.de) -for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver -under the GNU General Public License. - -The CAPI 2.0-support was added by Ulrich Albrecht (ualbrecht@hypercope.de) -for Hypercope GmbH Aachen, Germany. - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -.. Table of contents - - 1. About the driver - - 2. Loading/Unloading the driver - - 3. Entries in the /proc filesystem - - 4. The /proc/net/hysdn/cardconfX file - - 5. The /proc/net/hysdn/cardlogX file - - 6. Where to get additional info and help - - -1. About the driver -=================== - - The drivers/isdn/hysdn subdir contains a driver for HYPERCOPEs active - PCI isdn cards Champ, Ergo and Metro. To enable support for this cards - enable ISDN support in the kernel config and support for HYSDN cards in - the active cards submenu. The driver may only be compiled and used if - support for loadable modules and the process filesystem have been enabled. - - These cards provide two different interfaces to the kernel. Without the - optional CAPI 2.0 support, they register as ethernet card. IP-routing - to a ISDN-destination is performed on the card itself. All necessary - handlers for various protocols like ppp and others as well as config info - and firmware may be fetched from Hypercopes WWW-Site www.hypercope.de. - - With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0 - compliant devices with either CAPI 2.0 applications - (check isdn4k-utils) or -using the capidrv module- as a regular - isdn4linux device. This is done via the same mechanism as with the - active AVM cards and in fact uses the same module. - - -2. Loading/Unloading the driver -=============================== - - The module has no command line parameters and auto detects up to 10 cards - in the id-range 0-9. - If a loaded driver shall be unloaded all open files in the /proc/net/hysdn - subdir need to be closed and all ethernet interfaces allocated by this - driver must be shut down. Otherwise the module counter will avoid a module - unload. - - If you are using the CAPI 2.0-interface, make sure to load/modprobe the - kernelcapi-module first. - - If you plan to use the capidrv-link to isdn4linux, make sure to load - capidrv.o after all modules using this driver (i.e. after hysdn and - any avm-specific modules). - -3. Entries in the /proc filesystem -================================== - - When the module has been loaded it adds the directory hysdn in the - /proc/net tree. This directory contains exactly 2 file entries for each - card. One is called cardconfX and the other cardlogX, where X is the - card id number from 0 to 9. - The cards are numbered in the order found in the PCI config data. - -4. The /proc/net/hysdn/cardconfX file -===================================== - - This file may be read to get by everyone to get info about the cards type, - actual state, available features and used resources. - The first 3 entries (id, bus and slot) are PCI info fields, the following - type field gives the information about the cards type: - - - 4 -> Ergo card (server card with 2 b-chans) - - 5 -> Metro card (server card with 4 or 8 b-chans) - - 6 -> Champ card (client card with 2 b-chans) - - The following 3 fields show the hardware assignments for irq, iobase and the - dual ported memory (dp-mem). - - The fields b-chans and fax-chans announce the available card resources of - this types for the user. - - The state variable indicates the actual drivers state for this card with the - following assignments. - - - 0 -> card has not been booted since driver load - - 1 -> card booting is actually in progess - - 2 -> card is in an error state due to a previous boot failure - - 3 -> card is booted and active - - And the last field (device) shows the name of the ethernet device assigned - to this card. Up to the first successful boot this field only shows a - - to tell that no net device has been allocated up to now. Once a net device - has been allocated it remains assigned to this card, even if a card is - rebooted and an boot error occurs. - - Writing to the cardconfX file boots the card or transfers config lines to - the cards firmware. The type of data is automatically detected when the - first data is written. Only root has write access to this file. - The firmware boot files are normally called hyclient.pof for client cards - and hyserver.pof for server cards. - After successfully writing the boot file, complete config files or single - config lines may be copied to this file. - If an error occurs the return value given to the writing process has the - following additional codes (decimal): - - ==== ============================================ - 1000 Another process is currently bootng the card - 1001 Invalid firmware header - 1002 Boards dual-port RAM test failed - 1003 Internal firmware handler error - 1004 Boot image size invalid - 1005 First boot stage (bootstrap loader) failed - 1006 Second boot stage failure - 1007 Timeout waiting for card ready during boot - 1008 Operation only allowed in booted state - 1009 Config line too long - 1010 Invalid channel number - 1011 Timeout sending config data - ==== ============================================ - - Additional info about error reasons may be fetched from the log output. - -5. The /proc/net/hysdn/cardlogX file -==================================== - - The cardlogX file entry may be opened multiple for reading by everyone to - get the cards and drivers log data. Card messages always start with the - keyword LOG. All other lines are output from the driver. - The driver log data may be redirected to the syslog by selecting the - appropriate bitmask. The cards log messages will always be send to this - interface but never to the syslog. - - A root user may write a decimal or hex (with 0x) value t this file to select - desired output options. As mentioned above the cards log dat is always - written to the cardlog file independent of the following options only used - to check and debug the driver itself: - - For example:: - - echo "0x34560078" > /proc/net/hysdn/cardlog0 - - to output the hex log mask 34560078 for card 0. - - The written value is regarded as an unsigned 32-Bit value, bit ored for - desired output. The following bits are already assigned: - - ========== ============================================================ - 0x80000000 All driver log data is alternatively via syslog - 0x00000001 Log memory allocation errors - 0x00000010 Firmware load start and close are logged - 0x00000020 Log firmware record parser - 0x00000040 Log every firmware write actions - 0x00000080 Log all card related boot messages - 0x00000100 Output all config data sent for debugging purposes - 0x00000200 Only non comment config lines are shown wth channel - 0x00000400 Additional conf log output - 0x00001000 Log the asynchronous scheduler actions (config and log) - 0x00100000 Log all open and close actions to /proc/net/hysdn/card files - 0x00200000 Log all actions from /proc file entries - 0x00010000 Log network interface init and deinit - ========== ============================================================ - -6. Where to get additional info and help -======================================== - - If you have any problems concerning the driver or configuration contact - the Hypercope support team (support@hypercope.de) and or the authors - Werner Cornelius (werner@isdn4linux or cornelius@titro.de) or - Ulrich Albrecht (ualbrecht@hypercope.de). diff --git a/Documentation/isdn/index.rst b/Documentation/isdn/index.rst index 407e74b78372..9622939fa526 100644 --- a/Documentation/isdn/index.rst +++ b/Documentation/isdn/index.rst @@ -9,9 +9,6 @@ ISDN interface_capi - avmb1 - gigaset - hysdn m_isdn credits diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 4ef86433bd67..2e91370dc159 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -132,7 +132,6 @@ Code Seq# Include File Comments 'F' 80-8F linux/arcfb.h conflict! 'F' DD video/sstfb.h conflict! 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! -'G' 00-0F linux/gigaset_dev.h conflict! 'H' 00-7F linux/hiddev.h conflict! 'H' 00-0F linux/hidraw.h conflict! 'H' 01 linux/mei.h conflict! diff --git a/MAINTAINERS b/MAINTAINERS index bd5847e802de..e53e862bf2c3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8804,7 +8804,7 @@ S: Maintained F: drivers/isdn/mISDN F: drivers/isdn/hardware -ISDN/CAPI SUBSYSTEM +ISDN/CMTP OVER BLUETOOTH M: Karsten Keil L: isdn4linux@listserv.isdn4linux.de (subscribers-only) L: netdev@vger.kernel.org @@ -8812,7 +8812,6 @@ W: http://www.isdn4linux.de S: Odd Fixes F: Documentation/isdn/ F: drivers/isdn/capi/ -F: drivers/staging/isdn/ F: net/bluetooth/cmtp/ F: include/linux/isdn/ F: include/uapi/linux/isdn/ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index eaf753b70ec5..3a334a9dd453 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -116,8 +116,6 @@ source "drivers/staging/fieldbus/Kconfig" source "drivers/staging/kpc2000/Kconfig" -source "drivers/staging/isdn/Kconfig" - source "drivers/staging/wusbcore/Kconfig" source "drivers/staging/uwb/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 0a4396c9067b..fb0c518ce07c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ -obj-$(CONFIG_ISDN_CAPI) += isdn/ obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_USB_WUSB) += wusbcore/ obj-$(CONFIG_EXFAT_FS) += exfat/ diff --git a/drivers/staging/isdn/Kconfig b/drivers/staging/isdn/Kconfig deleted file mode 100644 index faaf63887094..000000000000 --- a/drivers/staging/isdn/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menu "ISDN CAPI drivers" - depends on ISDN_CAPI - -source "drivers/staging/isdn/avm/Kconfig" - -source "drivers/staging/isdn/gigaset/Kconfig" - -source "drivers/staging/isdn/hysdn/Kconfig" - -endmenu - diff --git a/drivers/staging/isdn/Makefile b/drivers/staging/isdn/Makefile deleted file mode 100644 index 025504bae5df..000000000000 --- a/drivers/staging/isdn/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Makefile for the kernel ISDN subsystem and device drivers. - -# Object files in subdirectories - -obj-$(CONFIG_CAPI_AVM) += avm/ -obj-$(CONFIG_HYSDN) += hysdn/ -obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/ diff --git a/drivers/staging/isdn/TODO b/drivers/staging/isdn/TODO deleted file mode 100644 index 9210d11eb68b..000000000000 --- a/drivers/staging/isdn/TODO +++ /dev/null @@ -1,22 +0,0 @@ -TODO: Remove in late 2019 unless there are users - - -I tried to find any indication of whether the capi drivers are -still in use, and have not found anything from a long time ago. - -With public ISDN networks almost completely shut down over the past 12 -months, there is very little you can actually do with this hardware. The -main remaining use case would be to connect ISDN voice phones to an -in-house installation with Asterisk or LCR, but anyone trying this in -turn seems to be using either the mISDN driver stack, or out-of-tree -drivers from the hardware vendors. - -I may of course have missed something, so I would suggest moving -these into drivers/staging/ just in case someone still uses one -of the three remaining in-kernel drivers (avm, hysdn, gigaset). - -If nobody complains, we can remove them entirely in six months, -or otherwise move the core code and any drivers that are still -needed back into drivers/isdn. - - Arnd Bergmann diff --git a/drivers/staging/isdn/avm/Kconfig b/drivers/staging/isdn/avm/Kconfig deleted file mode 100644 index 81483db067bb..000000000000 --- a/drivers/staging/isdn/avm/Kconfig +++ /dev/null @@ -1,65 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# ISDN AVM drivers -# - -menuconfig CAPI_AVM - bool "Active AVM cards" - help - Enable support for AVM active ISDN cards. - -if CAPI_AVM - -config ISDN_DRV_AVMB1_B1ISA - tristate "AVM B1 ISA support" - depends on ISA - help - Enable support for the ISA version of the AVM B1 card. - -config ISDN_DRV_AVMB1_B1PCI - tristate "AVM B1 PCI support" - depends on PCI - help - Enable support for the PCI version of the AVM B1 card. - -config ISDN_DRV_AVMB1_B1PCIV4 - bool "AVM B1 PCI V4 support" - depends on ISDN_DRV_AVMB1_B1PCI - help - Enable support for the V4 version of AVM B1 PCI card. - -config ISDN_DRV_AVMB1_T1ISA - tristate "AVM T1/T1-B ISA support" - depends on ISA - help - Enable support for the AVM T1 T1B card. - Note: This is a PRI card and handle 30 B-channels. - -config ISDN_DRV_AVMB1_B1PCMCIA - tristate "AVM B1/M1/M2 PCMCIA support" - depends on PCMCIA - help - Enable support for the PCMCIA version of the AVM B1 card. - -config ISDN_DRV_AVMB1_AVM_CS - tristate "AVM B1/M1/M2 PCMCIA cs module" - depends on ISDN_DRV_AVMB1_B1PCMCIA - help - Enable the PCMCIA client driver for the AVM B1/M1/M2 - PCMCIA cards. - -config ISDN_DRV_AVMB1_T1PCI - tristate "AVM T1/T1-B PCI support" - depends on PCI - help - Enable support for the AVM T1 T1B card. - Note: This is a PRI card and handle 30 B-channels. - -config ISDN_DRV_AVMB1_C4 - tristate "AVM C4/C2 support" - depends on PCI - help - Enable support for the AVM C4/C2 PCI cards. - These cards handle 4/2 BRI ISDN lines (8/4 channels). - -endif # CAPI_AVM diff --git a/drivers/staging/isdn/avm/Makefile b/drivers/staging/isdn/avm/Makefile deleted file mode 100644 index 3830a0573fcc..000000000000 --- a/drivers/staging/isdn/avm/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# Makefile for the AVM ISDN device drivers - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o -obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o -obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o -obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o -obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o -obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o -obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o diff --git a/drivers/staging/isdn/avm/avm_cs.c b/drivers/staging/isdn/avm/avm_cs.c deleted file mode 100644 index 62b8030ee331..000000000000 --- a/drivers/staging/isdn/avm/avm_cs.c +++ /dev/null @@ -1,166 +0,0 @@ -/* $Id: avm_cs.c,v 1.4.6.3 2001/09/23 22:24:33 kai Exp $ - * - * A PCMCIA client driver for AVM B1/M1/M2 - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -/*====================================================================*/ - -MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/*====================================================================*/ - -static int avmcs_config(struct pcmcia_device *link); -static void avmcs_release(struct pcmcia_device *link); -static void avmcs_detach(struct pcmcia_device *p_dev); - -static int avmcs_probe(struct pcmcia_device *p_dev) -{ - /* General socket configuration */ - p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - p_dev->config_index = 1; - p_dev->config_regs = PRESENT_OPTION; - - return avmcs_config(p_dev); -} /* avmcs_attach */ - - -static void avmcs_detach(struct pcmcia_device *link) -{ - avmcs_release(link); -} /* avmcs_detach */ - -static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data) -{ - p_dev->resource[0]->end = 16; - p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - - return pcmcia_request_io(p_dev); -} - -static int avmcs_config(struct pcmcia_device *link) -{ - int i = -1; - char devname[128]; - int cardtype; - int (*addcard)(unsigned int port, unsigned irq); - - devname[0] = 0; - if (link->prod_id[1]) - strlcpy(devname, link->prod_id[1], sizeof(devname)); - - /* - * find IO port - */ - if (pcmcia_loop_config(link, avmcs_configcheck, NULL)) - return -ENODEV; - - do { - if (!link->irq) { - /* undo */ - pcmcia_disable_device(link); - break; - } - - /* - * configure the PCMCIA socket - */ - i = pcmcia_enable_device(link); - if (i != 0) { - pcmcia_disable_device(link); - break; - } - - } while (0); - - if (devname[0]) { - char *s = strrchr(devname, ' '); - if (!s) - s = devname; - else s++; - if (strcmp("M1", s) == 0) { - cardtype = AVM_CARDTYPE_M1; - } else if (strcmp("M2", s) == 0) { - cardtype = AVM_CARDTYPE_M2; - } else { - cardtype = AVM_CARDTYPE_B1; - } - } else - cardtype = AVM_CARDTYPE_B1; - - /* If any step failed, release any partially configured state */ - if (i != 0) { - avmcs_release(link); - return -ENODEV; - } - - - switch (cardtype) { - case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break; - case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break; - default: - case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break; - } - if ((i = (*addcard)(link->resource[0]->start, link->irq)) < 0) { - dev_err(&link->dev, - "avm_cs: failed to add AVM-Controller at i/o %#x, irq %d\n", - (unsigned int) link->resource[0]->start, link->irq); - avmcs_release(link); - return -ENODEV; - } - return 0; - -} /* avmcs_config */ - - -static void avmcs_release(struct pcmcia_device *link) -{ - b1pcmcia_delcard(link->resource[0]->start, link->irq); - pcmcia_disable_device(link); -} /* avmcs_release */ - - -static const struct pcmcia_device_id avmcs_ids[] = { - PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), - PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M1", 0x95d42008, 0x81e10430), - PCMCIA_DEVICE_PROD_ID12("AVM", "Mobile ISDN-Controller M2", 0x95d42008, 0x18e8558a), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, avmcs_ids); - -static struct pcmcia_driver avmcs_driver = { - .owner = THIS_MODULE, - .name = "avm_cs", - .probe = avmcs_probe, - .remove = avmcs_detach, - .id_table = avmcs_ids, -}; -module_pcmcia_driver(avmcs_driver); diff --git a/drivers/staging/isdn/avm/avmcard.h b/drivers/staging/isdn/avm/avmcard.h deleted file mode 100644 index cdfa89c71997..000000000000 --- a/drivers/staging/isdn/avm/avmcard.h +++ /dev/null @@ -1,581 +0,0 @@ -/* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef _AVMCARD_H_ -#define _AVMCARD_H_ - -#include -#include -#include - -#define AVMB1_PORTLEN 0x1f -#define AVM_MAXVERSION 8 -#define AVM_NCCI_PER_CHANNEL 4 - -/* - * Versions - */ - -#define VER_DRIVER 0 -#define VER_CARDTYPE 1 -#define VER_HWID 2 -#define VER_SERIAL 3 -#define VER_OPTION 4 -#define VER_PROTO 5 -#define VER_PROFILE 6 -#define VER_CAPI 7 - -enum avmcardtype { - avm_b1isa, - avm_b1pci, - avm_b1pcmcia, - avm_m1, - avm_m2, - avm_t1isa, - avm_t1pci, - avm_c4, - avm_c2 -}; - -typedef struct avmcard_dmabuf { - long size; - u8 *dmabuf; - dma_addr_t dmaaddr; -} avmcard_dmabuf; - -typedef struct avmcard_dmainfo { - u32 recvlen; - avmcard_dmabuf recvbuf; - - avmcard_dmabuf sendbuf; - struct sk_buff_head send_queue; - - struct pci_dev *pcidev; -} avmcard_dmainfo; - -typedef struct avmctrl_info { - char cardname[32]; - - int versionlen; - char versionbuf[1024]; - char *version[AVM_MAXVERSION]; - - char infobuf[128]; /* for function procinfo */ - - struct avmcard *card; - struct capi_ctr capi_ctrl; - - struct list_head ncci_head; -} avmctrl_info; - -typedef struct avmcard { - char name[32]; - - spinlock_t lock; - unsigned int port; - unsigned irq; - unsigned long membase; - enum avmcardtype cardtype; - unsigned char revision; - unsigned char class; - int cardnr; /* for t1isa */ - - char msgbuf[128]; /* capimsg msg part */ - char databuf[2048]; /* capimsg data part */ - - void __iomem *mbase; - volatile u32 csr; - avmcard_dmainfo *dma; - - struct avmctrl_info *ctrlinfo; - - u_int nr_controllers; - u_int nlogcontr; - struct list_head list; -} avmcard; - -extern int b1_irq_table[16]; - -/* - * LLI Messages to the ISDN-ControllerISDN Controller - */ - -#define SEND_POLL 0x72 /* - * after load <- RECEIVE_POLL - */ -#define SEND_INIT 0x11 /* - * first message <- RECEIVE_INIT - * int32 NumApplications int32 - * NumNCCIs int32 BoardNumber - */ -#define SEND_REGISTER 0x12 /* - * register an application int32 - * ApplIDId int32 NumMessages - * int32 NumB3Connections int32 - * NumB3Blocks int32 B3Size - * - * AnzB3Connection != 0 && - * AnzB3Blocks >= 1 && B3Size >= 1 - */ -#define SEND_RELEASE 0x14 /* - * deregister an application int32 - * ApplID - */ -#define SEND_MESSAGE 0x15 /* - * send capi-message int32 length - * capi-data ... - */ -#define SEND_DATA_B3_REQ 0x13 /* - * send capi-data-message int32 - * MsgLength capi-data ... int32 - * B3Length data .... - */ - -#define SEND_CONFIG 0x21 /* - */ - -#define SEND_POLLACK 0x73 /* T1 Watchdog */ - -/* - * LLI Messages from the ISDN-ControllerISDN Controller - */ - -#define RECEIVE_POLL 0x32 /* - * <- after SEND_POLL - */ -#define RECEIVE_INIT 0x27 /* - * <- after SEND_INIT int32 length - * byte total length b1struct board - * driver revision b1struct card - * type b1struct reserved b1struct - * serial number b1struct driver - * capability b1struct d-channel - * protocol b1struct CAPI-2.0 - * profile b1struct capi version - */ -#define RECEIVE_MESSAGE 0x21 /* - * <- after SEND_MESSAGE int32 - * AppllID int32 Length capi-data - * .... - */ -#define RECEIVE_DATA_B3_IND 0x22 /* - * received data int32 AppllID - * int32 Length capi-data ... - * int32 B3Length data ... - */ -#define RECEIVE_START 0x23 /* - * Handshake - */ -#define RECEIVE_STOP 0x24 /* - * Handshake - */ -#define RECEIVE_NEW_NCCI 0x25 /* - * int32 AppllID int32 NCCI int32 - * WindowSize - */ -#define RECEIVE_FREE_NCCI 0x26 /* - * int32 AppllID int32 NCCI - */ -#define RECEIVE_RELEASE 0x26 /* - * int32 AppllID int32 0xffffffff - */ -#define RECEIVE_TASK_READY 0x31 /* - * int32 tasknr - * int32 Length Taskname ... - */ -#define RECEIVE_DEBUGMSG 0x71 /* - * int32 Length message - * - */ -#define RECEIVE_POLLDWORD 0x75 /* t1pci in dword mode */ - -#define WRITE_REGISTER 0x00 -#define READ_REGISTER 0x01 - -/* - * port offsets - */ - -#define B1_READ 0x00 -#define B1_WRITE 0x01 -#define B1_INSTAT 0x02 -#define B1_OUTSTAT 0x03 -#define B1_ANALYSE 0x04 -#define B1_REVISION 0x05 -#define B1_RESET 0x10 - - -#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l) -#define B1_STAT1(cardtype) (0x80E00000l) - -/* ---------------------------------------------------------------- */ - -static inline unsigned char b1outp(unsigned int base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); - return inb(base + B1_ANALYSE); -} - - -static inline int b1_rx_full(unsigned int base) -{ - return inb(base + B1_INSTAT) & 0x1; -} - -static inline unsigned char b1_get_byte(unsigned int base) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - while (!b1_rx_full(base) && time_before(jiffies, stop)); - if (b1_rx_full(base)) - return inb(base + B1_READ); - printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base); - return 0; -} - -static inline unsigned int b1_get_word(unsigned int base) -{ - unsigned int val = 0; - val |= b1_get_byte(base); - val |= (b1_get_byte(base) << 8); - val |= (b1_get_byte(base) << 16); - val |= (b1_get_byte(base) << 24); - return val; -} - -static inline int b1_tx_empty(unsigned int base) -{ - return inb(base + B1_OUTSTAT) & 0x1; -} - -static inline void b1_put_byte(unsigned int base, unsigned char val) -{ - while (!b1_tx_empty(base)); - b1outp(base, B1_WRITE, val); -} - -static inline int b1_save_put_byte(unsigned int base, unsigned char val) -{ - unsigned long stop = jiffies + 2 * HZ; - while (!b1_tx_empty(base) && time_before(jiffies, stop)); - if (!b1_tx_empty(base)) return -1; - b1outp(base, B1_WRITE, val); - return 0; -} - -static inline void b1_put_word(unsigned int base, unsigned int val) -{ - b1_put_byte(base, val & 0xff); - b1_put_byte(base, (val >> 8) & 0xff); - b1_put_byte(base, (val >> 16) & 0xff); - b1_put_byte(base, (val >> 24) & 0xff); -} - -static inline unsigned int b1_get_slice(unsigned int base, - unsigned char *dp) -{ - unsigned int len, i; - - len = i = b1_get_word(base); - while (i-- > 0) *dp++ = b1_get_byte(base); - return len; -} - -static inline void b1_put_slice(unsigned int base, - unsigned char *dp, unsigned int len) -{ - unsigned i = len; - b1_put_word(base, i); - while (i-- > 0) - b1_put_byte(base, *dp++); -} - -static void b1_wr_reg(unsigned int base, - unsigned int reg, - unsigned int value) -{ - b1_put_byte(base, WRITE_REGISTER); - b1_put_word(base, reg); - b1_put_word(base, value); -} - -static inline unsigned int b1_rd_reg(unsigned int base, - unsigned int reg) -{ - b1_put_byte(base, READ_REGISTER); - b1_put_word(base, reg); - return b1_get_word(base); - -} - -static inline void b1_reset(unsigned int base) -{ - b1outp(base, B1_RESET, 0); - mdelay(55 * 2); /* 2 TIC's */ - - b1outp(base, B1_RESET, 1); - mdelay(55 * 2); /* 2 TIC's */ - - b1outp(base, B1_RESET, 0); - mdelay(55 * 2); /* 2 TIC's */ -} - -static inline unsigned char b1_disable_irq(unsigned int base) -{ - return b1outp(base, B1_INSTAT, 0x00); -} - -/* ---------------------------------------------------------------- */ - -static inline void b1_set_test_bit(unsigned int base, - enum avmcardtype cardtype, - int onoff) -{ - b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); -} - -static inline int b1_get_test_bit(unsigned int base, - enum avmcardtype cardtype) -{ - return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; -} - -/* ---------------------------------------------------------------- */ - -#define T1_FASTLINK 0x00 -#define T1_SLOWLINK 0x08 - -#define T1_READ B1_READ -#define T1_WRITE B1_WRITE -#define T1_INSTAT B1_INSTAT -#define T1_OUTSTAT B1_OUTSTAT -#define T1_IRQENABLE 0x05 -#define T1_FIFOSTAT 0x06 -#define T1_RESETLINK 0x10 -#define T1_ANALYSE 0x11 -#define T1_IRQMASTER 0x12 -#define T1_IDENT 0x17 -#define T1_RESETBOARD 0x1f - -#define T1F_IREADY 0x01 -#define T1F_IHALF 0x02 -#define T1F_IFULL 0x04 -#define T1F_IEMPTY 0x08 -#define T1F_IFLAGS 0xF0 - -#define T1F_OREADY 0x10 -#define T1F_OHALF 0x20 -#define T1F_OEMPTY 0x40 -#define T1F_OFULL 0x80 -#define T1F_OFLAGS 0xF0 - -/* there are HEMA cards with 1k and 4k FIFO out */ -#define FIFO_OUTBSIZE 256 -#define FIFO_INPBSIZE 512 - -#define HEMA_VERSION_ID 0 -#define HEMA_PAL_ID 0 - -static inline void t1outp(unsigned int base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); -} - -static inline unsigned char t1inp(unsigned int base, - unsigned short offset) -{ - return inb(base + offset); -} - -static inline int t1_isfastlink(unsigned int base) -{ - return (inb(base + T1_IDENT) & ~0x82) == 1; -} - -static inline unsigned char t1_fifostatus(unsigned int base) -{ - return inb(base + T1_FIFOSTAT); -} - -static inline unsigned int t1_get_slice(unsigned int base, - unsigned char *dp) -{ - unsigned int len, i; -#ifdef FASTLINK_DEBUG - unsigned wcnt = 0, bcnt = 0; -#endif - - len = i = b1_get_word(base); - if (t1_isfastlink(base)) { - int status; - while (i > 0) { - status = t1_fifostatus(base) & (T1F_IREADY | T1F_IHALF); - if (i >= FIFO_INPBSIZE) status |= T1F_IFULL; - - switch (status) { - case T1F_IREADY | T1F_IHALF | T1F_IFULL: - insb(base + B1_READ, dp, FIFO_INPBSIZE); - dp += FIFO_INPBSIZE; - i -= FIFO_INPBSIZE; -#ifdef FASTLINK_DEBUG - wcnt += FIFO_INPBSIZE; -#endif - break; - case T1F_IREADY | T1F_IHALF: - insb(base + B1_READ, dp, i); -#ifdef FASTLINK_DEBUG - wcnt += i; -#endif - dp += i; - i = 0; - break; - default: - *dp++ = b1_get_byte(base); - i--; -#ifdef FASTLINK_DEBUG - bcnt++; -#endif - break; - } - } -#ifdef FASTLINK_DEBUG - if (wcnt) - printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n", - base, len, wcnt, bcnt); -#endif - } else { - while (i-- > 0) - *dp++ = b1_get_byte(base); - } - return len; -} - -static inline void t1_put_slice(unsigned int base, - unsigned char *dp, unsigned int len) -{ - unsigned i = len; - b1_put_word(base, i); - if (t1_isfastlink(base)) { - int status; - while (i > 0) { - status = t1_fifostatus(base) & (T1F_OREADY | T1F_OHALF); - if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY; - switch (status) { - case T1F_OREADY | T1F_OHALF | T1F_OEMPTY: - outsb(base + B1_WRITE, dp, FIFO_OUTBSIZE); - dp += FIFO_OUTBSIZE; - i -= FIFO_OUTBSIZE; - break; - case T1F_OREADY | T1F_OHALF: - outsb(base + B1_WRITE, dp, i); - dp += i; - i = 0; - break; - default: - b1_put_byte(base, *dp++); - i--; - break; - } - } - } else { - while (i-- > 0) - b1_put_byte(base, *dp++); - } -} - -static inline void t1_disable_irq(unsigned int base) -{ - t1outp(base, T1_IRQMASTER, 0x00); -} - -static inline void t1_reset(unsigned int base) -{ - /* reset T1 Controller */ - b1_reset(base); - /* disable irq on HEMA */ - t1outp(base, B1_INSTAT, 0x00); - t1outp(base, B1_OUTSTAT, 0x00); - t1outp(base, T1_IRQMASTER, 0x00); - /* reset HEMA board configuration */ - t1outp(base, T1_RESETBOARD, 0xf); -} - -static inline void b1_setinterrupt(unsigned int base, unsigned irq, - enum avmcardtype cardtype) -{ - switch (cardtype) { - case avm_t1isa: - t1outp(base, B1_INSTAT, 0x00); - t1outp(base, B1_INSTAT, 0x02); - t1outp(base, T1_IRQMASTER, 0x08); - break; - case avm_b1isa: - b1outp(base, B1_INSTAT, 0x00); - b1outp(base, B1_RESET, b1_irq_table[irq]); - b1outp(base, B1_INSTAT, 0x02); - break; - default: - case avm_m1: - case avm_m2: - case avm_b1pci: - b1outp(base, B1_INSTAT, 0x00); - b1outp(base, B1_RESET, 0xf0); - b1outp(base, B1_INSTAT, 0x02); - break; - case avm_c4: - case avm_t1pci: - b1outp(base, B1_RESET, 0xf0); - break; - } -} - -/* b1.c */ -avmcard *b1_alloc_card(int nr_controllers); -void b1_free_card(avmcard *card); -int b1_detect(unsigned int base, enum avmcardtype cardtype); -void b1_getrevision(avmcard *card); -int b1_load_t4file(avmcard *card, capiloaddatapart *t4file); -int b1_load_config(avmcard *card, capiloaddatapart *config); -int b1_loaded(avmcard *card); - -int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); -void b1_reset_ctr(struct capi_ctr *ctrl); -void b1_register_appl(struct capi_ctr *ctrl, u16 appl, - capi_register_params *rp); -void b1_release_appl(struct capi_ctr *ctrl, u16 appl); -u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -void b1_parse_version(avmctrl_info *card); -irqreturn_t b1_interrupt(int interrupt, void *devptr); - -int b1_proc_show(struct seq_file *m, void *v); - -avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, - long rsize, long ssize); -void avmcard_dma_free(avmcard_dmainfo *); - -/* b1dma.c */ -int b1pciv4_detect(avmcard *card); -int t1pci_detect(avmcard *card); -void b1dma_reset(avmcard *card); -irqreturn_t b1dma_interrupt(int interrupt, void *devptr); - -int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); -void b1dma_reset_ctr(struct capi_ctr *ctrl); -void b1dma_remove_ctr(struct capi_ctr *ctrl); -void b1dma_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp); -void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); -u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -int b1dma_proc_show(struct seq_file *m, void *v); - -#endif /* _AVMCARD_H_ */ diff --git a/drivers/staging/isdn/avm/b1.c b/drivers/staging/isdn/avm/b1.c deleted file mode 100644 index 32ec8cf31fd0..000000000000 --- a/drivers/staging/isdn/avm/b1.c +++ /dev/null @@ -1,819 +0,0 @@ -/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Common module for AVM B1 cards. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" -#include -#include - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -int b1_irq_table[16] = -{0, - 0, - 0, - 192, /* irq 3 */ - 32, /* irq 4 */ - 160, /* irq 5 */ - 96, /* irq 6 */ - 224, /* irq 7 */ - 0, - 64, /* irq 9 */ - 80, /* irq 10 */ - 208, /* irq 11 */ - 48, /* irq 12 */ - 0, - 0, - 112, /* irq 15 */ -}; - -/* ------------------------------------------------------------- */ - -avmcard *b1_alloc_card(int nr_controllers) -{ - avmcard *card; - avmctrl_info *cinfo; - int i; - - card = kzalloc(sizeof(*card), GFP_KERNEL); - if (!card) - return NULL; - - cinfo = kcalloc(nr_controllers, sizeof(*cinfo), GFP_KERNEL); - if (!cinfo) { - kfree(card); - return NULL; - } - - card->ctrlinfo = cinfo; - for (i = 0; i < nr_controllers; i++) { - INIT_LIST_HEAD(&cinfo[i].ncci_head); - cinfo[i].card = card; - } - spin_lock_init(&card->lock); - card->nr_controllers = nr_controllers; - - return card; -} - -/* ------------------------------------------------------------- */ - -void b1_free_card(avmcard *card) -{ - kfree(card->ctrlinfo); - kfree(card); -} - -/* ------------------------------------------------------------- */ - -int b1_detect(unsigned int base, enum avmcardtype cardtype) -{ - int onoff, i; - - /* - * Statusregister 0000 00xx - */ - if ((inb(base + B1_INSTAT) & 0xfc) - || (inb(base + B1_OUTSTAT) & 0xfc)) - return 1; - /* - * Statusregister 0000 001x - */ - b1outp(base, B1_INSTAT, 0x2); /* enable irq */ - /* b1outp(base, B1_OUTSTAT, 0x2); */ - if ((inb(base + B1_INSTAT) & 0xfe) != 0x2 - /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */) - return 2; - /* - * Statusregister 0000 000x - */ - b1outp(base, B1_INSTAT, 0x0); /* disable irq */ - b1outp(base, B1_OUTSTAT, 0x0); - if ((inb(base + B1_INSTAT) & 0xfe) - || (inb(base + B1_OUTSTAT) & 0xfe)) - return 3; - - for (onoff = !0, i = 0; i < 10; i++) { - b1_set_test_bit(base, cardtype, onoff); - if (b1_get_test_bit(base, cardtype) != onoff) - return 4; - onoff = !onoff; - } - - if (cardtype == avm_m1) - return 0; - - if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01) - return 5; - - return 0; -} - -void b1_getrevision(avmcard *card) -{ - card->class = inb(card->port + B1_ANALYSE); - card->revision = inb(card->port + B1_REVISION); -} - -#define FWBUF_SIZE 256 -int b1_load_t4file(avmcard *card, capiloaddatapart *t4file) -{ - unsigned char buf[FWBUF_SIZE]; - unsigned char *dp; - int i, left; - unsigned int base = card->port; - - dp = t4file->data; - left = t4file->len; - while (left > FWBUF_SIZE) { - if (t4file->user) { - if (copy_from_user(buf, dp, FWBUF_SIZE)) - return -EFAULT; - } else { - memcpy(buf, dp, FWBUF_SIZE); - } - for (i = 0; i < FWBUF_SIZE; i++) - if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - left -= FWBUF_SIZE; - dp += FWBUF_SIZE; - } - if (left) { - if (t4file->user) { - if (copy_from_user(buf, dp, left)) - return -EFAULT; - } else { - memcpy(buf, dp, left); - } - for (i = 0; i < left; i++) - if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - } - return 0; -} - -int b1_load_config(avmcard *card, capiloaddatapart *config) -{ - unsigned char buf[FWBUF_SIZE]; - unsigned char *dp; - unsigned int base = card->port; - int i, j, left; - - dp = config->data; - left = config->len; - if (left) { - b1_put_byte(base, SEND_CONFIG); - b1_put_word(base, 1); - b1_put_byte(base, SEND_CONFIG); - b1_put_word(base, left); - } - while (left > FWBUF_SIZE) { - if (config->user) { - if (copy_from_user(buf, dp, FWBUF_SIZE)) - return -EFAULT; - } else { - memcpy(buf, dp, FWBUF_SIZE); - } - for (i = 0; i < FWBUF_SIZE; ) { - b1_put_byte(base, SEND_CONFIG); - for (j = 0; j < 4; j++) { - b1_put_byte(base, buf[i++]); - } - } - left -= FWBUF_SIZE; - dp += FWBUF_SIZE; - } - if (left) { - if (config->user) { - if (copy_from_user(buf, dp, left)) - return -EFAULT; - } else { - memcpy(buf, dp, left); - } - for (i = 0; i < left; ) { - b1_put_byte(base, SEND_CONFIG); - for (j = 0; j < 4; j++) { - if (i < left) - b1_put_byte(base, buf[i++]); - else - b1_put_byte(base, 0); - } - } - } - return 0; -} - -int b1_loaded(avmcard *card) -{ - unsigned int base = card->port; - unsigned long stop; - unsigned char ans; - unsigned long tout = 2; - - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_tx_empty(base)) - break; - } - if (!b1_tx_empty(base)) { - printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n", - card->name); - return 0; - } - b1_put_byte(base, SEND_POLL); - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_rx_full(base)) { - ans = b1_get_byte(base); - if (ans == RECEIVE_POLL) - return 1; - - printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n", - card->name, ans); - return 0; - } - } - printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int retval; - - b1_reset(port); - retval = b1_load_t4file(card, &data->firmware); - - if (retval) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - b1_disable_irq(port); - - if (data->configuration.len > 0 && data->configuration.data) { - retval = b1_load_config(card, &data->configuration); - if (retval) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1_loaded(card)) { - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - spin_lock_irqsave(&card->lock, flags); - b1_setinterrupt(port, card->irq, card->cardtype); - b1_put_byte(port, SEND_INIT); - b1_put_word(port, CAPI_MAXAPPL); - b1_put_word(port, AVM_NCCI_PER_CHANNEL * 2); - b1_put_word(port, ctrl->cnr - 1); - spin_unlock_irqrestore(&card->lock, flags); - - return 0; -} - -void b1_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - b1_reset(port); - b1_reset(port); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - spin_lock_irqsave(&card->lock, flags); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(ctrl); -} - -void b1_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int nconn, want = rp->level3cnt; - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel; - - spin_lock_irqsave(&card->lock, flags); - b1_put_byte(port, SEND_REGISTER); - b1_put_word(port, appl); - b1_put_word(port, 1024 * (nconn + 1)); - b1_put_word(port, nconn); - b1_put_word(port, rp->datablkcnt); - b1_put_word(port, rp->datablklen); - spin_unlock_irqrestore(&card->lock, flags); -} - -void b1_release_appl(struct capi_ctr *ctrl, u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - capilib_release_appl(&cinfo->ncci_head, appl); - b1_put_byte(port, SEND_RELEASE); - b1_put_word(port, appl); - spin_unlock_irqrestore(&card->lock, flags); -} - -u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - u16 len = CAPIMSG_LEN(skb->data); - u8 cmd = CAPIMSG_COMMAND(skb->data); - u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - u16 dlen, retval; - - spin_lock_irqsave(&card->lock, flags); - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - if (retval != CAPI_NOERROR) { - spin_unlock_irqrestore(&card->lock, flags); - return retval; - } - - dlen = CAPIMSG_DATALEN(skb->data); - - b1_put_byte(port, SEND_DATA_B3_REQ); - b1_put_slice(port, skb->data, len); - b1_put_slice(port, skb->data + len, dlen); - } else { - b1_put_byte(port, SEND_MESSAGE); - b1_put_slice(port, skb->data, len); - } - spin_unlock_irqrestore(&card->lock, flags); - - dev_kfree_skb_any(skb); - return CAPI_NOERROR; -} - -/* ------------------------------------------------------------- */ - -void b1_parse_version(avmctrl_info *cinfo) -{ - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - avmcard *card = cinfo->card; - capi_profile *profp; - u8 *dversion; - u8 flag; - int i, j; - - for (j = 0; j < AVM_MAXVERSION; j++) - cinfo->version[j] = ""; - for (i = 0, j = 0; - j < AVM_MAXVERSION && i < cinfo->versionlen; - j++, i += cinfo->versionbuf[i] + 1) - cinfo->version[j] = &cinfo->versionbuf[i + 1]; - - strlcpy(ctrl->serial, cinfo->version[VER_SERIAL], sizeof(ctrl->serial)); - memcpy(&ctrl->profile, cinfo->version[VER_PROFILE], sizeof(capi_profile)); - strlcpy(ctrl->manu, "AVM GmbH", sizeof(ctrl->manu)); - dversion = cinfo->version[VER_DRIVER]; - ctrl->version.majorversion = 2; - ctrl->version.minorversion = 0; - ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); - ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf); - ctrl->version.minormanuversion = (dversion[3] - '0') << 4; - ctrl->version.minormanuversion |= - (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf); - - profp = &ctrl->profile; - - flag = ((u8 *)(profp->manu))[1]; - switch (flag) { - case 0: if (cinfo->version[VER_CARDTYPE]) - strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]); - else strcpy(cinfo->cardname, "B1"); - break; - case 3: strcpy(cinfo->cardname, "PCMCIA B"); break; - case 4: strcpy(cinfo->cardname, "PCMCIA M1"); break; - case 5: strcpy(cinfo->cardname, "PCMCIA M2"); break; - case 6: strcpy(cinfo->cardname, "B1 V3.0"); break; - case 7: strcpy(cinfo->cardname, "B1 PCI"); break; - default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break; - } - printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n", - card->name, ctrl->cnr, cinfo->cardname); - - flag = ((u8 *)(profp->manu))[3]; - if (flag) - printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n", - card->name, - ctrl->cnr, - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - - flag = ((u8 *)(profp->manu))[5]; - if (flag) - printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n", - card->name, - ctrl->cnr, - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); -} - -/* ------------------------------------------------------------- */ - -irqreturn_t b1_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - avmctrl_info *cinfo = &card->ctrlinfo[0]; - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - if (!b1_rx_full(card->port)) { - spin_unlock_irqrestore(&card->lock, flags); - return IRQ_NONE; - } - - b1cmd = b1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - DataB3Len = b1_get_slice(card->port, card->databuf); - spin_unlock_irqrestore(&card->lock, flags); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30-MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - - skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC); - if (!skb) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - skb = alloc_skb(MsgLen, GFP_ATOMIC); - - if (!skb) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - spin_unlock_irqrestore(&card->lock, flags); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - WindowSize = b1_get_word(card->port); - capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_FREE_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - if (NCCI != 0xffffffff) - capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_START: - /* b1_put_byte(card->port, SEND_POLLACK); */ - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_resume_output(ctrl); - break; - - case RECEIVE_STOP: - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); - spin_unlock_irqrestore(&card->lock, flags); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = b1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - case 0xff: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: card removed ?\n", card->name); - return IRQ_NONE; - default: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", - card->name, b1cmd); - return IRQ_HANDLED; - } - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------- */ -int b1_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u8 flag; - char *s; - - seq_printf(m, "%-16s %s\n", "name", card->name); - seq_printf(m, "%-16s 0x%x\n", "io", card->port); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - case avm_c2: s = "C2"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if (card->cardtype == avm_t1isa) - seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr); - - s = cinfo->version[VER_DRIVER]; - if (s) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - - s = cinfo->version[VER_CARDTYPE]; - if (s) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - - s = cinfo->version[VER_SERIAL]; - if (s) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[3]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[5]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - return 0; -} -EXPORT_SYMBOL(b1_proc_show); - -/* ------------------------------------------------------------- */ - -#ifdef CONFIG_PCI - -avmcard_dmainfo * -avmcard_dma_alloc(char *name, struct pci_dev *pdev, long rsize, long ssize) -{ - avmcard_dmainfo *p; - void *buf; - - p = kzalloc(sizeof(avmcard_dmainfo), GFP_KERNEL); - if (!p) { - printk(KERN_WARNING "%s: no memory.\n", name); - goto err; - } - - p->recvbuf.size = rsize; - buf = pci_alloc_consistent(pdev, rsize, &p->recvbuf.dmaaddr); - if (!buf) { - printk(KERN_WARNING "%s: allocation of receive dma buffer failed.\n", name); - goto err_kfree; - } - p->recvbuf.dmabuf = buf; - - p->sendbuf.size = ssize; - buf = pci_alloc_consistent(pdev, ssize, &p->sendbuf.dmaaddr); - if (!buf) { - printk(KERN_WARNING "%s: allocation of send dma buffer failed.\n", name); - goto err_free_consistent; - } - - p->sendbuf.dmabuf = buf; - skb_queue_head_init(&p->send_queue); - - return p; - -err_free_consistent: - pci_free_consistent(p->pcidev, p->recvbuf.size, - p->recvbuf.dmabuf, p->recvbuf.dmaaddr); -err_kfree: - kfree(p); -err: - return NULL; -} - -void avmcard_dma_free(avmcard_dmainfo *p) -{ - pci_free_consistent(p->pcidev, p->recvbuf.size, - p->recvbuf.dmabuf, p->recvbuf.dmaaddr); - pci_free_consistent(p->pcidev, p->sendbuf.size, - p->sendbuf.dmabuf, p->sendbuf.dmaaddr); - skb_queue_purge(&p->send_queue); - kfree(p); -} - -EXPORT_SYMBOL(avmcard_dma_alloc); -EXPORT_SYMBOL(avmcard_dma_free); - -#endif - -EXPORT_SYMBOL(b1_irq_table); - -EXPORT_SYMBOL(b1_alloc_card); -EXPORT_SYMBOL(b1_free_card); -EXPORT_SYMBOL(b1_detect); -EXPORT_SYMBOL(b1_getrevision); -EXPORT_SYMBOL(b1_load_t4file); -EXPORT_SYMBOL(b1_load_config); -EXPORT_SYMBOL(b1_loaded); -EXPORT_SYMBOL(b1_load_firmware); -EXPORT_SYMBOL(b1_reset_ctr); -EXPORT_SYMBOL(b1_register_appl); -EXPORT_SYMBOL(b1_release_appl); -EXPORT_SYMBOL(b1_send_message); - -EXPORT_SYMBOL(b1_parse_version); -EXPORT_SYMBOL(b1_interrupt); - -static int __init b1_init(void) -{ - char *p; - char rev[32]; - - p = strchr(revision, ':'); - if (p && p[1]) { - strlcpy(rev, p + 2, 32); - p = strchr(rev, '$'); - if (p && p > rev) - *(p - 1) = 0; - } else { - strcpy(rev, "1.0"); - } - printk(KERN_INFO "b1: revision %s\n", rev); - - return 0; -} - -static void __exit b1_exit(void) -{ -} - -module_init(b1_init); -module_exit(b1_exit); diff --git a/drivers/staging/isdn/avm/b1dma.c b/drivers/staging/isdn/avm/b1dma.c deleted file mode 100644 index 6a3dc9937ce5..000000000000 --- a/drivers/staging/isdn/avm/b1dma.c +++ /dev/null @@ -1,981 +0,0 @@ -/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ - * - * Common module for AVM B1 cards that support dma with AMCC - * - * Copyright 2000 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" -#include -#include - -static char *revision = "$Revision: 1.1.2.3 $"; - -#undef AVM_B1DMA_DEBUG - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -static bool suppress_pollack = 0; -module_param(suppress_pollack, bool, 0); - -/* ------------------------------------------------------------- */ - -static void b1dma_dispatch_tx(avmcard *card); - -/* ------------------------------------------------------------- */ - -/* S5933 */ - -#define AMCC_RXPTR 0x24 -#define AMCC_RXLEN 0x28 -#define AMCC_TXPTR 0x2c -#define AMCC_TXLEN 0x30 - -#define AMCC_INTCSR 0x38 -# define EN_READ_TC_INT 0x00008000L -# define EN_WRITE_TC_INT 0x00004000L -# define EN_TX_TC_INT EN_READ_TC_INT -# define EN_RX_TC_INT EN_WRITE_TC_INT -# define AVM_FLAG 0x30000000L - -# define ANY_S5933_INT 0x00800000L -# define READ_TC_INT 0x00080000L -# define WRITE_TC_INT 0x00040000L -# define TX_TC_INT READ_TC_INT -# define RX_TC_INT WRITE_TC_INT -# define MASTER_ABORT_INT 0x00100000L -# define TARGET_ABORT_INT 0x00200000L -# define BUS_MASTER_INT 0x00200000L -# define ALL_INT 0x000C0000L - -#define AMCC_MCSR 0x3c -# define A2P_HI_PRIORITY 0x00000100L -# define EN_A2P_TRANSFERS 0x00000400L -# define P2A_HI_PRIORITY 0x00001000L -# define EN_P2A_TRANSFERS 0x00004000L -# define RESET_A2P_FLAGS 0x04000000L -# define RESET_P2A_FLAGS 0x02000000L - -/* ------------------------------------------------------------- */ - -static inline void b1dma_writel(avmcard *card, u32 value, int off) -{ - writel(value, card->mbase + off); -} - -static inline u32 b1dma_readl(avmcard *card, int off) -{ - return readl(card->mbase + off); -} - -/* ------------------------------------------------------------- */ - -static inline int b1dma_tx_empty(unsigned int port) -{ - return inb(port + 0x03) & 0x1; -} - -static inline int b1dma_rx_full(unsigned int port) -{ - return inb(port + 0x02) & 0x1; -} - -static int b1dma_tolink(avmcard *card, void *buf, unsigned int len) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - unsigned char *s = (unsigned char *)buf; - while (len--) { - while (!b1dma_tx_empty(card->port) - && time_before(jiffies, stop)); - if (!b1dma_tx_empty(card->port)) - return -1; - t1outp(card->port, 0x01, *s++); - } - return 0; -} - -static int b1dma_fromlink(avmcard *card, void *buf, unsigned int len) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - unsigned char *s = (unsigned char *)buf; - while (len--) { - while (!b1dma_rx_full(card->port) - && time_before(jiffies, stop)); - if (!b1dma_rx_full(card->port)) - return -1; - *s++ = t1inp(card->port, 0x00); - } - return 0; -} - -static int WriteReg(avmcard *card, u32 reg, u8 val) -{ - u8 cmd = 0x00; - if (b1dma_tolink(card, &cmd, 1) == 0 - && b1dma_tolink(card, ®, 4) == 0) { - u32 tmp = val; - return b1dma_tolink(card, &tmp, 4); - } - return -1; -} - -static u8 ReadReg(avmcard *card, u32 reg) -{ - u8 cmd = 0x01; - if (b1dma_tolink(card, &cmd, 1) == 0 - && b1dma_tolink(card, ®, 4) == 0) { - u32 tmp; - if (b1dma_fromlink(card, &tmp, 4) == 0) - return (u8)tmp; - } - return 0xff; -} - -/* ------------------------------------------------------------- */ - -static inline void _put_byte(void **pp, u8 val) -{ - u8 *s = *pp; - *s++ = val; - *pp = s; -} - -static inline void _put_word(void **pp, u32 val) -{ - u8 *s = *pp; - *s++ = val & 0xff; - *s++ = (val >> 8) & 0xff; - *s++ = (val >> 16) & 0xff; - *s++ = (val >> 24) & 0xff; - *pp = s; -} - -static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) -{ - unsigned i = len; - _put_word(pp, i); - while (i-- > 0) - _put_byte(pp, *dp++); -} - -static inline u8 _get_byte(void **pp) -{ - u8 *s = *pp; - u8 val; - val = *s++; - *pp = s; - return val; -} - -static inline u32 _get_word(void **pp) -{ - u8 *s = *pp; - u32 val; - val = *s++; - val |= (*s++ << 8); - val |= (*s++ << 16); - val |= (*s++ << 24); - *pp = s; - return val; -} - -static inline u32 _get_slice(void **pp, unsigned char *dp) -{ - unsigned int len, i; - - len = i = _get_word(pp); - while (i-- > 0) *dp++ = _get_byte(pp); - return len; -} - -/* ------------------------------------------------------------- */ - -void b1dma_reset(avmcard *card) -{ - card->csr = 0x0; - b1dma_writel(card, card->csr, AMCC_INTCSR); - b1dma_writel(card, 0, AMCC_MCSR); - b1dma_writel(card, 0, AMCC_RXLEN); - b1dma_writel(card, 0, AMCC_TXLEN); - - t1outp(card->port, 0x10, 0x00); - t1outp(card->port, 0x07, 0x00); - - b1dma_writel(card, 0, AMCC_MCSR); - mdelay(10); - b1dma_writel(card, 0x0f000000, AMCC_MCSR); /* reset all */ - mdelay(10); - b1dma_writel(card, 0, AMCC_MCSR); - if (card->cardtype == avm_t1pci) - mdelay(42); - else - mdelay(10); -} - -/* ------------------------------------------------------------- */ - -static int b1dma_detect(avmcard *card) -{ - b1dma_writel(card, 0, AMCC_MCSR); - mdelay(10); - b1dma_writel(card, 0x0f000000, AMCC_MCSR); /* reset all */ - mdelay(10); - b1dma_writel(card, 0, AMCC_MCSR); - mdelay(42); - - b1dma_writel(card, 0, AMCC_RXLEN); - b1dma_writel(card, 0, AMCC_TXLEN); - card->csr = 0x0; - b1dma_writel(card, card->csr, AMCC_INTCSR); - - if (b1dma_readl(card, AMCC_MCSR) != 0x000000E6) - return 1; - - b1dma_writel(card, 0xffffffff, AMCC_RXPTR); - b1dma_writel(card, 0xffffffff, AMCC_TXPTR); - if (b1dma_readl(card, AMCC_RXPTR) != 0xfffffffc - || b1dma_readl(card, AMCC_TXPTR) != 0xfffffffc) - return 2; - - b1dma_writel(card, 0x0, AMCC_RXPTR); - b1dma_writel(card, 0x0, AMCC_TXPTR); - if (b1dma_readl(card, AMCC_RXPTR) != 0x0 - || b1dma_readl(card, AMCC_TXPTR) != 0x0) - return 3; - - t1outp(card->port, 0x10, 0x00); - t1outp(card->port, 0x07, 0x00); - - t1outp(card->port, 0x02, 0x02); - t1outp(card->port, 0x03, 0x02); - - if ((t1inp(card->port, 0x02) & 0xFE) != 0x02 - || t1inp(card->port, 0x3) != 0x03) - return 4; - - t1outp(card->port, 0x02, 0x00); - t1outp(card->port, 0x03, 0x00); - - if ((t1inp(card->port, 0x02) & 0xFE) != 0x00 - || t1inp(card->port, 0x3) != 0x01) - return 5; - - return 0; -} - -int t1pci_detect(avmcard *card) -{ - int ret; - - if ((ret = b1dma_detect(card)) != 0) - return ret; - - /* Transputer test */ - - if (WriteReg(card, 0x80001000, 0x11) != 0 - || WriteReg(card, 0x80101000, 0x22) != 0 - || WriteReg(card, 0x80201000, 0x33) != 0 - || WriteReg(card, 0x80301000, 0x44) != 0) - return 6; - - if (ReadReg(card, 0x80001000) != 0x11 - || ReadReg(card, 0x80101000) != 0x22 - || ReadReg(card, 0x80201000) != 0x33 - || ReadReg(card, 0x80301000) != 0x44) - return 7; - - if (WriteReg(card, 0x80001000, 0x55) != 0 - || WriteReg(card, 0x80101000, 0x66) != 0 - || WriteReg(card, 0x80201000, 0x77) != 0 - || WriteReg(card, 0x80301000, 0x88) != 0) - return 8; - - if (ReadReg(card, 0x80001000) != 0x55 - || ReadReg(card, 0x80101000) != 0x66 - || ReadReg(card, 0x80201000) != 0x77 - || ReadReg(card, 0x80301000) != 0x88) - return 9; - - return 0; -} - -int b1pciv4_detect(avmcard *card) -{ - int ret, i; - - if ((ret = b1dma_detect(card)) != 0) - return ret; - - for (i = 0; i < 5; i++) { - if (WriteReg(card, 0x80A00000, 0x21) != 0) - return 6; - if ((ReadReg(card, 0x80A00000) & 0x01) != 0x01) - return 7; - } - for (i = 0; i < 5; i++) { - if (WriteReg(card, 0x80A00000, 0x20) != 0) - return 8; - if ((ReadReg(card, 0x80A00000) & 0x01) != 0x00) - return 9; - } - - return 0; -} - -static void b1dma_queue_tx(avmcard *card, struct sk_buff *skb) -{ - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - skb_queue_tail(&card->dma->send_queue, skb); - - if (!(card->csr & EN_TX_TC_INT)) { - b1dma_dispatch_tx(card); - b1dma_writel(card, card->csr, AMCC_INTCSR); - } - - spin_unlock_irqrestore(&card->lock, flags); -} - -/* ------------------------------------------------------------- */ - -static void b1dma_dispatch_tx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct sk_buff *skb; - u8 cmd, subcmd; - u16 len; - u32 txlen; - void *p; - - skb = skb_dequeue(&dma->send_queue); - - len = CAPIMSG_LEN(skb->data); - - if (len) { - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - p = dma->sendbuf.dmabuf; - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - u16 dlen = CAPIMSG_DATALEN(skb->data); - _put_byte(&p, SEND_DATA_B3_REQ); - _put_slice(&p, skb->data, len); - _put_slice(&p, skb->data + len, dlen); - } else { - _put_byte(&p, SEND_MESSAGE); - _put_slice(&p, skb->data, len); - } - txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf; -#ifdef AVM_B1DMA_DEBUG - printk(KERN_DEBUG "tx: put msg len=%d\n", txlen); -#endif - } else { - txlen = skb->len - 2; -#ifdef AVM_B1DMA_POLLDEBUG - if (skb->data[2] == SEND_POLLACK) - printk(KERN_INFO "%s: send ack\n", card->name); -#endif -#ifdef AVM_B1DMA_DEBUG - printk(KERN_DEBUG "tx: put 0x%x len=%d\n", - skb->data[2], txlen); -#endif - skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf, - skb->len - 2); - } - txlen = (txlen + 3) & ~3; - - b1dma_writel(card, dma->sendbuf.dmaaddr, AMCC_TXPTR); - b1dma_writel(card, txlen, AMCC_TXLEN); - - card->csr |= EN_TX_TC_INT; - - dev_kfree_skb_any(skb); -} - -/* ------------------------------------------------------------- */ - -static void queue_pollack(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(3, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost poll ack\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_POLLACK); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -/* ------------------------------------------------------------- */ - -static void b1dma_handle_rx(avmcard *card) -{ - avmctrl_info *cinfo = &card->ctrlinfo[0]; - avmcard_dmainfo *dma = card->dma; - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - struct sk_buff *skb; - void *p = dma->recvbuf.dmabuf + 4; - u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; - u8 b1cmd = _get_byte(&p); - -#ifdef AVM_B1DMA_DEBUG - printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen); -#endif - - switch (b1cmd) { - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - DataB3Len = _get_slice(&p, card->databuf); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30 - MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) { - spin_lock(&card->lock); - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock(&card->lock); - } - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - WindowSize = _get_word(&p); - spin_lock(&card->lock); - capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); - spin_unlock(&card->lock); - break; - - case RECEIVE_FREE_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - - if (NCCI != 0xffffffff) { - spin_lock(&card->lock); - capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); - spin_unlock(&card->lock); - } - break; - - case RECEIVE_START: -#ifdef AVM_B1DMA_POLLDEBUG - printk(KERN_INFO "%s: receive poll\n", card->name); -#endif - if (!suppress_pollack) - queue_pollack(card); - capi_ctr_resume_output(ctrl); - break; - - case RECEIVE_STOP: - capi_ctr_suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - default: - printk(KERN_ERR "%s: b1dma_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ - -static void b1dma_handle_interrupt(avmcard *card) -{ - u32 status; - u32 newcsr; - - spin_lock(&card->lock); - - status = b1dma_readl(card, AMCC_INTCSR); - if ((status & ANY_S5933_INT) == 0) { - spin_unlock(&card->lock); - return; - } - - newcsr = card->csr | (status & ALL_INT); - if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; - if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; - b1dma_writel(card, newcsr, AMCC_INTCSR); - - if ((status & RX_TC_INT) != 0) { - struct avmcard_dmainfo *dma = card->dma; - u32 rxlen; - if (card->dma->recvlen == 0) { - rxlen = b1dma_readl(card, AMCC_RXLEN); - if (rxlen == 0) { - dma->recvlen = *((u32 *)dma->recvbuf.dmabuf); - rxlen = (dma->recvlen + 3) & ~3; - b1dma_writel(card, dma->recvbuf.dmaaddr + 4, AMCC_RXPTR); - b1dma_writel(card, rxlen, AMCC_RXLEN); -#ifdef AVM_B1DMA_DEBUG - } else { - printk(KERN_ERR "%s: rx not complete (%d).\n", - card->name, rxlen); -#endif - } - } else { - spin_unlock(&card->lock); - b1dma_handle_rx(card); - dma->recvlen = 0; - spin_lock(&card->lock); - b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR); - b1dma_writel(card, 4, AMCC_RXLEN); - } - } - - if ((status & TX_TC_INT) != 0) { - if (skb_queue_empty(&card->dma->send_queue)) - card->csr &= ~EN_TX_TC_INT; - else - b1dma_dispatch_tx(card); - } - b1dma_writel(card, card->csr, AMCC_INTCSR); - - spin_unlock(&card->lock); -} - -irqreturn_t b1dma_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - - b1dma_handle_interrupt(card); - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------- */ - -static int b1dma_loaded(avmcard *card) -{ - unsigned long stop; - unsigned char ans; - unsigned long tout = 2; - unsigned int base = card->port; - - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_tx_empty(base)) - break; - } - if (!b1_tx_empty(base)) { - printk(KERN_ERR "%s: b1dma_loaded: tx err, corrupted t4 file ?\n", - card->name); - return 0; - } - b1_put_byte(base, SEND_POLLACK); - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_rx_full(base)) { - if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) { - return 1; - } - printk(KERN_ERR "%s: b1dma_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans); - return 0; - } - } - printk(KERN_ERR "%s: b1dma_loaded: firmware not running\n", card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -static void b1dma_send_init(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(15, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_INIT); - _put_word(&p, CAPI_MAXAPPL); - _put_word(&p, AVM_NCCI_PER_CHANNEL * 30); - _put_word(&p, card->cardnr - 1); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - int retval; - - b1dma_reset(card); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1dma_loaded(card)) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - card->csr = AVM_FLAG; - b1dma_writel(card, card->csr, AMCC_INTCSR); - b1dma_writel(card, EN_A2P_TRANSFERS | EN_P2A_TRANSFERS | A2P_HI_PRIORITY | - P2A_HI_PRIORITY | RESET_A2P_FLAGS | RESET_P2A_FLAGS, - AMCC_MCSR); - t1outp(card->port, 0x07, 0x30); - t1outp(card->port, 0x10, 0xF0); - - card->dma->recvlen = 0; - b1dma_writel(card, card->dma->recvbuf.dmaaddr, AMCC_RXPTR); - b1dma_writel(card, 4, AMCC_RXLEN); - card->csr |= EN_RX_TC_INT; - b1dma_writel(card, card->csr, AMCC_INTCSR); - - b1dma_send_init(card); - - return 0; -} - -void b1dma_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - b1dma_reset(card); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(ctrl); -} - -/* ------------------------------------------------------------- */ - -void b1dma_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - int want = rp->level3cnt; - int nconn; - void *p; - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel; - - skb = alloc_skb(23, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_REGISTER); - _put_word(&p, appl); - _put_word(&p, 1024 * (nconn + 1)); - _put_word(&p, nconn); - _put_word(&p, rp->datablkcnt); - _put_word(&p, rp->datablklen); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -/* ------------------------------------------------------------- */ - -void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - void *p; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - capilib_release_appl(&cinfo->ncci_head, appl); - spin_unlock_irqrestore(&card->lock, flags); - - skb = alloc_skb(7, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost release appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_RELEASE); - _put_word(&p, appl); - - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - b1dma_queue_tx(card, skb); -} - -/* ------------------------------------------------------------- */ - -u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u16 retval = CAPI_NOERROR; - - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - unsigned long flags; - spin_lock_irqsave(&card->lock, flags); - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock_irqrestore(&card->lock, flags); - } - if (retval == CAPI_NOERROR) - b1dma_queue_tx(card, skb); - - return retval; -} - -/* ------------------------------------------------------------- */ - -int b1dma_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u8 flag; - char *s; - u32 txoff, txlen, rxoff, rxlen, csr; - unsigned long flags; - - seq_printf(m, "%-16s %s\n", "name", card->name); - seq_printf(m, "%-16s 0x%x\n", "io", card->port); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - case avm_c2: s = "C2"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[3]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[5]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - - spin_lock_irqsave(&card->lock, flags); - - txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr; - txlen = b1dma_readl(card, AMCC_TXLEN); - - rxoff = (dma_addr_t)b1dma_readl(card, AMCC_RXPTR)-card->dma->recvbuf.dmaaddr; - rxlen = b1dma_readl(card, AMCC_RXLEN); - - csr = b1dma_readl(card, AMCC_INTCSR); - - spin_unlock_irqrestore(&card->lock, flags); - - seq_printf(m, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); - seq_printf(m, "%-16s 0x%lx\n", "csr", (unsigned long)csr); - seq_printf(m, "%-16s %lu\n", "txoff", (unsigned long)txoff); - seq_printf(m, "%-16s %lu\n", "txlen", (unsigned long)txlen); - seq_printf(m, "%-16s %lu\n", "rxoff", (unsigned long)rxoff); - seq_printf(m, "%-16s %lu\n", "rxlen", (unsigned long)rxlen); - - return 0; -} -EXPORT_SYMBOL(b1dma_proc_show); - -/* ------------------------------------------------------------- */ - -EXPORT_SYMBOL(b1dma_reset); -EXPORT_SYMBOL(t1pci_detect); -EXPORT_SYMBOL(b1pciv4_detect); -EXPORT_SYMBOL(b1dma_interrupt); - -EXPORT_SYMBOL(b1dma_load_firmware); -EXPORT_SYMBOL(b1dma_reset_ctr); -EXPORT_SYMBOL(b1dma_register_appl); -EXPORT_SYMBOL(b1dma_release_appl); -EXPORT_SYMBOL(b1dma_send_message); - -static int __init b1dma_init(void) -{ - char *p; - char rev[32]; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, sizeof(rev)); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - printk(KERN_INFO "b1dma: revision %s\n", rev); - - return 0; -} - -static void __exit b1dma_exit(void) -{ -} - -module_init(b1dma_init); -module_exit(b1dma_exit); diff --git a/drivers/staging/isdn/avm/b1isa.c b/drivers/staging/isdn/avm/b1isa.c deleted file mode 100644 index cdfea72e0ef6..000000000000 --- a/drivers/staging/isdn/avm/b1isa.c +++ /dev/null @@ -1,243 +0,0 @@ -/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ - * - * Module for AVM B1 ISA-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.3 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static void b1isa_remove(struct pci_dev *pdev) -{ - avmctrl_info *cinfo = pci_get_drvdata(pdev); - avmcard *card; - - if (!cinfo) - return; - - card = cinfo->card; - - b1_reset(card->port); - b1_reset(card->port); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static char *b1isa_procinfo(struct capi_ctr *ctrl); - -static int b1isa_probe(struct pci_dev *pdev) -{ - avmctrl_info *cinfo; - avmcard *card; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1isa: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - cinfo = card->ctrlinfo; - - card->port = pci_resource_start(pdev, 0); - card->irq = pdev->irq; - card->cardtype = avm_b1isa; - sprintf(card->name, "b1isa-%x", card->port); - - if (card->port != 0x150 && card->port != 0x250 - && card->port != 0x300 && card->port != 0x340) { - printk(KERN_WARNING "b1isa: invalid port 0x%x.\n", card->port); - retval = -EINVAL; - goto err_free; - } - if (b1_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); - retval = -EINVAL; - goto err_free; - } - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "b1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free; - } - retval = request_irq(card->irq, b1_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); - goto err_release_region; - } - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_free_irq; - } - b1_reset(card->port); - b1_getrevision(card); - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "b1isa"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = b1_send_message; - cinfo->capi_ctrl.load_firmware = b1_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; - cinfo->capi_ctrl.procinfo = b1isa_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1isa: attach controller failed.\n"); - goto err_free_irq; - } - - printk(KERN_INFO "b1isa: AVM B1 ISA at i/o %#x, irq %d, revision %d\n", - card->port, card->irq, card->revision); - - pci_set_drvdata(pdev, cinfo); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free: - b1_free_card(card); -err: - return retval; -} - -static char *b1isa_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -#define MAX_CARDS 4 -static struct pci_dev isa_dev[MAX_CARDS]; -static int io[MAX_CARDS]; -static int irq[MAX_CARDS]; - -module_param_hw_array(io, int, ioport, NULL, 0); -module_param_hw_array(irq, int, irq, NULL, 0); -MODULE_PARM_DESC(io, "I/O base address(es)"); -MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); - -static int b1isa_add_card(struct capi_driver *driver, capicardparams *data) -{ - int i; - - for (i = 0; i < MAX_CARDS; i++) { - if (isa_dev[i].resource[0].start) - continue; - - isa_dev[i].resource[0].start = data->port; - isa_dev[i].irq = data->irq; - - if (b1isa_probe(&isa_dev[i]) == 0) - return 0; - } - return -ENODEV; -} - -static struct capi_driver capi_driver_b1isa = { - .name = "b1isa", - .revision = "1.0", - .add_card = b1isa_add_card, -}; - -static int __init b1isa_init(void) -{ - char *p; - char rev[32]; - int i; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq = irq[i]; - - if (b1isa_probe(&isa_dev[i]) != 0) - return -ENODEV; - } - - strlcpy(capi_driver_b1isa.revision, rev, 32); - register_capi_driver(&capi_driver_b1isa); - printk(KERN_INFO "b1isa: revision %s\n", rev); - - return 0; -} - -static void __exit b1isa_exit(void) -{ - int i; - - for (i = 0; i < MAX_CARDS; i++) { - if (isa_dev[i].resource[0].start) - b1isa_remove(&isa_dev[i]); - } - unregister_capi_driver(&capi_driver_b1isa); -} - -module_init(b1isa_init); -module_exit(b1isa_exit); diff --git a/drivers/staging/isdn/avm/b1pci.c b/drivers/staging/isdn/avm/b1pci.c deleted file mode 100644 index b76b57a82c02..000000000000 --- a/drivers/staging/isdn/avm/b1pci.c +++ /dev/null @@ -1,416 +0,0 @@ -/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM B1 PCI-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -static struct pci_device_id b1pci_pci_tbl[] = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl); -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static char *b1pci_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1pci: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - cinfo = card->ctrlinfo; - sprintf(card->name, "b1pci-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->cardtype = avm_b1pci; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free; - } - b1_reset(card->port); - retval = b1_detect(card->port, card->cardtype); - if (retval) { - printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_release_region; - } - b1_reset(card->port); - b1_getrevision(card); - - retval = request_irq(card->irq, b1_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_release_region; - } - - cinfo->capi_ctrl.driver_name = "b1pci"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = b1_send_message; - cinfo->capi_ctrl.load_firmware = b1_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; - cinfo->capi_ctrl.procinfo = b1pci_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1pci: attach controller failed.\n"); - goto err_free_irq; - } - - if (card->revision >= 4) { - printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n", - card->port, card->irq, card->revision); - } else { - printk(KERN_INFO "b1pci: AVM B1 PCI at i/o %#x, irq %d, revision %d\n", - card->port, card->irq, card->revision); - } - - pci_set_drvdata(pdev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free: - b1_free_card(card); -err: - return retval; -} - -static void b1pci_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo = card->ctrlinfo; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - b1_free_card(card); -} - -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 -/* ------------------------------------------------------------- */ - -static char *b1pciv4_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1pci: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - card->dma = avmcard_dma_alloc("b1pci", pdev, 2048 + 128, 2048 + 128); - if (!card->dma) { - printk(KERN_WARNING "b1pci: dma alloc.\n"); - retval = -ENOMEM; - goto err_free; - } - - cinfo = card->ctrlinfo; - sprintf(card->name, "b1pciv4-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_b1pci; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free_dma; - } - - card->mbase = ioremap(card->membase, 64); - if (!card->mbase) { - printk(KERN_NOTICE "b1pci: can't remap memory at 0x%lx\n", - card->membase); - retval = -ENOMEM; - goto err_release_region; - } - - b1dma_reset(card); - - retval = b1pciv4_detect(card); - if (retval) { - printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_unmap; - } - b1dma_reset(card); - b1_getrevision(card); - - retval = request_irq(card->irq, b1dma_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", - card->irq); - retval = -EBUSY; - goto err_unmap; - } - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "b1pciv4"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1dma_register_appl; - cinfo->capi_ctrl.release_appl = b1dma_release_appl; - cinfo->capi_ctrl.send_message = b1dma_send_message; - cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; - cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; - cinfo->capi_ctrl.proc_show = b1dma_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1pci: attach controller failed.\n"); - goto err_free_irq; - } - card->cardnr = cinfo->capi_ctrl.cnr; - - printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n", - card->port, card->irq, card->membase, card->revision); - - pci_set_drvdata(pdev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_unmap: - iounmap(card->mbase); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free_dma: - avmcard_dma_free(card->dma); -err_free: - b1_free_card(card); -err: - return retval; - -} - -static void b1pciv4_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo = card->ctrlinfo; - - b1dma_reset(card); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - iounmap(card->mbase); - release_region(card->port, AVMB1_PORTLEN); - avmcard_dma_free(card->dma); - b1_free_card(card); -} - -#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ - -static int b1pci_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct capicardparams param; - int retval; - - if (pci_enable_device(pdev) < 0) { - printk(KERN_ERR "b1pci: failed to enable AVM-B1\n"); - return -ENODEV; - } - param.irq = pdev->irq; - - if (pci_resource_start(pdev, 2)) { /* B1 PCI V4 */ -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - pci_set_master(pdev); -#endif - param.membase = pci_resource_start(pdev, 0); - param.port = pci_resource_start(pdev, 2); - - printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n", - param.port, param.irq, param.membase); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - retval = b1pciv4_probe(¶m, pdev); -#else - retval = b1pci_probe(¶m, pdev); -#endif - if (retval != 0) { - printk(KERN_ERR "b1pci: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n", - param.port, param.irq, param.membase); - } - } else { - param.membase = 0; - param.port = pci_resource_start(pdev, 1); - - printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", - param.port, param.irq); - retval = b1pci_probe(¶m, pdev); - if (retval != 0) { - printk(KERN_ERR "b1pci: no AVM-B1 at i/o %#x, irq %d detected\n", - param.port, param.irq); - } - } - return retval; -} - -static void b1pci_pci_remove(struct pci_dev *pdev) -{ -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - avmcard *card = pci_get_drvdata(pdev); - - if (card->dma) - b1pciv4_remove(pdev); - else - b1pci_remove(pdev); -#else - b1pci_remove(pdev); -#endif -} - -static struct pci_driver b1pci_pci_driver = { - .name = "b1pci", - .id_table = b1pci_pci_tbl, - .probe = b1pci_pci_probe, - .remove = b1pci_pci_remove, -}; - -static struct capi_driver capi_driver_b1pci = { - .name = "b1pci", - .revision = "1.0", -}; -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 -static struct capi_driver capi_driver_b1pciv4 = { - .name = "b1pciv4", - .revision = "1.0", -}; -#endif - -static int __init b1pci_init(void) -{ - char *p; - char rev[32]; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - - err = pci_register_driver(&b1pci_pci_driver); - if (!err) { - strlcpy(capi_driver_b1pci.revision, rev, 32); - register_capi_driver(&capi_driver_b1pci); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - strlcpy(capi_driver_b1pciv4.revision, rev, 32); - register_capi_driver(&capi_driver_b1pciv4); -#endif - printk(KERN_INFO "b1pci: revision %s\n", rev); - } - return err; -} - -static void __exit b1pci_exit(void) -{ - unregister_capi_driver(&capi_driver_b1pci); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - unregister_capi_driver(&capi_driver_b1pciv4); -#endif - pci_unregister_driver(&b1pci_pci_driver); -} - -module_init(b1pci_init); -module_exit(b1pci_exit); diff --git a/drivers/staging/isdn/avm/b1pcmcia.c b/drivers/staging/isdn/avm/b1pcmcia.c deleted file mode 100644 index 3aca16e62902..000000000000 --- a/drivers/staging/isdn/avm/b1pcmcia.c +++ /dev/null @@ -1,224 +0,0 @@ -/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM B1/M1/M2 PCMCIA-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - detach_capi_ctr(ctrl); - free_irq(card->irq, card); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static LIST_HEAD(cards); - -static char *b1pcmcia_procinfo(struct capi_ctr *ctrl); - -static int b1pcmcia_add_card(unsigned int port, unsigned irq, - enum avmcardtype cardtype) -{ - avmctrl_info *cinfo; - avmcard *card; - char *cardname; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "b1pcmcia: no memory.\n"); - retval = -ENOMEM; - goto err; - } - cinfo = card->ctrlinfo; - - switch (cardtype) { - case avm_m1: sprintf(card->name, "m1-%x", port); break; - case avm_m2: sprintf(card->name, "m2-%x", port); break; - default: sprintf(card->name, "b1pcmcia-%x", port); break; - } - card->port = port; - card->irq = irq; - card->cardtype = cardtype; - - retval = request_irq(card->irq, b1_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", - card->irq); - retval = -EBUSY; - goto err_free; - } - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_free_irq; - } - b1_reset(card->port); - b1_getrevision(card); - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "b1pcmcia"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = b1_send_message; - cinfo->capi_ctrl.load_firmware = b1_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; - cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "b1pcmcia: attach controller failed.\n"); - goto err_free_irq; - } - switch (cardtype) { - case avm_m1: cardname = "M1"; break; - case avm_m2: cardname = "M2"; break; - default: cardname = "B1 PCMCIA"; break; - } - - printk(KERN_INFO "b1pcmcia: AVM %s at i/o %#x, irq %d, revision %d\n", - cardname, card->port, card->irq, card->revision); - - list_add(&card->list, &cards); - return cinfo->capi_ctrl.cnr; - -err_free_irq: - free_irq(card->irq, card); -err_free: - b1_free_card(card); -err: - return retval; -} - -/* ------------------------------------------------------------- */ - -static char *b1pcmcia_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -int b1pcmcia_addcard_b1(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(port, irq, avm_b1pcmcia); -} - -int b1pcmcia_addcard_m1(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(port, irq, avm_m1); -} - -int b1pcmcia_addcard_m2(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(port, irq, avm_m2); -} - -int b1pcmcia_delcard(unsigned int port, unsigned irq) -{ - struct list_head *l; - avmcard *card; - - list_for_each(l, &cards) { - card = list_entry(l, avmcard, list); - if (card->port == port && card->irq == irq) { - b1pcmcia_remove_ctr(&card->ctrlinfo[0].capi_ctrl); - return 0; - } - } - return -ESRCH; -} - -EXPORT_SYMBOL(b1pcmcia_addcard_b1); -EXPORT_SYMBOL(b1pcmcia_addcard_m1); -EXPORT_SYMBOL(b1pcmcia_addcard_m2); -EXPORT_SYMBOL(b1pcmcia_delcard); - -static struct capi_driver capi_driver_b1pcmcia = { - .name = "b1pcmcia", - .revision = "1.0", -}; - -static int __init b1pcmcia_init(void) -{ - char *p; - char rev[32]; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - strlcpy(capi_driver_b1pcmcia.revision, rev, 32); - register_capi_driver(&capi_driver_b1pcmcia); - printk(KERN_INFO "b1pci: revision %s\n", rev); - - return 0; -} - -static void __exit b1pcmcia_exit(void) -{ - unregister_capi_driver(&capi_driver_b1pcmcia); -} - -module_init(b1pcmcia_init); -module_exit(b1pcmcia_exit); diff --git a/drivers/staging/isdn/avm/c4.c b/drivers/staging/isdn/avm/c4.c deleted file mode 100644 index ac72cd204c4d..000000000000 --- a/drivers/staging/isdn/avm/c4.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM C4 & C2 card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -#undef AVM_C4_DEBUG -#undef AVM_C4_POLLDEBUG - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.2 $"; - -/* ------------------------------------------------------------- */ - -static bool suppress_pollack; - -static const struct pci_device_id c4_pci_tbl[] = { - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 0, 0, (unsigned long)4 }, - { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2, 0, 0, (unsigned long)2 }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, c4_pci_tbl); -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); -module_param(suppress_pollack, bool, 0); - -/* ------------------------------------------------------------- */ - -static void c4_dispatch_tx(avmcard *card); - -/* ------------------------------------------------------------- */ - -#define DC21285_DRAM_A0MR 0x40000000 -#define DC21285_DRAM_A1MR 0x40004000 -#define DC21285_DRAM_A2MR 0x40008000 -#define DC21285_DRAM_A3MR 0x4000C000 - -#define CAS_OFFSET 0x88 - -#define DC21285_ARMCSR_BASE 0x42000000 - -#define PCI_OUT_INT_STATUS 0x30 -#define PCI_OUT_INT_MASK 0x34 -#define MAILBOX_0 0x50 -#define MAILBOX_1 0x54 -#define MAILBOX_2 0x58 -#define MAILBOX_3 0x5C -#define DOORBELL 0x60 -#define DOORBELL_SETUP 0x64 - -#define CHAN_1_CONTROL 0x90 -#define CHAN_2_CONTROL 0xB0 -#define DRAM_TIMING 0x10C -#define DRAM_ADDR_SIZE_0 0x110 -#define DRAM_ADDR_SIZE_1 0x114 -#define DRAM_ADDR_SIZE_2 0x118 -#define DRAM_ADDR_SIZE_3 0x11C -#define SA_CONTROL 0x13C -#define XBUS_CYCLE 0x148 -#define XBUS_STROBE 0x14C -#define DBELL_PCI_MASK 0x150 -#define DBELL_SA_MASK 0x154 - -#define SDRAM_SIZE 0x1000000 - -/* ------------------------------------------------------------- */ - -#define MBOX_PEEK_POKE MAILBOX_0 - -#define DBELL_ADDR 0x01 -#define DBELL_DATA 0x02 -#define DBELL_RNWR 0x40 -#define DBELL_INIT 0x80 - -/* ------------------------------------------------------------- */ - -#define MBOX_UP_ADDR MAILBOX_0 -#define MBOX_UP_LEN MAILBOX_1 -#define MBOX_DOWN_ADDR MAILBOX_2 -#define MBOX_DOWN_LEN MAILBOX_3 - -#define DBELL_UP_HOST 0x00000100 -#define DBELL_UP_ARM 0x00000200 -#define DBELL_DOWN_HOST 0x00000400 -#define DBELL_DOWN_ARM 0x00000800 -#define DBELL_RESET_HOST 0x40000000 -#define DBELL_RESET_ARM 0x80000000 - -/* ------------------------------------------------------------- */ - -#define DRAM_TIMING_DEF 0x001A01A5 -#define DRAM_AD_SZ_DEF0 0x00000045 -#define DRAM_AD_SZ_NULL 0x00000000 - -#define SA_CTL_ALLRIGHT 0x64AA0271 - -#define INIT_XBUS_CYCLE 0x100016DB -#define INIT_XBUS_STROBE 0xF1F1F1F1 - -/* ------------------------------------------------------------- */ - -#define RESET_TIMEOUT (15 * HZ) /* 15 sec */ -#define PEEK_POKE_TIMEOUT (HZ / 10) /* 0.1 sec */ - -/* ------------------------------------------------------------- */ - -#define c4outmeml(addr, value) writel(value, addr) -#define c4inmeml(addr) readl(addr) -#define c4outmemw(addr, value) writew(value, addr) -#define c4inmemw(addr) readw(addr) -#define c4outmemb(addr, value) writeb(value, addr) -#define c4inmemb(addr) readb(addr) - -/* ------------------------------------------------------------- */ - -static inline int wait_for_doorbell(avmcard *card, unsigned long t) -{ - unsigned long stop; - - stop = jiffies + t; - while (c4inmeml(card->mbase + DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return -1; - mb(); - } - return 0; -} - -static int c4_poke(avmcard *card, unsigned long off, unsigned long value) -{ - - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - c4outmeml(card->mbase + MBOX_PEEK_POKE, off); - c4outmeml(card->mbase + DOORBELL, DBELL_ADDR); - - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - c4outmeml(card->mbase + MBOX_PEEK_POKE, value); - c4outmeml(card->mbase + DOORBELL, DBELL_DATA | DBELL_ADDR); - - return 0; -} - -static int c4_peek(avmcard *card, unsigned long off, unsigned long *valuep) -{ - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - c4outmeml(card->mbase + MBOX_PEEK_POKE, off); - c4outmeml(card->mbase + DOORBELL, DBELL_RNWR | DBELL_ADDR); - - if (wait_for_doorbell(card, HZ / 10) < 0) - return -1; - - *valuep = c4inmeml(card->mbase + MBOX_PEEK_POKE); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static int c4_load_t4file(avmcard *card, capiloaddatapart *t4file) -{ - u32 val; - unsigned char *dp; - u_int left; - u32 loadoff = 0; - - dp = t4file->data; - left = t4file->len; - while (left >= sizeof(u32)) { - if (t4file->user) { - if (copy_from_user(&val, dp, sizeof(val))) - return -EFAULT; - } else { - memcpy(&val, dp, sizeof(val)); - } - if (c4_poke(card, loadoff, val)) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - left -= sizeof(u32); - dp += sizeof(u32); - loadoff += sizeof(u32); - } - if (left) { - val = 0; - if (t4file->user) { - if (copy_from_user(&val, dp, left)) - return -EFAULT; - } else { - memcpy(&val, dp, left); - } - if (c4_poke(card, loadoff, val)) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - } - return 0; -} - -/* ------------------------------------------------------------- */ - -static inline void _put_byte(void **pp, u8 val) -{ - u8 *s = *pp; - *s++ = val; - *pp = s; -} - -static inline void _put_word(void **pp, u32 val) -{ - u8 *s = *pp; - *s++ = val & 0xff; - *s++ = (val >> 8) & 0xff; - *s++ = (val >> 16) & 0xff; - *s++ = (val >> 24) & 0xff; - *pp = s; -} - -static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) -{ - unsigned i = len; - _put_word(pp, i); - while (i-- > 0) - _put_byte(pp, *dp++); -} - -static inline u8 _get_byte(void **pp) -{ - u8 *s = *pp; - u8 val; - val = *s++; - *pp = s; - return val; -} - -static inline u32 _get_word(void **pp) -{ - u8 *s = *pp; - u32 val; - val = *s++; - val |= (*s++ << 8); - val |= (*s++ << 16); - val |= (*s++ << 24); - *pp = s; - return val; -} - -static inline u32 _get_slice(void **pp, unsigned char *dp) -{ - unsigned int len, i; - - len = i = _get_word(pp); - while (i-- > 0) *dp++ = _get_byte(pp); - return len; -} - -/* ------------------------------------------------------------- */ - -static void c4_reset(avmcard *card) -{ - unsigned long stop; - - c4outmeml(card->mbase + DOORBELL, DBELL_RESET_ARM); - - stop = jiffies + HZ * 10; - while (c4inmeml(card->mbase + DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return; - c4outmeml(card->mbase + DOORBELL, DBELL_ADDR); - mb(); - } - - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0); -} - -/* ------------------------------------------------------------- */ - -static int c4_detect(avmcard *card) -{ - unsigned long stop, dummy; - - c4outmeml(card->mbase + PCI_OUT_INT_MASK, 0x0c); - if (c4inmeml(card->mbase + PCI_OUT_INT_MASK) != 0x0c) - return 1; - - c4outmeml(card->mbase + DOORBELL, DBELL_RESET_ARM); - - stop = jiffies + HZ * 10; - while (c4inmeml(card->mbase + DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return 2; - c4outmeml(card->mbase + DOORBELL, DBELL_ADDR); - mb(); - } - - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0); - - c4outmeml(card->mbase + MAILBOX_0, 0x55aa55aa); - if (c4inmeml(card->mbase + MAILBOX_0) != 0x55aa55aa) return 3; - - c4outmeml(card->mbase + MAILBOX_0, 0xaa55aa55); - if (c4inmeml(card->mbase + MAILBOX_0) != 0xaa55aa55) return 4; - - if (c4_poke(card, DC21285_ARMCSR_BASE + DBELL_SA_MASK, 0)) return 5; - if (c4_poke(card, DC21285_ARMCSR_BASE + DBELL_PCI_MASK, 0)) return 6; - if (c4_poke(card, DC21285_ARMCSR_BASE + SA_CONTROL, SA_CTL_ALLRIGHT)) - return 7; - if (c4_poke(card, DC21285_ARMCSR_BASE + XBUS_CYCLE, INIT_XBUS_CYCLE)) - return 8; - if (c4_poke(card, DC21285_ARMCSR_BASE + XBUS_STROBE, INIT_XBUS_STROBE)) - return 8; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_TIMING, 0)) return 9; - - mdelay(1); - - if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10; - if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11; - if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12; - if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13; - - if (c4_poke(card, DC21285_DRAM_A0MR + CAS_OFFSET, 0)) return 14; - if (c4_poke(card, DC21285_DRAM_A1MR + CAS_OFFSET, 0)) return 15; - if (c4_poke(card, DC21285_DRAM_A2MR + CAS_OFFSET, 0)) return 16; - if (c4_poke(card, DC21285_DRAM_A3MR + CAS_OFFSET, 0)) return 17; - - mdelay(1); - - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_TIMING, DRAM_TIMING_DEF)) - return 18; - - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_0, DRAM_AD_SZ_DEF0)) - return 19; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_1, DRAM_AD_SZ_NULL)) - return 20; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_2, DRAM_AD_SZ_NULL)) - return 21; - if (c4_poke(card, DC21285_ARMCSR_BASE + DRAM_ADDR_SIZE_3, DRAM_AD_SZ_NULL)) - return 22; - - /* Transputer test */ - - if (c4_poke(card, 0x000000, 0x11111111) - || c4_poke(card, 0x400000, 0x22222222) - || c4_poke(card, 0x800000, 0x33333333) - || c4_poke(card, 0xC00000, 0x44444444)) - return 23; - - if (c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111 - || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222 - || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333 - || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444) - return 24; - - if (c4_poke(card, 0x000000, 0x55555555) - || c4_poke(card, 0x400000, 0x66666666) - || c4_poke(card, 0x800000, 0x77777777) - || c4_poke(card, 0xC00000, 0x88888888)) - return 25; - - if (c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555 - || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666 - || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777 - || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888) - return 26; - - return 0; -} - -/* ------------------------------------------------------------- */ - -static void c4_dispatch_tx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct sk_buff *skb; - u8 cmd, subcmd; - u16 len; - u32 txlen; - void *p; - - - if (card->csr & DBELL_DOWN_ARM) { /* tx busy */ - return; - } - - skb = skb_dequeue(&dma->send_queue); - if (!skb) { -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: tx underrun\n", card->name); -#endif - return; - } - - len = CAPIMSG_LEN(skb->data); - - if (len) { - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - p = dma->sendbuf.dmabuf; - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - u16 dlen = CAPIMSG_DATALEN(skb->data); - _put_byte(&p, SEND_DATA_B3_REQ); - _put_slice(&p, skb->data, len); - _put_slice(&p, skb->data + len, dlen); - } else { - _put_byte(&p, SEND_MESSAGE); - _put_slice(&p, skb->data, len); - } - txlen = (u8 *)p - (u8 *)dma->sendbuf.dmabuf; -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen); -#endif - } else { - txlen = skb->len - 2; -#ifdef AVM_C4_POLLDEBUG - if (skb->data[2] == SEND_POLLACK) - printk(KERN_INFO "%s: ack to c4\n", card->name); -#endif -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n", - card->name, skb->data[2], txlen); -#endif - skb_copy_from_linear_data_offset(skb, 2, dma->sendbuf.dmabuf, - skb->len - 2); - } - txlen = (txlen + 3) & ~3; - - c4outmeml(card->mbase + MBOX_DOWN_ADDR, dma->sendbuf.dmaaddr); - c4outmeml(card->mbase + MBOX_DOWN_LEN, txlen); - - card->csr |= DBELL_DOWN_ARM; - - c4outmeml(card->mbase + DOORBELL, DBELL_DOWN_ARM); - - dev_kfree_skb_any(skb); -} - -/* ------------------------------------------------------------- */ - -static void queue_pollack(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(3, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost poll ack\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_POLLACK); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -static void c4_handle_rx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct capi_ctr *ctrl; - avmctrl_info *cinfo; - struct sk_buff *skb; - void *p = dma->recvbuf.dmabuf; - u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; - u8 b1cmd = _get_byte(&p); - u32 cidx; - - -#ifdef AVM_C4_DEBUG - printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name, - b1cmd, (unsigned long)dma->recvlen); -#endif - - switch (b1cmd) { - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - DataB3Len = _get_slice(&p, card->databuf); - cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30 - MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - cinfo = &card->ctrlinfo[cidx]; - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_CONF) - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - WindowSize = _get_word(&p); - cidx = (NCCI & 0x7f) - card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - - capilib_new_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - - if (NCCI != 0xffffffff) { - cidx = (NCCI & 0x7f) - card->cardnr; - if (cidx >= card->nlogcontr) cidx = 0; - capilib_free_ncci(&card->ctrlinfo[cidx].ncci_head, ApplId, NCCI); - } - break; - - case RECEIVE_START: -#ifdef AVM_C4_POLLDEBUG - printk(KERN_INFO "%s: poll from c4\n", card->name); -#endif - if (!suppress_pollack) - queue_pollack(card); - for (cidx = 0; cidx < card->nr_controllers; cidx++) { - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - capi_ctr_resume_output(ctrl); - } - break; - - case RECEIVE_STOP: - for (cidx = 0; cidx < card->nr_controllers; cidx++) { - ctrl = &card->ctrlinfo[cidx].capi_ctrl; - capi_ctr_suspend_output(ctrl); - } - break; - - case RECEIVE_INIT: - - cidx = card->nlogcontr; - if (cidx >= card->nr_controllers) { - printk(KERN_ERR "%s: card with %d controllers ??\n", - card->name, cidx + 1); - break; - } - card->nlogcontr++; - cinfo = &card->ctrlinfo[cidx]; - ctrl = &cinfo->capi_ctrl; - cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(&cinfo->capi_ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - default: - printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ - -static irqreturn_t c4_handle_interrupt(avmcard *card) -{ - unsigned long flags; - u32 status; - - spin_lock_irqsave(&card->lock, flags); - status = c4inmeml(card->mbase + DOORBELL); - - if (status & DBELL_RESET_HOST) { - u_int i; - c4outmeml(card->mbase + PCI_OUT_INT_MASK, 0x0c); - spin_unlock_irqrestore(&card->lock, flags); - if (card->nlogcontr == 0) - return IRQ_HANDLED; - printk(KERN_ERR "%s: unexpected reset\n", card->name); - for (i = 0; i < card->nr_controllers; i++) { - avmctrl_info *cinfo = &card->ctrlinfo[i]; - memset(cinfo->version, 0, sizeof(cinfo->version)); - spin_lock_irqsave(&card->lock, flags); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(&cinfo->capi_ctrl); - } - card->nlogcontr = 0; - return IRQ_HANDLED; - } - - status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); - if (!status) { - spin_unlock_irqrestore(&card->lock, flags); - return IRQ_HANDLED; - } - c4outmeml(card->mbase + DOORBELL, status); - - if ((status & DBELL_UP_HOST) != 0) { - card->dma->recvlen = c4inmeml(card->mbase + MBOX_UP_LEN); - c4outmeml(card->mbase + MBOX_UP_LEN, 0); - c4_handle_rx(card); - card->dma->recvlen = 0; - c4outmeml(card->mbase + MBOX_UP_LEN, card->dma->recvbuf.size); - c4outmeml(card->mbase + DOORBELL, DBELL_UP_ARM); - } - - if ((status & DBELL_DOWN_HOST) != 0) { - card->csr &= ~DBELL_DOWN_ARM; - c4_dispatch_tx(card); - } else if (card->csr & DBELL_DOWN_HOST) { - if (c4inmeml(card->mbase + MBOX_DOWN_LEN) == 0) { - card->csr &= ~DBELL_DOWN_ARM; - c4_dispatch_tx(card); - } - } - spin_unlock_irqrestore(&card->lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t c4_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - - return c4_handle_interrupt(card); -} - -/* ------------------------------------------------------------- */ - -static void c4_send_init(avmcard *card) -{ - struct sk_buff *skb; - void *p; - unsigned long flags; - - skb = alloc_skb(15, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_INIT); - _put_word(&p, CAPI_MAXAPPL); - _put_word(&p, AVM_NCCI_PER_CHANNEL * 30); - _put_word(&p, card->cardnr - 1); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); -} - -static int queue_sendconfigword(avmcard *card, u32 val) -{ - struct sk_buff *skb; - unsigned long flags; - void *p; - - skb = alloc_skb(3 + 4, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, send config\n", - card->name); - return -ENOMEM; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_CONFIG); - _put_word(&p, val); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - return 0; -} - -static int queue_sendconfig(avmcard *card, char cval[4]) -{ - struct sk_buff *skb; - unsigned long flags; - void *p; - - skb = alloc_skb(3 + 4, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, send config\n", - card->name); - return -ENOMEM; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_CONFIG); - _put_byte(&p, cval[0]); - _put_byte(&p, cval[1]); - _put_byte(&p, cval[2]); - _put_byte(&p, cval[3]); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - return 0; -} - -static int c4_send_config(avmcard *card, capiloaddatapart *config) -{ - u8 val[4]; - unsigned char *dp; - u_int left; - int retval; - - if ((retval = queue_sendconfigword(card, 1)) != 0) - return retval; - if ((retval = queue_sendconfigword(card, config->len)) != 0) - return retval; - - dp = config->data; - left = config->len; - while (left >= sizeof(u32)) { - if (config->user) { - if (copy_from_user(val, dp, sizeof(val))) - return -EFAULT; - } else { - memcpy(val, dp, sizeof(val)); - } - if ((retval = queue_sendconfig(card, val)) != 0) - return retval; - left -= sizeof(val); - dp += sizeof(val); - } - if (left) { - memset(val, 0, sizeof(val)); - if (config->user) { - if (copy_from_user(&val, dp, left)) - return -EFAULT; - } else { - memcpy(&val, dp, left); - } - if ((retval = queue_sendconfig(card, val)) != 0) - return retval; - } - - return 0; -} - -static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - int retval; - - if ((retval = c4_load_t4file(card, &data->firmware))) { - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - c4_reset(card); - return retval; - } - - card->csr = 0; - c4outmeml(card->mbase + MBOX_UP_LEN, 0); - c4outmeml(card->mbase + MBOX_DOWN_LEN, 0); - c4outmeml(card->mbase + DOORBELL, DBELL_INIT); - mdelay(1); - c4outmeml(card->mbase + DOORBELL, - DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST); - - c4outmeml(card->mbase + PCI_OUT_INT_MASK, 0x08); - - card->dma->recvlen = 0; - c4outmeml(card->mbase + MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr); - c4outmeml(card->mbase + MBOX_UP_LEN, card->dma->recvbuf.size); - c4outmeml(card->mbase + DOORBELL, DBELL_UP_ARM); - - if (data->configuration.len > 0 && data->configuration.data) { - retval = c4_send_config(card, &data->configuration); - if (retval) { - printk(KERN_ERR "%s: failed to set config!!\n", - card->name); - c4_reset(card); - return retval; - } - } - - c4_send_init(card); - - return 0; -} - - -static void c4_reset_ctr(struct capi_ctr *ctrl) -{ - avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; - avmctrl_info *cinfo; - u_int i; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - c4_reset(card); - - spin_unlock_irqrestore(&card->lock, flags); - - for (i = 0; i < card->nr_controllers; i++) { - cinfo = &card->ctrlinfo[i]; - memset(cinfo->version, 0, sizeof(cinfo->version)); - capi_ctr_down(&cinfo->capi_ctrl); - } - card->nlogcontr = 0; -} - -static void c4_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo; - u_int i; - - if (!card) - return; - - c4_reset(card); - - for (i = 0; i < card->nr_controllers; i++) { - cinfo = &card->ctrlinfo[i]; - detach_capi_ctr(&cinfo->capi_ctrl); - } - - free_irq(card->irq, card); - iounmap(card->mbase); - release_region(card->port, AVMB1_PORTLEN); - avmcard_dma_free(card->dma); - pci_set_drvdata(pdev, NULL); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - - -static void c4_register_appl(struct capi_ctr *ctrl, - u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - int want = rp->level3cnt; - unsigned long flags; - int nconn; - void *p; - - if (ctrl->cnr == card->cardnr) { - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * 4 * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel * 4; - - skb = alloc_skb(23, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_REGISTER); - _put_word(&p, appl); - _put_word(&p, 1024 * (nconn + 1)); - _put_word(&p, nconn); - _put_word(&p, rp->datablkcnt); - _put_word(&p, rp->datablklen); - skb_put(skb, (u8 *)p - (u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - } -} - -/* ------------------------------------------------------------- */ - -static void c4_release_appl(struct capi_ctr *ctrl, u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - struct sk_buff *skb; - void *p; - - spin_lock_irqsave(&card->lock, flags); - capilib_release_appl(&cinfo->ncci_head, appl); - spin_unlock_irqrestore(&card->lock, flags); - - if (ctrl->cnr == card->cardnr) { - skb = alloc_skb(7, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost release appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_RELEASE); - _put_word(&p, appl); - - skb_put(skb, (u8 *)p - (u8 *)skb->data); - skb_queue_tail(&card->dma->send_queue, skb); - spin_lock_irqsave(&card->lock, flags); - c4_dispatch_tx(card); - spin_unlock_irqrestore(&card->lock, flags); - } -} - -/* ------------------------------------------------------------- */ - - -static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u16 retval = CAPI_NOERROR; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - } - if (retval == CAPI_NOERROR) { - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); - } - spin_unlock_irqrestore(&card->lock, flags); - return retval; -} - -/* ------------------------------------------------------------- */ - -static char *c4_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0 - ); - return cinfo->infobuf; -} - -static int c4_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - u8 flag; - char *s; - - seq_printf(m, "%-16s %s\n", "name", card->name); - seq_printf(m, "%-16s 0x%x\n", "io", card->port); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - case avm_c2: s = "C2"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[3]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((u8 *)(ctrl->profile.manu))[5]; - if (flag) - seq_printf(m, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, - int nr_controllers) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - int i; - - card = b1_alloc_card(nr_controllers); - if (!card) { - printk(KERN_WARNING "c4: no memory.\n"); - retval = -ENOMEM; - goto err; - } - card->dma = avmcard_dma_alloc("c4", dev, 2048 + 128, 2048 + 128); - if (!card->dma) { - printk(KERN_WARNING "c4: no memory.\n"); - retval = -ENOMEM; - goto err_free; - } - - sprintf(card->name, "c%d-%x", nr_controllers, p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = (nr_controllers == 4) ? avm_c4 : avm_c2; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "c4: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free_dma; - } - - card->mbase = ioremap(card->membase, 128); - if (card->mbase == NULL) { - printk(KERN_NOTICE "c4: can't remap memory at 0x%lx\n", - card->membase); - retval = -EIO; - goto err_release_region; - } - - retval = c4_detect(card); - if (retval != 0) { - printk(KERN_NOTICE "c4: NO card at 0x%x error(%d)\n", - card->port, retval); - retval = -EIO; - goto err_unmap; - } - c4_reset(card); - - retval = request_irq(card->irq, c4_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "c4: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_unmap; - } - - for (i = 0; i < nr_controllers; i++) { - cinfo = &card->ctrlinfo[i]; - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "c4"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = c4_register_appl; - cinfo->capi_ctrl.release_appl = c4_release_appl; - cinfo->capi_ctrl.send_message = c4_send_message; - cinfo->capi_ctrl.load_firmware = c4_load_firmware; - cinfo->capi_ctrl.reset_ctr = c4_reset_ctr; - cinfo->capi_ctrl.procinfo = c4_procinfo; - cinfo->capi_ctrl.proc_show = c4_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "c4: attach controller failed (%d).\n", i); - for (i--; i >= 0; i--) { - cinfo = &card->ctrlinfo[i]; - detach_capi_ctr(&cinfo->capi_ctrl); - } - goto err_free_irq; - } - if (i == 0) - card->cardnr = cinfo->capi_ctrl.cnr; - } - - printk(KERN_INFO "c4: AVM C%d at i/o %#x, irq %d, mem %#lx\n", - nr_controllers, card->port, card->irq, - card->membase); - pci_set_drvdata(dev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_unmap: - iounmap(card->mbase); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free_dma: - avmcard_dma_free(card->dma); -err_free: - b1_free_card(card); -err: - return retval; -} - -/* ------------------------------------------------------------- */ - -static int c4_probe(struct pci_dev *dev, const struct pci_device_id *ent) -{ - int nr = ent->driver_data; - int retval = 0; - struct capicardparams param; - - if (pci_enable_device(dev) < 0) { - printk(KERN_ERR "c4: failed to enable AVM-C%d\n", nr); - return -ENODEV; - } - pci_set_master(dev); - - param.port = pci_resource_start(dev, 1); - param.irq = dev->irq; - param.membase = pci_resource_start(dev, 0); - - printk(KERN_INFO "c4: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n", - nr, param.port, param.irq, param.membase); - - retval = c4_add_card(¶m, dev, nr); - if (retval != 0) { - printk(KERN_ERR "c4: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n", - nr, param.port, param.irq, param.membase); - pci_disable_device(dev); - return -ENODEV; - } - return 0; -} - -static struct pci_driver c4_pci_driver = { - .name = "c4", - .id_table = c4_pci_tbl, - .probe = c4_probe, - .remove = c4_remove, -}; - -static struct capi_driver capi_driver_c2 = { - .name = "c2", - .revision = "1.0", -}; - -static struct capi_driver capi_driver_c4 = { - .name = "c4", - .revision = "1.0", -}; - -static int __init c4_init(void) -{ - char *p; - char rev[32]; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - err = pci_register_driver(&c4_pci_driver); - if (!err) { - strlcpy(capi_driver_c2.revision, rev, 32); - register_capi_driver(&capi_driver_c2); - strlcpy(capi_driver_c4.revision, rev, 32); - register_capi_driver(&capi_driver_c4); - printk(KERN_INFO "c4: revision %s\n", rev); - } - return err; -} - -static void __exit c4_exit(void) -{ - unregister_capi_driver(&capi_driver_c2); - unregister_capi_driver(&capi_driver_c4); - pci_unregister_driver(&c4_pci_driver); -} - -module_init(c4_init); -module_exit(c4_exit); diff --git a/drivers/staging/isdn/avm/t1isa.c b/drivers/staging/isdn/avm/t1isa.c deleted file mode 100644 index 2153619c5b31..000000000000 --- a/drivers/staging/isdn/avm/t1isa.c +++ /dev/null @@ -1,594 +0,0 @@ -/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ - * - * Module for AVM T1 HEMA-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -/* ------------------------------------------------------------- */ - -static char *revision = "$Revision: 1.1.2.3 $"; - -/* ------------------------------------------------------------- */ - -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static int hema_irq_table[16] = -{0, - 0, - 0, - 0x80, /* irq 3 */ - 0, - 0x90, /* irq 5 */ - 0, - 0xA0, /* irq 7 */ - 0, - 0xB0, /* irq 9 */ - 0xC0, /* irq 10 */ - 0xD0, /* irq 11 */ - 0xE0, /* irq 12 */ - 0, - 0, - 0xF0, /* irq 15 */ -}; - -static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr) -{ - unsigned char cregs[8]; - unsigned char reverse_cardnr; - unsigned char dummy; - int i; - - reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1) - | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3); - cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf); - cregs[1] = 0x00; /* fast & slow link connected to CON1 */ - cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */ - cregs[3] = 0; - cregs[4] = 0x11; /* zero wait state */ - cregs[5] = hema_irq_table[irq & 0xf]; - cregs[6] = 0; - cregs[7] = 0; - - /* - * no one else should use the ISA bus in this moment, - * but no function there to prevent this :-( - * save_flags(flags); cli(); - */ - - /* board reset */ - t1outp(base, T1_RESETBOARD, 0xf); - mdelay(100); - dummy = t1inp(base, T1_FASTLINK + T1_OUTSTAT); /* first read */ - - /* write config */ - dummy = (base >> 4) & 0xff; - for (i = 1; i <= 0xf; i++) t1outp(base, i, dummy); - t1outp(base, HEMA_PAL_ID & 0xf, dummy); - t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); - for (i = 1; i < 7; i++) t1outp(base, 0, cregs[i]); - t1outp(base, ((base >> 4)) & 0x3, cregs[7]); - /* restore_flags(flags); */ - - mdelay(100); - t1outp(base, T1_FASTLINK + T1_RESETLINK, 0); - t1outp(base, T1_SLOWLINK + T1_RESETLINK, 0); - mdelay(10); - t1outp(base, T1_FASTLINK + T1_RESETLINK, 1); - t1outp(base, T1_SLOWLINK + T1_RESETLINK, 1); - mdelay(100); - t1outp(base, T1_FASTLINK + T1_RESETLINK, 0); - t1outp(base, T1_SLOWLINK + T1_RESETLINK, 0); - mdelay(10); - t1outp(base, T1_FASTLINK + T1_ANALYSE, 0); - mdelay(5); - t1outp(base, T1_SLOWLINK + T1_ANALYSE, 0); - - if (t1inp(base, T1_FASTLINK + T1_OUTSTAT) != 0x1) /* tx empty */ - return 1; - if (t1inp(base, T1_FASTLINK + T1_INSTAT) != 0x0) /* rx empty */ - return 2; - if (t1inp(base, T1_FASTLINK + T1_IRQENABLE) != 0x0) - return 3; - if ((t1inp(base, T1_FASTLINK + T1_FIFOSTAT) & 0xf0) != 0x70) - return 4; - if ((t1inp(base, T1_FASTLINK + T1_IRQMASTER) & 0x0e) != 0) - return 5; - if ((t1inp(base, T1_FASTLINK + T1_IDENT) & 0x7d) != 1) - return 6; - if (t1inp(base, T1_SLOWLINK + T1_OUTSTAT) != 0x1) /* tx empty */ - return 7; - if ((t1inp(base, T1_SLOWLINK + T1_IRQMASTER) & 0x0e) != 0) - return 8; - if ((t1inp(base, T1_SLOWLINK + T1_IDENT) & 0x7d) != 0) - return 9; - return 0; -} - -static irqreturn_t t1isa_interrupt(int interrupt, void *devptr) -{ - avmcard *card = devptr; - avmctrl_info *cinfo = &card->ctrlinfo[0]; - struct capi_ctr *ctrl = &cinfo->capi_ctrl; - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); - - while (b1_rx_full(card->port)) { - - b1cmd = b1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - DataB3Len = t1_get_slice(card->port, card->databuf); - spin_unlock_irqrestore(&card->lock, flags); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf + MsgLen, 0, 30 - MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - skb_put_data(skb, card->databuf, DataB3Len); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - skb_put_data(skb, card->msgbuf, MsgLen); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3) - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_handle_message(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - WindowSize = b1_get_word(card->port); - capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_FREE_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - if (NCCI != 0xffffffff) - capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); - spin_unlock_irqrestore(&card->lock, flags); - break; - - case RECEIVE_START: - b1_put_byte(card->port, SEND_POLLACK); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_resume_output(ctrl); - break; - - case RECEIVE_STOP: - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); - spin_unlock_irqrestore(&card->lock, flags); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - capi_ctr_ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = t1_get_slice(card->port, card->msgbuf); - spin_unlock_irqrestore(&card->lock, flags); - card->msgbuf[MsgLen] = 0; - while (MsgLen > 0 - && (card->msgbuf[MsgLen - 1] == '\n' - || card->msgbuf[MsgLen - 1] == '\r')) { - card->msgbuf[MsgLen - 1] = 0; - MsgLen--; - } - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - - case 0xff: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: card reseted ?\n", card->name); - return IRQ_HANDLED; - default: - spin_unlock_irqrestore(&card->lock, flags); - printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", - card->name, b1cmd); - return IRQ_NONE; - } - } - return IRQ_HANDLED; -} - -/* ------------------------------------------------------------- */ - -static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int retval; - - t1_disable_irq(port); - b1_reset(port); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1_loaded(card)) { - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - spin_lock_irqsave(&card->lock, flags); - b1_setinterrupt(port, card->irq, card->cardtype); - b1_put_byte(port, SEND_INIT); - b1_put_word(port, CAPI_MAXAPPL); - b1_put_word(port, AVM_NCCI_PER_CHANNEL * 30); - b1_put_word(port, ctrl->cnr - 1); - spin_unlock_irqrestore(&card->lock, flags); - - return 0; -} - -static void t1isa_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - t1_disable_irq(port); - b1_reset(port); - b1_reset(port); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - spin_lock_irqsave(&card->lock, flags); - capilib_release(&cinfo->ncci_head); - spin_unlock_irqrestore(&card->lock, flags); - capi_ctr_down(ctrl); -} - -static void t1isa_remove(struct pci_dev *pdev) -{ - avmctrl_info *cinfo = pci_get_drvdata(pdev); - avmcard *card; - - if (!cinfo) - return; - - card = cinfo->card; - - t1_disable_irq(card->port); - b1_reset(card->port); - b1_reset(card->port); - t1_reset(card->port); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -static char *t1isa_procinfo(struct capi_ctr *ctrl); - -static int t1isa_probe(struct pci_dev *pdev, int cardnr) -{ - avmctrl_info *cinfo; - avmcard *card; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "t1isa: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - cinfo = card->ctrlinfo; - card->port = pci_resource_start(pdev, 0); - card->irq = pdev->irq; - card->cardtype = avm_t1isa; - card->cardnr = cardnr; - sprintf(card->name, "t1isa-%x", card->port); - - if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { - printk(KERN_WARNING "t1isa: invalid port 0x%x.\n", card->port); - retval = -EINVAL; - goto err_free; - } - if (hema_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq); - retval = -EINVAL; - goto err_free; - } - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_INFO "t1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free; - } - retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_INFO "t1isa: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_release_region; - } - - if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { - printk(KERN_INFO "t1isa: NO card at 0x%x (%d)\n", - card->port, retval); - retval = -ENODEV; - goto err_free_irq; - } - t1_disable_irq(card->port); - b1_reset(card->port); - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "t1isa"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1_register_appl; - cinfo->capi_ctrl.release_appl = b1_release_appl; - cinfo->capi_ctrl.send_message = t1isa_send_message; - cinfo->capi_ctrl.load_firmware = t1isa_load_firmware; - cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr; - cinfo->capi_ctrl.procinfo = t1isa_procinfo; - cinfo->capi_ctrl.proc_show = b1_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_INFO "t1isa: attach controller failed.\n"); - goto err_free_irq; - } - - printk(KERN_INFO "t1isa: AVM T1 ISA at i/o %#x, irq %d, card %d\n", - card->port, card->irq, card->cardnr); - - pci_set_drvdata(pdev, cinfo); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free: - b1_free_card(card); -err: - return retval; -} - -static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - u16 len = CAPIMSG_LEN(skb->data); - u8 cmd = CAPIMSG_COMMAND(skb->data); - u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - u16 dlen, retval; - - spin_lock_irqsave(&card->lock, flags); - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - if (retval != CAPI_NOERROR) { - spin_unlock_irqrestore(&card->lock, flags); - return retval; - } - dlen = CAPIMSG_DATALEN(skb->data); - - b1_put_byte(port, SEND_DATA_B3_REQ); - t1_put_slice(port, skb->data, len); - t1_put_slice(port, skb->data + len, dlen); - } else { - b1_put_byte(port, SEND_MESSAGE); - t1_put_slice(port, skb->data, len); - } - spin_unlock_irqrestore(&card->lock, flags); - dev_kfree_skb_any(skb); - return CAPI_NOERROR; -} -/* ------------------------------------------------------------- */ - -static char *t1isa_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d %d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->cardnr : 0 - ); - return cinfo->infobuf; -} - - -/* ------------------------------------------------------------- */ - -#define MAX_CARDS 4 -static struct pci_dev isa_dev[MAX_CARDS]; -static int io[MAX_CARDS]; -static int irq[MAX_CARDS]; -static int cardnr[MAX_CARDS]; - -module_param_hw_array(io, int, ioport, NULL, 0); -module_param_hw_array(irq, int, irq, NULL, 0); -module_param_array(cardnr, int, NULL, 0); -MODULE_PARM_DESC(io, "I/O base address(es)"); -MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); -MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)"); - -static int t1isa_add_card(struct capi_driver *driver, capicardparams *data) -{ - int i; - - for (i = 0; i < MAX_CARDS; i++) { - if (isa_dev[i].resource[0].start) - continue; - - isa_dev[i].resource[0].start = data->port; - isa_dev[i].irq = data->irq; - - if (t1isa_probe(&isa_dev[i], data->cardnr) == 0) - return 0; - } - return -ENODEV; -} - -static struct capi_driver capi_driver_t1isa = { - .name = "t1isa", - .revision = "1.0", - .add_card = t1isa_add_card, -}; - -static int __init t1isa_init(void) -{ - char rev[32]; - char *p; - int i; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq = irq[i]; - - if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0) - return -ENODEV; - } - - strlcpy(capi_driver_t1isa.revision, rev, 32); - register_capi_driver(&capi_driver_t1isa); - printk(KERN_INFO "t1isa: revision %s\n", rev); - - return 0; -} - -static void __exit t1isa_exit(void) -{ - int i; - - unregister_capi_driver(&capi_driver_t1isa); - for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - t1isa_remove(&isa_dev[i]); - } -} - -module_init(t1isa_init); -module_exit(t1isa_exit); diff --git a/drivers/staging/isdn/avm/t1pci.c b/drivers/staging/isdn/avm/t1pci.c deleted file mode 100644 index f5ed1d5004c9..000000000000 --- a/drivers/staging/isdn/avm/t1pci.c +++ /dev/null @@ -1,259 +0,0 @@ -/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ - * - * Module for AVM T1 PCI-card. - * - * Copyright 1999 by Carsten Paeth - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "avmcard.h" - -#undef CONFIG_T1PCI_DEBUG -#undef CONFIG_T1PCI_POLLDEBUG - -/* ------------------------------------------------------------- */ -static char *revision = "$Revision: 1.1.2.2 $"; -/* ------------------------------------------------------------- */ - -static struct pci_device_id t1pci_pci_tbl[] = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl); -MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------- */ - -static char *t1pci_procinfo(struct capi_ctr *ctrl); - -static int t1pci_add_card(struct capicardparams *p, struct pci_dev *pdev) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = b1_alloc_card(1); - if (!card) { - printk(KERN_WARNING "t1pci: no memory.\n"); - retval = -ENOMEM; - goto err; - } - - card->dma = avmcard_dma_alloc("t1pci", pdev, 2048 + 128, 2048 + 128); - if (!card->dma) { - printk(KERN_WARNING "t1pci: no memory.\n"); - retval = -ENOMEM; - goto err_free; - } - - cinfo = card->ctrlinfo; - sprintf(card->name, "t1pci-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_t1pci; - - if (!request_region(card->port, AVMB1_PORTLEN, card->name)) { - printk(KERN_WARNING "t1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - retval = -EBUSY; - goto err_free_dma; - } - - card->mbase = ioremap(card->membase, 64); - if (!card->mbase) { - printk(KERN_NOTICE "t1pci: can't remap memory at 0x%lx\n", - card->membase); - retval = -EIO; - goto err_release_region; - } - - b1dma_reset(card); - - retval = t1pci_detect(card); - if (retval != 0) { - if (retval < 6) - printk(KERN_NOTICE "t1pci: NO card at 0x%x (%d)\n", - card->port, retval); - else - printk(KERN_NOTICE "t1pci: card at 0x%x, but cable not connected or T1 has no power (%d)\n", - card->port, retval); - retval = -EIO; - goto err_unmap; - } - b1dma_reset(card); - - retval = request_irq(card->irq, b1dma_interrupt, IRQF_SHARED, card->name, card); - if (retval) { - printk(KERN_ERR "t1pci: unable to get IRQ %d.\n", card->irq); - retval = -EBUSY; - goto err_unmap; - } - - cinfo->capi_ctrl.owner = THIS_MODULE; - cinfo->capi_ctrl.driver_name = "t1pci"; - cinfo->capi_ctrl.driverdata = cinfo; - cinfo->capi_ctrl.register_appl = b1dma_register_appl; - cinfo->capi_ctrl.release_appl = b1dma_release_appl; - cinfo->capi_ctrl.send_message = b1dma_send_message; - cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; - cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; - cinfo->capi_ctrl.procinfo = t1pci_procinfo; - cinfo->capi_ctrl.proc_show = b1dma_proc_show; - strcpy(cinfo->capi_ctrl.name, card->name); - - retval = attach_capi_ctr(&cinfo->capi_ctrl); - if (retval) { - printk(KERN_ERR "t1pci: attach controller failed.\n"); - retval = -EBUSY; - goto err_free_irq; - } - card->cardnr = cinfo->capi_ctrl.cnr; - - printk(KERN_INFO "t1pci: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n", - card->port, card->irq, card->membase); - - pci_set_drvdata(pdev, card); - return 0; - -err_free_irq: - free_irq(card->irq, card); -err_unmap: - iounmap(card->mbase); -err_release_region: - release_region(card->port, AVMB1_PORTLEN); -err_free_dma: - avmcard_dma_free(card->dma); -err_free: - b1_free_card(card); -err: - return retval; -} - -/* ------------------------------------------------------------- */ - -static void t1pci_remove(struct pci_dev *pdev) -{ - avmcard *card = pci_get_drvdata(pdev); - avmctrl_info *cinfo = card->ctrlinfo; - - b1dma_reset(card); - - detach_capi_ctr(&cinfo->capi_ctrl); - free_irq(card->irq, card); - iounmap(card->mbase); - release_region(card->port, AVMB1_PORTLEN); - avmcard_dma_free(card->dma); - b1_free_card(card); -} - -/* ------------------------------------------------------------- */ - -static char *t1pci_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int t1pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) -{ - struct capicardparams param; - int retval; - - if (pci_enable_device(dev) < 0) { - printk(KERN_ERR "t1pci: failed to enable AVM-T1-PCI\n"); - return -ENODEV; - } - pci_set_master(dev); - - param.port = pci_resource_start(dev, 1); - param.irq = dev->irq; - param.membase = pci_resource_start(dev, 0); - - printk(KERN_INFO "t1pci: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", - param.port, param.irq, param.membase); - - retval = t1pci_add_card(¶m, dev); - if (retval != 0) { - printk(KERN_ERR "t1pci: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", - param.port, param.irq, param.membase); - pci_disable_device(dev); - return -ENODEV; - } - return 0; -} - -static struct pci_driver t1pci_pci_driver = { - .name = "t1pci", - .id_table = t1pci_pci_tbl, - .probe = t1pci_probe, - .remove = t1pci_remove, -}; - -static struct capi_driver capi_driver_t1pci = { - .name = "t1pci", - .revision = "1.0", -}; - -static int __init t1pci_init(void) -{ - char *p; - char rev[32]; - int err; - - if ((p = strchr(revision, ':')) != NULL && p[1]) { - strlcpy(rev, p + 2, 32); - if ((p = strchr(rev, '$')) != NULL && p > rev) - *(p - 1) = 0; - } else - strcpy(rev, "1.0"); - - err = pci_register_driver(&t1pci_pci_driver); - if (!err) { - strlcpy(capi_driver_t1pci.revision, rev, 32); - register_capi_driver(&capi_driver_t1pci); - printk(KERN_INFO "t1pci: revision %s\n", rev); - } - return err; -} - -static void __exit t1pci_exit(void) -{ - unregister_capi_driver(&capi_driver_t1pci); - pci_unregister_driver(&t1pci_pci_driver); -} - -module_init(t1pci_init); -module_exit(t1pci_exit); diff --git a/drivers/staging/isdn/gigaset/Kconfig b/drivers/staging/isdn/gigaset/Kconfig deleted file mode 100644 index c593105b3600..000000000000 --- a/drivers/staging/isdn/gigaset/Kconfig +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -menuconfig ISDN_DRV_GIGASET - tristate "Siemens Gigaset support" - depends on TTY - select CRC_CCITT - select BITREVERSE - help - This driver supports the Siemens Gigaset SX205/255 family of - ISDN DECT bases, including the predecessors Gigaset 3070/3075 - and 4170/4175 and their T-Com versions Sinus 45isdn and Sinus - 721X. - If you have one of these devices, say M here and for at least - one of the connection specific parts that follow. - This will build a module called "gigaset". - Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L) - as a module, you have to build this driver as a module too, - otherwise the Gigaset device won't show up as an ISDN device. - -if ISDN_DRV_GIGASET - -config GIGASET_CAPI - bool "Gigaset CAPI support" - depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m') - default 'y' - help - Build the Gigaset driver as a CAPI 2.0 driver interfacing with - the Kernel CAPI subsystem. To use it with the old ISDN4Linux - subsystem you'll have to enable the capidrv glue driver. - (select ISDN_CAPI_CAPIDRV.) - Say N to build the old native ISDN4Linux variant. - If unsure, say Y. - -config GIGASET_BASE - tristate "Gigaset base station support" - depends on USB - help - Say M here if you want to use the USB interface of the Gigaset - base for connection to your system. - This will build a module called "bas_gigaset". - -config GIGASET_M105 - tristate "Gigaset M105 support" - depends on USB - help - Say M here if you want to connect to the Gigaset base via DECT - using a Gigaset M105 (Sinus 45 Data 2) USB DECT device. - This will build a module called "usb_gigaset". - -config GIGASET_M101 - tristate "Gigaset M101 support" - help - Say M here if you want to connect to the Gigaset base via DECT - using a Gigaset M101 (Sinus 45 Data 1) RS232 DECT device. - This will build a module called "ser_gigaset". - -config GIGASET_DEBUG - bool "Gigaset debugging" - help - This enables debugging code in the Gigaset drivers. - If in doubt, say yes. - -endif # ISDN_DRV_GIGASET diff --git a/drivers/staging/isdn/gigaset/Makefile b/drivers/staging/isdn/gigaset/Makefile deleted file mode 100644 index 9c010891dcd7..000000000000 --- a/drivers/staging/isdn/gigaset/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o - -ifdef CONFIG_GIGASET_CAPI -gigaset-y += capi.o -else -gigaset-y += dummyll.o -endif - -usb_gigaset-y := usb-gigaset.o -ser_gigaset-y := ser-gigaset.o -bas_gigaset-y := bas-gigaset.o isocdata.o - -obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset.o -obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o -obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o -obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o diff --git a/drivers/staging/isdn/gigaset/asyncdata.c b/drivers/staging/isdn/gigaset/asyncdata.c deleted file mode 100644 index a34b3c9d8a71..000000000000 --- a/drivers/staging/isdn/gigaset/asyncdata.c +++ /dev/null @@ -1,606 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Common data handling layer for ser_gigaset and usb_gigaset - * - * Copyright (c) 2005 by Tilman Schmidt , - * Hansjoerg Lipp , - * Stefan Eilers. - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/* check if byte must be stuffed/escaped - * I'm not sure which data should be encoded. - * Therefore I will go the hard way and encode every value - * less than 0x20, the flag sequence and the control escape char. - */ -static inline int muststuff(unsigned char c) -{ - if (c < PPP_TRANS) return 1; - if (c == PPP_FLAG) return 1; - if (c == PPP_ESCAPE) return 1; - /* other possible candidates: */ - /* 0x91: XON with parity set */ - /* 0x93: XOFF with parity set */ - return 0; -} - -/* == data input =========================================================== */ - -/* process a block of received bytes in command mode - * (mstate != MS_LOCKED && (inputstate & INS_command)) - * Append received bytes to the command response buffer and forward them - * line by line to the response handler. Exit whenever a mode/state change - * might have occurred. - * Note: Received lines may be terminated by CR, LF, or CR LF, which will be - * removed before passing the line to the response handler. - * Return value: - * number of processed bytes - */ -static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - unsigned char *src = inbuf->data + inbuf->head; - struct cardstate *cs = inbuf->cs; - unsigned cbytes = cs->cbytes; - unsigned procbytes = 0; - unsigned char c; - - while (procbytes < numbytes) { - c = *src++; - procbytes++; - - switch (c) { - case '\n': - if (cbytes == 0 && cs->respdata[0] == '\r') { - /* collapse LF with preceding CR */ - cs->respdata[0] = 0; - break; - } - /* fall through */ - case '\r': - /* end of message line, pass to response handler */ - if (cbytes >= MAX_RESP_SIZE) { - dev_warn(cs->dev, "response too large (%d)\n", - cbytes); - cbytes = MAX_RESP_SIZE; - } - cs->cbytes = cbytes; - gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", - cbytes, cs->respdata); - gigaset_handle_modem_response(cs); - cbytes = 0; - - /* store EOL byte for CRLF collapsing */ - cs->respdata[0] = c; - - /* cs->dle may have changed */ - if (cs->dle && !(inbuf->inputstate & INS_DLE_command)) - inbuf->inputstate &= ~INS_command; - - /* return for reevaluating state */ - goto exit; - - case DLE_FLAG: - if (inbuf->inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inbuf->inputstate &= ~INS_DLE_char; - } else if (cs->dle || - (inbuf->inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inbuf->inputstate |= INS_DLE_char; - goto exit; - } - /* quoted or not in DLE mode: treat as regular data */ - /* fall through */ - default: - /* append to line buffer if possible */ - if (cbytes < MAX_RESP_SIZE) - cs->respdata[cbytes] = c; - cbytes++; - } - } -exit: - cs->cbytes = cbytes; - return procbytes; -} - -/* process a block of received bytes in lock mode - * All received bytes are passed unmodified to the tty i/f. - * Return value: - * number of processed bytes - */ -static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - unsigned char *src = inbuf->data + inbuf->head; - - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); - gigaset_if_receive(inbuf->cs, src, numbytes); - return numbytes; -} - -/* process a block of received bytes in HDLC data mode - * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) - * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. - * When a frame is complete, check the FCS and pass valid frames to the LL. - * If DLE is encountered, return immediately to let the caller handle it. - * Return value: - * number of processed bytes - */ -static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = cs->bcs; - int inputstate = bcs->inputstate; - __u16 fcs = bcs->rx_fcs; - struct sk_buff *skb = bcs->rx_skb; - unsigned char *src = inbuf->data + inbuf->head; - unsigned procbytes = 0; - unsigned char c; - - if (inputstate & INS_byte_stuff) { - if (!numbytes) - return 0; - inputstate &= ~INS_byte_stuff; - goto byte_stuff; - } - - while (procbytes < numbytes) { - c = *src++; - procbytes++; - if (c == DLE_FLAG) { - if (inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inputstate &= ~INS_DLE_char; - } else if (cs->dle || (inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inputstate |= INS_DLE_char; - break; - } - } - - if (c == PPP_ESCAPE) { - /* byte stuffing indicator: pull in next byte */ - if (procbytes >= numbytes) { - /* end of buffer, save for later processing */ - inputstate |= INS_byte_stuff; - break; - } -byte_stuff: - c = *src++; - procbytes++; - if (c == DLE_FLAG) { - if (inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inputstate &= ~INS_DLE_char; - } else if (cs->dle || - (inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inputstate |= - INS_DLE_char | INS_byte_stuff; - break; - } - } - c ^= PPP_TRANS; -#ifdef CONFIG_GIGASET_DEBUG - if (!muststuff(c)) - gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); -#endif - } else if (c == PPP_FLAG) { - /* end of frame: process content if any */ - if (inputstate & INS_have_data) { - gig_dbg(DEBUG_HDLC, - "7e----------------------------"); - - /* check and pass received frame */ - if (!skb) { - /* skipped frame */ - gigaset_isdn_rcv_err(bcs); - } else if (skb->len < 2) { - /* frame too short for FCS */ - dev_warn(cs->dev, - "short frame (%d)\n", - skb->len); - gigaset_isdn_rcv_err(bcs); - dev_kfree_skb_any(skb); - } else if (fcs != PPP_GOODFCS) { - /* frame check error */ - dev_err(cs->dev, - "Checksum failed, %u bytes corrupted!\n", - skb->len); - gigaset_isdn_rcv_err(bcs); - dev_kfree_skb_any(skb); - } else { - /* good frame */ - __skb_trim(skb, skb->len - 2); - gigaset_skb_rcvd(bcs, skb); - } - - /* prepare reception of next frame */ - inputstate &= ~INS_have_data; - skb = gigaset_new_rx_skb(bcs); - } else { - /* empty frame (7E 7E) */ -#ifdef CONFIG_GIGASET_DEBUG - ++bcs->emptycount; -#endif - if (!skb) { - /* skipped (?) */ - gigaset_isdn_rcv_err(bcs); - skb = gigaset_new_rx_skb(bcs); - } - } - - fcs = PPP_INITFCS; - continue; -#ifdef CONFIG_GIGASET_DEBUG - } else if (muststuff(c)) { - /* Should not happen. Possible after ZDLE=1. */ - gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); -#endif - } - - /* regular data byte, append to skb */ -#ifdef CONFIG_GIGASET_DEBUG - if (!(inputstate & INS_have_data)) { - gig_dbg(DEBUG_HDLC, "7e (%d x) ================", - bcs->emptycount); - bcs->emptycount = 0; - } -#endif - inputstate |= INS_have_data; - if (skb) { - if (skb->len >= bcs->rx_bufsize) { - dev_warn(cs->dev, "received packet too long\n"); - dev_kfree_skb_any(skb); - /* skip remainder of packet */ - bcs->rx_skb = skb = NULL; - } else { - __skb_put_u8(skb, c); - fcs = crc_ccitt_byte(fcs, c); - } - } - } - - bcs->inputstate = inputstate; - bcs->rx_fcs = fcs; - return procbytes; -} - -/* process a block of received bytes in transparent data mode - * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC) - * Invert bytes, undoing byte stuffing and watching for DLE escapes. - * If DLE is encountered, return immediately to let the caller handle it. - * Return value: - * number of processed bytes - */ -static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - struct bc_state *bcs = cs->bcs; - int inputstate = bcs->inputstate; - struct sk_buff *skb = bcs->rx_skb; - unsigned char *src = inbuf->data + inbuf->head; - unsigned procbytes = 0; - unsigned char c; - - if (!skb) { - /* skip this block */ - gigaset_new_rx_skb(bcs); - return numbytes; - } - - while (procbytes < numbytes && skb->len < bcs->rx_bufsize) { - c = *src++; - procbytes++; - - if (c == DLE_FLAG) { - if (inputstate & INS_DLE_char) { - /* quoted DLE: clear quote flag */ - inputstate &= ~INS_DLE_char; - } else if (cs->dle || (inputstate & INS_DLE_command)) { - /* DLE escape, pass up for handling */ - inputstate |= INS_DLE_char; - break; - } - } - - /* regular data byte: append to current skb */ - inputstate |= INS_have_data; - __skb_put_u8(skb, bitrev8(c)); - } - - /* pass data up */ - if (inputstate & INS_have_data) { - gigaset_skb_rcvd(bcs, skb); - inputstate &= ~INS_have_data; - gigaset_new_rx_skb(bcs); - } - - bcs->inputstate = inputstate; - return procbytes; -} - -/* process DLE escapes - * Called whenever a DLE sequence might be encountered in the input stream. - * Either processes the entire DLE sequence or, if that isn't possible, - * notes the fact that an initial DLE has been received in the INS_DLE_char - * inputstate flag and resumes processing of the sequence on the next call. - */ -static void handle_dle(struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - - if (cs->mstate == MS_LOCKED) - return; /* no DLE processing in lock mode */ - - if (!(inbuf->inputstate & INS_DLE_char)) { - /* no DLE pending */ - if (inbuf->data[inbuf->head] == DLE_FLAG && - (cs->dle || inbuf->inputstate & INS_DLE_command)) { - /* start of DLE sequence */ - inbuf->head++; - if (inbuf->head == inbuf->tail || - inbuf->head == RBUFSIZE) { - /* end of buffer, save for later processing */ - inbuf->inputstate |= INS_DLE_char; - return; - } - } else { - /* regular data byte */ - return; - } - } - - /* consume pending DLE */ - inbuf->inputstate &= ~INS_DLE_char; - - switch (inbuf->data[inbuf->head]) { - case 'X': /* begin of event message */ - if (inbuf->inputstate & INS_command) - dev_notice(cs->dev, - "received X in command mode\n"); - inbuf->inputstate |= INS_command | INS_DLE_command; - inbuf->head++; /* byte consumed */ - break; - case '.': /* end of event message */ - if (!(inbuf->inputstate & INS_DLE_command)) - dev_notice(cs->dev, - "received . without X\n"); - inbuf->inputstate &= ~INS_DLE_command; - /* return to data mode if in DLE mode */ - if (cs->dle) - inbuf->inputstate &= ~INS_command; - inbuf->head++; /* byte consumed */ - break; - case DLE_FLAG: /* DLE in data stream */ - /* mark as quoted */ - inbuf->inputstate |= INS_DLE_char; - if (!(cs->dle || inbuf->inputstate & INS_DLE_command)) - dev_notice(cs->dev, - "received not in DLE mode\n"); - break; /* quoted byte left in buffer */ - default: - dev_notice(cs->dev, "received <%02x>\n", - inbuf->data[inbuf->head]); - /* quoted byte left in buffer */ - } -} - -/** - * gigaset_m10x_input() - process a block of data received from the device - * @inbuf: received data and device descriptor structure. - * - * Called by hardware module {ser,usb}_gigaset with a block of received - * bytes. Separates the bytes received over the serial data channel into - * user data and command replies (locked/unlocked) according to the - * current state of the interface. - */ -void gigaset_m10x_input(struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - unsigned numbytes, procbytes; - - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail); - - while (inbuf->head != inbuf->tail) { - /* check for DLE escape */ - handle_dle(inbuf); - - /* process a contiguous block of bytes */ - numbytes = (inbuf->head > inbuf->tail ? - RBUFSIZE : inbuf->tail) - inbuf->head; - gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); - /* - * numbytes may be 0 if handle_dle() ate the last byte. - * This does no harm, *_loop() will just return 0 immediately. - */ - - if (cs->mstate == MS_LOCKED) - procbytes = lock_loop(numbytes, inbuf); - else if (inbuf->inputstate & INS_command) - procbytes = cmd_loop(numbytes, inbuf); - else if (cs->bcs->proto2 == L2_HDLC) - procbytes = hdlc_loop(numbytes, inbuf); - else - procbytes = iraw_loop(numbytes, inbuf); - inbuf->head += procbytes; - - /* check for buffer wraparound */ - if (inbuf->head >= RBUFSIZE) - inbuf->head = 0; - - gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head); - } -} -EXPORT_SYMBOL_GPL(gigaset_m10x_input); - - -/* == data output ========================================================== */ - -/* - * Encode a data packet into an octet stuffed HDLC frame with FCS, - * opening and closing flags, preserving headroom data. - * parameters: - * skb skb containing original packet (freed upon return) - * Return value: - * pointer to newly allocated skb containing the result frame - * and the original link layer header, NULL on error - */ -static struct sk_buff *HDLC_Encode(struct sk_buff *skb) -{ - struct sk_buff *hdlc_skb; - __u16 fcs; - unsigned char c; - unsigned char *cp; - int len; - unsigned int stuf_cnt; - - stuf_cnt = 0; - fcs = PPP_INITFCS; - cp = skb->data; - len = skb->len; - while (len--) { - if (muststuff(*cp)) - stuf_cnt++; - fcs = crc_ccitt_byte(fcs, *cp++); - } - fcs ^= 0xffff; /* complement */ - - /* size of new buffer: original size + number of stuffing bytes - * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes - * + room for link layer header - */ - hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len); - if (!hdlc_skb) { - dev_kfree_skb_any(skb); - return NULL; - } - - /* Copy link layer header into new skb */ - skb_reset_mac_header(hdlc_skb); - skb_reserve(hdlc_skb, skb->mac_len); - memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len); - hdlc_skb->mac_len = skb->mac_len; - - /* Add flag sequence in front of everything.. */ - skb_put_u8(hdlc_skb, PPP_FLAG); - - /* Perform byte stuffing while copying data. */ - while (skb->len--) { - if (muststuff(*skb->data)) { - skb_put_u8(hdlc_skb, PPP_ESCAPE); - skb_put_u8(hdlc_skb, (*skb->data++) ^ PPP_TRANS); - } else - skb_put_u8(hdlc_skb, *skb->data++); - } - - /* Finally add FCS (byte stuffed) and flag sequence */ - c = (fcs & 0x00ff); /* least significant byte first */ - if (muststuff(c)) { - skb_put_u8(hdlc_skb, PPP_ESCAPE); - c ^= PPP_TRANS; - } - skb_put_u8(hdlc_skb, c); - - c = ((fcs >> 8) & 0x00ff); - if (muststuff(c)) { - skb_put_u8(hdlc_skb, PPP_ESCAPE); - c ^= PPP_TRANS; - } - skb_put_u8(hdlc_skb, c); - - skb_put_u8(hdlc_skb, PPP_FLAG); - - dev_kfree_skb_any(skb); - return hdlc_skb; -} - -/* - * Encode a data packet into an octet stuffed raw bit inverted frame, - * preserving headroom data. - * parameters: - * skb skb containing original packet (freed upon return) - * Return value: - * pointer to newly allocated skb containing the result frame - * and the original link layer header, NULL on error - */ -static struct sk_buff *iraw_encode(struct sk_buff *skb) -{ - struct sk_buff *iraw_skb; - unsigned char c; - unsigned char *cp; - int len; - - /* size of new buffer (worst case = every byte must be stuffed): - * 2 * original size + room for link layer header - */ - iraw_skb = dev_alloc_skb(2 * skb->len + skb->mac_len); - if (!iraw_skb) { - dev_kfree_skb_any(skb); - return NULL; - } - - /* copy link layer header into new skb */ - skb_reset_mac_header(iraw_skb); - skb_reserve(iraw_skb, skb->mac_len); - memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len); - iraw_skb->mac_len = skb->mac_len; - - /* copy and stuff data */ - cp = skb->data; - len = skb->len; - while (len--) { - c = bitrev8(*cp++); - if (c == DLE_FLAG) - skb_put_u8(iraw_skb, c); - skb_put_u8(iraw_skb, c); - } - dev_kfree_skb_any(skb); - return iraw_skb; -} - -/** - * gigaset_m10x_send_skb() - queue an skb for sending - * @bcs: B channel descriptor structure. - * @skb: data to send. - * - * Called by LL to encode and queue an skb for sending, and start - * transmission if necessary. - * Once the payload data has been transmitted completely, gigaset_skb_sent() - * will be called with the skb's link layer header preserved. - * - * Return value: - * number of bytes accepted for sending (skb->len) if ok, - * error code < 0 (eg. -ENOMEM) on error - */ -int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) -{ - struct cardstate *cs = bcs->cs; - unsigned len = skb->len; - unsigned long flags; - - if (bcs->proto2 == L2_HDLC) - skb = HDLC_Encode(skb); - else - skb = iraw_encode(skb); - if (!skb) { - dev_err(cs->dev, - "unable to allocate memory for encoding!\n"); - return -ENOMEM; - } - - skb_queue_tail(&bcs->squeue, skb); - spin_lock_irqsave(&cs->lock, flags); - if (cs->connected) - tasklet_schedule(&cs->write_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); - - return len; /* ok so far */ -} -EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb); diff --git a/drivers/staging/isdn/gigaset/bas-gigaset.c b/drivers/staging/isdn/gigaset/bas-gigaset.c deleted file mode 100644 index c334525a5f63..000000000000 --- a/drivers/staging/isdn/gigaset/bas-gigaset.c +++ /dev/null @@ -1,2672 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * USB driver for Gigaset 307x base via direct USB connection. - * - * Copyright (c) 2001 by Hansjoerg Lipp , - * Tilman Schmidt , - * Stefan Eilers. - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Tilman Schmidt , Hansjoerg Lipp , Stefan Eilers" -#define DRIVER_DESC "USB Driver for Gigaset 307x" - - -/* Module parameters */ - -static int startmode = SM_ISDN; -static int cidmode = 1; - -module_param(startmode, int, S_IRUGO); -module_param(cidmode, int, S_IRUGO); -MODULE_PARM_DESC(startmode, "start in isdn4linux mode"); -MODULE_PARM_DESC(cidmode, "Call-ID mode"); - -#define GIGASET_MINORS 1 -#define GIGASET_MINOR 16 -#define GIGASET_MODULENAME "bas_gigaset" -#define GIGASET_DEVNAME "ttyGB" - -/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ -#define IF_WRITEBUF 264 - -/* interrupt pipe message size according to ibid. ch. 2.2 */ -#define IP_MSGSIZE 3 - -/* Values for the Gigaset 307x */ -#define USB_GIGA_VENDOR_ID 0x0681 -#define USB_3070_PRODUCT_ID 0x0001 -#define USB_3075_PRODUCT_ID 0x0002 -#define USB_SX303_PRODUCT_ID 0x0021 -#define USB_SX353_PRODUCT_ID 0x0022 - -/* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table[] = { - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, - { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX353_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, gigaset_table); - -/*======================= local function prototypes ==========================*/ - -/* function called if a new device belonging to this driver is connected */ -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); - -/* Function will be called if the device is unplugged */ -static void gigaset_disconnect(struct usb_interface *interface); - -/* functions called before/after suspend */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); -static int gigaset_resume(struct usb_interface *intf); - -/* functions called before/after device reset */ -static int gigaset_pre_reset(struct usb_interface *intf); -static int gigaset_post_reset(struct usb_interface *intf); - -static int atread_submit(struct cardstate *, int); -static void stopurbs(struct bas_bc_state *); -static int req_submit(struct bc_state *, int, int, int); -static int atwrite_submit(struct cardstate *, unsigned char *, int); -static int start_cbsend(struct cardstate *); - -/*============================================================================*/ - -struct bas_cardstate { - struct usb_device *udev; /* USB device pointer */ - struct cardstate *cs; - struct usb_interface *interface; /* interface for this device */ - unsigned char minor; /* starting minor number */ - - struct urb *urb_ctrl; /* control pipe default URB */ - struct usb_ctrlrequest dr_ctrl; - struct timer_list timer_ctrl; /* control request timeout */ - int retry_ctrl; - - struct timer_list timer_atrdy; /* AT command ready timeout */ - struct urb *urb_cmd_out; /* for sending AT commands */ - struct usb_ctrlrequest dr_cmd_out; - int retry_cmd_out; - - struct urb *urb_cmd_in; /* for receiving AT replies */ - struct usb_ctrlrequest dr_cmd_in; - struct timer_list timer_cmd_in; /* receive request timeout */ - unsigned char *rcvbuf; /* AT reply receive buffer */ - - struct urb *urb_int_in; /* URB for interrupt pipe */ - unsigned char *int_in_buf; - struct work_struct int_in_wq; /* for usb_clear_halt() */ - struct timer_list timer_int_in; /* int read retry delay */ - int retry_int_in; - - spinlock_t lock; /* locks all following */ - int basstate; /* bitmap (BS_*) */ - int pending; /* uncompleted base request */ - wait_queue_head_t waitqueue; - int rcvbuf_size; /* size of AT receive buffer */ - /* 0: no receive in progress */ - int retry_cmd_in; /* receive req retry count */ -}; - -/* status of direct USB connection to 307x base (bits in basstate) */ -#define BS_ATOPEN 0x001 /* AT channel open */ -#define BS_B1OPEN 0x002 /* B channel 1 open */ -#define BS_B2OPEN 0x004 /* B channel 2 open */ -#define BS_ATREADY 0x008 /* base ready for AT command */ -#define BS_INIT 0x010 /* base has signalled INIT_OK */ -#define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ -#define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ -#define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ -#define BS_SUSPEND 0x100 /* USB port suspended */ -#define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ - - -static struct gigaset_driver *driver; - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, - .suspend = gigaset_suspend, - .resume = gigaset_resume, - .reset_resume = gigaset_post_reset, - .pre_reset = gigaset_pre_reset, - .post_reset = gigaset_post_reset, - .disable_hub_initiated_lpm = 1, -}; - -/* get message text for usb_submit_urb return code - */ -static char *get_usb_rcmsg(int rc) -{ - static char unkmsg[28]; - - switch (rc) { - case 0: - return "success"; - case -ENOMEM: - return "out of memory"; - case -ENODEV: - return "device not present"; - case -ENOENT: - return "endpoint not present"; - case -ENXIO: - return "URB type not supported"; - case -EINVAL: - return "invalid argument"; - case -EAGAIN: - return "start frame too early or too much scheduled"; - case -EFBIG: - return "too many isoc frames requested"; - case -EPIPE: - return "endpoint stalled"; - case -EMSGSIZE: - return "invalid packet size"; - case -ENOSPC: - return "would overcommit USB bandwidth"; - case -ESHUTDOWN: - return "device shut down"; - case -EPERM: - return "reject flag set"; - case -EHOSTUNREACH: - return "device suspended"; - default: - snprintf(unkmsg, sizeof(unkmsg), "unknown error %d", rc); - return unkmsg; - } -} - -/* get message text for USB status code - */ -static char *get_usb_statmsg(int status) -{ - static char unkmsg[28]; - - switch (status) { - case 0: - return "success"; - case -ENOENT: - return "unlinked (sync)"; - case -EINPROGRESS: - return "URB still pending"; - case -EPROTO: - return "bitstuff error, timeout, or unknown USB error"; - case -EILSEQ: - return "CRC mismatch, timeout, or unknown USB error"; - case -ETIME: - return "USB response timeout"; - case -EPIPE: - return "endpoint stalled"; - case -ECOMM: - return "IN buffer overrun"; - case -ENOSR: - return "OUT buffer underrun"; - case -EOVERFLOW: - return "endpoint babble"; - case -EREMOTEIO: - return "short packet"; - case -ENODEV: - return "device removed"; - case -EXDEV: - return "partial isoc transfer"; - case -EINVAL: - return "ISO madness"; - case -ECONNRESET: - return "unlinked (async)"; - case -ESHUTDOWN: - return "device shut down"; - default: - snprintf(unkmsg, sizeof(unkmsg), "unknown status %d", status); - return unkmsg; - } -} - -/* usb_pipetype_str - * retrieve string representation of USB pipe type - */ -static inline char *usb_pipetype_str(int pipe) -{ - if (usb_pipeisoc(pipe)) - return "Isoc"; - if (usb_pipeint(pipe)) - return "Int"; - if (usb_pipecontrol(pipe)) - return "Ctrl"; - if (usb_pipebulk(pipe)) - return "Bulk"; - return "?"; -} - -/* dump_urb - * write content of URB to syslog for debugging - */ -static inline void dump_urb(enum debuglevel level, const char *tag, - struct urb *urb) -{ -#ifdef CONFIG_GIGASET_DEBUG - int i; - gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); - if (urb) { - gig_dbg(level, - " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " - "hcpriv=0x%08lx, transfer_flags=0x%x,", - (unsigned long) urb->dev, - usb_pipetype_str(urb->pipe), - usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - (unsigned long) urb->hcpriv, - urb->transfer_flags); - gig_dbg(level, - " transfer_buffer=0x%08lx[%d], actual_length=%d, " - "setup_packet=0x%08lx,", - (unsigned long) urb->transfer_buffer, - urb->transfer_buffer_length, urb->actual_length, - (unsigned long) urb->setup_packet); - gig_dbg(level, - " start_frame=%d, number_of_packets=%d, interval=%d, " - "error_count=%d,", - urb->start_frame, urb->number_of_packets, urb->interval, - urb->error_count); - gig_dbg(level, - " context=0x%08lx, complete=0x%08lx, " - "iso_frame_desc[]={", - (unsigned long) urb->context, - (unsigned long) urb->complete); - for (i = 0; i < urb->number_of_packets; i++) { - struct usb_iso_packet_descriptor *pifd - = &urb->iso_frame_desc[i]; - gig_dbg(level, - " {offset=%u, length=%u, actual_length=%u, " - "status=%u}", - pifd->offset, pifd->length, pifd->actual_length, - pifd->status); - } - } - gig_dbg(level, "}}"); -#endif -} - -/* read/set modem control bits etc. (m10x only) */ -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - return -EINVAL; -} - -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -/* set/clear bits in base connection state, return previous state - */ -static inline int update_basstate(struct bas_cardstate *ucs, - int set, int clear) -{ - unsigned long flags; - int state; - - spin_lock_irqsave(&ucs->lock, flags); - state = ucs->basstate; - ucs->basstate = (state & ~clear) | set; - spin_unlock_irqrestore(&ucs->lock, flags); - return state; -} - -/* error_hangup - * hang up any existing connection because of an unrecoverable error - * This function may be called from any context and takes care of scheduling - * the necessary actions for execution outside of interrupt context. - * cs->lock must not be held. - * argument: - * B channel control structure - */ -static inline void error_hangup(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - - gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL); - gigaset_schedule_event(cs); -} - -/* error_reset - * reset Gigaset device because of an unrecoverable error - * This function may be called from any context, and takes care of - * scheduling the necessary actions for execution outside of interrupt context. - * cs->hw.bas->lock must not be held. - * argument: - * controller state structure - */ -static inline void error_reset(struct cardstate *cs) -{ - /* reset interrupt pipe to recover (ignore errors) */ - update_basstate(cs->hw.bas, BS_RESETTING, 0); - if (req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT)) - /* submission failed, escalate to USB port reset */ - usb_queue_reset_device(cs->hw.bas->interface); -} - -/* check_pending - * check for completion of pending control request - * parameter: - * ucs hardware specific controller state structure - */ -static void check_pending(struct bas_cardstate *ucs) -{ - unsigned long flags; - - spin_lock_irqsave(&ucs->lock, flags); - switch (ucs->pending) { - case 0: - break; - case HD_OPEN_ATCHANNEL: - if (ucs->basstate & BS_ATOPEN) - ucs->pending = 0; - break; - case HD_OPEN_B1CHANNEL: - if (ucs->basstate & BS_B1OPEN) - ucs->pending = 0; - break; - case HD_OPEN_B2CHANNEL: - if (ucs->basstate & BS_B2OPEN) - ucs->pending = 0; - break; - case HD_CLOSE_ATCHANNEL: - if (!(ucs->basstate & BS_ATOPEN)) - ucs->pending = 0; - break; - case HD_CLOSE_B1CHANNEL: - if (!(ucs->basstate & BS_B1OPEN)) - ucs->pending = 0; - break; - case HD_CLOSE_B2CHANNEL: - if (!(ucs->basstate & BS_B2OPEN)) - ucs->pending = 0; - break; - case HD_DEVICE_INIT_ACK: /* no reply expected */ - ucs->pending = 0; - break; - case HD_RESET_INTERRUPT_PIPE: - if (!(ucs->basstate & BS_RESETTING)) - ucs->pending = 0; - break; - /* - * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately - * and should never end up here - */ - default: - dev_warn(&ucs->interface->dev, - "unknown pending request 0x%02x cleared\n", - ucs->pending); - ucs->pending = 0; - } - - if (!ucs->pending) - del_timer(&ucs->timer_ctrl); - - spin_unlock_irqrestore(&ucs->lock, flags); -} - -/* cmd_in_timeout - * timeout routine for command input request - * argument: - * controller state structure - */ -static void cmd_in_timeout(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_cmd_in); - struct cardstate *cs = ucs->cs; - int rc; - - if (!ucs->rcvbuf_size) { - gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); - return; - } - - if (ucs->retry_cmd_in++ >= BAS_RETRY) { - dev_err(cs->dev, - "control read: timeout, giving up after %d tries\n", - ucs->retry_cmd_in); - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - error_reset(cs); - return; - } - - gig_dbg(DEBUG_USBREQ, "%s: timeout, retry %d", - __func__, ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc < 0) { - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - if (rc != -ENODEV) - error_reset(cs); - } -} - -/* read_ctrl_callback - * USB completion handler for control pipe input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block - * urb->context = inbuf structure for controller state - */ -static void read_ctrl_callback(struct urb *urb) -{ - struct inbuf_t *inbuf = urb->context; - struct cardstate *cs = inbuf->cs; - struct bas_cardstate *ucs = cs->hw.bas; - int status = urb->status; - unsigned numbytes; - int rc; - - update_basstate(ucs, 0, BS_ATRDPEND); - wake_up(&ucs->waitqueue); - del_timer(&ucs->timer_cmd_in); - - switch (status) { - case 0: /* normal completion */ - numbytes = urb->actual_length; - if (unlikely(numbytes != ucs->rcvbuf_size)) { - dev_warn(cs->dev, - "control read: received %d chars, expected %d\n", - numbytes, ucs->rcvbuf_size); - if (numbytes > ucs->rcvbuf_size) - numbytes = ucs->rcvbuf_size; - } - - /* copy received bytes to inbuf, notify event layer */ - if (gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes)) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - } - break; - - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* no further action necessary */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - break; - - default: /* other errors: retry */ - if (ucs->retry_cmd_in++ < BAS_RETRY) { - gig_dbg(DEBUG_USBREQ, "%s: %s, retry %d", __func__, - get_usb_statmsg(status), ucs->retry_cmd_in); - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc >= 0) - /* successfully resubmitted, skip freeing */ - return; - if (rc == -ENODEV) - /* disconnect, no further action necessary */ - break; - } - dev_err(cs->dev, "control read: %s, giving up after %d tries\n", - get_usb_statmsg(status), ucs->retry_cmd_in); - error_reset(cs); - } - - /* read finished, free buffer */ - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; -} - -/* atread_submit - * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout - * parameters: - * cs controller state structure - * timeout timeout in 1/10 sec., 0: none - * return value: - * 0 on success - * -EBUSY if another request is pending - * any URB submission error code - */ -static int atread_submit(struct cardstate *cs, int timeout) -{ - struct bas_cardstate *ucs = cs->hw.bas; - int basstate; - int ret; - - gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", - ucs->rcvbuf_size); - - basstate = update_basstate(ucs, BS_ATRDPEND, 0); - if (basstate & BS_ATRDPEND) { - dev_err(cs->dev, - "could not submit HD_READ_ATMESSAGE: URB busy\n"); - return -EBUSY; - } - - if (basstate & BS_SUSPEND) { - dev_notice(cs->dev, - "HD_READ_ATMESSAGE not submitted, " - "suspend in progress\n"); - update_basstate(ucs, 0, BS_ATRDPEND); - /* treat like disconnect */ - return -ENODEV; - } - - ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; - ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; - ucs->dr_cmd_in.wValue = 0; - ucs->dr_cmd_in.wIndex = 0; - ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); - usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, - usb_rcvctrlpipe(ucs->udev, 0), - (unsigned char *) &ucs->dr_cmd_in, - ucs->rcvbuf, ucs->rcvbuf_size, - read_ctrl_callback, cs->inbuf); - - ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC); - if (ret != 0) { - update_basstate(ucs, 0, BS_ATRDPEND); - dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", - get_usb_rcmsg(ret)); - return ret; - } - - if (timeout > 0) { - gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); - mod_timer(&ucs->timer_cmd_in, jiffies + timeout * HZ / 10); - } - return 0; -} - -/* int_in_work - * workqueue routine to clear halt on interrupt in endpoint - */ - -static void int_in_work(struct work_struct *work) -{ - struct bas_cardstate *ucs = - container_of(work, struct bas_cardstate, int_in_wq); - struct urb *urb = ucs->urb_int_in; - struct cardstate *cs = urb->context; - int rc; - - /* clear halt condition */ - rc = usb_clear_halt(ucs->udev, urb->pipe); - gig_dbg(DEBUG_USBREQ, "clear_halt: %s", get_usb_rcmsg(rc)); - if (rc == 0) - /* success, resubmit interrupt read URB */ - rc = usb_submit_urb(urb, GFP_ATOMIC); - - switch (rc) { - case 0: /* success */ - case -ENODEV: /* device gone */ - case -EINVAL: /* URB already resubmitted, or terminal badness */ - break; - default: /* failure: try to recover by resetting the device */ - dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); - rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); - if (rc == 0) { - rc = usb_reset_device(ucs->udev); - usb_unlock_device(ucs->udev); - } - } - ucs->retry_int_in = 0; -} - -/* int_in_resubmit - * timer routine for interrupt read delayed resubmit - * argument: - * controller state structure - */ -static void int_in_resubmit(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_int_in); - struct cardstate *cs = ucs->cs; - int rc; - - if (ucs->retry_int_in++ >= BAS_RETRY) { - dev_err(cs->dev, "interrupt read: giving up after %d tries\n", - ucs->retry_int_in); - usb_queue_reset_device(ucs->interface); - return; - } - - gig_dbg(DEBUG_USBREQ, "%s: retry %d", __func__, ucs->retry_int_in); - rc = usb_submit_urb(ucs->urb_int_in, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { - dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - usb_queue_reset_device(ucs->interface); - } -} - -/* read_int_callback - * USB completion handler for interrupt pipe input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block - * urb->context = controller state structure - */ -static void read_int_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - struct bas_cardstate *ucs = cs->hw.bas; - struct bc_state *bcs; - int status = urb->status; - unsigned long flags; - int rc; - unsigned l; - int channel; - - switch (status) { - case 0: /* success */ - ucs->retry_int_in = 0; - break; - case -EPIPE: /* endpoint stalled */ - schedule_work(&ucs->int_in_wq); - /* fall through */ - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* no further action necessary */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - case -EPROTO: /* protocol error or unplug */ - case -EILSEQ: - case -ETIME: - /* resubmit after delay */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - mod_timer(&ucs->timer_int_in, jiffies + HZ / 10); - return; - default: /* other errors: just resubmit */ - dev_warn(cs->dev, "interrupt read: %s\n", - get_usb_statmsg(status)); - goto resubmit; - } - - /* drop incomplete packets even if the missing bytes wouldn't matter */ - if (unlikely(urb->actual_length < IP_MSGSIZE)) { - dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", - urb->actual_length); - goto resubmit; - } - - l = (unsigned) ucs->int_in_buf[1] + - (((unsigned) ucs->int_in_buf[2]) << 8); - - gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", - urb->actual_length, (int)ucs->int_in_buf[0], l, - (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); - - channel = 0; - - switch (ucs->int_in_buf[0]) { - case HD_DEVICE_INIT_OK: - update_basstate(ucs, BS_INIT, 0); - break; - - case HD_READY_SEND_ATDATA: - del_timer(&ucs->timer_atrdy); - update_basstate(ucs, BS_ATREADY, BS_ATTIMER); - start_cbsend(cs); - break; - - case HD_OPEN_B2CHANNEL_ACK: - ++channel; - /* fall through */ - case HD_OPEN_B1CHANNEL_ACK: - bcs = cs->bcs + channel; - update_basstate(ucs, BS_B1OPEN << channel, 0); - gigaset_bchannel_up(bcs); - break; - - case HD_OPEN_ATCHANNEL_ACK: - update_basstate(ucs, BS_ATOPEN, 0); - start_cbsend(cs); - break; - - case HD_CLOSE_B2CHANNEL_ACK: - ++channel; - /* fall through */ - case HD_CLOSE_B1CHANNEL_ACK: - bcs = cs->bcs + channel; - update_basstate(ucs, 0, BS_B1OPEN << channel); - stopurbs(bcs->hw.bas); - gigaset_bchannel_down(bcs); - break; - - case HD_CLOSE_ATCHANNEL_ACK: - update_basstate(ucs, 0, BS_ATOPEN); - break; - - case HD_B2_FLOW_CONTROL: - ++channel; - /* fall through */ - case HD_B1_FLOW_CONTROL: - bcs = cs->bcs + channel; - atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES, - &bcs->hw.bas->corrbytes); - gig_dbg(DEBUG_ISO, - "Flow control (channel %d, sub %d): 0x%02x => %d", - channel, bcs->hw.bas->numsub, l, - atomic_read(&bcs->hw.bas->corrbytes)); - break; - - case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */ - if (!l) { - dev_warn(cs->dev, - "HD_RECEIVEATDATA_ACK with length 0 ignored\n"); - break; - } - spin_lock_irqsave(&cs->lock, flags); - if (ucs->basstate & BS_ATRDPEND) { - spin_unlock_irqrestore(&cs->lock, flags); - dev_warn(cs->dev, - "HD_RECEIVEATDATA_ACK(%d) during HD_READ_ATMESSAGE(%d) ignored\n", - l, ucs->rcvbuf_size); - break; - } - if (ucs->rcvbuf_size) { - /* throw away previous buffer - we have no queue */ - dev_err(cs->dev, - "receive AT data overrun, %d bytes lost\n", - ucs->rcvbuf_size); - kfree(ucs->rcvbuf); - ucs->rcvbuf_size = 0; - } - ucs->rcvbuf = kmalloc(l, GFP_ATOMIC); - if (ucs->rcvbuf == NULL) { - spin_unlock_irqrestore(&cs->lock, flags); - dev_err(cs->dev, "out of memory receiving AT data\n"); - break; - } - ucs->rcvbuf_size = l; - ucs->retry_cmd_in = 0; - rc = atread_submit(cs, BAS_TIMEOUT); - if (rc < 0) { - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - } - spin_unlock_irqrestore(&cs->lock, flags); - if (rc < 0 && rc != -ENODEV) - error_reset(cs); - break; - - case HD_RESET_INTERRUPT_PIPE_ACK: - update_basstate(ucs, 0, BS_RESETTING); - dev_notice(cs->dev, "interrupt pipe reset\n"); - break; - - case HD_SUSPEND_END: - gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); - break; - - default: - dev_warn(cs->dev, - "unknown Gigaset signal 0x%02x (%u) ignored\n", - (int) ucs->int_in_buf[0], l); - } - - check_pending(ucs); - wake_up(&ucs->waitqueue); - -resubmit: - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc != 0 && rc != -ENODEV)) { - dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - error_reset(cs); - } -} - -/* read_iso_callback - * USB completion handler for B channel isochronous input - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = bc_state structure - */ -static void read_iso_callback(struct urb *urb) -{ - struct bc_state *bcs; - struct bas_bc_state *ubc; - int status = urb->status; - unsigned long flags; - int i, rc; - - /* status codes not worth bothering the tasklet with */ - if (unlikely(status == -ENOENT || - status == -ECONNRESET || - status == -EINPROGRESS || - status == -ENODEV || - status == -ESHUTDOWN)) { - gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - } - - bcs = urb->context; - ubc = bcs->hw.bas; - - spin_lock_irqsave(&ubc->isoinlock, flags); - if (likely(ubc->isoindone == NULL)) { - /* pass URB to tasklet */ - ubc->isoindone = urb; - ubc->isoinstatus = status; - tasklet_hi_schedule(&ubc->rcvd_tasklet); - } else { - /* tasklet still busy, drop data and resubmit URB */ - gig_dbg(DEBUG_ISO, "%s: overrun", __func__); - ubc->loststatus = status; - for (i = 0; i < BAS_NUMFRAMES; i++) { - ubc->isoinlost += urb->iso_frame_desc[i].actual_length; - if (unlikely(urb->iso_frame_desc[i].status != 0 && - urb->iso_frame_desc[i].status != -EINPROGRESS)) - ubc->loststatus = urb->iso_frame_desc[i].status; - urb->iso_frame_desc[i].status = 0; - urb->iso_frame_desc[i].actual_length = 0; - } - if (likely(ubc->running)) { - /* urb->dev is clobbered by USB subsystem */ - urb->dev = bcs->cs->hw.bas->udev; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc != 0 && rc != -ENODEV)) { - dev_err(bcs->cs->dev, - "could not resubmit isoc read URB: %s\n", - get_usb_rcmsg(rc)); - dump_urb(DEBUG_ISO, "isoc read", urb); - error_hangup(bcs); - } - } - } - spin_unlock_irqrestore(&ubc->isoinlock, flags); -} - -/* write_iso_callback - * USB completion handler for B channel isochronous output - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = isow_urbctx_t structure - */ -static void write_iso_callback(struct urb *urb) -{ - struct isow_urbctx_t *ucx; - struct bas_bc_state *ubc; - int status = urb->status; - unsigned long flags; - - /* status codes not worth bothering the tasklet with */ - if (unlikely(status == -ENOENT || - status == -ECONNRESET || - status == -EINPROGRESS || - status == -ENODEV || - status == -ESHUTDOWN)) { - gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - } - - /* pass URB context to tasklet */ - ucx = urb->context; - ubc = ucx->bcs->hw.bas; - ucx->status = status; - - spin_lock_irqsave(&ubc->isooutlock, flags); - ubc->isooutovfl = ubc->isooutdone; - ubc->isooutdone = ucx; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - tasklet_hi_schedule(&ubc->sent_tasklet); -} - -/* starturbs - * prepare and submit USB request blocks for isochronous input and output - * argument: - * B channel control structure - * return value: - * 0 on success - * < 0 on error (no URBs submitted) - */ -static int starturbs(struct bc_state *bcs) -{ - struct usb_device *udev = bcs->cs->hw.bas->udev; - struct bas_bc_state *ubc = bcs->hw.bas; - struct urb *urb; - int j, k; - int rc; - - /* initialize L2 reception */ - if (bcs->proto2 == L2_HDLC) - bcs->inputstate |= INS_flag_hunt; - - /* submit all isochronous input URBs */ - ubc->running = 1; - for (k = 0; k < BAS_INURBS; k++) { - urb = ubc->isoinurbs[k]; - if (!urb) { - rc = -EFAULT; - goto error; - } - usb_fill_int_urb(urb, udev, - usb_rcvisocpipe(udev, 3 + 2 * bcs->channel), - ubc->isoinbuf + k * BAS_INBUFSIZE, - BAS_INBUFSIZE, read_iso_callback, bcs, - BAS_FRAMETIME); - - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - for (j = 0; j < BAS_NUMFRAMES; j++) { - urb->iso_frame_desc[j].offset = j * BAS_MAXFRAME; - urb->iso_frame_desc[j].length = BAS_MAXFRAME; - urb->iso_frame_desc[j].status = 0; - urb->iso_frame_desc[j].actual_length = 0; - } - - dump_urb(DEBUG_ISO, "Initial isoc read", urb); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0) - goto error; - } - - /* initialize L2 transmission */ - gigaset_isowbuf_init(ubc->isooutbuf, PPP_FLAG); - - /* set up isochronous output URBs for flag idling */ - for (k = 0; k < BAS_OUTURBS; ++k) { - urb = ubc->isoouturbs[k].urb; - if (!urb) { - rc = -EFAULT; - goto error; - } - usb_fill_int_urb(urb, udev, - usb_sndisocpipe(udev, 4 + 2 * bcs->channel), - ubc->isooutbuf->data, - sizeof(ubc->isooutbuf->data), - write_iso_callback, &ubc->isoouturbs[k], - BAS_FRAMETIME); - - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - for (j = 0; j < BAS_NUMFRAMES; ++j) { - urb->iso_frame_desc[j].offset = BAS_OUTBUFSIZE; - urb->iso_frame_desc[j].length = BAS_NORMFRAME; - urb->iso_frame_desc[j].status = 0; - urb->iso_frame_desc[j].actual_length = 0; - } - ubc->isoouturbs[k].limit = -1; - } - - /* keep one URB free, submit the others */ - for (k = 0; k < BAS_OUTURBS - 1; ++k) { - dump_urb(DEBUG_ISO, "Initial isoc write", urb); - rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); - if (rc != 0) - goto error; - } - dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); - ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS - 1]; - ubc->isooutdone = ubc->isooutovfl = NULL; - return 0; -error: - stopurbs(ubc); - return rc; -} - -/* stopurbs - * cancel the USB request blocks for isochronous input and output - * errors are silently ignored - * argument: - * B channel control structure - */ -static void stopurbs(struct bas_bc_state *ubc) -{ - int k, rc; - - ubc->running = 0; - - for (k = 0; k < BAS_INURBS; ++k) { - rc = usb_unlink_urb(ubc->isoinurbs[k]); - gig_dbg(DEBUG_ISO, - "%s: isoc input URB %d unlinked, result = %s", - __func__, k, get_usb_rcmsg(rc)); - } - - for (k = 0; k < BAS_OUTURBS; ++k) { - rc = usb_unlink_urb(ubc->isoouturbs[k].urb); - gig_dbg(DEBUG_ISO, - "%s: isoc output URB %d unlinked, result = %s", - __func__, k, get_usb_rcmsg(rc)); - } -} - -/* Isochronous Write - Bottom Half */ -/* =============================== */ - -/* submit_iso_write_urb - * fill and submit the next isochronous write URB - * parameters: - * ucx context structure containing URB - * return value: - * number of frames submitted in URB - * 0 if URB not submitted because no data available (isooutbuf busy) - * error code < 0 on error - */ -static int submit_iso_write_urb(struct isow_urbctx_t *ucx) -{ - struct urb *urb = ucx->urb; - struct bas_bc_state *ubc = ucx->bcs->hw.bas; - struct usb_iso_packet_descriptor *ifd; - int corrbytes, nframe, rc; - - /* urb->dev is clobbered by USB subsystem */ - urb->dev = ucx->bcs->cs->hw.bas->udev; - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = ubc->isooutbuf->data; - urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data); - - for (nframe = 0; nframe < BAS_NUMFRAMES; nframe++) { - ifd = &urb->iso_frame_desc[nframe]; - - /* compute frame length according to flow control */ - ifd->length = BAS_NORMFRAME; - corrbytes = atomic_read(&ubc->corrbytes); - if (corrbytes != 0) { - gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", - __func__, corrbytes); - if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) - corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME; - else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME) - corrbytes = BAS_LOWFRAME - BAS_NORMFRAME; - ifd->length += corrbytes; - atomic_add(-corrbytes, &ubc->corrbytes); - } - - /* retrieve block of data to send */ - rc = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length); - if (rc < 0) { - if (rc == -EBUSY) { - gig_dbg(DEBUG_ISO, - "%s: buffer busy at frame %d", - __func__, nframe); - /* tasklet will be restarted from - gigaset_isoc_send_skb() */ - } else { - dev_err(ucx->bcs->cs->dev, - "%s: buffer error %d at frame %d\n", - __func__, rc, nframe); - return rc; - } - break; - } - ifd->offset = rc; - ucx->limit = ubc->isooutbuf->nextread; - ifd->status = 0; - ifd->actual_length = 0; - } - if (unlikely(nframe == 0)) - return 0; /* no data to send */ - urb->number_of_packets = nframe; - - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc)) { - if (rc == -ENODEV) - /* device removed - give up silently */ - gig_dbg(DEBUG_ISO, "%s: disconnected", __func__); - else - dev_err(ucx->bcs->cs->dev, - "could not submit isoc write URB: %s\n", - get_usb_rcmsg(rc)); - return rc; - } - ++ubc->numsub; - return nframe; -} - -/* write_iso_tasklet - * tasklet scheduled when an isochronous output URB from the Gigaset device - * has completed - * parameter: - * data B channel state structure - */ -static void write_iso_tasklet(unsigned long data) -{ - struct bc_state *bcs = (struct bc_state *) data; - struct bas_bc_state *ubc = bcs->hw.bas; - struct cardstate *cs = bcs->cs; - struct isow_urbctx_t *done, *next, *ovfl; - struct urb *urb; - int status; - struct usb_iso_packet_descriptor *ifd; - unsigned long flags; - int i; - struct sk_buff *skb; - int len; - int rc; - - /* loop while completed URBs arrive in time */ - for (;;) { - if (unlikely(!(ubc->running))) { - gig_dbg(DEBUG_ISO, "%s: not running", __func__); - return; - } - - /* retrieve completed URBs */ - spin_lock_irqsave(&ubc->isooutlock, flags); - done = ubc->isooutdone; - ubc->isooutdone = NULL; - ovfl = ubc->isooutovfl; - ubc->isooutovfl = NULL; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (ovfl) { - dev_err(cs->dev, "isoc write underrun\n"); - error_hangup(bcs); - break; - } - if (!done) - break; - - /* submit free URB if available */ - spin_lock_irqsave(&ubc->isooutlock, flags); - next = ubc->isooutfree; - ubc->isooutfree = NULL; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (next) { - rc = submit_iso_write_urb(next); - if (unlikely(rc <= 0 && rc != -ENODEV)) { - /* could not submit URB, put it back */ - spin_lock_irqsave(&ubc->isooutlock, flags); - if (ubc->isooutfree == NULL) { - ubc->isooutfree = next; - next = NULL; - } - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (next) { - /* couldn't put it back */ - dev_err(cs->dev, - "losing isoc write URB\n"); - error_hangup(bcs); - } - } - } - - /* process completed URB */ - urb = done->urb; - status = done->status; - switch (status) { - case -EXDEV: /* partial completion */ - gig_dbg(DEBUG_ISO, "%s: URB partially completed", - __func__); - /* fall through - what's the difference anyway? */ - case 0: /* normal completion */ - /* inspect individual frames - * assumptions (for lack of documentation): - * - actual_length bytes of first frame in error are - * successfully sent - * - all following frames are not sent at all - */ - for (i = 0; i < BAS_NUMFRAMES; i++) { - ifd = &urb->iso_frame_desc[i]; - if (ifd->status || - ifd->actual_length != ifd->length) { - dev_warn(cs->dev, - "isoc write: frame %d[%d/%d]: %s\n", - i, ifd->actual_length, - ifd->length, - get_usb_statmsg(ifd->status)); - break; - } - } - break; - case -EPIPE: /* stall - probably underrun */ - dev_err(cs->dev, "isoc write: stalled\n"); - error_hangup(bcs); - break; - default: /* other errors */ - dev_warn(cs->dev, "isoc write: %s\n", - get_usb_statmsg(status)); - } - - /* mark the write buffer area covered by this URB as free */ - if (done->limit >= 0) - ubc->isooutbuf->read = done->limit; - - /* mark URB as free */ - spin_lock_irqsave(&ubc->isooutlock, flags); - next = ubc->isooutfree; - ubc->isooutfree = done; - spin_unlock_irqrestore(&ubc->isooutlock, flags); - if (next) { - /* only one URB still active - resubmit one */ - rc = submit_iso_write_urb(next); - if (unlikely(rc <= 0 && rc != -ENODEV)) { - /* couldn't submit */ - error_hangup(bcs); - } - } - } - - /* process queued SKBs */ - while ((skb = skb_dequeue(&bcs->squeue))) { - /* copy to output buffer, doing L2 encapsulation */ - len = skb->len; - if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) { - /* insufficient buffer space, push back onto queue */ - skb_queue_head(&bcs->squeue, skb); - gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", - __func__, skb_queue_len(&bcs->squeue)); - break; - } - skb_pull(skb, len); - gigaset_skb_sent(bcs, skb); - dev_kfree_skb_any(skb); - } -} - -/* Isochronous Read - Bottom Half */ -/* ============================== */ - -/* read_iso_tasklet - * tasklet scheduled when an isochronous input URB from the Gigaset device - * has completed - * parameter: - * data B channel state structure - */ -static void read_iso_tasklet(unsigned long data) -{ - struct bc_state *bcs = (struct bc_state *) data; - struct bas_bc_state *ubc = bcs->hw.bas; - struct cardstate *cs = bcs->cs; - struct urb *urb; - int status; - struct usb_iso_packet_descriptor *ifd; - char *rcvbuf; - unsigned long flags; - int totleft, numbytes, offset, frame, rc; - - /* loop while more completed URBs arrive in the meantime */ - for (;;) { - /* retrieve URB */ - spin_lock_irqsave(&ubc->isoinlock, flags); - urb = ubc->isoindone; - if (!urb) { - spin_unlock_irqrestore(&ubc->isoinlock, flags); - return; - } - status = ubc->isoinstatus; - ubc->isoindone = NULL; - if (unlikely(ubc->loststatus != -EINPROGRESS)) { - dev_warn(cs->dev, - "isoc read overrun, URB dropped (status: %s, %d bytes)\n", - get_usb_statmsg(ubc->loststatus), - ubc->isoinlost); - ubc->loststatus = -EINPROGRESS; - } - spin_unlock_irqrestore(&ubc->isoinlock, flags); - - if (unlikely(!(ubc->running))) { - gig_dbg(DEBUG_ISO, - "%s: channel not running, " - "dropped URB with status: %s", - __func__, get_usb_statmsg(status)); - return; - } - - switch (status) { - case 0: /* normal completion */ - break; - case -EXDEV: /* inspect individual frames - (we do that anyway) */ - gig_dbg(DEBUG_ISO, "%s: URB partially completed", - __func__); - break; - case -ENOENT: - case -ECONNRESET: - case -EINPROGRESS: - gig_dbg(DEBUG_ISO, "%s: %s", - __func__, get_usb_statmsg(status)); - continue; /* -> skip */ - case -EPIPE: - dev_err(cs->dev, "isoc read: stalled\n"); - error_hangup(bcs); - continue; /* -> skip */ - default: /* other error */ - dev_warn(cs->dev, "isoc read: %s\n", - get_usb_statmsg(status)); - goto error; - } - - rcvbuf = urb->transfer_buffer; - totleft = urb->actual_length; - for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { - ifd = &urb->iso_frame_desc[frame]; - numbytes = ifd->actual_length; - switch (ifd->status) { - case 0: /* success */ - break; - case -EPROTO: /* protocol error or unplug */ - case -EILSEQ: - case -ETIME: - /* probably just disconnected, ignore */ - gig_dbg(DEBUG_ISO, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - get_usb_statmsg(ifd->status)); - break; - default: /* other error */ - /* report, assume transferred bytes are ok */ - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - get_usb_statmsg(ifd->status)); - } - if (unlikely(numbytes > BAS_MAXFRAME)) - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - "exceeds max frame size"); - if (unlikely(numbytes > totleft)) { - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - "exceeds total transfer length"); - numbytes = totleft; - } - offset = ifd->offset; - if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { - dev_warn(cs->dev, - "isoc read: frame %d[%d]: %s\n", - frame, numbytes, - "exceeds end of buffer"); - numbytes = BAS_INBUFSIZE - offset; - } - gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); - totleft -= numbytes; - } - if (unlikely(totleft > 0)) - dev_warn(cs->dev, "isoc read: %d data bytes missing\n", - totleft); - -error: - /* URB processed, resubmit */ - for (frame = 0; frame < BAS_NUMFRAMES; frame++) { - urb->iso_frame_desc[frame].status = 0; - urb->iso_frame_desc[frame].actual_length = 0; - } - /* urb->dev is clobbered by USB subsystem */ - urb->dev = bcs->cs->hw.bas->udev; - urb->transfer_flags = URB_ISO_ASAP; - urb->number_of_packets = BAS_NUMFRAMES; - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc != 0 && rc != -ENODEV)) { - dev_err(cs->dev, - "could not resubmit isoc read URB: %s\n", - get_usb_rcmsg(rc)); - dump_urb(DEBUG_ISO, "resubmit isoc read", urb); - error_hangup(bcs); - } - } -} - -/* Channel Operations */ -/* ================== */ - -/* req_timeout - * timeout routine for control output request - * argument: - * controller state structure - */ -static void req_timeout(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_ctrl); - struct cardstate *cs = ucs->cs; - int pending; - unsigned long flags; - - check_pending(ucs); - - spin_lock_irqsave(&ucs->lock, flags); - pending = ucs->pending; - ucs->pending = 0; - spin_unlock_irqrestore(&ucs->lock, flags); - - switch (pending) { - case 0: /* no pending request */ - gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__); - break; - - case HD_OPEN_ATCHANNEL: - dev_err(cs->dev, "timeout opening AT channel\n"); - error_reset(cs); - break; - - case HD_OPEN_B1CHANNEL: - dev_err(cs->dev, "timeout opening channel 1\n"); - error_hangup(&cs->bcs[0]); - break; - - case HD_OPEN_B2CHANNEL: - dev_err(cs->dev, "timeout opening channel 2\n"); - error_hangup(&cs->bcs[1]); - break; - - case HD_CLOSE_ATCHANNEL: - dev_err(cs->dev, "timeout closing AT channel\n"); - error_reset(cs); - break; - - case HD_CLOSE_B1CHANNEL: - dev_err(cs->dev, "timeout closing channel 1\n"); - error_reset(cs); - break; - - case HD_CLOSE_B2CHANNEL: - dev_err(cs->dev, "timeout closing channel 2\n"); - error_reset(cs); - break; - - case HD_RESET_INTERRUPT_PIPE: - /* error recovery escalation */ - dev_err(cs->dev, - "reset interrupt pipe timeout, attempting USB reset\n"); - usb_queue_reset_device(ucs->interface); - break; - - default: - dev_warn(cs->dev, "request 0x%02x timed out, clearing\n", - pending); - } - - wake_up(&ucs->waitqueue); -} - -/* write_ctrl_callback - * USB completion handler for control pipe output - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = hardware specific controller state structure - */ -static void write_ctrl_callback(struct urb *urb) -{ - struct bas_cardstate *ucs = urb->context; - int status = urb->status; - int rc; - unsigned long flags; - - /* check status */ - switch (status) { - case 0: /* normal completion */ - spin_lock_irqsave(&ucs->lock, flags); - switch (ucs->pending) { - case HD_DEVICE_INIT_ACK: /* no reply expected */ - del_timer(&ucs->timer_ctrl); - ucs->pending = 0; - break; - } - spin_unlock_irqrestore(&ucs->lock, flags); - return; - - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* ignore silently */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - break; - - default: /* any failure */ - /* don't retry if suspend requested */ - if (++ucs->retry_ctrl > BAS_RETRY || - (ucs->basstate & BS_SUSPEND)) { - dev_err(&ucs->interface->dev, - "control request 0x%02x failed: %s\n", - ucs->dr_ctrl.bRequest, - get_usb_statmsg(status)); - break; /* give up */ - } - dev_notice(&ucs->interface->dev, - "control request 0x%02x: %s, retry %d\n", - ucs->dr_ctrl.bRequest, get_usb_statmsg(status), - ucs->retry_ctrl); - /* urb->dev is clobbered by USB subsystem */ - urb->dev = ucs->udev; - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(rc)) { - dev_err(&ucs->interface->dev, - "could not resubmit request 0x%02x: %s\n", - ucs->dr_ctrl.bRequest, get_usb_rcmsg(rc)); - break; - } - /* resubmitted */ - return; - } - - /* failed, clear pending request */ - spin_lock_irqsave(&ucs->lock, flags); - del_timer(&ucs->timer_ctrl); - ucs->pending = 0; - spin_unlock_irqrestore(&ucs->lock, flags); - wake_up(&ucs->waitqueue); -} - -/* req_submit - * submit a control output request without message buffer to the Gigaset base - * and optionally start a timeout - * parameters: - * bcs B channel control structure - * req control request code (HD_*) - * val control request parameter value (set to 0 if unused) - * timeout timeout in seconds (0: no timeout) - * return value: - * 0 on success - * -EBUSY if another request is pending - * any URB submission error code - */ -static int req_submit(struct bc_state *bcs, int req, int val, int timeout) -{ - struct bas_cardstate *ucs = bcs->cs->hw.bas; - int ret; - unsigned long flags; - - gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); - - spin_lock_irqsave(&ucs->lock, flags); - if (ucs->pending) { - spin_unlock_irqrestore(&ucs->lock, flags); - dev_err(bcs->cs->dev, - "submission of request 0x%02x failed: " - "request 0x%02x still pending\n", - req, ucs->pending); - return -EBUSY; - } - - ucs->dr_ctrl.bRequestType = OUT_VENDOR_REQ; - ucs->dr_ctrl.bRequest = req; - ucs->dr_ctrl.wValue = cpu_to_le16(val); - ucs->dr_ctrl.wIndex = 0; - ucs->dr_ctrl.wLength = 0; - usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - (unsigned char *) &ucs->dr_ctrl, NULL, 0, - write_ctrl_callback, ucs); - ucs->retry_ctrl = 0; - ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); - if (unlikely(ret)) { - dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", - req, get_usb_rcmsg(ret)); - spin_unlock_irqrestore(&ucs->lock, flags); - return ret; - } - ucs->pending = req; - - if (timeout > 0) { - gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); - mod_timer(&ucs->timer_ctrl, jiffies + timeout * HZ / 10); - } - - spin_unlock_irqrestore(&ucs->lock, flags); - return 0; -} - -/* gigaset_init_bchannel - * called by common.c to connect a B channel - * initialize isochronous I/O and tell the Gigaset base to open the channel - * argument: - * B channel control structure - * return value: - * 0 on success, error code < 0 on error - */ -static int gigaset_init_bchannel(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - int req, ret; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (unlikely(!cs->connected)) { - gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - spin_unlock_irqrestore(&cs->lock, flags); - return -ENODEV; - } - - if (cs->hw.bas->basstate & BS_SUSPEND) { - dev_notice(cs->dev, - "not starting isoc I/O, suspend in progress\n"); - spin_unlock_irqrestore(&cs->lock, flags); - return -EHOSTUNREACH; - } - - ret = starturbs(bcs); - if (ret < 0) { - spin_unlock_irqrestore(&cs->lock, flags); - dev_err(cs->dev, - "could not start isoc I/O for channel B%d: %s\n", - bcs->channel + 1, - ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); - if (ret != -ENODEV) - error_hangup(bcs); - return ret; - } - - req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; - ret = req_submit(bcs, req, 0, BAS_TIMEOUT); - if (ret < 0) { - dev_err(cs->dev, "could not open channel B%d\n", - bcs->channel + 1); - stopurbs(bcs->hw.bas); - } - - spin_unlock_irqrestore(&cs->lock, flags); - if (ret < 0 && ret != -ENODEV) - error_hangup(bcs); - return ret; -} - -/* gigaset_close_bchannel - * called by common.c to disconnect a B channel - * tell the Gigaset base to close the channel - * stopping isochronous I/O and LL notification will be done when the - * acknowledgement for the close arrives - * argument: - * B channel control structure - * return value: - * 0 on success, error code < 0 on error - */ -static int gigaset_close_bchannel(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - int req, ret; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (unlikely(!cs->connected)) { - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - return -ENODEV; - } - - if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { - /* channel not running: just signal common.c */ - spin_unlock_irqrestore(&cs->lock, flags); - gigaset_bchannel_down(bcs); - return 0; - } - - /* channel running: tell device to close it */ - req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; - ret = req_submit(bcs, req, 0, BAS_TIMEOUT); - if (ret < 0) - dev_err(cs->dev, "closing channel B%d failed\n", - bcs->channel + 1); - - spin_unlock_irqrestore(&cs->lock, flags); - return ret; -} - -/* Device Operations */ -/* ================= */ - -/* complete_cb - * unqueue first command buffer from queue, waking any sleepers - * must be called with cs->cmdlock held - * parameter: - * cs controller state structure - */ -static void complete_cb(struct cardstate *cs) -{ - struct cmdbuf_t *cb = cs->cmdbuf; - - /* unqueue completed buffer */ - cs->cmdbytes -= cs->curlen; - gig_dbg(DEBUG_OUTPUT, "write_command: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); - if (cb->next != NULL) { - cs->cmdbuf = cb->next; - cs->cmdbuf->prev = NULL; - cs->curlen = cs->cmdbuf->len; - } else { - cs->cmdbuf = NULL; - cs->lastcmdbuf = NULL; - cs->curlen = 0; - } - - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - - kfree(cb); -} - -/* write_command_callback - * USB completion handler for AT command transmission - * called by the USB subsystem in interrupt context - * parameter: - * urb USB request block of completed request - * urb->context = controller state structure - */ -static void write_command_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - struct bas_cardstate *ucs = cs->hw.bas; - int status = urb->status; - unsigned long flags; - - update_basstate(ucs, 0, BS_ATWRPEND); - wake_up(&ucs->waitqueue); - - /* check status */ - switch (status) { - case 0: /* normal completion */ - break; - case -ENOENT: /* cancelled */ - case -ECONNRESET: /* cancelled (async) */ - case -EINPROGRESS: /* pending */ - case -ENODEV: /* device removed */ - case -ESHUTDOWN: /* device shut down */ - /* ignore silently */ - gig_dbg(DEBUG_USBREQ, "%s: %s", - __func__, get_usb_statmsg(status)); - return; - default: /* any failure */ - if (++ucs->retry_cmd_out > BAS_RETRY) { - dev_warn(cs->dev, - "command write: %s, " - "giving up after %d retries\n", - get_usb_statmsg(status), - ucs->retry_cmd_out); - break; - } - if (ucs->basstate & BS_SUSPEND) { - dev_warn(cs->dev, - "command write: %s, " - "won't retry - suspend requested\n", - get_usb_statmsg(status)); - break; - } - if (cs->cmdbuf == NULL) { - dev_warn(cs->dev, - "command write: %s, " - "cannot retry - cmdbuf gone\n", - get_usb_statmsg(status)); - break; - } - dev_notice(cs->dev, "command write: %s, retry %d\n", - get_usb_statmsg(status), ucs->retry_cmd_out); - if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) - /* resubmitted - bypass regular exit block */ - return; - /* command send failed, assume base still waiting */ - update_basstate(ucs, BS_ATREADY, 0); - } - - spin_lock_irqsave(&cs->cmdlock, flags); - if (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); -} - -/* atrdy_timeout - * timeout routine for AT command transmission - * argument: - * controller state structure - */ -static void atrdy_timeout(struct timer_list *t) -{ - struct bas_cardstate *ucs = from_timer(ucs, t, timer_atrdy); - struct cardstate *cs = ucs->cs; - - dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n"); - - /* fake the missing signal - what else can I do? */ - update_basstate(ucs, BS_ATREADY, BS_ATTIMER); - start_cbsend(cs); -} - -/* atwrite_submit - * submit an HD_WRITE_ATMESSAGE command URB - * parameters: - * cs controller state structure - * buf buffer containing command to send - * len length of command to send - * return value: - * 0 on success - * -EBUSY if another request is pending - * any URB submission error code - */ -static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) -{ - struct bas_cardstate *ucs = cs->hw.bas; - int rc; - - gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); - - if (update_basstate(ucs, BS_ATWRPEND, 0) & BS_ATWRPEND) { - dev_err(cs->dev, - "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); - return -EBUSY; - } - - ucs->dr_cmd_out.bRequestType = OUT_VENDOR_REQ; - ucs->dr_cmd_out.bRequest = HD_WRITE_ATMESSAGE; - ucs->dr_cmd_out.wValue = 0; - ucs->dr_cmd_out.wIndex = 0; - ucs->dr_cmd_out.wLength = cpu_to_le16(len); - usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - (unsigned char *) &ucs->dr_cmd_out, buf, len, - write_command_callback, cs); - rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); - if (unlikely(rc)) { - update_basstate(ucs, 0, BS_ATWRPEND); - dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", - get_usb_rcmsg(rc)); - return rc; - } - - /* submitted successfully, start timeout if necessary */ - if (!(update_basstate(ucs, BS_ATTIMER, BS_ATREADY) & BS_ATTIMER)) { - gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", - ATRDY_TIMEOUT); - mod_timer(&ucs->timer_atrdy, jiffies + ATRDY_TIMEOUT * HZ / 10); - } - return 0; -} - -/* start_cbsend - * start transmission of AT command queue if necessary - * parameter: - * cs controller state structure - * return value: - * 0 on success - * error code < 0 on error - */ -static int start_cbsend(struct cardstate *cs) -{ - struct cmdbuf_t *cb; - struct bas_cardstate *ucs = cs->hw.bas; - unsigned long flags; - int rc; - int retval = 0; - - /* check if suspend requested */ - if (ucs->basstate & BS_SUSPEND) { - gig_dbg(DEBUG_OUTPUT, "suspending"); - return -EHOSTUNREACH; - } - - /* check if AT channel is open */ - if (!(ucs->basstate & BS_ATOPEN)) { - gig_dbg(DEBUG_OUTPUT, "AT channel not open"); - rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); - if (rc < 0) { - /* flush command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); - } - return rc; - } - - /* try to send first command in queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - - while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) { - ucs->retry_cmd_out = 0; - rc = atwrite_submit(cs, cb->buf, cb->len); - if (unlikely(rc)) { - retval = rc; - complete_cb(cs); - } - } - - spin_unlock_irqrestore(&cs->cmdlock, flags); - return retval; -} - -/* gigaset_write_cmd - * This function is called by the device independent part of the driver - * to transmit an AT command string to the Gigaset device. - * It encapsulates the device specific method for transmission over the - * direct USB connection to the base. - * The command string is added to the queue of commands to send, and - * USB transmission is started if necessary. - * parameters: - * cs controller state structure - * cb command buffer structure - * return value: - * number of bytes queued on success - * error code < 0 on error - */ -static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) -{ - unsigned long flags; - int rc; - - gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", cb->len, cb->buf); - - /* translate "+++" escape sequence sent as a single separate command - * into "close AT channel" command for error recovery - * The next command will reopen the AT channel automatically. - */ - if (cb->len == 3 && !memcmp(cb->buf, "+++", 3)) { - /* If an HD_RECEIVEATDATA_ACK message remains unhandled - * because of an error, the base never sends another one. - * The response channel is thus effectively blocked. - * Closing and reopening the AT channel does *not* clear - * this condition. - * As a stopgap measure, submit a zero-length AT read - * before closing the AT channel. This has the undocumented - * effect of triggering a new HD_RECEIVEATDATA_ACK message - * from the base if necessary. - * The subsequent AT channel close then discards any pending - * messages. - */ - spin_lock_irqsave(&cs->lock, flags); - if (!(cs->hw.bas->basstate & BS_ATRDPEND)) { - kfree(cs->hw.bas->rcvbuf); - cs->hw.bas->rcvbuf = NULL; - cs->hw.bas->rcvbuf_size = 0; - cs->hw.bas->retry_cmd_in = 0; - atread_submit(cs, 0); - } - spin_unlock_irqrestore(&cs->lock, flags); - - rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - if (!rc) - rc = cb->len; - kfree(cb); - return rc; - } - - spin_lock_irqsave(&cs->cmdlock, flags); - cb->prev = cs->lastcmdbuf; - if (cs->lastcmdbuf) - cs->lastcmdbuf->next = cb; - else { - cs->cmdbuf = cb; - cs->curlen = cb->len; - } - cs->cmdbytes += cb->len; - cs->lastcmdbuf = cb; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - spin_lock_irqsave(&cs->lock, flags); - if (unlikely(!cs->connected)) { - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); - /* flush command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while (cs->cmdbuf != NULL) - complete_cb(cs); - spin_unlock_irqrestore(&cs->cmdlock, flags); - return -ENODEV; - } - rc = start_cbsend(cs); - spin_unlock_irqrestore(&cs->lock, flags); - return rc < 0 ? rc : cb->len; -} - -/* gigaset_write_room - * tty_driver.write_room interface routine - * return number of characters the driver will accept to be written via - * gigaset_write_cmd - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_write_room(struct cardstate *cs) -{ - return IF_WRITEBUF; -} - -/* gigaset_chars_in_buffer - * tty_driver.chars_in_buffer interface routine - * return number of characters waiting to be sent - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_chars_in_buffer(struct cardstate *cs) -{ - return cs->cmdbytes; -} - -/* gigaset_brkchars - * implementation of ioctl(GIGASET_BRKCHARS) - * parameter: - * controller state structure - * return value: - * -EINVAL (unimplemented function) - */ -static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) -{ - return -EINVAL; -} - - -/* Device Initialization/Shutdown */ -/* ============================== */ - -/* Free hardware dependent part of the B channel structure - * parameter: - * bcs B channel structure - */ -static void gigaset_freebcshw(struct bc_state *bcs) -{ - struct bas_bc_state *ubc = bcs->hw.bas; - int i; - - if (!ubc) - return; - - /* kill URBs and tasklets before freeing - better safe than sorry */ - ubc->running = 0; - gig_dbg(DEBUG_INIT, "%s: killing isoc URBs", __func__); - for (i = 0; i < BAS_OUTURBS; ++i) { - usb_kill_urb(ubc->isoouturbs[i].urb); - usb_free_urb(ubc->isoouturbs[i].urb); - } - for (i = 0; i < BAS_INURBS; ++i) { - usb_kill_urb(ubc->isoinurbs[i]); - usb_free_urb(ubc->isoinurbs[i]); - } - tasklet_kill(&ubc->sent_tasklet); - tasklet_kill(&ubc->rcvd_tasklet); - kfree(ubc->isooutbuf); - kfree(ubc); - bcs->hw.bas = NULL; -} - -/* Initialize hardware dependent part of the B channel structure - * parameter: - * bcs B channel structure - * return value: - * 0 on success, error code < 0 on failure - */ -static int gigaset_initbcshw(struct bc_state *bcs) -{ - int i; - struct bas_bc_state *ubc; - - bcs->hw.bas = ubc = kmalloc(sizeof(struct bas_bc_state), GFP_KERNEL); - if (!ubc) { - pr_err("out of memory\n"); - return -ENOMEM; - } - - ubc->running = 0; - atomic_set(&ubc->corrbytes, 0); - spin_lock_init(&ubc->isooutlock); - for (i = 0; i < BAS_OUTURBS; ++i) { - ubc->isoouturbs[i].urb = NULL; - ubc->isoouturbs[i].bcs = bcs; - } - ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; - ubc->numsub = 0; - ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL); - if (!ubc->isooutbuf) { - pr_err("out of memory\n"); - kfree(ubc); - bcs->hw.bas = NULL; - return -ENOMEM; - } - tasklet_init(&ubc->sent_tasklet, - write_iso_tasklet, (unsigned long) bcs); - - spin_lock_init(&ubc->isoinlock); - for (i = 0; i < BAS_INURBS; ++i) - ubc->isoinurbs[i] = NULL; - ubc->isoindone = NULL; - ubc->loststatus = -EINPROGRESS; - ubc->isoinlost = 0; - ubc->seqlen = 0; - ubc->inbyte = 0; - ubc->inbits = 0; - ubc->goodbytes = 0; - ubc->alignerrs = 0; - ubc->fcserrs = 0; - ubc->frameerrs = 0; - ubc->giants = 0; - ubc->runts = 0; - ubc->aborts = 0; - ubc->shared0s = 0; - ubc->stolen0s = 0; - tasklet_init(&ubc->rcvd_tasklet, - read_iso_tasklet, (unsigned long) bcs); - return 0; -} - -static void gigaset_reinitbcshw(struct bc_state *bcs) -{ - struct bas_bc_state *ubc = bcs->hw.bas; - - bcs->hw.bas->running = 0; - atomic_set(&bcs->hw.bas->corrbytes, 0); - bcs->hw.bas->numsub = 0; - spin_lock_init(&ubc->isooutlock); - spin_lock_init(&ubc->isoinlock); - ubc->loststatus = -EINPROGRESS; -} - -static void gigaset_freecshw(struct cardstate *cs) -{ - /* timers, URBs and rcvbuf are disposed of in disconnect */ - kfree(cs->hw.bas->int_in_buf); - kfree(cs->hw.bas); - cs->hw.bas = NULL; -} - -/* Initialize hardware dependent part of the cardstate structure - * parameter: - * cs cardstate structure - * return value: - * 0 on success, error code < 0 on failure - */ -static int gigaset_initcshw(struct cardstate *cs) -{ - struct bas_cardstate *ucs; - - cs->hw.bas = ucs = kzalloc(sizeof(*ucs), GFP_KERNEL); - if (!ucs) { - pr_err("out of memory\n"); - return -ENOMEM; - } - ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL); - if (!ucs->int_in_buf) { - kfree(ucs); - pr_err("out of memory\n"); - return -ENOMEM; - } - - spin_lock_init(&ucs->lock); - ucs->cs = cs; - timer_setup(&ucs->timer_ctrl, req_timeout, 0); - timer_setup(&ucs->timer_atrdy, atrdy_timeout, 0); - timer_setup(&ucs->timer_cmd_in, cmd_in_timeout, 0); - timer_setup(&ucs->timer_int_in, int_in_resubmit, 0); - init_waitqueue_head(&ucs->waitqueue); - INIT_WORK(&ucs->int_in_wq, int_in_work); - - return 0; -} - -/* freeurbs - * unlink and deallocate all URBs unconditionally - * caller must make sure that no commands are still in progress - * parameter: - * cs controller state structure - */ -static void freeurbs(struct cardstate *cs) -{ - struct bas_cardstate *ucs = cs->hw.bas; - struct bas_bc_state *ubc; - int i, j; - - gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); - for (j = 0; j < BAS_CHANNELS; ++j) { - ubc = cs->bcs[j].hw.bas; - for (i = 0; i < BAS_OUTURBS; ++i) { - usb_kill_urb(ubc->isoouturbs[i].urb); - usb_free_urb(ubc->isoouturbs[i].urb); - ubc->isoouturbs[i].urb = NULL; - } - for (i = 0; i < BAS_INURBS; ++i) { - usb_kill_urb(ubc->isoinurbs[i]); - usb_free_urb(ubc->isoinurbs[i]); - ubc->isoinurbs[i] = NULL; - } - } - usb_kill_urb(ucs->urb_int_in); - usb_free_urb(ucs->urb_int_in); - ucs->urb_int_in = NULL; - usb_kill_urb(ucs->urb_cmd_out); - usb_free_urb(ucs->urb_cmd_out); - ucs->urb_cmd_out = NULL; - usb_kill_urb(ucs->urb_cmd_in); - usb_free_urb(ucs->urb_cmd_in); - ucs->urb_cmd_in = NULL; - usb_kill_urb(ucs->urb_ctrl); - usb_free_urb(ucs->urb_ctrl); - ucs->urb_ctrl = NULL; -} - -/* gigaset_probe - * This function is called when a new USB device is connected. - * It checks whether the new device is handled by this driver. - */ -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_host_interface *hostif; - struct usb_device *udev = interface_to_usbdev(interface); - struct cardstate *cs = NULL; - struct bas_cardstate *ucs = NULL; - struct bas_bc_state *ubc; - struct usb_endpoint_descriptor *endpoint; - int i, j; - int rc; - - gig_dbg(DEBUG_INIT, - "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - /* set required alternate setting */ - hostif = interface->cur_altsetting; - if (hostif->desc.bAlternateSetting != 3) { - gig_dbg(DEBUG_INIT, - "%s: wrong alternate setting %d - trying to switch", - __func__, hostif->desc.bAlternateSetting); - if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) - < 0) { - dev_warn(&udev->dev, "usb_set_interface failed, " - "device %d interface %d altsetting %d\n", - udev->devnum, hostif->desc.bInterfaceNumber, - hostif->desc.bAlternateSetting); - return -ENODEV; - } - hostif = interface->cur_altsetting; - } - - /* Reject application specific interfaces - */ - if (hostif->desc.bInterfaceClass != 255) { - dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n", - __func__, hostif->desc.bInterfaceClass); - return -ENODEV; - } - - if (hostif->desc.bNumEndpoints < 1) - return -ENODEV; - - dev_info(&udev->dev, - "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - - /* allocate memory for our device state and initialize it */ - cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, - GIGASET_MODULENAME); - if (!cs) - return -ENODEV; - ucs = cs->hw.bas; - - /* save off device structure ptrs for later use */ - usb_get_dev(udev); - ucs->udev = udev; - ucs->interface = interface; - cs->dev = &interface->dev; - - /* allocate URBs: - * - one for the interrupt pipe - * - three for the different uses of the default control pipe - * - three for each isochronous pipe - */ - if (!(ucs->urb_int_in = usb_alloc_urb(0, GFP_KERNEL)) || - !(ucs->urb_cmd_in = usb_alloc_urb(0, GFP_KERNEL)) || - !(ucs->urb_cmd_out = usb_alloc_urb(0, GFP_KERNEL)) || - !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) - goto allocerr; - - for (j = 0; j < BAS_CHANNELS; ++j) { - ubc = cs->bcs[j].hw.bas; - for (i = 0; i < BAS_OUTURBS; ++i) - if (!(ubc->isoouturbs[i].urb = - usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL))) - goto allocerr; - for (i = 0; i < BAS_INURBS; ++i) - if (!(ubc->isoinurbs[i] = - usb_alloc_urb(BAS_NUMFRAMES, GFP_KERNEL))) - goto allocerr; - } - - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - - /* Fill the interrupt urb and send it to the core */ - endpoint = &hostif->endpoint[0].desc; - usb_fill_int_urb(ucs->urb_int_in, udev, - usb_rcvintpipe(udev, - usb_endpoint_num(endpoint)), - ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, - endpoint->bInterval); - rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); - if (rc != 0) { - dev_err(cs->dev, "could not submit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - goto error; - } - ucs->retry_int_in = 0; - - /* tell the device that the driver is ready */ - rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); - if (rc != 0) - goto error; - - /* tell common part that the device is ready */ - if (startmode == SM_LOCKED) - cs->mstate = MS_LOCKED; - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - rc = gigaset_start(cs); - if (rc < 0) - goto error; - - return 0; - -allocerr: - dev_err(cs->dev, "could not allocate URBs\n"); - rc = -ENOMEM; -error: - freeurbs(cs); - usb_set_intfdata(interface, NULL); - usb_put_dev(udev); - gigaset_freecs(cs); - return rc; -} - -/* gigaset_disconnect - * This function is called when the Gigaset base is unplugged. - */ -static void gigaset_disconnect(struct usb_interface *interface) -{ - struct cardstate *cs; - struct bas_cardstate *ucs; - int j; - - cs = usb_get_intfdata(interface); - - ucs = cs->hw.bas; - - dev_info(cs->dev, "disconnecting Gigaset base\n"); - - /* mark base as not ready, all channels disconnected */ - ucs->basstate = 0; - - /* tell LL all channels are down */ - for (j = 0; j < BAS_CHANNELS; ++j) - gigaset_bchannel_down(cs->bcs + j); - - /* stop driver (common part) */ - gigaset_stop(cs); - - /* stop delayed work and URBs, free ressources */ - del_timer_sync(&ucs->timer_ctrl); - del_timer_sync(&ucs->timer_atrdy); - del_timer_sync(&ucs->timer_cmd_in); - del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); - freeurbs(cs); - usb_set_intfdata(interface, NULL); - kfree(ucs->rcvbuf); - ucs->rcvbuf = NULL; - ucs->rcvbuf_size = 0; - usb_put_dev(ucs->udev); - ucs->interface = NULL; - ucs->udev = NULL; - cs->dev = NULL; - gigaset_freecs(cs); -} - -/* gigaset_suspend - * This function is called before the USB connection is suspended - * or before the USB device is reset. - * In the latter case, message == PMSG_ON. - */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct cardstate *cs = usb_get_intfdata(intf); - struct bas_cardstate *ucs = cs->hw.bas; - int rc; - - /* set suspend flag; this stops AT command/response traffic */ - if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) { - gig_dbg(DEBUG_SUSPEND, "already suspended"); - return 0; - } - - /* wait a bit for blocking conditions to go away */ - rc = wait_event_timeout(ucs->waitqueue, - !(ucs->basstate & - (BS_B1OPEN | BS_B2OPEN | BS_ATRDPEND | BS_ATWRPEND)), - BAS_TIMEOUT * HZ / 10); - gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc); - - /* check for conditions preventing suspend */ - if (ucs->basstate & (BS_B1OPEN | BS_B2OPEN | BS_ATRDPEND | BS_ATWRPEND)) { - dev_warn(cs->dev, "cannot suspend:\n"); - if (ucs->basstate & BS_B1OPEN) - dev_warn(cs->dev, " B channel 1 open\n"); - if (ucs->basstate & BS_B2OPEN) - dev_warn(cs->dev, " B channel 2 open\n"); - if (ucs->basstate & BS_ATRDPEND) - dev_warn(cs->dev, " receiving AT reply\n"); - if (ucs->basstate & BS_ATWRPEND) - dev_warn(cs->dev, " sending AT command\n"); - update_basstate(ucs, 0, BS_SUSPEND); - return -EBUSY; - } - - /* close AT channel if open */ - if (ucs->basstate & BS_ATOPEN) { - gig_dbg(DEBUG_SUSPEND, "closing AT channel"); - rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0); - if (rc) { - update_basstate(ucs, 0, BS_SUSPEND); - return rc; - } - wait_event_timeout(ucs->waitqueue, !ucs->pending, - BAS_TIMEOUT * HZ / 10); - /* in case of timeout, proceed anyway */ - } - - /* kill all URBs and delayed work that might still be pending */ - usb_kill_urb(ucs->urb_ctrl); - usb_kill_urb(ucs->urb_int_in); - del_timer_sync(&ucs->timer_ctrl); - del_timer_sync(&ucs->timer_atrdy); - del_timer_sync(&ucs->timer_cmd_in); - del_timer_sync(&ucs->timer_int_in); - - /* don't try to cancel int_in_wq from within reset as it - * might be the one requesting the reset - */ - if (message.event != PM_EVENT_ON) - cancel_work_sync(&ucs->int_in_wq); - - gig_dbg(DEBUG_SUSPEND, "suspend complete"); - return 0; -} - -/* gigaset_resume - * This function is called after the USB connection has been resumed. - */ -static int gigaset_resume(struct usb_interface *intf) -{ - struct cardstate *cs = usb_get_intfdata(intf); - struct bas_cardstate *ucs = cs->hw.bas; - int rc; - - /* resubmit interrupt URB for spontaneous messages from base */ - rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); - if (rc) { - dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", - get_usb_rcmsg(rc)); - return rc; - } - ucs->retry_int_in = 0; - - /* clear suspend flag to reallow activity */ - update_basstate(ucs, 0, BS_SUSPEND); - - gig_dbg(DEBUG_SUSPEND, "resume complete"); - return 0; -} - -/* gigaset_pre_reset - * This function is called before the USB connection is reset. - */ -static int gigaset_pre_reset(struct usb_interface *intf) -{ - /* handle just like suspend */ - return gigaset_suspend(intf, PMSG_ON); -} - -/* gigaset_post_reset - * This function is called after the USB connection has been reset. - */ -static int gigaset_post_reset(struct usb_interface *intf) -{ - /* FIXME: send HD_DEVICE_INIT_ACK? */ - - /* resume operations */ - return gigaset_resume(intf); -} - - -static const struct gigaset_ops gigops = { - .write_cmd = gigaset_write_cmd, - .write_room = gigaset_write_room, - .chars_in_buffer = gigaset_chars_in_buffer, - .brkchars = gigaset_brkchars, - .init_bchannel = gigaset_init_bchannel, - .close_bchannel = gigaset_close_bchannel, - .initbcshw = gigaset_initbcshw, - .freebcshw = gigaset_freebcshw, - .reinitbcshw = gigaset_reinitbcshw, - .initcshw = gigaset_initcshw, - .freecshw = gigaset_freecshw, - .set_modem_ctrl = gigaset_set_modem_ctrl, - .baud_rate = gigaset_baud_rate, - .set_line_ctrl = gigaset_set_line_ctrl, - .send_skb = gigaset_isoc_send_skb, - .handle_input = gigaset_isoc_input, -}; - -/* bas_gigaset_init - * This function is called after the kernel module is loaded. - */ -static int __init bas_gigaset_init(void) -{ - int result; - - /* allocate memory for our driver state and initialize it */ - driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &gigops, THIS_MODULE); - if (driver == NULL) - goto error; - - /* register this driver with the USB subsystem */ - result = usb_register(&gigaset_usb_driver); - if (result < 0) { - pr_err("error %d registering USB driver\n", -result); - goto error; - } - - pr_info(DRIVER_DESC "\n"); - return 0; - -error: - if (driver) - gigaset_freedriver(driver); - driver = NULL; - return -1; -} - -/* bas_gigaset_exit - * This function is called before the kernel module is unloaded. - */ -static void __exit bas_gigaset_exit(void) -{ - struct bas_cardstate *ucs; - int i; - - gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ - - /* stop all connected devices */ - for (i = 0; i < driver->minors; i++) { - if (gigaset_shutdown(driver->cs + i) < 0) - continue; /* no device */ - /* from now on, no isdn callback should be possible */ - - /* close all still open channels */ - ucs = driver->cs[i].hw.bas; - if (ucs->basstate & BS_B1OPEN) { - gig_dbg(DEBUG_INIT, "closing B1 channel"); - usb_control_msg(ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, - 0, 0, NULL, 0, BAS_TIMEOUT); - } - if (ucs->basstate & BS_B2OPEN) { - gig_dbg(DEBUG_INIT, "closing B2 channel"); - usb_control_msg(ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, - 0, 0, NULL, 0, BAS_TIMEOUT); - } - if (ucs->basstate & BS_ATOPEN) { - gig_dbg(DEBUG_INIT, "closing AT channel"); - usb_control_msg(ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, - 0, 0, NULL, 0, BAS_TIMEOUT); - } - ucs->basstate = 0; - } - - /* deregister this driver with the USB subsystem */ - usb_deregister(&gigaset_usb_driver); - /* this will call the disconnect-callback */ - /* from now on, no disconnect/probe callback should be running */ - - gigaset_freedriver(driver); - driver = NULL; -} - - -module_init(bas_gigaset_init); -module_exit(bas_gigaset_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/isdn/gigaset/capi.c b/drivers/staging/isdn/gigaset/capi.c deleted file mode 100644 index 83d7dd48c61d..000000000000 --- a/drivers/staging/isdn/gigaset/capi.c +++ /dev/null @@ -1,2517 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Kernel CAPI interface for the Gigaset driver - * - * Copyright (c) 2009 by Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include -#include -#include -#include -#include - -/* missing from kernelcapi.h */ -#define CapiNcpiNotSupportedByProtocol 0x0001 -#define CapiFlagsNotSupportedByProtocol 0x0002 -#define CapiAlertAlreadySent 0x0003 -#define CapiFacilitySpecificFunctionNotSupported 0x3011 - -/* missing from capicmd.h */ -#define CAPI_CONNECT_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 2 + 8 * 1) -#define CAPI_CONNECT_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 3 * 1) -#define CAPI_CONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 1) -#define CAPI_CONNECT_B3_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 1) -#define CAPI_DATA_B3_REQ_LEN64 (CAPI_MSG_BASELEN + 4 + 4 + 2 + 2 + 2 + 8) -#define CAPI_DATA_B3_CONF_LEN (CAPI_MSG_BASELEN + 4 + 2 + 2) -#define CAPI_DISCONNECT_IND_LEN (CAPI_MSG_BASELEN + 4 + 2) -#define CAPI_DISCONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN + 4 + 2 + 1) -#define CAPI_FACILITY_CONF_BASELEN (CAPI_MSG_BASELEN + 4 + 2 + 2 + 1) -/* most _CONF messages contain only Controller/PLCI/NCCI and Info parameters */ -#define CAPI_STDCONF_LEN (CAPI_MSG_BASELEN + 4 + 2) - -#define CAPI_FACILITY_HANDSET 0x0000 -#define CAPI_FACILITY_DTMF 0x0001 -#define CAPI_FACILITY_V42BIS 0x0002 -#define CAPI_FACILITY_SUPPSVC 0x0003 -#define CAPI_FACILITY_WAKEUP 0x0004 -#define CAPI_FACILITY_LI 0x0005 - -#define CAPI_SUPPSVC_GETSUPPORTED 0x0000 -#define CAPI_SUPPSVC_LISTEN 0x0001 - -/* missing from capiutil.h */ -#define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9) -#define CAPIMSG_NCCI_PART(m) CAPIMSG_U16(m, 10) -#define CAPIMSG_HANDLE_REQ(m) CAPIMSG_U16(m, 18) /* DATA_B3_REQ/_IND only! */ -#define CAPIMSG_FLAGS(m) CAPIMSG_U16(m, 20) -#define CAPIMSG_SETCONTROLLER(m, contr) capimsg_setu8(m, 8, contr) -#define CAPIMSG_SETPLCI_PART(m, plci) capimsg_setu8(m, 9, plci) -#define CAPIMSG_SETNCCI_PART(m, ncci) capimsg_setu16(m, 10, ncci) -#define CAPIMSG_SETFLAGS(m, flags) capimsg_setu16(m, 20, flags) - -/* parameters with differing location in DATA_B3_CONF/_RESP: */ -#define CAPIMSG_SETHANDLE_CONF(m, handle) capimsg_setu16(m, 12, handle) -#define CAPIMSG_SETINFO_CONF(m, info) capimsg_setu16(m, 14, info) - -/* Flags (DATA_B3_REQ/_IND) */ -#define CAPI_FLAGS_DELIVERY_CONFIRMATION 0x04 -#define CAPI_FLAGS_RESERVED (~0x1f) - -/* buffer sizes */ -#define MAX_BC_OCTETS 11 -#define MAX_HLC_OCTETS 3 -#define MAX_NUMBER_DIGITS 20 -#define MAX_FMT_IE_LEN 20 - -/* values for bcs->apconnstate */ -#define APCONN_NONE 0 /* inactive/listening */ -#define APCONN_SETUP 1 /* connecting */ -#define APCONN_ACTIVE 2 /* B channel up */ - -/* registered application data structure */ -struct gigaset_capi_appl { - struct list_head ctrlist; - struct gigaset_capi_appl *bcnext; - u16 id; - struct capi_register_params rp; - u16 nextMessageNumber; - u32 listenInfoMask; - u32 listenCIPmask; -}; - -/* CAPI specific controller data structure */ -struct gigaset_capi_ctr { - struct capi_ctr ctr; - struct list_head appls; - struct sk_buff_head sendqueue; - atomic_t sendqlen; - /* two _cmsg structures possibly used concurrently: */ - _cmsg hcmsg; /* for message composition triggered from hardware */ - _cmsg acmsg; /* for dissection of messages sent from application */ - u8 bc_buf[MAX_BC_OCTETS + 1]; - u8 hlc_buf[MAX_HLC_OCTETS + 1]; - u8 cgpty_buf[MAX_NUMBER_DIGITS + 3]; - u8 cdpty_buf[MAX_NUMBER_DIGITS + 2]; -}; - -/* CIP Value table (from CAPI 2.0 standard, ch. 6.1) */ -static struct { - u8 *bc; - u8 *hlc; -} cip2bchlc[] = { - [1] = { "8090A3", NULL }, /* Speech (A-law) */ - [2] = { "8890", NULL }, /* Unrestricted digital information */ - [3] = { "8990", NULL }, /* Restricted digital information */ - [4] = { "9090A3", NULL }, /* 3,1 kHz audio (A-law) */ - [5] = { "9190", NULL }, /* 7 kHz audio */ - [6] = { "9890", NULL }, /* Video */ - [7] = { "88C0C6E6", NULL }, /* Packet mode */ - [8] = { "8890218F", NULL }, /* 56 kbit/s rate adaptation */ - [9] = { "9190A5", NULL }, /* Unrestricted digital information - * with tones/announcements */ - [16] = { "8090A3", "9181" }, /* Telephony */ - [17] = { "9090A3", "9184" }, /* Group 2/3 facsimile */ - [18] = { "8890", "91A1" }, /* Group 4 facsimile Class 1 */ - [19] = { "8890", "91A4" }, /* Teletex service basic and mixed mode - * and Group 4 facsimile service - * Classes II and III */ - [20] = { "8890", "91A8" }, /* Teletex service basic and - * processable mode */ - [21] = { "8890", "91B1" }, /* Teletex service basic mode */ - [22] = { "8890", "91B2" }, /* International interworking for - * Videotex */ - [23] = { "8890", "91B5" }, /* Telex */ - [24] = { "8890", "91B8" }, /* Message Handling Systems - * in accordance with X.400 */ - [25] = { "8890", "91C1" }, /* OSI application - * in accordance with X.200 */ - [26] = { "9190A5", "9181" }, /* 7 kHz telephony */ - [27] = { "9190A5", "916001" }, /* Video telephony, first connection */ - [28] = { "8890", "916002" }, /* Video telephony, second connection */ -}; - -/* - * helper functions - * ================ - */ - -/* - * emit unsupported parameter warning - */ -static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, - char *msgname, char *paramname) -{ - if (param && *param) - dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", - msgname, paramname); -} - -/* - * convert an IE from Gigaset hex string to ETSI binary representation - * including length byte - * return value: result length, -1 on error - */ -static int encode_ie(char *in, u8 *out, int maxlen) -{ - int l = 0; - while (*in) { - if (!isxdigit(in[0]) || !isxdigit(in[1]) || l >= maxlen) - return -1; - out[++l] = (hex_to_bin(in[0]) << 4) + hex_to_bin(in[1]); - in += 2; - } - out[0] = l; - return l; -} - -/* - * convert an IE from ETSI binary representation including length byte - * to Gigaset hex string - */ -static void decode_ie(u8 *in, char *out) -{ - int i = *in; - while (i-- > 0) { - /* ToDo: conversion to upper case necessary? */ - *out++ = toupper(hex_asc_hi(*++in)); - *out++ = toupper(hex_asc_lo(*in)); - } -} - -/* - * retrieve application data structure for an application ID - */ -static inline struct gigaset_capi_appl * -get_appl(struct gigaset_capi_ctr *iif, u16 appl) -{ - struct gigaset_capi_appl *ap; - - list_for_each_entry(ap, &iif->appls, ctrlist) - if (ap->id == appl) - return ap; - return NULL; -} - -/* - * dump CAPI message to kernel messages for debugging - */ -static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) -{ -#ifdef CONFIG_GIGASET_DEBUG - /* dump at most 20 messages in 20 secs */ - static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20); - _cdebbuf *cdb; - - if (!(gigaset_debuglevel & level)) - return; - if (!___ratelimit(&msg_dump_ratelimit, tag)) - return; - - cdb = capi_cmsg2str(p); - if (cdb) { - gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, cdb->buf); - cdebbuf_free(cdb); - } else { - gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, - capi_cmd2str(p->Command, p->Subcommand)); - } -#endif -} - -static inline void dump_rawmsg(enum debuglevel level, const char *tag, - unsigned char *data) -{ -#ifdef CONFIG_GIGASET_DEBUG - char *dbgline; - int i, l; - - if (!(gigaset_debuglevel & level)) - return; - - l = CAPIMSG_LEN(data); - if (l < 12) { - gig_dbg(level, "%s: ??? LEN=%04d", tag, l); - return; - } - gig_dbg(level, "%s: 0x%02x:0x%02x: ID=%03d #0x%04x LEN=%04d NCCI=0x%x", - tag, CAPIMSG_COMMAND(data), CAPIMSG_SUBCOMMAND(data), - CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, - CAPIMSG_CONTROL(data)); - l -= 12; - if (l <= 0) - return; - if (l > 64) - l = 64; /* arbitrary limit */ - dbgline = kmalloc_array(3, l, GFP_ATOMIC); - if (!dbgline) - return; - for (i = 0; i < l; i++) { - dbgline[3 * i] = hex_asc_hi(data[12 + i]); - dbgline[3 * i + 1] = hex_asc_lo(data[12 + i]); - dbgline[3 * i + 2] = ' '; - } - dbgline[3 * l - 1] = '\0'; - gig_dbg(level, " %s", dbgline); - kfree(dbgline); - if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 && - (CAPIMSG_SUBCOMMAND(data) == CAPI_REQ || - CAPIMSG_SUBCOMMAND(data) == CAPI_IND)) { - l = CAPIMSG_DATALEN(data); - gig_dbg(level, " DataLength=%d", l); - if (l <= 0 || !(gigaset_debuglevel & DEBUG_LLDATA)) - return; - if (l > 64) - l = 64; /* arbitrary limit */ - dbgline = kmalloc_array(3, l, GFP_ATOMIC); - if (!dbgline) - return; - data += CAPIMSG_LEN(data); - for (i = 0; i < l; i++) { - dbgline[3 * i] = hex_asc_hi(data[i]); - dbgline[3 * i + 1] = hex_asc_lo(data[i]); - dbgline[3 * i + 2] = ' '; - } - dbgline[3 * l - 1] = '\0'; - gig_dbg(level, " %s", dbgline); - kfree(dbgline); - } -#endif -} - -/* - * format CAPI IE as string - */ - -#ifdef CONFIG_GIGASET_DEBUG -static const char *format_ie(const char *ie) -{ - static char result[3 * MAX_FMT_IE_LEN]; - int len, count; - char *pout = result; - - if (!ie) - return "NULL"; - - count = len = ie[0]; - if (count > MAX_FMT_IE_LEN) - count = MAX_FMT_IE_LEN - 1; - while (count--) { - *pout++ = hex_asc_hi(*++ie); - *pout++ = hex_asc_lo(*ie); - *pout++ = ' '; - } - if (len > MAX_FMT_IE_LEN) { - *pout++ = '.'; - *pout++ = '.'; - *pout++ = '.'; - } - *--pout = 0; - return result; -} -#endif - -/* - * emit DATA_B3_CONF message - */ -static void send_data_b3_conf(struct cardstate *cs, struct capi_ctr *ctr, - u16 appl, u16 msgid, int channel, - u16 handle, u16 info) -{ - struct sk_buff *cskb; - u8 *msg; - - cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); - if (!cskb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - /* frequent message, avoid _cmsg overhead */ - msg = __skb_put(cskb, CAPI_DATA_B3_CONF_LEN); - CAPIMSG_SETLEN(msg, CAPI_DATA_B3_CONF_LEN); - CAPIMSG_SETAPPID(msg, appl); - CAPIMSG_SETCOMMAND(msg, CAPI_DATA_B3); - CAPIMSG_SETSUBCOMMAND(msg, CAPI_CONF); - CAPIMSG_SETMSGID(msg, msgid); - CAPIMSG_SETCONTROLLER(msg, ctr->cnr); - CAPIMSG_SETPLCI_PART(msg, channel); - CAPIMSG_SETNCCI_PART(msg, 1); - CAPIMSG_SETHANDLE_CONF(msg, handle); - CAPIMSG_SETINFO_CONF(msg, info); - - /* emit message */ - dump_rawmsg(DEBUG_MCMD, __func__, msg); - capi_ctr_handle_message(ctr, appl, cskb); -} - - -/* - * driver interface functions - * ========================== - */ - -/** - * gigaset_skb_sent() - acknowledge transmission of outgoing skb - * @bcs: B channel descriptor structure. - * @skb: sent data. - * - * Called by hardware module {bas,ser,usb}_gigaset when the data in a - * skb has been successfully sent, for signalling completion to the LL. - */ -void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap = bcs->ap; - unsigned char *req = skb_mac_header(dskb); - u16 flags; - - /* update statistics */ - ++bcs->trans_up; - - if (!ap) { - gig_dbg(DEBUG_MCMD, "%s: application gone", __func__); - return; - } - - /* don't send further B3 messages if disconnected */ - if (bcs->apconnstate < APCONN_ACTIVE) { - gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__); - return; - } - - /* - * send DATA_B3_CONF if "delivery confirmation" bit was set in request; - * otherwise it has already been sent by do_data_b3_req() - */ - flags = CAPIMSG_FLAGS(req); - if (flags & CAPI_FLAGS_DELIVERY_CONFIRMATION) - send_data_b3_conf(cs, &iif->ctr, ap->id, CAPIMSG_MSGID(req), - bcs->channel + 1, CAPIMSG_HANDLE_REQ(req), - (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) ? - CapiFlagsNotSupportedByProtocol : - CAPI_NOERROR); -} -EXPORT_SYMBOL_GPL(gigaset_skb_sent); - -/** - * gigaset_skb_rcvd() - pass received skb to LL - * @bcs: B channel descriptor structure. - * @skb: received data. - * - * Called by hardware module {bas,ser,usb}_gigaset when user data has - * been successfully received, for passing to the LL. - * Warning: skb must not be accessed anymore! - */ -void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap = bcs->ap; - int len = skb->len; - - /* update statistics */ - bcs->trans_down++; - - if (!ap) { - gig_dbg(DEBUG_MCMD, "%s: application gone", __func__); - dev_kfree_skb_any(skb); - return; - } - - /* don't send further B3 messages if disconnected */ - if (bcs->apconnstate < APCONN_ACTIVE) { - gig_dbg(DEBUG_MCMD, "%s: disconnected", __func__); - dev_kfree_skb_any(skb); - return; - } - - /* - * prepend DATA_B3_IND message to payload - * Parameters: NCCI = 1, all others 0/unused - * frequent message, avoid _cmsg overhead - */ - skb_push(skb, CAPI_DATA_B3_REQ_LEN); - CAPIMSG_SETLEN(skb->data, CAPI_DATA_B3_REQ_LEN); - CAPIMSG_SETAPPID(skb->data, ap->id); - CAPIMSG_SETCOMMAND(skb->data, CAPI_DATA_B3); - CAPIMSG_SETSUBCOMMAND(skb->data, CAPI_IND); - CAPIMSG_SETMSGID(skb->data, ap->nextMessageNumber++); - CAPIMSG_SETCONTROLLER(skb->data, iif->ctr.cnr); - CAPIMSG_SETPLCI_PART(skb->data, bcs->channel + 1); - CAPIMSG_SETNCCI_PART(skb->data, 1); - /* Data parameter not used */ - CAPIMSG_SETDATALEN(skb->data, len); - /* Data handle parameter not used */ - CAPIMSG_SETFLAGS(skb->data, 0); - /* Data64 parameter not present */ - - /* emit message */ - dump_rawmsg(DEBUG_MCMD, __func__, skb->data); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} -EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); - -/** - * gigaset_isdn_rcv_err() - signal receive error - * @bcs: B channel descriptor structure. - * - * Called by hardware module {bas,ser,usb}_gigaset when a receive error - * has occurred, for signalling to the LL. - */ -void gigaset_isdn_rcv_err(struct bc_state *bcs) -{ - /* if currently ignoring packets, just count down */ - if (bcs->ignore) { - bcs->ignore--; - return; - } - - /* update statistics */ - bcs->corrupted++; - - /* ToDo: signal error -> LL */ -} -EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); - -/** - * gigaset_isdn_icall() - signal incoming call - * @at_state: connection state structure. - * - * Called by main module at tasklet level to notify the LL that an incoming - * call has been received. @at_state contains the parameters of the call. - * - * Return value: call disposition (ICALL_*) - */ -int gigaset_isdn_icall(struct at_state_t *at_state) -{ - struct cardstate *cs = at_state->cs; - struct bc_state *bcs = at_state->bcs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap; - u32 actCIPmask; - struct sk_buff *skb; - unsigned int msgsize; - unsigned long flags; - int i; - - /* - * ToDo: signal calls without a free B channel, too - * (requires a u8 handle for the at_state structure that can - * be stored in the PLCI and used in the CONNECT_RESP message - * handler to retrieve it) - */ - if (!bcs) - return ICALL_IGNORE; - - /* prepare CONNECT_IND message, using B channel number as PLCI */ - capi_cmsg_header(&iif->hcmsg, 0, CAPI_CONNECT, CAPI_IND, 0, - iif->ctr.cnr | ((bcs->channel + 1) << 8)); - - /* minimum size, all structs empty */ - msgsize = CAPI_CONNECT_IND_BASELEN; - - /* Bearer Capability (mandatory) */ - if (at_state->str_var[STR_ZBC]) { - /* pass on BC from Gigaset */ - if (encode_ie(at_state->str_var[STR_ZBC], iif->bc_buf, - MAX_BC_OCTETS) < 0) { - dev_warn(cs->dev, "RING ignored - bad BC %s\n", - at_state->str_var[STR_ZBC]); - return ICALL_IGNORE; - } - - /* look up corresponding CIP value */ - iif->hcmsg.CIPValue = 0; /* default if nothing found */ - for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) - if (cip2bchlc[i].bc != NULL && - cip2bchlc[i].hlc == NULL && - !strcmp(cip2bchlc[i].bc, - at_state->str_var[STR_ZBC])) { - iif->hcmsg.CIPValue = i; - break; - } - } else { - /* no BC (internal call): assume CIP 1 (speech, A-law) */ - iif->hcmsg.CIPValue = 1; - encode_ie(cip2bchlc[1].bc, iif->bc_buf, MAX_BC_OCTETS); - } - iif->hcmsg.BC = iif->bc_buf; - msgsize += iif->hcmsg.BC[0]; - - /* High Layer Compatibility (optional) */ - if (at_state->str_var[STR_ZHLC]) { - /* pass on HLC from Gigaset */ - if (encode_ie(at_state->str_var[STR_ZHLC], iif->hlc_buf, - MAX_HLC_OCTETS) < 0) { - dev_warn(cs->dev, "RING ignored - bad HLC %s\n", - at_state->str_var[STR_ZHLC]); - return ICALL_IGNORE; - } - iif->hcmsg.HLC = iif->hlc_buf; - msgsize += iif->hcmsg.HLC[0]; - - /* look up corresponding CIP value */ - /* keep BC based CIP value if none found */ - if (at_state->str_var[STR_ZBC]) - for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) - if (cip2bchlc[i].hlc != NULL && - !strcmp(cip2bchlc[i].hlc, - at_state->str_var[STR_ZHLC]) && - !strcmp(cip2bchlc[i].bc, - at_state->str_var[STR_ZBC])) { - iif->hcmsg.CIPValue = i; - break; - } - } - - /* Called Party Number (optional) */ - if (at_state->str_var[STR_ZCPN]) { - i = strlen(at_state->str_var[STR_ZCPN]); - if (i > MAX_NUMBER_DIGITS) { - dev_warn(cs->dev, "RING ignored - bad number %s\n", - at_state->str_var[STR_ZBC]); - return ICALL_IGNORE; - } - iif->cdpty_buf[0] = i + 1; - iif->cdpty_buf[1] = 0x80; /* type / numbering plan unknown */ - memcpy(iif->cdpty_buf + 2, at_state->str_var[STR_ZCPN], i); - iif->hcmsg.CalledPartyNumber = iif->cdpty_buf; - msgsize += iif->hcmsg.CalledPartyNumber[0]; - } - - /* Calling Party Number (optional) */ - if (at_state->str_var[STR_NMBR]) { - i = strlen(at_state->str_var[STR_NMBR]); - if (i > MAX_NUMBER_DIGITS) { - dev_warn(cs->dev, "RING ignored - bad number %s\n", - at_state->str_var[STR_ZBC]); - return ICALL_IGNORE; - } - iif->cgpty_buf[0] = i + 2; - iif->cgpty_buf[1] = 0x00; /* type / numbering plan unknown */ - iif->cgpty_buf[2] = 0x80; /* pres. allowed, not screened */ - memcpy(iif->cgpty_buf + 3, at_state->str_var[STR_NMBR], i); - iif->hcmsg.CallingPartyNumber = iif->cgpty_buf; - msgsize += iif->hcmsg.CallingPartyNumber[0]; - } - - /* remaining parameters (not supported, always left NULL): - * - CalledPartySubaddress - * - CallingPartySubaddress - * - AdditionalInfo - * - BChannelinformation - * - Keypadfacility - * - Useruserdata - * - Facilitydataarray - */ - - gig_dbg(DEBUG_CMD, "icall: PLCI %x CIP %d BC %s", - iif->hcmsg.adr.adrPLCI, iif->hcmsg.CIPValue, - format_ie(iif->hcmsg.BC)); - gig_dbg(DEBUG_CMD, "icall: HLC %s", - format_ie(iif->hcmsg.HLC)); - gig_dbg(DEBUG_CMD, "icall: CgPty %s", - format_ie(iif->hcmsg.CallingPartyNumber)); - gig_dbg(DEBUG_CMD, "icall: CdPty %s", - format_ie(iif->hcmsg.CalledPartyNumber)); - - /* scan application list for matching listeners */ - spin_lock_irqsave(&bcs->aplock, flags); - if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) { - dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", - __func__, bcs->ap, bcs->apconnstate); - bcs->ap = NULL; - bcs->apconnstate = APCONN_NONE; - } - spin_unlock_irqrestore(&bcs->aplock, flags); - actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); - list_for_each_entry(ap, &iif->appls, ctrlist) - if (actCIPmask & ap->listenCIPmask) { - /* build CONNECT_IND message for this application */ - iif->hcmsg.ApplId = ap->id; - iif->hcmsg.Messagenumber = ap->nextMessageNumber++; - - skb = alloc_skb(msgsize, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", - __func__); - break; - } - if (capi_cmsg2message(&iif->hcmsg, - __skb_put(skb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", - __func__); - dev_kfree_skb_any(skb); - break; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - - /* add to listeners on this B channel, update state */ - spin_lock_irqsave(&bcs->aplock, flags); - ap->bcnext = bcs->ap; - bcs->ap = ap; - bcs->chstate |= CHS_NOTIFY_LL; - bcs->apconnstate = APCONN_SETUP; - spin_unlock_irqrestore(&bcs->aplock, flags); - - /* emit message */ - capi_ctr_handle_message(&iif->ctr, ap->id, skb); - } - - /* - * Return "accept" if any listeners. - * Gigaset will send ALERTING. - * There doesn't seem to be a way to avoid this. - */ - return bcs->ap ? ICALL_ACCEPT : ICALL_IGNORE; -} - -/* - * send a DISCONNECT_IND message to an application - * does not sleep, clobbers the controller's hcmsg structure - */ -static void send_disconnect_ind(struct bc_state *bcs, - struct gigaset_capi_appl *ap, u16 reason) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct sk_buff *skb; - - if (bcs->apconnstate == APCONN_NONE) - return; - - capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8)); - iif->hcmsg.Reason = reason; - skb = alloc_skb(CAPI_DISCONNECT_IND_LEN, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, - __skb_put(skb, CAPI_DISCONNECT_IND_LEN))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/* - * send a DISCONNECT_B3_IND message to an application - * Parameters: NCCI = 1, NCPI empty, Reason_B3 = 0 - * does not sleep, clobbers the controller's hcmsg structure - */ -static void send_disconnect_b3_ind(struct bc_state *bcs, - struct gigaset_capi_appl *ap) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct sk_buff *skb; - - /* nothing to do if no logical connection active */ - if (bcs->apconnstate < APCONN_ACTIVE) - return; - bcs->apconnstate = APCONN_SETUP; - - capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); - skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, - __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/** - * gigaset_isdn_connD() - signal D channel connect - * @bcs: B channel descriptor structure. - * - * Called by main module at tasklet level to notify the LL that the D channel - * connection has been established. - */ -void gigaset_isdn_connD(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap; - struct sk_buff *skb; - unsigned int msgsize; - unsigned long flags; - - spin_lock_irqsave(&bcs->aplock, flags); - ap = bcs->ap; - if (!ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - gig_dbg(DEBUG_CMD, "%s: application gone", __func__); - return; - } - if (bcs->apconnstate == APCONN_NONE) { - spin_unlock_irqrestore(&bcs->aplock, flags); - dev_warn(cs->dev, "%s: application %u not connected\n", - __func__, ap->id); - return; - } - spin_unlock_irqrestore(&bcs->aplock, flags); - while (ap->bcnext) { - /* this should never happen */ - dev_warn(cs->dev, "%s: dropping extra application %u\n", - __func__, ap->bcnext->id); - send_disconnect_ind(bcs, ap->bcnext, - CapiCallGivenToOtherApplication); - ap->bcnext = ap->bcnext->bcnext; - } - - /* prepare CONNECT_ACTIVE_IND message - * Note: LLC not supported by device - */ - capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_CONNECT_ACTIVE, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8)); - - /* minimum size, all structs empty */ - msgsize = CAPI_CONNECT_ACTIVE_IND_BASELEN; - - /* ToDo: set parameter: Connected number - * (requires ev-layer state machine extension to collect - * ZCON device reply) - */ - - /* build and emit CONNECT_ACTIVE_IND message */ - skb = alloc_skb(msgsize, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/** - * gigaset_isdn_hupD() - signal D channel hangup - * @bcs: B channel descriptor structure. - * - * Called by main module at tasklet level to notify the LL that the D channel - * connection has been shut down. - */ -void gigaset_isdn_hupD(struct bc_state *bcs) -{ - struct gigaset_capi_appl *ap; - unsigned long flags; - - /* - * ToDo: pass on reason code reported by device - * (requires ev-layer state machine extension to collect - * ZCAU device reply) - */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - ap = bcs->ap; - bcs->ap = ap->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); - send_disconnect_b3_ind(bcs, ap); - send_disconnect_ind(bcs, ap, 0); - spin_lock_irqsave(&bcs->aplock, flags); - } - bcs->apconnstate = APCONN_NONE; - spin_unlock_irqrestore(&bcs->aplock, flags); -} - -/** - * gigaset_isdn_connB() - signal B channel connect - * @bcs: B channel descriptor structure. - * - * Called by main module at tasklet level to notify the LL that the B channel - * connection has been established. - */ -void gigaset_isdn_connB(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_ctr *iif = cs->iif; - struct gigaset_capi_appl *ap; - struct sk_buff *skb; - unsigned long flags; - unsigned int msgsize; - u8 command; - - spin_lock_irqsave(&bcs->aplock, flags); - ap = bcs->ap; - if (!ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - gig_dbg(DEBUG_CMD, "%s: application gone", __func__); - return; - } - if (!bcs->apconnstate) { - spin_unlock_irqrestore(&bcs->aplock, flags); - dev_warn(cs->dev, "%s: application %u not connected\n", - __func__, ap->id); - return; - } - - /* - * emit CONNECT_B3_ACTIVE_IND if we already got CONNECT_B3_REQ; - * otherwise we have to emit CONNECT_B3_IND first, and follow up with - * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP - * Parameters in both cases always: NCCI = 1, NCPI empty - */ - if (bcs->apconnstate >= APCONN_ACTIVE) { - command = CAPI_CONNECT_B3_ACTIVE; - msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; - } else { - command = CAPI_CONNECT_B3; - msgsize = CAPI_CONNECT_B3_IND_BASELEN; - } - bcs->apconnstate = APCONN_ACTIVE; - - spin_unlock_irqrestore(&bcs->aplock, flags); - - while (ap->bcnext) { - /* this should never happen */ - dev_warn(cs->dev, "%s: dropping extra application %u\n", - __func__, ap->bcnext->id); - send_disconnect_ind(bcs, ap->bcnext, - CapiCallGivenToOtherApplication); - ap->bcnext = ap->bcnext->bcnext; - } - - capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, - ap->nextMessageNumber++, - iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); - skb = alloc_skb(msgsize, GFP_ATOMIC); - if (!skb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/** - * gigaset_isdn_hupB() - signal B channel hangup - * @bcs: B channel descriptor structure. - * - * Called by main module to notify the LL that the B channel connection has - * been shut down. - */ -void gigaset_isdn_hupB(struct bc_state *bcs) -{ - struct gigaset_capi_appl *ap = bcs->ap; - - /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ - - if (!ap) { - gig_dbg(DEBUG_CMD, "%s: application gone", __func__); - return; - } - - send_disconnect_b3_ind(bcs, ap); -} - -/** - * gigaset_isdn_start() - signal device availability - * @cs: device descriptor structure. - * - * Called by main module to notify the LL that the device is available for - * use. - */ -void gigaset_isdn_start(struct cardstate *cs) -{ - struct gigaset_capi_ctr *iif = cs->iif; - - /* fill profile data: manufacturer name */ - strcpy(iif->ctr.manu, "Siemens"); - /* CAPI and device version */ - iif->ctr.version.majorversion = 2; /* CAPI 2.0 */ - iif->ctr.version.minorversion = 0; - /* ToDo: check/assert cs->gotfwver? */ - iif->ctr.version.majormanuversion = cs->fwver[0]; - iif->ctr.version.minormanuversion = cs->fwver[1]; - /* number of B channels supported */ - iif->ctr.profile.nbchannel = cs->channels; - /* global options: internal controller, supplementary services */ - iif->ctr.profile.goptions = 0x11; - /* B1 protocols: 64 kbit/s HDLC or transparent */ - iif->ctr.profile.support1 = 0x03; - /* B2 protocols: transparent only */ - /* ToDo: X.75 SLP ? */ - iif->ctr.profile.support2 = 0x02; - /* B3 protocols: transparent only */ - iif->ctr.profile.support3 = 0x01; - /* no serial number */ - strcpy(iif->ctr.serial, "0"); - capi_ctr_ready(&iif->ctr); -} - -/** - * gigaset_isdn_stop() - signal device unavailability - * @cs: device descriptor structure. - * - * Called by main module to notify the LL that the device is no longer - * available for use. - */ -void gigaset_isdn_stop(struct cardstate *cs) -{ - struct gigaset_capi_ctr *iif = cs->iif; - capi_ctr_down(&iif->ctr); -} - -/* - * kernel CAPI callback methods - * ============================ - */ - -/* - * register CAPI application - */ -static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, - capi_register_params *rp) -{ - struct gigaset_capi_ctr *iif - = container_of(ctr, struct gigaset_capi_ctr, ctr); - struct cardstate *cs = ctr->driverdata; - struct gigaset_capi_appl *ap; - - gig_dbg(DEBUG_CMD, "%s [%u] l3cnt=%u blkcnt=%u blklen=%u", - __func__, appl, rp->level3cnt, rp->datablkcnt, rp->datablklen); - - list_for_each_entry(ap, &iif->appls, ctrlist) - if (ap->id == appl) { - dev_notice(cs->dev, - "application %u already registered\n", appl); - return; - } - - ap = kzalloc(sizeof(*ap), GFP_KERNEL); - if (!ap) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - ap->id = appl; - ap->rp = *rp; - - list_add(&ap->ctrlist, &iif->appls); - dev_info(cs->dev, "application %u registered\n", ap->id); -} - -/* - * remove CAPI application from channel - * helper function to keep indentation levels down and stay in 80 columns - */ - -static inline void remove_appl_from_channel(struct bc_state *bcs, - struct gigaset_capi_appl *ap) -{ - struct cardstate *cs = bcs->cs; - struct gigaset_capi_appl *bcap; - unsigned long flags; - int prevconnstate; - - spin_lock_irqsave(&bcs->aplock, flags); - bcap = bcs->ap; - if (bcap == NULL) { - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - - /* check first application on channel */ - if (bcap == ap) { - bcs->ap = ap->bcnext; - if (bcs->ap != NULL) { - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - - /* none left, clear channel state */ - prevconnstate = bcs->apconnstate; - bcs->apconnstate = APCONN_NONE; - spin_unlock_irqrestore(&bcs->aplock, flags); - - if (prevconnstate == APCONN_ACTIVE) { - dev_notice(cs->dev, "%s: hanging up channel %u\n", - __func__, bcs->channel); - gigaset_add_event(cs, &bcs->at_state, - EV_HUP, NULL, 0, NULL); - gigaset_schedule_event(cs); - } - return; - } - - /* check remaining list */ - do { - if (bcap->bcnext == ap) { - bcap->bcnext = bcap->bcnext->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - bcap = bcap->bcnext; - } while (bcap != NULL); - spin_unlock_irqrestore(&bcs->aplock, flags); -} - -/* - * release CAPI application - */ -static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) -{ - struct gigaset_capi_ctr *iif - = container_of(ctr, struct gigaset_capi_ctr, ctr); - struct cardstate *cs = iif->ctr.driverdata; - struct gigaset_capi_appl *ap, *tmp; - unsigned ch; - - gig_dbg(DEBUG_CMD, "%s [%u]", __func__, appl); - - list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) - if (ap->id == appl) { - /* remove from any channels */ - for (ch = 0; ch < cs->channels; ch++) - remove_appl_from_channel(&cs->bcs[ch], ap); - - /* remove from registration list */ - list_del(&ap->ctrlist); - kfree(ap); - dev_info(cs->dev, "application %u released\n", appl); - } -} - -/* - * ===================================================================== - * outgoing CAPI message handler - * ===================================================================== - */ - -/* - * helper function: emit reply message with given Info value - */ -static void send_conf(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb, - u16 info) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* - * _CONF replies always only have NCCI and Info parameters - * so they'll fit into the _REQ message skb - */ - capi_cmsg_answer(&iif->acmsg); - iif->acmsg.Info = info; - if (capi_cmsg2message(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - __skb_trim(skb, CAPI_STDCONF_LEN); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/* - * process FACILITY_REQ message - */ -static void do_facility_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct sk_buff *cskb; - u8 *pparam; - unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; - u16 function, info; - static u8 confparam[10]; /* max. 9 octets + length byte */ - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* - * Facility Request Parameter is not decoded by capi_message2cmsg() - * encoding depends on Facility Selector - */ - switch (cmsg->FacilitySelector) { - case CAPI_FACILITY_DTMF: /* ToDo */ - info = CapiFacilityNotSupported; - confparam[0] = 2; /* length */ - /* DTMF information: Unknown DTMF request */ - capimsg_setu16(confparam, 1, 2); - break; - - case CAPI_FACILITY_V42BIS: /* not supported */ - info = CapiFacilityNotSupported; - confparam[0] = 2; /* length */ - /* V.42 bis information: not available */ - capimsg_setu16(confparam, 1, 1); - break; - - case CAPI_FACILITY_SUPPSVC: - /* decode Function parameter */ - pparam = cmsg->FacilityRequestParameter; - if (pparam == NULL || pparam[0] < 2) { - dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", - "Facility Request Parameter"); - send_conf(iif, ap, skb, CapiIllMessageParmCoding); - return; - } - function = CAPIMSG_U16(pparam, 1); - switch (function) { - case CAPI_SUPPSVC_GETSUPPORTED: - info = CapiSuccess; - /* Supplementary Service specific parameter */ - confparam[3] = 6; /* length */ - /* Supplementary services info: Success */ - capimsg_setu16(confparam, 4, CapiSuccess); - /* Supported Services: none */ - capimsg_setu32(confparam, 6, 0); - break; - case CAPI_SUPPSVC_LISTEN: - if (pparam[0] < 7 || pparam[3] < 4) { - dev_notice(cs->dev, "%s: %s missing\n", - "FACILITY_REQ", "Notification Mask"); - send_conf(iif, ap, skb, - CapiIllMessageParmCoding); - return; - } - if (CAPIMSG_U32(pparam, 4) != 0) { - dev_notice(cs->dev, - "%s: unsupported supplementary service notification mask 0x%x\n", - "FACILITY_REQ", CAPIMSG_U32(pparam, 4)); - info = CapiFacilitySpecificFunctionNotSupported; - confparam[3] = 2; /* length */ - capimsg_setu16(confparam, 4, - CapiSupplementaryServiceNotSupported); - break; - } - info = CapiSuccess; - confparam[3] = 2; /* length */ - capimsg_setu16(confparam, 4, CapiSuccess); - break; - - /* ToDo: add supported services */ - - default: - dev_notice(cs->dev, - "%s: unsupported supplementary service function 0x%04x\n", - "FACILITY_REQ", function); - info = CapiFacilitySpecificFunctionNotSupported; - /* Supplementary Service specific parameter */ - confparam[3] = 2; /* length */ - /* Supplementary services info: not supported */ - capimsg_setu16(confparam, 4, - CapiSupplementaryServiceNotSupported); - } - - /* Facility confirmation parameter */ - confparam[0] = confparam[3] + 3; /* total length */ - /* Function: copy from _REQ message */ - capimsg_setu16(confparam, 1, function); - /* Supplementary Service specific parameter already set above */ - break; - - case CAPI_FACILITY_WAKEUP: /* ToDo */ - info = CapiFacilityNotSupported; - confparam[0] = 2; /* length */ - /* Number of accepted awake request parameters: 0 */ - capimsg_setu16(confparam, 1, 0); - break; - - default: - info = CapiFacilityNotSupported; - confparam[0] = 0; /* empty struct */ - } - - /* send FACILITY_CONF with given Info and confirmation parameter */ - dev_kfree_skb_any(skb); - capi_cmsg_answer(cmsg); - cmsg->Info = info; - cmsg->FacilityConfirmationParameter = confparam; - msgsize += confparam[0]; /* length */ - cskb = alloc_skb(msgsize, GFP_ATOMIC); - if (!cskb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (capi_cmsg2message(cmsg, __skb_put(cskb, msgsize))) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(cskb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, cskb); -} - - -/* - * process LISTEN_REQ message - * just store the masks in the application data structure - */ -static void do_listen_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - - /* store listening parameters */ - ap->listenInfoMask = iif->acmsg.InfoMask; - ap->listenCIPmask = iif->acmsg.CIPmask; - send_conf(iif, ap, skb, CapiSuccess); -} - -/* - * process ALERT_REQ message - * nothing to do, Gigaset always alerts anyway - */ -static void do_alert_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - send_conf(iif, ap, skb, CapiAlertAlreadySent); -} - -/* - * process CONNECT_REQ message - * allocate a B channel, prepare dial commands, queue a DIAL event, - * emit CONNECT_CONF reply - */ -static void do_connect_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - char **commands; - char *s; - u8 *pp; - unsigned long flags; - int i, l, lbc, lhlc; - u16 info; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* get free B channel & construct PLCI */ - bcs = gigaset_get_free_channel(cs); - if (!bcs) { - dev_notice(cs->dev, "%s: no B channel available\n", - "CONNECT_REQ"); - send_conf(iif, ap, skb, CapiNoPlciAvailable); - return; - } - spin_lock_irqsave(&bcs->aplock, flags); - if (bcs->ap != NULL || bcs->apconnstate != APCONN_NONE) - dev_warn(cs->dev, "%s: channel not properly cleared (%p/%d)\n", - __func__, bcs->ap, bcs->apconnstate); - ap->bcnext = NULL; - bcs->ap = ap; - bcs->apconnstate = APCONN_SETUP; - spin_unlock_irqrestore(&bcs->aplock, flags); - - bcs->rx_bufsize = ap->rp.datablklen; - dev_kfree_skb(bcs->rx_skb); - gigaset_new_rx_skb(bcs); - cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; - - /* build command table */ - commands = kcalloc(AT_NUM, sizeof(*commands), GFP_KERNEL); - if (!commands) - goto oom; - - /* encode parameter: Called party number */ - pp = cmsg->CalledPartyNumber; - if (pp == NULL || *pp == 0) { - dev_notice(cs->dev, "%s: %s missing\n", - "CONNECT_REQ", "Called party number"); - info = CapiIllMessageParmCoding; - goto error; - } - l = *pp++; - /* check type of number/numbering plan byte */ - switch (*pp) { - case 0x80: /* unknown type / unknown numbering plan */ - case 0x81: /* unknown type / ISDN/Telephony numbering plan */ - break; - default: /* others: warn about potential misinterpretation */ - dev_notice(cs->dev, "%s: %s type/plan 0x%02x unsupported\n", - "CONNECT_REQ", "Called party number", *pp); - } - pp++; - l--; - /* translate "**" internal call prefix to CTP value */ - if (l >= 2 && pp[0] == '*' && pp[1] == '*') { - s = "^SCTP=0\r"; - pp += 2; - l -= 2; - } else { - s = "^SCTP=1\r"; - } - commands[AT_TYPE] = kstrdup(s, GFP_KERNEL); - if (!commands[AT_TYPE]) - goto oom; - commands[AT_DIAL] = kmalloc(l + 3, GFP_KERNEL); - if (!commands[AT_DIAL]) - goto oom; - snprintf(commands[AT_DIAL], l + 3, "D%.*s\r", l, pp); - - /* encode parameter: Calling party number */ - pp = cmsg->CallingPartyNumber; - if (pp != NULL && *pp > 0) { - l = *pp++; - - /* check type of number/numbering plan byte */ - /* ToDo: allow for/handle Ext=1? */ - switch (*pp) { - case 0x00: /* unknown type / unknown numbering plan */ - case 0x01: /* unknown type / ISDN/Telephony num. plan */ - break; - default: - dev_notice(cs->dev, - "%s: %s type/plan 0x%02x unsupported\n", - "CONNECT_REQ", "Calling party number", *pp); - } - pp++; - l--; - - /* check presentation indicator */ - if (!l) { - dev_notice(cs->dev, "%s: %s IE truncated\n", - "CONNECT_REQ", "Calling party number"); - info = CapiIllMessageParmCoding; - goto error; - } - switch (*pp & 0xfc) { /* ignore Screening indicator */ - case 0x80: /* Presentation allowed */ - s = "^SCLIP=1\r"; - break; - case 0xa0: /* Presentation restricted */ - s = "^SCLIP=0\r"; - break; - default: - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_REQ", - "Presentation/Screening indicator", - *pp); - s = "^SCLIP=1\r"; - } - commands[AT_CLIP] = kstrdup(s, GFP_KERNEL); - if (!commands[AT_CLIP]) - goto oom; - pp++; - l--; - - if (l) { - /* number */ - commands[AT_MSN] = kmalloc(l + 8, GFP_KERNEL); - if (!commands[AT_MSN]) - goto oom; - snprintf(commands[AT_MSN], l + 8, "^SMSN=%*s\r", l, pp); - } - } - - /* check parameter: CIP Value */ - if (cmsg->CIPValue >= ARRAY_SIZE(cip2bchlc) || - (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) { - dev_notice(cs->dev, "%s: unknown CIP value %d\n", - "CONNECT_REQ", cmsg->CIPValue); - info = CapiCipValueUnknown; - goto error; - } - - /* - * check/encode parameters: BC & HLC - * must be encoded together as device doesn't accept HLC separately - * explicit parameters override values derived from CIP - */ - - /* determine lengths */ - if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ - lbc = 2 * cmsg->BC[0]; - else if (cip2bchlc[cmsg->CIPValue].bc) /* BC derived from CIP */ - lbc = strlen(cip2bchlc[cmsg->CIPValue].bc); - else /* no BC */ - lbc = 0; - if (cmsg->HLC && cmsg->HLC[0]) /* HLC specified explicitly */ - lhlc = 2 * cmsg->HLC[0]; - else if (cip2bchlc[cmsg->CIPValue].hlc) /* HLC derived from CIP */ - lhlc = strlen(cip2bchlc[cmsg->CIPValue].hlc); - else /* no HLC */ - lhlc = 0; - - if (lbc) { - /* have BC: allocate and assemble command string */ - l = lbc + 7; /* "^SBC=" + value + "\r" + null byte */ - if (lhlc) - l += lhlc + 7; /* ";^SHLC=" + value */ - commands[AT_BC] = kmalloc(l, GFP_KERNEL); - if (!commands[AT_BC]) - goto oom; - strcpy(commands[AT_BC], "^SBC="); - if (cmsg->BC && cmsg->BC[0]) /* BC specified explicitly */ - decode_ie(cmsg->BC, commands[AT_BC] + 5); - else /* BC derived from CIP */ - strcpy(commands[AT_BC] + 5, - cip2bchlc[cmsg->CIPValue].bc); - if (lhlc) { - strcpy(commands[AT_BC] + lbc + 5, ";^SHLC="); - if (cmsg->HLC && cmsg->HLC[0]) - /* HLC specified explicitly */ - decode_ie(cmsg->HLC, - commands[AT_BC] + lbc + 12); - else /* HLC derived from CIP */ - strcpy(commands[AT_BC] + lbc + 12, - cip2bchlc[cmsg->CIPValue].hlc); - } - strcpy(commands[AT_BC] + l - 2, "\r"); - } else { - /* no BC */ - if (lhlc) { - dev_notice(cs->dev, "%s: cannot set HLC without BC\n", - "CONNECT_REQ"); - info = CapiIllMessageParmCoding; /* ? */ - goto error; - } - } - - /* check/encode parameter: B Protocol */ - if (cmsg->BProtocol == CAPI_DEFAULT) { - bcs->proto2 = L2_HDLC; - dev_warn(cs->dev, - "B2 Protocol X.75 SLP unsupported, using Transparent\n"); - } else { - switch (cmsg->B1protocol) { - case 0: - bcs->proto2 = L2_HDLC; - break; - case 1: - bcs->proto2 = L2_VOICE; - break; - default: - dev_warn(cs->dev, - "B1 Protocol %u unsupported, using Transparent\n", - cmsg->B1protocol); - bcs->proto2 = L2_VOICE; - } - if (cmsg->B2protocol != 1) - dev_warn(cs->dev, - "B2 Protocol %u unsupported, using Transparent\n", - cmsg->B2protocol); - if (cmsg->B3protocol != 0) - dev_warn(cs->dev, - "B3 Protocol %u unsupported, using Transparent\n", - cmsg->B3protocol); - ignore_cstruct_param(cs, cmsg->B1configuration, - "CONNECT_REQ", "B1 Configuration"); - ignore_cstruct_param(cs, cmsg->B2configuration, - "CONNECT_REQ", "B2 Configuration"); - ignore_cstruct_param(cs, cmsg->B3configuration, - "CONNECT_REQ", "B3 Configuration"); - } - commands[AT_PROTO] = kmalloc(9, GFP_KERNEL); - if (!commands[AT_PROTO]) - goto oom; - snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); - - /* ToDo: check/encode remaining parameters */ - ignore_cstruct_param(cs, cmsg->CalledPartySubaddress, - "CONNECT_REQ", "Called pty subaddr"); - ignore_cstruct_param(cs, cmsg->CallingPartySubaddress, - "CONNECT_REQ", "Calling pty subaddr"); - ignore_cstruct_param(cs, cmsg->LLC, - "CONNECT_REQ", "LLC"); - if (cmsg->AdditionalInfo != CAPI_DEFAULT) { - ignore_cstruct_param(cs, cmsg->BChannelinformation, - "CONNECT_REQ", "B Channel Information"); - ignore_cstruct_param(cs, cmsg->Keypadfacility, - "CONNECT_REQ", "Keypad Facility"); - ignore_cstruct_param(cs, cmsg->Useruserdata, - "CONNECT_REQ", "User-User Data"); - ignore_cstruct_param(cs, cmsg->Facilitydataarray, - "CONNECT_REQ", "Facility Data Array"); - } - - /* encode parameter: B channel to use */ - commands[AT_ISO] = kmalloc(9, GFP_KERNEL); - if (!commands[AT_ISO]) - goto oom; - snprintf(commands[AT_ISO], 9, "^SISO=%u\r", - (unsigned) bcs->channel + 1); - - /* queue & schedule EV_DIAL event */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, - bcs->at_state.seq_index, NULL)) { - info = CAPI_MSGOSRESOURCEERR; - goto error; - } - gigaset_schedule_event(cs); - send_conf(iif, ap, skb, CapiSuccess); - return; - -oom: - dev_err(cs->dev, "%s: out of memory\n", __func__); - info = CAPI_MSGOSRESOURCEERR; -error: - if (commands) - for (i = 0; i < AT_NUM; i++) - kfree(commands[i]); - kfree(commands); - gigaset_free_channel(bcs); - send_conf(iif, ap, skb, info); -} - -/* - * process CONNECT_RESP message - * checks protocol parameters and queues an ACCEPT or HUP event - */ -static void do_connect_resp(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - struct gigaset_capi_appl *oap; - unsigned long flags; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - dev_kfree_skb_any(skb); - - /* extract and check channel number from PLCI */ - channel = (cmsg->adr.adrPLCI >> 8) & 0xff; - if (!channel || channel > cs->channels) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_RESP", "PLCI", cmsg->adr.adrPLCI); - return; - } - bcs = cs->bcs + channel - 1; - - switch (cmsg->Reject) { - case 0: /* Accept */ - /* drop all competing applications, keep only this one */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - oap = bcs->ap; - bcs->ap = oap->bcnext; - if (oap != ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - send_disconnect_ind(bcs, oap, - CapiCallGivenToOtherApplication); - spin_lock_irqsave(&bcs->aplock, flags); - } - } - ap->bcnext = NULL; - bcs->ap = ap; - spin_unlock_irqrestore(&bcs->aplock, flags); - - bcs->rx_bufsize = ap->rp.datablklen; - dev_kfree_skb(bcs->rx_skb); - gigaset_new_rx_skb(bcs); - bcs->chstate |= CHS_NOTIFY_LL; - - /* check/encode B channel protocol */ - if (cmsg->BProtocol == CAPI_DEFAULT) { - bcs->proto2 = L2_HDLC; - dev_warn(cs->dev, - "B2 Protocol X.75 SLP unsupported, using Transparent\n"); - } else { - switch (cmsg->B1protocol) { - case 0: - bcs->proto2 = L2_HDLC; - break; - case 1: - bcs->proto2 = L2_VOICE; - break; - default: - dev_warn(cs->dev, - "B1 Protocol %u unsupported, using Transparent\n", - cmsg->B1protocol); - bcs->proto2 = L2_VOICE; - } - if (cmsg->B2protocol != 1) - dev_warn(cs->dev, - "B2 Protocol %u unsupported, using Transparent\n", - cmsg->B2protocol); - if (cmsg->B3protocol != 0) - dev_warn(cs->dev, - "B3 Protocol %u unsupported, using Transparent\n", - cmsg->B3protocol); - ignore_cstruct_param(cs, cmsg->B1configuration, - "CONNECT_RESP", "B1 Configuration"); - ignore_cstruct_param(cs, cmsg->B2configuration, - "CONNECT_RESP", "B2 Configuration"); - ignore_cstruct_param(cs, cmsg->B3configuration, - "CONNECT_RESP", "B3 Configuration"); - } - - /* ToDo: check/encode remaining parameters */ - ignore_cstruct_param(cs, cmsg->ConnectedNumber, - "CONNECT_RESP", "Connected Number"); - ignore_cstruct_param(cs, cmsg->ConnectedSubaddress, - "CONNECT_RESP", "Connected Subaddress"); - ignore_cstruct_param(cs, cmsg->LLC, - "CONNECT_RESP", "LLC"); - if (cmsg->AdditionalInfo != CAPI_DEFAULT) { - ignore_cstruct_param(cs, cmsg->BChannelinformation, - "CONNECT_RESP", "BChannel Information"); - ignore_cstruct_param(cs, cmsg->Keypadfacility, - "CONNECT_RESP", "Keypad Facility"); - ignore_cstruct_param(cs, cmsg->Useruserdata, - "CONNECT_RESP", "User-User Data"); - ignore_cstruct_param(cs, cmsg->Facilitydataarray, - "CONNECT_RESP", "Facility Data Array"); - } - - /* Accept call */ - if (!gigaset_add_event(cs, &cs->bcs[channel - 1].at_state, - EV_ACCEPT, NULL, 0, NULL)) - return; - gigaset_schedule_event(cs); - return; - - case 1: /* Ignore */ - /* send DISCONNECT_IND to this application */ - send_disconnect_ind(bcs, ap, 0); - - /* remove it from the list of listening apps */ - spin_lock_irqsave(&bcs->aplock, flags); - if (bcs->ap == ap) { - bcs->ap = ap->bcnext; - if (bcs->ap == NULL) { - /* last one: stop ev-layer hupD notifications */ - bcs->apconnstate = APCONN_NONE; - bcs->chstate &= ~CHS_NOTIFY_LL; - } - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { - if (oap->bcnext == ap) { - oap->bcnext = oap->bcnext->bcnext; - spin_unlock_irqrestore(&bcs->aplock, flags); - return; - } - } - spin_unlock_irqrestore(&bcs->aplock, flags); - dev_err(cs->dev, "%s: application %u not found\n", - __func__, ap->id); - return; - - default: /* Reject */ - /* drop all competing applications, keep only this one */ - spin_lock_irqsave(&bcs->aplock, flags); - while (bcs->ap != NULL) { - oap = bcs->ap; - bcs->ap = oap->bcnext; - if (oap != ap) { - spin_unlock_irqrestore(&bcs->aplock, flags); - send_disconnect_ind(bcs, oap, - CapiCallGivenToOtherApplication); - spin_lock_irqsave(&bcs->aplock, flags); - } - } - ap->bcnext = NULL; - bcs->ap = ap; - spin_unlock_irqrestore(&bcs->aplock, flags); - - /* reject call - will trigger DISCONNECT_IND for this app */ - dev_info(cs->dev, "%s: Reject=%x\n", - "CONNECT_RESP", cmsg->Reject); - if (!gigaset_add_event(cs, &cs->bcs[channel - 1].at_state, - EV_HUP, NULL, 0, NULL)) - return; - gigaset_schedule_event(cs); - return; - } -} - -/* - * process CONNECT_B3_REQ message - * build NCCI and emit CONNECT_B3_CONF reply - */ -static void do_connect_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number from PLCI */ - channel = (cmsg->adr.adrPLCI >> 8) & 0xff; - if (!channel || channel > cs->channels) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = &cs->bcs[channel - 1]; - - /* mark logical connection active */ - bcs->apconnstate = APCONN_ACTIVE; - - /* build NCCI: always 1 (one B3 connection only) */ - cmsg->adr.adrNCCI |= 1 << 16; - - /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (cmsg->NCPI && cmsg->NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); -} - -/* - * process CONNECT_B3_RESP message - * Depending on the Reject parameter, either emit CONNECT_B3_ACTIVE_IND - * or queue EV_HUP and emit DISCONNECT_B3_IND. - * The emitted message is always shorter than the received one, - * allowing to reuse the skb. - */ -static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - int channel; - unsigned int msgsize; - u8 command; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number and NCCI */ - channel = (cmsg->adr.adrNCCI >> 8) & 0xff; - if (!channel || channel > cs->channels || - ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); - dev_kfree_skb_any(skb); - return; - } - bcs = &cs->bcs[channel - 1]; - - if (cmsg->Reject) { - /* Reject: clear B3 connect received flag */ - bcs->apconnstate = APCONN_SETUP; - - /* trigger hangup, causing eventual DISCONNECT_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, - EV_HUP, NULL, 0, NULL)) { - dev_kfree_skb_any(skb); - return; - } - gigaset_schedule_event(cs); - - /* emit DISCONNECT_B3_IND */ - command = CAPI_DISCONNECT_B3; - msgsize = CAPI_DISCONNECT_B3_IND_BASELEN; - } else { - /* - * Accept: emit CONNECT_B3_ACTIVE_IND immediately, as - * we only send CONNECT_B3_IND if the B channel is up - */ - command = CAPI_CONNECT_B3_ACTIVE; - msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; - } - capi_cmsg_header(cmsg, ap->id, command, CAPI_IND, - ap->nextMessageNumber++, cmsg->adr.adrNCCI); - __skb_trim(skb, msgsize); - if (capi_cmsg2message(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, skb); -} - -/* - * process DISCONNECT_REQ message - * schedule EV_HUP and emit DISCONNECT_B3_IND if necessary, - * emit DISCONNECT_CONF reply - */ -static void do_disconnect_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - _cmsg *b3cmsg; - struct sk_buff *b3skb; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number from PLCI */ - channel = (cmsg->adr.adrPLCI >> 8) & 0xff; - if (!channel || channel > cs->channels) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = cs->bcs + channel - 1; - - /* ToDo: process parameter: Additional info */ - if (cmsg->AdditionalInfo != CAPI_DEFAULT) { - ignore_cstruct_param(cs, cmsg->BChannelinformation, - "DISCONNECT_REQ", "B Channel Information"); - ignore_cstruct_param(cs, cmsg->Keypadfacility, - "DISCONNECT_REQ", "Keypad Facility"); - ignore_cstruct_param(cs, cmsg->Useruserdata, - "DISCONNECT_REQ", "User-User Data"); - ignore_cstruct_param(cs, cmsg->Facilitydataarray, - "DISCONNECT_REQ", "Facility Data Array"); - } - - /* skip if DISCONNECT_IND already sent */ - if (!bcs->apconnstate) - return; - - /* check for active logical connection */ - if (bcs->apconnstate >= APCONN_ACTIVE) { - /* clear it */ - bcs->apconnstate = APCONN_SETUP; - - /* - * emit DISCONNECT_B3_IND with cause 0x3301 - * use separate cmsg structure, as the content of iif->acmsg - * is still needed for creating the _CONF message - */ - b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL); - if (!b3cmsg) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, - ap->nextMessageNumber++, - cmsg->adr.adrPLCI | (1 << 16)); - b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; - b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); - if (b3skb == NULL) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - kfree(b3cmsg); - return; - } - if (capi_cmsg2message(b3cmsg, - __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN))) { - dev_err(cs->dev, "%s: message parser failure\n", - __func__); - kfree(b3cmsg); - dev_kfree_skb_any(b3skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, b3cmsg); - kfree(b3cmsg); - capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); - } - - /* trigger hangup, causing eventual DISCONNECT_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - gigaset_schedule_event(cs); - - /* emit reply */ - send_conf(iif, ap, skb, CapiSuccess); -} - -/* - * process DISCONNECT_B3_REQ message - * schedule EV_HUP and emit DISCONNECT_B3_CONF reply - */ -static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - _cmsg *cmsg = &iif->acmsg; - struct bc_state *bcs; - int channel; - - /* decode message */ - if (capi_message2cmsg(cmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, cmsg); - - /* extract and check channel number and NCCI */ - channel = (cmsg->adr.adrNCCI >> 8) & 0xff; - if (!channel || channel > cs->channels || - ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = &cs->bcs[channel - 1]; - - /* reject if logical connection not active */ - if (bcs->apconnstate < APCONN_ACTIVE) { - send_conf(iif, ap, skb, - CapiMessageNotSupportedInCurrentState); - return; - } - - /* trigger hangup, causing eventual DISCONNECT_B3_IND */ - if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - gigaset_schedule_event(cs); - - /* NCPI parameter: not applicable for B3 Transparent */ - ignore_cstruct_param(cs, cmsg->NCPI, - "DISCONNECT_B3_REQ", "NCPI"); - send_conf(iif, ap, skb, - (cmsg->NCPI && cmsg->NCPI[0]) ? - CapiNcpiNotSupportedByProtocol : CapiSuccess); -} - -/* - * process DATA_B3_REQ message - */ -static void do_data_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - struct bc_state *bcs; - int channel = CAPIMSG_PLCI_PART(skb->data); - u16 ncci = CAPIMSG_NCCI_PART(skb->data); - u16 msglen = CAPIMSG_LEN(skb->data); - u16 datalen = CAPIMSG_DATALEN(skb->data); - u16 flags = CAPIMSG_FLAGS(skb->data); - u16 msgid = CAPIMSG_MSGID(skb->data); - u16 handle = CAPIMSG_HANDLE_REQ(skb->data); - - /* frequent message, avoid _cmsg overhead */ - dump_rawmsg(DEBUG_MCMD, __func__, skb->data); - - /* check parameters */ - if (channel == 0 || channel > cs->channels || ncci != 1) { - dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", - "DATA_B3_REQ", "NCCI", CAPIMSG_NCCI(skb->data)); - send_conf(iif, ap, skb, CapiIllContrPlciNcci); - return; - } - bcs = &cs->bcs[channel - 1]; - if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) - dev_notice(cs->dev, "%s: unexpected length %d\n", - "DATA_B3_REQ", msglen); - if (msglen + datalen != skb->len) - dev_notice(cs->dev, "%s: length mismatch (%d+%d!=%d)\n", - "DATA_B3_REQ", msglen, datalen, skb->len); - if (msglen + datalen > skb->len) { - /* message too short for announced data length */ - send_conf(iif, ap, skb, CapiIllMessageParmCoding); /* ? */ - return; - } - if (flags & CAPI_FLAGS_RESERVED) { - dev_notice(cs->dev, "%s: reserved flags set (%x)\n", - "DATA_B3_REQ", flags); - send_conf(iif, ap, skb, CapiIllMessageParmCoding); - return; - } - - /* reject if logical connection not active */ - if (bcs->apconnstate < APCONN_ACTIVE) { - send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); - return; - } - - /* pull CAPI message into link layer header */ - skb_reset_mac_header(skb); - skb->mac_len = msglen; - skb_pull(skb, msglen); - - /* pass to device-specific module */ - if (cs->ops->send_skb(bcs, skb) < 0) { - send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); - return; - } - - /* - * DATA_B3_CONF will be sent by gigaset_skb_sent() only if "delivery - * confirmation" bit is set; otherwise we have to send it now - */ - if (!(flags & CAPI_FLAGS_DELIVERY_CONFIRMATION)) - send_data_b3_conf(cs, &iif->ctr, ap->id, msgid, channel, handle, - flags ? CapiFlagsNotSupportedByProtocol - : CAPI_NOERROR); -} - -/* - * process RESET_B3_REQ message - * just always reply "not supported by current protocol" - */ -static void do_reset_b3_req(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - send_conf(iif, ap, skb, - CapiResetProcedureNotSupportedByCurrentProtocol); -} - -/* - * unsupported CAPI message handler - */ -static void do_unsupported(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); -} - -/* - * CAPI message handler: no-op - */ -static void do_nothing(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - struct cardstate *cs = iif->ctr.driverdata; - - /* decode message */ - if (capi_message2cmsg(&iif->acmsg, skb->data)) { - dev_err(cs->dev, "%s: message parser failure\n", __func__); - dev_kfree_skb_any(skb); - return; - } - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - dev_kfree_skb_any(skb); -} - -static void do_data_b3_resp(struct gigaset_capi_ctr *iif, - struct gigaset_capi_appl *ap, - struct sk_buff *skb) -{ - dump_rawmsg(DEBUG_MCMD, __func__, skb->data); - dev_kfree_skb_any(skb); -} - -/* table of outgoing CAPI message handlers with lookup function */ -typedef void (*capi_send_handler_t)(struct gigaset_capi_ctr *, - struct gigaset_capi_appl *, - struct sk_buff *); - -static struct { - u16 cmd; - capi_send_handler_t handler; -} capi_send_handler_table[] = { - /* most frequent messages first for faster lookup */ - { CAPI_DATA_B3_REQ, do_data_b3_req }, - { CAPI_DATA_B3_RESP, do_data_b3_resp }, - - { CAPI_ALERT_REQ, do_alert_req }, - { CAPI_CONNECT_ACTIVE_RESP, do_nothing }, - { CAPI_CONNECT_B3_ACTIVE_RESP, do_nothing }, - { CAPI_CONNECT_B3_REQ, do_connect_b3_req }, - { CAPI_CONNECT_B3_RESP, do_connect_b3_resp }, - { CAPI_CONNECT_B3_T90_ACTIVE_RESP, do_nothing }, - { CAPI_CONNECT_REQ, do_connect_req }, - { CAPI_CONNECT_RESP, do_connect_resp }, - { CAPI_DISCONNECT_B3_REQ, do_disconnect_b3_req }, - { CAPI_DISCONNECT_B3_RESP, do_nothing }, - { CAPI_DISCONNECT_REQ, do_disconnect_req }, - { CAPI_DISCONNECT_RESP, do_nothing }, - { CAPI_FACILITY_REQ, do_facility_req }, - { CAPI_FACILITY_RESP, do_nothing }, - { CAPI_LISTEN_REQ, do_listen_req }, - { CAPI_SELECT_B_PROTOCOL_REQ, do_unsupported }, - { CAPI_RESET_B3_REQ, do_reset_b3_req }, - { CAPI_RESET_B3_RESP, do_nothing }, - - /* - * ToDo: support overlap sending (requires ev-layer state - * machine extension to generate additional ATD commands) - */ - { CAPI_INFO_REQ, do_unsupported }, - { CAPI_INFO_RESP, do_nothing }, - - /* - * ToDo: what's the proper response for these? - */ - { CAPI_MANUFACTURER_REQ, do_nothing }, - { CAPI_MANUFACTURER_RESP, do_nothing }, -}; - -/* look up handler */ -static inline capi_send_handler_t lookup_capi_send_handler(const u16 cmd) -{ - size_t i; - - for (i = 0; i < ARRAY_SIZE(capi_send_handler_table); i++) - if (capi_send_handler_table[i].cmd == cmd) - return capi_send_handler_table[i].handler; - return NULL; -} - - -/** - * gigaset_send_message() - accept a CAPI message from an application - * @ctr: controller descriptor structure. - * @skb: CAPI message. - * - * Return value: CAPI error code - * Note: capidrv (and probably others, too) only uses the return value to - * decide whether it has to free the skb (only if result != CAPI_NOERROR (0)) - */ -static u16 gigaset_send_message(struct capi_ctr *ctr, struct sk_buff *skb) -{ - struct gigaset_capi_ctr *iif - = container_of(ctr, struct gigaset_capi_ctr, ctr); - struct cardstate *cs = ctr->driverdata; - struct gigaset_capi_appl *ap; - capi_send_handler_t handler; - - /* can only handle linear sk_buffs */ - if (skb_linearize(skb) < 0) { - dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__); - return CAPI_MSGOSRESOURCEERR; - } - - /* retrieve application data structure */ - ap = get_appl(iif, CAPIMSG_APPID(skb->data)); - if (!ap) { - dev_notice(cs->dev, "%s: application %u not registered\n", - __func__, CAPIMSG_APPID(skb->data)); - return CAPI_ILLAPPNR; - } - - /* look up command */ - handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); - if (!handler) { - /* unknown/unsupported message type */ - if (printk_ratelimit()) - dev_notice(cs->dev, "%s: unsupported message %u\n", - __func__, CAPIMSG_CMD(skb->data)); - return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; - } - - /* serialize */ - if (atomic_add_return(1, &iif->sendqlen) > 1) { - /* queue behind other messages */ - skb_queue_tail(&iif->sendqueue, skb); - return CAPI_NOERROR; - } - - /* process message */ - handler(iif, ap, skb); - - /* process other messages arrived in the meantime */ - while (atomic_sub_return(1, &iif->sendqlen) > 0) { - skb = skb_dequeue(&iif->sendqueue); - if (!skb) { - /* should never happen */ - dev_err(cs->dev, "%s: send queue empty\n", __func__); - continue; - } - ap = get_appl(iif, CAPIMSG_APPID(skb->data)); - if (!ap) { - /* could that happen? */ - dev_warn(cs->dev, "%s: application %u vanished\n", - __func__, CAPIMSG_APPID(skb->data)); - continue; - } - handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); - if (!handler) { - /* should never happen */ - dev_err(cs->dev, "%s: handler %x vanished\n", - __func__, CAPIMSG_CMD(skb->data)); - continue; - } - handler(iif, ap, skb); - } - - return CAPI_NOERROR; -} - -/** - * gigaset_procinfo() - build single line description for controller - * @ctr: controller descriptor structure. - * - * Return value: pointer to generated string (null terminated) - */ -static char *gigaset_procinfo(struct capi_ctr *ctr) -{ - return ctr->name; /* ToDo: more? */ -} - -static int gigaset_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctr = m->private; - struct cardstate *cs = ctr->driverdata; - char *s; - int i; - - seq_printf(m, "%-16s %s\n", "name", ctr->name); - seq_printf(m, "%-16s %s %s\n", "dev", - dev_driver_string(cs->dev), dev_name(cs->dev)); - seq_printf(m, "%-16s %d\n", "id", cs->myid); - if (cs->gotfwver) - seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware", - cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); - seq_printf(m, "%-16s %d\n", "channels", cs->channels); - seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no"); - - switch (cs->mode) { - case M_UNKNOWN: - s = "unknown"; - break; - case M_CONFIG: - s = "config"; - break; - case M_UNIMODEM: - s = "Unimodem"; - break; - case M_CID: - s = "CID"; - break; - default: - s = "??"; - } - seq_printf(m, "%-16s %s\n", "mode", s); - - switch (cs->mstate) { - case MS_UNINITIALIZED: - s = "uninitialized"; - break; - case MS_INIT: - s = "init"; - break; - case MS_LOCKED: - s = "locked"; - break; - case MS_SHUTDOWN: - s = "shutdown"; - break; - case MS_RECOVER: - s = "recover"; - break; - case MS_READY: - s = "ready"; - break; - default: - s = "??"; - } - seq_printf(m, "%-16s %s\n", "mstate", s); - - seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no"); - seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no"); - seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no"); - seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no"); - - for (i = 0; i < cs->channels; i++) { - seq_printf(m, "[%d]%-13s %d\n", i, "corrupted", - cs->bcs[i].corrupted); - seq_printf(m, "[%d]%-13s %d\n", i, "trans_down", - cs->bcs[i].trans_down); - seq_printf(m, "[%d]%-13s %d\n", i, "trans_up", - cs->bcs[i].trans_up); - seq_printf(m, "[%d]%-13s %d\n", i, "chstate", - cs->bcs[i].chstate); - switch (cs->bcs[i].proto2) { - case L2_BITSYNC: - s = "bitsync"; - break; - case L2_HDLC: - s = "HDLC"; - break; - case L2_VOICE: - s = "voice"; - break; - default: - s = "??"; - } - seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s); - } - return 0; -} - -/** - * gigaset_isdn_regdev() - register device to LL - * @cs: device descriptor structure. - * @isdnid: device name. - * - * Return value: 0 on success, error code < 0 on failure - */ -int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) -{ - struct gigaset_capi_ctr *iif; - int rc; - - iif = kzalloc(sizeof(*iif), GFP_KERNEL); - if (!iif) { - pr_err("%s: out of memory\n", __func__); - return -ENOMEM; - } - - /* prepare controller structure */ - iif->ctr.owner = THIS_MODULE; - iif->ctr.driverdata = cs; - strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name) - 1); - iif->ctr.driver_name = "gigaset"; - iif->ctr.load_firmware = NULL; - iif->ctr.reset_ctr = NULL; - iif->ctr.register_appl = gigaset_register_appl; - iif->ctr.release_appl = gigaset_release_appl; - iif->ctr.send_message = gigaset_send_message; - iif->ctr.procinfo = gigaset_procinfo; - iif->ctr.proc_show = gigaset_proc_show, - INIT_LIST_HEAD(&iif->appls); - skb_queue_head_init(&iif->sendqueue); - atomic_set(&iif->sendqlen, 0); - - /* register controller with CAPI */ - rc = attach_capi_ctr(&iif->ctr); - if (rc) { - pr_err("attach_capi_ctr failed (%d)\n", rc); - kfree(iif); - return rc; - } - - cs->iif = iif; - cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN; - return 0; -} - -/** - * gigaset_isdn_unregdev() - unregister device from LL - * @cs: device descriptor structure. - */ -void gigaset_isdn_unregdev(struct cardstate *cs) -{ - struct gigaset_capi_ctr *iif = cs->iif; - - detach_capi_ctr(&iif->ctr); - kfree(iif); - cs->iif = NULL; -} - -static struct capi_driver capi_driver_gigaset = { - .name = "gigaset", - .revision = "1.0", -}; - -/** - * gigaset_isdn_regdrv() - register driver to LL - */ -void gigaset_isdn_regdrv(void) -{ - pr_info("Kernel CAPI interface\n"); - register_capi_driver(&capi_driver_gigaset); -} - -/** - * gigaset_isdn_unregdrv() - unregister driver from LL - */ -void gigaset_isdn_unregdrv(void) -{ - unregister_capi_driver(&capi_driver_gigaset); -} diff --git a/drivers/staging/isdn/gigaset/common.c b/drivers/staging/isdn/gigaset/common.c deleted file mode 100644 index 3bb8092858ab..000000000000 --- a/drivers/staging/isdn/gigaset/common.c +++ /dev/null @@ -1,1153 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Stuff used by all variants of the driver - * - * Copyright (c) 2001 by Stefan Eilers, - * Hansjoerg Lipp , - * Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp , Tilman Schmidt , Stefan Eilers" -#define DRIVER_DESC "Driver for Gigaset 307x" - -#ifdef CONFIG_GIGASET_DEBUG -#define DRIVER_DESC_DEBUG " (debug build)" -#else -#define DRIVER_DESC_DEBUG "" -#endif - -/* Module parameters */ -int gigaset_debuglevel; -EXPORT_SYMBOL_GPL(gigaset_debuglevel); -module_param_named(debug, gigaset_debuglevel, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "debug level"); - -/* driver state flags */ -#define VALID_MINOR 0x01 -#define VALID_ID 0x02 - -/** - * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging - * @level: debugging level. - * @msg: message prefix. - * @len: number of bytes to dump. - * @buf: data to dump. - * - * If the current debugging level includes one of the bits set in @level, - * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio, - * prefixed by the text @msg. - */ -void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf) -{ - unsigned char outbuf[80]; - unsigned char c; - size_t space = sizeof outbuf - 1; - unsigned char *out = outbuf; - size_t numin = len; - - while (numin--) { - c = *buf++; - if (c == '~' || c == '^' || c == '\\') { - if (!space--) - break; - *out++ = '\\'; - } - if (c & 0x80) { - if (!space--) - break; - *out++ = '~'; - c ^= 0x80; - } - if (c < 0x20 || c == 0x7f) { - if (!space--) - break; - *out++ = '^'; - c ^= 0x40; - } - if (!space--) - break; - *out++ = c; - } - *out = 0; - - gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); -} -EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); - -static int setflags(struct cardstate *cs, unsigned flags, unsigned delay) -{ - int r; - - r = cs->ops->set_modem_ctrl(cs, cs->control_state, flags); - cs->control_state = flags; - if (r < 0) - return r; - - if (delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(delay * HZ / 1000); - } - - return 0; -} - -int gigaset_enterconfigmode(struct cardstate *cs) -{ - int i, r; - - cs->control_state = TIOCM_RTS; - - r = setflags(cs, TIOCM_DTR, 200); - if (r < 0) - goto error; - r = setflags(cs, 0, 200); - if (r < 0) - goto error; - for (i = 0; i < 5; ++i) { - r = setflags(cs, TIOCM_RTS, 100); - if (r < 0) - goto error; - r = setflags(cs, 0, 100); - if (r < 0) - goto error; - } - r = setflags(cs, TIOCM_RTS | TIOCM_DTR, 800); - if (r < 0) - goto error; - - return 0; - -error: - dev_err(cs->dev, "error %d on setuartbits\n", -r); - cs->control_state = TIOCM_RTS | TIOCM_DTR; - cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS | TIOCM_DTR); - - return -1; -} - -static int test_timeout(struct at_state_t *at_state) -{ - if (!at_state->timer_expires) - return 0; - - if (--at_state->timer_expires) { - gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu", - at_state, at_state->timer_expires); - return 0; - } - - gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - at_state->timer_index, NULL); - return 1; -} - -static void timer_tick(struct timer_list *t) -{ - struct cardstate *cs = from_timer(cs, t, timer); - unsigned long flags; - unsigned channel; - struct at_state_t *at_state; - int timeout = 0; - - spin_lock_irqsave(&cs->lock, flags); - - for (channel = 0; channel < cs->channels; ++channel) - if (test_timeout(&cs->bcs[channel].at_state)) - timeout = 1; - - if (test_timeout(&cs->at_state)) - timeout = 1; - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (test_timeout(at_state)) - timeout = 1; - - if (cs->running) { - mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); - if (timeout) { - gig_dbg(DEBUG_EVENT, "scheduling timeout"); - tasklet_schedule(&cs->event_tasklet); - } - } - - spin_unlock_irqrestore(&cs->lock, flags); -} - -int gigaset_get_channel(struct bc_state *bcs) -{ - unsigned long flags; - - spin_lock_irqsave(&bcs->cs->lock, flags); - if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { - gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d", - bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return -EBUSY; - } - ++bcs->use_count; - bcs->busy = 1; - gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return 0; -} - -struct bc_state *gigaset_get_free_channel(struct cardstate *cs) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&cs->lock, flags); - if (!try_module_get(cs->driver->owner)) { - gig_dbg(DEBUG_CHANNEL, - "could not get module for allocating channel"); - spin_unlock_irqrestore(&cs->lock, flags); - return NULL; - } - for (i = 0; i < cs->channels; ++i) - if (!cs->bcs[i].use_count) { - ++cs->bcs[i].use_count; - cs->bcs[i].busy = 1; - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_CHANNEL, "allocated channel %d", i); - return cs->bcs + i; - } - module_put(cs->driver->owner); - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_CHANNEL, "no free channel"); - return NULL; -} - -void gigaset_free_channel(struct bc_state *bcs) -{ - unsigned long flags; - - spin_lock_irqsave(&bcs->cs->lock, flags); - if (!bcs->busy) { - gig_dbg(DEBUG_CHANNEL, "could not free channel %d", - bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return; - } - --bcs->use_count; - bcs->busy = 0; - module_put(bcs->cs->driver->owner); - gig_dbg(DEBUG_CHANNEL, "freed channel %d", bcs->channel); - spin_unlock_irqrestore(&bcs->cs->lock, flags); -} - -int gigaset_get_channels(struct cardstate *cs) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&cs->lock, flags); - for (i = 0; i < cs->channels; ++i) - if (cs->bcs[i].use_count) { - spin_unlock_irqrestore(&cs->lock, flags); - gig_dbg(DEBUG_CHANNEL, - "could not allocate all channels"); - return -EBUSY; - } - for (i = 0; i < cs->channels; ++i) - ++cs->bcs[i].use_count; - spin_unlock_irqrestore(&cs->lock, flags); - - gig_dbg(DEBUG_CHANNEL, "allocated all channels"); - - return 0; -} - -void gigaset_free_channels(struct cardstate *cs) -{ - unsigned long flags; - int i; - - gig_dbg(DEBUG_CHANNEL, "unblocking all channels"); - spin_lock_irqsave(&cs->lock, flags); - for (i = 0; i < cs->channels; ++i) - --cs->bcs[i].use_count; - spin_unlock_irqrestore(&cs->lock, flags); -} - -void gigaset_block_channels(struct cardstate *cs) -{ - unsigned long flags; - int i; - - gig_dbg(DEBUG_CHANNEL, "blocking all channels"); - spin_lock_irqsave(&cs->lock, flags); - for (i = 0; i < cs->channels; ++i) - ++cs->bcs[i].use_count; - spin_unlock_irqrestore(&cs->lock, flags); -} - -static void clear_events(struct cardstate *cs) -{ - struct event_t *ev; - unsigned head, tail; - unsigned long flags; - - spin_lock_irqsave(&cs->ev_lock, flags); - - head = cs->ev_head; - tail = cs->ev_tail; - - while (tail != head) { - ev = cs->events + head; - kfree(ev->ptr); - head = (head + 1) % MAX_EVENTS; - } - - cs->ev_head = tail; - - spin_unlock_irqrestore(&cs->ev_lock, flags); -} - -/** - * gigaset_add_event() - add event to device event queue - * @cs: device descriptor structure. - * @at_state: connection state structure. - * @type: event type. - * @ptr: pointer parameter for event. - * @parameter: integer parameter for event. - * @arg: pointer parameter for event. - * - * Allocate an event queue entry from the device's event queue, and set it up - * with the parameters given. - * - * Return value: added event - */ -struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg) -{ - unsigned long flags; - unsigned next, tail; - struct event_t *event = NULL; - - gig_dbg(DEBUG_EVENT, "queueing event %d", type); - - spin_lock_irqsave(&cs->ev_lock, flags); - - tail = cs->ev_tail; - next = (tail + 1) % MAX_EVENTS; - if (unlikely(next == cs->ev_head)) - dev_err(cs->dev, "event queue full\n"); - else { - event = cs->events + tail; - event->type = type; - event->at_state = at_state; - event->cid = -1; - event->ptr = ptr; - event->arg = arg; - event->parameter = parameter; - cs->ev_tail = next; - } - - spin_unlock_irqrestore(&cs->ev_lock, flags); - - return event; -} -EXPORT_SYMBOL_GPL(gigaset_add_event); - -static void clear_at_state(struct at_state_t *at_state) -{ - int i; - - for (i = 0; i < STR_NUM; ++i) { - kfree(at_state->str_var[i]); - at_state->str_var[i] = NULL; - } -} - -static void dealloc_temp_at_states(struct cardstate *cs) -{ - struct at_state_t *cur, *next; - - list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) { - list_del(&cur->list); - clear_at_state(cur); - kfree(cur); - } -} - -static void gigaset_freebcs(struct bc_state *bcs) -{ - int i; - - gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); - bcs->cs->ops->freebcshw(bcs); - - gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); - clear_at_state(&bcs->at_state); - gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); - dev_kfree_skb(bcs->rx_skb); - bcs->rx_skb = NULL; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - } -} - -static struct cardstate *alloc_cs(struct gigaset_driver *drv) -{ - unsigned long flags; - unsigned i; - struct cardstate *cs; - struct cardstate *ret = NULL; - - spin_lock_irqsave(&drv->lock, flags); - if (drv->blocked) - goto exit; - for (i = 0; i < drv->minors; ++i) { - cs = drv->cs + i; - if (!(cs->flags & VALID_MINOR)) { - cs->flags = VALID_MINOR; - ret = cs; - break; - } - } -exit: - spin_unlock_irqrestore(&drv->lock, flags); - return ret; -} - -static void free_cs(struct cardstate *cs) -{ - cs->flags = 0; -} - -static void make_valid(struct cardstate *cs, unsigned mask) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - cs->flags |= mask; - spin_unlock_irqrestore(&drv->lock, flags); -} - -static void make_invalid(struct cardstate *cs, unsigned mask) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - cs->flags &= ~mask; - spin_unlock_irqrestore(&drv->lock, flags); -} - -/** - * gigaset_freecs() - free all associated ressources of a device - * @cs: device descriptor structure. - * - * Stops all tasklets and timers, unregisters the device from all - * subsystems it was registered to, deallocates the device structure - * @cs and all structures referenced from it. - * Operations on the device should be stopped before calling this. - */ -void gigaset_freecs(struct cardstate *cs) -{ - int i; - unsigned long flags; - - if (!cs) - return; - - mutex_lock(&cs->mutex); - - spin_lock_irqsave(&cs->lock, flags); - cs->running = 0; - spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are - not rescheduled below */ - - tasklet_kill(&cs->event_tasklet); - del_timer_sync(&cs->timer); - - switch (cs->cs_init) { - default: - /* clear B channel structures */ - for (i = 0; i < cs->channels; ++i) { - gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); - gigaset_freebcs(cs->bcs + i); - } - - /* clear device sysfs */ - gigaset_free_dev_sysfs(cs); - - gigaset_if_free(cs); - - gig_dbg(DEBUG_INIT, "clearing hw"); - cs->ops->freecshw(cs); - - /* fall through */ - case 2: /* error in initcshw */ - /* Deregister from LL */ - make_invalid(cs, VALID_ID); - gigaset_isdn_unregdev(cs); - - /* fall through */ - case 1: /* error when registering to LL */ - gig_dbg(DEBUG_INIT, "clearing at_state"); - clear_at_state(&cs->at_state); - dealloc_temp_at_states(cs); - clear_events(cs); - tty_port_destroy(&cs->port); - - /* fall through */ - case 0: /* error in basic setup */ - gig_dbg(DEBUG_INIT, "freeing inbuf"); - kfree(cs->inbuf); - kfree(cs->bcs); - } - - mutex_unlock(&cs->mutex); - free_cs(cs); -} -EXPORT_SYMBOL_GPL(gigaset_freecs); - -void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid) -{ - int i; - - INIT_LIST_HEAD(&at_state->list); - at_state->waiting = 0; - at_state->getstring = 0; - at_state->pending_commands = 0; - at_state->timer_expires = 0; - at_state->timer_active = 0; - at_state->timer_index = 0; - at_state->seq_index = 0; - at_state->ConState = 0; - for (i = 0; i < STR_NUM; ++i) - at_state->str_var[i] = NULL; - at_state->int_var[VAR_ZDLE] = 0; - at_state->int_var[VAR_ZCTP] = -1; - at_state->int_var[VAR_ZSAU] = ZSAU_NULL; - at_state->cs = cs; - at_state->bcs = bcs; - at_state->cid = cid; - if (!cid) - at_state->replystruct = cs->tabnocid; - else - at_state->replystruct = cs->tabcid; -} - - -static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) -/* inbuf->read must be allocated before! */ -{ - inbuf->head = 0; - inbuf->tail = 0; - inbuf->cs = cs; - inbuf->inputstate = INS_command; -} - -/** - * gigaset_fill_inbuf() - append received data to input buffer - * @inbuf: buffer structure. - * @src: received data. - * @numbytes: number of bytes received. - * - * Return value: !=0 if some data was appended - */ -int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, - unsigned numbytes) -{ - unsigned n, head, tail, bytesleft; - - gig_dbg(DEBUG_INTR, "received %u bytes", numbytes); - - if (!numbytes) - return 0; - - bytesleft = numbytes; - tail = inbuf->tail; - head = inbuf->head; - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - - while (bytesleft) { - if (head > tail) - n = head - 1 - tail; - else if (head == 0) - n = (RBUFSIZE - 1) - tail; - else - n = RBUFSIZE - tail; - if (!n) { - dev_err(inbuf->cs->dev, - "buffer overflow (%u bytes lost)\n", - bytesleft); - break; - } - if (n > bytesleft) - n = bytesleft; - memcpy(inbuf->data + tail, src, n); - bytesleft -= n; - tail = (tail + n) % RBUFSIZE; - src += n; - } - gig_dbg(DEBUG_INTR, "setting tail to %u", tail); - inbuf->tail = tail; - return numbytes != bytesleft; -} -EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); - -/* Initialize the b-channel structure */ -static int gigaset_initbcs(struct bc_state *bcs, struct cardstate *cs, - int channel) -{ - int i; - - bcs->tx_skb = NULL; - - skb_queue_head_init(&bcs->squeue); - - bcs->corrupted = 0; - bcs->trans_down = 0; - bcs->trans_up = 0; - - gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); - gigaset_at_init(&bcs->at_state, bcs, cs, -1); - -#ifdef CONFIG_GIGASET_DEBUG - bcs->emptycount = 0; -#endif - - bcs->rx_bufsize = 0; - bcs->rx_skb = NULL; - bcs->rx_fcs = PPP_INITFCS; - bcs->inputstate = 0; - bcs->channel = channel; - bcs->cs = cs; - - bcs->chstate = 0; - bcs->use_count = 1; - bcs->busy = 0; - bcs->ignore = cs->ignoreframes; - - for (i = 0; i < AT_NUM; ++i) - bcs->commands[i] = NULL; - - spin_lock_init(&bcs->aplock); - bcs->ap = NULL; - bcs->apconnstate = 0; - - gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); - return cs->ops->initbcshw(bcs); -} - -/** - * gigaset_initcs() - initialize device structure - * @drv: hardware driver the device belongs to - * @channels: number of B channels supported by device - * @onechannel: !=0 if B channel data and AT commands share one - * communication channel (M10x), - * ==0 if B channels have separate communication channels (base) - * @ignoreframes: number of frames to ignore after setting up B channel - * @cidmode: !=0: start in CallID mode - * @modulename: name of driver module for LL registration - * - * Allocate and initialize cardstate structure for Gigaset driver - * Calls hardware dependent gigaset_initcshw() function - * Calls B channel initialization function gigaset_initbcs() for each B channel - * - * Return value: - * pointer to cardstate structure - */ -struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, - int onechannel, int ignoreframes, - int cidmode, const char *modulename) -{ - struct cardstate *cs; - unsigned long flags; - int i; - - gig_dbg(DEBUG_INIT, "allocating cs"); - cs = alloc_cs(drv); - if (!cs) { - pr_err("maximum number of devices exceeded\n"); - return NULL; - } - - cs->cs_init = 0; - cs->channels = channels; - cs->onechannel = onechannel; - cs->ignoreframes = ignoreframes; - INIT_LIST_HEAD(&cs->temp_at_states); - cs->running = 0; - timer_setup(&cs->timer, timer_tick, 0); - spin_lock_init(&cs->ev_lock); - cs->ev_tail = 0; - cs->ev_head = 0; - - tasklet_init(&cs->event_tasklet, gigaset_handle_event, - (unsigned long) cs); - tty_port_init(&cs->port); - cs->commands_pending = 0; - cs->cur_at_seq = 0; - cs->gotfwver = -1; - cs->dev = NULL; - cs->tty_dev = NULL; - cs->cidmode = cidmode != 0; - cs->tabnocid = gigaset_tab_nocid; - cs->tabcid = gigaset_tab_cid; - - init_waitqueue_head(&cs->waitqueue); - cs->waiting = 0; - - cs->mode = M_UNKNOWN; - cs->mstate = MS_UNINITIALIZED; - - cs->bcs = kmalloc_array(channels, sizeof(struct bc_state), GFP_KERNEL); - cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); - if (!cs->bcs || !cs->inbuf) { - pr_err("out of memory\n"); - goto error; - } - ++cs->cs_init; - - gig_dbg(DEBUG_INIT, "setting up at_state"); - spin_lock_init(&cs->lock); - gigaset_at_init(&cs->at_state, NULL, cs, 0); - cs->dle = 0; - cs->cbytes = 0; - - gig_dbg(DEBUG_INIT, "setting up inbuf"); - gigaset_inbuf_init(cs->inbuf, cs); - - cs->connected = 0; - cs->isdn_up = 0; - - gig_dbg(DEBUG_INIT, "setting up cmdbuf"); - cs->cmdbuf = cs->lastcmdbuf = NULL; - spin_lock_init(&cs->cmdlock); - cs->curlen = 0; - cs->cmdbytes = 0; - - gig_dbg(DEBUG_INIT, "setting up iif"); - if (gigaset_isdn_regdev(cs, modulename) < 0) { - pr_err("error registering ISDN device\n"); - goto error; - } - - make_valid(cs, VALID_ID); - ++cs->cs_init; - gig_dbg(DEBUG_INIT, "setting up hw"); - if (cs->ops->initcshw(cs) < 0) - goto error; - - ++cs->cs_init; - - /* set up character device */ - gigaset_if_init(cs); - - /* set up device sysfs */ - gigaset_init_dev_sysfs(cs); - - /* set up channel data structures */ - for (i = 0; i < channels; ++i) { - gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i); - if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) { - pr_err("could not allocate channel %d data\n", i); - goto error; - } - } - - spin_lock_irqsave(&cs->lock, flags); - cs->running = 1; - spin_unlock_irqrestore(&cs->lock, flags); - cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK); - add_timer(&cs->timer); - - gig_dbg(DEBUG_INIT, "cs initialized"); - return cs; - -error: - gig_dbg(DEBUG_INIT, "failed"); - gigaset_freecs(cs); - return NULL; -} -EXPORT_SYMBOL_GPL(gigaset_initcs); - -/* ReInitialize the b-channel structure on hangup */ -void gigaset_bcs_reinit(struct bc_state *bcs) -{ - struct sk_buff *skb; - struct cardstate *cs = bcs->cs; - unsigned long flags; - - while ((skb = skb_dequeue(&bcs->squeue)) != NULL) - dev_kfree_skb(skb); - - spin_lock_irqsave(&cs->lock, flags); - clear_at_state(&bcs->at_state); - bcs->at_state.ConState = 0; - bcs->at_state.timer_active = 0; - bcs->at_state.timer_expires = 0; - bcs->at_state.cid = -1; /* No CID defined */ - spin_unlock_irqrestore(&cs->lock, flags); - - bcs->inputstate = 0; - -#ifdef CONFIG_GIGASET_DEBUG - bcs->emptycount = 0; -#endif - - bcs->rx_fcs = PPP_INITFCS; - bcs->chstate = 0; - - bcs->ignore = cs->ignoreframes; - dev_kfree_skb(bcs->rx_skb); - bcs->rx_skb = NULL; - - cs->ops->reinitbcshw(bcs); -} - -static void cleanup_cs(struct cardstate *cs) -{ - struct cmdbuf_t *cb, *tcb; - int i; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - - cs->mode = M_UNKNOWN; - cs->mstate = MS_UNINITIALIZED; - - clear_at_state(&cs->at_state); - dealloc_temp_at_states(cs); - gigaset_at_init(&cs->at_state, NULL, cs, 0); - - cs->inbuf->inputstate = INS_command; - cs->inbuf->head = 0; - cs->inbuf->tail = 0; - - cb = cs->cmdbuf; - while (cb) { - tcb = cb; - cb = cb->next; - kfree(tcb); - } - cs->cmdbuf = cs->lastcmdbuf = NULL; - cs->curlen = 0; - cs->cmdbytes = 0; - cs->gotfwver = -1; - cs->dle = 0; - cs->cur_at_seq = 0; - cs->commands_pending = 0; - cs->cbytes = 0; - - spin_unlock_irqrestore(&cs->lock, flags); - - for (i = 0; i < cs->channels; ++i) { - gigaset_freebcs(cs->bcs + i); - if (gigaset_initbcs(cs->bcs + i, cs, i) < 0) - pr_err("could not allocate channel %d data\n", i); - } - - if (cs->waiting) { - cs->cmd_result = -ENODEV; - cs->waiting = 0; - wake_up_interruptible(&cs->waitqueue); - } -} - - -/** - * gigaset_start() - start device operations - * @cs: device descriptor structure. - * - * Prepares the device for use by setting up communication parameters, - * scheduling an EV_START event to initiate device initialization, and - * waiting for completion of the initialization. - * - * Return value: - * 0 on success, error code < 0 on failure - */ -int gigaset_start(struct cardstate *cs) -{ - unsigned long flags; - - if (mutex_lock_interruptible(&cs->mutex)) - return -EBUSY; - - spin_lock_irqsave(&cs->lock, flags); - cs->connected = 1; - spin_unlock_irqrestore(&cs->lock, flags); - - if (cs->mstate != MS_LOCKED) { - cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR | TIOCM_RTS); - cs->ops->baud_rate(cs, B115200); - cs->ops->set_line_ctrl(cs, CS8); - cs->control_state = TIOCM_DTR | TIOCM_RTS; - } - - cs->waiting = 1; - - if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { - cs->waiting = 0; - goto error; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - mutex_unlock(&cs->mutex); - return 0; - -error: - mutex_unlock(&cs->mutex); - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(gigaset_start); - -/** - * gigaset_shutdown() - shut down device operations - * @cs: device descriptor structure. - * - * Deactivates the device by scheduling an EV_SHUTDOWN event and - * waiting for completion of the shutdown. - * - * Return value: - * 0 - success, -ENODEV - error (no device associated) - */ -int gigaset_shutdown(struct cardstate *cs) -{ - mutex_lock(&cs->mutex); - - if (!(cs->flags & VALID_MINOR)) { - mutex_unlock(&cs->mutex); - return -ENODEV; - } - - cs->waiting = 1; - - if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) - goto exit; - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - cleanup_cs(cs); - -exit: - mutex_unlock(&cs->mutex); - return 0; -} -EXPORT_SYMBOL_GPL(gigaset_shutdown); - -/** - * gigaset_stop() - stop device operations - * @cs: device descriptor structure. - * - * Stops operations on the device by scheduling an EV_STOP event and - * waiting for completion of the shutdown. - */ -void gigaset_stop(struct cardstate *cs) -{ - mutex_lock(&cs->mutex); - - cs->waiting = 1; - - if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) - goto exit; - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - cleanup_cs(cs); - -exit: - mutex_unlock(&cs->mutex); -} -EXPORT_SYMBOL_GPL(gigaset_stop); - -static LIST_HEAD(drivers); -static DEFINE_SPINLOCK(driver_lock); - -struct cardstate *gigaset_get_cs_by_id(int id) -{ - unsigned long flags; - struct cardstate *ret = NULL; - struct cardstate *cs; - struct gigaset_driver *drv; - unsigned i; - - spin_lock_irqsave(&driver_lock, flags); - list_for_each_entry(drv, &drivers, list) { - spin_lock(&drv->lock); - for (i = 0; i < drv->minors; ++i) { - cs = drv->cs + i; - if ((cs->flags & VALID_ID) && cs->myid == id) { - ret = cs; - break; - } - } - spin_unlock(&drv->lock); - if (ret) - break; - } - spin_unlock_irqrestore(&driver_lock, flags); - return ret; -} - -static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) -{ - unsigned long flags; - struct cardstate *ret = NULL; - struct gigaset_driver *drv; - unsigned index; - - spin_lock_irqsave(&driver_lock, flags); - list_for_each_entry(drv, &drivers, list) { - if (minor < drv->minor || minor >= drv->minor + drv->minors) - continue; - index = minor - drv->minor; - spin_lock(&drv->lock); - if (drv->cs[index].flags & VALID_MINOR) - ret = drv->cs + index; - spin_unlock(&drv->lock); - if (ret) - break; - } - spin_unlock_irqrestore(&driver_lock, flags); - return ret; -} - -struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) -{ - return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); -} - -/** - * gigaset_freedriver() - free all associated ressources of a driver - * @drv: driver descriptor structure. - * - * Unregisters the driver from the system and deallocates the driver - * structure @drv and all structures referenced from it. - * All devices should be shut down before calling this. - */ -void gigaset_freedriver(struct gigaset_driver *drv) -{ - unsigned long flags; - - spin_lock_irqsave(&driver_lock, flags); - list_del(&drv->list); - spin_unlock_irqrestore(&driver_lock, flags); - - gigaset_if_freedriver(drv); - - kfree(drv->cs); - kfree(drv); -} -EXPORT_SYMBOL_GPL(gigaset_freedriver); - -/** - * gigaset_initdriver() - initialize driver structure - * @minor: First minor number - * @minors: Number of minors this driver can handle - * @procname: Name of the driver - * @devname: Name of the device files (prefix without minor number) - * - * Allocate and initialize gigaset_driver structure. Initialize interface. - * - * Return value: - * Pointer to the gigaset_driver structure on success, NULL on failure. - */ -struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const struct gigaset_ops *ops, - struct module *owner) -{ - struct gigaset_driver *drv; - unsigned long flags; - unsigned i; - - drv = kmalloc(sizeof *drv, GFP_KERNEL); - if (!drv) - return NULL; - - drv->have_tty = 0; - drv->minor = minor; - drv->minors = minors; - spin_lock_init(&drv->lock); - drv->blocked = 0; - drv->ops = ops; - drv->owner = owner; - INIT_LIST_HEAD(&drv->list); - - drv->cs = kmalloc_array(minors, sizeof(*drv->cs), GFP_KERNEL); - if (!drv->cs) - goto error; - - for (i = 0; i < minors; ++i) { - drv->cs[i].flags = 0; - drv->cs[i].driver = drv; - drv->cs[i].ops = drv->ops; - drv->cs[i].minor_index = i; - mutex_init(&drv->cs[i].mutex); - } - - gigaset_if_initdriver(drv, procname, devname); - - spin_lock_irqsave(&driver_lock, flags); - list_add(&drv->list, &drivers); - spin_unlock_irqrestore(&driver_lock, flags); - - return drv; - -error: - kfree(drv); - return NULL; -} -EXPORT_SYMBOL_GPL(gigaset_initdriver); - -/** - * gigaset_blockdriver() - block driver - * @drv: driver descriptor structure. - * - * Prevents the driver from attaching new devices, in preparation for - * deregistration. - */ -void gigaset_blockdriver(struct gigaset_driver *drv) -{ - drv->blocked = 1; -} -EXPORT_SYMBOL_GPL(gigaset_blockdriver); - -static int __init gigaset_init_module(void) -{ - /* in accordance with the principle of least astonishment, - * setting the 'debug' parameter to 1 activates a sensible - * set of default debug levels - */ - if (gigaset_debuglevel == 1) - gigaset_debuglevel = DEBUG_DEFAULT; - - pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); - gigaset_isdn_regdrv(); - return 0; -} - -static void __exit gigaset_exit_module(void) -{ - gigaset_isdn_unregdrv(); -} - -module_init(gigaset_init_module); -module_exit(gigaset_exit_module); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/isdn/gigaset/dummyll.c b/drivers/staging/isdn/gigaset/dummyll.c deleted file mode 100644 index 4b9637e5da6e..000000000000 --- a/drivers/staging/isdn/gigaset/dummyll.c +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Dummy LL interface for the Gigaset driver - * - * Copyright (c) 2009 by Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include -#include "gigaset.h" - -void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) -{ -} -EXPORT_SYMBOL_GPL(gigaset_skb_sent); - -void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) -{ -} -EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); - -void gigaset_isdn_rcv_err(struct bc_state *bcs) -{ -} -EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); - -int gigaset_isdn_icall(struct at_state_t *at_state) -{ - return ICALL_IGNORE; -} - -void gigaset_isdn_connD(struct bc_state *bcs) -{ -} - -void gigaset_isdn_hupD(struct bc_state *bcs) -{ -} - -void gigaset_isdn_connB(struct bc_state *bcs) -{ -} - -void gigaset_isdn_hupB(struct bc_state *bcs) -{ -} - -void gigaset_isdn_start(struct cardstate *cs) -{ -} - -void gigaset_isdn_stop(struct cardstate *cs) -{ -} - -int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) -{ - return 0; -} - -void gigaset_isdn_unregdev(struct cardstate *cs) -{ -} - -void gigaset_isdn_regdrv(void) -{ - pr_info("no ISDN subsystem interface\n"); -} - -void gigaset_isdn_unregdrv(void) -{ -} diff --git a/drivers/staging/isdn/gigaset/ev-layer.c b/drivers/staging/isdn/gigaset/ev-layer.c deleted file mode 100644 index f8bb1869c600..000000000000 --- a/drivers/staging/isdn/gigaset/ev-layer.c +++ /dev/null @@ -1,1910 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Stuff used by all variants of the driver - * - * Copyright (c) 2001 by Stefan Eilers, - * Hansjoerg Lipp , - * Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include -#include "gigaset.h" - -/* ========================================================== */ -/* bit masks for pending commands */ -#define PC_DIAL 0x001 -#define PC_HUP 0x002 -#define PC_INIT 0x004 -#define PC_DLE0 0x008 -#define PC_DLE1 0x010 -#define PC_SHUTDOWN 0x020 -#define PC_ACCEPT 0x040 -#define PC_CID 0x080 -#define PC_NOCID 0x100 -#define PC_CIDMODE 0x200 -#define PC_UMMODE 0x400 - -/* types of modem responses */ -#define RT_NOTHING 0 -#define RT_ZSAU 1 -#define RT_RING 2 -#define RT_NUMBER 3 -#define RT_STRING 4 -#define RT_ZCAU 6 - -/* Possible ASCII responses */ -#define RSP_OK 0 -#define RSP_ERROR 1 -#define RSP_ZGCI 3 -#define RSP_RING 4 -#define RSP_ZVLS 5 -#define RSP_ZCAU 6 - -/* responses with values to store in at_state */ -/* - numeric */ -#define RSP_VAR 100 -#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) -#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) -#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) -/* - string */ -#define RSP_STR (RSP_VAR + VAR_NUM) -#define RSP_NMBR (RSP_STR + STR_NMBR) -#define RSP_ZCPN (RSP_STR + STR_ZCPN) -#define RSP_ZCON (RSP_STR + STR_ZCON) -#define RSP_ZBC (RSP_STR + STR_ZBC) -#define RSP_ZHLC (RSP_STR + STR_ZHLC) - -#define RSP_WRONG_CID -2 /* unknown cid in cmd */ -#define RSP_INVAL -6 /* invalid response */ -#define RSP_NODEV -9 /* device not connected */ - -#define RSP_NONE -19 -#define RSP_STRING -20 -#define RSP_NULL -21 -#define RSP_INIT -27 -#define RSP_ANY -26 -#define RSP_LAST -28 - -/* actions for process_response */ -#define ACT_NOTHING 0 -#define ACT_SETDLE1 1 -#define ACT_SETDLE0 2 -#define ACT_FAILINIT 3 -#define ACT_HUPMODEM 4 -#define ACT_CONFIGMODE 5 -#define ACT_INIT 6 -#define ACT_DLE0 7 -#define ACT_DLE1 8 -#define ACT_FAILDLE0 9 -#define ACT_FAILDLE1 10 -#define ACT_RING 11 -#define ACT_CID 12 -#define ACT_FAILCID 13 -#define ACT_SDOWN 14 -#define ACT_FAILSDOWN 15 -#define ACT_DEBUG 16 -#define ACT_WARN 17 -#define ACT_DIALING 18 -#define ACT_ABORTDIAL 19 -#define ACT_DISCONNECT 20 -#define ACT_CONNECT 21 -#define ACT_REMOTEREJECT 22 -#define ACT_CONNTIMEOUT 23 -#define ACT_REMOTEHUP 24 -#define ACT_ABORTHUP 25 -#define ACT_ICALL 26 -#define ACT_ACCEPTED 27 -#define ACT_ABORTACCEPT 28 -#define ACT_TIMEOUT 29 -#define ACT_GETSTRING 30 -#define ACT_SETVER 31 -#define ACT_FAILVER 32 -#define ACT_GOTVER 33 -#define ACT_TEST 34 -#define ACT_ERROR 35 -#define ACT_ABORTCID 36 -#define ACT_ZCAU 37 -#define ACT_NOTIFY_BC_DOWN 38 -#define ACT_NOTIFY_BC_UP 39 -#define ACT_DIAL 40 -#define ACT_ACCEPT 41 -#define ACT_HUP 43 -#define ACT_IF_LOCK 44 -#define ACT_START 45 -#define ACT_STOP 46 -#define ACT_FAKEDLE0 47 -#define ACT_FAKEHUP 48 -#define ACT_FAKESDOWN 49 -#define ACT_SHUTDOWN 50 -#define ACT_PROC_CIDMODE 51 -#define ACT_UMODESET 52 -#define ACT_FAILUMODE 53 -#define ACT_CMODESET 54 -#define ACT_FAILCMODE 55 -#define ACT_IF_VER 56 -#define ACT_CMD 100 - -/* at command sequences */ -#define SEQ_NONE 0 -#define SEQ_INIT 100 -#define SEQ_DLE0 200 -#define SEQ_DLE1 250 -#define SEQ_CID 300 -#define SEQ_NOCID 350 -#define SEQ_HUP 400 -#define SEQ_DIAL 600 -#define SEQ_ACCEPT 720 -#define SEQ_SHUTDOWN 500 -#define SEQ_CIDMODE 10 -#define SEQ_UMMODE 11 - - -/* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), - * 400: hup, 500: reset, 600: dial, 700: ring */ -struct reply_t gigaset_tab_nocid[] = -{ -/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, - * action, command */ - -/* initialize device, set cid mode if possible */ - {RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} }, - - {EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"}, - {RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING}, - "+GMR\r"}, - - {EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"}, - {RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"}, - - {EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1}, - "^SDLE=0\r"}, - {RSP_OK, 108, 108, -1, 104, -1}, - {RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"}, - {EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} }, - {RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} }, - - {EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0, - ACT_HUPMODEM, - ACT_TIMEOUT} }, - {EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"}, - - {RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"}, - {RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} }, - {RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, - {EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, - - {RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, - {EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, - - {RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} }, - - {EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER, - ACT_INIT} }, - {RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER, - ACT_INIT} }, - {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, - ACT_INIT} }, - {RSP_NONE, 121, 121, -1, 120, 0, {ACT_GETSTRING} }, - -/* leave dle mode */ - {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, - {RSP_OK, 201, 201, -1, 202, -1}, - {RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} }, - {RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} }, - {RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, - {EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, - -/* enter dle mode */ - {RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, - {RSP_OK, 251, 251, -1, 252, -1}, - {RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} }, - {RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, - {EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, - -/* incoming call */ - {RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} }, - -/* get cid */ - {RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, - {RSP_OK, 301, 301, -1, 302, -1}, - {RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} }, - {RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} }, - {EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} }, - -/* enter cid mode */ - {RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, - {RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} }, - {RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, - {EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, - -/* leave cid mode */ - {RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"}, - {RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} }, - {RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, - {EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, - -/* abort getting cid */ - {RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} }, - -/* reset */ - {RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, - {RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} }, - {RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, - {EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, - {RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} }, - - {EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} }, - {EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} }, - {EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} }, - {EV_START, -1, -1, -1, -1, -1, {ACT_START} }, - {EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} }, - {EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} }, - -/* misc. */ - {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, - {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, - {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, - {RSP_LAST} -}; - -/* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, - * 400: hup, 750: accepted icall */ -struct reply_t gigaset_tab_cid[] = -{ -/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, - * action, command */ - -/* dial */ - {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, - {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD + AT_BC} }, - {RSP_OK, 601, 601, -1, 603, 5, {ACT_CMD + AT_PROTO} }, - {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD + AT_TYPE} }, - {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD + AT_MSN} }, - {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} }, - {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD + AT_CLIP} }, - {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} }, - {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD + AT_ISO} }, - {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 608, 608, -1, 609, -1}, - {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD + AT_DIAL} }, - {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, - - {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, - -/* optional dialing responses */ - {EV_BC_OPEN, 650, 650, -1, 651, -1}, - {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, - {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} }, - -/* connect */ - {RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, - {RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP} }, - {RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, - {RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, - ACT_NOTIFY_BC_UP} }, - {EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} }, - -/* remote hangup */ - {RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} }, - {RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, - {RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, - -/* hangup */ - {EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} }, - {RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, - {RSP_OK, 401, 401, -1, 402, 5}, - {RSP_ZVLS, 402, 402, 0, 403, 5}, - {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, - {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, - {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, - {RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} }, - {EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} }, - - {EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, - -/* ring */ - {RSP_ZBC, 700, 700, -1, -1, -1, {0} }, - {RSP_ZHLC, 700, 700, -1, -1, -1, {0} }, - {RSP_NMBR, 700, 700, -1, -1, -1, {0} }, - {RSP_ZCPN, 700, 700, -1, -1, -1, {0} }, - {RSP_ZCTP, 700, 700, -1, -1, -1, {0} }, - {EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} }, - {EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, - -/*accept icall*/ - {EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} }, - {RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD + AT_PROTO} }, - {RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD + AT_ISO} }, - {RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"}, - {RSP_OK, 723, 723, -1, 724, 5, {0} }, - {RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} }, - {RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, - {EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, - {RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} }, - {RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} }, - {RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} }, - - {EV_BC_OPEN, 750, 750, -1, 751, -1}, - {EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} }, - -/* B channel closed (general case) */ - {EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} }, - -/* misc. */ - {RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, - {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, - {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, - {RSP_LAST} -}; - - -static const struct resp_type_t { - char *response; - int resp_code; - int type; -} -resp_type[] = -{ - {"OK", RSP_OK, RT_NOTHING}, - {"ERROR", RSP_ERROR, RT_NOTHING}, - {"ZSAU", RSP_ZSAU, RT_ZSAU}, - {"ZCAU", RSP_ZCAU, RT_ZCAU}, - {"RING", RSP_RING, RT_RING}, - {"ZGCI", RSP_ZGCI, RT_NUMBER}, - {"ZVLS", RSP_ZVLS, RT_NUMBER}, - {"ZCTP", RSP_ZCTP, RT_NUMBER}, - {"ZDLE", RSP_ZDLE, RT_NUMBER}, - {"ZHLC", RSP_ZHLC, RT_STRING}, - {"ZBC", RSP_ZBC, RT_STRING}, - {"NMBR", RSP_NMBR, RT_STRING}, - {"ZCPN", RSP_ZCPN, RT_STRING}, - {"ZCON", RSP_ZCON, RT_STRING}, - {NULL, 0, 0} -}; - -static const struct zsau_resp_t { - char *str; - int code; -} -zsau_resp[] = -{ - {"OUTGOING_CALL_PROCEEDING", ZSAU_PROCEEDING}, - {"CALL_DELIVERED", ZSAU_CALL_DELIVERED}, - {"ACTIVE", ZSAU_ACTIVE}, - {"DISCONNECT_IND", ZSAU_DISCONNECT_IND}, - {"NULL", ZSAU_NULL}, - {"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ}, - {NULL, ZSAU_UNKNOWN} -}; - -/* check for and remove fixed string prefix - * If s starts with prefix terminated by a non-alphanumeric character, - * return pointer to the first character after that, otherwise return NULL. - */ -static char *skip_prefix(char *s, const char *prefix) -{ - while (*prefix) - if (*s++ != *prefix++) - return NULL; - if (isalnum(*s)) - return NULL; - return s; -} - -/* queue event with CID */ -static void add_cid_event(struct cardstate *cs, int cid, int type, - void *ptr, int parameter) -{ - unsigned long flags; - unsigned next, tail; - struct event_t *event; - - gig_dbg(DEBUG_EVENT, "queueing event %d for cid %d", type, cid); - - spin_lock_irqsave(&cs->ev_lock, flags); - - tail = cs->ev_tail; - next = (tail + 1) % MAX_EVENTS; - if (unlikely(next == cs->ev_head)) { - dev_err(cs->dev, "event queue full\n"); - kfree(ptr); - } else { - event = cs->events + tail; - event->type = type; - event->cid = cid; - event->ptr = ptr; - event->arg = NULL; - event->parameter = parameter; - event->at_state = NULL; - cs->ev_tail = next; - } - - spin_unlock_irqrestore(&cs->ev_lock, flags); -} - -/** - * gigaset_handle_modem_response() - process received modem response - * @cs: device descriptor structure. - * - * Called by asyncdata/isocdata if a block of data received from the - * device must be processed as a modem command response. The data is - * already in the cs structure. - */ -void gigaset_handle_modem_response(struct cardstate *cs) -{ - char *eoc, *psep, *ptr; - const struct resp_type_t *rt; - const struct zsau_resp_t *zr; - int cid, parameter; - u8 type, value; - - if (!cs->cbytes) { - /* ignore additional LFs/CRs (M10x config mode or cx100) */ - gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[0]); - return; - } - cs->respdata[cs->cbytes] = 0; - - if (cs->at_state.getstring) { - /* state machine wants next line verbatim */ - cs->at_state.getstring = 0; - ptr = kstrdup(cs->respdata, GFP_ATOMIC); - gig_dbg(DEBUG_EVENT, "string==%s", ptr ? ptr : "NULL"); - add_cid_event(cs, 0, RSP_STRING, ptr, 0); - return; - } - - /* look up response type */ - for (rt = resp_type; rt->response; ++rt) { - eoc = skip_prefix(cs->respdata, rt->response); - if (eoc) - break; - } - if (!rt->response) { - add_cid_event(cs, 0, RSP_NONE, NULL, 0); - gig_dbg(DEBUG_EVENT, "unknown modem response: '%s'\n", - cs->respdata); - return; - } - - /* check for CID */ - psep = strrchr(cs->respdata, ';'); - if (psep && - !kstrtoint(psep + 1, 10, &cid) && - cid >= 1 && cid <= 65535) { - /* valid CID: chop it off */ - *psep = 0; - } else { - /* no valid CID: leave unchanged */ - cid = 0; - } - - gig_dbg(DEBUG_EVENT, "CMD received: %s", cs->respdata); - if (cid) - gig_dbg(DEBUG_EVENT, "CID: %d", cid); - - switch (rt->type) { - case RT_NOTHING: - /* check parameter separator */ - if (*eoc) - goto bad_param; /* extra parameter */ - - add_cid_event(cs, cid, rt->resp_code, NULL, 0); - break; - - case RT_RING: - /* check parameter separator */ - if (!*eoc) - eoc = NULL; /* no parameter */ - else if (*eoc++ != ',') - goto bad_param; - - add_cid_event(cs, 0, rt->resp_code, NULL, cid); - - /* process parameters as individual responses */ - while (eoc) { - /* look up parameter type */ - psep = NULL; - for (rt = resp_type; rt->response; ++rt) { - psep = skip_prefix(eoc, rt->response); - if (psep) - break; - } - - /* all legal parameters are of type RT_STRING */ - if (!psep || rt->type != RT_STRING) { - dev_warn(cs->dev, - "illegal RING parameter: '%s'\n", - eoc); - return; - } - - /* skip parameter value separator */ - if (*psep++ != '=') - goto bad_param; - - /* look up end of parameter */ - eoc = strchr(psep, ','); - if (eoc) - *eoc++ = 0; - - /* retrieve parameter value */ - ptr = kstrdup(psep, GFP_ATOMIC); - - /* queue event */ - add_cid_event(cs, cid, rt->resp_code, ptr, 0); - } - break; - - case RT_ZSAU: - /* check parameter separator */ - if (!*eoc) { - /* no parameter */ - add_cid_event(cs, cid, rt->resp_code, NULL, ZSAU_NONE); - break; - } - if (*eoc++ != '=') - goto bad_param; - - /* look up parameter value */ - for (zr = zsau_resp; zr->str; ++zr) - if (!strcmp(eoc, zr->str)) - break; - if (!zr->str) - goto bad_param; - - add_cid_event(cs, cid, rt->resp_code, NULL, zr->code); - break; - - case RT_STRING: - /* check parameter separator */ - if (*eoc++ != '=') - goto bad_param; - - /* retrieve parameter value */ - ptr = kstrdup(eoc, GFP_ATOMIC); - - /* queue event */ - add_cid_event(cs, cid, rt->resp_code, ptr, 0); - break; - - case RT_ZCAU: - /* check parameter separators */ - if (*eoc++ != '=') - goto bad_param; - psep = strchr(eoc, ','); - if (!psep) - goto bad_param; - *psep++ = 0; - - /* decode parameter values */ - if (kstrtou8(eoc, 16, &type) || kstrtou8(psep, 16, &value)) { - *--psep = ','; - goto bad_param; - } - parameter = (type << 8) | value; - - add_cid_event(cs, cid, rt->resp_code, NULL, parameter); - break; - - case RT_NUMBER: - /* check parameter separator */ - if (*eoc++ != '=') - goto bad_param; - - /* decode parameter value */ - if (kstrtoint(eoc, 10, ¶meter)) - goto bad_param; - - /* special case ZDLE: set flag before queueing event */ - if (rt->resp_code == RSP_ZDLE) - cs->dle = parameter; - - add_cid_event(cs, cid, rt->resp_code, NULL, parameter); - break; - -bad_param: - /* parameter unexpected, incomplete or malformed */ - dev_warn(cs->dev, "bad parameter in response '%s'\n", - cs->respdata); - add_cid_event(cs, cid, rt->resp_code, NULL, -1); - break; - - default: - dev_err(cs->dev, "%s: internal error on '%s'\n", - __func__, cs->respdata); - } -} -EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); - -/* disconnect_nobc - * process closing of connection associated with given AT state structure - * without B channel - */ -static void disconnect_nobc(struct at_state_t **at_state_p, - struct cardstate *cs) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - ++(*at_state_p)->seq_index; - - /* revert to selected idle mode */ - if (!cs->cidmode) { - cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); - cs->commands_pending = 1; - } - - /* check for and deallocate temporary AT state */ - if (!list_empty(&(*at_state_p)->list)) { - list_del(&(*at_state_p)->list); - kfree(*at_state_p); - *at_state_p = NULL; - } - - spin_unlock_irqrestore(&cs->lock, flags); -} - -/* disconnect_bc - * process closing of connection associated with given AT state structure - * and B channel - */ -static void disconnect_bc(struct at_state_t *at_state, - struct cardstate *cs, struct bc_state *bcs) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - ++at_state->seq_index; - - /* revert to selected idle mode */ - if (!cs->cidmode) { - cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); - cs->commands_pending = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - - /* invoke hardware specific handler */ - cs->ops->close_bchannel(bcs); - - /* notify LL */ - if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { - bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_isdn_hupD(bcs); - } -} - -/* get_free_channel - * get a free AT state structure: either one of those associated with the - * B channels of the Gigaset device, or if none of those is available, - * a newly allocated one with bcs=NULL - * The structure should be freed by calling disconnect_nobc() after use. - */ -static inline struct at_state_t *get_free_channel(struct cardstate *cs, - int cid) -/* cids: >0: siemens-cid - * 0: without cid - * -1: no cid assigned yet - */ -{ - unsigned long flags; - int i; - struct at_state_t *ret; - - for (i = 0; i < cs->channels; ++i) - if (gigaset_get_channel(cs->bcs + i) >= 0) { - ret = &cs->bcs[i].at_state; - ret->cid = cid; - return ret; - } - - spin_lock_irqsave(&cs->lock, flags); - ret = kmalloc(sizeof(struct at_state_t), GFP_ATOMIC); - if (ret) { - gigaset_at_init(ret, NULL, cs, cid); - list_add(&ret->list, &cs->temp_at_states); - } - spin_unlock_irqrestore(&cs->lock, flags); - return ret; -} - -static void init_failed(struct cardstate *cs, int mode) -{ - int i; - struct at_state_t *at_state; - - cs->at_state.pending_commands &= ~PC_INIT; - cs->mode = mode; - cs->mstate = MS_UNINITIALIZED; - gigaset_free_channels(cs); - for (i = 0; i < cs->channels; ++i) { - at_state = &cs->bcs[i].at_state; - if (at_state->pending_commands & PC_CID) { - at_state->pending_commands &= ~PC_CID; - at_state->pending_commands |= PC_NOCID; - cs->commands_pending = 1; - } - } -} - -static void schedule_init(struct cardstate *cs, int state) -{ - if (cs->at_state.pending_commands & PC_INIT) { - gig_dbg(DEBUG_EVENT, "not scheduling PC_INIT again"); - return; - } - cs->mstate = state; - cs->mode = M_UNKNOWN; - gigaset_block_channels(cs); - cs->at_state.pending_commands |= PC_INIT; - gig_dbg(DEBUG_EVENT, "Scheduling PC_INIT"); - cs->commands_pending = 1; -} - -/* send an AT command - * adding the "AT" prefix, cid and DLE encapsulation as appropriate - */ -static void send_command(struct cardstate *cs, const char *cmd, - struct at_state_t *at_state) -{ - int cid = at_state->cid; - struct cmdbuf_t *cb; - size_t buflen; - - buflen = strlen(cmd) + 12; /* DLE ( A T 1 2 3 4 5 DLE ) \0 */ - cb = kmalloc(sizeof(struct cmdbuf_t) + buflen, GFP_ATOMIC); - if (!cb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - return; - } - if (cid > 0 && cid <= 65535) - cb->len = snprintf(cb->buf, buflen, - cs->dle ? "\020(AT%d%s\020)" : "AT%d%s", - cid, cmd); - else - cb->len = snprintf(cb->buf, buflen, - cs->dle ? "\020(AT%s\020)" : "AT%s", - cmd); - cb->offset = 0; - cb->next = NULL; - cb->wake_tasklet = NULL; - cs->ops->write_cmd(cs, cb); -} - -static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) -{ - struct at_state_t *at_state; - int i; - unsigned long flags; - - if (cid == 0) - return &cs->at_state; - - for (i = 0; i < cs->channels; ++i) - if (cid == cs->bcs[i].at_state.cid) - return &cs->bcs[i].at_state; - - spin_lock_irqsave(&cs->lock, flags); - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (cid == at_state->cid) { - spin_unlock_irqrestore(&cs->lock, flags); - return at_state; - } - - spin_unlock_irqrestore(&cs->lock, flags); - - return NULL; -} - -static void bchannel_down(struct bc_state *bcs) -{ - if (bcs->chstate & CHS_B_UP) { - bcs->chstate &= ~CHS_B_UP; - gigaset_isdn_hupB(bcs); - } - - if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { - bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); - gigaset_isdn_hupD(bcs); - } - - gigaset_free_channel(bcs); - - gigaset_bcs_reinit(bcs); -} - -static void bchannel_up(struct bc_state *bcs) -{ - if (bcs->chstate & CHS_B_UP) { - dev_notice(bcs->cs->dev, "%s: B channel already up\n", - __func__); - return; - } - - bcs->chstate |= CHS_B_UP; - gigaset_isdn_connB(bcs); -} - -static void start_dial(struct at_state_t *at_state, void *data, - unsigned seq_index) -{ - struct bc_state *bcs = at_state->bcs; - struct cardstate *cs = at_state->cs; - char **commands = data; - unsigned long flags; - int i; - - bcs->chstate |= CHS_NOTIFY_LL; - - spin_lock_irqsave(&cs->lock, flags); - if (at_state->seq_index != seq_index) { - spin_unlock_irqrestore(&cs->lock, flags); - goto error; - } - spin_unlock_irqrestore(&cs->lock, flags); - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = commands[i]; - } - - at_state->pending_commands |= PC_CID; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CID"); - cs->commands_pending = 1; - return; - -error: - for (i = 0; i < AT_NUM; ++i) { - kfree(commands[i]); - commands[i] = NULL; - } - at_state->pending_commands |= PC_NOCID; - gig_dbg(DEBUG_EVENT, "Scheduling PC_NOCID"); - cs->commands_pending = 1; - return; -} - -static void start_accept(struct at_state_t *at_state) -{ - struct cardstate *cs = at_state->cs; - struct bc_state *bcs = at_state->bcs; - int i; - - for (i = 0; i < AT_NUM; ++i) { - kfree(bcs->commands[i]); - bcs->commands[i] = NULL; - } - - bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); - bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); - if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) { - dev_err(at_state->cs->dev, "out of memory\n"); - /* error reset */ - at_state->pending_commands |= PC_HUP; - gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); - cs->commands_pending = 1; - return; - } - - snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); - snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); - - at_state->pending_commands |= PC_ACCEPT; - gig_dbg(DEBUG_EVENT, "Scheduling PC_ACCEPT"); - cs->commands_pending = 1; -} - -static void do_start(struct cardstate *cs) -{ - gigaset_free_channels(cs); - - if (cs->mstate != MS_LOCKED) - schedule_init(cs, MS_INIT); - - cs->isdn_up = 1; - gigaset_isdn_start(cs); - - cs->waiting = 0; - wake_up(&cs->waitqueue); -} - -static void finish_shutdown(struct cardstate *cs) -{ - if (cs->mstate != MS_LOCKED) { - cs->mstate = MS_UNINITIALIZED; - cs->mode = M_UNKNOWN; - } - - /* Tell the LL that the device is not available .. */ - if (cs->isdn_up) { - cs->isdn_up = 0; - gigaset_isdn_stop(cs); - } - - /* The rest is done by cleanup_cs() in process context. */ - - cs->cmd_result = -ENODEV; - cs->waiting = 0; - wake_up(&cs->waitqueue); -} - -static void do_shutdown(struct cardstate *cs) -{ - gigaset_block_channels(cs); - - if (cs->mstate == MS_READY) { - cs->mstate = MS_SHUTDOWN; - cs->at_state.pending_commands |= PC_SHUTDOWN; - gig_dbg(DEBUG_EVENT, "Scheduling PC_SHUTDOWN"); - cs->commands_pending = 1; - } else - finish_shutdown(cs); -} - -static void do_stop(struct cardstate *cs) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - cs->connected = 0; - spin_unlock_irqrestore(&cs->lock, flags); - - do_shutdown(cs); -} - -/* Entering cid mode or getting a cid failed: - * try to initialize the device and try again. - * - * channel >= 0: getting cid for the channel failed - * channel < 0: entering cid mode failed - * - * returns 0 on success, <0 on failure - */ -static int reinit_and_retry(struct cardstate *cs, int channel) -{ - int i; - - if (--cs->retry_count <= 0) - return -EFAULT; - - for (i = 0; i < cs->channels; ++i) - if (cs->bcs[i].at_state.cid > 0) - return -EBUSY; - - if (channel < 0) - dev_warn(cs->dev, - "Could not enter cid mode. Reinit device and try again.\n"); - else { - dev_warn(cs->dev, - "Could not get a call id. Reinit device and try again.\n"); - cs->bcs[channel].at_state.pending_commands |= PC_CID; - } - schedule_init(cs, MS_INIT); - return 0; -} - -static int at_state_invalid(struct cardstate *cs, - struct at_state_t *test_ptr) -{ - unsigned long flags; - unsigned channel; - struct at_state_t *at_state; - int retval = 0; - - spin_lock_irqsave(&cs->lock, flags); - - if (test_ptr == &cs->at_state) - goto exit; - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (at_state == test_ptr) - goto exit; - - for (channel = 0; channel < cs->channels; ++channel) - if (&cs->bcs[channel].at_state == test_ptr) - goto exit; - - retval = 1; -exit: - spin_unlock_irqrestore(&cs->lock, flags); - return retval; -} - -static void handle_icall(struct cardstate *cs, struct bc_state *bcs, - struct at_state_t *at_state) -{ - int retval; - - retval = gigaset_isdn_icall(at_state); - switch (retval) { - case ICALL_ACCEPT: - break; - default: - dev_err(cs->dev, "internal error: disposition=%d\n", retval); - /* fall through */ - case ICALL_IGNORE: - case ICALL_REJECT: - /* hang up actively - * Device doc says that would reject the call. - * In fact it doesn't. - */ - at_state->pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - } -} - -static int do_lock(struct cardstate *cs) -{ - int mode; - int i; - - switch (cs->mstate) { - case MS_UNINITIALIZED: - case MS_READY: - if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || - cs->at_state.pending_commands) - return -EBUSY; - - for (i = 0; i < cs->channels; ++i) - if (cs->bcs[i].at_state.pending_commands) - return -EBUSY; - - if (gigaset_get_channels(cs) < 0) - return -EBUSY; - - break; - case MS_LOCKED: - break; - default: - return -EBUSY; - } - - mode = cs->mode; - cs->mstate = MS_LOCKED; - cs->mode = M_UNKNOWN; - - return mode; -} - -static int do_unlock(struct cardstate *cs) -{ - if (cs->mstate != MS_LOCKED) - return -EINVAL; - - cs->mstate = MS_UNINITIALIZED; - cs->mode = M_UNKNOWN; - gigaset_free_channels(cs); - if (cs->connected) - schedule_init(cs, MS_INIT); - - return 0; -} - -static void do_action(int action, struct cardstate *cs, - struct bc_state *bcs, - struct at_state_t **p_at_state, char **pp_command, - int *p_genresp, int *p_resp_code, - struct event_t *ev) -{ - struct at_state_t *at_state = *p_at_state; - struct bc_state *bcs2; - unsigned long flags; - - int channel; - - unsigned char *s, *e; - int i; - unsigned long val; - - switch (action) { - case ACT_NOTHING: - break; - case ACT_TIMEOUT: - at_state->waiting = 1; - break; - case ACT_INIT: - cs->at_state.pending_commands &= ~PC_INIT; - cs->cur_at_seq = SEQ_NONE; - cs->mode = M_UNIMODEM; - spin_lock_irqsave(&cs->lock, flags); - if (!cs->cidmode) { - spin_unlock_irqrestore(&cs->lock, flags); - gigaset_free_channels(cs); - cs->mstate = MS_READY; - break; - } - spin_unlock_irqrestore(&cs->lock, flags); - cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); - cs->commands_pending = 1; - break; - case ACT_FAILINIT: - dev_warn(cs->dev, "Could not initialize the device.\n"); - cs->dle = 0; - init_failed(cs, M_UNKNOWN); - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_CONFIGMODE: - init_failed(cs, M_CONFIG); - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_SETDLE1: - cs->dle = 1; - /* cs->inbuf[0].inputstate |= INS_command | INS_DLE_command; */ - cs->inbuf[0].inputstate &= - ~(INS_command | INS_DLE_command); - break; - case ACT_SETDLE0: - cs->dle = 0; - cs->inbuf[0].inputstate = - (cs->inbuf[0].inputstate & ~INS_DLE_command) - | INS_command; - break; - case ACT_CMODESET: - if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { - gigaset_free_channels(cs); - cs->mstate = MS_READY; - } - cs->mode = M_CID; - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_UMODESET: - cs->mode = M_UNIMODEM; - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_FAILCMODE: - cs->cur_at_seq = SEQ_NONE; - if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { - init_failed(cs, M_UNKNOWN); - break; - } - if (reinit_and_retry(cs, -1) < 0) - schedule_init(cs, MS_RECOVER); - break; - case ACT_FAILUMODE: - cs->cur_at_seq = SEQ_NONE; - schedule_init(cs, MS_RECOVER); - break; - case ACT_HUPMODEM: - /* send "+++" (hangup in unimodem mode) */ - if (cs->connected) { - struct cmdbuf_t *cb; - - cb = kmalloc(sizeof(struct cmdbuf_t) + 3, GFP_ATOMIC); - if (!cb) { - dev_err(cs->dev, "%s: out of memory\n", - __func__); - return; - } - memcpy(cb->buf, "+++", 3); - cb->len = 3; - cb->offset = 0; - cb->next = NULL; - cb->wake_tasklet = NULL; - cs->ops->write_cmd(cs, cb); - } - break; - case ACT_RING: - /* get fresh AT state structure for new CID */ - at_state = get_free_channel(cs, ev->parameter); - if (!at_state) { - dev_warn(cs->dev, - "RING ignored: could not allocate channel structure\n"); - break; - } - - /* initialize AT state structure - * note that bcs may be NULL if no B channel is free - */ - at_state->ConState = 700; - for (i = 0; i < STR_NUM; ++i) { - kfree(at_state->str_var[i]); - at_state->str_var[i] = NULL; - } - at_state->int_var[VAR_ZCTP] = -1; - - spin_lock_irqsave(&cs->lock, flags); - at_state->timer_expires = RING_TIMEOUT; - at_state->timer_active = 1; - spin_unlock_irqrestore(&cs->lock, flags); - break; - case ACT_ICALL: - handle_icall(cs, bcs, at_state); - break; - case ACT_FAILSDOWN: - dev_warn(cs->dev, "Could not shut down the device.\n"); - /* fall through */ - case ACT_FAKESDOWN: - case ACT_SDOWN: - cs->cur_at_seq = SEQ_NONE; - finish_shutdown(cs); - break; - case ACT_CONNECT: - if (cs->onechannel) { - at_state->pending_commands |= PC_DLE1; - cs->commands_pending = 1; - break; - } - bcs->chstate |= CHS_D_UP; - gigaset_isdn_connD(bcs); - cs->ops->init_bchannel(bcs); - break; - case ACT_DLE1: - cs->cur_at_seq = SEQ_NONE; - bcs = cs->bcs + cs->curchannel; - - bcs->chstate |= CHS_D_UP; - gigaset_isdn_connD(bcs); - cs->ops->init_bchannel(bcs); - break; - case ACT_FAKEHUP: - at_state->int_var[VAR_ZSAU] = ZSAU_NULL; - /* fall through */ - case ACT_DISCONNECT: - cs->cur_at_seq = SEQ_NONE; - at_state->cid = -1; - if (!bcs) { - disconnect_nobc(p_at_state, cs); - } else if (cs->onechannel && cs->dle) { - /* Check for other open channels not needed: - * DLE only used for M10x with one B channel. - */ - at_state->pending_commands |= PC_DLE0; - cs->commands_pending = 1; - } else { - disconnect_bc(at_state, cs, bcs); - } - break; - case ACT_FAKEDLE0: - at_state->int_var[VAR_ZDLE] = 0; - cs->dle = 0; - /* fall through */ - case ACT_DLE0: - cs->cur_at_seq = SEQ_NONE; - bcs2 = cs->bcs + cs->curchannel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - break; - case ACT_ABORTHUP: - cs->cur_at_seq = SEQ_NONE; - dev_warn(cs->dev, "Could not hang up.\n"); - at_state->cid = -1; - if (!bcs) - disconnect_nobc(p_at_state, cs); - else if (cs->onechannel) - at_state->pending_commands |= PC_DLE0; - else - disconnect_bc(at_state, cs, bcs); - schedule_init(cs, MS_RECOVER); - break; - case ACT_FAILDLE0: - cs->cur_at_seq = SEQ_NONE; - dev_warn(cs->dev, "Error leaving DLE mode.\n"); - cs->dle = 0; - bcs2 = cs->bcs + cs->curchannel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - schedule_init(cs, MS_RECOVER); - break; - case ACT_FAILDLE1: - cs->cur_at_seq = SEQ_NONE; - dev_warn(cs->dev, - "Could not enter DLE mode. Trying to hang up.\n"); - channel = cs->curchannel; - cs->bcs[channel].at_state.pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - - case ACT_CID: /* got cid; start dialing */ - cs->cur_at_seq = SEQ_NONE; - channel = cs->curchannel; - if (ev->parameter > 0 && ev->parameter <= 65535) { - cs->bcs[channel].at_state.cid = ev->parameter; - cs->bcs[channel].at_state.pending_commands |= - PC_DIAL; - cs->commands_pending = 1; - break; - } - /* fall through - bad cid */ - case ACT_FAILCID: - cs->cur_at_seq = SEQ_NONE; - channel = cs->curchannel; - if (reinit_and_retry(cs, channel) < 0) { - dev_warn(cs->dev, - "Could not get a call ID. Cannot dial.\n"); - bcs2 = cs->bcs + channel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - } - break; - case ACT_ABORTCID: - cs->cur_at_seq = SEQ_NONE; - bcs2 = cs->bcs + cs->curchannel; - disconnect_bc(&bcs2->at_state, cs, bcs2); - break; - - case ACT_DIALING: - case ACT_ACCEPTED: - cs->cur_at_seq = SEQ_NONE; - break; - - case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */ - if (bcs) - disconnect_bc(at_state, cs, bcs); - else - disconnect_nobc(p_at_state, cs); - break; - - case ACT_ABORTDIAL: /* error/timeout during dial preparation */ - cs->cur_at_seq = SEQ_NONE; - at_state->pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - - case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ - case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ - case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ - at_state->pending_commands |= PC_HUP; - cs->commands_pending = 1; - break; - case ACT_GETSTRING: /* warning: RING, ZDLE, ... - are not handled properly anymore */ - at_state->getstring = 1; - break; - case ACT_SETVER: - if (!ev->ptr) { - *p_genresp = 1; - *p_resp_code = RSP_ERROR; - break; - } - s = ev->ptr; - - if (!strcmp(s, "OK")) { - /* OK without version string: assume old response */ - *p_genresp = 1; - *p_resp_code = RSP_NONE; - break; - } - - for (i = 0; i < 4; ++i) { - val = simple_strtoul(s, (char **) &e, 10); - if (val > INT_MAX || e == s) - break; - if (i == 3) { - if (*e) - break; - } else if (*e != '.') - break; - else - s = e + 1; - cs->fwver[i] = val; - } - if (i != 4) { - *p_genresp = 1; - *p_resp_code = RSP_ERROR; - break; - } - cs->gotfwver = 0; - break; - case ACT_GOTVER: - if (cs->gotfwver == 0) { - cs->gotfwver = 1; - gig_dbg(DEBUG_EVENT, - "firmware version %02d.%03d.%02d.%02d", - cs->fwver[0], cs->fwver[1], - cs->fwver[2], cs->fwver[3]); - break; - } - /* fall through */ - case ACT_FAILVER: - cs->gotfwver = -1; - dev_err(cs->dev, "could not read firmware version.\n"); - break; - case ACT_ERROR: - gig_dbg(DEBUG_ANY, "%s: ERROR response in ConState %d", - __func__, at_state->ConState); - cs->cur_at_seq = SEQ_NONE; - break; - case ACT_DEBUG: - gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", - __func__, ev->type, at_state->ConState); - break; - case ACT_WARN: - dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n", - __func__, ev->type, at_state->ConState); - break; - case ACT_ZCAU: - dev_warn(cs->dev, "cause code %04x in connection state %d.\n", - ev->parameter, at_state->ConState); - break; - - /* events from the LL */ - - case ACT_DIAL: - if (!ev->ptr) { - *p_genresp = 1; - *p_resp_code = RSP_ERROR; - break; - } - start_dial(at_state, ev->ptr, ev->parameter); - break; - case ACT_ACCEPT: - start_accept(at_state); - break; - case ACT_HUP: - at_state->pending_commands |= PC_HUP; - gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); - cs->commands_pending = 1; - break; - - /* hotplug events */ - - case ACT_STOP: - do_stop(cs); - break; - case ACT_START: - do_start(cs); - break; - - /* events from the interface */ - - case ACT_IF_LOCK: - cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); - cs->waiting = 0; - wake_up(&cs->waitqueue); - break; - case ACT_IF_VER: - if (ev->parameter != 0) - cs->cmd_result = -EINVAL; - else if (cs->gotfwver != 1) { - cs->cmd_result = -ENOENT; - } else { - memcpy(ev->arg, cs->fwver, sizeof cs->fwver); - cs->cmd_result = 0; - } - cs->waiting = 0; - wake_up(&cs->waitqueue); - break; - - /* events from the proc file system */ - - case ACT_PROC_CIDMODE: - spin_lock_irqsave(&cs->lock, flags); - if (ev->parameter != cs->cidmode) { - cs->cidmode = ev->parameter; - if (ev->parameter) { - cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); - } else { - cs->at_state.pending_commands |= PC_UMMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); - } - cs->commands_pending = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - cs->waiting = 0; - wake_up(&cs->waitqueue); - break; - - /* events from the hardware drivers */ - - case ACT_NOTIFY_BC_DOWN: - bchannel_down(bcs); - break; - case ACT_NOTIFY_BC_UP: - bchannel_up(bcs); - break; - case ACT_SHUTDOWN: - do_shutdown(cs); - break; - - - default: - if (action >= ACT_CMD && action < ACT_CMD + AT_NUM) { - *pp_command = at_state->bcs->commands[action - ACT_CMD]; - if (!*pp_command) { - *p_genresp = 1; - *p_resp_code = RSP_NULL; - } - } else - dev_err(cs->dev, "%s: action==%d!\n", __func__, action); - } -} - -/* State machine to do the calling and hangup procedure */ -static void process_event(struct cardstate *cs, struct event_t *ev) -{ - struct bc_state *bcs; - char *p_command = NULL; - struct reply_t *rep; - int rcode; - int genresp = 0; - int resp_code = RSP_ERROR; - struct at_state_t *at_state; - int index; - int curact; - unsigned long flags; - - if (ev->cid >= 0) { - at_state = at_state_from_cid(cs, ev->cid); - if (!at_state) { - gig_dbg(DEBUG_EVENT, "event %d for invalid cid %d", - ev->type, ev->cid); - gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, - NULL, 0, NULL); - return; - } - } else { - at_state = ev->at_state; - if (at_state_invalid(cs, at_state)) { - gig_dbg(DEBUG_EVENT, "event for invalid at_state %p", - at_state); - return; - } - } - - gig_dbg(DEBUG_EVENT, "connection state %d, event %d", - at_state->ConState, ev->type); - - bcs = at_state->bcs; - - /* Setting the pointer to the dial array */ - rep = at_state->replystruct; - - spin_lock_irqsave(&cs->lock, flags); - if (ev->type == EV_TIMEOUT) { - if (ev->parameter != at_state->timer_index - || !at_state->timer_active) { - ev->type = RSP_NONE; /* old timeout */ - gig_dbg(DEBUG_EVENT, "old timeout"); - } else { - if (at_state->waiting) - gig_dbg(DEBUG_EVENT, "stopped waiting"); - else - gig_dbg(DEBUG_EVENT, "timeout occurred"); - } - } - spin_unlock_irqrestore(&cs->lock, flags); - - /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] - or at_state->str_var[STR_XXXX], set it */ - if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) { - index = ev->type - RSP_VAR; - at_state->int_var[index] = ev->parameter; - } else if (ev->type >= RSP_STR && ev->type < RSP_STR + STR_NUM) { - index = ev->type - RSP_STR; - kfree(at_state->str_var[index]); - at_state->str_var[index] = ev->ptr; - ev->ptr = NULL; /* prevent process_events() from - deallocating ptr */ - } - - if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING) - at_state->getstring = 0; - - /* Search row in dial array which matches modem response and current - constate */ - for (;; rep++) { - rcode = rep->resp_code; - if (rcode == RSP_LAST) { - /* found nothing...*/ - dev_warn(cs->dev, "%s: rcode=RSP_LAST: " - "resp_code %d in ConState %d!\n", - __func__, ev->type, at_state->ConState); - return; - } - if ((rcode == RSP_ANY || rcode == ev->type) - && ((int) at_state->ConState >= rep->min_ConState) - && (rep->max_ConState < 0 - || (int) at_state->ConState <= rep->max_ConState) - && (rep->parameter < 0 || rep->parameter == ev->parameter)) - break; - } - - p_command = rep->command; - - at_state->waiting = 0; - for (curact = 0; curact < MAXACT; ++curact) { - /* The row tells us what we should do .. - */ - do_action(rep->action[curact], cs, bcs, &at_state, &p_command, - &genresp, &resp_code, ev); - if (!at_state) - /* at_state destroyed by disconnect */ - return; - } - - /* Jump to the next con-state regarding the array */ - if (rep->new_ConState >= 0) - at_state->ConState = rep->new_ConState; - - if (genresp) { - spin_lock_irqsave(&cs->lock, flags); - at_state->timer_expires = 0; - at_state->timer_active = 0; - spin_unlock_irqrestore(&cs->lock, flags); - gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); - } else { - /* Send command to modem if not NULL... */ - if (p_command) { - if (cs->connected) - send_command(cs, p_command, at_state); - else - gigaset_add_event(cs, at_state, RSP_NODEV, - NULL, 0, NULL); - } - - spin_lock_irqsave(&cs->lock, flags); - if (!rep->timeout) { - at_state->timer_expires = 0; - at_state->timer_active = 0; - } else if (rep->timeout > 0) { /* new timeout */ - at_state->timer_expires = rep->timeout * 10; - at_state->timer_active = 1; - ++at_state->timer_index; - } - spin_unlock_irqrestore(&cs->lock, flags); - } -} - -static void schedule_sequence(struct cardstate *cs, - struct at_state_t *at_state, int sequence) -{ - cs->cur_at_seq = sequence; - gigaset_add_event(cs, at_state, RSP_INIT, NULL, sequence, NULL); -} - -static void process_command_flags(struct cardstate *cs) -{ - struct at_state_t *at_state = NULL; - struct bc_state *bcs; - int i; - int sequence; - unsigned long flags; - - cs->commands_pending = 0; - - if (cs->cur_at_seq) { - gig_dbg(DEBUG_EVENT, "not searching scheduled commands: busy"); - return; - } - - gig_dbg(DEBUG_EVENT, "searching scheduled commands"); - - sequence = SEQ_NONE; - - /* clear pending_commands and hangup channels on shutdown */ - if (cs->at_state.pending_commands & PC_SHUTDOWN) { - cs->at_state.pending_commands &= ~PC_CIDMODE; - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - at_state = &bcs->at_state; - at_state->pending_commands &= - ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); - if (at_state->cid > 0) - at_state->pending_commands |= PC_HUP; - if (at_state->pending_commands & PC_CID) { - at_state->pending_commands |= PC_NOCID; - at_state->pending_commands &= ~PC_CID; - } - } - } - - /* clear pending_commands and hangup channels on reset */ - if (cs->at_state.pending_commands & PC_INIT) { - cs->at_state.pending_commands &= ~PC_CIDMODE; - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - at_state = &bcs->at_state; - at_state->pending_commands &= - ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); - if (at_state->cid > 0) - at_state->pending_commands |= PC_HUP; - if (cs->mstate == MS_RECOVER) { - if (at_state->pending_commands & PC_CID) { - at_state->pending_commands |= PC_NOCID; - at_state->pending_commands &= ~PC_CID; - } - } - } - } - - /* only switch back to unimodem mode if no commands are pending and - * no channels are up */ - spin_lock_irqsave(&cs->lock, flags); - if (cs->at_state.pending_commands == PC_UMMODE - && !cs->cidmode - && list_empty(&cs->temp_at_states) - && cs->mode == M_CID) { - sequence = SEQ_UMMODE; - at_state = &cs->at_state; - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - if (bcs->at_state.pending_commands || - bcs->at_state.cid > 0) { - sequence = SEQ_NONE; - break; - } - } - } - spin_unlock_irqrestore(&cs->lock, flags); - cs->at_state.pending_commands &= ~PC_UMMODE; - if (sequence != SEQ_NONE) { - schedule_sequence(cs, at_state, sequence); - return; - } - - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - if (bcs->at_state.pending_commands & PC_HUP) { - if (cs->dle) { - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_DLE0); - return; - } - bcs->at_state.pending_commands &= ~PC_HUP; - if (bcs->at_state.pending_commands & PC_CID) { - /* not yet dialing: PC_NOCID is sufficient */ - bcs->at_state.pending_commands |= PC_NOCID; - bcs->at_state.pending_commands &= ~PC_CID; - } else { - schedule_sequence(cs, &bcs->at_state, SEQ_HUP); - return; - } - } - if (bcs->at_state.pending_commands & PC_NOCID) { - bcs->at_state.pending_commands &= ~PC_NOCID; - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_NOCID); - return; - } else if (bcs->at_state.pending_commands & PC_DLE0) { - bcs->at_state.pending_commands &= ~PC_DLE0; - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_DLE0); - return; - } - } - - list_for_each_entry(at_state, &cs->temp_at_states, list) - if (at_state->pending_commands & PC_HUP) { - at_state->pending_commands &= ~PC_HUP; - schedule_sequence(cs, at_state, SEQ_HUP); - return; - } - - if (cs->at_state.pending_commands & PC_INIT) { - cs->at_state.pending_commands &= ~PC_INIT; - cs->dle = 0; - cs->inbuf->inputstate = INS_command; - schedule_sequence(cs, &cs->at_state, SEQ_INIT); - return; - } - if (cs->at_state.pending_commands & PC_SHUTDOWN) { - cs->at_state.pending_commands &= ~PC_SHUTDOWN; - schedule_sequence(cs, &cs->at_state, SEQ_SHUTDOWN); - return; - } - if (cs->at_state.pending_commands & PC_CIDMODE) { - cs->at_state.pending_commands &= ~PC_CIDMODE; - if (cs->mode == M_UNIMODEM) { - cs->retry_count = 1; - schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); - return; - } - } - - for (i = 0; i < cs->channels; ++i) { - bcs = cs->bcs + i; - if (bcs->at_state.pending_commands & PC_DLE1) { - bcs->at_state.pending_commands &= ~PC_DLE1; - cs->curchannel = bcs->channel; - schedule_sequence(cs, &cs->at_state, SEQ_DLE1); - return; - } - if (bcs->at_state.pending_commands & PC_ACCEPT) { - bcs->at_state.pending_commands &= ~PC_ACCEPT; - schedule_sequence(cs, &bcs->at_state, SEQ_ACCEPT); - return; - } - if (bcs->at_state.pending_commands & PC_DIAL) { - bcs->at_state.pending_commands &= ~PC_DIAL; - schedule_sequence(cs, &bcs->at_state, SEQ_DIAL); - return; - } - if (bcs->at_state.pending_commands & PC_CID) { - switch (cs->mode) { - case M_UNIMODEM: - cs->at_state.pending_commands |= PC_CIDMODE; - gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); - cs->commands_pending = 1; - return; - case M_UNKNOWN: - schedule_init(cs, MS_INIT); - return; - } - bcs->at_state.pending_commands &= ~PC_CID; - cs->curchannel = bcs->channel; - cs->retry_count = 2; - schedule_sequence(cs, &cs->at_state, SEQ_CID); - return; - } - } -} - -static void process_events(struct cardstate *cs) -{ - struct event_t *ev; - unsigned head, tail; - int i; - int check_flags = 0; - int was_busy; - unsigned long flags; - - spin_lock_irqsave(&cs->ev_lock, flags); - head = cs->ev_head; - - for (i = 0; i < 2 * MAX_EVENTS; ++i) { - tail = cs->ev_tail; - if (tail == head) { - if (!check_flags && !cs->commands_pending) - break; - check_flags = 0; - spin_unlock_irqrestore(&cs->ev_lock, flags); - process_command_flags(cs); - spin_lock_irqsave(&cs->ev_lock, flags); - tail = cs->ev_tail; - if (tail == head) { - if (!cs->commands_pending) - break; - continue; - } - } - - ev = cs->events + head; - was_busy = cs->cur_at_seq != SEQ_NONE; - spin_unlock_irqrestore(&cs->ev_lock, flags); - process_event(cs, ev); - spin_lock_irqsave(&cs->ev_lock, flags); - kfree(ev->ptr); - ev->ptr = NULL; - if (was_busy && cs->cur_at_seq == SEQ_NONE) - check_flags = 1; - - head = (head + 1) % MAX_EVENTS; - cs->ev_head = head; - } - - spin_unlock_irqrestore(&cs->ev_lock, flags); - - if (i == 2 * MAX_EVENTS) { - dev_err(cs->dev, - "infinite loop in process_events; aborting.\n"); - } -} - -/* tasklet scheduled on any event received from the Gigaset device - * parameter: - * data ISDN controller state structure - */ -void gigaset_handle_event(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *) data; - - /* handle incoming data on control/common channel */ - if (cs->inbuf->head != cs->inbuf->tail) { - gig_dbg(DEBUG_INTR, "processing new data"); - cs->ops->handle_input(cs->inbuf); - } - - process_events(cs); -} diff --git a/drivers/staging/isdn/gigaset/gigaset.h b/drivers/staging/isdn/gigaset/gigaset.h deleted file mode 100644 index 0ecc2b5ea553..000000000000 --- a/drivers/staging/isdn/gigaset/gigaset.h +++ /dev/null @@ -1,827 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Siemens Gigaset 307x driver - * Common header file for all connection variants - * - * Written by Stefan Eilers - * and Hansjoerg Lipp - * - * ===================================================================== - * ===================================================================== - */ - -#ifndef GIGASET_H -#define GIGASET_H - -/* define global prefix for pr_ macros in linux/kernel.h */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GIG_VERSION {0, 5, 0, 0} -#define GIG_COMPAT {0, 4, 0, 0} - -#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ -#define MAX_RESP_SIZE 511 /* Max. size of a response string */ - -#define MAX_EVENTS 64 /* size of event queue */ - -#define RBUFSIZE 8192 - -#define GIG_TICK 100 /* in milliseconds */ - -/* timeout values (unit: 1 sec) */ -#define INIT_TIMEOUT 1 - -/* timeout values (unit: 0.1 sec) */ -#define RING_TIMEOUT 3 /* for additional parameters to RING */ -#define BAS_TIMEOUT 20 /* for response to Base USB ops */ -#define ATRDY_TIMEOUT 3 /* for HD_READY_SEND_ATDATA */ - -#define BAS_RETRY 3 /* max. retries for base USB ops */ - -#define MAXACT 3 - -extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ - -/* debug flags, combine by adding/bitwise OR */ -enum debuglevel { - DEBUG_INTR = 0x00008, /* interrupt processing */ - DEBUG_CMD = 0x00020, /* sent/received LL commands */ - DEBUG_STREAM = 0x00040, /* application data stream I/O events */ - DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ - DEBUG_LLDATA = 0x00100, /* sent/received LL data */ - DEBUG_EVENT = 0x00200, /* event processing */ - DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ - DEBUG_CHANNEL = 0x01000, /* channel allocation/deallocation */ - DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ - DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ - DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data - structures */ - DEBUG_SUSPEND = 0x10000, /* suspend/resume processing */ - DEBUG_OUTPUT = 0x20000, /* output to device */ - DEBUG_ISO = 0x40000, /* isochronous transfers */ - DEBUG_IF = 0x80000, /* character device operations */ - DEBUG_USBREQ = 0x100000, /* USB communication (except payload - data) */ - DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when - MS_LOCKED */ - - DEBUG_ANY = 0x3fffff, /* print message if any of the others is - activated */ -}; - -#ifdef CONFIG_GIGASET_DEBUG - -#define gig_dbg(level, format, arg...) \ - do { \ - if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ - printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ - ## arg); \ - } while (0) -#define DEBUG_DEFAULT (DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) - -#else - -#define gig_dbg(level, format, arg...) do {} while (0) -#define DEBUG_DEFAULT 0 - -#endif - -void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf); - -/* connection state */ -#define ZSAU_NONE 0 -#define ZSAU_PROCEEDING 1 -#define ZSAU_CALL_DELIVERED 2 -#define ZSAU_ACTIVE 3 -#define ZSAU_DISCONNECT_IND 4 -#define ZSAU_NULL 5 -#define ZSAU_DISCONNECT_REQ 6 -#define ZSAU_UNKNOWN -1 - -/* USB control transfer requests */ -#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) -#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) - -/* interrupt pipe messages */ -#define HD_B1_FLOW_CONTROL 0x80 -#define HD_B2_FLOW_CONTROL 0x81 -#define HD_RECEIVEATDATA_ACK (0x35) /* 3070 */ -#define HD_READY_SEND_ATDATA (0x36) /* 3070 */ -#define HD_OPEN_ATCHANNEL_ACK (0x37) /* 3070 */ -#define HD_CLOSE_ATCHANNEL_ACK (0x38) /* 3070 */ -#define HD_DEVICE_INIT_OK (0x11) /* ISurf USB + 3070 */ -#define HD_OPEN_B1CHANNEL_ACK (0x51) /* ISurf USB + 3070 */ -#define HD_OPEN_B2CHANNEL_ACK (0x52) /* ISurf USB + 3070 */ -#define HD_CLOSE_B1CHANNEL_ACK (0x53) /* ISurf USB + 3070 */ -#define HD_CLOSE_B2CHANNEL_ACK (0x54) /* ISurf USB + 3070 */ -#define HD_SUSPEND_END (0x61) /* ISurf USB */ -#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) /* ISurf USB + 3070 */ - -/* control requests */ -#define HD_OPEN_B1CHANNEL (0x23) /* ISurf USB + 3070 */ -#define HD_CLOSE_B1CHANNEL (0x24) /* ISurf USB + 3070 */ -#define HD_OPEN_B2CHANNEL (0x25) /* ISurf USB + 3070 */ -#define HD_CLOSE_B2CHANNEL (0x26) /* ISurf USB + 3070 */ -#define HD_RESET_INTERRUPT_PIPE (0x27) /* ISurf USB + 3070 */ -#define HD_DEVICE_INIT_ACK (0x34) /* ISurf USB + 3070 */ -#define HD_WRITE_ATMESSAGE (0x12) /* 3070 */ -#define HD_READ_ATMESSAGE (0x13) /* 3070 */ -#define HD_OPEN_ATCHANNEL (0x28) /* 3070 */ -#define HD_CLOSE_ATCHANNEL (0x29) /* 3070 */ - -/* number of B channels supported by base driver */ -#define BAS_CHANNELS 2 - -/* USB frames for isochronous transfer */ -#define BAS_FRAMETIME 1 /* number of milliseconds between frames */ -#define BAS_NUMFRAMES 8 /* number of frames per URB */ -#define BAS_MAXFRAME 16 /* allocated bytes per frame */ -#define BAS_NORMFRAME 8 /* send size without flow control */ -#define BAS_HIGHFRAME 10 /* " " with positive flow control */ -#define BAS_LOWFRAME 5 /* " " with negative flow control */ -#define BAS_CORRFRAMES 4 /* flow control multiplicator */ - -#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isoc in buf - * per URB */ -#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */ -#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */ - -#define BAS_INURBS 3 -#define BAS_OUTURBS 3 - -/* variable commands in struct bc_state */ -#define AT_ISO 0 -#define AT_DIAL 1 -#define AT_MSN 2 -#define AT_BC 3 -#define AT_PROTO 4 -#define AT_TYPE 5 -#define AT_CLIP 6 -/* total number */ -#define AT_NUM 7 - -/* variables in struct at_state_t */ -/* - numeric */ -#define VAR_ZSAU 0 -#define VAR_ZDLE 1 -#define VAR_ZCTP 2 -/* total number */ -#define VAR_NUM 3 -/* - string */ -#define STR_NMBR 0 -#define STR_ZCPN 1 -#define STR_ZCON 2 -#define STR_ZBC 3 -#define STR_ZHLC 4 -/* total number */ -#define STR_NUM 5 - -/* event types */ -#define EV_TIMEOUT -105 -#define EV_IF_VER -106 -#define EV_PROC_CIDMODE -107 -#define EV_SHUTDOWN -108 -#define EV_START -110 -#define EV_STOP -111 -#define EV_IF_LOCK -112 -#define EV_ACCEPT -114 -#define EV_DIAL -115 -#define EV_HUP -116 -#define EV_BC_OPEN -117 -#define EV_BC_CLOSED -118 - -/* input state */ -#define INS_command 0x0001 /* receiving messages (not payload data) */ -#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ -#define INS_byte_stuff 0x0004 -#define INS_have_data 0x0008 -#define INS_DLE_command 0x0020 /* DLE message start ( X) received */ -#define INS_flag_hunt 0x0040 - -/* channel state */ -#define CHS_D_UP 0x01 -#define CHS_B_UP 0x02 -#define CHS_NOTIFY_LL 0x04 - -#define ICALL_REJECT 0 -#define ICALL_ACCEPT 1 -#define ICALL_IGNORE 2 - -/* device state */ -#define MS_UNINITIALIZED 0 -#define MS_INIT 1 -#define MS_LOCKED 2 -#define MS_SHUTDOWN 3 -#define MS_RECOVER 4 -#define MS_READY 5 - -/* mode */ -#define M_UNKNOWN 0 -#define M_CONFIG 1 -#define M_UNIMODEM 2 -#define M_CID 3 - -/* start mode */ -#define SM_LOCKED 0 -#define SM_ISDN 1 /* default */ - -/* layer 2 protocols (AT^SBPR=...) */ -#define L2_BITSYNC 0 -#define L2_HDLC 1 -#define L2_VOICE 2 - -struct gigaset_ops; -struct gigaset_driver; - -struct usb_cardstate; -struct ser_cardstate; -struct bas_cardstate; - -struct bc_state; -struct usb_bc_state; -struct ser_bc_state; -struct bas_bc_state; - -struct reply_t { - int resp_code; /* RSP_XXXX */ - int min_ConState; /* <0 => ignore */ - int max_ConState; /* <0 => ignore */ - int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ - int new_ConState; /* <0 => ignore */ - int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ - int action[MAXACT]; /* ACT_XXXX */ - char *command; /* NULL==none */ -}; - -extern struct reply_t gigaset_tab_cid[]; -extern struct reply_t gigaset_tab_nocid[]; - -struct inbuf_t { - struct cardstate *cs; - int inputstate; - int head, tail; - unsigned char data[RBUFSIZE]; -}; - -/* isochronous write buffer structure - * circular buffer with pad area for extraction of complete USB frames - * - data[read..nextread-1] is valid data already submitted to the USB subsystem - * - data[nextread..write-1] is valid data yet to be sent - * - data[write] is the next byte to write to - * - in byte-oriented L2 procotols, it is completely free - * - in bit-oriented L2 procotols, it may contain a partial byte of valid data - * - data[write+1..read-1] is free - * - wbits is the number of valid data bits in data[write], starting at the LSB - * - writesem is the semaphore for writing to the buffer: - * if writesem <= 0, data[write..read-1] is currently being written to - * - idle contains the byte value to repeat when the end of valid data is - * reached; if nextread==write (buffer contains no data to send), either the - * BAS_OUTBUFPAD bytes immediately before data[write] (if - * write>=BAS_OUTBUFPAD) or those of the pad area (if write for modem reponses (and - * incoming data for M10x) - * -> on timeout - * -> after setting bits in - * xxx.at_state.pending_command - * (e.g. command from LL) */ - struct tasklet_struct - write_tasklet; /* tasklet for serial output - * (not used in base driver) */ - - /* event queue */ - struct event_t events[MAX_EVENTS]; - unsigned ev_tail, ev_head; - spinlock_t ev_lock; - - /* current modem response */ - unsigned char respdata[MAX_RESP_SIZE + 1]; - unsigned cbytes; - - /* private data of hardware drivers */ - union { - struct usb_cardstate *usb; /* USB hardware driver (m105) */ - struct ser_cardstate *ser; /* serial hardware driver */ - struct bas_cardstate *bas; /* USB hardware driver (base) */ - } hw; -}; - -struct gigaset_driver { - struct list_head list; - spinlock_t lock; /* locks minor tables and blocked */ - struct tty_driver *tty; - unsigned have_tty; - unsigned minor; - unsigned minors; - struct cardstate *cs; - int blocked; - - const struct gigaset_ops *ops; - struct module *owner; -}; - -struct cmdbuf_t { - struct cmdbuf_t *next, *prev; - int len, offset; - struct tasklet_struct *wake_tasklet; - unsigned char buf[0]; -}; - -struct bas_bc_state { - /* isochronous output state */ - int running; - atomic_t corrbytes; - spinlock_t isooutlock; - struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; - struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl; - struct isowbuf_t *isooutbuf; - unsigned numsub; /* submitted URB counter - (for diagnostic messages only) */ - struct tasklet_struct sent_tasklet; - - /* isochronous input state */ - spinlock_t isoinlock; - struct urb *isoinurbs[BAS_INURBS]; - unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; - struct urb *isoindone; /* completed isoc read URB */ - int isoinstatus; /* status of completed URB */ - int loststatus; /* status of dropped URB */ - unsigned isoinlost; /* number of bytes lost */ - /* state of bit unstuffing algorithm - (in addition to BC_state.inputstate) */ - unsigned seqlen; /* number of '1' bits not yet - unstuffed */ - unsigned inbyte, inbits; /* collected bits for next byte */ - /* statistics */ - unsigned goodbytes; /* bytes correctly received */ - unsigned alignerrs; /* frames with incomplete byte at end */ - unsigned fcserrs; /* FCS errors */ - unsigned frameerrs; /* framing errors */ - unsigned giants; /* long frames */ - unsigned runts; /* short frames */ - unsigned aborts; /* HDLC aborts */ - unsigned shared0s; /* '0' bits shared between flags */ - unsigned stolen0s; /* '0' stuff bits also serving as - leading flag bits */ - struct tasklet_struct rcvd_tasklet; -}; - -struct gigaset_ops { - /* Called from ev-layer.c/interface.c for sending AT commands to the - device */ - int (*write_cmd)(struct cardstate *cs, struct cmdbuf_t *cb); - - /* Called from interface.c for additional device control */ - int (*write_room)(struct cardstate *cs); - int (*chars_in_buffer)(struct cardstate *cs); - int (*brkchars)(struct cardstate *cs, const unsigned char buf[6]); - - /* Called from ev-layer.c after setting up connection - * Should call gigaset_bchannel_up(), when finished. */ - int (*init_bchannel)(struct bc_state *bcs); - - /* Called from ev-layer.c after hanging up - * Should call gigaset_bchannel_down(), when finished. */ - int (*close_bchannel)(struct bc_state *bcs); - - /* Called by gigaset_initcs() for setting up bcs->hw.xxx */ - int (*initbcshw)(struct bc_state *bcs); - - /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ - void (*freebcshw)(struct bc_state *bcs); - - /* Called by gigaset_bchannel_down() for resetting bcs->hw.xxx */ - void (*reinitbcshw)(struct bc_state *bcs); - - /* Called by gigaset_initcs() for setting up cs->hw.xxx */ - int (*initcshw)(struct cardstate *cs); - - /* Called by gigaset_freecs() for freeing cs->hw.xxx */ - void (*freecshw)(struct cardstate *cs); - - /* Called from common.c/interface.c for additional serial port - control */ - int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, - unsigned new_state); - int (*baud_rate)(struct cardstate *cs, unsigned cflag); - int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); - - /* Called from LL interface to put an skb into the send-queue. - * After sending is completed, gigaset_skb_sent() must be called - * with the skb's link layer header preserved. */ - int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); - - /* Called from ev-layer.c to process a block of data - * received through the common/control channel. */ - void (*handle_input)(struct inbuf_t *inbuf); - -}; - -/* = Common structures and definitions ======================================= - */ - -/* Parser states for DLE-Event: - * : "X" "." - * : 0x10 - * : ((a-z)* | (A-Z)* | (0-10)*)+ - */ -#define DLE_FLAG 0x10 - -/* =========================================================================== - * Functions implemented in asyncdata.c - */ - -/* Called from LL interface to put an skb into the send queue. */ -int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); - -/* Called from ev-layer.c to process a block of data - * received through the common/control channel. */ -void gigaset_m10x_input(struct inbuf_t *inbuf); - -/* =========================================================================== - * Functions implemented in isocdata.c - */ - -/* Called from LL interface to put an skb into the send queue. */ -int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); - -/* Called from ev-layer.c to process a block of data - * received through the common/control channel. */ -void gigaset_isoc_input(struct inbuf_t *inbuf); - -/* Called from bas-gigaset.c to process a block of data - * received through the isochronous channel */ -void gigaset_isoc_receive(unsigned char *src, unsigned count, - struct bc_state *bcs); - -/* Called from bas-gigaset.c to put a block of data - * into the isochronous output buffer */ -int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len); - -/* Called from bas-gigaset.c to initialize the isochronous output buffer */ -void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); - -/* Called from bas-gigaset.c to retrieve a block of bytes for sending */ -int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); - -/* =========================================================================== - * Functions implemented in LL interface - */ - -/* Called from common.c for setting up/shutting down with the ISDN subsystem */ -void gigaset_isdn_regdrv(void); -void gigaset_isdn_unregdrv(void); -int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid); -void gigaset_isdn_unregdev(struct cardstate *cs); - -/* Called from hardware module to indicate completion of an skb */ -void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); -void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb); -void gigaset_isdn_rcv_err(struct bc_state *bcs); - -/* Called from common.c/ev-layer.c to indicate events relevant to the LL */ -void gigaset_isdn_start(struct cardstate *cs); -void gigaset_isdn_stop(struct cardstate *cs); -int gigaset_isdn_icall(struct at_state_t *at_state); -void gigaset_isdn_connD(struct bc_state *bcs); -void gigaset_isdn_hupD(struct bc_state *bcs); -void gigaset_isdn_connB(struct bc_state *bcs); -void gigaset_isdn_hupB(struct bc_state *bcs); - -/* =========================================================================== - * Functions implemented in ev-layer.c - */ - -/* tasklet called from common.c to process queued events */ -void gigaset_handle_event(unsigned long data); - -/* called from isocdata.c / asyncdata.c - * when a complete modem response line has been received */ -void gigaset_handle_modem_response(struct cardstate *cs); - -/* =========================================================================== - * Functions implemented in proc.c - */ - -/* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct cardstate *cs); -void gigaset_free_dev_sysfs(struct cardstate *cs); - -/* =========================================================================== - * Functions implemented in common.c/gigaset.h - */ - -void gigaset_bcs_reinit(struct bc_state *bcs); -void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid); -int gigaset_get_channel(struct bc_state *bcs); -struct bc_state *gigaset_get_free_channel(struct cardstate *cs); -void gigaset_free_channel(struct bc_state *bcs); -int gigaset_get_channels(struct cardstate *cs); -void gigaset_free_channels(struct cardstate *cs); -void gigaset_block_channels(struct cardstate *cs); - -/* Allocate and initialize driver structure. */ -struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const struct gigaset_ops *ops, - struct module *owner); - -/* Deallocate driver structure. */ -void gigaset_freedriver(struct gigaset_driver *drv); - -struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); -struct cardstate *gigaset_get_cs_by_id(int id); -void gigaset_blockdriver(struct gigaset_driver *drv); - -/* Allocate and initialize card state. Calls hardware dependent - gigaset_init[b]cs(). */ -struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, - int onechannel, int ignoreframes, - int cidmode, const char *modulename); - -/* Free card state. Calls hardware dependent gigaset_free[b]cs(). */ -void gigaset_freecs(struct cardstate *cs); - -/* Tell common.c that hardware and driver are ready. */ -int gigaset_start(struct cardstate *cs); - -/* Tell common.c that the device is not present any more. */ -void gigaset_stop(struct cardstate *cs); - -/* Tell common.c that the driver is being unloaded. */ -int gigaset_shutdown(struct cardstate *cs); - -/* Append event to the queue. - * Returns NULL on failure or a pointer to the event on success. - * ptr must be kmalloc()ed (and not be freed by the caller). - */ -struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg); - -/* Called on CONFIG1 command from frontend. */ -int gigaset_enterconfigmode(struct cardstate *cs); - -/* cs->lock must not be locked */ -static inline void gigaset_schedule_event(struct cardstate *cs) -{ - unsigned long flags; - spin_lock_irqsave(&cs->lock, flags); - if (cs->running) - tasklet_schedule(&cs->event_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); -} - -/* Tell common.c that B channel has been closed. */ -/* cs->lock must not be locked */ -static inline void gigaset_bchannel_down(struct bc_state *bcs) -{ - gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); - gigaset_schedule_event(bcs->cs); -} - -/* Tell common.c that B channel has been opened. */ -/* cs->lock must not be locked */ -static inline void gigaset_bchannel_up(struct bc_state *bcs) -{ - gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); - gigaset_schedule_event(bcs->cs); -} - -/* set up next receive skb for data mode */ -static inline struct sk_buff *gigaset_new_rx_skb(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - unsigned short hw_hdr_len = cs->hw_hdr_len; - - if (bcs->ignore) { - bcs->rx_skb = NULL; - } else { - bcs->rx_skb = dev_alloc_skb(bcs->rx_bufsize + hw_hdr_len); - if (bcs->rx_skb == NULL) - dev_warn(cs->dev, "could not allocate skb\n"); - else - skb_reserve(bcs->rx_skb, hw_hdr_len); - } - return bcs->rx_skb; -} - -/* append received bytes to inbuf */ -int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, - unsigned numbytes); - -/* =========================================================================== - * Functions implemented in interface.c - */ - -/* initialize interface */ -void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname); -/* release interface */ -void gigaset_if_freedriver(struct gigaset_driver *drv); -/* add minor */ -void gigaset_if_init(struct cardstate *cs); -/* remove minor */ -void gigaset_if_free(struct cardstate *cs); -/* device received data */ -void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len); - -#endif diff --git a/drivers/staging/isdn/gigaset/interface.c b/drivers/staging/isdn/gigaset/interface.c deleted file mode 100644 index 9ddadd07e707..000000000000 --- a/drivers/staging/isdn/gigaset/interface.c +++ /dev/null @@ -1,613 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * interface to user space for the gigaset driver - * - * Copyright (c) 2004 by Hansjoerg Lipp - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/*** our ioctls ***/ - -static int if_lock(struct cardstate *cs, int *arg) -{ - int cmd = *arg; - - gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); - - if (cmd > 1) - return -EINVAL; - - if (cmd < 0) { - *arg = cs->mstate == MS_LOCKED; - return 0; - } - - if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { - cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR | TIOCM_RTS); - cs->ops->baud_rate(cs, B115200); - cs->ops->set_line_ctrl(cs, CS8); - cs->control_state = TIOCM_DTR | TIOCM_RTS; - } - - cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK, - NULL, cmd, NULL)) { - cs->waiting = 0; - return -ENOMEM; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - if (cs->cmd_result >= 0) { - *arg = cs->cmd_result; - return 0; - } - - return cs->cmd_result; -} - -static int if_version(struct cardstate *cs, unsigned arg[4]) -{ - static const unsigned version[4] = GIG_VERSION; - static const unsigned compat[4] = GIG_COMPAT; - unsigned cmd = arg[0]; - - gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); - - switch (cmd) { - case GIGVER_DRIVER: - memcpy(arg, version, sizeof version); - return 0; - case GIGVER_COMPAT: - memcpy(arg, compat, sizeof compat); - return 0; - case GIGVER_FWBASE: - cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER, - NULL, 0, arg)) { - cs->waiting = 0; - return -ENOMEM; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - if (cs->cmd_result >= 0) - return 0; - - return cs->cmd_result; - default: - return -EINVAL; - } -} - -static int if_config(struct cardstate *cs, int *arg) -{ - gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); - - if (*arg != 1) - return -EINVAL; - - if (cs->mstate != MS_LOCKED) - return -EBUSY; - - if (!cs->connected) { - pr_err("%s: not connected\n", __func__); - return -ENODEV; - } - - *arg = 0; - return gigaset_enterconfigmode(cs); -} - -/*** the terminal driver ***/ - -static int if_open(struct tty_struct *tty, struct file *filp) -{ - struct cardstate *cs; - - gig_dbg(DEBUG_IF, "%d+%d: %s()", - tty->driver->minor_start, tty->index, __func__); - - cs = gigaset_get_cs_by_tty(tty); - if (!cs || !try_module_get(cs->driver->owner)) - return -ENODEV; - - if (mutex_lock_interruptible(&cs->mutex)) { - module_put(cs->driver->owner); - return -ERESTARTSYS; - } - tty->driver_data = cs; - - ++cs->port.count; - - if (cs->port.count == 1) { - tty_port_tty_set(&cs->port, tty); - cs->port.low_latency = 1; - } - - mutex_unlock(&cs->mutex); - return 0; -} - -static void if_close(struct tty_struct *tty, struct file *filp) -{ - struct cardstate *cs = tty->driver_data; - - if (!cs) { /* happens if we didn't find cs in open */ - gig_dbg(DEBUG_IF, "%s: no cardstate", __func__); - return; - } - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else if (!cs->port.count) - dev_warn(cs->dev, "%s: device not opened\n", __func__); - else if (!--cs->port.count) - tty_port_tty_set(&cs->port, NULL); - - mutex_unlock(&cs->mutex); - - module_put(cs->driver->owner); -} - -static int if_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct cardstate *cs = tty->driver_data; - int retval = -ENODEV; - int int_arg; - unsigned char buf[6]; - unsigned version[4]; - - gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else { - retval = 0; - switch (cmd) { - case GIGASET_REDIR: - retval = get_user(int_arg, (int __user *) arg); - if (retval >= 0) - retval = if_lock(cs, &int_arg); - if (retval >= 0) - retval = put_user(int_arg, (int __user *) arg); - break; - case GIGASET_CONFIG: - retval = get_user(int_arg, (int __user *) arg); - if (retval >= 0) - retval = if_config(cs, &int_arg); - if (retval >= 0) - retval = put_user(int_arg, (int __user *) arg); - break; - case GIGASET_BRKCHARS: - retval = copy_from_user(&buf, - (const unsigned char __user *) arg, 6) - ? -EFAULT : 0; - if (retval >= 0) { - gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", - 6, buf); - retval = cs->ops->brkchars(cs, buf); - } - break; - case GIGASET_VERSION: - retval = copy_from_user(version, - (unsigned __user *) arg, sizeof version) - ? -EFAULT : 0; - if (retval >= 0) - retval = if_version(cs, version); - if (retval >= 0) - retval = copy_to_user((unsigned __user *) arg, - version, sizeof version) - ? -EFAULT : 0; - break; - default: - gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", - __func__, cmd); - retval = -ENOIOCTLCMD; - } - } - - mutex_unlock(&cs->mutex); - - return retval; -} - -#ifdef CONFIG_COMPAT -static long if_compat_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - return if_ioctl(tty, cmd, (unsigned long)compat_ptr(arg)); -} -#endif - -static int if_tiocmget(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - int retval; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - retval = cs->control_state & (TIOCM_RTS | TIOCM_DTR); - - mutex_unlock(&cs->mutex); - - return retval; -} - -static int if_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct cardstate *cs = tty->driver_data; - int retval; - unsigned mc; - - gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)", - cs->minor_index, __func__, set, clear); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else { - mc = (cs->control_state | set) & ~clear & (TIOCM_RTS | TIOCM_DTR); - retval = cs->ops->set_modem_ctrl(cs, cs->control_state, mc); - cs->control_state = mc; - } - - mutex_unlock(&cs->mutex); - - return retval; -} - -static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) -{ - struct cardstate *cs = tty->driver_data; - struct cmdbuf_t *cb; - int retval; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - goto done; - } - if (cs->mstate != MS_LOCKED) { - dev_warn(cs->dev, "can't write to unlocked device\n"); - retval = -EBUSY; - goto done; - } - if (count <= 0) { - /* nothing to do */ - retval = 0; - goto done; - } - - cb = kmalloc(sizeof(struct cmdbuf_t) + count, GFP_KERNEL); - if (!cb) { - dev_err(cs->dev, "%s: out of memory\n", __func__); - retval = -ENOMEM; - goto done; - } - - memcpy(cb->buf, buf, count); - cb->len = count; - cb->offset = 0; - cb->next = NULL; - cb->wake_tasklet = &cs->if_wake_tasklet; - retval = cs->ops->write_cmd(cs, cb); -done: - mutex_unlock(&cs->mutex); - return retval; -} - -static int if_write_room(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - int retval; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - retval = -ENODEV; - } else if (cs->mstate != MS_LOCKED) { - dev_warn(cs->dev, "can't write to unlocked device\n"); - retval = -EBUSY; - } else - retval = cs->ops->write_room(cs); - - mutex_unlock(&cs->mutex); - - return retval; -} - -static int if_chars_in_buffer(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - int retval = 0; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); - else if (cs->mstate != MS_LOCKED) - dev_warn(cs->dev, "can't write to unlocked device\n"); - else - retval = cs->ops->chars_in_buffer(cs); - - mutex_unlock(&cs->mutex); - - return retval; -} - -static void if_throttle(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else - gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); - - mutex_unlock(&cs->mutex); -} - -static void if_unthrottle(struct tty_struct *tty) -{ - struct cardstate *cs = tty->driver_data; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) - gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ - else - gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); - - mutex_unlock(&cs->mutex); -} - -static void if_set_termios(struct tty_struct *tty, struct ktermios *old) -{ - struct cardstate *cs = tty->driver_data; - unsigned int iflag; - unsigned int cflag; - unsigned int old_cflag; - unsigned int control_state, new_state; - - gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - - mutex_lock(&cs->mutex); - - if (!cs->connected) { - gig_dbg(DEBUG_IF, "not connected"); - goto out; - } - - iflag = tty->termios.c_iflag; - cflag = tty->termios.c_cflag; - old_cflag = old ? old->c_cflag : cflag; - gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", - cs->minor_index, iflag, cflag, old_cflag); - - /* get a local copy of the current port settings */ - control_state = cs->control_state; - - /* - * Update baud rate. - * Do not attempt to cache old rates and skip settings, - * disconnects screw such tricks up completely. - * Premature optimization is the root of all evil. - */ - - /* reassert DTR and (maybe) RTS on transition from B0 */ - if ((old_cflag & CBAUD) == B0) { - new_state = control_state | TIOCM_DTR; - /* don't set RTS if using hardware flow control */ - if (!(old_cflag & CRTSCTS)) - new_state |= TIOCM_RTS; - gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s", - cs->minor_index, - (new_state & TIOCM_RTS) ? " only" : "/RTS"); - cs->ops->set_modem_ctrl(cs, control_state, new_state); - control_state = new_state; - } - - cs->ops->baud_rate(cs, cflag & CBAUD); - - if ((cflag & CBAUD) == B0) { - /* Drop RTS and DTR */ - gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); - new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS); - cs->ops->set_modem_ctrl(cs, control_state, new_state); - control_state = new_state; - } - - /* - * Update line control register (LCR) - */ - - cs->ops->set_line_ctrl(cs, cflag); - - /* save off the modified port settings */ - cs->control_state = control_state; - -out: - mutex_unlock(&cs->mutex); -} - -static const struct tty_operations if_ops = { - .open = if_open, - .close = if_close, - .ioctl = if_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = if_compat_ioctl, -#endif - .write = if_write, - .write_room = if_write_room, - .chars_in_buffer = if_chars_in_buffer, - .set_termios = if_set_termios, - .throttle = if_throttle, - .unthrottle = if_unthrottle, - .tiocmget = if_tiocmget, - .tiocmset = if_tiocmset, -}; - - -/* wakeup tasklet for the write operation */ -static void if_wake(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *)data; - - tty_port_tty_wakeup(&cs->port); -} - -/*** interface to common ***/ - -void gigaset_if_init(struct cardstate *cs) -{ - struct gigaset_driver *drv; - - drv = cs->driver; - if (!drv->have_tty) - return; - - tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); - - mutex_lock(&cs->mutex); - cs->tty_dev = tty_port_register_device(&cs->port, drv->tty, - cs->minor_index, NULL); - - if (!IS_ERR(cs->tty_dev)) - dev_set_drvdata(cs->tty_dev, cs); - else { - pr_warn("could not register device to the tty subsystem\n"); - cs->tty_dev = NULL; - } - mutex_unlock(&cs->mutex); -} - -void gigaset_if_free(struct cardstate *cs) -{ - struct gigaset_driver *drv; - - drv = cs->driver; - if (!drv->have_tty) - return; - - tasklet_disable(&cs->if_wake_tasklet); - tasklet_kill(&cs->if_wake_tasklet); - cs->tty_dev = NULL; - tty_unregister_device(drv->tty, cs->minor_index); -} - -/** - * gigaset_if_receive() - pass a received block of data to the tty device - * @cs: device descriptor structure. - * @buffer: received data. - * @len: number of bytes received. - * - * Called by asyncdata/isocdata if a block of data received from the - * device must be sent to userspace through the ttyG* device. - */ -void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len) -{ - tty_insert_flip_string(&cs->port, buffer, len); - tty_flip_buffer_push(&cs->port); -} -EXPORT_SYMBOL_GPL(gigaset_if_receive); - -/* gigaset_if_initdriver - * Initialize tty interface. - * parameters: - * drv Driver - * procname Name of the driver (e.g. for /proc/tty/drivers) - * devname Name of the device files (prefix without minor number) - */ -void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname) -{ - int ret; - struct tty_driver *tty; - - drv->have_tty = 0; - - drv->tty = tty = alloc_tty_driver(drv->minors); - if (tty == NULL) - goto enomem; - - tty->type = TTY_DRIVER_TYPE_SERIAL; - tty->subtype = SERIAL_TYPE_NORMAL; - tty->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - - tty->driver_name = procname; - tty->name = devname; - tty->minor_start = drv->minor; - - tty->init_termios = tty_std_termios; - tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty_set_operations(tty, &if_ops); - - ret = tty_register_driver(tty); - if (ret < 0) { - pr_err("error %d registering tty driver\n", ret); - goto error; - } - gig_dbg(DEBUG_IF, "tty driver initialized"); - drv->have_tty = 1; - return; - -enomem: - pr_err("out of memory\n"); -error: - if (drv->tty) - put_tty_driver(drv->tty); -} - -void gigaset_if_freedriver(struct gigaset_driver *drv) -{ - if (!drv->have_tty) - return; - - drv->have_tty = 0; - tty_unregister_driver(drv->tty); - put_tty_driver(drv->tty); -} diff --git a/drivers/staging/isdn/gigaset/isocdata.c b/drivers/staging/isdn/gigaset/isocdata.c deleted file mode 100644 index 3ecf6e33ed15..000000000000 --- a/drivers/staging/isdn/gigaset/isocdata.c +++ /dev/null @@ -1,1006 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Common data handling layer for bas_gigaset - * - * Copyright (c) 2005 by Tilman Schmidt , - * Hansjoerg Lipp . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include - -/* access methods for isowbuf_t */ -/* ============================ */ - -/* initialize buffer structure - */ -void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) -{ - iwb->read = 0; - iwb->nextread = 0; - iwb->write = 0; - atomic_set(&iwb->writesem, 1); - iwb->wbits = 0; - iwb->idle = idle; - memset(iwb->data + BAS_OUTBUFSIZE, idle, BAS_OUTBUFPAD); -} - -/* compute number of bytes which can be appended to buffer - * so that there is still room to append a maximum frame of flags - */ -static inline int isowbuf_freebytes(struct isowbuf_t *iwb) -{ - int read, write, freebytes; - - read = iwb->read; - write = iwb->write; - freebytes = read - write; - if (freebytes > 0) { - /* no wraparound: need padding space within regular area */ - return freebytes - BAS_OUTBUFPAD; - } else if (read < BAS_OUTBUFPAD) { - /* wraparound: can use space up to end of regular area */ - return BAS_OUTBUFSIZE - write; - } else { - /* following the wraparound yields more space */ - return freebytes + BAS_OUTBUFSIZE - BAS_OUTBUFPAD; - } -} - -/* start writing - * acquire the write semaphore - * return 0 if acquired, <0 if busy - */ -static inline int isowbuf_startwrite(struct isowbuf_t *iwb) -{ - if (!atomic_dec_and_test(&iwb->writesem)) { - atomic_inc(&iwb->writesem); - gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore", - __func__); - return -EBUSY; - } - gig_dbg(DEBUG_ISO, - "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", - __func__, iwb->data[iwb->write], iwb->wbits); - return 0; -} - -/* finish writing - * release the write semaphore - * returns the current write position - */ -static inline int isowbuf_donewrite(struct isowbuf_t *iwb) -{ - int write = iwb->write; - atomic_inc(&iwb->writesem); - return write; -} - -/* append bits to buffer without any checks - * - data contains bits to append, starting at LSB - * - nbits is number of bits to append (0..24) - * must be called with the write semaphore held - * If more than nbits bits are set in data, the extraneous bits are set in the - * buffer too, but the write position is only advanced by nbits. - */ -static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) -{ - int write = iwb->write; - data <<= iwb->wbits; - data |= iwb->data[write]; - nbits += iwb->wbits; - while (nbits >= 8) { - iwb->data[write++] = data & 0xff; - write %= BAS_OUTBUFSIZE; - data >>= 8; - nbits -= 8; - } - iwb->wbits = nbits; - iwb->data[write] = data & 0xff; - iwb->write = write; -} - -/* put final flag on HDLC bitstream - * also sets the idle fill byte to the correspondingly shifted flag pattern - * must be called with the write semaphore held - */ -static inline void isowbuf_putflag(struct isowbuf_t *iwb) -{ - int write; - - /* add two flags, thus reliably covering one byte */ - isowbuf_putbits(iwb, 0x7e7e, 8); - /* recover the idle flag byte */ - write = iwb->write; - iwb->idle = iwb->data[write]; - gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); - /* mask extraneous bits in buffer */ - iwb->data[write] &= (1 << iwb->wbits) - 1; -} - -/* retrieve a block of bytes for sending - * The requested number of bytes is provided as a contiguous block. - * If necessary, the frame is filled to the requested number of bytes - * with the idle value. - * returns offset to frame, < 0 on busy or error - */ -int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) -{ - int read, write, limit, src, dst; - unsigned char pbyte; - - read = iwb->nextread; - write = iwb->write; - if (likely(read == write)) { - /* return idle frame */ - return read < BAS_OUTBUFPAD ? - BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; - } - - limit = read + size; - gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d", - __func__, read, write, limit); -#ifdef CONFIG_GIGASET_DEBUG - if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) { - pr_err("invalid size %d\n", size); - return -EINVAL; - } -#endif - - if (read < write) { - /* no wraparound in valid data */ - if (limit >= write) { - /* append idle frame */ - if (isowbuf_startwrite(iwb) < 0) - return -EBUSY; - /* write position could have changed */ - write = iwb->write; - if (limit >= write) { - pbyte = iwb->data[write]; /* save - partial byte */ - limit = write + BAS_OUTBUFPAD; - gig_dbg(DEBUG_STREAM, - "%s: filling %d->%d with %02x", - __func__, write, limit, iwb->idle); - if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE) - memset(iwb->data + write, iwb->idle, - BAS_OUTBUFPAD); - else { - /* wraparound, fill entire pad area */ - memset(iwb->data + write, iwb->idle, - BAS_OUTBUFSIZE + BAS_OUTBUFPAD - - write); - limit = 0; - } - gig_dbg(DEBUG_STREAM, - "%s: restoring %02x at %d", - __func__, pbyte, limit); - iwb->data[limit] = pbyte; /* restore - partial byte */ - iwb->write = limit; - } - isowbuf_donewrite(iwb); - } - } else { - /* valid data wraparound */ - if (limit >= BAS_OUTBUFSIZE) { - /* copy wrapped part into pad area */ - src = 0; - dst = BAS_OUTBUFSIZE; - while (dst < limit && src < write) - iwb->data[dst++] = iwb->data[src++]; - if (dst <= limit) { - /* fill pad area with idle byte */ - memset(iwb->data + dst, iwb->idle, - BAS_OUTBUFSIZE + BAS_OUTBUFPAD - dst); - } - limit = src; - } - } - iwb->nextread = limit; - return read; -} - -/* dump_bytes - * write hex bytes to syslog for debugging - */ -static inline void dump_bytes(enum debuglevel level, const char *tag, - unsigned char *bytes, int count) -{ -#ifdef CONFIG_GIGASET_DEBUG - unsigned char c; - static char dbgline[3 * 32 + 1]; - int i = 0; - - if (!(gigaset_debuglevel & level)) - return; - - while (count-- > 0) { - if (i > sizeof(dbgline) - 4) { - dbgline[i] = '\0'; - gig_dbg(level, "%s:%s", tag, dbgline); - i = 0; - } - c = *bytes++; - dbgline[i] = (i && !(i % 12)) ? '-' : ' '; - i++; - dbgline[i++] = hex_asc_hi(c); - dbgline[i++] = hex_asc_lo(c); - } - dbgline[i] = '\0'; - gig_dbg(level, "%s:%s", tag, dbgline); -#endif -} - -/*============================================================================*/ - -/* bytewise HDLC bitstuffing via table lookup - * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits - * index: 256*(number of preceding '1' bits) + (next byte to stuff) - * value: bit 9.. 0 = result bits - * bit 12..10 = number of trailing '1' bits in result - * bit 14..13 = number of bits added by stuffing - */ -static const u16 stufftab[5 * 256] = { -/* previous 1s = 0: */ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f, - 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf, - 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f, - 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, - -/* previous 1s = 1: */ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f, - 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f, - 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af, - 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, - -/* previous 1s = 2: */ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577, - 0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997, - 0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7, - 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, - 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, - -/* previous 1s = 3: */ - 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, - 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, - 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, - 0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b, - 0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b, - 0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb, - 0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db, - 0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb, - 0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b, - 0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b, - 0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b, - 0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b, - 0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b, - 0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb, - 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, - 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, - -/* previous 1s = 4: */ - 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, - 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, - 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, - 0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d, - 0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d, - 0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd, - 0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd, - 0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d, - 0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d, - 0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d, - 0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d, - 0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d, - 0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d, - 0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd, - 0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd, - 0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d -}; - -/* hdlc_bitstuff_byte - * perform HDLC bitstuffing for one input byte (8 bits, LSB first) - * parameters: - * cin input byte - * ones number of trailing '1' bits in result before this step - * iwb pointer to output buffer structure - * (write semaphore must be held) - * return value: - * number of trailing '1' bits in result after this step - */ - -static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, - int ones) -{ - u16 stuff; - int shiftinc, newones; - - /* get stuffing information for input byte - * value: bit 9.. 0 = result bits - * bit 12..10 = number of trailing '1' bits in result - * bit 14..13 = number of bits added by stuffing - */ - stuff = stufftab[256 * ones + cin]; - shiftinc = (stuff >> 13) & 3; - newones = (stuff >> 10) & 7; - stuff &= 0x3ff; - - /* append stuffed byte to output stream */ - isowbuf_putbits(iwb, stuff, 8 + shiftinc); - return newones; -} - -/* hdlc_buildframe - * Perform HDLC framing with bitstuffing on a byte buffer - * The input buffer is regarded as a sequence of bits, starting with the least - * significant bit of the first byte and ending with the most significant bit - * of the last byte. A 16 bit FCS is appended as defined by RFC 1662. - * Whenever five consecutive '1' bits appear in the resulting bit sequence, a - * '0' bit is inserted after them. - * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110') - * are appended to the output buffer starting at the given bit position, which - * is assumed to already contain a leading flag. - * The output buffer must have sufficient length; count + count/5 + 6 bytes - * starting at *out are safe and are verified to be present. - * parameters: - * in input buffer - * count number of bytes in input buffer - * iwb pointer to output buffer structure - * (write semaphore must be held) - * return value: - * position of end of packet in output buffer on success, - * -EAGAIN if write semaphore busy or buffer full - */ - -static inline int hdlc_buildframe(struct isowbuf_t *iwb, - unsigned char *in, int count) -{ - int ones; - u16 fcs; - int end; - unsigned char c; - - if (isowbuf_freebytes(iwb) < count + count / 5 + 6 || - isowbuf_startwrite(iwb) < 0) { - gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", - __func__, isowbuf_freebytes(iwb)); - return -EAGAIN; - } - - dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count); - - /* bitstuff and checksum input data */ - fcs = PPP_INITFCS; - ones = 0; - while (count-- > 0) { - c = *in++; - ones = hdlc_bitstuff_byte(iwb, c, ones); - fcs = crc_ccitt_byte(fcs, c); - } - - /* bitstuff and append FCS - * (complemented, least significant byte first) */ - fcs ^= 0xffff; - ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); - ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); - - /* put closing flag and repeat byte for flag idle */ - isowbuf_putflag(iwb); - end = isowbuf_donewrite(iwb); - return end; -} - -/* trans_buildframe - * Append a block of 'transparent' data to the output buffer, - * inverting the bytes. - * The output buffer must have sufficient length; count bytes - * starting at *out are safe and are verified to be present. - * parameters: - * in input buffer - * count number of bytes in input buffer - * iwb pointer to output buffer structure - * (write semaphore must be held) - * return value: - * position of end of packet in output buffer on success, - * -EAGAIN if write semaphore busy or buffer full - */ - -static inline int trans_buildframe(struct isowbuf_t *iwb, - unsigned char *in, int count) -{ - int write; - unsigned char c; - - if (unlikely(count <= 0)) - return iwb->write; - - if (isowbuf_freebytes(iwb) < count || - isowbuf_startwrite(iwb) < 0) { - gig_dbg(DEBUG_ISO, "can't put %d bytes", count); - return -EAGAIN; - } - - gig_dbg(DEBUG_STREAM, "put %d bytes", count); - dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count); - - write = iwb->write; - do { - c = bitrev8(*in++); - iwb->data[write++] = c; - write %= BAS_OUTBUFSIZE; - } while (--count > 0); - iwb->write = write; - iwb->idle = c; - - return isowbuf_donewrite(iwb); -} - -int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) -{ - int result; - - switch (bcs->proto2) { - case L2_HDLC: - result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); - gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", - __func__, len, result); - break; - default: /* assume transparent */ - result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len); - gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", - __func__, len, result); - } - return result; -} - -/* hdlc_putbyte - * append byte c to current skb of B channel structure *bcs, updating fcs - */ -static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) -{ - bcs->rx_fcs = crc_ccitt_byte(bcs->rx_fcs, c); - if (bcs->rx_skb == NULL) - /* skipping */ - return; - if (bcs->rx_skb->len >= bcs->rx_bufsize) { - dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); - bcs->hw.bas->giants++; - dev_kfree_skb_any(bcs->rx_skb); - bcs->rx_skb = NULL; - return; - } - __skb_put_u8(bcs->rx_skb, c); -} - -/* hdlc_flush - * drop partial HDLC data packet - */ -static inline void hdlc_flush(struct bc_state *bcs) -{ - /* clear skb or allocate new if not skipping */ - if (bcs->rx_skb != NULL) - skb_trim(bcs->rx_skb, 0); - else - gigaset_new_rx_skb(bcs); - - /* reset packet state */ - bcs->rx_fcs = PPP_INITFCS; -} - -/* hdlc_done - * process completed HDLC data packet - */ -static inline void hdlc_done(struct bc_state *bcs) -{ - struct cardstate *cs = bcs->cs; - struct sk_buff *procskb; - unsigned int len; - - if (unlikely(bcs->ignore)) { - bcs->ignore--; - hdlc_flush(bcs); - return; - } - procskb = bcs->rx_skb; - if (procskb == NULL) { - /* previous error */ - gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); - gigaset_isdn_rcv_err(bcs); - } else if (procskb->len < 2) { - dev_notice(cs->dev, "received short frame (%d octets)\n", - procskb->len); - bcs->hw.bas->runts++; - dev_kfree_skb_any(procskb); - gigaset_isdn_rcv_err(bcs); - } else if (bcs->rx_fcs != PPP_GOODFCS) { - dev_notice(cs->dev, "frame check error\n"); - bcs->hw.bas->fcserrs++; - dev_kfree_skb_any(procskb); - gigaset_isdn_rcv_err(bcs); - } else { - len = procskb->len; - __skb_trim(procskb, len -= 2); /* subtract FCS */ - gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len); - dump_bytes(DEBUG_STREAM_DUMP, - "rcv data", procskb->data, len); - bcs->hw.bas->goodbytes += len; - gigaset_skb_rcvd(bcs, procskb); - } - gigaset_new_rx_skb(bcs); - bcs->rx_fcs = PPP_INITFCS; -} - -/* hdlc_frag - * drop HDLC data packet with non-integral last byte - */ -static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) -{ - if (unlikely(bcs->ignore)) { - bcs->ignore--; - hdlc_flush(bcs); - return; - } - - dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); - bcs->hw.bas->alignerrs++; - gigaset_isdn_rcv_err(bcs); - __skb_trim(bcs->rx_skb, 0); - bcs->rx_fcs = PPP_INITFCS; -} - -/* bit counts lookup table for HDLC bit unstuffing - * index: input byte - * value: bit 0..3 = number of consecutive '1' bits starting from LSB - * bit 4..6 = number of consecutive '1' bits starting from MSB - * (replacing 8 by 7 to make it fit; the algorithm won't care) - * bit 7 set if there are 5 or more "interior" consecutive '1' bits - */ -static const unsigned char bitcounts[256] = { - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14, - 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16, - 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24, - 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25, - 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34, - 0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78 -}; - -/* hdlc_unpack - * perform HDLC frame processing (bit unstuffing, flag detection, FCS - * calculation) on a sequence of received data bytes (8 bits each, LSB first) - * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd - * notify of errors via gigaset_isdn_rcv_err - * tally frames, errors etc. in BC structure counters - * parameters: - * src received data - * count number of received bytes - * bcs receiving B channel structure - */ -static inline void hdlc_unpack(unsigned char *src, unsigned count, - struct bc_state *bcs) -{ - struct bas_bc_state *ubc = bcs->hw.bas; - int inputstate; - unsigned seqlen, inbyte, inbits; - - /* load previous state: - * inputstate = set of flag bits: - * - INS_flag_hunt: no complete opening flag received since connection - * setup or last abort - * - INS_have_data: at least one complete data byte received since last - * flag - * seqlen = number of consecutive '1' bits in last 7 input stream bits - * (0..7) - * inbyte = accumulated partial data byte (if !INS_flag_hunt) - * inbits = number of valid bits in inbyte, starting at LSB (0..6) - */ - inputstate = bcs->inputstate; - seqlen = ubc->seqlen; - inbyte = ubc->inbyte; - inbits = ubc->inbits; - - /* bit unstuffing a byte a time - * Take your time to understand this; it's straightforward but tedious. - * The "bitcounts" lookup table is used to speed up the counting of - * leading and trailing '1' bits. - */ - while (count--) { - unsigned char c = *src++; - unsigned char tabentry = bitcounts[c]; - unsigned lead1 = tabentry & 0x0f; - unsigned trail1 = (tabentry >> 4) & 0x0f; - - seqlen += lead1; - - if (unlikely(inputstate & INS_flag_hunt)) { - if (c == PPP_FLAG) { - /* flag-in-one */ - inputstate &= ~(INS_flag_hunt | INS_have_data); - inbyte = 0; - inbits = 0; - } else if (seqlen == 6 && trail1 != 7) { - /* flag completed & not followed by abort */ - inputstate &= ~(INS_flag_hunt | INS_have_data); - inbyte = c >> (lead1 + 1); - inbits = 7 - lead1; - if (trail1 >= 8) { - /* interior stuffing: - * omitting the MSB handles most cases, - * correct the incorrectly handled - * cases individually */ - inbits--; - switch (c) { - case 0xbe: - inbyte = 0x3f; - break; - } - } - } - /* else: continue flag-hunting */ - } else if (likely(seqlen < 5 && trail1 < 7)) { - /* streamlined case: 8 data bits, no stuffing */ - inbyte |= c << inbits; - hdlc_putbyte(inbyte & 0xff, bcs); - inputstate |= INS_have_data; - inbyte >>= 8; - /* inbits unchanged */ - } else if (likely(seqlen == 6 && inbits == 7 - lead1 && - trail1 + 1 == inbits && - !(inputstate & INS_have_data))) { - /* streamlined case: flag idle - state unchanged */ - } else if (unlikely(seqlen > 6)) { - /* abort sequence */ - ubc->aborts++; - hdlc_flush(bcs); - inputstate |= INS_flag_hunt; - } else if (seqlen == 6) { - /* closing flag, including (6 - lead1) '1's - * and one '0' from inbits */ - if (inbits > 7 - lead1) { - hdlc_frag(bcs, inbits + lead1 - 7); - inputstate &= ~INS_have_data; - } else { - if (inbits < 7 - lead1) - ubc->stolen0s++; - if (inputstate & INS_have_data) { - hdlc_done(bcs); - inputstate &= ~INS_have_data; - } - } - - if (c == PPP_FLAG) { - /* complete flag, LSB overlaps preceding flag */ - ubc->shared0s++; - inbits = 0; - inbyte = 0; - } else if (trail1 != 7) { - /* remaining bits */ - inbyte = c >> (lead1 + 1); - inbits = 7 - lead1; - if (trail1 >= 8) { - /* interior stuffing: - * omitting the MSB handles most cases, - * correct the incorrectly handled - * cases individually */ - inbits--; - switch (c) { - case 0xbe: - inbyte = 0x3f; - break; - } - } - } else { - /* abort sequence follows, - * skb already empty anyway */ - ubc->aborts++; - inputstate |= INS_flag_hunt; - } - } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */ - - if (c == PPP_FLAG) { - /* complete flag */ - if (seqlen == 5) - ubc->stolen0s++; - if (inbits) { - hdlc_frag(bcs, inbits); - inbits = 0; - inbyte = 0; - } else if (inputstate & INS_have_data) - hdlc_done(bcs); - inputstate &= ~INS_have_data; - } else if (trail1 == 7) { - /* abort sequence */ - ubc->aborts++; - hdlc_flush(bcs); - inputstate |= INS_flag_hunt; - } else { - /* stuffed data */ - if (trail1 < 7) { /* => seqlen == 5 */ - /* stuff bit at position lead1, - * no interior stuffing */ - unsigned char mask = (1 << lead1) - 1; - c = (c & mask) | ((c & ~mask) >> 1); - inbyte |= c << inbits; - inbits += 7; - } else if (seqlen < 5) { /* trail1 >= 8 */ - /* interior stuffing: - * omitting the MSB handles most cases, - * correct the incorrectly handled - * cases individually */ - switch (c) { - case 0xbe: - c = 0x7e; - break; - } - inbyte |= c << inbits; - inbits += 7; - } else { /* seqlen == 5 && trail1 >= 8 */ - - /* stuff bit at lead1 *and* interior - * stuffing -- unstuff individually */ - switch (c) { - case 0x7d: - c = 0x3f; - break; - case 0xbe: - c = 0x3f; - break; - case 0x3e: - c = 0x1f; - break; - case 0x7c: - c = 0x3e; - break; - } - inbyte |= c << inbits; - inbits += 6; - } - if (inbits >= 8) { - inbits -= 8; - hdlc_putbyte(inbyte & 0xff, bcs); - inputstate |= INS_have_data; - inbyte >>= 8; - } - } - } - seqlen = trail1 & 7; - } - - /* save new state */ - bcs->inputstate = inputstate; - ubc->seqlen = seqlen; - ubc->inbyte = inbyte; - ubc->inbits = inbits; -} - -/* trans_receive - * pass on received USB frame transparently as SKB via gigaset_skb_rcvd - * invert bytes - * tally frames, errors etc. in BC structure counters - * parameters: - * src received data - * count number of received bytes - * bcs receiving B channel structure - */ -static inline void trans_receive(unsigned char *src, unsigned count, - struct bc_state *bcs) -{ - struct sk_buff *skb; - int dobytes; - unsigned char *dst; - - if (unlikely(bcs->ignore)) { - bcs->ignore--; - return; - } - skb = bcs->rx_skb; - if (skb == NULL) { - skb = gigaset_new_rx_skb(bcs); - if (skb == NULL) - return; - } - dobytes = bcs->rx_bufsize - skb->len; - while (count > 0) { - dst = skb_put(skb, count < dobytes ? count : dobytes); - while (count > 0 && dobytes > 0) { - *dst++ = bitrev8(*src++); - count--; - dobytes--; - } - if (dobytes == 0) { - dump_bytes(DEBUG_STREAM_DUMP, - "rcv data", skb->data, skb->len); - bcs->hw.bas->goodbytes += skb->len; - gigaset_skb_rcvd(bcs, skb); - skb = gigaset_new_rx_skb(bcs); - if (skb == NULL) - return; - dobytes = bcs->rx_bufsize; - } - } -} - -void gigaset_isoc_receive(unsigned char *src, unsigned count, - struct bc_state *bcs) -{ - switch (bcs->proto2) { - case L2_HDLC: - hdlc_unpack(src, count, bcs); - break; - default: /* assume transparent */ - trans_receive(src, count, bcs); - } -} - -/* == data input =========================================================== */ - -/* process a block of received bytes in command mode (mstate != MS_LOCKED) - * Append received bytes to the command response buffer and forward them - * line by line to the response handler. - * Note: Received lines may be terminated by CR, LF, or CR LF, which will be - * removed before passing the line to the response handler. - */ -static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - unsigned cbytes = cs->cbytes; - unsigned char c; - - while (numbytes--) { - c = *src++; - switch (c) { - case '\n': - if (cbytes == 0 && cs->respdata[0] == '\r') { - /* collapse LF with preceding CR */ - cs->respdata[0] = 0; - break; - } - /* fall through */ - case '\r': - /* end of message line, pass to response handler */ - if (cbytes >= MAX_RESP_SIZE) { - dev_warn(cs->dev, "response too large (%d)\n", - cbytes); - cbytes = MAX_RESP_SIZE; - } - cs->cbytes = cbytes; - gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", - cbytes, cs->respdata); - gigaset_handle_modem_response(cs); - cbytes = 0; - - /* store EOL byte for CRLF collapsing */ - cs->respdata[0] = c; - break; - default: - /* append to line buffer if possible */ - if (cbytes < MAX_RESP_SIZE) - cs->respdata[cbytes] = c; - cbytes++; - } - } - - /* save state */ - cs->cbytes = cbytes; -} - - -/* process a block of data received through the control channel - */ -void gigaset_isoc_input(struct inbuf_t *inbuf) -{ - struct cardstate *cs = inbuf->cs; - unsigned tail, head, numbytes; - unsigned char *src; - - head = inbuf->head; - while (head != (tail = inbuf->tail)) { - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - if (head > tail) - tail = RBUFSIZE; - src = inbuf->data + head; - numbytes = tail - head; - gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); - - if (cs->mstate == MS_LOCKED) { - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", - numbytes, src); - gigaset_if_receive(inbuf->cs, src, numbytes); - } else { - cmd_loop(src, numbytes, inbuf); - } - - head += numbytes; - if (head == RBUFSIZE) - head = 0; - gig_dbg(DEBUG_INTR, "setting head to %u", head); - inbuf->head = head; - } -} - - -/* == data output ========================================================== */ - -/** - * gigaset_isoc_send_skb() - queue an skb for sending - * @bcs: B channel descriptor structure. - * @skb: data to send. - * - * Called by LL to queue an skb for sending, and start transmission if - * necessary. - * Once the payload data has been transmitted completely, gigaset_skb_sent() - * will be called with the skb's link layer header preserved. - * - * Return value: - * number of bytes accepted for sending (skb->len) if ok, - * error code < 0 (eg. -ENODEV) on error - */ -int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) -{ - int len = skb->len; - unsigned long flags; - - spin_lock_irqsave(&bcs->cs->lock, flags); - if (!bcs->cs->connected) { - spin_unlock_irqrestore(&bcs->cs->lock, flags); - return -ENODEV; - } - - skb_queue_tail(&bcs->squeue, skb); - gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", - __func__, skb_queue_len(&bcs->squeue)); - - /* tasklet submits URB if necessary */ - tasklet_schedule(&bcs->hw.bas->sent_tasklet); - spin_unlock_irqrestore(&bcs->cs->lock, flags); - - return len; /* ok so far */ -} diff --git a/drivers/staging/isdn/gigaset/proc.c b/drivers/staging/isdn/gigaset/proc.c deleted file mode 100644 index 8914439a4237..000000000000 --- a/drivers/staging/isdn/gigaset/proc.c +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Stuff used by all variants of the driver - * - * Copyright (c) 2001 by Stefan Eilers, - * Hansjoerg Lipp , - * Tilman Schmidt . - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" - -static ssize_t show_cidmode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct cardstate *cs = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", cs->cidmode); -} - -static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cardstate *cs = dev_get_drvdata(dev); - long int value; - char *end; - - value = simple_strtol(buf, &end, 0); - while (*end) - if (!isspace(*end++)) - return -EINVAL; - if (value < 0 || value > 1) - return -EINVAL; - - if (mutex_lock_interruptible(&cs->mutex)) - return -ERESTARTSYS; - - cs->waiting = 1; - if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, - NULL, value, NULL)) { - cs->waiting = 0; - mutex_unlock(&cs->mutex); - return -ENOMEM; - } - gigaset_schedule_event(cs); - - wait_event(cs->waitqueue, !cs->waiting); - - mutex_unlock(&cs->mutex); - - return count; -} - -static DEVICE_ATTR(cidmode, S_IRUGO | S_IWUSR, show_cidmode, set_cidmode); - -/* free sysfs for device */ -void gigaset_free_dev_sysfs(struct cardstate *cs) -{ - if (!cs->tty_dev) - return; - - gig_dbg(DEBUG_INIT, "removing sysfs entries"); - device_remove_file(cs->tty_dev, &dev_attr_cidmode); -} - -/* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct cardstate *cs) -{ - if (!cs->tty_dev) - return; - - gig_dbg(DEBUG_INIT, "setting up sysfs"); - if (device_create_file(cs->tty_dev, &dev_attr_cidmode)) - pr_err("could not create sysfs attribute\n"); -} diff --git a/drivers/staging/isdn/gigaset/ser-gigaset.c b/drivers/staging/isdn/gigaset/ser-gigaset.c deleted file mode 100644 index 5587e9e7fc73..000000000000 --- a/drivers/staging/isdn/gigaset/ser-gigaset.c +++ /dev/null @@ -1,796 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* This is the serial hardware link layer (HLL) for the Gigaset 307x isdn - * DECT base (aka Sinus 45 isdn) using the RS232 DECT data module M101, - * written as a line discipline. - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Tilman Schmidt" -#define DRIVER_DESC "Serial Driver for Gigaset 307x using Siemens M101" - -#define GIGASET_MINORS 1 -#define GIGASET_MINOR 0 -#define GIGASET_MODULENAME "ser_gigaset" -#define GIGASET_DEVNAME "ttyGS" - -/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ -#define IF_WRITEBUF 264 - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_LDISC(N_GIGASET_M101); - -static int startmode = SM_ISDN; -module_param(startmode, int, S_IRUGO); -MODULE_PARM_DESC(startmode, "initial operation mode"); -static int cidmode = 1; -module_param(cidmode, int, S_IRUGO); -MODULE_PARM_DESC(cidmode, "stay in CID mode when idle"); - -static struct gigaset_driver *driver; - -struct ser_cardstate { - struct platform_device dev; - struct tty_struct *tty; - atomic_t refcnt; - struct completion dead_cmp; -}; - -static struct platform_driver device_driver = { - .driver = { - .name = GIGASET_MODULENAME, - }, -}; - -static void flush_send_queue(struct cardstate *); - -/* transmit data from current open skb - * result: number of bytes sent or error code < 0 - */ -static int write_modem(struct cardstate *cs) -{ - struct tty_struct *tty = cs->hw.ser->tty; - struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ - struct sk_buff *skb = bcs->tx_skb; - int sent = -EOPNOTSUPP; - - WARN_ON(!tty || !tty->ops || !skb); - - if (!skb->len) { - dev_kfree_skb_any(skb); - bcs->tx_skb = NULL; - return -EINVAL; - } - - set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (tty->ops->write) - sent = tty->ops->write(tty, skb->data, skb->len); - gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent); - if (sent < 0) { - /* error */ - flush_send_queue(cs); - return sent; - } - skb_pull(skb, sent); - if (!skb->len) { - /* skb sent completely */ - gigaset_skb_sent(bcs, skb); - - gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", - (unsigned long) skb); - dev_kfree_skb_any(skb); - bcs->tx_skb = NULL; - } - return sent; -} - -/* - * transmit first queued command buffer - * result: number of bytes sent or error code < 0 - */ -static int send_cb(struct cardstate *cs) -{ - struct tty_struct *tty = cs->hw.ser->tty; - struct cmdbuf_t *cb, *tcb; - unsigned long flags; - int sent = 0; - - WARN_ON(!tty || !tty->ops); - - cb = cs->cmdbuf; - if (!cb) - return 0; /* nothing to do */ - - if (cb->len) { - set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len); - if (sent < 0) { - /* error */ - gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent); - flush_send_queue(cs); - return sent; - } - cb->offset += sent; - cb->len -= sent; - gig_dbg(DEBUG_OUTPUT, "send_cb: sent %d, left %u, queued %u", - sent, cb->len, cs->cmdbytes); - } - - while (cb && !cb->len) { - spin_lock_irqsave(&cs->cmdlock, flags); - cs->cmdbytes -= cs->curlen; - tcb = cb; - cs->cmdbuf = cb = cb->next; - if (cb) { - cb->prev = NULL; - cs->curlen = cb->len; - } else { - cs->lastcmdbuf = NULL; - cs->curlen = 0; - } - spin_unlock_irqrestore(&cs->cmdlock, flags); - - if (tcb->wake_tasklet) - tasklet_schedule(tcb->wake_tasklet); - kfree(tcb); - } - return sent; -} - -/* - * send queue tasklet - * If there is already a skb opened, put data to the transfer buffer - * by calling "write_modem". - * Otherwise take a new skb out of the queue. - */ -static void gigaset_modem_fill(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *) data; - struct bc_state *bcs; - struct sk_buff *nextskb; - int sent = 0; - - if (!cs) { - gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); - return; - } - bcs = cs->bcs; - if (!bcs) { - gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); - return; - } - if (!bcs->tx_skb) { - /* no skb is being sent; send command if any */ - sent = send_cb(cs); - gig_dbg(DEBUG_OUTPUT, "%s: send_cb -> %d", __func__, sent); - if (sent) - /* something sent or error */ - return; - - /* no command to send; get skb */ - nextskb = skb_dequeue(&bcs->squeue); - if (!nextskb) - /* no skb either, nothing to do */ - return; - bcs->tx_skb = nextskb; - - gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", - (unsigned long) bcs->tx_skb); - } - - /* send skb */ - gig_dbg(DEBUG_OUTPUT, "%s: tx_skb", __func__); - if (write_modem(cs) < 0) - gig_dbg(DEBUG_OUTPUT, "%s: write_modem failed", __func__); -} - -/* - * throw away all data queued for sending - */ -static void flush_send_queue(struct cardstate *cs) -{ - struct sk_buff *skb; - struct cmdbuf_t *cb; - unsigned long flags; - - /* command queue */ - spin_lock_irqsave(&cs->cmdlock, flags); - while ((cb = cs->cmdbuf) != NULL) { - cs->cmdbuf = cb->next; - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - kfree(cb); - } - cs->cmdbuf = cs->lastcmdbuf = NULL; - cs->cmdbytes = cs->curlen = 0; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - /* data queue */ - if (cs->bcs->tx_skb) - dev_kfree_skb_any(cs->bcs->tx_skb); - while ((skb = skb_dequeue(&cs->bcs->squeue)) != NULL) - dev_kfree_skb_any(skb); -} - - -/* Gigaset Driver Interface */ -/* ======================== */ - -/* - * queue an AT command string for transmission to the Gigaset device - * parameters: - * cs controller state structure - * buf buffer containing the string to send - * len number of characters to send - * wake_tasklet tasklet to run when transmission is complete, or NULL - * return value: - * number of bytes queued, or error code < 0 - */ -static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) -{ - unsigned long flags; - - gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", cb->len, cb->buf); - - spin_lock_irqsave(&cs->cmdlock, flags); - cb->prev = cs->lastcmdbuf; - if (cs->lastcmdbuf) - cs->lastcmdbuf->next = cb; - else { - cs->cmdbuf = cb; - cs->curlen = cb->len; - } - cs->cmdbytes += cb->len; - cs->lastcmdbuf = cb; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - spin_lock_irqsave(&cs->lock, flags); - if (cs->connected) - tasklet_schedule(&cs->write_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); - return cb->len; -} - -/* - * tty_driver.write_room interface routine - * return number of characters the driver will accept to be written - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_write_room(struct cardstate *cs) -{ - unsigned bytes; - - bytes = cs->cmdbytes; - return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0; -} - -/* - * tty_driver.chars_in_buffer interface routine - * return number of characters waiting to be sent - * parameter: - * controller state structure - * return value: - * number of characters - */ -static int gigaset_chars_in_buffer(struct cardstate *cs) -{ - return cs->cmdbytes; -} - -/* - * implementation of ioctl(GIGASET_BRKCHARS) - * parameter: - * controller state structure - * return value: - * -EINVAL (unimplemented function) - */ -static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) -{ - /* not implemented */ - return -EINVAL; -} - -/* - * Open B channel - * Called by "do_action" in ev-layer.c - */ -static int gigaset_init_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_up(bcs); - return 0; -} - -/* - * Close B channel - * Called by "do_action" in ev-layer.c - */ -static int gigaset_close_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_down(bcs); - return 0; -} - -/* - * Set up B channel structure - * This is called by "gigaset_initcs" in common.c - */ -static int gigaset_initbcshw(struct bc_state *bcs) -{ - /* unused */ - bcs->hw.ser = NULL; - return 0; -} - -/* - * Free B channel structure - * Called by "gigaset_freebcs" in common.c - */ -static void gigaset_freebcshw(struct bc_state *bcs) -{ - /* unused */ -} - -/* - * Reinitialize B channel structure - * This is called by "bcs_reinit" in common.c - */ -static void gigaset_reinitbcshw(struct bc_state *bcs) -{ - /* nothing to do for M10x */ -} - -/* - * Free hardware specific device data - * This will be called by "gigaset_freecs" in common.c - */ -static void gigaset_freecshw(struct cardstate *cs) -{ - tasklet_kill(&cs->write_tasklet); - if (!cs->hw.ser) - return; - platform_device_unregister(&cs->hw.ser->dev); -} - -static void gigaset_device_release(struct device *dev) -{ - kfree(container_of(dev, struct ser_cardstate, dev.dev)); -} - -/* - * Set up hardware specific device data - * This is called by "gigaset_initcs" in common.c - */ -static int gigaset_initcshw(struct cardstate *cs) -{ - int rc; - struct ser_cardstate *scs; - - scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); - if (!scs) { - pr_err("out of memory\n"); - return -ENOMEM; - } - cs->hw.ser = scs; - - cs->hw.ser->dev.name = GIGASET_MODULENAME; - cs->hw.ser->dev.id = cs->minor_index; - cs->hw.ser->dev.dev.release = gigaset_device_release; - rc = platform_device_register(&cs->hw.ser->dev); - if (rc != 0) { - pr_err("error %d registering platform device\n", rc); - kfree(cs->hw.ser); - cs->hw.ser = NULL; - return rc; - } - - tasklet_init(&cs->write_tasklet, - gigaset_modem_fill, (unsigned long) cs); - return 0; -} - -/* - * set modem control lines - * Parameters: - * card state structure - * modem control line state ([TIOCM_DTR]|[TIOCM_RTS]) - * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c - * and by "if_lock" and "if_termios" in interface.c - */ -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - struct tty_struct *tty = cs->hw.ser->tty; - unsigned int set, clear; - - WARN_ON(!tty || !tty->ops); - /* tiocmset is an optional tty driver method */ - if (!tty->ops->tiocmset) - return -EINVAL; - set = new_state & ~old_state; - clear = old_state & ~new_state; - if (!set && !clear) - return 0; - gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear); - return tty->ops->tiocmset(tty, set, clear); -} - -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - return -EINVAL; -} - -static const struct gigaset_ops ops = { - .write_cmd = gigaset_write_cmd, - .write_room = gigaset_write_room, - .chars_in_buffer = gigaset_chars_in_buffer, - .brkchars = gigaset_brkchars, - .init_bchannel = gigaset_init_bchannel, - .close_bchannel = gigaset_close_bchannel, - .initbcshw = gigaset_initbcshw, - .freebcshw = gigaset_freebcshw, - .reinitbcshw = gigaset_reinitbcshw, - .initcshw = gigaset_initcshw, - .freecshw = gigaset_freecshw, - .set_modem_ctrl = gigaset_set_modem_ctrl, - .baud_rate = gigaset_baud_rate, - .set_line_ctrl = gigaset_set_line_ctrl, - .send_skb = gigaset_m10x_send_skb, /* asyncdata.c */ - .handle_input = gigaset_m10x_input, /* asyncdata.c */ -}; - - -/* Line Discipline Interface */ -/* ========================= */ - -/* helper functions for cardstate refcounting */ -static struct cardstate *cs_get(struct tty_struct *tty) -{ - struct cardstate *cs = tty->disc_data; - - if (!cs || !cs->hw.ser) { - gig_dbg(DEBUG_ANY, "%s: no cardstate", __func__); - return NULL; - } - atomic_inc(&cs->hw.ser->refcnt); - return cs; -} - -static void cs_put(struct cardstate *cs) -{ - if (atomic_dec_and_test(&cs->hw.ser->refcnt)) - complete(&cs->hw.ser->dead_cmp); -} - -/* - * Called by the tty driver when the line discipline is pushed onto the tty. - * Called in process context. - */ -static int -gigaset_tty_open(struct tty_struct *tty) -{ - struct cardstate *cs; - int rc; - - gig_dbg(DEBUG_INIT, "Starting HLL for Gigaset M101"); - - pr_info(DRIVER_DESC "\n"); - - if (!driver) { - pr_err("%s: no driver structure\n", __func__); - return -ENODEV; - } - - /* allocate memory for our device state and initialize it */ - cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); - if (!cs) { - rc = -ENODEV; - goto error; - } - - cs->dev = &cs->hw.ser->dev.dev; - cs->hw.ser->tty = tty; - atomic_set(&cs->hw.ser->refcnt, 1); - init_completion(&cs->hw.ser->dead_cmp); - tty->disc_data = cs; - - /* Set the amount of data we're willing to receive per call - * from the hardware driver to half of the input buffer size - * to leave some reserve. - * Note: We don't do flow control towards the hardware driver. - * If more data is received than will fit into the input buffer, - * it will be dropped and an error will be logged. This should - * never happen as the device is slow and the buffer size ample. - */ - tty->receive_room = RBUFSIZE/2; - - /* OK.. Initialization of the datastructures and the HW is done.. Now - * startup system and notify the LL that we are ready to run - */ - if (startmode == SM_LOCKED) - cs->mstate = MS_LOCKED; - rc = gigaset_start(cs); - if (rc < 0) { - tasklet_kill(&cs->write_tasklet); - goto error; - } - - gig_dbg(DEBUG_INIT, "Startup of HLL done"); - return 0; - -error: - gig_dbg(DEBUG_INIT, "Startup of HLL failed"); - tty->disc_data = NULL; - gigaset_freecs(cs); - return rc; -} - -/* - * Called by the tty driver when the line discipline is removed. - * Called from process context. - */ -static void -gigaset_tty_close(struct tty_struct *tty) -{ - struct cardstate *cs = tty->disc_data; - - gig_dbg(DEBUG_INIT, "Stopping HLL for Gigaset M101"); - - if (!cs) { - gig_dbg(DEBUG_INIT, "%s: no cardstate", __func__); - return; - } - - /* prevent other callers from entering ldisc methods */ - tty->disc_data = NULL; - - if (!cs->hw.ser) - pr_err("%s: no hw cardstate\n", __func__); - else { - /* wait for running methods to finish */ - if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) - wait_for_completion(&cs->hw.ser->dead_cmp); - } - - /* stop operations */ - gigaset_stop(cs); - tasklet_kill(&cs->write_tasklet); - flush_send_queue(cs); - cs->dev = NULL; - gigaset_freecs(cs); - - gig_dbg(DEBUG_INIT, "Shutdown of HLL done"); -} - -/* - * Called by the tty driver when the tty line is hung up. - * Wait for I/O to driver to complete and unregister ISDN device. - * This is already done by the close routine, so just call that. - * Called from process context. - */ -static int gigaset_tty_hangup(struct tty_struct *tty) -{ - gigaset_tty_close(tty); - return 0; -} - -/* - * Ioctl on the tty. - * Called in process context only. - * May be re-entered by multiple ioctl calling threads. - */ -static int -gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct cardstate *cs = cs_get(tty); - int rc, val; - int __user *p = (int __user *)arg; - - if (!cs) - return -ENXIO; - - switch (cmd) { - - case FIONREAD: - /* unused, always return zero */ - val = 0; - rc = put_user(val, p); - break; - - case TCFLSH: - /* flush our buffers and the serial port's buffer */ - switch (arg) { - case TCIFLUSH: - /* no own input buffer to flush */ - break; - case TCIOFLUSH: - case TCOFLUSH: - flush_send_queue(cs); - break; - } - /* fall through */ - - default: - /* pass through to underlying serial device */ - rc = n_tty_ioctl_helper(tty, file, cmd, arg); - break; - } - cs_put(cs); - return rc; -} - -/* - * Called by the tty driver when a block of data has been received. - * Will not be re-entered while running but other ldisc functions - * may be called in parallel. - * Can be called from hard interrupt level as well as soft interrupt - * level or mainline. - * Parameters: - * tty tty structure - * buf buffer containing received characters - * cflags buffer containing error flags for received characters (ignored) - * count number of received characters - */ -static void -gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, - char *cflags, int count) -{ - struct cardstate *cs = cs_get(tty); - unsigned tail, head, n; - struct inbuf_t *inbuf; - - if (!cs) - return; - inbuf = cs->inbuf; - if (!inbuf) { - dev_err(cs->dev, "%s: no inbuf\n", __func__); - cs_put(cs); - return; - } - - tail = inbuf->tail; - head = inbuf->head; - gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", - head, tail, count); - - if (head <= tail) { - /* possible buffer wraparound */ - n = min_t(unsigned, count, RBUFSIZE - tail); - memcpy(inbuf->data + tail, buf, n); - tail = (tail + n) % RBUFSIZE; - buf += n; - count -= n; - } - - if (count > 0) { - /* tail < head and some data left */ - n = head - tail - 1; - if (count > n) { - dev_err(cs->dev, - "inbuf overflow, discarding %d bytes\n", - count - n); - count = n; - } - memcpy(inbuf->data + tail, buf, count); - tail += count; - } - - gig_dbg(DEBUG_INTR, "setting tail to %u", tail); - inbuf->tail = tail; - - /* Everything was received .. Push data into handler */ - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(cs); - cs_put(cs); -} - -/* - * Called by the tty driver when there's room for more data to send. - */ -static void -gigaset_tty_wakeup(struct tty_struct *tty) -{ - struct cardstate *cs = cs_get(tty); - - clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (!cs) - return; - tasklet_schedule(&cs->write_tasklet); - cs_put(cs); -} - -static struct tty_ldisc_ops gigaset_ldisc = { - .owner = THIS_MODULE, - .magic = TTY_LDISC_MAGIC, - .name = "ser_gigaset", - .open = gigaset_tty_open, - .close = gigaset_tty_close, - .hangup = gigaset_tty_hangup, - .ioctl = gigaset_tty_ioctl, - .receive_buf = gigaset_tty_receive, - .write_wakeup = gigaset_tty_wakeup, -}; - - -/* Initialization / Shutdown */ -/* ========================= */ - -static int __init ser_gigaset_init(void) -{ - int rc; - - gig_dbg(DEBUG_INIT, "%s", __func__); - rc = platform_driver_register(&device_driver); - if (rc != 0) { - pr_err("error %d registering platform driver\n", rc); - return rc; - } - - /* allocate memory for our driver state and initialize it */ - driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE); - if (!driver) { - rc = -ENOMEM; - goto error; - } - - rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc); - if (rc != 0) { - pr_err("error %d registering line discipline\n", rc); - goto error; - } - - return 0; - -error: - if (driver) { - gigaset_freedriver(driver); - driver = NULL; - } - platform_driver_unregister(&device_driver); - return rc; -} - -static void __exit ser_gigaset_exit(void) -{ - int rc; - - gig_dbg(DEBUG_INIT, "%s", __func__); - - if (driver) { - gigaset_freedriver(driver); - driver = NULL; - } - - rc = tty_unregister_ldisc(N_GIGASET_M101); - if (rc != 0) - pr_err("error %d unregistering line discipline\n", rc); - - platform_driver_unregister(&device_driver); -} - -module_init(ser_gigaset_init); -module_exit(ser_gigaset_exit); diff --git a/drivers/staging/isdn/gigaset/usb-gigaset.c b/drivers/staging/isdn/gigaset/usb-gigaset.c deleted file mode 100644 index 1b9b43659bdf..000000000000 --- a/drivers/staging/isdn/gigaset/usb-gigaset.c +++ /dev/null @@ -1,946 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * USB driver for Gigaset 307x directly or using M105 Data. - * - * Copyright (c) 2001 by Stefan Eilers - * and Hansjoerg Lipp . - * - * This driver was derived from the USB skeleton driver by - * Greg Kroah-Hartman - * - * ===================================================================== - * ===================================================================== - */ - -#include "gigaset.h" -#include -#include -#include - -/* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp , Stefan Eilers" -#define DRIVER_DESC "USB Driver for Gigaset 307x using M105" - -/* Module parameters */ - -static int startmode = SM_ISDN; -static int cidmode = 1; - -module_param(startmode, int, S_IRUGO); -module_param(cidmode, int, S_IRUGO); -MODULE_PARM_DESC(startmode, "start in isdn4linux mode"); -MODULE_PARM_DESC(cidmode, "Call-ID mode"); - -#define GIGASET_MINORS 1 -#define GIGASET_MINOR 8 -#define GIGASET_MODULENAME "usb_gigaset" -#define GIGASET_DEVNAME "ttyGU" - -/* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ -#define IF_WRITEBUF 264 - -/* Values for the Gigaset M105 Data */ -#define USB_M105_VENDOR_ID 0x0681 -#define USB_M105_PRODUCT_ID 0x0009 - -/* table of devices that work with this driver */ -static const struct usb_device_id gigaset_table[] = { - { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, gigaset_table); - -/* - * Control requests (empty fields: 00) - * - * RT|RQ|VALUE|INDEX|LEN |DATA - * In: - * C1 08 01 - * Get flags (1 byte). Bits: 0=dtr,1=rts,3-7:? - * C1 0F ll ll - * Get device information/status (llll: 0x200 and 0x40 seen). - * Real size: I only saw MIN(llll,0x64). - * Contents: seems to be always the same... - * offset 0x00: Length of this structure (0x64) (len: 1,2,3 bytes) - * offset 0x3c: String (16 bit chars): "MCCI USB Serial V2.0" - * rest: ? - * Out: - * 41 11 - * Initialize/reset device ? - * 41 00 xx 00 - * ? (xx=00 or 01; 01 on start, 00 on close) - * 41 07 vv mm - * Set/clear flags vv=value, mm=mask (see RQ 08) - * 41 12 xx - * Used before the following configuration requests are issued - * (with xx=0x0f). I've seen other values<0xf, though. - * 41 01 xx xx - * Set baud rate. xxxx=ceil(0x384000/rate)=trunc(0x383fff/rate)+1. - * 41 03 ps bb - * Set byte size and parity. p: 0x20=even,0x10=odd,0x00=no parity - * [ 0x30: m, 0x40: s ] - * [s: 0: 1 stop bit; 1: 1.5; 2: 2] - * bb: bits/byte (seen 7 and 8) - * 41 13 -- -- -- -- 10 00 ww 00 00 00 xx 00 00 00 yy 00 00 00 zz 00 00 00 - * ?? - * Initialization: 01, 40, 00, 00 - * Open device: 00 40, 00, 00 - * yy and zz seem to be equal, either 0x00 or 0x0a - * (ww,xx) pairs seen: (00,00), (00,40), (01,40), (09,80), (19,80) - * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 - * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). - * xx is usually 0x00 but was 0x7e before starting data transfer - * in unimodem mode. So, this might be an array of characters that - * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. - * - * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two - * flags per packet. - */ - -/* functions called if a device of this driver is connected/disconnected */ -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void gigaset_disconnect(struct usb_interface *interface); - -/* functions called before/after suspend */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); -static int gigaset_resume(struct usb_interface *intf); -static int gigaset_pre_reset(struct usb_interface *intf); - -static struct gigaset_driver *driver; - -/* usb specific object needed to register this driver with the usb subsystem */ -static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, - .suspend = gigaset_suspend, - .resume = gigaset_resume, - .reset_resume = gigaset_resume, - .pre_reset = gigaset_pre_reset, - .post_reset = gigaset_resume, - .disable_hub_initiated_lpm = 1, -}; - -struct usb_cardstate { - struct usb_device *udev; /* usb device pointer */ - struct usb_interface *interface; /* interface for this device */ - int busy; /* bulk output in progress */ - - /* Output buffer */ - unsigned char *bulk_out_buffer; - int bulk_out_size; - int bulk_out_epnum; - struct urb *bulk_out_urb; - - /* Input buffer */ - unsigned char *rcvbuf; - int rcvbuf_size; - struct urb *read_urb; - - char bchars[6]; /* for request 0x19 */ -}; - -static inline unsigned tiocm_to_gigaset(unsigned state) -{ - return ((state & TIOCM_DTR) ? 1 : 0) | ((state & TIOCM_RTS) ? 2 : 0); -} - -static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) -{ - struct usb_device *udev = cs->hw.usb->udev; - unsigned mask, val; - int r; - - mask = tiocm_to_gigaset(old_state ^ new_state); - val = tiocm_to_gigaset(new_state); - - gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, - (val & 0xff) | ((mask & 0xff) << 8), 0, - NULL, 0, 2000 /* timeout? */); - if (r < 0) - return r; - return 0; -} - -/* - * Set M105 configuration value - * using undocumented device commands reverse engineered from USB traces - * of the Siemens Windows driver - */ -static int set_value(struct cardstate *cs, u8 req, u16 val) -{ - struct usb_device *udev = cs->hw.usb->udev; - int r, r2; - - gig_dbg(DEBUG_USBREQ, "request %02x (%04x)", - (unsigned)req, (unsigned)val); - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41, - 0xf /*?*/, 0, NULL, 0, 2000 /*?*/); - /* no idea what this does */ - if (r < 0) { - dev_err(&udev->dev, "error %d on request 0x12\n", -r); - return r; - } - - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41, - val, 0, NULL, 0, 2000 /*?*/); - if (r < 0) - dev_err(&udev->dev, "error %d on request 0x%02x\n", - -r, (unsigned)req); - - r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, - 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); - if (r2 < 0) - dev_err(&udev->dev, "error %d on request 0x19\n", -r2); - - return r < 0 ? r : (r2 < 0 ? r2 : 0); -} - -/* - * set the baud rate on the internal serial adapter - * using the undocumented parameter setting command - */ -static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) -{ - u16 val; - u32 rate; - - cflag &= CBAUD; - - switch (cflag) { - case B300: rate = 300; break; - case B600: rate = 600; break; - case B1200: rate = 1200; break; - case B2400: rate = 2400; break; - case B4800: rate = 4800; break; - case B9600: rate = 9600; break; - case B19200: rate = 19200; break; - case B38400: rate = 38400; break; - case B57600: rate = 57600; break; - case B115200: rate = 115200; break; - default: - rate = 9600; - dev_err(cs->dev, "unsupported baudrate request 0x%x," - " using default of B9600\n", cflag); - } - - val = 0x383fff / rate + 1; - - return set_value(cs, 1, val); -} - -/* - * set the line format on the internal serial adapter - * using the undocumented parameter setting command - */ -static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) -{ - u16 val = 0; - - /* set the parity */ - if (cflag & PARENB) - val |= (cflag & PARODD) ? 0x10 : 0x20; - - /* set the number of data bits */ - switch (cflag & CSIZE) { - case CS5: - val |= 5 << 8; break; - case CS6: - val |= 6 << 8; break; - case CS7: - val |= 7 << 8; break; - case CS8: - val |= 8 << 8; break; - default: - dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n"); - val |= 8 << 8; - break; - } - - /* set the number of stop bits */ - if (cflag & CSTOPB) { - if ((cflag & CSIZE) == CS5) - val |= 1; /* 1.5 stop bits */ - else - val |= 2; /* 2 stop bits */ - } - - return set_value(cs, 3, val); -} - - -/*============================================================================*/ -static int gigaset_init_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_up(bcs); - return 0; -} - -static int gigaset_close_bchannel(struct bc_state *bcs) -{ - /* nothing to do for M10x */ - gigaset_bchannel_down(bcs); - return 0; -} - -static int write_modem(struct cardstate *cs); -static int send_cb(struct cardstate *cs); - - -/* Write tasklet handler: Continue sending current skb, or send command, or - * start sending an skb from the send queue. - */ -static void gigaset_modem_fill(unsigned long data) -{ - struct cardstate *cs = (struct cardstate *) data; - struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ - - gig_dbg(DEBUG_OUTPUT, "modem_fill"); - - if (cs->hw.usb->busy) { - gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); - return; - } - -again: - if (!bcs->tx_skb) { /* no skb is being sent */ - if (cs->cmdbuf) { /* commands to send? */ - gig_dbg(DEBUG_OUTPUT, "modem_fill: cb"); - if (send_cb(cs) < 0) { - gig_dbg(DEBUG_OUTPUT, - "modem_fill: send_cb failed"); - goto again; /* no callback will be called! */ - } - return; - } - - /* skbs to send? */ - bcs->tx_skb = skb_dequeue(&bcs->squeue); - if (!bcs->tx_skb) - return; - - gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); - } - - gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); - if (write_modem(cs) < 0) { - gig_dbg(DEBUG_OUTPUT, "modem_fill: write_modem failed"); - goto again; /* no callback will be called! */ - } -} - -/* - * Interrupt Input URB completion routine - */ -static void gigaset_read_int_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - struct inbuf_t *inbuf = cs->inbuf; - int status = urb->status; - int r; - unsigned numbytes; - unsigned char *src; - unsigned long flags; - - if (!status) { - numbytes = urb->actual_length; - - if (numbytes) { - src = cs->hw.usb->rcvbuf; - if (unlikely(*src)) - dev_warn(cs->dev, - "%s: There was no leading 0, but 0x%02x!\n", - __func__, (unsigned) *src); - ++src; /* skip leading 0x00 */ - --numbytes; - if (gigaset_fill_inbuf(inbuf, src, numbytes)) { - gig_dbg(DEBUG_INTR, "%s-->BH", __func__); - gigaset_schedule_event(inbuf->cs); - } - } else - gig_dbg(DEBUG_INTR, "Received zero block length"); - } else { - /* The urb might have been killed. */ - gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", - __func__, status); - if (status == -ENOENT || status == -ESHUTDOWN) - /* killed or endpoint shutdown: don't resubmit */ - return; - } - - /* resubmit URB */ - spin_lock_irqsave(&cs->lock, flags); - if (!cs->connected) { - spin_unlock_irqrestore(&cs->lock, flags); - pr_err("%s: disconnected\n", __func__); - return; - } - r = usb_submit_urb(urb, GFP_ATOMIC); - spin_unlock_irqrestore(&cs->lock, flags); - if (r) - dev_err(cs->dev, "error %d resubmitting URB\n", -r); -} - - -/* This callback routine is called when data was transmitted to the device. */ -static void gigaset_write_bulk_callback(struct urb *urb) -{ - struct cardstate *cs = urb->context; - int status = urb->status; - unsigned long flags; - - switch (status) { - case 0: /* normal completion */ - break; - case -ENOENT: /* killed */ - gig_dbg(DEBUG_ANY, "%s: killed", __func__); - cs->hw.usb->busy = 0; - return; - default: - dev_err(cs->dev, "bulk transfer failed (status %d)\n", - -status); - /* That's all we can do. Communication problems - are handled by timeouts or network protocols. */ - } - - spin_lock_irqsave(&cs->lock, flags); - if (!cs->connected) { - pr_err("%s: disconnected\n", __func__); - } else { - cs->hw.usb->busy = 0; - tasklet_schedule(&cs->write_tasklet); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static int send_cb(struct cardstate *cs) -{ - struct cmdbuf_t *cb = cs->cmdbuf; - unsigned long flags; - int count; - int status = -ENOENT; - struct usb_cardstate *ucs = cs->hw.usb; - - do { - if (!cb->len) { - spin_lock_irqsave(&cs->cmdlock, flags); - cs->cmdbytes -= cs->curlen; - gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); - cs->cmdbuf = cb->next; - if (cs->cmdbuf) { - cs->cmdbuf->prev = NULL; - cs->curlen = cs->cmdbuf->len; - } else { - cs->lastcmdbuf = NULL; - cs->curlen = 0; - } - spin_unlock_irqrestore(&cs->cmdlock, flags); - - if (cb->wake_tasklet) - tasklet_schedule(cb->wake_tasklet); - kfree(cb); - - cb = cs->cmdbuf; - } - - if (cb) { - count = min(cb->len, ucs->bulk_out_size); - gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); - - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_epnum), - cb->buf + cb->offset, count, - gigaset_write_bulk_callback, cs); - - cb->offset += count; - cb->len -= count; - ucs->busy = 1; - - spin_lock_irqsave(&cs->lock, flags); - status = cs->connected ? - usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : - -ENODEV; - spin_unlock_irqrestore(&cs->lock, flags); - - if (status) { - ucs->busy = 0; - dev_err(cs->dev, - "could not submit urb (error %d)\n", - -status); - cb->len = 0; /* skip urb => remove cb+wakeup - in next loop cycle */ - } - } - } while (cb && status); /* next command on error */ - - return status; -} - -/* Send command to device. */ -static int gigaset_write_cmd(struct cardstate *cs, struct cmdbuf_t *cb) -{ - unsigned long flags; - int len; - - gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", cb->len, cb->buf); - - spin_lock_irqsave(&cs->cmdlock, flags); - cb->prev = cs->lastcmdbuf; - if (cs->lastcmdbuf) - cs->lastcmdbuf->next = cb; - else { - cs->cmdbuf = cb; - cs->curlen = cb->len; - } - cs->cmdbytes += cb->len; - cs->lastcmdbuf = cb; - spin_unlock_irqrestore(&cs->cmdlock, flags); - - spin_lock_irqsave(&cs->lock, flags); - len = cb->len; - if (cs->connected) - tasklet_schedule(&cs->write_tasklet); - spin_unlock_irqrestore(&cs->lock, flags); - return len; -} - -static int gigaset_write_room(struct cardstate *cs) -{ - unsigned bytes; - - bytes = cs->cmdbytes; - return bytes < IF_WRITEBUF ? IF_WRITEBUF - bytes : 0; -} - -static int gigaset_chars_in_buffer(struct cardstate *cs) -{ - return cs->cmdbytes; -} - -/* - * set the break characters on the internal serial adapter - * using undocumented device commands reverse engineered from USB traces - * of the Siemens Windows driver - */ -static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) -{ - struct usb_device *udev = cs->hw.usb->udev; - - gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); - memcpy(cs->hw.usb->bchars, buf, 6); - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, - 0, 0, &buf, 6, 2000); -} - -static void gigaset_freebcshw(struct bc_state *bcs) -{ - /* unused */ -} - -/* Initialize the b-channel structure */ -static int gigaset_initbcshw(struct bc_state *bcs) -{ - /* unused */ - bcs->hw.usb = NULL; - return 0; -} - -static void gigaset_reinitbcshw(struct bc_state *bcs) -{ - /* nothing to do for M10x */ -} - -static void gigaset_freecshw(struct cardstate *cs) -{ - tasklet_kill(&cs->write_tasklet); - kfree(cs->hw.usb); -} - -static int gigaset_initcshw(struct cardstate *cs) -{ - struct usb_cardstate *ucs; - - cs->hw.usb = ucs = - kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL); - if (!ucs) { - pr_err("out of memory\n"); - return -ENOMEM; - } - - ucs->bchars[0] = 0; - ucs->bchars[1] = 0; - ucs->bchars[2] = 0; - ucs->bchars[3] = 0; - ucs->bchars[4] = 0x11; - ucs->bchars[5] = 0x13; - ucs->bulk_out_buffer = NULL; - ucs->bulk_out_urb = NULL; - ucs->read_urb = NULL; - tasklet_init(&cs->write_tasklet, - gigaset_modem_fill, (unsigned long) cs); - - return 0; -} - -/* Send data from current skb to the device. */ -static int write_modem(struct cardstate *cs) -{ - int ret = 0; - int count; - struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ - struct usb_cardstate *ucs = cs->hw.usb; - unsigned long flags; - - gig_dbg(DEBUG_OUTPUT, "len: %d...", bcs->tx_skb->len); - - if (!bcs->tx_skb->len) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - return -EINVAL; - } - - /* Copy data to bulk out buffer and transmit data */ - count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); - skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); - skb_pull(bcs->tx_skb, count); - ucs->busy = 1; - gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); - - spin_lock_irqsave(&cs->lock, flags); - if (cs->connected) { - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_epnum), - ucs->bulk_out_buffer, count, - gigaset_write_bulk_callback, cs); - ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); - } else { - ret = -ENODEV; - } - spin_unlock_irqrestore(&cs->lock, flags); - - if (ret) { - dev_err(cs->dev, "could not submit urb (error %d)\n", -ret); - ucs->busy = 0; - } - - if (!bcs->tx_skb->len) { - /* skb sent completely */ - gigaset_skb_sent(bcs, bcs->tx_skb); - - gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - } - - return ret; -} - -static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int retval; - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *hostif = interface->cur_altsetting; - struct cardstate *cs = NULL; - struct usb_cardstate *ucs = NULL; - struct usb_endpoint_descriptor *endpoint; - int buffer_size; - - gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); - - /* See if the device offered us matches what we can accept */ - if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || - (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { - gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); - return -ENODEV; - } - if (hostif->desc.bInterfaceNumber != 0) { - gig_dbg(DEBUG_ANY, "interface %d not for me - skip", - hostif->desc.bInterfaceNumber); - return -ENODEV; - } - if (hostif->desc.bAlternateSetting != 0) { - dev_notice(&udev->dev, "unsupported altsetting %d - skip", - hostif->desc.bAlternateSetting); - return -ENODEV; - } - if (hostif->desc.bInterfaceClass != 255) { - dev_notice(&udev->dev, "unsupported interface class %d - skip", - hostif->desc.bInterfaceClass); - return -ENODEV; - } - - dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); - - /* allocate memory for our device state and initialize it */ - cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); - if (!cs) - return -ENODEV; - ucs = cs->hw.usb; - - /* save off device structure ptrs for later use */ - usb_get_dev(udev); - ucs->udev = udev; - ucs->interface = interface; - cs->dev = &interface->dev; - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - endpoint = &hostif->endpoint[0].desc; - - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - ucs->bulk_out_size = buffer_size; - ucs->bulk_out_epnum = usb_endpoint_num(endpoint); - ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!ucs->bulk_out_buffer) { - dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n"); - retval = -ENOMEM; - goto error; - } - - ucs->bulk_out_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ucs->bulk_out_urb) { - dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n"); - retval = -ENOMEM; - goto error; - } - - endpoint = &hostif->endpoint[1].desc; - - ucs->busy = 0; - - ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ucs->read_urb) { - dev_err(cs->dev, "No free urbs available\n"); - retval = -ENOMEM; - goto error; - } - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); - ucs->rcvbuf_size = buffer_size; - ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); - if (!ucs->rcvbuf) { - dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); - retval = -ENOMEM; - goto error; - } - /* Fill the interrupt urb and send it to the core */ - usb_fill_int_urb(ucs->read_urb, udev, - usb_rcvintpipe(udev, usb_endpoint_num(endpoint)), - ucs->rcvbuf, buffer_size, - gigaset_read_int_callback, - cs, endpoint->bInterval); - - retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); - if (retval) { - dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval); - goto error; - } - - /* tell common part that the device is ready */ - if (startmode == SM_LOCKED) - cs->mstate = MS_LOCKED; - - retval = gigaset_start(cs); - if (retval < 0) { - tasklet_kill(&cs->write_tasklet); - goto error; - } - return 0; - -error: - usb_kill_urb(ucs->read_urb); - kfree(ucs->bulk_out_buffer); - usb_free_urb(ucs->bulk_out_urb); - kfree(ucs->rcvbuf); - usb_free_urb(ucs->read_urb); - usb_set_intfdata(interface, NULL); - ucs->read_urb = ucs->bulk_out_urb = NULL; - ucs->rcvbuf = ucs->bulk_out_buffer = NULL; - usb_put_dev(ucs->udev); - ucs->udev = NULL; - ucs->interface = NULL; - gigaset_freecs(cs); - return retval; -} - -static void gigaset_disconnect(struct usb_interface *interface) -{ - struct cardstate *cs; - struct usb_cardstate *ucs; - - cs = usb_get_intfdata(interface); - ucs = cs->hw.usb; - - dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); - - usb_kill_urb(ucs->read_urb); - - gigaset_stop(cs); - - usb_set_intfdata(interface, NULL); - tasklet_kill(&cs->write_tasklet); - - usb_kill_urb(ucs->bulk_out_urb); - - kfree(ucs->bulk_out_buffer); - usb_free_urb(ucs->bulk_out_urb); - kfree(ucs->rcvbuf); - usb_free_urb(ucs->read_urb); - ucs->read_urb = ucs->bulk_out_urb = NULL; - ucs->rcvbuf = ucs->bulk_out_buffer = NULL; - - usb_put_dev(ucs->udev); - ucs->interface = NULL; - ucs->udev = NULL; - cs->dev = NULL; - gigaset_freecs(cs); -} - -/* gigaset_suspend - * This function is called before the USB connection is suspended or reset. - */ -static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct cardstate *cs = usb_get_intfdata(intf); - - /* stop activity */ - cs->connected = 0; /* prevent rescheduling */ - usb_kill_urb(cs->hw.usb->read_urb); - tasklet_kill(&cs->write_tasklet); - usb_kill_urb(cs->hw.usb->bulk_out_urb); - - gig_dbg(DEBUG_SUSPEND, "suspend complete"); - return 0; -} - -/* gigaset_resume - * This function is called after the USB connection has been resumed or reset. - */ -static int gigaset_resume(struct usb_interface *intf) -{ - struct cardstate *cs = usb_get_intfdata(intf); - int rc; - - /* resubmit interrupt URB */ - cs->connected = 1; - rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL); - if (rc) { - dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc); - return rc; - } - - gig_dbg(DEBUG_SUSPEND, "resume complete"); - return 0; -} - -/* gigaset_pre_reset - * This function is called before the USB connection is reset. - */ -static int gigaset_pre_reset(struct usb_interface *intf) -{ - /* same as suspend */ - return gigaset_suspend(intf, PMSG_ON); -} - -static const struct gigaset_ops ops = { - .write_cmd = gigaset_write_cmd, - .write_room = gigaset_write_room, - .chars_in_buffer = gigaset_chars_in_buffer, - .brkchars = gigaset_brkchars, - .init_bchannel = gigaset_init_bchannel, - .close_bchannel = gigaset_close_bchannel, - .initbcshw = gigaset_initbcshw, - .freebcshw = gigaset_freebcshw, - .reinitbcshw = gigaset_reinitbcshw, - .initcshw = gigaset_initcshw, - .freecshw = gigaset_freecshw, - .set_modem_ctrl = gigaset_set_modem_ctrl, - .baud_rate = gigaset_baud_rate, - .set_line_ctrl = gigaset_set_line_ctrl, - .send_skb = gigaset_m10x_send_skb, - .handle_input = gigaset_m10x_input, -}; - -/* - * This function is called while kernel-module is loaded - */ -static int __init usb_gigaset_init(void) -{ - int result; - - /* allocate memory for our driver state and initialize it */ - driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - &ops, THIS_MODULE); - if (driver == NULL) { - result = -ENOMEM; - goto error; - } - - /* register this driver with the USB subsystem */ - result = usb_register(&gigaset_usb_driver); - if (result < 0) { - pr_err("error %d registering USB driver\n", -result); - goto error; - } - - pr_info(DRIVER_DESC "\n"); - return 0; - -error: - if (driver) - gigaset_freedriver(driver); - driver = NULL; - return result; -} - -/* - * This function is called while unloading the kernel-module - */ -static void __exit usb_gigaset_exit(void) -{ - int i; - - gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ - - /* stop all connected devices */ - for (i = 0; i < driver->minors; i++) - gigaset_shutdown(driver->cs + i); - - /* from now on, no isdn callback should be possible */ - - /* deregister this driver with the USB subsystem */ - usb_deregister(&gigaset_usb_driver); - /* this will call the disconnect-callback */ - /* from now on, no disconnect/probe callback should be running */ - - gigaset_freedriver(driver); - driver = NULL; -} - - -module_init(usb_gigaset_init); -module_exit(usb_gigaset_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/isdn/hysdn/Kconfig b/drivers/staging/isdn/hysdn/Kconfig deleted file mode 100644 index 4c8a9283b9dd..000000000000 --- a/drivers/staging/isdn/hysdn/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -config HYSDN - tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" - depends on m && PROC_FS && PCI - help - Say Y here if you have one of Hypercope's active PCI ISDN cards - Champ, Ergo and Metro. You will then get a module called hysdn. - Please read the file for more - information. - -config HYSDN_CAPI - bool "HYSDN CAPI 2.0 support" - depends on HYSDN && ISDN_CAPI - help - Say Y here if you like to use Hypercope's CAPI 2.0 interface. diff --git a/drivers/staging/isdn/hysdn/Makefile b/drivers/staging/isdn/hysdn/Makefile deleted file mode 100644 index e01f17f22ebb..000000000000 --- a/drivers/staging/isdn/hysdn/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Makefile for the hysdn ISDN device driver - -# Each configuration option enables a list of files. - -obj-$(CONFIG_HYSDN) += hysdn.o - -# Multipart objects. - -hysdn-y := hysdn_procconf.o hysdn_proclog.o boardergo.o \ - hysdn_boot.o hysdn_sched.o hysdn_net.o hysdn_init.o -hysdn-$(CONFIG_HYSDN_CAPI) += hycapi.o diff --git a/drivers/staging/isdn/hysdn/boardergo.c b/drivers/staging/isdn/hysdn/boardergo.c deleted file mode 100644 index 2aa2a0e08247..000000000000 --- a/drivers/staging/isdn/hysdn/boardergo.c +++ /dev/null @@ -1,445 +0,0 @@ -/* $Id: boardergo.c,v 1.5.6.7 2001/11/06 21:58:19 kai Exp $ - * - * Linux driver for HYSDN cards, specific routines for ergo type boards. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same - * DPRAM interface and layout with only minor differences all related - * stuff is done here, not in separate modules. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" -#include "boardergo.h" - -#define byteout(addr, val) outb(val, addr) -#define bytein(addr) inb(addr) - -/***************************************************/ -/* The cards interrupt handler. Called from system */ -/***************************************************/ -static irqreturn_t -ergo_interrupt(int intno, void *dev_id) -{ - hysdn_card *card = dev_id; /* parameter from irq */ - tErgDpram *dpr; - unsigned long flags; - unsigned char volatile b; - - if (!card) - return IRQ_NONE; /* error -> spurious interrupt */ - if (!card->irq_enabled) - return IRQ_NONE; /* other device interrupting or irq switched off */ - - spin_lock_irqsave(&card->hysdn_lock, flags); /* no further irqs allowed */ - - if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); /* restore old state */ - return IRQ_NONE; /* no interrupt requested by E1 */ - } - /* clear any pending ints on the board */ - dpr = card->dpram; - b = dpr->ToPcInt; /* clear for ergo */ - b |= dpr->ToPcIntMetro; /* same for metro */ - b |= dpr->ToHyInt; /* and for champ */ - - /* start kernel task immediately after leaving all interrupts */ - if (!card->hw_lock) - schedule_work(&card->irq_queue); - spin_unlock_irqrestore(&card->hysdn_lock, flags); - return IRQ_HANDLED; -} /* ergo_interrupt */ - -/******************************************************************************/ -/* ergo_irq_bh will be called as part of the kernel clearing its shared work */ -/* queue sometime after a call to schedule_work has been made passing our */ -/* work_struct. This task is the only one handling data transfer from or to */ -/* the card after booting. The task may be queued from everywhere */ -/* (interrupts included). */ -/******************************************************************************/ -static void -ergo_irq_bh(struct work_struct *ugli_api) -{ - hysdn_card *card = container_of(ugli_api, hysdn_card, irq_queue); - tErgDpram *dpr; - int again; - unsigned long flags; - - if (card->state != CARD_STATE_RUN) - return; /* invalid call */ - - dpr = card->dpram; /* point to DPRAM */ - - spin_lock_irqsave(&card->hysdn_lock, flags); - if (card->hw_lock) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); /* hardware currently unavailable */ - return; - } - card->hw_lock = 1; /* we now lock the hardware */ - - do { - again = 0; /* assume loop not to be repeated */ - - if (!dpr->ToHyFlag) { - /* we are able to send a buffer */ - - if (hysdn_sched_tx(card, dpr->ToHyBuf, &dpr->ToHySize, &dpr->ToHyChannel, - ERG_TO_HY_BUF_SIZE)) { - dpr->ToHyFlag = 1; /* enable tx */ - again = 1; /* restart loop */ - } - } /* we are able to send a buffer */ - if (dpr->ToPcFlag) { - /* a message has arrived for us, handle it */ - - if (hysdn_sched_rx(card, dpr->ToPcBuf, dpr->ToPcSize, dpr->ToPcChannel)) { - dpr->ToPcFlag = 0; /* we worked the data */ - again = 1; /* restart loop */ - } - } /* a message has arrived for us */ - if (again) { - dpr->ToHyInt = 1; - dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ - } else - card->hw_lock = 0; /* free hardware again */ - } while (again); /* until nothing more to do */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); -} /* ergo_irq_bh */ - - -/*********************************************************/ -/* stop the card (hardware reset) and disable interrupts */ -/*********************************************************/ -static void -ergo_stopcard(hysdn_card *card) -{ - unsigned long flags; - unsigned char val; - - hysdn_net_release(card); /* first release the net device if existing */ -#ifdef CONFIG_HYSDN_CAPI - hycapi_capi_stop(card); -#endif /* CONFIG_HYSDN_CAPI */ - spin_lock_irqsave(&card->hysdn_lock, flags); - val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */ - val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */ - byteout(card->iobase + PCI9050_INTR_REG, val); - card->irq_enabled = 0; - byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */ - card->state = CARD_STATE_UNUSED; - card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); -} /* ergo_stopcard */ - -/**************************************************************************/ -/* enable or disable the cards error log. The event is queued if possible */ -/**************************************************************************/ -static void -ergo_set_errlog_state(hysdn_card *card, int on) -{ - unsigned long flags; - - if (card->state != CARD_STATE_RUN) { - card->err_log_state = ERRLOG_STATE_OFF; /* must be off */ - return; - } - spin_lock_irqsave(&card->hysdn_lock, flags); - - if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) || - ((card->err_log_state == ERRLOG_STATE_ON) && on)) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); - return; /* nothing to do */ - } - if (on) - card->err_log_state = ERRLOG_STATE_START; /* request start */ - else - card->err_log_state = ERRLOG_STATE_STOP; /* request stop */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); - schedule_work(&card->irq_queue); -} /* ergo_set_errlog_state */ - -/******************************************/ -/* test the cards RAM and return 0 if ok. */ -/******************************************/ -static const char TestText[36] = "This Message is filler, why read it"; - -static int -ergo_testram(hysdn_card *card) -{ - tErgDpram *dpr = card->dpram; - - memset(dpr->TrapTable, 0, sizeof(dpr->TrapTable)); /* clear all Traps */ - dpr->ToHyInt = 1; /* E1 INTR state forced */ - - memcpy(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText)); - if (memcmp(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText))) - return (-1); - - memcpy(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText)); - if (memcmp(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText))) - return (-1); - - return (0); -} /* ergo_testram */ - -/*****************************************************************************/ -/* this function is intended to write stage 1 boot image to the cards buffer */ -/* this is done in two steps. First the 1024 hi-words are written (offs=0), */ -/* then the 1024 lo-bytes are written. The remaining DPRAM is cleared, the */ -/* PCI-write-buffers flushed and the card is taken out of reset. */ -/* The function then waits for a reaction of the E1 processor or a timeout. */ -/* Negative return values are interpreted as errors. */ -/*****************************************************************************/ -static int -ergo_writebootimg(struct HYSDN_CARD *card, unsigned char *buf, - unsigned long offs) -{ - unsigned char *dst; - tErgDpram *dpram; - int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */ - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs); - - dst = card->dpram; /* pointer to start of DPRAM */ - dst += (offs + ERG_DPRAM_FILL_SIZE); /* offset in the DPRAM */ - while (cnt--) { - *dst++ = *(buf + 1); /* high byte */ - *dst++ = *buf; /* low byte */ - dst += 2; /* point to next longword */ - buf += 2; /* buffer only filled with words */ - } - - /* if low words (offs = 2) have been written, clear the rest of the DPRAM, */ - /* flush the PCI-write-buffer and take the E1 out of reset */ - if (offs) { - memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE); /* fill the DPRAM still not cleared */ - dpram = card->dpram; /* get pointer to dpram structure */ - dpram->ToHyNoDpramErrLog = 0xFF; /* write a dpram register */ - while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */ - - byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */ - /* the interrupts are still masked */ - - msleep_interruptible(20); /* Timeout 20ms */ - - if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) { - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write bootldr no answer"); - return (-ERR_BOOTIMG_FAIL); - } - } /* start_boot_img */ - return (0); /* successful */ -} /* ergo_writebootimg */ - -/********************************************************************************/ -/* ergo_writebootseq writes the buffer containing len bytes to the E1 processor */ -/* using the boot spool mechanism. If everything works fine 0 is returned. In */ -/* case of errors a negative error value is returned. */ -/********************************************************************************/ -static int -ergo_writebootseq(struct HYSDN_CARD *card, unsigned char *buf, int len) -{ - tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram; - unsigned char *dst; - unsigned char buflen; - int nr_write; - unsigned char tmp_rdptr; - unsigned char wr_mirror; - int i; - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write boot seq len=%d ", len); - - dst = sp->Data; /* point to data in spool structure */ - buflen = sp->Len; /* maximum len of spooled data */ - wr_mirror = sp->WrPtr; /* only once read */ - - /* try until all bytes written or error */ - i = 0x1000; /* timeout value */ - while (len) { - - /* first determine the number of bytes that may be buffered */ - do { - tmp_rdptr = sp->RdPtr; /* first read the pointer */ - i--; /* decrement timeout */ - } while (i && (tmp_rdptr != sp->RdPtr)); /* wait for stable pointer */ - - if (!i) { - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write boot seq timeout"); - return (-ERR_BOOTSEQ_FAIL); /* value not stable -> timeout */ - } - if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0) - nr_write += buflen; /* now we got number of free bytes - 1 in buffer */ - - if (!nr_write) - continue; /* no free bytes in buffer */ - - if (nr_write > len) - nr_write = len; /* limit if last few bytes */ - i = 0x1000; /* reset timeout value */ - - /* now we know how much bytes we may put in the puffer */ - len -= nr_write; /* we savely could adjust len before output */ - while (nr_write--) { - *(dst + wr_mirror) = *buf++; /* output one byte */ - if (++wr_mirror >= buflen) - wr_mirror = 0; - sp->WrPtr = wr_mirror; /* announce the next byte to E1 */ - } /* while (nr_write) */ - - } /* while (len) */ - return (0); -} /* ergo_writebootseq */ - -/***********************************************************************************/ -/* ergo_waitpofready waits for a maximum of 10 seconds for the completition of the */ -/* boot process. If the process has been successful 0 is returned otherwise a */ -/* negative error code is returned. */ -/***********************************************************************************/ -static int -ergo_waitpofready(struct HYSDN_CARD *card) -{ - tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */ - int timecnt = 10000 / 50; /* timeout is 10 secs max. */ - unsigned long flags; - int msg_size; - int i; - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: waiting for pof ready"); - while (timecnt--) { - /* wait until timeout */ - - if (dpr->ToPcFlag) { - /* data has arrived */ - - if ((dpr->ToPcChannel != CHAN_SYSTEM) || - (dpr->ToPcSize < MIN_RDY_MSG_SIZE) || - (dpr->ToPcSize > MAX_RDY_MSG_SIZE) || - ((*(unsigned long *) dpr->ToPcBuf) != RDY_MAGIC)) - break; /* an error occurred */ - - /* Check for additional data delivered during SysReady */ - msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE; - if (msg_size > 0) - if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size)) - break; - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "ERGO: pof boot success"); - spin_lock_irqsave(&card->hysdn_lock, flags); - - card->state = CARD_STATE_RUN; /* now card is running */ - /* enable the cards interrupt */ - byteout(card->iobase + PCI9050_INTR_REG, - bytein(card->iobase + PCI9050_INTR_REG) | - (PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1)); - card->irq_enabled = 1; /* we are ready to receive interrupts */ - - dpr->ToPcFlag = 0; /* reset data indicator */ - dpr->ToHyInt = 1; - dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); - if ((hynet_enable & (1 << card->myid)) - && (i = hysdn_net_create(card))) - { - ergo_stopcard(card); - card->state = CARD_STATE_BOOTERR; - return (i); - } -#ifdef CONFIG_HYSDN_CAPI - if ((i = hycapi_capi_create(card))) { - printk(KERN_WARNING "HYSDN: failed to create capi-interface.\n"); - } -#endif /* CONFIG_HYSDN_CAPI */ - return (0); /* success */ - } /* data has arrived */ - msleep_interruptible(50); /* Timeout 50ms */ - } /* wait until timeout */ - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: pof boot ready timeout"); - return (-ERR_POF_TIMEOUT); -} /* ergo_waitpofready */ - - - -/************************************************************************************/ -/* release the cards hardware. Before releasing do a interrupt disable and hardware */ -/* reset. Also unmap dpram. */ -/* Use only during module release. */ -/************************************************************************************/ -static void -ergo_releasehardware(hysdn_card *card) -{ - ergo_stopcard(card); /* first stop the card if not already done */ - free_irq(card->irq, card); /* release interrupt */ - release_region(card->iobase + PCI9050_INTR_REG, 1); /* release all io ports */ - release_region(card->iobase + PCI9050_USER_IO, 1); - iounmap(card->dpram); - card->dpram = NULL; /* release shared mem */ -} /* ergo_releasehardware */ - - -/*********************************************************************************/ -/* acquire the needed hardware ports and map dpram. If an error occurs a nonzero */ -/* value is returned. */ -/* Use only during module init. */ -/*********************************************************************************/ -int -ergo_inithardware(hysdn_card *card) -{ - if (!request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN")) - return (-1); - if (!request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN")) { - release_region(card->iobase + PCI9050_INTR_REG, 1); - return (-1); /* ports already in use */ - } - card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1; - if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) { - release_region(card->iobase + PCI9050_INTR_REG, 1); - release_region(card->iobase + PCI9050_USER_IO, 1); - return (-1); - } - - ergo_stopcard(card); /* disable interrupts */ - if (request_irq(card->irq, ergo_interrupt, IRQF_SHARED, "HYSDN", card)) { - ergo_releasehardware(card); /* return the acquired hardware */ - return (-1); - } - /* success, now setup the function pointers */ - card->stopcard = ergo_stopcard; - card->releasehardware = ergo_releasehardware; - card->testram = ergo_testram; - card->writebootimg = ergo_writebootimg; - card->writebootseq = ergo_writebootseq; - card->waitpofready = ergo_waitpofready; - card->set_errlog_state = ergo_set_errlog_state; - INIT_WORK(&card->irq_queue, ergo_irq_bh); - spin_lock_init(&card->hysdn_lock); - - return (0); -} /* ergo_inithardware */ diff --git a/drivers/staging/isdn/hysdn/boardergo.h b/drivers/staging/isdn/hysdn/boardergo.h deleted file mode 100644 index e99bd81c4034..000000000000 --- a/drivers/staging/isdn/hysdn/boardergo.h +++ /dev/null @@ -1,100 +0,0 @@ -/* $Id: boardergo.h,v 1.2.6.1 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..). - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - - -/************************************************/ -/* defines for the dual port memory of the card */ -/************************************************/ -#define ERG_DPRAM_PAGE_SIZE 0x2000 /* DPRAM occupies a 8K page */ -#define BOOT_IMG_SIZE 4096 -#define ERG_DPRAM_FILL_SIZE (ERG_DPRAM_PAGE_SIZE - BOOT_IMG_SIZE) - -#define ERG_TO_HY_BUF_SIZE 0x0E00 /* 3072 bytes buffer size to card */ -#define ERG_TO_PC_BUF_SIZE 0x0E00 /* 3072 bytes to PC, too */ - -/* following DPRAM layout copied from OS2-driver boarderg.h */ -typedef struct ErgDpram_tag { - /*0000 */ unsigned char ToHyBuf[ERG_TO_HY_BUF_SIZE]; - /*0E00 */ unsigned char ToPcBuf[ERG_TO_PC_BUF_SIZE]; - - /*1C00 */ unsigned char bSoftUart[SIZE_RSV_SOFT_UART]; - /* size 0x1B0 */ - - /*1DB0 *//* tErrLogEntry */ unsigned char volatile ErrLogMsg[64]; - /* size 64 bytes */ - /*1DB0 unsigned long ulErrType; */ - /*1DB4 unsigned long ulErrSubtype; */ - /*1DB8 unsigned long ucTextSize; */ - /*1DB9 unsigned long ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */ - /*1DF0 */ - - /*1DF0 */ unsigned short volatile ToHyChannel; - /*1DF2 */ unsigned short volatile ToHySize; - /*1DF4 */ unsigned char volatile ToHyFlag; - /* !=0: msg for Hy waiting */ - /*1DF5 */ unsigned char volatile ToPcFlag; - /* !=0: msg for PC waiting */ - /*1DF6 */ unsigned short volatile ToPcChannel; - /*1DF8 */ unsigned short volatile ToPcSize; - /*1DFA */ unsigned char bRes1DBA[0x1E00 - 0x1DFA]; - /* 6 bytes */ - - /*1E00 */ unsigned char bRestOfEntryTbl[0x1F00 - 0x1E00]; - /*1F00 */ unsigned long TrapTable[62]; - /*1FF8 */ unsigned char bRes1FF8[0x1FFB - 0x1FF8]; - /* low part of reset vetor */ - /*1FFB */ unsigned char ToPcIntMetro; - /* notes: - * - metro has 32-bit boot ram - accessing - * ToPcInt and ToHyInt would be the same; - * so we moved ToPcInt to 1FFB. - * Because on the PC side both vars are - * readonly (reseting on int from E1 to PC), - * we can read both vars on both cards - * without destroying anything. - * - 1FFB is the high byte of the reset vector, - * so E1 side should NOT change this byte - * when writing! - */ - /*1FFC */ unsigned char volatile ToHyNoDpramErrLog; - /* note: ToHyNoDpramErrLog is used to inform - * boot loader, not to use DPRAM based - * ErrLog; when DOS driver is rewritten - * this becomes obsolete - */ - /*1FFD */ unsigned char bRes1FFD; - /*1FFE */ unsigned char ToPcInt; - /* E1_intclear; on CHAMP2: E1_intset */ - /*1FFF */ unsigned char ToHyInt; - /* E1_intset; on CHAMP2: E1_intclear */ -} tErgDpram; - -/**********************************************/ -/* PCI9050 controller local register offsets: */ -/* copied from boarderg.c */ -/**********************************************/ -#define PCI9050_INTR_REG 0x4C /* Interrupt register */ -#define PCI9050_USER_IO 0x51 /* User I/O register */ - -/* bitmask for PCI9050_INTR_REG: */ -#define PCI9050_INTR_REG_EN1 0x01 /* 1= enable (def.), 0= disable */ -#define PCI9050_INTR_REG_POL1 0x02 /* 1= active high (def.), 0= active low */ -#define PCI9050_INTR_REG_STAT1 0x04 /* 1= intr. active, 0= intr. not active (def.) */ -#define PCI9050_INTR_REG_ENPCI 0x40 /* 1= PCI interrupts enable (def.) */ - -/* bitmask for PCI9050_USER_IO: */ -#define PCI9050_USER_IO_EN3 0x02 /* 1= disable , 0= enable (def.) */ -#define PCI9050_USER_IO_DIR3 0x04 /* 1= output (def.), 0= input */ -#define PCI9050_USER_IO_DAT3 0x08 /* 1= high (def.) , 0= low */ - -#define PCI9050_E1_RESET (PCI9050_USER_IO_DIR3) /* 0x04 */ -#define PCI9050_E1_RUN (PCI9050_USER_IO_DAT3 | PCI9050_USER_IO_DIR3) /* 0x0C */ diff --git a/drivers/staging/isdn/hysdn/hycapi.c b/drivers/staging/isdn/hysdn/hycapi.c deleted file mode 100644 index a2c15cd7bf67..000000000000 --- a/drivers/staging/isdn/hysdn/hycapi.c +++ /dev/null @@ -1,785 +0,0 @@ -/* $Id: hycapi.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, CAPI2.0-Interface. - * - * Author Ulrich Albrecht for Hypercope GmbH - * Copyright 2000 by Hypercope GmbH - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define VER_DRIVER 0 -#define VER_CARDTYPE 1 -#define VER_HWID 2 -#define VER_SERIAL 3 -#define VER_OPTION 4 -#define VER_PROTO 5 -#define VER_PROFILE 6 -#define VER_CAPI 7 - -#include "hysdn_defs.h" -#include - -static char hycapi_revision[] = "$Revision: 1.8.6.4 $"; - -unsigned int hycapi_enable = 0xffffffff; -module_param(hycapi_enable, uint, 0); - -typedef struct _hycapi_appl { - unsigned int ctrl_mask; - capi_register_params rp; - struct sk_buff *listen_req[CAPI_MAXCONTR]; -} hycapi_appl; - -static hycapi_appl hycapi_applications[CAPI_MAXAPPL]; - -static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); - -static inline int _hycapi_appCheck(int app_id, int ctrl_no) -{ - if ((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) || - (app_id > CAPI_MAXAPPL)) - { - printk(KERN_ERR "HYCAPI: Invalid request app_id %d for controller %d", app_id, ctrl_no); - return -1; - } - return ((hycapi_applications[app_id - 1].ctrl_mask & (1 << (ctrl_no-1))) != 0); -} - -/****************************** -Kernel-Capi callback reset_ctr -******************************/ - -static void -hycapi_reset_ctr(struct capi_ctr *ctrl) -{ - hycapictrl_info *cinfo = ctrl->driverdata; - -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n"); -#endif - capilib_release(&cinfo->ncci_head); - capi_ctr_down(ctrl); -} - -/****************************** -Kernel-Capi callback remove_ctr -******************************/ - -static void -hycapi_remove_ctr(struct capi_ctr *ctrl) -{ - int i; - hycapictrl_info *cinfo = NULL; - hysdn_card *card = NULL; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "HYCAPI hycapi_remove_ctr\n"); -#endif - cinfo = (hycapictrl_info *)(ctrl->driverdata); - if (!cinfo) { - printk(KERN_ERR "No hycapictrl_info set!"); - return; - } - card = cinfo->card; - capi_ctr_suspend_output(ctrl); - for (i = 0; i < CAPI_MAXAPPL; i++) { - if (hycapi_applications[i].listen_req[ctrl->cnr - 1]) { - kfree_skb(hycapi_applications[i].listen_req[ctrl->cnr - 1]); - hycapi_applications[i].listen_req[ctrl->cnr - 1] = NULL; - } - } - detach_capi_ctr(ctrl); - ctrl->driverdata = NULL; - kfree(card->hyctrlinfo); - - - card->hyctrlinfo = NULL; -} - -/*********************************************************** - -Queue a CAPI-message to the controller. - -***********************************************************/ - -static void -hycapi_sendmsg_internal(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - - spin_lock_irq(&cinfo->lock); -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_send_message\n"); -#endif - cinfo->skbs[cinfo->in_idx++] = skb; /* add to buffer list */ - if (cinfo->in_idx >= HYSDN_MAX_CAPI_SKB) - cinfo->in_idx = 0; /* wrap around */ - cinfo->sk_count++; /* adjust counter */ - if (cinfo->sk_count >= HYSDN_MAX_CAPI_SKB) { - /* inform upper layers we're full */ - printk(KERN_ERR "HYSDN Card%d: CAPI-buffer overrun!\n", - card->myid); - capi_ctr_suspend_output(ctrl); - } - cinfo->tx_skb = skb; - spin_unlock_irq(&cinfo->lock); - schedule_work(&card->irq_queue); -} - -/*********************************************************** -hycapi_register_internal - -Send down the CAPI_REGISTER-Command to the controller. -This functions will also be used if the adapter has been rebooted to -re-register any applications in the private list. - -************************************************************/ - -static void -hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl, - capi_register_params *rp) -{ - char ExtFeatureDefaults[] = "49 /0/0/0/0,*/1,*/2,*/3,*/4,*/5,*/6,*/7,*/8,*/9,*"; - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - struct sk_buff *skb; - __u16 len; - __u8 _command = 0xa0, _subcommand = 0x80; - __u16 MessageNumber = 0x0000; - __u16 MessageBufferSize = 0; - int slen = strlen(ExtFeatureDefaults); -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_register_appl\n"); -#endif - MessageBufferSize = rp->level3cnt * rp->datablkcnt * rp->datablklen; - - len = CAPI_MSG_BASELEN + 8 + slen + 1; - if (!(skb = alloc_skb(len, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", - card->myid); - return; - } - skb_put_data(skb, &len, sizeof(__u16)); - skb_put_data(skb, &appl, sizeof(__u16)); - skb_put_data(skb, &_command, sizeof(__u8)); - skb_put_data(skb, &_subcommand, sizeof(__u8)); - skb_put_data(skb, &MessageNumber, sizeof(__u16)); - skb_put_data(skb, &MessageBufferSize, sizeof(__u16)); - skb_put_data(skb, &(rp->level3cnt), sizeof(__u16)); - skb_put_data(skb, &(rp->datablkcnt), sizeof(__u16)); - skb_put_data(skb, &(rp->datablklen), sizeof(__u16)); - skb_put_data(skb, ExtFeatureDefaults, slen); - hycapi_applications[appl - 1].ctrl_mask |= (1 << (ctrl->cnr - 1)); - hycapi_send_message(ctrl, skb); -} - -/************************************************************ -hycapi_restart_internal - -After an adapter has been rebootet, re-register all applications and -send a LISTEN_REQ (if there has been such a thing ) - -*************************************************************/ - -static void hycapi_restart_internal(struct capi_ctr *ctrl) -{ - int i; - struct sk_buff *skb; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_WARNING "HYSDN: hycapi_restart_internal"); -#endif - for (i = 0; i < CAPI_MAXAPPL; i++) { - if (_hycapi_appCheck(i + 1, ctrl->cnr) == 1) { - hycapi_register_internal(ctrl, i + 1, - &hycapi_applications[i].rp); - if (hycapi_applications[i].listen_req[ctrl->cnr - 1]) { - skb = skb_copy(hycapi_applications[i].listen_req[ctrl->cnr - 1], GFP_ATOMIC); - hycapi_sendmsg_internal(ctrl, skb); - } - } - } -} - -/************************************************************* -Register an application. -Error-checking is done for CAPI-compliance. - -The application is recorded in the internal list. -*************************************************************/ - -static void -hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl, - capi_register_params *rp) -{ - int MaxLogicalConnections = 0, MaxBDataBlocks = 0, MaxBDataLen = 0; - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - int chk = _hycapi_appCheck(appl, ctrl->cnr); - if (chk < 0) { - return; - } - if (chk == 1) { - printk(KERN_INFO "HYSDN: apl %d already registered\n", appl); - return; - } - MaxBDataBlocks = rp->datablkcnt > CAPI_MAXDATAWINDOW ? CAPI_MAXDATAWINDOW : rp->datablkcnt; - rp->datablkcnt = MaxBDataBlocks; - MaxBDataLen = rp->datablklen < 1024 ? 1024 : rp->datablklen; - rp->datablklen = MaxBDataLen; - - MaxLogicalConnections = rp->level3cnt; - if (MaxLogicalConnections < 0) { - MaxLogicalConnections = card->bchans * -MaxLogicalConnections; - } - if (MaxLogicalConnections == 0) { - MaxLogicalConnections = card->bchans; - } - - rp->level3cnt = MaxLogicalConnections; - memcpy(&hycapi_applications[appl - 1].rp, - rp, sizeof(capi_register_params)); -} - -/********************************************************************* - -hycapi_release_internal - -Send down a CAPI_RELEASE to the controller. -*********************************************************************/ - -static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl) -{ - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - struct sk_buff *skb; - __u16 len; - __u8 _command = 0xa1, _subcommand = 0x80; - __u16 MessageNumber = 0x0000; - - capilib_release_appl(&cinfo->ncci_head, appl); - -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_release_appl\n"); -#endif - len = CAPI_MSG_BASELEN; - if (!(skb = alloc_skb(len, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", - card->myid); - return; - } - skb_put_data(skb, &len, sizeof(__u16)); - skb_put_data(skb, &appl, sizeof(__u16)); - skb_put_data(skb, &_command, sizeof(__u8)); - skb_put_data(skb, &_subcommand, sizeof(__u8)); - skb_put_data(skb, &MessageNumber, sizeof(__u16)); - hycapi_send_message(ctrl, skb); - hycapi_applications[appl - 1].ctrl_mask &= ~(1 << (ctrl->cnr - 1)); -} - -/****************************************************************** -hycapi_release_appl - -Release the application from the internal list an remove it's -registration at controller-level -******************************************************************/ - -static void -hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl) -{ - int chk; - - chk = _hycapi_appCheck(appl, ctrl->cnr); - if (chk < 0) { - printk(KERN_ERR "HYCAPI: Releasing invalid appl %d on controller %d\n", appl, ctrl->cnr); - return; - } - if (hycapi_applications[appl - 1].listen_req[ctrl->cnr - 1]) { - kfree_skb(hycapi_applications[appl - 1].listen_req[ctrl->cnr - 1]); - hycapi_applications[appl - 1].listen_req[ctrl->cnr - 1] = NULL; - } - if (chk == 1) - { - hycapi_release_internal(ctrl, appl); - } -} - - -/************************************************************** -Kill a single controller. -**************************************************************/ - -int hycapi_capi_release(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; - struct capi_ctr *ctrl; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_capi_release\n"); -#endif - if (cinfo) { - ctrl = &cinfo->capi_ctrl; - hycapi_remove_ctr(ctrl); - } - return 0; -} - -/************************************************************** -hycapi_capi_stop - -Stop CAPI-Output on a card. (e.g. during reboot) -***************************************************************/ - -int hycapi_capi_stop(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; - struct capi_ctr *ctrl; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_capi_stop\n"); -#endif - if (cinfo) { - ctrl = &cinfo->capi_ctrl; -/* ctrl->suspend_output(ctrl); */ - capi_ctr_down(ctrl); - } - return 0; -} - -/*************************************************************** -hycapi_send_message - -Send a message to the controller. - -Messages are parsed for their Command/Subcommand-type, and appropriate -action's are performed. - -Note that we have to muck around with a 64Bit-DATA_REQ as there are -firmware-releases that do not check the MsgLen-Indication! - -***************************************************************/ - -static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - __u16 appl_id; - int _len, _len2; - __u8 msghead[64]; - hycapictrl_info *cinfo = ctrl->driverdata; - u16 retval = CAPI_NOERROR; - - appl_id = CAPIMSG_APPID(skb->data); - switch (_hycapi_appCheck(appl_id, ctrl->cnr)) - { - case 0: -/* printk(KERN_INFO "Need to register\n"); */ - hycapi_register_internal(ctrl, - appl_id, - &(hycapi_applications[appl_id - 1].rp)); - break; - case 1: - break; - default: - printk(KERN_ERR "HYCAPI: Controller mixup!\n"); - retval = CAPI_ILLAPPNR; - goto out; - } - switch (CAPIMSG_CMD(skb->data)) { - case CAPI_DISCONNECT_B3_RESP: - capilib_free_ncci(&cinfo->ncci_head, appl_id, - CAPIMSG_NCCI(skb->data)); - break; - case CAPI_DATA_B3_REQ: - _len = CAPIMSG_LEN(skb->data); - if (_len > 22) { - _len2 = _len - 22; - skb_copy_from_linear_data(skb, msghead, 22); - skb_copy_to_linear_data_offset(skb, _len2, - msghead, 22); - skb_pull(skb, _len2); - CAPIMSG_SETLEN(skb->data, 22); - retval = capilib_data_b3_req(&cinfo->ncci_head, - CAPIMSG_APPID(skb->data), - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - } - break; - case CAPI_LISTEN_REQ: - if (hycapi_applications[appl_id - 1].listen_req[ctrl->cnr - 1]) - { - kfree_skb(hycapi_applications[appl_id - 1].listen_req[ctrl->cnr - 1]); - hycapi_applications[appl_id - 1].listen_req[ctrl->cnr - 1] = NULL; - } - if (!(hycapi_applications[appl_id -1].listen_req[ctrl->cnr - 1] = skb_copy(skb, GFP_ATOMIC))) - { - printk(KERN_ERR "HYSDN: memory squeeze in private_listen\n"); - } - break; - default: - break; - } -out: - if (retval == CAPI_NOERROR) - hycapi_sendmsg_internal(ctrl, skb); - else - dev_kfree_skb_any(skb); - - return retval; -} - -static int hycapi_proc_show(struct seq_file *m, void *v) -{ - struct capi_ctr *ctrl = m->private; - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); - hysdn_card *card = cinfo->card; - char *s; - - seq_printf(m, "%-16s %s\n", "name", cinfo->cardname); - seq_printf(m, "%-16s 0x%x\n", "io", card->iobase); - seq_printf(m, "%-16s %d\n", "irq", card->irq); - - switch (card->brdtype) { - case BD_PCCARD: s = "HYSDN Hycard"; break; - case BD_ERGO: s = "HYSDN Ergo2"; break; - case BD_METRO: s = "HYSDN Metro4"; break; - case BD_CHAMP2: s = "HYSDN Champ2"; break; - case BD_PLEXUS: s = "HYSDN Plexus30"; break; - default: s = "???"; break; - } - seq_printf(m, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != NULL) - seq_printf(m, "%-16s %s\n", "ver_serial", s); - - seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); - - return 0; -} - -/************************************************************** -hycapi_load_firmware - -This does NOT load any firmware, but the callback somehow is needed -on capi-interface registration. - -**************************************************************/ - -static int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_load_firmware\n"); -#endif - return 0; -} - - -static char *hycapi_procinfo(struct capi_ctr *ctrl) -{ - hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "%s\n", __func__); -#endif - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d %s", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->iobase : 0x0, - cinfo->card ? cinfo->card->irq : 0, - hycapi_revision - ); - return cinfo->infobuf; -} - -/****************************************************************** -hycapi_rx_capipkt - -Receive a capi-message. - -All B3_DATA_IND are converted to 64K-extension compatible format. -New nccis are created if necessary. -*******************************************************************/ - -void -hycapi_rx_capipkt(hysdn_card *card, unsigned char *buf, unsigned short len) -{ - struct sk_buff *skb; - hycapictrl_info *cinfo = card->hyctrlinfo; - struct capi_ctr *ctrl; - __u16 ApplId; - __u16 MsgLen, info; - __u16 len2, CapiCmd; - __u32 CP64[2] = {0, 0}; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_rx_capipkt\n"); -#endif - if (!cinfo) { - return; - } - ctrl = &cinfo->capi_ctrl; - if (len < CAPI_MSG_BASELEN) { - printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, length %d!\n", - card->myid, len); - return; - } - MsgLen = CAPIMSG_LEN(buf); - ApplId = CAPIMSG_APPID(buf); - CapiCmd = CAPIMSG_CMD(buf); - - if ((CapiCmd == CAPI_DATA_B3_IND) && (MsgLen < 30)) { - len2 = len + (30 - MsgLen); - if (!(skb = alloc_skb(len2, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", - card->myid); - return; - } - skb_put_data(skb, buf, MsgLen); - skb_put_data(skb, CP64, 2 * sizeof(__u32)); - skb_put_data(skb, buf + MsgLen, len - MsgLen); - CAPIMSG_SETLEN(skb->data, 30); - } else { - if (!(skb = alloc_skb(len, GFP_ATOMIC))) { - printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", - card->myid); - return; - } - skb_put_data(skb, buf, len); - } - switch (CAPIMSG_CMD(skb->data)) - { - case CAPI_CONNECT_B3_CONF: -/* Check info-field for error-indication: */ - info = CAPIMSG_U16(skb->data, 12); - switch (info) - { - case 0: - capilib_new_ncci(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data), - hycapi_applications[ApplId - 1].rp.datablkcnt); - - break; - case 0x0001: - printk(KERN_ERR "HYSDN Card%d: NCPI not supported by current " - "protocol. NCPI ignored.\n", card->myid); - break; - case 0x2001: - printk(KERN_ERR "HYSDN Card%d: Message not supported in" - " current state\n", card->myid); - break; - case 0x2002: - printk(KERN_ERR "HYSDN Card%d: invalid PLCI\n", card->myid); - break; - case 0x2004: - printk(KERN_ERR "HYSDN Card%d: out of NCCI\n", card->myid); - break; - case 0x3008: - printk(KERN_ERR "HYSDN Card%d: NCPI not supported\n", - card->myid); - break; - default: - printk(KERN_ERR "HYSDN Card%d: Info in CONNECT_B3_CONF: %d\n", - card->myid, info); - break; - } - break; - case CAPI_CONNECT_B3_IND: - capilib_new_ncci(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - hycapi_applications[ApplId - 1].rp.datablkcnt); - break; - case CAPI_DATA_B3_CONF: - capilib_data_b3_conf(&cinfo->ncci_head, ApplId, - CAPIMSG_NCCI(skb->data), - CAPIMSG_MSGID(skb->data)); - break; - default: - break; - } - capi_ctr_handle_message(ctrl, ApplId, skb); -} - -/****************************************************************** -hycapi_tx_capiack - -Internally acknowledge a msg sent. This will remove the msg from the -internal queue. - -*******************************************************************/ - -void hycapi_tx_capiack(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_tx_capiack\n"); -#endif - if (!cinfo) { - return; - } - spin_lock_irq(&cinfo->lock); - kfree_skb(cinfo->skbs[cinfo->out_idx]); /* free skb */ - cinfo->skbs[cinfo->out_idx++] = NULL; - if (cinfo->out_idx >= HYSDN_MAX_CAPI_SKB) - cinfo->out_idx = 0; /* wrap around */ - - if (cinfo->sk_count-- == HYSDN_MAX_CAPI_SKB) /* dec usage count */ - capi_ctr_resume_output(&cinfo->capi_ctrl); - spin_unlock_irq(&cinfo->lock); -} - -/*************************************************************** -hycapi_tx_capiget(hysdn_card *card) - -This is called when polling for messages to SEND. - -****************************************************************/ - -struct sk_buff * -hycapi_tx_capiget(hysdn_card *card) -{ - hycapictrl_info *cinfo = card->hyctrlinfo; - if (!cinfo) { - return (struct sk_buff *)NULL; - } - if (!cinfo->sk_count) - return (struct sk_buff *)NULL; /* nothing available */ - - return (cinfo->skbs[cinfo->out_idx]); /* next packet to send */ -} - - -/********************************************************** -int hycapi_init() - -attach the capi-driver to the kernel-capi. - -***********************************************************/ - -int hycapi_init(void) -{ - int i; - for (i = 0; i < CAPI_MAXAPPL; i++) { - memset(&(hycapi_applications[i]), 0, sizeof(hycapi_appl)); - } - return (0); -} - -/************************************************************** -hycapi_cleanup(void) - -detach the capi-driver to the kernel-capi. Actually this should -free some more ressources. Do that later. -**************************************************************/ - -void -hycapi_cleanup(void) -{ -} - -/******************************************************************** -hycapi_capi_create(hysdn_card *card) - -Attach the card with its capi-ctrl. -*********************************************************************/ - -static void hycapi_fill_profile(hysdn_card *card) -{ - hycapictrl_info *cinfo = NULL; - struct capi_ctr *ctrl = NULL; - cinfo = card->hyctrlinfo; - if (!cinfo) return; - ctrl = &cinfo->capi_ctrl; - strcpy(ctrl->manu, "Hypercope"); - ctrl->version.majorversion = 2; - ctrl->version.minorversion = 0; - ctrl->version.majormanuversion = 3; - ctrl->version.minormanuversion = 2; - ctrl->profile.ncontroller = card->myid; - ctrl->profile.nbchannel = card->bchans; - ctrl->profile.goptions = GLOBAL_OPTION_INTERNAL_CONTROLLER | - GLOBAL_OPTION_B_CHANNEL_OPERATION; - ctrl->profile.support1 = B1_PROT_64KBIT_HDLC | - (card->faxchans ? B1_PROT_T30 : 0) | - B1_PROT_64KBIT_TRANSPARENT; - ctrl->profile.support2 = B2_PROT_ISO7776 | - (card->faxchans ? B2_PROT_T30 : 0) | - B2_PROT_TRANSPARENT; - ctrl->profile.support3 = B3_PROT_TRANSPARENT | - B3_PROT_T90NL | - (card->faxchans ? B3_PROT_T30 : 0) | - (card->faxchans ? B3_PROT_T30EXT : 0) | - B3_PROT_ISO8208; -} - -int -hycapi_capi_create(hysdn_card *card) -{ - hycapictrl_info *cinfo = NULL; - struct capi_ctr *ctrl = NULL; - int retval; -#ifdef HYCAPI_PRINTFNAMES - printk(KERN_NOTICE "hycapi_capi_create\n"); -#endif - if ((hycapi_enable & (1 << card->myid)) == 0) { - return 1; - } - if (!card->hyctrlinfo) { - cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n"); - return -ENOMEM; - } - card->hyctrlinfo = cinfo; - cinfo->card = card; - spin_lock_init(&cinfo->lock); - INIT_LIST_HEAD(&cinfo->ncci_head); - - switch (card->brdtype) { - case BD_PCCARD: strcpy(cinfo->cardname, "HYSDN Hycard"); break; - case BD_ERGO: strcpy(cinfo->cardname, "HYSDN Ergo2"); break; - case BD_METRO: strcpy(cinfo->cardname, "HYSDN Metro4"); break; - case BD_CHAMP2: strcpy(cinfo->cardname, "HYSDN Champ2"); break; - case BD_PLEXUS: strcpy(cinfo->cardname, "HYSDN Plexus30"); break; - default: strcpy(cinfo->cardname, "HYSDN ???"); break; - } - - ctrl = &cinfo->capi_ctrl; - ctrl->driver_name = "hycapi"; - ctrl->driverdata = cinfo; - ctrl->register_appl = hycapi_register_appl; - ctrl->release_appl = hycapi_release_appl; - ctrl->send_message = hycapi_send_message; - ctrl->load_firmware = hycapi_load_firmware; - ctrl->reset_ctr = hycapi_reset_ctr; - ctrl->procinfo = hycapi_procinfo; - ctrl->proc_show = hycapi_proc_show; - strcpy(ctrl->name, cinfo->cardname); - ctrl->owner = THIS_MODULE; - - retval = attach_capi_ctr(ctrl); - if (retval) { - printk(KERN_ERR "hycapi: attach controller failed.\n"); - return -EBUSY; - } - /* fill in the blanks: */ - hycapi_fill_profile(card); - capi_ctr_ready(ctrl); - } else { - /* resume output on stopped ctrl */ - ctrl = &card->hyctrlinfo->capi_ctrl; - hycapi_fill_profile(card); - capi_ctr_ready(ctrl); - hycapi_restart_internal(ctrl); -/* ctrl->resume_output(ctrl); */ - } - return 0; -} diff --git a/drivers/staging/isdn/hysdn/hysdn_boot.c b/drivers/staging/isdn/hysdn/hysdn_boot.c deleted file mode 100644 index ba177c3a621b..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_boot.c +++ /dev/null @@ -1,400 +0,0 @@ -/* $Id: hysdn_boot.c,v 1.4.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards - * specific routines for booting and pof handling - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include - -#include "hysdn_defs.h" -#include "hysdn_pof.h" - -/********************************/ -/* defines for pof read handler */ -/********************************/ -#define POF_READ_FILE_HEAD 0 -#define POF_READ_TAG_HEAD 1 -#define POF_READ_TAG_DATA 2 - -/************************************************************/ -/* definition of boot specific data area. This data is only */ -/* needed during boot and so allocated dynamically. */ -/************************************************************/ -struct boot_data { - unsigned short Cryptor; /* for use with Decrypt function */ - unsigned short Nrecs; /* records remaining in file */ - unsigned char pof_state;/* actual state of read handler */ - unsigned char is_crypted;/* card data is crypted */ - int BufSize; /* actual number of bytes bufferd */ - int last_error; /* last occurred error */ - unsigned short pof_recid;/* actual pof recid */ - unsigned long pof_reclen;/* total length of pof record data */ - unsigned long pof_recoffset;/* actual offset inside pof record */ - union { - unsigned char BootBuf[BOOT_BUF_SIZE];/* buffer as byte count */ - tPofRecHdr PofRecHdr; /* header for actual record/chunk */ - tPofFileHdr PofFileHdr; /* header from POF file */ - tPofTimeStamp PofTime; /* time information */ - } buf; -}; - -/*****************************************************/ -/* start decryption of successive POF file chuncks. */ -/* */ -/* to be called at start of POF file reading, */ -/* before starting any decryption on any POF record. */ -/*****************************************************/ -static void -StartDecryption(struct boot_data *boot) -{ - boot->Cryptor = CRYPT_STARTTERM; -} /* StartDecryption */ - - -/***************************************************************/ -/* decrypt complete BootBuf */ -/* NOTE: decryption must be applied to all or none boot tags - */ -/* to HI and LO boot loader and (all) seq tags, because */ -/* global Cryptor is started for whole POF. */ -/***************************************************************/ -static void -DecryptBuf(struct boot_data *boot, int cnt) -{ - unsigned char *bufp = boot->buf.BootBuf; - - while (cnt--) { - boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0); - *bufp++ ^= (unsigned char)boot->Cryptor; - } -} /* DecryptBuf */ - -/********************************************************************************/ -/* pof_handle_data executes the required actions dependent on the active record */ -/* id. If successful 0 is returned, a negative value shows an error. */ -/********************************************************************************/ -static int -pof_handle_data(hysdn_card *card, int datlen) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - long l; - unsigned char *imgp; - int img_len; - - /* handle the different record types */ - switch (boot->pof_recid) { - - case TAG_TIMESTMP: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText); - break; - - case TAG_CBOOTDTA: - DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ - /* fall through */ - case TAG_BOOTDTA: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", - (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA", - datlen, boot->pof_recoffset); - - if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) { - boot->last_error = EPOF_BAD_IMG_SIZE; /* invalid length */ - return (boot->last_error); - } - imgp = boot->buf.BootBuf; /* start of buffer */ - img_len = datlen; /* maximum length to transfer */ - - l = POF_BOOT_LOADER_OFF_IN_PAGE - - (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1)); - if (l > 0) { - /* buffer needs to be truncated */ - imgp += l; /* advance pointer */ - img_len -= l; /* adjust len */ - } - /* at this point no special handling for data wrapping over buffer */ - /* is necessary, because the boot image always will be adjusted to */ - /* match a page boundary inside the buffer. */ - /* The buffer for the boot image on the card is filled in 2 cycles */ - /* first the 1024 hi-words are put in the buffer, then the low 1024 */ - /* word are handled in the same way with different offset. */ - - if (img_len > 0) { - /* data available for copy */ - if ((boot->last_error = - card->writebootimg(card, imgp, - (boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0) - return (boot->last_error); - } - break; /* end of case boot image hi/lo */ - - case TAG_CABSDATA: - DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ - /* fall through */ - case TAG_ABSDATA: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", - (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", - datlen, boot->pof_recoffset); - - if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0) - return (boot->last_error); /* error writing data */ - - if (boot->pof_recoffset + datlen >= boot->pof_reclen) - return (card->waitpofready(card)); /* data completely spooled, wait for ready */ - - break; /* end of case boot seq data */ - - default: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid, - datlen, boot->pof_recoffset); - - break; /* simply skip record */ - } /* switch boot->pof_recid */ - - return (0); -} /* pof_handle_data */ - - -/******************************************************************************/ -/* pof_write_buffer is called when the buffer has been filled with the needed */ -/* number of data bytes. The number delivered is additionally supplied for */ -/* verification. The functions handles the data and returns the needed number */ -/* of bytes for the next action. If the returned value is 0 or less an error */ -/* occurred and booting must be aborted. */ -/******************************************************************************/ -int -pof_write_buffer(hysdn_card *card, int datlen) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - - if (!boot) - return (-EFAULT); /* invalid call */ - if (boot->last_error < 0) - return (boot->last_error); /* repeated error */ - - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: got %d bytes ", datlen); - - switch (boot->pof_state) { - case POF_READ_FILE_HEAD: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: checking file header"); - - if (datlen != sizeof(tPofFileHdr)) { - boot->last_error = -EPOF_INTERNAL; - break; - } - if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) { - boot->last_error = -EPOF_BAD_MAGIC; - break; - } - /* Setup the new state and vars */ - boot->Nrecs = (unsigned short)(boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */ - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - break; - - case POF_READ_TAG_HEAD: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: checking tag header"); - - if (datlen != sizeof(tPofRecHdr)) { - boot->last_error = -EPOF_INTERNAL; - break; - } - boot->pof_recid = boot->buf.PofRecHdr.PofRecId; /* actual pof recid */ - boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen; /* total length */ - boot->pof_recoffset = 0; /* no starting offset */ - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ", - boot->pof_recid, boot->pof_reclen); - - boot->pof_state = POF_READ_TAG_DATA; /* now start with tag data */ - if (boot->pof_reclen < BOOT_BUF_SIZE) - boot->last_error = boot->pof_reclen; /* limit size */ - else - boot->last_error = BOOT_BUF_SIZE; /* maximum */ - - if (!boot->last_error) { /* no data inside record */ - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - } - break; - - case POF_READ_TAG_DATA: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: getting tag data"); - - if (datlen != boot->last_error) { - boot->last_error = -EPOF_INTERNAL; - break; - } - if ((boot->last_error = pof_handle_data(card, datlen)) < 0) - return (boot->last_error); /* an error occurred */ - boot->pof_recoffset += datlen; - if (boot->pof_recoffset >= boot->pof_reclen) { - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - } else { - if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE) - boot->last_error = boot->pof_reclen - boot->pof_recoffset; /* limit size */ - else - boot->last_error = BOOT_BUF_SIZE; /* maximum */ - } - break; - - default: - boot->last_error = -EPOF_INTERNAL; /* unknown state */ - break; - } /* switch (boot->pof_state) */ - - return (boot->last_error); -} /* pof_write_buffer */ - - -/*******************************************************************************/ -/* pof_write_open is called when an open for boot on the cardlog device occurs. */ -/* The function returns the needed number of bytes for the next operation. If */ -/* the returned number is less or equal 0 an error specified by this code */ -/* occurred. Additionally the pointer to the buffer data area is set on success */ -/*******************************************************************************/ -int -pof_write_open(hysdn_card *card, unsigned char **bufp) -{ - struct boot_data *boot; /* pointer to boot specific data */ - - if (card->boot) { - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: already opened for boot"); - return (-ERR_ALREADY_BOOT); /* boot already active */ - } - /* error no mem available */ - if (!(boot = kzalloc(sizeof(struct boot_data), GFP_KERNEL))) { - if (card->debug_flags & LOG_MEM_ERR) - hysdn_addlog(card, "POF open: unable to allocate mem"); - return (-EFAULT); - } - card->boot = boot; - card->state = CARD_STATE_BOOTING; - - card->stopcard(card); /* first stop the card */ - if (card->testram(card)) { - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: DPRAM test failure"); - boot->last_error = -ERR_BOARD_DPRAM; - card->state = CARD_STATE_BOOTERR; /* show boot error */ - return (boot->last_error); - } - boot->BufSize = 0; /* Buffer is empty */ - boot->pof_state = POF_READ_FILE_HEAD; /* read file header */ - StartDecryption(boot); /* if POF File should be encrypted */ - - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: success"); - - *bufp = boot->buf.BootBuf; /* point to buffer */ - return (sizeof(tPofFileHdr)); -} /* pof_write_open */ - -/********************************************************************************/ -/* pof_write_close is called when an close of boot on the cardlog device occurs. */ -/* The return value must be 0 if everything has happened as desired. */ -/********************************************************************************/ -int -pof_write_close(hysdn_card *card) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - - if (!boot) - return (-EFAULT); /* invalid call */ - - card->boot = NULL; /* no boot active */ - kfree(boot); - - if (card->state == CARD_STATE_RUN) - card->set_errlog_state(card, 1); /* activate error log */ - - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF close: success"); - - return (0); -} /* pof_write_close */ - -/*********************************************************************************/ -/* EvalSysrTokData checks additional records delivered with the Sysready Message */ -/* when POF has been booted. A return value of 0 is used if no error occurred. */ -/*********************************************************************************/ -int -EvalSysrTokData(hysdn_card *card, unsigned char *cp, int len) -{ - u_char *p; - u_char crc; - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "SysReady Token data length %d", len); - - if (len < 2) { - hysdn_addlog(card, "SysReady Token Data to short"); - return (1); - } - for (p = cp, crc = 0; p < (cp + len - 2); p++) - if ((crc & 0x80)) - crc = (((u_char) (crc << 1)) + 1) + *p; - else - crc = ((u_char) (crc << 1)) + *p; - crc = ~crc; - if (crc != *(cp + len - 1)) { - hysdn_addlog(card, "SysReady Token Data invalid CRC"); - return (1); - } - len--; /* don't check CRC byte */ - while (len > 0) { - - if (*cp == SYSR_TOK_END) - return (0); /* End of Token stream */ - - if (len < (*(cp + 1) + 2)) { - hysdn_addlog(card, "token 0x%x invalid length %d", *cp, *(cp + 1)); - return (1); - } - switch (*cp) { - case SYSR_TOK_B_CHAN: /* 1 */ - if (*(cp + 1) != 1) - return (1); /* length invalid */ - card->bchans = *(cp + 2); - break; - - case SYSR_TOK_FAX_CHAN: /* 2 */ - if (*(cp + 1) != 1) - return (1); /* length invalid */ - card->faxchans = *(cp + 2); - break; - - case SYSR_TOK_MAC_ADDR: /* 3 */ - if (*(cp + 1) != 6) - return (1); /* length invalid */ - memcpy(card->mac_addr, cp + 2, 6); - break; - - default: - hysdn_addlog(card, "unknown token 0x%02x length %d", *cp, *(cp + 1)); - break; - } - len -= (*(cp + 1) + 2); /* adjust len */ - cp += (*(cp + 1) + 2); /* and pointer */ - } - - hysdn_addlog(card, "no end token found"); - return (1); -} /* EvalSysrTokData */ diff --git a/drivers/staging/isdn/hysdn/hysdn_defs.h b/drivers/staging/isdn/hysdn/hysdn_defs.h deleted file mode 100644 index cdac46a21692..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_defs.h +++ /dev/null @@ -1,282 +0,0 @@ -/* $Id: hysdn_defs.h,v 1.5.6.3 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards - * global definitions and exported vars and functions. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef HYSDN_DEFS_H -#define HYSDN_DEFS_H - -#include -#include -#include -#include - -#include "ince1pc.h" - -#ifdef CONFIG_HYSDN_CAPI -#include -#include -#include -#include - -/***************************/ -/* CAPI-Profile values. */ -/***************************/ - -#define GLOBAL_OPTION_INTERNAL_CONTROLLER 0x0001 -#define GLOBAL_OPTION_EXTERNAL_CONTROLLER 0x0002 -#define GLOBAL_OPTION_HANDSET 0x0004 -#define GLOBAL_OPTION_DTMF 0x0008 -#define GLOBAL_OPTION_SUPPL_SERVICES 0x0010 -#define GLOBAL_OPTION_CHANNEL_ALLOCATION 0x0020 -#define GLOBAL_OPTION_B_CHANNEL_OPERATION 0x0040 - -#define B1_PROT_64KBIT_HDLC 0x0001 -#define B1_PROT_64KBIT_TRANSPARENT 0x0002 -#define B1_PROT_V110_ASYNCH 0x0004 -#define B1_PROT_V110_SYNCH 0x0008 -#define B1_PROT_T30 0x0010 -#define B1_PROT_64KBIT_INV_HDLC 0x0020 -#define B1_PROT_56KBIT_TRANSPARENT 0x0040 - -#define B2_PROT_ISO7776 0x0001 -#define B2_PROT_TRANSPARENT 0x0002 -#define B2_PROT_SDLC 0x0004 -#define B2_PROT_LAPD 0x0008 -#define B2_PROT_T30 0x0010 -#define B2_PROT_PPP 0x0020 -#define B2_PROT_TRANSPARENT_IGNORE_B1_FRAMING_ERRORS 0x0040 - -#define B3_PROT_TRANSPARENT 0x0001 -#define B3_PROT_T90NL 0x0002 -#define B3_PROT_ISO8208 0x0004 -#define B3_PROT_X25_DCE 0x0008 -#define B3_PROT_T30 0x0010 -#define B3_PROT_T30EXT 0x0020 - -#define HYSDN_MAXVERSION 8 - -/* Number of sendbuffers in CAPI-queue */ -#define HYSDN_MAX_CAPI_SKB 20 - -#endif /* CONFIG_HYSDN_CAPI*/ - -/************************************************/ -/* constants and bits for debugging/log outputs */ -/************************************************/ -#define LOG_MAX_LINELEN 120 -#define DEB_OUT_SYSLOG 0x80000000 /* output to syslog instead of proc fs */ -#define LOG_MEM_ERR 0x00000001 /* log memory errors like kmalloc failure */ -#define LOG_POF_OPEN 0x00000010 /* log pof open and close activities */ -#define LOG_POF_RECORD 0x00000020 /* log pof record parser */ -#define LOG_POF_WRITE 0x00000040 /* log detailed pof write operation */ -#define LOG_POF_CARD 0x00000080 /* log pof related card functions */ -#define LOG_CNF_LINE 0x00000100 /* all conf lines are put to procfs */ -#define LOG_CNF_DATA 0x00000200 /* non comment conf lines are shown with channel */ -#define LOG_CNF_MISC 0x00000400 /* additional conf line debug outputs */ -#define LOG_SCHED_ASYN 0x00001000 /* debug schedulers async tx routines */ -#define LOG_PROC_OPEN 0x00100000 /* open and close from procfs are logged */ -#define LOG_PROC_ALL 0x00200000 /* all actions from procfs are logged */ -#define LOG_NET_INIT 0x00010000 /* network init and deinit logging */ - -#define DEF_DEB_FLAGS 0x7fff000f /* everything is logged to procfs */ - -/**********************************/ -/* proc filesystem name constants */ -/**********************************/ -#define PROC_SUBDIR_NAME "hysdn" -#define PROC_CONF_BASENAME "cardconf" -#define PROC_LOG_BASENAME "cardlog" - -/***********************************/ -/* PCI 32 bit parms for IO and MEM */ -/***********************************/ -#define PCI_REG_PLX_MEM_BASE 0 -#define PCI_REG_PLX_IO_BASE 1 -#define PCI_REG_MEMORY_BASE 3 - -/**************/ -/* card types */ -/**************/ -#define BD_NONE 0U -#define BD_PERFORMANCE 1U -#define BD_VALUE 2U -#define BD_PCCARD 3U -#define BD_ERGO 4U -#define BD_METRO 5U -#define BD_CHAMP2 6U -#define BD_PLEXUS 7U - -/******************************************************/ -/* defined states for cards shown by reading cardconf */ -/******************************************************/ -#define CARD_STATE_UNUSED 0 /* never been used or booted */ -#define CARD_STATE_BOOTING 1 /* booting is in progress */ -#define CARD_STATE_BOOTERR 2 /* a previous boot was aborted */ -#define CARD_STATE_RUN 3 /* card is active */ - -/*******************************/ -/* defines for error_log_state */ -/*******************************/ -#define ERRLOG_STATE_OFF 0 /* error log is switched off, nothing to do */ -#define ERRLOG_STATE_ON 1 /* error log is switched on, wait for data */ -#define ERRLOG_STATE_START 2 /* start error logging */ -#define ERRLOG_STATE_STOP 3 /* stop error logging */ - -/*******************************/ -/* data structure for one card */ -/*******************************/ -typedef struct HYSDN_CARD { - - /* general variables for the cards */ - int myid; /* own driver card id */ - unsigned char bus; /* pci bus the card is connected to */ - unsigned char devfn; /* slot+function bit encoded */ - unsigned short subsysid;/* PCI subsystem id */ - unsigned char brdtype; /* type of card */ - unsigned int bchans; /* number of available B-channels */ - unsigned int faxchans; /* number of available fax-channels */ - unsigned char mac_addr[6];/* MAC Address read from card */ - unsigned int irq; /* interrupt number */ - unsigned int iobase; /* IO-port base address */ - unsigned long plxbase; /* PLX memory base */ - unsigned long membase; /* DPRAM memory base */ - unsigned long memend; /* DPRAM memory end */ - void *dpram; /* mapped dpram */ - int state; /* actual state of card -> CARD_STATE_** */ - struct HYSDN_CARD *next; /* pointer to next card */ - - /* data areas for the /proc file system */ - void *proclog; /* pointer to proclog filesystem specific data */ - void *procconf; /* pointer to procconf filesystem specific data */ - - /* debugging and logging */ - unsigned char err_log_state;/* actual error log state of the card */ - unsigned long debug_flags;/* tells what should be debugged and where */ - void (*set_errlog_state) (struct HYSDN_CARD *, int); - - /* interrupt handler + interrupt synchronisation */ - struct work_struct irq_queue; /* interrupt task queue */ - unsigned char volatile irq_enabled;/* interrupt enabled if != 0 */ - unsigned char volatile hw_lock;/* hardware is currently locked -> no access */ - - /* boot process */ - void *boot; /* pointer to boot private data */ - int (*writebootimg) (struct HYSDN_CARD *, unsigned char *, unsigned long); - int (*writebootseq) (struct HYSDN_CARD *, unsigned char *, int); - int (*waitpofready) (struct HYSDN_CARD *); - int (*testram) (struct HYSDN_CARD *); - - /* scheduler for data transfer (only async parts) */ - unsigned char async_data[256];/* async data to be sent (normally for config) */ - unsigned short volatile async_len;/* length of data to sent */ - unsigned short volatile async_channel;/* channel number for async transfer */ - int volatile async_busy; /* flag != 0 sending in progress */ - int volatile net_tx_busy; /* a network packet tx is in progress */ - - /* network interface */ - void *netif; /* pointer to network structure */ - - /* init and deinit stopcard for booting, too */ - void (*stopcard) (struct HYSDN_CARD *); - void (*releasehardware) (struct HYSDN_CARD *); - - spinlock_t hysdn_lock; -#ifdef CONFIG_HYSDN_CAPI - struct hycapictrl_info { - char cardname[32]; - spinlock_t lock; - int versionlen; - char versionbuf[1024]; - char *version[HYSDN_MAXVERSION]; - - char infobuf[128]; /* for function procinfo */ - - struct HYSDN_CARD *card; - struct capi_ctr capi_ctrl; - struct sk_buff *skbs[HYSDN_MAX_CAPI_SKB]; - int in_idx, out_idx; /* indexes to buffer ring */ - int sk_count; /* number of buffers currently in ring */ - struct sk_buff *tx_skb; /* buffer for tx operation */ - - struct list_head ncci_head; - } *hyctrlinfo; -#endif /* CONFIG_HYSDN_CAPI */ -} hysdn_card; - -#ifdef CONFIG_HYSDN_CAPI -typedef struct hycapictrl_info hycapictrl_info; -#endif /* CONFIG_HYSDN_CAPI */ - - -/*****************/ -/* exported vars */ -/*****************/ -extern hysdn_card *card_root; /* pointer to first card */ - - - -/*************************/ -/* im/exported functions */ -/*************************/ - -/* hysdn_procconf.c */ -extern int hysdn_procconf_init(void); /* init proc config filesys */ -extern void hysdn_procconf_release(void); /* deinit proc config filesys */ - -/* hysdn_proclog.c */ -extern int hysdn_proclog_init(hysdn_card *); /* init proc log entry */ -extern void hysdn_proclog_release(hysdn_card *); /* deinit proc log entry */ -extern void hysdn_addlog(hysdn_card *, char *, ...); /* output data to log */ -extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int); /* output card log */ - -/* boardergo.c */ -extern int ergo_inithardware(hysdn_card *card); /* get hardware -> module init */ - -/* hysdn_boot.c */ -extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */ -extern int pof_write_open(hysdn_card *, unsigned char **); /* open proc file for writing pof */ -extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */ -extern int EvalSysrTokData(hysdn_card *, unsigned char *, int); /* Check Sysready Token Data */ - -/* hysdn_sched.c */ -extern int hysdn_sched_tx(hysdn_card *, unsigned char *, - unsigned short volatile *, unsigned short volatile *, - unsigned short); -extern int hysdn_sched_rx(hysdn_card *, unsigned char *, unsigned short, - unsigned short); -extern int hysdn_tx_cfgline(hysdn_card *, unsigned char *, - unsigned short); /* send one cfg line */ - -/* hysdn_net.c */ -extern unsigned int hynet_enable; -extern int hysdn_net_create(hysdn_card *); /* create a new net device */ -extern int hysdn_net_release(hysdn_card *); /* delete the device */ -extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */ -extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */ -extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */ -extern void hysdn_rx_netpkt(hysdn_card *, unsigned char *, - unsigned short); /* rxed packet from network */ - -#ifdef CONFIG_HYSDN_CAPI -extern unsigned int hycapi_enable; -extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */ -extern int hycapi_capi_release(hysdn_card *); /* delete the device */ -extern int hycapi_capi_stop(hysdn_card *card); /* suspend */ -extern void hycapi_rx_capipkt(hysdn_card *card, unsigned char *buf, - unsigned short len); -extern void hycapi_tx_capiack(hysdn_card *card); -extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card); -extern int hycapi_init(void); -extern void hycapi_cleanup(void); -#endif /* CONFIG_HYSDN_CAPI */ - -#endif /* HYSDN_DEFS_H */ diff --git a/drivers/staging/isdn/hysdn/hysdn_init.c b/drivers/staging/isdn/hysdn/hysdn_init.c deleted file mode 100644 index 0db2f7506250..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_init.c +++ /dev/null @@ -1,213 +0,0 @@ -/* $Id: hysdn_init.c,v 1.6.6.6 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, init functions. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static struct pci_device_id hysdn_pci_tbl[] = { - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO, 0, 0, BD_METRO }, - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, 0, 0, BD_CHAMP2 }, - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, 0, 0, BD_ERGO }, - { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, - PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, 0, 0, BD_ERGO }, - - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl); -MODULE_DESCRIPTION("ISDN4Linux: Driver for HYSDN cards"); -MODULE_AUTHOR("Werner Cornelius"); -MODULE_LICENSE("GPL"); - -static int cardmax; /* number of found cards */ -hysdn_card *card_root = NULL; /* pointer to first card */ -static hysdn_card *card_last = NULL; /* pointer to first card */ - - -/****************************************************************************/ -/* The module startup and shutdown code. Only compiled when used as module. */ -/* Using the driver as module is always advisable, because the booting */ -/* image becomes smaller and the driver code is only loaded when needed. */ -/* Additionally newer versions may be activated without rebooting. */ -/****************************************************************************/ - -/****************************************************************************/ -/* init_module is called once when the module is loaded to do all necessary */ -/* things like autodetect... */ -/* If the return value of this function is 0 the init has been successful */ -/* and the module is added to the list in /proc/modules, otherwise an error */ -/* is assumed and the module will not be kept in memory. */ -/****************************************************************************/ - -static int hysdn_pci_init_one(struct pci_dev *akt_pcidev, - const struct pci_device_id *ent) -{ - hysdn_card *card; - int rc; - - rc = pci_enable_device(akt_pcidev); - if (rc) - return rc; - - if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) { - printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); - rc = -ENOMEM; - goto err_out; - } - card->myid = cardmax; /* set own id */ - card->bus = akt_pcidev->bus->number; - card->devfn = akt_pcidev->devfn; /* slot + function */ - card->subsysid = akt_pcidev->subsystem_device; - card->irq = akt_pcidev->irq; - card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE); - card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE); - card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE); - card->brdtype = BD_NONE; /* unknown */ - card->debug_flags = DEF_DEB_FLAGS; /* set default debug */ - card->faxchans = 0; /* default no fax channels */ - card->bchans = 2; /* and 2 b-channels */ - card->brdtype = ent->driver_data; - - if (ergo_inithardware(card)) { - printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase); - rc = -EBUSY; - goto err_out_card; - } - - cardmax++; - card->next = NULL; /*end of chain */ - if (card_last) - card_last->next = card; /* pointer to next card */ - else - card_root = card; - card_last = card; /* new chain end */ - - pci_set_drvdata(akt_pcidev, card); - return 0; - -err_out_card: - kfree(card); -err_out: - pci_disable_device(akt_pcidev); - return rc; -} - -static void hysdn_pci_remove_one(struct pci_dev *akt_pcidev) -{ - hysdn_card *card = pci_get_drvdata(akt_pcidev); - - pci_set_drvdata(akt_pcidev, NULL); - - if (card->stopcard) - card->stopcard(card); - -#ifdef CONFIG_HYSDN_CAPI - hycapi_capi_release(card); -#endif - - if (card->releasehardware) - card->releasehardware(card); /* free all hardware resources */ - - if (card == card_root) { - card_root = card_root->next; - if (!card_root) - card_last = NULL; - } else { - hysdn_card *tmp = card_root; - while (tmp) { - if (tmp->next == card) - tmp->next = card->next; - card_last = tmp; - tmp = tmp->next; - } - } - - kfree(card); - pci_disable_device(akt_pcidev); -} - -static struct pci_driver hysdn_pci_driver = { - .name = "hysdn", - .id_table = hysdn_pci_tbl, - .probe = hysdn_pci_init_one, - .remove = hysdn_pci_remove_one, -}; - -static int hysdn_have_procfs; - -static int __init -hysdn_init(void) -{ - int rc; - - printk(KERN_NOTICE "HYSDN: module loaded\n"); - - rc = pci_register_driver(&hysdn_pci_driver); - if (rc) - return rc; - - printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax); - - if (!hysdn_procconf_init()) - hysdn_have_procfs = 1; - -#ifdef CONFIG_HYSDN_CAPI - if (cardmax > 0) { - if (hycapi_init()) { - printk(KERN_ERR "HYCAPI: init failed\n"); - - if (hysdn_have_procfs) - hysdn_procconf_release(); - - pci_unregister_driver(&hysdn_pci_driver); - return -ESPIPE; - } - } -#endif /* CONFIG_HYSDN_CAPI */ - - return 0; /* no error */ -} /* init_module */ - - -/***********************************************************************/ -/* cleanup_module is called when the module is released by the kernel. */ -/* The routine is only called if init_module has been successful and */ -/* the module counter has a value of 0. Otherwise this function will */ -/* not be called. This function must release all resources still allo- */ -/* cated as after the return from this function the module code will */ -/* be removed from memory. */ -/***********************************************************************/ -static void __exit -hysdn_exit(void) -{ - if (hysdn_have_procfs) - hysdn_procconf_release(); - - pci_unregister_driver(&hysdn_pci_driver); - -#ifdef CONFIG_HYSDN_CAPI - hycapi_cleanup(); -#endif /* CONFIG_HYSDN_CAPI */ - - printk(KERN_NOTICE "HYSDN: module unloaded\n"); -} /* cleanup_module */ - -module_init(hysdn_init); -module_exit(hysdn_exit); diff --git a/drivers/staging/isdn/hysdn/hysdn_net.c b/drivers/staging/isdn/hysdn/hysdn_net.c deleted file mode 100644 index dcb9ef7a2651..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_net.c +++ /dev/null @@ -1,330 +0,0 @@ -/* $Id: hysdn_net.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, net (ethernet type) handling routines. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * This net module has been inspired by the skeleton driver from - * Donald Becker (becker@CESDIS.gsfc.nasa.gov) - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -unsigned int hynet_enable = 0xffffffff; -module_param(hynet_enable, uint, 0); - -#define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */ - -/****************************************************************************/ -/* structure containing the complete network data. The structure is aligned */ -/* in a way that both, the device and statistics are kept inside it. */ -/* for proper access, the device structure MUST be the first var/struct */ -/* inside the definition. */ -/****************************************************************************/ -struct net_local { - /* Tx control lock. This protects the transmit buffer ring - * state along with the "tx full" state of the driver. This - * means all netif_queue flow control actions are protected - * by this lock as well. - */ - struct net_device *dev; - spinlock_t lock; - struct sk_buff *skbs[MAX_SKB_BUFFERS]; /* pointers to tx-skbs */ - int in_idx, out_idx; /* indexes to buffer ring */ - int sk_count; /* number of buffers currently in ring */ -}; /* net_local */ - - - -/*********************************************************************/ -/* Open/initialize the board. This is called (in the current kernel) */ -/* sometime after booting when the 'ifconfig' program is run. */ -/* This routine should set everything up anew at each open, even */ -/* registers that "should" only need to be set once at boot, so that */ -/* there is non-reboot way to recover if something goes wrong. */ -/*********************************************************************/ -static int -net_open(struct net_device *dev) -{ - struct in_device *in_dev; - hysdn_card *card = dev->ml_priv; - int i; - - netif_start_queue(dev); /* start tx-queueing */ - - /* Fill in the MAC-level header (if not already set) */ - if (!card->mac_addr[0]) { - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = 0xfc; - if ((in_dev = dev->ip_ptr) != NULL) { - const struct in_ifaddr *ifa; - - rcu_read_lock(); - ifa = rcu_dereference(in_dev->ifa_list); - if (ifa != NULL) - memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ifa->ifa_local)), &ifa->ifa_local, sizeof(ifa->ifa_local)); - rcu_read_unlock(); - } - } else - memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); - - return (0); -} /* net_open */ - -/*******************************************/ -/* flush the currently occupied tx-buffers */ -/* must only be called when device closed */ -/*******************************************/ -static void -flush_tx_buffers(struct net_local *nl) -{ - - while (nl->sk_count) { - dev_kfree_skb(nl->skbs[nl->out_idx++]); /* free skb */ - if (nl->out_idx >= MAX_SKB_BUFFERS) - nl->out_idx = 0; /* wrap around */ - nl->sk_count--; - } -} /* flush_tx_buffers */ - - -/*********************************************************************/ -/* close/decativate the device. The device is not removed, but only */ -/* deactivated. */ -/*********************************************************************/ -static int -net_close(struct net_device *dev) -{ - - netif_stop_queue(dev); /* disable queueing */ - - flush_tx_buffers((struct net_local *) dev); - - return (0); /* success */ -} /* net_close */ - -/************************************/ -/* send a packet on this interface. */ -/* new style for kernel >= 2.3.33 */ -/************************************/ -static netdev_tx_t -net_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct net_local *lp = (struct net_local *) dev; - - spin_lock_irq(&lp->lock); - - lp->skbs[lp->in_idx++] = skb; /* add to buffer list */ - if (lp->in_idx >= MAX_SKB_BUFFERS) - lp->in_idx = 0; /* wrap around */ - lp->sk_count++; /* adjust counter */ - netif_trans_update(dev); - - /* If we just used up the very last entry in the - * TX ring on this device, tell the queueing - * layer to send no more. - */ - if (lp->sk_count >= MAX_SKB_BUFFERS) - netif_stop_queue(dev); - - /* When the TX completion hw interrupt arrives, this - * is when the transmit statistics are updated. - */ - - spin_unlock_irq(&lp->lock); - - if (lp->sk_count <= 3) { - schedule_work(&((hysdn_card *) dev->ml_priv)->irq_queue); - } - return NETDEV_TX_OK; /* success */ -} /* net_send_packet */ - - - -/***********************************************************************/ -/* acknowlegde a packet send. The network layer will be informed about */ -/* completion */ -/***********************************************************************/ -void -hysdn_tx_netack(hysdn_card *card) -{ - struct net_local *lp = card->netif; - - if (!lp) - return; /* non existing device */ - - - if (!lp->sk_count) - return; /* error condition */ - - lp->dev->stats.tx_packets++; - lp->dev->stats.tx_bytes += lp->skbs[lp->out_idx]->len; - - dev_kfree_skb(lp->skbs[lp->out_idx++]); /* free skb */ - if (lp->out_idx >= MAX_SKB_BUFFERS) - lp->out_idx = 0; /* wrap around */ - - if (lp->sk_count-- == MAX_SKB_BUFFERS) /* dec usage count */ - netif_start_queue((struct net_device *) lp); -} /* hysdn_tx_netack */ - -/*****************************************************/ -/* we got a packet from the network, go and queue it */ -/*****************************************************/ -void -hysdn_rx_netpkt(hysdn_card *card, unsigned char *buf, unsigned short len) -{ - struct net_local *lp = card->netif; - struct net_device *dev; - struct sk_buff *skb; - - if (!lp) - return; /* non existing device */ - - dev = lp->dev; - dev->stats.rx_bytes += len; - - skb = dev_alloc_skb(len); - if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - return; - } - /* copy the data */ - skb_put_data(skb, buf, len); - - /* determine the used protocol */ - skb->protocol = eth_type_trans(skb, dev); - - dev->stats.rx_packets++; /* adjust packet count */ - - netif_rx(skb); -} /* hysdn_rx_netpkt */ - -/*****************************************************/ -/* return the pointer to a network packet to be send */ -/*****************************************************/ -struct sk_buff * -hysdn_tx_netget(hysdn_card *card) -{ - struct net_local *lp = card->netif; - - if (!lp) - return (NULL); /* non existing device */ - - if (!lp->sk_count) - return (NULL); /* nothing available */ - - return (lp->skbs[lp->out_idx]); /* next packet to send */ -} /* hysdn_tx_netget */ - -static const struct net_device_ops hysdn_netdev_ops = { - .ndo_open = net_open, - .ndo_stop = net_close, - .ndo_start_xmit = net_send_packet, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - - -/*****************************************************************************/ -/* hysdn_net_create creates a new net device for the given card. If a device */ -/* already exists, it will be deleted and created a new one. The return value */ -/* 0 announces success, else a negative error code will be returned. */ -/*****************************************************************************/ -int -hysdn_net_create(hysdn_card *card) -{ - struct net_device *dev; - int i; - struct net_local *lp; - - if (!card) { - printk(KERN_WARNING "No card-pt in hysdn_net_create!\n"); - return (-ENOMEM); - } - hysdn_net_release(card); /* release an existing net device */ - - dev = alloc_etherdev(sizeof(struct net_local)); - if (!dev) { - printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); - return (-ENOMEM); - } - - lp = netdev_priv(dev); - lp->dev = dev; - - dev->netdev_ops = &hysdn_netdev_ops; - spin_lock_init(&((struct net_local *) dev)->lock); - - /* initialise necessary or informing fields */ - dev->base_addr = card->iobase; /* IO address */ - dev->irq = card->irq; /* irq */ - - dev->netdev_ops = &hysdn_netdev_ops; - if ((i = register_netdev(dev))) { - printk(KERN_WARNING "HYSDN: unable to create network device\n"); - free_netdev(dev); - return (i); - } - dev->ml_priv = card; /* remember pointer to own data structure */ - card->netif = dev; /* setup the local pointer */ - - if (card->debug_flags & LOG_NET_INIT) - hysdn_addlog(card, "network device created"); - return 0; /* and return success */ -} /* hysdn_net_create */ - -/***************************************************************************/ -/* hysdn_net_release deletes the net device for the given card. The return */ -/* value 0 announces success, else a negative error code will be returned. */ -/***************************************************************************/ -int -hysdn_net_release(hysdn_card *card) -{ - struct net_device *dev = card->netif; - - if (!dev) - return (0); /* non existing */ - - card->netif = NULL; /* clear out pointer */ - net_close(dev); - - flush_tx_buffers((struct net_local *) dev); /* empty buffers */ - - unregister_netdev(dev); /* release the device */ - free_netdev(dev); /* release the memory allocated */ - if (card->debug_flags & LOG_NET_INIT) - hysdn_addlog(card, "network device deleted"); - - return (0); /* always successful */ -} /* hysdn_net_release */ - -/*****************************************************************************/ -/* hysdn_net_getname returns a pointer to the name of the network interface. */ -/* if the interface is not existing, a "-" is returned. */ -/*****************************************************************************/ -char * -hysdn_net_getname(hysdn_card *card) -{ - struct net_device *dev = card->netif; - - if (!dev) - return ("-"); /* non existing */ - - return (dev->name); -} /* hysdn_net_getname */ diff --git a/drivers/staging/isdn/hysdn/hysdn_pof.h b/drivers/staging/isdn/hysdn/hysdn_pof.h deleted file mode 100644 index f63f5fa59d7e..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_pof.h +++ /dev/null @@ -1,78 +0,0 @@ -/* $Id: hysdn_pof.h,v 1.2.6.1 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, definitions used for handling pof-files. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -/************************/ -/* POF specific defines */ -/************************/ -#define BOOT_BUF_SIZE 0x1000 /* =4096, maybe moved to other h file */ -#define CRYPT_FEEDTERM 0x8142 -#define CRYPT_STARTTERM 0x81a5 -/* max. timeout time in seconds - * from end of booting to POF is ready - */ -#define POF_READY_TIME_OUT_SEC 10 - -/**********************************/ -/* defines for 1.stage boot image */ -/**********************************/ - -/* the POF file record containing the boot loader image - * has 2 pages a 16KB: - * 1. page contains the high 16-bit part of the 32-bit E1 words - * 2. page contains the low 16-bit part of the 32-bit E1 words - * - * In each 16KB page we assume the start of the boot loader code - * in the highest 2KB part (at offset 0x3800); - * the rest (0x0000..0x37FF) is assumed to contain 0 bytes. - */ - -#define POF_BOOT_LOADER_PAGE_SIZE 0x4000 /* =16384U */ -#define POF_BOOT_LOADER_TOTAL_SIZE (2U * POF_BOOT_LOADER_PAGE_SIZE) - -#define POF_BOOT_LOADER_CODE_SIZE 0x0800 /* =2KB =2048U */ - -/* offset in boot page, where loader code may start */ -/* =0x3800= 14336U */ -#define POF_BOOT_LOADER_OFF_IN_PAGE (POF_BOOT_LOADER_PAGE_SIZE-POF_BOOT_LOADER_CODE_SIZE) - - -/*--------------------------------------POF file record structs------------*/ -typedef struct PofFileHdr_tag { /* Pof file header */ - /*00 */ unsigned long Magic __attribute__((packed)); - /*04 */ unsigned long N_PofRecs __attribute__((packed)); -/*08 */ -} tPofFileHdr; - -typedef struct PofRecHdr_tag { /* Pof record header */ - /*00 */ unsigned short PofRecId __attribute__((packed)); - /*02 */ unsigned long PofRecDataLen __attribute__((packed)); -/*06 */ -} tPofRecHdr; - -typedef struct PofTimeStamp_tag { - /*00 */ unsigned long UnixTime __attribute__((packed)); - /*04 */ unsigned char DateTimeText[0x28]; - /* =40 */ -/*2C */ -} tPofTimeStamp; - -/* tPofFileHdr.Magic value: */ -#define TAGFILEMAGIC 0x464F501AUL -/* tPofRecHdr.PofRecId values: */ -#define TAG_ABSDATA 0x1000 /* abs. data */ -#define TAG_BOOTDTA 0x1001 /* boot data */ -#define TAG_COMMENT 0x0020 -#define TAG_SYSCALL 0x0021 -#define TAG_FLOWCTRL 0x0022 -#define TAG_TIMESTMP 0x0010 /* date/time stamp of version */ -#define TAG_CABSDATA 0x1100 /* crypted abs. data */ -#define TAG_CBOOTDTA 0x1101 /* crypted boot data */ diff --git a/drivers/staging/isdn/hysdn/hysdn_procconf.c b/drivers/staging/isdn/hysdn/hysdn_procconf.c deleted file mode 100644 index 48afd9f5316e..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_procconf.c +++ /dev/null @@ -1,411 +0,0 @@ -/* $Id: hysdn_procconf.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. - * - * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH - * - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static DEFINE_MUTEX(hysdn_conf_mutex); - -#define INFO_OUT_LEN 80 /* length of info line including lf */ - -/********************************************************/ -/* defines and data structure for conf write operations */ -/********************************************************/ -#define CONF_STATE_DETECT 0 /* waiting for detect */ -#define CONF_STATE_CONF 1 /* writing config data */ -#define CONF_STATE_POF 2 /* writing pof data */ -#define CONF_LINE_LEN 255 /* 255 chars max */ - -struct conf_writedata { - hysdn_card *card; /* card the device is connected to */ - int buf_size; /* actual number of bytes in the buffer */ - int needed_size; /* needed size when reading pof */ - int state; /* actual interface states from above constants */ - unsigned char conf_line[CONF_LINE_LEN]; /* buffered conf line */ - unsigned short channel; /* active channel number */ - unsigned char *pof_buffer; /* buffer when writing pof */ -}; - -/***********************************************************************/ -/* process_line parses one config line and transfers it to the card if */ -/* necessary. */ -/* if the return value is negative an error occurred. */ -/***********************************************************************/ -static int -process_line(struct conf_writedata *cnf) -{ - unsigned char *cp = cnf->conf_line; - int i; - - if (cnf->card->debug_flags & LOG_CNF_LINE) - hysdn_addlog(cnf->card, "conf line: %s", cp); - - if (*cp == '-') { /* option */ - cp++; /* point to option char */ - - if (*cp++ != 'c') - return (0); /* option unknown or used */ - i = 0; /* start value for channel */ - while ((*cp <= '9') && (*cp >= '0')) - i = i * 10 + *cp++ - '0'; /* get decimal number */ - if (i > 65535) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "conf channel invalid %d", i); - return (-ERR_INV_CHAN); /* invalid channel */ - } - cnf->channel = i & 0xFFFF; /* set new channel number */ - return (0); /* success */ - } /* option */ - if (*cp == '*') { /* line to send */ - if (cnf->card->debug_flags & LOG_CNF_DATA) - hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp); - return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1, - cnf->channel)); /* send the line without * */ - } /* line to send */ - return (0); -} /* process_line */ - -/***********************************/ -/* conf file operations and tables */ -/***********************************/ - -/****************************************************/ -/* write conf file -> boot or send cfg line to card */ -/****************************************************/ -static ssize_t -hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t *off) -{ - struct conf_writedata *cnf; - int i; - unsigned char ch, *cp; - - if (!count) - return (0); /* nothing to handle */ - - if (!(cnf = file->private_data)) - return (-EFAULT); /* should never happen */ - - if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */ - if (copy_from_user(&ch, buf, 1)) /* get first char for detect */ - return (-EFAULT); - - if (ch == 0x1A) { - /* we detected a pof file */ - if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0) - return (cnf->needed_size); /* an error occurred -> exit */ - cnf->buf_size = 0; /* buffer is empty */ - cnf->state = CONF_STATE_POF; /* new state */ - } else { - /* conf data has been detected */ - cnf->buf_size = 0; /* buffer is empty */ - cnf->state = CONF_STATE_CONF; /* requested conf data write */ - if (cnf->card->state != CARD_STATE_RUN) - return (-ERR_NOT_BOOTED); - cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */ - cnf->channel = 4098; /* default channel for output */ - } - } /* state was auto detect */ - if (cnf->state == CONF_STATE_POF) { /* pof write active */ - i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */ - if (i <= 0) - return (-EINVAL); /* size error handling pof */ - - if (i < count) - count = i; /* limit requested number of bytes */ - if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count)) - return (-EFAULT); /* error while copying */ - cnf->buf_size += count; - - if (cnf->needed_size == cnf->buf_size) { - cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */ - if (cnf->needed_size <= 0) { - cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */ - return (cnf->needed_size); /* an error occurred */ - } - cnf->buf_size = 0; /* buffer is empty again */ - } - } - /* pof write active */ - else { /* conf write active */ - - if (cnf->card->state != CARD_STATE_RUN) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf write denied -> not booted"); - return (-ERR_NOT_BOOTED); - } - i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */ - if (i > 0) { - /* copy remaining bytes into buffer */ - - if (count > i) - count = i; /* limit transfer */ - if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count)) - return (-EFAULT); /* error while copying */ - - i = count; /* number of chars in buffer */ - cp = cnf->conf_line + cnf->buf_size; - while (i) { - /* search for end of line */ - if ((*cp < ' ') && (*cp != 9)) - break; /* end of line found */ - cp++; - i--; - } /* search for end of line */ - - if (i) { - /* delimiter found */ - *cp++ = 0; /* string termination */ - count -= (i - 1); /* subtract remaining bytes from count */ - while ((i) && (*cp < ' ') && (*cp != 9)) { - i--; /* discard next char */ - count++; /* mark as read */ - cp++; /* next char */ - } - cnf->buf_size = 0; /* buffer is empty after transfer */ - if ((i = process_line(cnf)) < 0) /* handle the line */ - count = i; /* return the error */ - } - /* delimiter found */ - else { - cnf->buf_size += count; /* add chars to string */ - if (cnf->buf_size >= CONF_LINE_LEN - 1) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count); - return (-ERR_CONF_LONG); - } - } /* not delimited */ - - } - /* copy remaining bytes into buffer */ - else { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf line too long"); - return (-ERR_CONF_LONG); - } - } /* conf write active */ - - return (count); -} /* hysdn_conf_write */ - -/*******************************************/ -/* read conf file -> output card info data */ -/*******************************************/ -static ssize_t -hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t *off) -{ - char *cp; - - if (!(file->f_mode & FMODE_READ)) - return -EPERM; /* no permission to read */ - - if (!(cp = file->private_data)) - return -EFAULT; /* should never happen */ - - return simple_read_from_buffer(buf, count, off, cp, strlen(cp)); -} /* hysdn_conf_read */ - -/******************/ -/* open conf file */ -/******************/ -static int -hysdn_conf_open(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct conf_writedata *cnf; - char *cp, *tmp; - - /* now search the addressed card */ - mutex_lock(&hysdn_conf_mutex); - card = PDE_DATA(ino); - if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) - hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x", - filep->f_cred->fsuid, filep->f_cred->fsgid, - filep->f_mode); - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write boot file or conf line */ - - if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { - mutex_unlock(&hysdn_conf_mutex); - return (-EFAULT); - } - cnf->card = card; - cnf->buf_size = 0; /* nothing buffered */ - cnf->state = CONF_STATE_DETECT; /* start auto detect */ - filep->private_data = cnf; - - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - /* read access -> output card info data */ - - if (!(tmp = kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { - mutex_unlock(&hysdn_conf_mutex); - return (-EFAULT); /* out of memory */ - } - filep->private_data = tmp; /* start of string */ - - /* first output a headline */ - sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device"); - cp = tmp; /* start of string */ - while (*cp) - cp++; - while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) - *cp++ = ' '; - *cp++ = '\n'; - - /* and now the data */ - sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d %s", - card->myid, - card->bus, - PCI_SLOT(card->devfn), - card->brdtype, - card->irq, - card->iobase, - card->membase, - card->bchans, - card->faxchans, - card->state, - hysdn_net_getname(card)); - while (*cp) - cp++; - while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) - *cp++ = ' '; - *cp++ = '\n'; - *cp = 0; /* end of string */ - } else { /* simultaneous read/write access forbidden ! */ - mutex_unlock(&hysdn_conf_mutex); - return (-EPERM); /* no permission this time */ - } - mutex_unlock(&hysdn_conf_mutex); - return nonseekable_open(ino, filep); -} /* hysdn_conf_open */ - -/***************************/ -/* close a config file. */ -/***************************/ -static int -hysdn_conf_close(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct conf_writedata *cnf; - int retval = 0; - - mutex_lock(&hysdn_conf_mutex); - card = PDE_DATA(ino); - if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) - hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x", - filep->f_cred->fsuid, filep->f_cred->fsgid, - filep->f_mode); - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write boot file or conf line */ - if (filep->private_data) { - cnf = filep->private_data; - - if (cnf->state == CONF_STATE_POF) - retval = pof_write_close(cnf->card); /* close the pof write */ - kfree(filep->private_data); /* free allocated memory for buffer */ - - } /* handle write private data */ - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - /* read access -> output card info data */ - - kfree(filep->private_data); /* release memory */ - } - mutex_unlock(&hysdn_conf_mutex); - return (retval); -} /* hysdn_conf_close */ - -/******************************************************/ -/* table for conf filesystem functions defined above. */ -/******************************************************/ -static const struct file_operations conf_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = hysdn_conf_read, - .write = hysdn_conf_write, - .open = hysdn_conf_open, - .release = hysdn_conf_close, -}; - -/*****************************/ -/* hysdn subdir in /proc/net */ -/*****************************/ -struct proc_dir_entry *hysdn_proc_entry = NULL; - -/*******************************************************************************/ -/* hysdn_procconf_init is called when the module is loaded and after the cards */ -/* have been detected. The needed proc dir and card config files are created. */ -/* The log init is called at last. */ -/*******************************************************************************/ -int -hysdn_procconf_init(void) -{ - hysdn_card *card; - unsigned char conf_name[20]; - - hysdn_proc_entry = proc_mkdir(PROC_SUBDIR_NAME, init_net.proc_net); - if (!hysdn_proc_entry) { - printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); - return (-1); - } - card = card_root; /* point to first card */ - while (card) { - - sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); - if ((card->procconf = (void *) proc_create_data(conf_name, - S_IFREG | S_IRUGO | S_IWUSR, - hysdn_proc_entry, - &conf_fops, - card)) != NULL) { - hysdn_proclog_init(card); /* init the log file entry */ - } - card = card->next; /* next entry */ - } - - printk(KERN_NOTICE "HYSDN: procfs initialised\n"); - return 0; -} /* hysdn_procconf_init */ - -/*************************************************************************************/ -/* hysdn_procconf_release is called when the module is unloaded and before the cards */ -/* resources are released. The module counter is assumed to be 0 ! */ -/*************************************************************************************/ -void -hysdn_procconf_release(void) -{ - hysdn_card *card; - unsigned char conf_name[20]; - - card = card_root; /* start with first card */ - while (card) { - - sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); - if (card->procconf) - remove_proc_entry(conf_name, hysdn_proc_entry); - - hysdn_proclog_release(card); /* init the log file entry */ - - card = card->next; /* point to next card */ - } - - remove_proc_entry(PROC_SUBDIR_NAME, init_net.proc_net); -} diff --git a/drivers/staging/isdn/hysdn/hysdn_proclog.c b/drivers/staging/isdn/hysdn/hysdn_proclog.c deleted file mode 100644 index 6e898b90e86e..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_proclog.c +++ /dev/null @@ -1,357 +0,0 @@ -/* $Id: hysdn_proclog.c,v 1.9.6.3 2001/09/23 22:24:54 kai Exp $ - * - * Linux driver for HYSDN cards, /proc/net filesystem log functions. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -/* the proc subdir for the interface is defined in the procconf module */ -extern struct proc_dir_entry *hysdn_proc_entry; - -static DEFINE_MUTEX(hysdn_log_mutex); -static void put_log_buffer(hysdn_card *card, char *cp); - -/*************************************************/ -/* structure keeping ascii log for device output */ -/*************************************************/ -struct log_data { - struct log_data *next; - unsigned long usage_cnt;/* number of files still to work */ - void *proc_ctrl; /* pointer to own control procdata structure */ - char log_start[2]; /* log string start (final len aligned by size) */ -}; - -/**********************************************/ -/* structure holding proc entrys for one card */ -/**********************************************/ -struct procdata { - struct proc_dir_entry *log; /* log entry */ - char log_name[15]; /* log filename */ - struct log_data *log_head, *log_tail; /* head and tail for queue */ - int if_used; /* open count for interface */ - unsigned char logtmp[LOG_MAX_LINELEN]; - wait_queue_head_t rd_queue; -}; - - -/**********************************************/ -/* log function for cards error log interface */ -/**********************************************/ -void -hysdn_card_errlog(hysdn_card *card, tErrLogEntry *logp, int maxsize) -{ - char buf[ERRLOG_TEXT_SIZE + 40]; - - sprintf(buf, "LOG 0x%08lX 0x%08lX : %s\n", logp->ulErrType, logp->ulErrSubtype, logp->ucText); - put_log_buffer(card, buf); /* output the string */ -} /* hysdn_card_errlog */ - -/***************************************************/ -/* Log function using format specifiers for output */ -/***************************************************/ -void -hysdn_addlog(hysdn_card *card, char *fmt, ...) -{ - struct procdata *pd = card->proclog; - char *cp; - va_list args; - - if (!pd) - return; /* log structure non existent */ - - cp = pd->logtmp; - cp += sprintf(cp, "HYSDN: card %d ", card->myid); - - va_start(args, fmt); - cp += vsprintf(cp, fmt, args); - va_end(args); - *cp++ = '\n'; - *cp = 0; - - if (card->debug_flags & DEB_OUT_SYSLOG) - printk(KERN_INFO "%s", pd->logtmp); - else - put_log_buffer(card, pd->logtmp); - -} /* hysdn_addlog */ - -/********************************************/ -/* put an log buffer into the log queue. */ -/* This buffer will be kept until all files */ -/* opened for read got the contents. */ -/* Flushes buffers not longer in use. */ -/********************************************/ -static void -put_log_buffer(hysdn_card *card, char *cp) -{ - struct log_data *ib; - struct procdata *pd = card->proclog; - unsigned long flags; - - if (!pd) - return; - if (!cp) - return; - if (!*cp) - return; - if (pd->if_used <= 0) - return; /* no open file for read */ - - if (!(ib = kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC))) - return; /* no memory */ - strcpy(ib->log_start, cp); /* set output string */ - ib->next = NULL; - ib->proc_ctrl = pd; /* point to own control structure */ - spin_lock_irqsave(&card->hysdn_lock, flags); - ib->usage_cnt = pd->if_used; - if (!pd->log_head) - pd->log_head = ib; /* new head */ - else - pd->log_tail->next = ib; /* follows existing messages */ - pd->log_tail = ib; /* new tail */ - - /* delete old entrys */ - while (pd->log_head->next) { - if ((pd->log_head->usage_cnt <= 0) && - (pd->log_head->next->usage_cnt <= 0)) { - ib = pd->log_head; - pd->log_head = pd->log_head->next; - kfree(ib); - } else { - break; - } - } /* pd->log_head->next */ - - spin_unlock_irqrestore(&card->hysdn_lock, flags); - - wake_up_interruptible(&(pd->rd_queue)); /* announce new entry */ -} /* put_log_buffer */ - - -/******************************/ -/* file operations and tables */ -/******************************/ - -/****************************************/ -/* write log file -> set log level bits */ -/****************************************/ -static ssize_t -hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t *off) -{ - int rc; - hysdn_card *card = file->private_data; - - rc = kstrtoul_from_user(buf, count, 0, &card->debug_flags); - if (rc < 0) - return rc; - hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags); - return (count); -} /* hysdn_log_write */ - -/******************/ -/* read log file */ -/******************/ -static ssize_t -hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t *off) -{ - struct log_data *inf; - int len; - hysdn_card *card = PDE_DATA(file_inode(file)); - - if (!(inf = *((struct log_data **) file->private_data))) { - struct procdata *pd = card->proclog; - if (file->f_flags & O_NONBLOCK) - return (-EAGAIN); - - wait_event_interruptible(pd->rd_queue, (inf = - *((struct log_data **) file->private_data))); - } - if (!inf) - return (0); - - inf->usage_cnt--; /* new usage count */ - file->private_data = &inf->next; /* next structure */ - if ((len = strlen(inf->log_start)) <= count) { - if (copy_to_user(buf, inf->log_start, len)) - return -EFAULT; - *off += len; - return (len); - } - return (0); -} /* hysdn_log_read */ - -/******************/ -/* open log file */ -/******************/ -static int -hysdn_log_open(struct inode *ino, struct file *filep) -{ - hysdn_card *card = PDE_DATA(ino); - - mutex_lock(&hysdn_log_mutex); - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write log level only */ - filep->private_data = card; /* remember our own card */ - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - struct procdata *pd = card->proclog; - unsigned long flags; - - /* read access -> log/debug read */ - spin_lock_irqsave(&card->hysdn_lock, flags); - pd->if_used++; - if (pd->log_head) - filep->private_data = &pd->log_tail->next; - else - filep->private_data = &pd->log_head; - spin_unlock_irqrestore(&card->hysdn_lock, flags); - } else { /* simultaneous read/write access forbidden ! */ - mutex_unlock(&hysdn_log_mutex); - return (-EPERM); /* no permission this time */ - } - mutex_unlock(&hysdn_log_mutex); - return nonseekable_open(ino, filep); -} /* hysdn_log_open */ - -/*******************************************************************************/ -/* close a cardlog file. If the file has been opened for exclusive write it is */ -/* assumed as pof data input and the pof loader is noticed about. */ -/* Otherwise file is handled as log output. In this case the interface usage */ -/* count is decremented and all buffers are noticed of closing. If this file */ -/* was the last one to be closed, all buffers are freed. */ -/*******************************************************************************/ -static int -hysdn_log_close(struct inode *ino, struct file *filep) -{ - struct log_data *inf; - struct procdata *pd; - hysdn_card *card; - int retval = 0; - - mutex_lock(&hysdn_log_mutex); - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write debug level written */ - retval = 0; /* success */ - } else { - /* read access -> log/debug read, mark one further file as closed */ - - inf = *((struct log_data **) filep->private_data); /* get first log entry */ - if (inf) - pd = (struct procdata *) inf->proc_ctrl; /* still entries there */ - else { - /* no info available -> search card */ - card = PDE_DATA(file_inode(filep)); - pd = card->proclog; /* pointer to procfs log */ - } - if (pd) - pd->if_used--; /* decrement interface usage count by one */ - - while (inf) { - inf->usage_cnt--; /* decrement usage count for buffers */ - inf = inf->next; - } - - if (pd) - if (pd->if_used <= 0) /* delete buffers if last file closed */ - while (pd->log_head) { - inf = pd->log_head; - pd->log_head = pd->log_head->next; - kfree(inf); - } - } /* read access */ - mutex_unlock(&hysdn_log_mutex); - - return (retval); -} /* hysdn_log_close */ - -/*************************************************/ -/* select/poll routine to be able using select() */ -/*************************************************/ -static __poll_t -hysdn_log_poll(struct file *file, poll_table *wait) -{ - __poll_t mask = 0; - hysdn_card *card = PDE_DATA(file_inode(file)); - struct procdata *pd = card->proclog; - - if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) - return (mask); /* no polling for write supported */ - - poll_wait(file, &(pd->rd_queue), wait); - - if (*((struct log_data **) file->private_data)) - mask |= EPOLLIN | EPOLLRDNORM; - - return mask; -} /* hysdn_log_poll */ - -/**************************************************/ -/* table for log filesystem functions defined above. */ -/**************************************************/ -static const struct file_operations log_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = hysdn_log_read, - .write = hysdn_log_write, - .poll = hysdn_log_poll, - .open = hysdn_log_open, - .release = hysdn_log_close, -}; - - -/***********************************************************************************/ -/* hysdn_proclog_init is called when the module is loaded after creating the cards */ -/* conf files. */ -/***********************************************************************************/ -int -hysdn_proclog_init(hysdn_card *card) -{ - struct procdata *pd; - - /* create a cardlog proc entry */ - - if ((pd = kzalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) { - sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid); - pd->log = proc_create_data(pd->log_name, - S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry, - &log_fops, card); - - init_waitqueue_head(&(pd->rd_queue)); - - card->proclog = (void *) pd; /* remember procfs structure */ - } - return (0); -} /* hysdn_proclog_init */ - -/************************************************************************************/ -/* hysdn_proclog_release is called when the module is unloaded and before the cards */ -/* conf file is released */ -/* The module counter is assumed to be 0 ! */ -/************************************************************************************/ -void -hysdn_proclog_release(hysdn_card *card) -{ - struct procdata *pd; - - if ((pd = (struct procdata *) card->proclog) != NULL) { - if (pd->log) - remove_proc_entry(pd->log_name, hysdn_proc_entry); - kfree(pd); /* release memory */ - card->proclog = NULL; - } -} /* hysdn_proclog_release */ diff --git a/drivers/staging/isdn/hysdn/hysdn_sched.c b/drivers/staging/isdn/hysdn/hysdn_sched.c deleted file mode 100644 index 31d7c1415543..000000000000 --- a/drivers/staging/isdn/hysdn/hysdn_sched.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: hysdn_sched.c,v 1.5.6.4 2001/11/06 21:58:19 kai Exp $ - * - * Linux driver for HYSDN cards - * scheduler routines for handling exchange card <-> pc. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -/*****************************************************************************/ -/* hysdn_sched_rx is called from the cards handler to announce new data is */ -/* available from the card. The routine has to handle the data and return */ -/* with a nonzero code if the data could be worked (or even thrown away), if */ -/* no room to buffer the data is available a zero return tells the card */ -/* to keep the data until later. */ -/*****************************************************************************/ -int -hysdn_sched_rx(hysdn_card *card, unsigned char *buf, unsigned short len, - unsigned short chan) -{ - - switch (chan) { - case CHAN_NDIS_DATA: - if (hynet_enable & (1 << card->myid)) { - /* give packet to network handler */ - hysdn_rx_netpkt(card, buf, len); - } - break; - - case CHAN_ERRLOG: - hysdn_card_errlog(card, (tErrLogEntry *) buf, len); - if (card->err_log_state == ERRLOG_STATE_ON) - card->err_log_state = ERRLOG_STATE_START; /* start new fetch */ - break; -#ifdef CONFIG_HYSDN_CAPI - case CHAN_CAPI: -/* give packet to CAPI handler */ - if (hycapi_enable & (1 << card->myid)) { - hycapi_rx_capipkt(card, buf, len); - } - break; -#endif /* CONFIG_HYSDN_CAPI */ - default: - printk(KERN_INFO "irq message channel %d len %d unhandled \n", chan, len); - break; - - } /* switch rx channel */ - - return (1); /* always handled */ -} /* hysdn_sched_rx */ - -/*****************************************************************************/ -/* hysdn_sched_tx is called from the cards handler to announce that there is */ -/* room in the tx-buffer to the card and data may be sent if needed. */ -/* If the routine wants to send data it must fill buf, len and chan with the */ -/* appropriate data and return a nonzero value. With a zero return no new */ -/* data to send is assumed. maxlen specifies the buffer size available for */ -/* sending. */ -/*****************************************************************************/ -int -hysdn_sched_tx(hysdn_card *card, unsigned char *buf, - unsigned short volatile *len, unsigned short volatile *chan, - unsigned short maxlen) -{ - struct sk_buff *skb; - - if (card->net_tx_busy) { - card->net_tx_busy = 0; /* reset flag */ - hysdn_tx_netack(card); /* acknowledge packet send */ - } /* a network packet has completely been transferred */ - /* first of all async requests are handled */ - if (card->async_busy) { - if (card->async_len <= maxlen) { - memcpy(buf, card->async_data, card->async_len); - *len = card->async_len; - *chan = card->async_channel; - card->async_busy = 0; /* reset request */ - return (1); - } - card->async_busy = 0; /* in case of length error */ - } /* async request */ - if ((card->err_log_state == ERRLOG_STATE_START) && - (maxlen >= ERRLOG_CMD_REQ_SIZE)) { - strcpy(buf, ERRLOG_CMD_REQ); /* copy the command */ - *len = ERRLOG_CMD_REQ_SIZE; /* buffer length */ - *chan = CHAN_ERRLOG; /* and channel */ - card->err_log_state = ERRLOG_STATE_ON; /* new state is on */ - return (1); /* tell that data should be send */ - } /* error log start and able to send */ - if ((card->err_log_state == ERRLOG_STATE_STOP) && - (maxlen >= ERRLOG_CMD_STOP_SIZE)) { - strcpy(buf, ERRLOG_CMD_STOP); /* copy the command */ - *len = ERRLOG_CMD_STOP_SIZE; /* buffer length */ - *chan = CHAN_ERRLOG; /* and channel */ - card->err_log_state = ERRLOG_STATE_OFF; /* new state is off */ - return (1); /* tell that data should be send */ - } /* error log start and able to send */ - /* now handle network interface packets */ - if ((hynet_enable & (1 << card->myid)) && - (skb = hysdn_tx_netget(card)) != NULL) - { - if (skb->len <= maxlen) { - /* copy the packet to the buffer */ - skb_copy_from_linear_data(skb, buf, skb->len); - *len = skb->len; - *chan = CHAN_NDIS_DATA; - card->net_tx_busy = 1; /* we are busy sending network data */ - return (1); /* go and send the data */ - } else - hysdn_tx_netack(card); /* aknowledge packet -> throw away */ - } /* send a network packet if available */ -#ifdef CONFIG_HYSDN_CAPI - if (((hycapi_enable & (1 << card->myid))) && - ((skb = hycapi_tx_capiget(card)) != NULL)) - { - if (skb->len <= maxlen) { - skb_copy_from_linear_data(skb, buf, skb->len); - *len = skb->len; - *chan = CHAN_CAPI; - hycapi_tx_capiack(card); - return (1); /* go and send the data */ - } - } -#endif /* CONFIG_HYSDN_CAPI */ - return (0); /* nothing to send */ -} /* hysdn_sched_tx */ - - -/*****************************************************************************/ -/* send one config line to the card and return 0 if successful, otherwise a */ -/* negative error code. */ -/* The function works with timeouts perhaps not giving the greatest speed */ -/* sending the line, but this should be meaningless because only some lines */ -/* are to be sent and this happens very seldom. */ -/*****************************************************************************/ -int -hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) -{ - int cnt = 50; /* timeout intervalls */ - unsigned long flags; - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1); - - while (card->async_busy) { - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg delayed"); - - msleep_interruptible(20); /* Timeout 20ms */ - if (!--cnt) - return (-ERR_ASYNC_TIME); /* timed out */ - } /* wait for buffer to become free */ - - spin_lock_irqsave(&card->hysdn_lock, flags); - strcpy(card->async_data, line); - card->async_len = strlen(line) + 1; - card->async_channel = chan; - card->async_busy = 1; /* request transfer */ - - /* now queue the task */ - schedule_work(&card->irq_queue); - spin_unlock_irqrestore(&card->hysdn_lock, flags); - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg data queued"); - - cnt++; /* short delay */ - - while (card->async_busy) { - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg waiting for tx-ready"); - - msleep_interruptible(20); /* Timeout 20ms */ - if (!--cnt) - return (-ERR_ASYNC_TIME); /* timed out */ - } /* wait for buffer to become free again */ - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg data send"); - - return (0); /* line send correctly */ -} /* hysdn_tx_cfgline */ diff --git a/drivers/staging/isdn/hysdn/ince1pc.h b/drivers/staging/isdn/hysdn/ince1pc.h deleted file mode 100644 index cab68361de65..000000000000 --- a/drivers/staging/isdn/hysdn/ince1pc.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Linux driver for HYSDN cards - * common definitions for both sides of the bus: - * - conventions both spoolers must know - * - channel numbers agreed upon - * - * Author M. Steinkopf - * Copyright 1999 by M. Steinkopf - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef __INCE1PC_H__ -#define __INCE1PC_H__ - -/* basic scalar definitions have same meanning, - * but their declaration location depends on environment - */ - -/*--------------------------------------channel numbers---------------------*/ -#define CHAN_SYSTEM 0x0001 /* system channel (spooler to spooler) */ -#define CHAN_ERRLOG 0x0005 /* error logger */ -#define CHAN_CAPI 0x0064 /* CAPI interface */ -#define CHAN_NDIS_DATA 0x1001 /* NDIS data transfer */ - -/*--------------------------------------POF ready msg-----------------------*/ -/* NOTE: after booting POF sends system ready message to PC: */ -#define RDY_MAGIC 0x52535953UL /* 'SYSR' reversed */ -#define RDY_MAGIC_SIZE 4 /* size in bytes */ - -#define MAX_N_TOK_BYTES 255 - -#define MIN_RDY_MSG_SIZE RDY_MAGIC_SIZE -#define MAX_RDY_MSG_SIZE (RDY_MAGIC_SIZE + MAX_N_TOK_BYTES) - -#define SYSR_TOK_END 0 -#define SYSR_TOK_B_CHAN 1 /* nr. of B-Channels; DataLen=1; def: 2 */ -#define SYSR_TOK_FAX_CHAN 2 /* nr. of FAX Channels; DataLen=1; def: 0 */ -#define SYSR_TOK_MAC_ADDR 3 /* MAC-Address; DataLen=6; def: auto */ -#define SYSR_TOK_ESC 255 /* undefined data size yet */ -/* default values, if not corrected by token: */ -#define SYSR_TOK_B_CHAN_DEF 2 /* assume 2 B-Channels */ -#define SYSR_TOK_FAX_CHAN_DEF 1 /* assume 1 FAX Channel */ - -/* syntax of new SYSR token stream: - * channel: CHAN_SYSTEM - * msgsize: MIN_RDY_MSG_SIZE <= x <= MAX_RDY_MSG_SIZE - * RDY_MAGIC_SIZE <= x <= (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES) - * msg : 0 1 2 3 {4 5 6 ..} - * S Y S R MAX_N_TOK_BYTES bytes of TokenStream - * - * TokenStream := empty - * | {NonEndTokenChunk} EndToken RotlCRC - * NonEndTokenChunk:= NonEndTokenId DataLen [Data] - * NonEndTokenId := 0x01 .. 0xFE 1 BYTE - * DataLen := 0x00 .. 0xFF 1 BYTE - * Data := DataLen bytes - * EndToken := 0x00 - * RotlCRC := special 1 byte CRC over all NonEndTokenChunk bytes - * s. RotlCRC algorithm - * - * RotlCRC algorithm: - * ucSum= 0 1 unsigned char - * for all NonEndTokenChunk bytes: - * ROTL(ucSum,1) rotate left by 1 - * ucSum += Char; add current byte with swap around - * RotlCRC= ~ucSum; invert all bits for result - * - * note: - * - for 16-bit FIFO add padding 0 byte to achieve even token data bytes! - */ - -/*--------------------------------------error logger------------------------*/ -/* note: pof needs final 0 ! */ -#define ERRLOG_CMD_REQ "ERRLOG ON" -#define ERRLOG_CMD_REQ_SIZE 10 /* with final 0 byte ! */ -#define ERRLOG_CMD_STOP "ERRLOG OFF" -#define ERRLOG_CMD_STOP_SIZE 11 /* with final 0 byte ! */ - -#define ERRLOG_ENTRY_SIZE 64 /* sizeof(tErrLogEntry) */ - /* remaining text size = 55 */ -#define ERRLOG_TEXT_SIZE (ERRLOG_ENTRY_SIZE - 2 * 4 - 1) - -typedef struct ErrLogEntry_tag { - - /*00 */ unsigned long ulErrType; - - /*04 */ unsigned long ulErrSubtype; - - /*08 */ unsigned char ucTextSize; - - /*09 */ unsigned char ucText[ERRLOG_TEXT_SIZE]; - /* ASCIIZ of len ucTextSize-1 */ - -/*40 */ -} tErrLogEntry; - - -#if defined(__TURBOC__) -#if sizeof(tErrLogEntry) != ERRLOG_ENTRY_SIZE -#error size of tErrLogEntry != ERRLOG_ENTRY_SIZE -#endif /* */ -#endif /* */ - -/*--------------------------------------DPRAM boot spooler------------------*/ -/* this is the struture used between pc and - * hyperstone to exchange boot data - */ -#define DPRAM_SPOOLER_DATA_SIZE 0x20 -typedef struct DpramBootSpooler_tag { - - /*00 */ unsigned char Len; - - /*01 */ volatile unsigned char RdPtr; - - /*02 */ unsigned char WrPtr; - - /*03 */ unsigned char Data[DPRAM_SPOOLER_DATA_SIZE]; - -/*23 */ -} tDpramBootSpooler; - - -#define DPRAM_SPOOLER_MIN_SIZE 5 /* Len+RdPtr+Wrptr+2*data */ -#define DPRAM_SPOOLER_DEF_SIZE 0x23 /* current default size */ - -/*--------------------------------------HYCARD/ERGO DPRAM SoftUart----------*/ -/* at DPRAM offset 0x1C00: */ -#define SIZE_RSV_SOFT_UART 0x1B0 /* 432 bytes reserved for SoftUart */ - - -#endif /* __INCE1PC_H__ */ diff --git a/include/linux/b1pcmcia.h b/include/linux/b1pcmcia.h deleted file mode 100644 index 12a867c6061e..000000000000 --- a/include/linux/b1pcmcia.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id: b1pcmcia.h,v 1.1.8.2 2001/09/23 22:25:05 kai Exp $ - * - * Exported functions of module b1pcmcia to be called by - * avm_cs card services module. - * - * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef _B1PCMCIA_H_ -#define _B1PCMCIA_H_ - -int b1pcmcia_addcard_b1(unsigned int port, unsigned irq); -int b1pcmcia_addcard_m1(unsigned int port, unsigned irq); -int b1pcmcia_addcard_m2(unsigned int port, unsigned irq); -int b1pcmcia_delcard(unsigned int port, unsigned irq); - -#endif /* _B1PCMCIA_H_ */ diff --git a/include/uapi/linux/gigaset_dev.h b/include/uapi/linux/gigaset_dev.h deleted file mode 100644 index 279551af8ebf..000000000000 --- a/include/uapi/linux/gigaset_dev.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -/* - * interface to user space for the gigaset driver - * - * Copyright (c) 2004 by Hansjoerg Lipp - * - * ===================================================================== - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * ===================================================================== - */ - -#ifndef GIGASET_INTERFACE_H -#define GIGASET_INTERFACE_H - -#include - -/* The magic IOCTL value for this interface. */ -#define GIGASET_IOCTL 0x47 - -/* enable/disable device control via character device (lock out ISDN subsys) */ -#define GIGASET_REDIR _IOWR(GIGASET_IOCTL, 0, int) - -/* enable adapter configuration mode (M10x only) */ -#define GIGASET_CONFIG _IOWR(GIGASET_IOCTL, 1, int) - -/* set break characters (M105 only) */ -#define GIGASET_BRKCHARS _IOW(GIGASET_IOCTL, 2, unsigned char[6]) - -/* get version information selected by arg[0] */ -#define GIGASET_VERSION _IOWR(GIGASET_IOCTL, 3, unsigned[4]) -/* values for GIGASET_VERSION arg[0] */ -#define GIGVER_DRIVER 0 /* get driver version */ -#define GIGVER_COMPAT 1 /* get interface compatibility version */ -#define GIGVER_FWBASE 2 /* get base station firmware version */ - -#endif diff --git a/include/uapi/linux/hysdn_if.h b/include/uapi/linux/hysdn_if.h deleted file mode 100644 index 99f77c517e6d..000000000000 --- a/include/uapi/linux/hysdn_if.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* $Id: hysdn_if.h,v 1.1.8.3 2001/09/23 22:25:05 kai Exp $ - * - * Linux driver for HYSDN cards - * ioctl definitions shared by hynetmgr and driver. - * - * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -/****************/ -/* error values */ -/****************/ -#define ERR_NONE 0 /* no error occurred */ -#define ERR_ALREADY_BOOT 1000 /* we are already booting */ -#define EPOF_BAD_MAGIC 1001 /* bad magic in POF header */ -#define ERR_BOARD_DPRAM 1002 /* board DPRAM failed */ -#define EPOF_INTERNAL 1003 /* internal POF handler error */ -#define EPOF_BAD_IMG_SIZE 1004 /* POF boot image size invalid */ -#define ERR_BOOTIMG_FAIL 1005 /* 1. stage boot image did not start */ -#define ERR_BOOTSEQ_FAIL 1006 /* 2. stage boot seq handshake timeout */ -#define ERR_POF_TIMEOUT 1007 /* timeout waiting for card pof ready */ -#define ERR_NOT_BOOTED 1008 /* operation only allowed when booted */ -#define ERR_CONF_LONG 1009 /* conf line is too long */ -#define ERR_INV_CHAN 1010 /* invalid channel number */ -#define ERR_ASYNC_TIME 1011 /* timeout sending async data */ - - - - -- cgit v1.2.3 From f59aba2f75795e5b6a4f1aa31f3e20d7b71ca804 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 10 Dec 2019 21:59:16 +0100 Subject: isdn: capi: dead code removal The staging isdn drivers are gone, and CONFIG_BT_CMTP is now the only user. This means a lot of the code in the subsystem has no remaining callers and can be removed. Change the capi user space front-end to be part of kernelcapi, and the combined module to only be compiled if BT_CMTP is also enabled, then remove the interfaces that have no remaining callers. As the notifier list and the capi_drivers list have no callers outside of kcapi.c, the implementation gets much simpler. Some definitions from the include/linux/*.h headers are only needed internally and are moved to kcapi.h. Acked-by: David Miller Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20191210210455.3475361-2-arnd@arndb.de Signed-off-by: Greg Kroah-Hartman --- Documentation/isdn/interface_capi.rst | 71 ------ drivers/isdn/Makefile | 2 +- drivers/isdn/capi/Kconfig | 32 +-- drivers/isdn/capi/Makefile | 18 +- drivers/isdn/capi/capi.c | 14 +- drivers/isdn/capi/capilib.c | 202 --------------- drivers/isdn/capi/capiutil.c | 231 +---------------- drivers/isdn/capi/kcapi.c | 409 +----------------------------- drivers/isdn/capi/kcapi.h | 149 ++++++++++- drivers/isdn/capi/kcapi_proc.c | 34 +-- include/linux/isdn/capilli.h | 18 -- include/linux/isdn/capiutil.h | 456 ---------------------------------- include/linux/kernelcapi.h | 75 ------ include/uapi/linux/b1lli.h | 74 ------ 14 files changed, 179 insertions(+), 1606 deletions(-) delete mode 100644 drivers/isdn/capi/capilib.c delete mode 100644 include/uapi/linux/b1lli.h (limited to 'Documentation') diff --git a/Documentation/isdn/interface_capi.rst b/Documentation/isdn/interface_capi.rst index 01a4b5ade9a4..fe2421444b76 100644 --- a/Documentation/isdn/interface_capi.rst +++ b/Documentation/isdn/interface_capi.rst @@ -26,13 +26,6 @@ This standard is freely available from https://www.capi.org. 2. Driver and Device Registration ================================= -CAPI drivers optionally register themselves with Kernel CAPI by calling the -Kernel CAPI function register_capi_driver() with a pointer to a struct -capi_driver. This structure must be filled with the name and revision of the -driver, and optionally a pointer to a callback function, add_card(). The -registration can be revoked by calling the function unregister_capi_driver() -with a pointer to the same struct capi_driver. - CAPI drivers must register each of the ISDN devices they control with Kernel CAPI by calling the Kernel CAPI function attach_capi_ctr() with a pointer to a struct capi_ctr before they can be used. This structure must be filled with @@ -89,9 +82,6 @@ register_capi_driver(): the name of the driver, as a zero-terminated ASCII string ``char revision[32]`` the revision number of the driver, as a zero-terminated ASCII string -``int (*add_card)(struct capi_driver *driver, capicardparams *data)`` - a callback function pointer (may be NULL) - 4.2 struct capi_ctr ------------------- @@ -178,12 +168,6 @@ to be set by the driver before calling attach_capi_ctr(): pointer to a callback function returning the entry for the device in the CAPI controller info table, /proc/capi/controller -``const struct file_operations *proc_fops`` - pointers to callback functions for the device's proc file - system entry, /proc/capi/controllers/; pointer to the device's - capi_ctr structure is available from struct proc_dir_entry::data - which is available from struct inode. - Note: Callback functions except send_message() are never called in interrupt context. @@ -267,25 +251,10 @@ _cmstruct alternative representation for CAPI parameters of type 'struct' _cmsg structure members. =========== ================================================================= -Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert -messages between their transport encoding described in the CAPI 2.0 standard -and their _cmsg structure representation. Note that capi_cmsg2message() does -not know or check the size of its destination buffer. The caller must make -sure it is big enough to accommodate the resulting CAPI message. - 5. Lower Layer Interface Functions ================================== -(declared in ) - -:: - - void register_capi_driver(struct capi_driver *drvr) - void unregister_capi_driver(struct capi_driver *drvr) - -register/unregister a driver with Kernel CAPI - :: int attach_capi_ctr(struct capi_ctr *ctrlr) @@ -300,13 +269,6 @@ register/unregister a device (controller) with Kernel CAPI signal controller ready/not ready -:: - - void capi_ctr_suspend_output(struct capi_ctr *ctrlr) - void capi_ctr_resume_output(struct capi_ctr *ctrlr) - -signal suspend/resume - :: void capi_ctr_handle_message(struct capi_ctr * ctrlr, u16 applid, @@ -319,21 +281,6 @@ for forwarding to the specified application 6. Helper Functions and Macros ============================== -Library functions (from ): - -:: - - void capilib_new_ncci(struct list_head *head, u16 applid, - u32 ncci, u32 winsize) - void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) - void capilib_release_appl(struct list_head *head, u16 applid) - void capilib_release(struct list_head *head) - void capilib_data_b3_conf(struct list_head *head, u16 applid, - u32 ncci, u16 msgid) - u16 capilib_data_b3_req(struct list_head *head, u16 applid, - u32 ncci, u16 msgid) - - Macros to extract/set element values from/in a CAPI message header (from ): @@ -357,24 +304,6 @@ CAPIMSG_DATALEN(m) CAPIMSG_SETDATALEN(m, len) Data Length (u16) Library functions for working with _cmsg structures (from ): -``unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg)`` - Assembles a CAPI 2.0 message from the parameters in ``*cmsg``, - storing the result in ``*msg``. - -``unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg)`` - Disassembles the CAPI 2.0 message in ``*msg``, storing the parameters - in ``*cmsg``. - -``unsigned capi_cmsg_header(_cmsg *cmsg, u16 ApplId, u8 Command, u8 Subcommand, u16 Messagenumber, u32 Controller)`` - Fills the header part and address field of the _cmsg structure ``*cmsg`` - with the given values, zeroing the remainder of the structure so only - parameters with non-default values need to be changed before sending - the message. - -``void capi_cmsg_answer(_cmsg *cmsg)`` - Sets the low bit of the Subcommand field in ``*cmsg``, thereby - converting ``_REQ`` to ``_CONF`` and ``_IND`` to ``_RESP``. - ``char *capi_cmd2str(u8 Command, u8 Subcommand)`` Returns the CAPI 2.0 message name corresponding to the given command and subcommand values, as a static ASCII string. The return value may diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 63baf27a2c79..d14334f4007e 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -3,6 +3,6 @@ # Object files in subdirectories -obj-$(CONFIG_ISDN_CAPI) += capi/ +obj-$(CONFIG_BT_CMTP) += capi/ obj-$(CONFIG_MISDN) += mISDN/ obj-$(CONFIG_ISDN) += hardware/ diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index 573fea5500ce..cc408ad9aafb 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -menuconfig ISDN_CAPI - tristate "CAPI 2.0 subsystem" +config ISDN_CAPI + def_bool ISDN && BT help This provides CAPI (the Common ISDN Application Programming Interface) Version 2.0, a standard making it easy for programs to @@ -15,42 +15,18 @@ menuconfig ISDN_CAPI See CONFIG_BT_CMTP for the last remaining regular driver in the kernel that uses the CAPI subsystem. -if ISDN_CAPI - config CAPI_TRACE - bool "CAPI trace support" - default y + def_bool BT_CMTP help If you say Y here, the kernelcapi driver can make verbose traces of CAPI messages. This feature can be enabled/disabled via IOCTL for every controller (default disabled). - This will increase the size of the kernelcapi module by 20 KB. - If unsure, say Y. - -config ISDN_CAPI_CAPI20 - tristate "CAPI2.0 /dev/capi20 support" - help - This option will provide the CAPI 2.0 interface to userspace - applications via /dev/capi20. Applications should use the - standardized libcapi20 to access this functionality. You should say - Y/M here. config ISDN_CAPI_MIDDLEWARE - bool "CAPI2.0 Middleware support" - depends on ISDN_CAPI_CAPI20 && TTY + def_bool BT_CMTP && TTY help This option will enhance the capabilities of the /dev/capi20 interface. It will provide a means of moving a data connection, established via the usual /dev/capi20 interface to a special tty device. If you want to use pppd with pppdcapiplugin to dial up to your ISP, say Y here. - -config ISDN_CAPI_CAPIDRV_VERBOSE - bool "Verbose reason code reporting" - depends on ISDN_CAPI_CAPIDRV - help - If you say Y here, the capidrv interface will give verbose reasons - for disconnecting. This will increase the size of the kernel by 7 KB. - If unsure, say N. - -endif diff --git a/drivers/isdn/capi/Makefile b/drivers/isdn/capi/Makefile index d299f3e75f89..352217ebabd8 100644 --- a/drivers/isdn/capi/Makefile +++ b/drivers/isdn/capi/Makefile @@ -1,17 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Makefile for the CAPI subsystem. +# Makefile for the CAPI subsystem used by BT_CMTP -# Ordering constraints: kernelcapi.o first - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o -obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o -obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o - -# Multipart objects. - -kernelcapi-y := kcapi.o capiutil.o capilib.o -kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o - -ccflags-y += -I$(srctree)/$(src)/../include -I$(srctree)/$(src)/../include/uapi +obj-$(CONFIG_BT_CMTP) += kernelcapi.o +kernelcapi-y := kcapi.o capiutil.o capi.o kcapi_proc.o diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 1675da34239b..85767f52fe3c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -39,7 +39,9 @@ #include #include -MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); +#include "kcapi.h" + +MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer and /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -1412,15 +1414,22 @@ static int __init capi_init(void) { const char *compileinfo; int major_ret; + int ret; + + ret = kcapi_init(); + if (ret) + return ret; major_ret = register_chrdev(capi_major, "capi20", &capi_fops); if (major_ret < 0) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); + kcapi_exit(); return major_ret; } capi_class = class_create(THIS_MODULE, "capi"); if (IS_ERR(capi_class)) { unregister_chrdev(capi_major, "capi20"); + kcapi_exit(); return PTR_ERR(capi_class); } @@ -1430,6 +1439,7 @@ static int __init capi_init(void) device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); + kcapi_exit(); return -ENOMEM; } @@ -1455,6 +1465,8 @@ static void __exit capi_exit(void) unregister_chrdev(capi_major, "capi20"); capinc_tty_exit(); + + kcapi_exit(); } module_init(capi_init); diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c deleted file mode 100644 index a39ad3796bba..000000000000 --- a/drivers/isdn/capi/capilib.c +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include -#include -#include -#include - -#define DBG(format, arg...) do { \ - printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ - } while (0) - -struct capilib_msgidqueue { - struct capilib_msgidqueue *next; - u16 msgid; -}; - -struct capilib_ncci { - struct list_head list; - u16 applid; - u32 ncci; - u32 winsize; - int nmsg; - struct capilib_msgidqueue *msgidqueue; - struct capilib_msgidqueue *msgidlast; - struct capilib_msgidqueue *msgidfree; - struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW]; -}; - -// --------------------------------------------------------------------------- -// NCCI Handling - -static inline void mq_init(struct capilib_ncci *np) -{ - u_int i; - np->msgidqueue = NULL; - np->msgidlast = NULL; - np->nmsg = 0; - memset(np->msgidpool, 0, sizeof(np->msgidpool)); - np->msgidfree = &np->msgidpool[0]; - for (i = 1; i < np->winsize; i++) { - np->msgidpool[i].next = np->msgidfree; - np->msgidfree = &np->msgidpool[i]; - } -} - -static inline int mq_enqueue(struct capilib_ncci *np, u16 msgid) -{ - struct capilib_msgidqueue *mq; - if ((mq = np->msgidfree) == NULL) - return 0; - np->msgidfree = mq->next; - mq->msgid = msgid; - mq->next = NULL; - if (np->msgidlast) - np->msgidlast->next = mq; - np->msgidlast = mq; - if (!np->msgidqueue) - np->msgidqueue = mq; - np->nmsg++; - return 1; -} - -static inline int mq_dequeue(struct capilib_ncci *np, u16 msgid) -{ - struct capilib_msgidqueue **pp; - for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->msgid == msgid) { - struct capilib_msgidqueue *mq = *pp; - *pp = mq->next; - if (mq == np->msgidlast) - np->msgidlast = NULL; - mq->next = np->msgidfree; - np->msgidfree = mq; - np->nmsg--; - return 1; - } - } - return 0; -} - -void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize) -{ - struct capilib_ncci *np; - - np = kmalloc(sizeof(*np), GFP_ATOMIC); - if (!np) { - printk(KERN_WARNING "capilib_new_ncci: no memory.\n"); - return; - } - if (winsize > CAPI_MAXDATAWINDOW) { - printk(KERN_ERR "capi_new_ncci: winsize %d too big\n", - winsize); - winsize = CAPI_MAXDATAWINDOW; - } - np->applid = applid; - np->ncci = ncci; - np->winsize = winsize; - mq_init(np); - list_add_tail(&np->list, head); - DBG("kcapi: appl %d ncci 0x%x up", applid, ncci); -} - -EXPORT_SYMBOL(capilib_new_ncci); - -void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci); - list_del(&np->list); - kfree(np); - return; - } - printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci); -} - -EXPORT_SYMBOL(capilib_free_ncci); - -void capilib_release_appl(struct list_head *head, u16 applid) -{ - struct list_head *l, *n; - struct capilib_ncci *np; - - list_for_each_safe(l, n, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci); - list_del(&np->list); - kfree(np); - } -} - -EXPORT_SYMBOL(capilib_release_appl); - -void capilib_release(struct list_head *head) -{ - struct list_head *l, *n; - struct capilib_ncci *np; - - list_for_each_safe(l, n, head) { - np = list_entry(l, struct capilib_ncci, list); - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci); - list_del(&np->list); - kfree(np); - } -} - -EXPORT_SYMBOL(capilib_release); - -u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - - if (mq_enqueue(np, msgid) == 0) - return CAPI_SENDQUEUEFULL; - - return CAPI_NOERROR; - } - printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci); - return CAPI_NOERROR; -} - -EXPORT_SYMBOL(capilib_data_b3_req); - -void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - - if (mq_dequeue(np, msgid) == 0) { - printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n", - msgid, ncci); - } - return; - } - printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci); -} - -EXPORT_SYMBOL(capilib_data_b3_conf); diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index 9846d82eb097..f26bf3c66d7e 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -20,6 +20,8 @@ #include #include +#include "kcapi.h" + /* from CAPI2.0 DDK AVM Berlin GmbH */ typedef struct { @@ -245,190 +247,6 @@ static void jumpcstruct(_cmsg *cmsg) } } } -/*-------------------------------------------------------*/ -static void pars_2_message(_cmsg *cmsg) -{ - - for (; TYP != _CEND; cmsg->p++) { - switch (TYP) { - case _CBYTE: - byteTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - if (*(u8 **) OFF == NULL) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - } else if (**(_cstruct *) OFF != 0xff) { - structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF); - cmsg->l += 1 + **(_cstruct *) OFF; - } else { - _cstruct s = *(_cstruct *) OFF; - structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1)); - cmsg->l += 3 + *(u16 *) (s + 1); - } - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (*(_cmstruct *) OFF == CAPI_DEFAULT) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - jumpcstruct(cmsg); - } -/*----- Metastruktur wird composed -----*/ - else { - unsigned _l = cmsg->l; - unsigned _ls; - cmsg->l++; - cmsg->p++; - pars_2_message(cmsg); - _ls = cmsg->l - _l - 1; - if (_ls < 255) - (cmsg->m + _l)[0] = (u8) _ls; - else { - structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls); - (cmsg->m + _l)[0] = 0xff; - wordTLcpy(cmsg->m + _l + 1, &_ls); - } - } - break; - } - } -} - -/** - * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure - * @cmsg: _cmsg structure - * @msg: buffer for assembled message - * - * Return value: 0 for success - */ - -unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg) -{ - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand); - if (!cmsg->par) - return 1; /* invalid command/subcommand */ - - pars_2_message(cmsg); - - wordTLcpy(msg + 0, &cmsg->l); - byteTLcpy(cmsg->m + 4, &cmsg->Command); - byteTLcpy(cmsg->m + 5, &cmsg->Subcommand); - wordTLcpy(cmsg->m + 2, &cmsg->ApplId); - wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/*-------------------------------------------------------*/ -static void message_2_pars(_cmsg *cmsg) -{ - for (; TYP != _CEND; cmsg->p++) { - - switch (TYP) { - case _CBYTE: - byteTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - *(u8 **) OFF = cmsg->m + cmsg->l; - - if (cmsg->m[cmsg->l] != 0xff) - cmsg->l += 1 + cmsg->m[cmsg->l]; - else - cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1); - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (cmsg->m[cmsg->l] == '\0') { - *(_cmstruct *) OFF = CAPI_DEFAULT; - cmsg->l++; - jumpcstruct(cmsg); - } else { - unsigned _l = cmsg->l; - *(_cmstruct *) OFF = CAPI_COMPOSE; - cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; - cmsg->p++; - message_2_pars(cmsg); - } - break; - } - } -} - -/** - * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure - * @cmsg: _cmsg structure - * @msg: buffer for assembled message - * - * Return value: 0 for success - */ - -unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - byteTRcpy(cmsg->m + 4, &cmsg->Command); - byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); - cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand); - if (!cmsg->par) - return 1; /* invalid command/subcommand */ - - message_2_pars(cmsg); - - wordTRcpy(msg + 0, &cmsg->l); - wordTRcpy(cmsg->m + 2, &cmsg->ApplId); - wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/** - * capi_cmsg_header() - initialize header part of _cmsg structure - * @cmsg: _cmsg structure - * @_ApplId: ApplID field value - * @_Command: Command field value - * @_Subcommand: Subcommand field value - * @_Messagenumber: Message Number field value - * @_Controller: Controller/PLCI/NCCI field value - * - * Return value: 0 for success - */ - -unsigned capi_cmsg_header(_cmsg *cmsg, u16 _ApplId, - u8 _Command, u8 _Subcommand, - u16 _Messagenumber, u32 _Controller) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->ApplId = _ApplId; - cmsg->Command = _Command; - cmsg->Subcommand = _Subcommand; - cmsg->Messagenumber = _Messagenumber; - cmsg->adr.adrController = _Controller; - return 0; -} /*-------------------------------------------------------*/ @@ -561,8 +379,6 @@ static char *pnames[] = /*2f */ "Useruserdata" }; - - #include /*-------------------------------------------------------*/ @@ -800,37 +616,6 @@ _cdebbuf *capi_message2str(u8 *msg) return cdb; } -/** - * capi_cmsg2str() - format _cmsg structure for printing - * @cmsg: _cmsg structure - * - * Allocates a CAPI debug buffer and fills it with a printable representation - * of the CAPI 2.0 message stored in @cmsg by a previous call to - * capi_cmsg2message() or capi_message2cmsg(). - * Return value: allocated debug buffer, NULL on error - * The returned buffer should be freed by a call to cdebbuf_free() after use. - */ - -_cdebbuf *capi_cmsg2str(_cmsg *cmsg) -{ - _cdebbuf *cdb; - - if (!cmsg->m) - return NULL; /* no message */ - cdb = cdebbuf_alloc(); - if (!cdb) - return NULL; - cmsg->l = 8; - cmsg->p = 0; - cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - ((u16 *) cmsg->m)[1], - ((u16 *) cmsg->m)[3], - ((u16 *) cmsg->m)[0]); - cdb = protocol_message_2_pars(cdb, cmsg, 1); - return cdb; -} - int __init cdebug_init(void) { g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL); @@ -854,7 +639,7 @@ int __init cdebug_init(void) return 0; } -void __exit cdebug_exit(void) +void cdebug_exit(void) { if (g_debbuf) kfree(g_debbuf->buf); @@ -885,16 +670,8 @@ int __init cdebug_init(void) return 0; } -void __exit cdebug_exit(void) +void cdebug_exit(void) { } #endif - -EXPORT_SYMBOL(cdebbuf_free); -EXPORT_SYMBOL(capi_cmsg2message); -EXPORT_SYMBOL(capi_message2cmsg); -EXPORT_SYMBOL(capi_cmsg_header); -EXPORT_SYMBOL(capi_cmd2str); -EXPORT_SYMBOL(capi_cmsg2str); -EXPORT_SYMBOL(capi_message2str); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index a4ceb61c5b60..7168778fbbe1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -10,8 +10,6 @@ * */ -#define AVMB1_COMPAT - #include "kcapi.h" #include #include @@ -31,18 +29,12 @@ #include #include #include -#ifdef AVMB1_COMPAT -#include -#endif #include #include static int showcapimsgs = 0; static struct workqueue_struct *kcapi_wq; -MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); module_param(showcapimsgs, uint, 0); /* ------------------------------------------------------------- */ @@ -61,9 +53,6 @@ static char capi_manufakturer[64] = "AVM Berlin"; #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) -LIST_HEAD(capi_drivers); -DEFINE_MUTEX(capi_drivers_lock); - struct capi_ctr *capi_controller[CAPI_MAXCONTR]; DEFINE_MUTEX(capi_controller_lock); @@ -71,8 +60,6 @@ struct capi20_appl *capi_applications[CAPI_MAXAPPL]; static int ncontrollers; -static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); - /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * @@ -200,8 +187,6 @@ static void notify_up(u32 contr) if (ap) register_appl(ctr, applid, &ap->rparam); } - - wake_up_interruptible_all(&ctr->state_wait_queue); } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); @@ -229,8 +214,6 @@ static void ctr_down(struct capi_ctr *ctr, int new_state) if (ap) capi_ctr_put(ctr); } - - wake_up_interruptible_all(&ctr->state_wait_queue); } static void notify_down(u32 contr) @@ -251,36 +234,23 @@ static void notify_down(u32 contr) mutex_unlock(&capi_controller_lock); } -static int -notify_handler(struct notifier_block *nb, unsigned long val, void *v) +static void do_notify_work(struct work_struct *work) { - u32 contr = (long)v; + struct capictr_event *event = + container_of(work, struct capictr_event, work); - switch (val) { + switch (event->type) { case CAPICTR_UP: - notify_up(contr); + notify_up(event->controller); break; case CAPICTR_DOWN: - notify_down(contr); + notify_down(event->controller); break; } - return NOTIFY_OK; -} -static void do_notify_work(struct work_struct *work) -{ - struct capictr_event *event = - container_of(work, struct capictr_event, work); - - blocking_notifier_call_chain(&ctr_notifier_list, event->type, - (void *)(long)event->controller); kfree(event); } -/* - * The notifier will result in adding/deleteing of devices. Devices can - * only removed in user process, not in bh. - */ static int notify_push(unsigned int event_type, u32 controller) { struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); @@ -296,18 +266,6 @@ static int notify_push(unsigned int event_type, u32 controller) return 0; } -int register_capictr_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&ctr_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(register_capictr_notifier); - -int unregister_capictr_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_capictr_notifier); - /* -------- Receiver ------------------------------------------ */ static void recv_handler(struct work_struct *work) @@ -454,48 +412,6 @@ void capi_ctr_down(struct capi_ctr *ctr) EXPORT_SYMBOL(capi_ctr_down); -/** - * capi_ctr_suspend_output() - suspend controller - * @ctr: controller descriptor structure. - * - * Called by hardware driver to stop data flow. - * - * Note: The caller is responsible for synchronizing concurrent state changes - * as well as invocations of capi_ctr_handle_message. - */ - -void capi_ctr_suspend_output(struct capi_ctr *ctr) -{ - if (!ctr->blocked) { - printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", - ctr->cnr); - ctr->blocked = 1; - } -} - -EXPORT_SYMBOL(capi_ctr_suspend_output); - -/** - * capi_ctr_resume_output() - resume controller - * @ctr: controller descriptor structure. - * - * Called by hardware driver to resume data flow. - * - * Note: The caller is responsible for synchronizing concurrent state changes - * as well as invocations of capi_ctr_handle_message. - */ - -void capi_ctr_resume_output(struct capi_ctr *ctr) -{ - if (ctr->blocked) { - printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", - ctr->cnr); - ctr->blocked = 0; - } -} - -EXPORT_SYMBOL(capi_ctr_resume_output); - /* ------------------------------------------------------------- */ /** @@ -531,7 +447,6 @@ int attach_capi_ctr(struct capi_ctr *ctr) ctr->state = CAPI_CTR_DETECTED; ctr->blocked = 0; ctr->traceflag = showcapimsgs; - init_waitqueue_head(&ctr->state_wait_queue); sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); ctr->procent = proc_create_single_data(ctr->procfn, 0, NULL, @@ -586,38 +501,6 @@ unlock_out: EXPORT_SYMBOL(detach_capi_ctr); -/** - * register_capi_driver() - register CAPI driver - * @driver: driver descriptor structure. - * - * Called by hardware driver to register itself with the CAPI subsystem. - */ - -void register_capi_driver(struct capi_driver *driver) -{ - mutex_lock(&capi_drivers_lock); - list_add_tail(&driver->list, &capi_drivers); - mutex_unlock(&capi_drivers_lock); -} - -EXPORT_SYMBOL(register_capi_driver); - -/** - * unregister_capi_driver() - unregister CAPI driver - * @driver: driver descriptor structure. - * - * Called by hardware driver to unregister itself from the CAPI subsystem. - */ - -void unregister_capi_driver(struct capi_driver *driver) -{ - mutex_lock(&capi_drivers_lock); - list_del(&driver->list); - mutex_unlock(&capi_drivers_lock); -} - -EXPORT_SYMBOL(unregister_capi_driver); - /* ------------------------------------------------------------- */ /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ @@ -648,8 +531,6 @@ u16 capi20_isinstalled(void) return ret; } -EXPORT_SYMBOL(capi20_isinstalled); - /** * capi20_register() - CAPI 2.0 operation CAPI_REGISTER * @ap: CAPI application descriptor structure. @@ -711,8 +592,6 @@ u16 capi20_register(struct capi20_appl *ap) return CAPI_NOERROR; } -EXPORT_SYMBOL(capi20_register); - /** * capi20_release() - CAPI 2.0 operation CAPI_RELEASE * @ap: CAPI application descriptor structure. @@ -755,8 +634,6 @@ u16 capi20_release(struct capi20_appl *ap) return CAPI_NOERROR; } -EXPORT_SYMBOL(capi20_release); - /** * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE * @ap: CAPI application descriptor structure. @@ -834,8 +711,6 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) return ctr->send_message(ctr, skb); } -EXPORT_SYMBOL(capi20_put_message); - /** * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER * @contr: controller number. @@ -869,8 +744,6 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf) return ret; } -EXPORT_SYMBOL(capi20_get_manufacturer); - /** * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION * @contr: controller number. @@ -904,8 +777,6 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) return ret; } -EXPORT_SYMBOL(capi20_get_version); - /** * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER * @contr: controller number. @@ -939,8 +810,6 @@ u16 capi20_get_serial(u32 contr, u8 *serial) return ret; } -EXPORT_SYMBOL(capi20_get_serial); - /** * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE * @contr: controller number. @@ -974,209 +843,6 @@ u16 capi20_get_profile(u32 contr, struct capi_profile *profp) return ret; } -EXPORT_SYMBOL(capi20_get_profile); - -/* Must be called with capi_controller_lock held. */ -static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) -{ - DEFINE_WAIT(wait); - int retval = 0; - - ctr = capi_ctr_get(ctr); - if (!ctr) - return -ESRCH; - - for (;;) { - prepare_to_wait(&ctr->state_wait_queue, &wait, - TASK_INTERRUPTIBLE); - - if (ctr->state == state) - break; - if (ctr->state == CAPI_CTR_DETACHED) { - retval = -ESRCH; - break; - } - if (signal_pending(current)) { - retval = -EINTR; - break; - } - - mutex_unlock(&capi_controller_lock); - schedule(); - mutex_lock(&capi_controller_lock); - } - finish_wait(&ctr->state_wait_queue, &wait); - - capi_ctr_put(ctr); - - return retval; -} - -#ifdef AVMB1_COMPAT -static int old_capi_manufacturer(unsigned int cmd, void __user *data) -{ - avmb1_loadandconfigdef ldef; - avmb1_extcarddef cdef; - avmb1_resetdef rdef; - capicardparams cparams; - struct capi_ctr *ctr; - struct capi_driver *driver = NULL; - capiloaddata ldata; - struct list_head *l; - int retval; - - switch (cmd) { - case AVMB1_ADDCARD: - case AVMB1_ADDCARD_WITH_TYPE: - if (cmd == AVMB1_ADDCARD) { - if ((retval = copy_from_user(&cdef, data, - sizeof(avmb1_carddef)))) - return -EFAULT; - cdef.cardtype = AVM_CARDTYPE_B1; - cdef.cardnr = 0; - } else { - if ((retval = copy_from_user(&cdef, data, - sizeof(avmb1_extcarddef)))) - return -EFAULT; - } - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.cardnr = cdef.cardnr; - - mutex_lock(&capi_drivers_lock); - - switch (cdef.cardtype) { - case AVM_CARDTYPE_B1: - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, "b1isa") == 0) - break; - } - break; - case AVM_CARDTYPE_T1: - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, "t1isa") == 0) - break; - } - break; - default: - driver = NULL; - break; - } - if (!driver) { - printk(KERN_ERR "kcapi: driver not loaded.\n"); - retval = -EIO; - } else if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver has no add card function.\n"); - retval = -EIO; - } else - retval = driver->add_card(driver, &cparams); - - mutex_unlock(&capi_drivers_lock); - return retval; - - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - - if (cmd == AVMB1_LOAD) { - if (copy_from_user(&ldef, data, - sizeof(avmb1_loaddef))) - return -EFAULT; - ldef.t4config.len = 0; - ldef.t4config.data = NULL; - } else { - if (copy_from_user(&ldef, data, - sizeof(avmb1_loadandconfigdef))) - return -EFAULT; - } - - mutex_lock(&capi_controller_lock); - - ctr = get_capi_ctr_by_nr(ldef.contr); - if (!ctr) { - retval = -EINVAL; - goto load_unlock_out; - } - - if (ctr->load_firmware == NULL) { - printk(KERN_DEBUG "kcapi: load: no load function\n"); - retval = -ESRCH; - goto load_unlock_out; - } - - if (ldef.t4file.len <= 0) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - retval = -EINVAL; - goto load_unlock_out; - } - if (ldef.t4file.data == NULL) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - retval = -EINVAL; - goto load_unlock_out; - } - - ldata.firmware.user = 1; - ldata.firmware.data = ldef.t4file.data; - ldata.firmware.len = ldef.t4file.len; - ldata.configuration.user = 1; - ldata.configuration.data = ldef.t4config.data; - ldata.configuration.len = ldef.t4config.len; - - if (ctr->state != CAPI_CTR_DETECTED) { - printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - retval = -EBUSY; - goto load_unlock_out; - } - ctr->state = CAPI_CTR_LOADING; - - retval = ctr->load_firmware(ctr, &ldata); - if (retval) { - ctr->state = CAPI_CTR_DETECTED; - goto load_unlock_out; - } - - retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); - - load_unlock_out: - mutex_unlock(&capi_controller_lock); - return retval; - - case AVMB1_RESETCARD: - if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) - return -EFAULT; - - retval = 0; - - mutex_lock(&capi_controller_lock); - - ctr = get_capi_ctr_by_nr(rdef.contr); - if (!ctr) { - retval = -ESRCH; - goto reset_unlock_out; - } - - if (ctr->state == CAPI_CTR_DETECTED) - goto reset_unlock_out; - - if (ctr->reset_ctr == NULL) { - printk(KERN_DEBUG "kcapi: reset: no reset function\n"); - retval = -ESRCH; - goto reset_unlock_out; - } - - ctr->reset_ctr(ctr); - - retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); - - reset_unlock_out: - mutex_unlock(&capi_controller_lock); - return retval; - } - return -EINVAL; -} -#endif - /** * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER * @cmd: command. @@ -1192,14 +858,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) int retval; switch (cmd) { -#ifdef AVMB1_COMPAT - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - case AVMB1_RESETCARD: - case AVMB1_GET_CARDINFO: - case AVMB1_REMOVECARD: - return old_capi_manufacturer(cmd, data); -#endif case KCAPI_CMD_TRACE: { kcapi_flagdef fdef; @@ -1222,43 +880,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) return retval; } - case KCAPI_CMD_ADDCARD: - { - struct list_head *l; - struct capi_driver *driver = NULL; - capicardparams cparams; - kcapi_carddef cdef; - - if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) - return -EFAULT; - - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.membase = cdef.membase; - cparams.cardnr = cdef.cardnr; - cparams.cardtype = 0; - cdef.driver[sizeof(cdef.driver) - 1] = 0; - - mutex_lock(&capi_drivers_lock); - - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, cdef.driver) == 0) - break; - } - if (driver == NULL) { - printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", - cdef.driver); - retval = -ESRCH; - } else if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); - retval = -EIO; - } else - retval = driver->add_card(driver, &cparams); - - mutex_unlock(&capi_drivers_lock); - return retval; - } default: printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n", @@ -1269,8 +890,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) return -EINVAL; } -EXPORT_SYMBOL(capi20_manufacturer); - /* ------------------------------------------------------------- */ /* -------- Init & Cleanup ------------------------------------- */ /* ------------------------------------------------------------- */ @@ -1279,12 +898,7 @@ EXPORT_SYMBOL(capi20_manufacturer); * init / exit functions */ -static struct notifier_block capictr_nb = { - .notifier_call = notify_handler, - .priority = INT_MAX, -}; - -static int __init kcapi_init(void) +int __init kcapi_init(void) { int err; @@ -1292,11 +906,8 @@ static int __init kcapi_init(void) if (!kcapi_wq) return -ENOMEM; - register_capictr_notifier(&capictr_nb); - err = cdebug_init(); if (err) { - unregister_capictr_notifier(&capictr_nb); destroy_workqueue(kcapi_wq); return err; } @@ -1305,14 +916,10 @@ static int __init kcapi_init(void) return 0; } -static void __exit kcapi_exit(void) +void kcapi_exit(void) { kcapi_proc_exit(); - unregister_capictr_notifier(&capictr_nb); cdebug_exit(); destroy_workqueue(kcapi_wq); } - -module_init(kcapi_init); -module_exit(kcapi_exit); diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 6d439f9a76b2..479623e1db2a 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -30,22 +30,153 @@ enum { CAPI_CTR_RUNNING = 3, }; -extern struct list_head capi_drivers; -extern struct mutex capi_drivers_lock; - extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; extern struct mutex capi_controller_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -#ifdef CONFIG_PROC_FS - void kcapi_proc_init(void); void kcapi_proc_exit(void); -#else +struct capi20_appl { + u16 applid; + capi_register_params rparam; + void (*recv_message)(struct capi20_appl *ap, struct sk_buff *skb); + void *private; -static inline void kcapi_proc_init(void) { }; -static inline void kcapi_proc_exit(void) { }; + /* internal to kernelcapi.o */ + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; + struct mutex recv_mtx; + struct sk_buff_head recv_queue; + struct work_struct recv_work; + int release_in_progress; +}; -#endif +u16 capi20_isinstalled(void); +u16 capi20_register(struct capi20_appl *ap); +u16 capi20_release(struct capi20_appl *ap); +u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb); +u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]); +u16 capi20_get_version(u32 contr, struct capi_version *verp); +u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]); +u16 capi20_get_profile(u32 contr, struct capi_profile *profp); +int capi20_manufacturer(unsigned long cmd, void __user *data); + +#define CAPICTR_UP 0 +#define CAPICTR_DOWN 1 + +int kcapi_init(void); +void kcapi_exit(void); + +/*----- basic-type definitions -----*/ + +typedef __u8 *_cstruct; + +typedef enum { + CAPI_COMPOSE, + CAPI_DEFAULT +} _cmstruct; + +/* + The _cmsg structure contains all possible CAPI 2.0 parameter. + All parameters are stored here first. The function CAPI_CMSG_2_MESSAGE + assembles the parameter and builds CAPI2.0 conform messages. + CAPI_MESSAGE_2_CMSG disassembles CAPI 2.0 messages and stores the + parameter in the _cmsg structure + */ + +typedef struct { + /* Header */ + __u16 ApplId; + __u8 Command; + __u8 Subcommand; + __u16 Messagenumber; + + /* Parameter */ + union { + __u32 adrController; + __u32 adrPLCI; + __u32 adrNCCI; + } adr; + + _cmstruct AdditionalInfo; + _cstruct B1configuration; + __u16 B1protocol; + _cstruct B2configuration; + __u16 B2protocol; + _cstruct B3configuration; + __u16 B3protocol; + _cstruct BC; + _cstruct BChannelinformation; + _cmstruct BProtocol; + _cstruct CalledPartyNumber; + _cstruct CalledPartySubaddress; + _cstruct CallingPartyNumber; + _cstruct CallingPartySubaddress; + __u32 CIPmask; + __u32 CIPmask2; + __u16 CIPValue; + __u32 Class; + _cstruct ConnectedNumber; + _cstruct ConnectedSubaddress; + __u32 Data; + __u16 DataHandle; + __u16 DataLength; + _cstruct FacilityConfirmationParameter; + _cstruct Facilitydataarray; + _cstruct FacilityIndicationParameter; + _cstruct FacilityRequestParameter; + __u16 FacilitySelector; + __u16 Flags; + __u32 Function; + _cstruct HLC; + __u16 Info; + _cstruct InfoElement; + __u32 InfoMask; + __u16 InfoNumber; + _cstruct Keypadfacility; + _cstruct LLC; + _cstruct ManuData; + __u32 ManuID; + _cstruct NCPI; + __u16 Reason; + __u16 Reason_B3; + __u16 Reject; + _cstruct Useruserdata; + + /* intern */ + unsigned l, p; + unsigned char *par; + __u8 *m; + + /* buffer to construct message */ + __u8 buf[180]; + +} _cmsg; + +/*-----------------------------------------------------------------------*/ + +/* + * Debugging / Tracing functions + */ + +char *capi_cmd2str(__u8 cmd, __u8 subcmd); + +typedef struct { + u_char *buf; + u_char *p; + size_t size; + size_t pos; +} _cdebbuf; + +#define CDEBUG_SIZE 1024 +#define CDEBUG_GSIZE 4096 + +void cdebbuf_free(_cdebbuf *cdb); +int cdebug_init(void); +void cdebug_exit(void); + +_cdebbuf *capi_message2str(__u8 *msg); diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index c94bd12c0f7c..2bffbb8bf271 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -192,37 +192,15 @@ static const struct seq_operations seq_applstats_ops = { // --------------------------------------------------------------------------- -static void *capi_driver_start(struct seq_file *seq, loff_t *pos) - __acquires(&capi_drivers_lock) +/* /proc/capi/drivers is always empty */ +static ssize_t empty_read(struct file *file, char __user *buf, + size_t size, loff_t *off) { - mutex_lock(&capi_drivers_lock); - return seq_list_start(&capi_drivers, *pos); -} - -static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) -{ - return seq_list_next(v, &capi_drivers, pos); -} - -static void capi_driver_stop(struct seq_file *seq, void *v) - __releases(&capi_drivers_lock) -{ - mutex_unlock(&capi_drivers_lock); -} - -static int capi_driver_show(struct seq_file *seq, void *v) -{ - struct capi_driver *drv = list_entry(v, struct capi_driver, list); - - seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); return 0; } -static const struct seq_operations seq_capi_driver_ops = { - .start = capi_driver_start, - .next = capi_driver_next, - .stop = capi_driver_stop, - .show = capi_driver_show, +static const struct file_operations empty_fops = { + .read = empty_read, }; // --------------------------------------------------------------------------- @@ -236,7 +214,7 @@ kcapi_proc_init(void) proc_create_seq("capi/contrstats", 0, NULL, &seq_contrstats_ops); proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops); proc_create_seq("capi/applstats", 0, NULL, &seq_applstats_ops); - proc_create_seq("capi/driver", 0, NULL, &seq_capi_driver_ops); + proc_create("capi/driver", 0, NULL, &empty_fops); } void __exit diff --git a/include/linux/isdn/capilli.h b/include/linux/isdn/capilli.h index d75e1ad72964..12be09b6883b 100644 --- a/include/linux/isdn/capilli.h +++ b/include/linux/isdn/capilli.h @@ -69,7 +69,6 @@ struct capi_ctr { unsigned short state; /* controller state */ int blocked; /* output blocked */ int traceflag; /* capi trace */ - wait_queue_head_t state_wait_queue; struct proc_dir_entry *procent; char procfn[128]; @@ -80,8 +79,6 @@ int detach_capi_ctr(struct capi_ctr *); void capi_ctr_ready(struct capi_ctr * card); void capi_ctr_down(struct capi_ctr * card); -void capi_ctr_suspend_output(struct capi_ctr * card); -void capi_ctr_resume_output(struct capi_ctr * card); void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb); // --------------------------------------------------------------------------- @@ -91,23 +88,8 @@ struct capi_driver { char name[32]; /* driver name */ char revision[32]; - int (*add_card)(struct capi_driver *driver, capicardparams *data); - /* management information for kcapi */ struct list_head list; }; -void register_capi_driver(struct capi_driver *driver); -void unregister_capi_driver(struct capi_driver *driver); - -// --------------------------------------------------------------------------- -// library functions for use by hardware controller drivers - -void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize); -void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci); -void capilib_release_appl(struct list_head *head, u16 applid); -void capilib_release(struct list_head *head); -void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid); -u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid); - #endif /* __CAPILLI_H__ */ diff --git a/include/linux/isdn/capiutil.h b/include/linux/isdn/capiutil.h index 44bd6046e6e2..953fd500dff7 100644 --- a/include/linux/isdn/capiutil.h +++ b/include/linux/isdn/capiutil.h @@ -57,460 +57,4 @@ static inline void capimsg_setu32(void *m, int off, __u32 val) #define CAPIMSG_SETCONTROL(m, contr) capimsg_setu32(m, 8, contr) #define CAPIMSG_SETDATALEN(m, len) capimsg_setu16(m, 16, len) -/*----- basic-type definitions -----*/ - -typedef __u8 *_cstruct; - -typedef enum { - CAPI_COMPOSE, - CAPI_DEFAULT -} _cmstruct; - -/* - The _cmsg structure contains all possible CAPI 2.0 parameter. - All parameters are stored here first. The function CAPI_CMSG_2_MESSAGE - assembles the parameter and builds CAPI2.0 conform messages. - CAPI_MESSAGE_2_CMSG disassembles CAPI 2.0 messages and stores the - parameter in the _cmsg structure - */ - -typedef struct { - /* Header */ - __u16 ApplId; - __u8 Command; - __u8 Subcommand; - __u16 Messagenumber; - - /* Parameter */ - union { - __u32 adrController; - __u32 adrPLCI; - __u32 adrNCCI; - } adr; - - _cmstruct AdditionalInfo; - _cstruct B1configuration; - __u16 B1protocol; - _cstruct B2configuration; - __u16 B2protocol; - _cstruct B3configuration; - __u16 B3protocol; - _cstruct BC; - _cstruct BChannelinformation; - _cmstruct BProtocol; - _cstruct CalledPartyNumber; - _cstruct CalledPartySubaddress; - _cstruct CallingPartyNumber; - _cstruct CallingPartySubaddress; - __u32 CIPmask; - __u32 CIPmask2; - __u16 CIPValue; - __u32 Class; - _cstruct ConnectedNumber; - _cstruct ConnectedSubaddress; - __u32 Data; - __u16 DataHandle; - __u16 DataLength; - _cstruct FacilityConfirmationParameter; - _cstruct Facilitydataarray; - _cstruct FacilityIndicationParameter; - _cstruct FacilityRequestParameter; - __u16 FacilitySelector; - __u16 Flags; - __u32 Function; - _cstruct HLC; - __u16 Info; - _cstruct InfoElement; - __u32 InfoMask; - __u16 InfoNumber; - _cstruct Keypadfacility; - _cstruct LLC; - _cstruct ManuData; - __u32 ManuID; - _cstruct NCPI; - __u16 Reason; - __u16 Reason_B3; - __u16 Reject; - _cstruct Useruserdata; - - /* intern */ - unsigned l, p; - unsigned char *par; - __u8 *m; - - /* buffer to construct message */ - __u8 buf[180]; - -} _cmsg; - -/* - * capi_cmsg2message() assembles the parameter from _cmsg to a CAPI 2.0 - * conform message - */ -unsigned capi_cmsg2message(_cmsg * cmsg, __u8 * msg); - -/* - * capi_message2cmsg disassembles a CAPI message an writes the parameter - * into _cmsg for easy access - */ -unsigned capi_message2cmsg(_cmsg * cmsg, __u8 * msg); - -/* - * capi_cmsg_header() fills the _cmsg structure with default values, so only - * parameter with non default values must be changed before sending the - * message. - */ -unsigned capi_cmsg_header(_cmsg * cmsg, __u16 _ApplId, - __u8 _Command, __u8 _Subcommand, - __u16 _Messagenumber, __u32 _Controller); - -/*-----------------------------------------------------------------------*/ - -/* - * Debugging / Tracing functions - */ - -char *capi_cmd2str(__u8 cmd, __u8 subcmd); - -typedef struct { - u_char *buf; - u_char *p; - size_t size; - size_t pos; -} _cdebbuf; - -#define CDEBUG_SIZE 1024 -#define CDEBUG_GSIZE 4096 - -void cdebbuf_free(_cdebbuf *cdb); -int cdebug_init(void); -void cdebug_exit(void); - -_cdebbuf *capi_cmsg2str(_cmsg *cmsg); -_cdebbuf *capi_message2str(__u8 *msg); - -/*-----------------------------------------------------------------------*/ - -static inline void capi_cmsg_answer(_cmsg * cmsg) -{ - cmsg->Subcommand |= 0x01; -} - -/*-----------------------------------------------------------------------*/ - -static inline void capi_fill_CONNECT_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - capi_cmsg_header(cmsg, ApplId, 0x82, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_FACILITY_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 FacilitySelector, - _cstruct FacilityRequestParameter) -{ - capi_cmsg_header(cmsg, ApplId, 0x80, 0x80, Messagenumber, adr); - cmsg->FacilitySelector = FacilitySelector; - cmsg->FacilityRequestParameter = FacilityRequestParameter; -} - -static inline void capi_fill_INFO_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct CalledPartyNumber, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x08, 0x80, Messagenumber, adr); - cmsg->CalledPartyNumber = CalledPartyNumber; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_LISTEN_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 InfoMask, - __u32 CIPmask, - __u32 CIPmask2, - _cstruct CallingPartyNumber, - _cstruct CallingPartySubaddress) -{ - capi_cmsg_header(cmsg, ApplId, 0x05, 0x80, Messagenumber, adr); - cmsg->InfoMask = InfoMask; - cmsg->CIPmask = CIPmask; - cmsg->CIPmask2 = CIPmask2; - cmsg->CallingPartyNumber = CallingPartyNumber; - cmsg->CallingPartySubaddress = CallingPartySubaddress; -} - -static inline void capi_fill_ALERT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x01, 0x80, Messagenumber, adr); - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_CONNECT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 CIPValue, - _cstruct CalledPartyNumber, - _cstruct CallingPartyNumber, - _cstruct CalledPartySubaddress, - _cstruct CallingPartySubaddress, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration, - _cstruct BC, - _cstruct LLC, - _cstruct HLC, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - - capi_cmsg_header(cmsg, ApplId, 0x02, 0x80, Messagenumber, adr); - cmsg->CIPValue = CIPValue; - cmsg->CalledPartyNumber = CalledPartyNumber; - cmsg->CallingPartyNumber = CallingPartyNumber; - cmsg->CalledPartySubaddress = CalledPartySubaddress; - cmsg->CallingPartySubaddress = CallingPartySubaddress; - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; - cmsg->BC = BC; - cmsg->LLC = LLC; - cmsg->HLC = HLC; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_DATA_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 Data, - __u16 DataLength, - __u16 DataHandle, - __u16 Flags) -{ - - capi_cmsg_header(cmsg, ApplId, 0x86, 0x80, Messagenumber, adr); - cmsg->Data = Data; - cmsg->DataLength = DataLength; - cmsg->DataHandle = DataHandle; - cmsg->Flags = Flags; -} - -static inline void capi_fill_DISCONNECT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - - capi_cmsg_header(cmsg, ApplId, 0x04, 0x80, Messagenumber, adr); - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_DISCONNECT_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - - capi_cmsg_header(cmsg, ApplId, 0x84, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_MANUFACTURER_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 ManuID, - __u32 Class, - __u32 Function, - _cstruct ManuData) -{ - - capi_cmsg_header(cmsg, ApplId, 0xff, 0x80, Messagenumber, adr); - cmsg->ManuID = ManuID; - cmsg->Class = Class; - cmsg->Function = Function; - cmsg->ManuData = ManuData; -} - -static inline void capi_fill_RESET_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - - capi_cmsg_header(cmsg, ApplId, 0x87, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_SELECT_B_PROTOCOL_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration) -{ - - capi_cmsg_header(cmsg, ApplId, 0x41, 0x80, Messagenumber, adr); - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; -} - -static inline void capi_fill_CONNECT_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 Reject, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration, - _cstruct ConnectedNumber, - _cstruct ConnectedSubaddress, - _cstruct LLC, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x02, 0x83, Messagenumber, adr); - cmsg->Reject = Reject; - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; - cmsg->ConnectedNumber = ConnectedNumber; - cmsg->ConnectedSubaddress = ConnectedSubaddress; - cmsg->LLC = LLC; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_CONNECT_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x03, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_CONNECT_B3_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x83, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_CONNECT_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 Reject, - _cstruct NCPI) -{ - capi_cmsg_header(cmsg, ApplId, 0x82, 0x83, Messagenumber, adr); - cmsg->Reject = Reject; - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_CONNECT_B3_T90_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x88, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_DATA_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 DataHandle) -{ - - capi_cmsg_header(cmsg, ApplId, 0x86, 0x83, Messagenumber, adr); - cmsg->DataHandle = DataHandle; -} - -static inline void capi_fill_DISCONNECT_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x84, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_DISCONNECT_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x04, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_FACILITY_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 FacilitySelector) -{ - - capi_cmsg_header(cmsg, ApplId, 0x80, 0x83, Messagenumber, adr); - cmsg->FacilitySelector = FacilitySelector; -} - -static inline void capi_fill_INFO_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x08, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_MANUFACTURER_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 ManuID, - __u32 Class, - __u32 Function, - _cstruct ManuData) -{ - - capi_cmsg_header(cmsg, ApplId, 0xff, 0x83, Messagenumber, adr); - cmsg->ManuID = ManuID; - cmsg->Class = Class; - cmsg->Function = Function; - cmsg->ManuData = ManuData; -} - -static inline void capi_fill_RESET_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x87, 0x83, Messagenumber, adr); -} - #endif /* __CAPIUTIL_H__ */ diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h index 075fab5f92e1..94ba42bf9da1 100644 --- a/include/linux/kernelcapi.h +++ b/include/linux/kernelcapi.h @@ -10,46 +10,12 @@ #ifndef __KERNELCAPI_H__ #define __KERNELCAPI_H__ - #include #include #include #include #include -struct capi20_appl { - u16 applid; - capi_register_params rparam; - void (*recv_message)(struct capi20_appl *ap, struct sk_buff *skb); - void *private; - - /* internal to kernelcapi.o */ - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; - struct mutex recv_mtx; - struct sk_buff_head recv_queue; - struct work_struct recv_work; - int release_in_progress; -}; - -u16 capi20_isinstalled(void); -u16 capi20_register(struct capi20_appl *ap); -u16 capi20_release(struct capi20_appl *ap); -u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb); -u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]); -u16 capi20_get_version(u32 contr, struct capi_version *verp); -u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]); -u16 capi20_get_profile(u32 contr, struct capi_profile *profp); -int capi20_manufacturer(unsigned long cmd, void __user *data); - -#define CAPICTR_UP 0 -#define CAPICTR_DOWN 1 - -int register_capictr_notifier(struct notifier_block *nb); -int unregister_capictr_notifier(struct notifier_block *nb); - #define CAPI_NOERROR 0x0000 #define CAPI_TOOMANYAPPLS 0x1001 @@ -76,45 +42,4 @@ int unregister_capictr_notifier(struct notifier_block *nb); #define CAPI_MSGCTRLERNOTSUPPORTEXTEQUIP 0x110a #define CAPI_MSGCTRLERONLYSUPPORTEXTEQUIP 0x110b -typedef enum { - CapiMessageNotSupportedInCurrentState = 0x2001, - CapiIllContrPlciNcci = 0x2002, - CapiNoPlciAvailable = 0x2003, - CapiNoNcciAvailable = 0x2004, - CapiNoListenResourcesAvailable = 0x2005, - CapiNoFaxResourcesAvailable = 0x2006, - CapiIllMessageParmCoding = 0x2007, -} RESOURCE_CODING_PROBLEM; - -typedef enum { - CapiB1ProtocolNotSupported = 0x3001, - CapiB2ProtocolNotSupported = 0x3002, - CapiB3ProtocolNotSupported = 0x3003, - CapiB1ProtocolParameterNotSupported = 0x3004, - CapiB2ProtocolParameterNotSupported = 0x3005, - CapiB3ProtocolParameterNotSupported = 0x3006, - CapiBProtocolCombinationNotSupported = 0x3007, - CapiNcpiNotSupported = 0x3008, - CapiCipValueUnknown = 0x3009, - CapiFlagsNotSupported = 0x300a, - CapiFacilityNotSupported = 0x300b, - CapiDataLengthNotSupportedByCurrentProtocol = 0x300c, - CapiResetProcedureNotSupportedByCurrentProtocol = 0x300d, - CapiTeiAssignmentFailed = 0x300e, -} REQUESTED_SERVICES_PROBLEM; - -typedef enum { - CapiSuccess = 0x0000, - CapiSupplementaryServiceNotSupported = 0x300e, - CapiRequestNotAllowedInThisState = 0x3010, -} SUPPLEMENTARY_SERVICE_INFO; - -typedef enum { - CapiProtocolErrorLayer1 = 0x3301, - CapiProtocolErrorLayer2 = 0x3302, - CapiProtocolErrorLayer3 = 0x3303, - CapiTimeOut = 0x3303, // SuppServiceReason - CapiCallGivenToOtherApplication = 0x3304, -} CAPI_REASON; - #endif /* __KERNELCAPI_H__ */ diff --git a/include/uapi/linux/b1lli.h b/include/uapi/linux/b1lli.h deleted file mode 100644 index 4ae6ac9950df..000000000000 --- a/include/uapi/linux/b1lli.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* $Id: b1lli.h,v 1.8.8.3 2001/09/23 22:25:05 kai Exp $ - * - * ISDN lowlevel-module for AVM B1-card. - * - * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef _B1LLI_H_ -#define _B1LLI_H_ -/* - * struct for loading t4 file - */ -typedef struct avmb1_t4file { - int len; - unsigned char *data; -} avmb1_t4file; - -typedef struct avmb1_loaddef { - int contr; - avmb1_t4file t4file; -} avmb1_loaddef; - -typedef struct avmb1_loadandconfigdef { - int contr; - avmb1_t4file t4file; - avmb1_t4file t4config; -} avmb1_loadandconfigdef; - -typedef struct avmb1_resetdef { - int contr; -} avmb1_resetdef; - -typedef struct avmb1_getdef { - int contr; - int cardtype; - int cardstate; -} avmb1_getdef; - -/* - * struct for adding new cards - */ -typedef struct avmb1_carddef { - int port; - int irq; -} avmb1_carddef; - -#define AVM_CARDTYPE_B1 0 -#define AVM_CARDTYPE_T1 1 -#define AVM_CARDTYPE_M1 2 -#define AVM_CARDTYPE_M2 3 - -typedef struct avmb1_extcarddef { - int port; - int irq; - int cardtype; - int cardnr; /* for HEMA/T1 */ -} avmb1_extcarddef; - -#define AVMB1_LOAD 0 /* load image to card */ -#define AVMB1_ADDCARD 1 /* add a new card - OBSOLETE */ -#define AVMB1_RESETCARD 2 /* reset a card */ -#define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */ -#define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */ -#define AVMB1_GET_CARDINFO 5 /* get cardtype */ -#define AVMB1_REMOVECARD 6 /* remove a card - OBSOLETE */ - -#define AVMB1_REGISTERCARD_IS_OBSOLETE - -#endif /* _B1LLI_H_ */ -- cgit v1.2.3 From efdd6099c68a0d47242d491f19edc44ad9d575ed Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Tue, 19 Nov 2019 19:16:19 -0800 Subject: dt-bindings: rng: add BCM2711 RNG compatible The BCM2711 has a RNG200 block, so document its compatible string. Signed-off-by: Stefan Wahren Signed-off-by: Stephen Brennan Reviewed-by: Florian Fainelli Acked-by: Rob Herring Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/rng/brcm,iproc-rng200.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/rng/brcm,iproc-rng200.txt b/Documentation/devicetree/bindings/rng/brcm,iproc-rng200.txt index c223e54452da..802523196ee5 100644 --- a/Documentation/devicetree/bindings/rng/brcm,iproc-rng200.txt +++ b/Documentation/devicetree/bindings/rng/brcm,iproc-rng200.txt @@ -2,6 +2,7 @@ HWRNG support for the iproc-rng200 driver Required properties: - compatible : Must be one of: + "brcm,bcm2711-rng200" "brcm,bcm7211-rng200" "brcm,bcm7278-rng200" "brcm,iproc-rng200" -- cgit v1.2.3 From 91a71d612128f84f725022d7b7c5d5a741f6fdc7 Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Tue, 3 Dec 2019 14:31:12 -0500 Subject: padata: remove cpumask change notifier Since commit 63d3578892dc ("crypto: pcrypt - remove padata cpumask notifier") this feature is unused, so get rid of it. Signed-off-by: Daniel Jordan Cc: Eric Biggers Cc: Herbert Xu Cc: Jonathan Corbet Cc: Steffen Klassert Cc: linux-crypto@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Herbert Xu --- Documentation/padata.txt | 24 ---------------------- crypto/pcrypt.c | 1 - include/linux/padata.h | 11 ---------- kernel/padata.c | 52 +----------------------------------------------- 4 files changed, 1 insertion(+), 87 deletions(-) (limited to 'Documentation') diff --git a/Documentation/padata.txt b/Documentation/padata.txt index b37ba1eaace3..b45df9c6547b 100644 --- a/Documentation/padata.txt +++ b/Documentation/padata.txt @@ -75,30 +75,6 @@ To simply add or remove one CPU from a certain cpumask the functions padata_add_cpu/padata_remove_cpu are used. cpu specifies the CPU to add or remove and mask is one of PADATA_CPU_SERIAL, PADATA_CPU_PARALLEL. -If a user is interested in padata cpumask changes, he can register to -the padata cpumask change notifier:: - - int padata_register_cpumask_notifier(struct padata_instance *pinst, - struct notifier_block *nblock); - -To unregister from that notifier:: - - int padata_unregister_cpumask_notifier(struct padata_instance *pinst, - struct notifier_block *nblock); - -The padata cpumask change notifier notifies about changes of the usable -cpumasks, i.e. the subset of active CPUs in the user supplied cpumask. - -Padata calls the notifier chain with:: - - blocking_notifier_call_chain(&pinst->cpumask_change_notifier, - notification_mask, - &pd_new->cpumask); - -Here cpumask_change_notifier is registered notifier, notification_mask -is one of PADATA_CPU_SERIAL, PADATA_CPU_PARALLEL and cpumask is a pointer -to a struct padata_cpumask that contains the new cpumask information. - Actually submitting work to the padata instance requires the creation of a padata_priv structure:: diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index a4f3b3f342c8..d6696e217128 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/include/linux/padata.h b/include/linux/padata.h index cccab7a59787..178d5cc6b494 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #define PADATA_CPU_SERIAL 0x01 @@ -151,10 +150,6 @@ struct padata_shell { * @pslist: List of padata_shell objects attached to this instance. * @cpumask: User supplied cpumasks for parallel and serial works. * @rcpumask: Actual cpumasks based on user cpumask and cpu_online_mask. - * @omask: Temporary storage used to compute the notification mask. - * @cpumask_change_notifier: Notifiers chain for user-defined notify - * callbacks that will be called when either @pcpu or @cbcpu - * or both cpumasks change. * @kobj: padata instance kernel object. * @lock: padata instance lock. * @flags: padata flags. @@ -166,8 +161,6 @@ struct padata_instance { struct list_head pslist; struct padata_cpumask cpumask; struct padata_cpumask rcpumask; - cpumask_var_t omask; - struct blocking_notifier_head cpumask_change_notifier; struct kobject kobj; struct mutex lock; u8 flags; @@ -187,8 +180,4 @@ extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, cpumask_var_t cpumask); extern int padata_start(struct padata_instance *pinst); extern void padata_stop(struct padata_instance *pinst); -extern int padata_register_cpumask_notifier(struct padata_instance *pinst, - struct notifier_block *nblock); -extern int padata_unregister_cpumask_notifier(struct padata_instance *pinst, - struct notifier_block *nblock); #endif diff --git a/kernel/padata.c b/kernel/padata.c index f5964f015139..bc594c00b26e 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -514,23 +514,16 @@ static int padata_replace_one(struct padata_shell *ps) static int padata_replace(struct padata_instance *pinst) { - int notification_mask = 0; struct padata_shell *ps; int err; pinst->flags |= PADATA_RESET; - cpumask_copy(pinst->omask, pinst->rcpumask.pcpu); cpumask_and(pinst->rcpumask.pcpu, pinst->cpumask.pcpu, cpu_online_mask); - if (!cpumask_equal(pinst->omask, pinst->rcpumask.pcpu)) - notification_mask |= PADATA_CPU_PARALLEL; - cpumask_copy(pinst->omask, pinst->rcpumask.cbcpu); cpumask_and(pinst->rcpumask.cbcpu, pinst->cpumask.cbcpu, cpu_online_mask); - if (!cpumask_equal(pinst->omask, pinst->rcpumask.cbcpu)) - notification_mask |= PADATA_CPU_SERIAL; list_for_each_entry(ps, &pinst->pslist, list) { err = padata_replace_one(ps); @@ -544,48 +537,11 @@ static int padata_replace(struct padata_instance *pinst) if (atomic_dec_and_test(&ps->opd->refcnt)) padata_free_pd(ps->opd); - if (notification_mask) - blocking_notifier_call_chain(&pinst->cpumask_change_notifier, - notification_mask, - &pinst->cpumask); - pinst->flags &= ~PADATA_RESET; return err; } -/** - * padata_register_cpumask_notifier - Registers a notifier that will be called - * if either pcpu or cbcpu or both cpumasks change. - * - * @pinst: A poineter to padata instance - * @nblock: A pointer to notifier block. - */ -int padata_register_cpumask_notifier(struct padata_instance *pinst, - struct notifier_block *nblock) -{ - return blocking_notifier_chain_register(&pinst->cpumask_change_notifier, - nblock); -} -EXPORT_SYMBOL(padata_register_cpumask_notifier); - -/** - * padata_unregister_cpumask_notifier - Unregisters cpumask notifier - * registered earlier using padata_register_cpumask_notifier - * - * @pinst: A pointer to data instance. - * @nlock: A pointer to notifier block. - */ -int padata_unregister_cpumask_notifier(struct padata_instance *pinst, - struct notifier_block *nblock) -{ - return blocking_notifier_chain_unregister( - &pinst->cpumask_change_notifier, - nblock); -} -EXPORT_SYMBOL(padata_unregister_cpumask_notifier); - - /* If cpumask contains no active cpu, we mark the instance as invalid. */ static bool padata_validate_cpumask(struct padata_instance *pinst, const struct cpumask *cpumask) @@ -785,7 +741,6 @@ static void __padata_free(struct padata_instance *pinst) WARN_ON(!list_empty(&pinst->pslist)); padata_stop(pinst); - free_cpumask_var(pinst->omask); free_cpumask_var(pinst->rcpumask.cbcpu); free_cpumask_var(pinst->rcpumask.pcpu); free_cpumask_var(pinst->cpumask.pcpu); @@ -965,8 +920,6 @@ static struct padata_instance *padata_alloc(const char *name, goto err_free_masks; if (!alloc_cpumask_var(&pinst->rcpumask.cbcpu, GFP_KERNEL)) goto err_free_rcpumask_pcpu; - if (!alloc_cpumask_var(&pinst->omask, GFP_KERNEL)) - goto err_free_rcpumask_cbcpu; INIT_LIST_HEAD(&pinst->pslist); @@ -976,11 +929,10 @@ static struct padata_instance *padata_alloc(const char *name, cpumask_and(pinst->rcpumask.cbcpu, cbcpumask, cpu_online_mask); if (padata_setup_cpumasks(pinst)) - goto err_free_omask; + goto err_free_rcpumask_cbcpu; pinst->flags = 0; - BLOCKING_INIT_NOTIFIER_HEAD(&pinst->cpumask_change_notifier); kobject_init(&pinst->kobj, &padata_attr_type); mutex_init(&pinst->lock); @@ -994,8 +946,6 @@ static struct padata_instance *padata_alloc(const char *name, return pinst; -err_free_omask: - free_cpumask_var(pinst->omask); err_free_rcpumask_cbcpu: free_cpumask_var(pinst->rcpumask.cbcpu); err_free_rcpumask_pcpu: -- cgit v1.2.3 From bfcdcef8c8e3469f4d6c082a1da27a6ef77e5715 Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Tue, 3 Dec 2019 14:31:14 -0500 Subject: padata: update documentation Remove references to unused functions, standardize language, update to reflect new functionality, migrate to rst format, and fix all kernel-doc warnings. Fixes: 815613da6a67 ("kernel/padata.c: removed unused code") Signed-off-by: Daniel Jordan Cc: Eric Biggers Cc: Herbert Xu Cc: Jonathan Corbet Cc: Steffen Klassert Cc: linux-crypto@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Daniel Jordan Signed-off-by: Herbert Xu --- Documentation/core-api/index.rst | 1 + Documentation/core-api/padata.rst | 169 ++++++++++++++++++++++++++++++++++++++ Documentation/padata.txt | 139 ------------------------------- include/linux/padata.h | 15 ++-- kernel/padata.c | 35 +++++--- 5 files changed, 198 insertions(+), 161 deletions(-) create mode 100644 Documentation/core-api/padata.rst delete mode 100644 Documentation/padata.txt (limited to 'Documentation') diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index ab0eae1c153a..ab0b9ec85506 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -39,6 +39,7 @@ Core utilities ../RCU/index gcc-plugins symbol-namespaces + padata Interfaces for kernel debugging diff --git a/Documentation/core-api/padata.rst b/Documentation/core-api/padata.rst new file mode 100644 index 000000000000..9a24c111781d --- /dev/null +++ b/Documentation/core-api/padata.rst @@ -0,0 +1,169 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================================= +The padata parallel execution mechanism +======================================= + +:Date: December 2019 + +Padata is a mechanism by which the kernel can farm jobs out to be done in +parallel on multiple CPUs while retaining their ordering. It was developed for +use with the IPsec code, which needs to be able to perform encryption and +decryption on large numbers of packets without reordering those packets. The +crypto developers made a point of writing padata in a sufficiently general +fashion that it could be put to other uses as well. + +Usage +===== + +Initializing +------------ + +The first step in using padata is to set up a padata_instance structure for +overall control of how jobs are to be run:: + + #include + + struct padata_instance *padata_alloc_possible(const char *name); + +'name' simply identifies the instance. + +There are functions for enabling and disabling the instance:: + + int padata_start(struct padata_instance *pinst); + void padata_stop(struct padata_instance *pinst); + +These functions are setting or clearing the "PADATA_INIT" flag; if that flag is +not set, other functions will refuse to work. padata_start() returns zero on +success (flag set) or -EINVAL if the padata cpumask contains no active CPU +(flag not set). padata_stop() clears the flag and blocks until the padata +instance is unused. + +Finally, complete padata initialization by allocating a padata_shell:: + + struct padata_shell *padata_alloc_shell(struct padata_instance *pinst); + +A padata_shell is used to submit a job to padata and allows a series of such +jobs to be serialized independently. A padata_instance may have one or more +padata_shells associated with it, each allowing a separate series of jobs. + +Modifying cpumasks +------------------ + +The CPUs used to run jobs can be changed in two ways, programatically with +padata_set_cpumask() or via sysfs. The former is defined:: + + int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, + cpumask_var_t cpumask); + +Here cpumask_type is one of PADATA_CPU_PARALLEL or PADATA_CPU_SERIAL, where a +parallel cpumask describes which processors will be used to execute jobs +submitted to this instance in parallel and a serial cpumask defines which +processors are allowed to be used as the serialization callback processor. +cpumask specifies the new cpumask to use. + +There may be sysfs files for an instance's cpumasks. For example, pcrypt's +live in /sys/kernel/pcrypt/. Within an instance's directory +there are two files, parallel_cpumask and serial_cpumask, and either cpumask +may be changed by echoing a bitmask into the file, for example:: + + echo f > /sys/kernel/pcrypt/pencrypt/parallel_cpumask + +Reading one of these files shows the user-supplied cpumask, which may be +different from the 'usable' cpumask. + +Padata maintains two pairs of cpumasks internally, the user-supplied cpumasks +and the 'usable' cpumasks. (Each pair consists of a parallel and a serial +cpumask.) The user-supplied cpumasks default to all possible CPUs on instance +allocation and may be changed as above. The usable cpumasks are always a +subset of the user-supplied cpumasks and contain only the online CPUs in the +user-supplied masks; these are the cpumasks padata actually uses. So it is +legal to supply a cpumask to padata that contains offline CPUs. Once an +offline CPU in the user-supplied cpumask comes online, padata is going to use +it. + +Changing the CPU masks are expensive operations, so it should not be done with +great frequency. + +Running A Job +------------- + +Actually submitting work to the padata instance requires the creation of a +padata_priv structure, which represents one job:: + + struct padata_priv { + /* Other stuff here... */ + void (*parallel)(struct padata_priv *padata); + void (*serial)(struct padata_priv *padata); + }; + +This structure will almost certainly be embedded within some larger +structure specific to the work to be done. Most of its fields are private to +padata, but the structure should be zeroed at initialisation time, and the +parallel() and serial() functions should be provided. Those functions will +be called in the process of getting the work done as we will see +momentarily. + +The submission of the job is done with:: + + int padata_do_parallel(struct padata_shell *ps, + struct padata_priv *padata, int *cb_cpu); + +The ps and padata structures must be set up as described above; cb_cpu +points to the preferred CPU to be used for the final callback when the job is +done; it must be in the current instance's CPU mask (if not the cb_cpu pointer +is updated to point to the CPU actually chosen). The return value from +padata_do_parallel() is zero on success, indicating that the job is in +progress. -EBUSY means that somebody, somewhere else is messing with the +instance's CPU mask, while -EINVAL is a complaint about cb_cpu not being in the +serial cpumask, no online CPUs in the parallel or serial cpumasks, or a stopped +instance. + +Each job submitted to padata_do_parallel() will, in turn, be passed to +exactly one call to the above-mentioned parallel() function, on one CPU, so +true parallelism is achieved by submitting multiple jobs. parallel() runs with +software interrupts disabled and thus cannot sleep. The parallel() +function gets the padata_priv structure pointer as its lone parameter; +information about the actual work to be done is probably obtained by using +container_of() to find the enclosing structure. + +Note that parallel() has no return value; the padata subsystem assumes that +parallel() will take responsibility for the job from this point. The job +need not be completed during this call, but, if parallel() leaves work +outstanding, it should be prepared to be called again with a new job before +the previous one completes. + +Serializing Jobs +---------------- + +When a job does complete, parallel() (or whatever function actually finishes +the work) should inform padata of the fact with a call to:: + + void padata_do_serial(struct padata_priv *padata); + +At some point in the future, padata_do_serial() will trigger a call to the +serial() function in the padata_priv structure. That call will happen on +the CPU requested in the initial call to padata_do_parallel(); it, too, is +run with local software interrupts disabled. +Note that this call may be deferred for a while since the padata code takes +pains to ensure that jobs are completed in the order in which they were +submitted. + +Destroying +---------- + +Cleaning up a padata instance predictably involves calling the three free +functions that correspond to the allocation in reverse:: + + void padata_free_shell(struct padata_shell *ps); + void padata_stop(struct padata_instance *pinst); + void padata_free(struct padata_instance *pinst); + +It is the user's responsibility to ensure all outstanding jobs are complete +before any of the above are called. + +Interface +========= + +.. kernel-doc:: include/linux/padata.h +.. kernel-doc:: kernel/padata.c diff --git a/Documentation/padata.txt b/Documentation/padata.txt deleted file mode 100644 index b45df9c6547b..000000000000 --- a/Documentation/padata.txt +++ /dev/null @@ -1,139 +0,0 @@ -======================================= -The padata parallel execution mechanism -======================================= - -:Last updated: for 2.6.36 - -Padata is a mechanism by which the kernel can farm work out to be done in -parallel on multiple CPUs while retaining the ordering of tasks. It was -developed for use with the IPsec code, which needs to be able to perform -encryption and decryption on large numbers of packets without reordering -those packets. The crypto developers made a point of writing padata in a -sufficiently general fashion that it could be put to other uses as well. - -The first step in using padata is to set up a padata_instance structure for -overall control of how tasks are to be run:: - - #include - - struct padata_instance *padata_alloc(const char *name, - const struct cpumask *pcpumask, - const struct cpumask *cbcpumask); - -'name' simply identifies the instance. - -The pcpumask describes which processors will be used to execute work -submitted to this instance in parallel. The cbcpumask defines which -processors are allowed to be used as the serialization callback processor. -The workqueue wq is where the work will actually be done; it should be -a multithreaded queue, naturally. - -To allocate a padata instance with the cpu_possible_mask for both -cpumasks this helper function can be used:: - - struct padata_instance *padata_alloc_possible(struct workqueue_struct *wq); - -Note: Padata maintains two kinds of cpumasks internally. The user supplied -cpumasks, submitted by padata_alloc/padata_alloc_possible and the 'usable' -cpumasks. The usable cpumasks are always a subset of active CPUs in the -user supplied cpumasks; these are the cpumasks padata actually uses. So -it is legal to supply a cpumask to padata that contains offline CPUs. -Once an offline CPU in the user supplied cpumask comes online, padata -is going to use it. - -There are functions for enabling and disabling the instance:: - - int padata_start(struct padata_instance *pinst); - void padata_stop(struct padata_instance *pinst); - -These functions are setting or clearing the "PADATA_INIT" flag; -if that flag is not set, other functions will refuse to work. -padata_start returns zero on success (flag set) or -EINVAL if the -padata cpumask contains no active CPU (flag not set). -padata_stop clears the flag and blocks until the padata instance -is unused. - -The list of CPUs to be used can be adjusted with these functions:: - - int padata_set_cpumasks(struct padata_instance *pinst, - cpumask_var_t pcpumask, - cpumask_var_t cbcpumask); - int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, - cpumask_var_t cpumask); - int padata_add_cpu(struct padata_instance *pinst, int cpu, int mask); - int padata_remove_cpu(struct padata_instance *pinst, int cpu, int mask); - -Changing the CPU masks are expensive operations, though, so it should not be -done with great frequency. - -It's possible to change both cpumasks of a padata instance with -padata_set_cpumasks by specifying the cpumasks for parallel execution (pcpumask) -and for the serial callback function (cbcpumask). padata_set_cpumask is used to -change just one of the cpumasks. Here cpumask_type is one of PADATA_CPU_SERIAL, -PADATA_CPU_PARALLEL and cpumask specifies the new cpumask to use. -To simply add or remove one CPU from a certain cpumask the functions -padata_add_cpu/padata_remove_cpu are used. cpu specifies the CPU to add or -remove and mask is one of PADATA_CPU_SERIAL, PADATA_CPU_PARALLEL. - -Actually submitting work to the padata instance requires the creation of a -padata_priv structure:: - - struct padata_priv { - /* Other stuff here... */ - void (*parallel)(struct padata_priv *padata); - void (*serial)(struct padata_priv *padata); - }; - -This structure will almost certainly be embedded within some larger -structure specific to the work to be done. Most of its fields are private to -padata, but the structure should be zeroed at initialisation time, and the -parallel() and serial() functions should be provided. Those functions will -be called in the process of getting the work done as we will see -momentarily. - -The submission of work is done with:: - - int padata_do_parallel(struct padata_instance *pinst, - struct padata_priv *padata, int cb_cpu); - -The pinst and padata structures must be set up as described above; cb_cpu -specifies which CPU will be used for the final callback when the work is -done; it must be in the current instance's CPU mask. The return value from -padata_do_parallel() is zero on success, indicating that the work is in -progress. -EBUSY means that somebody, somewhere else is messing with the -instance's CPU mask, while -EINVAL is a complaint about cb_cpu not being -in that CPU mask or about a not running instance. - -Each task submitted to padata_do_parallel() will, in turn, be passed to -exactly one call to the above-mentioned parallel() function, on one CPU, so -true parallelism is achieved by submitting multiple tasks. parallel() runs with -software interrupts disabled and thus cannot sleep. The parallel() -function gets the padata_priv structure pointer as its lone parameter; -information about the actual work to be done is probably obtained by using -container_of() to find the enclosing structure. - -Note that parallel() has no return value; the padata subsystem assumes that -parallel() will take responsibility for the task from this point. The work -need not be completed during this call, but, if parallel() leaves work -outstanding, it should be prepared to be called again with a new job before -the previous one completes. When a task does complete, parallel() (or -whatever function actually finishes the job) should inform padata of the -fact with a call to:: - - void padata_do_serial(struct padata_priv *padata); - -At some point in the future, padata_do_serial() will trigger a call to the -serial() function in the padata_priv structure. That call will happen on -the CPU requested in the initial call to padata_do_parallel(); it, too, is -run with local software interrupts disabled. -Note that this call may be deferred for a while since the padata code takes -pains to ensure that tasks are completed in the order in which they were -submitted. - -The one remaining function in the padata API should be called to clean up -when a padata instance is no longer needed:: - - void padata_free(struct padata_instance *pinst); - -This function will busy-wait while any remaining tasks are completed, so it -might be best not to call it while there is work outstanding. diff --git a/include/linux/padata.h b/include/linux/padata.h index faa2e36832f8..a0d8b41850b2 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -19,7 +19,7 @@ #define PADATA_CPU_PARALLEL 0x02 /** - * struct padata_priv - Embedded to the users data structure. + * struct padata_priv - Represents one job * * @list: List entry, to attach to the padata lists. * @pd: Pointer to the internal control structure. @@ -42,7 +42,7 @@ struct padata_priv { }; /** - * struct padata_list + * struct padata_list - one per work type per CPU * * @list: List head. * @lock: List lock. @@ -70,9 +70,6 @@ struct padata_serial_queue { * * @parallel: List to wait for parallelization. * @reorder: List to wait for reordering after parallel processing. - * @serial: List to wait for serialization after reordering. - * @pwork: work struct for parallelization. - * @swork: work struct for serialization. * @work: work struct for parallelization. * @num_obj: Number of objects that are processed by this cpu. */ @@ -98,11 +95,11 @@ struct padata_cpumask { * struct parallel_data - Internal control structure, covers everything * that depends on the cpumask in use. * - * @sh: padata_shell object. + * @ps: padata_shell object. * @pqueue: percpu padata queues used for parallelization. * @squeue: percpu padata queues used for serialuzation. * @refcnt: Number of objects holding a reference on this parallel_data. - * @max_seq_nr: Maximal used sequence number. + * @seq_nr: Sequence number of the parallelized data object. * @processed: Number of already processed objects. * @cpu: Next CPU to be processed. * @cpumask: The cpumasks in use for parallel and serial workers. @@ -119,7 +116,7 @@ struct parallel_data { int cpu; struct padata_cpumask cpumask; struct work_struct reorder_work; - spinlock_t lock ____cacheline_aligned; + spinlock_t ____cacheline_aligned lock; }; /** @@ -142,7 +139,7 @@ struct padata_shell { /** * struct padata_instance - The overall control structure. * - * @cpu_notifier: cpu hotplug notifier. + * @node: Used by CPU hotplug. * @parallel_wq: The workqueue used for parallel work. * @serial_wq: The workqueue used for serial work. * @pslist: List of padata_shell objects attached to this instance. diff --git a/kernel/padata.c b/kernel/padata.c index db950d287b3d..72777c10bb9c 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -2,7 +2,7 @@ /* * padata.c - generic interface to process data streams in parallel * - * See Documentation/padata.txt for an api documentation. + * See Documentation/core-api/padata.rst for more information. * * Copyright (C) 2008, 2009 secunet Security Networks AG * Copyright (C) 2008, 2009 Steffen Klassert @@ -99,6 +99,8 @@ static void padata_parallel_worker(struct work_struct *parallel_work) * The parallelization callback function will run with BHs off. * Note: Every object which is parallelized by padata_do_parallel * must be seen by padata_do_serial. + * + * Return: 0 on success or else negative error code. */ int padata_do_parallel(struct padata_shell *ps, struct padata_priv *padata, int *cb_cpu) @@ -163,14 +165,12 @@ EXPORT_SYMBOL(padata_do_parallel); /* * padata_find_next - Find the next object that needs serialization. * - * Return values are: - * - * A pointer to the control struct of the next object that needs - * serialization, if present in one of the percpu reorder queues. - * - * NULL, if the next object that needs serialization will - * be parallel processed by another cpu and is not yet present in - * the cpu's reorder queue. + * Return: + * * A pointer to the control struct of the next object that needs + * serialization, if present in one of the percpu reorder queues. + * * NULL, if the next object that needs serialization will + * be parallel processed by another cpu and is not yet present in + * the cpu's reorder queue. */ static struct padata_priv *padata_find_next(struct parallel_data *pd, bool remove_object) @@ -582,13 +582,14 @@ out_replace: } /** - * padata_set_cpumask: Sets specified by @cpumask_type cpumask to the value - * equivalent to @cpumask. - * + * padata_set_cpumask - Sets specified by @cpumask_type cpumask to the value + * equivalent to @cpumask. * @pinst: padata instance * @cpumask_type: PADATA_CPU_SERIAL or PADATA_CPU_PARALLEL corresponding * to parallel and serial cpumasks respectively. * @cpumask: the cpumask to use + * + * Return: 0 on success or negative error code */ int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type, cpumask_var_t cpumask) @@ -626,6 +627,8 @@ EXPORT_SYMBOL(padata_set_cpumask); * padata_start - start the parallel processing * * @pinst: padata instance to start + * + * Return: 0 on success or negative error code */ int padata_start(struct padata_instance *pinst) { @@ -880,6 +883,8 @@ static struct kobj_type padata_attr_type = { * @name: used to identify the instance * @pcpumask: cpumask that will be used for padata parallelization * @cbcpumask: cpumask that will be used for padata serialization + * + * Return: new instance on success, NULL on error */ static struct padata_instance *padata_alloc(const char *name, const struct cpumask *pcpumask, @@ -967,6 +972,8 @@ err: * parallel workers. * * @name: used to identify the instance + * + * Return: new instance on success, NULL on error */ struct padata_instance *padata_alloc_possible(const char *name) { @@ -977,7 +984,7 @@ EXPORT_SYMBOL(padata_alloc_possible); /** * padata_free - free a padata instance * - * @padata_inst: padata instance to free + * @pinst: padata instance to free */ void padata_free(struct padata_instance *pinst) { @@ -989,6 +996,8 @@ EXPORT_SYMBOL(padata_free); * padata_alloc_shell - Allocate and initialize padata shell. * * @pinst: Parent padata_instance object. + * + * Return: new shell on success, NULL on error */ struct padata_shell *padata_alloc_shell(struct padata_instance *pinst) { -- cgit v1.2.3 From 4a2abbc6b8683dd8ac399d305b23409a7a7503d3 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 6 Dec 2019 20:19:37 -0800 Subject: crypto: doc - remove references to ARC4 arc4 is no longer considered secure, so it shouldn't be used, even as just an example. Mention serpent and chacha20 instead. Signed-off-by: Eric Biggers Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- Documentation/crypto/devel-algos.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/crypto/devel-algos.rst b/Documentation/crypto/devel-algos.rst index f9d288015acc..fb6b7979a1de 100644 --- a/Documentation/crypto/devel-algos.rst +++ b/Documentation/crypto/devel-algos.rst @@ -57,7 +57,7 @@ follows: Single-Block Symmetric Ciphers [CIPHER] --------------------------------------- -Example of transformations: aes, arc4, ... +Example of transformations: aes, serpent, ... This section describes the simplest of all transformation implementations, that being the CIPHER type used for symmetric ciphers. @@ -108,7 +108,7 @@ is also valid: Multi-Block Ciphers ------------------- -Example of transformations: cbc(aes), ecb(arc4), ... +Example of transformations: cbc(aes), chacha20, ... This section describes the multi-block cipher transformation implementations. The multi-block ciphers are used for transformations -- cgit v1.2.3 From 6a85afe4bc88fa9cbb0c1e76efd0d2588b2b572c Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 19 Nov 2019 18:53:12 +0100 Subject: dt-bindings: pwm: allwinner: Add H6 PWM description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit H6 PWM block is basically the same as A20 PWM, except that it also has bus clock and reset line which needs to be handled accordingly. Expand Allwinner PWM binding with H6 PWM specifics. Signed-off-by: Jernej Skrabec Reviewed-by: Rob Herring Signed-off-by: Clément Péron Signed-off-by: Maxime Ripard --- .../bindings/pwm/allwinner,sun4i-a10-pwm.yaml | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml b/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml index 0ac52f83a58c..fab89f052450 100644 --- a/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml @@ -30,13 +30,51 @@ properties: - items: - const: allwinner,sun50i-h5-pwm - const: allwinner,sun5i-a13-pwm + - const: allwinner,sun50i-h6-pwm reg: maxItems: 1 clocks: + minItems: 1 + maxItems: 2 + items: + - description: Module Clock + - description: Bus Clock + + # Even though it only applies to subschemas under the conditionals, + # not listing them here will trigger a warning because of the + # additionalsProperties set to false. + clock-names: true + + resets: maxItems: 1 +if: + properties: + compatible: + contains: + const: allwinner,sun50i-h6-pwm + +then: + properties: + clocks: + maxItems: 2 + + clock-names: + items: + - const: mod + - const: bus + + required: + - clock-names + - resets + +else: + properties: + clocks: + maxItems: 1 + required: - "#pwm-cells" - compatible @@ -54,4 +92,17 @@ examples: #pwm-cells = <3>; }; + - | + #include + #include + + pwm@300a000 { + compatible = "allwinner,sun50i-h6-pwm"; + reg = <0x0300a000 0x400>; + clocks = <&osc24M>, <&ccu CLK_BUS_PWM>; + clock-names = "mod", "bus"; + resets = <&ccu RST_BUS_PWM>; + #pwm-cells = <3>; + }; + ... -- cgit v1.2.3 From 51b6fe7e66eee0fe353ff8157c64d16b971fac39 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 17 Nov 2019 15:07:30 +0100 Subject: dt-bindings: clock: add the Amlogic Meson8 DDR clock controller binding Amlogic Meson8, Meson8b and Meson8m2 SoCs have a DDR clock controller in the MMCBUS registers. There is no public documentation on this, but the GPL u-boot sources from the Amlogic BSP show that: - it uses the same XTAL input as the main clock controller - it contains a PLL which seems to be implemented just like the other PLLs in this SoC - there is a power-of-two PLL post-divider Add the documentation and header file for this DDR clock controller. Reviewed-by: Rob Herring Acked-by: Stephen Boyd Signed-off-by: Martin Blumenstingl Signed-off-by: Jerome Brunet --- .../bindings/clock/amlogic,meson8-ddr-clkc.yaml | 50 ++++++++++++++++++++++ include/dt-bindings/clock/meson8-ddr-clkc.h | 4 ++ 2 files changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml create mode 100644 include/dt-bindings/clock/meson8-ddr-clkc.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml new file mode 100644 index 000000000000..4b8669f870ec --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,meson8-ddr-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic DDR Clock Controller Device Tree Bindings + +maintainers: + - Martin Blumenstingl + +properties: + compatible: + enum: + - amlogic,meson8-ddr-clkc + - amlogic,meson8b-ddr-clkc + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: xtal + + "#clock-cells": + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - "#clock-cells" + +additionalProperties: false + +examples: + - | + ddr_clkc: clock-controller@400 { + compatible = "amlogic,meson8-ddr-clkc"; + reg = <0x400 0x20>; + clocks = <&xtal>; + clock-names = "xtal"; + #clock-cells = <1>; + }; + +... diff --git a/include/dt-bindings/clock/meson8-ddr-clkc.h b/include/dt-bindings/clock/meson8-ddr-clkc.h new file mode 100644 index 000000000000..a8e0fa2987ab --- /dev/null +++ b/include/dt-bindings/clock/meson8-ddr-clkc.h @@ -0,0 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#define DDR_CLKID_DDR_PLL_DCO 0 +#define DDR_CLKID_DDR_PLL 1 -- cgit v1.2.3 From 25d316989e2b1beebaa69e6c3e76e762776c93de Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sun, 17 Nov 2019 14:59:23 +0100 Subject: dt-bindings: clock: meson8b: add the clock inputs The clock controller on Meson8/Meson8b/Meson8m2 has three (known) inputs: - "xtal": the main 24MHz crystal - "ddr_pll": some of the audio clocks use the output of the DDR PLL as input - "clk_32k": an optional clock signal which can be connected to GPIOAO_6 (which then has to be switched to the CLK_32K_IN function) Add the inputs to the documentation so we can wire up these inputs in a follow-up patch. Reviewed-by: Rob Herring Signed-off-by: Martin Blumenstingl Signed-off-by: Jerome Brunet --- Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt index 4d94091c1d2d..cc51e4746b3b 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt @@ -11,6 +11,11 @@ Required Properties: - "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs - #clock-cells: should be 1. - #reset-cells: should be 1. +- clocks: list of clock phandles, one for each entry in clock-names +- clock-names: should contain the following: + * "xtal": the 24MHz system oscillator + * "ddr_pll": the DDR PLL clock + * "clk_32k": (if present) the 32kHz clock signal from GPIOAO_6 (CLK_32K_IN) Parent node should have the following properties : - compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon" -- cgit v1.2.3 From 042f057fe2dcf38682d85d9f88df00d1a8d45dbd Mon Sep 17 00:00:00 2001 From: Vijay Khemka Date: Wed, 11 Dec 2019 10:56:04 -0800 Subject: drivers: ipmi: Support raw i2c packet in IPMB Many IPMB devices don't support smbus protocol and this driver only supports the smbus protocol at the moment. Added support for the i2c protocol as well. There will be a variable "i2c-protocol" passed by the device tree or ACPI table which determines whether the protocol is i2c or smbus. Signed-off-by: Vijay Khemka Reviewed-by: Asmaa Mnebhi Message-Id: <20191211185604.1266063-1-vijaykhemka@fb.com> [IPMB.txt had moved to driver-api/ipmb.rst, I adjusted] Signed-off-by: Corey Minyard --- Documentation/driver-api/ipmb.rst | 4 ++++ drivers/char/ipmi/ipmb_dev_int.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) (limited to 'Documentation') diff --git a/Documentation/driver-api/ipmb.rst b/Documentation/driver-api/ipmb.rst index 3ec3baed84c4..209c49e05116 100644 --- a/Documentation/driver-api/ipmb.rst +++ b/Documentation/driver-api/ipmb.rst @@ -71,9 +71,13 @@ b) Example for device tree:: ipmb@10 { compatible = "ipmb-dev"; reg = <0x10>; + i2c-protocol; }; }; +If xmit of data to be done using raw i2c block vs smbus +then "i2c-protocol" needs to be defined as above. + 2) Manually from Linux:: modprobe ipmb-dev-int diff --git a/drivers/char/ipmi/ipmb_dev_int.c b/drivers/char/ipmi/ipmb_dev_int.c index 1ff4fb1def7c..86674292b213 100644 --- a/drivers/char/ipmi/ipmb_dev_int.c +++ b/drivers/char/ipmi/ipmb_dev_int.c @@ -63,6 +63,7 @@ struct ipmb_dev { spinlock_t lock; wait_queue_head_t wait_queue; struct mutex file_mutex; + bool is_i2c_protocol; }; static inline struct ipmb_dev *to_ipmb_dev(struct file *file) @@ -112,6 +113,25 @@ static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count, return ret < 0 ? ret : count; } +static int ipmb_i2c_write(struct i2c_client *client, u8 *msg, u8 addr) +{ + struct i2c_msg i2c_msg; + + /* + * subtract 1 byte (rq_sa) from the length of the msg passed to + * raw i2c_transfer + */ + i2c_msg.len = msg[IPMB_MSG_LEN_IDX] - 1; + + /* Assign message to buffer except first 2 bytes (length and address) */ + i2c_msg.buf = msg + 2; + + i2c_msg.addr = addr; + i2c_msg.flags = client->flags & I2C_CLIENT_PEC; + + return i2c_transfer(client->adapter, &i2c_msg, 1); +} + static ssize_t ipmb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -133,6 +153,12 @@ static ssize_t ipmb_write(struct file *file, const char __user *buf, rq_sa = GET_7BIT_ADDR(msg[RQ_SA_8BIT_IDX]); netf_rq_lun = msg[NETFN_LUN_IDX]; + /* Check i2c block transfer vs smbus */ + if (ipmb_dev->is_i2c_protocol) { + ret = ipmb_i2c_write(ipmb_dev->client, msg, rq_sa); + return (ret == 1) ? count : ret; + } + /* * subtract rq_sa and netf_rq_lun from the length of the msg passed to * i2c_smbus_xfer @@ -302,6 +328,9 @@ static int ipmb_probe(struct i2c_client *client, if (ret) return ret; + ipmb_dev->is_i2c_protocol + = device_property_read_bool(&client->dev, "i2c-protocol"); + ipmb_dev->client = client; i2c_set_clientdata(client, ipmb_dev); ret = i2c_slave_register(client, ipmb_slave_cb); -- cgit v1.2.3 From 18ec173d56a13d239dfabe9fe67c36edaa155847 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 18 Nov 2019 17:40:08 +0000 Subject: dt-bindings: power: Add rpmh power-domain bindings for SM8150 Add RPMH power-domain bindings for the SM8150 family of SoCs. Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Reviewed-by: Rajendra Nayak Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/0101016e7f99ad2b-2bce2fac-2f02-4b3f-ac64-09942f7251ea-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/power/qcom,rpmpd.txt | 1 + include/dt-bindings/power/qcom-rpmpd.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt index bc75bf49cdae..f3bbaa4aef29 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -10,6 +10,7 @@ Required Properties: * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC + * qcom,sm8150-rpmhpd: RPMh Power domain for the sm8150 family of SoC - #power-domain-cells: number of cells in Power domain specifier must be 1. - operating-points-v2: Phandle to the OPP table for the Power domain. diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index f05f8b1808ec..7d43bafc0026 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -15,12 +15,26 @@ #define SDM845_GFX 7 #define SDM845_MSS 8 +/* SM8150 Power Domain Indexes */ +#define SM8150_MSS 0 +#define SM8150_EBI 1 +#define SM8150_LMX 2 +#define SM8150_LCX 3 +#define SM8150_GFX 4 +#define SM8150_MX 5 +#define SM8150_MX_AO 6 +#define SM8150_CX 7 +#define SM8150_CX_AO 8 +#define SM8150_MMCX 9 +#define SM8150_MMCX_AO 10 + /* SDM845 Power Domain performance levels */ #define RPMH_REGULATOR_LEVEL_RETENTION 16 #define RPMH_REGULATOR_LEVEL_MIN_SVS 48 #define RPMH_REGULATOR_LEVEL_LOW_SVS 64 #define RPMH_REGULATOR_LEVEL_SVS 128 #define RPMH_REGULATOR_LEVEL_SVS_L1 192 +#define RPMH_REGULATOR_LEVEL_SVS_L2 224 #define RPMH_REGULATOR_LEVEL_NOM 256 #define RPMH_REGULATOR_LEVEL_NOM_L1 320 #define RPMH_REGULATOR_LEVEL_NOM_L2 336 -- cgit v1.2.3 From 52a4cb577bde6e69fae451c10c8b2ec69033263a Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 18 Nov 2019 17:40:15 +0000 Subject: dt-bindings: power: Add rpmh power-domain bindings for sc7180 Add RPMH power-domain bindings for the SC7180 family of SoCs. Reviewed-by: Stephen Boyd Reviewed-by: Rajendra Nayak Reviewed-by: Bjorn Andersson Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/0101016e7f99ca4e-47d442f4-b923-4eea-b812-898e5476beab-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/power/qcom,rpmpd.txt | 1 + include/dt-bindings/power/qcom-rpmpd.h | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt index f3bbaa4aef29..6346d00b1b40 100644 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt @@ -9,6 +9,7 @@ Required Properties: * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC + * qcom,sc7180-rpmhpd: RPMh Power domain for the sc7180 family of SoC * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC * qcom,sm8150-rpmhpd: RPMh Power domain for the sm8150 family of SoC - #power-domain-cells: number of cells in Power domain specifier diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 7d43bafc0026..3f74096d5a7c 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -28,6 +28,16 @@ #define SM8150_MMCX 9 #define SM8150_MMCX_AO 10 +/* SC7180 Power Domain Indexes */ +#define SC7180_CX 0 +#define SC7180_CX_AO 1 +#define SC7180_GFX 2 +#define SC7180_MX 3 +#define SC7180_MX_AO 4 +#define SC7180_LMX 5 +#define SC7180_LCX 6 +#define SC7180_MSS 7 + /* SDM845 Power Domain performance levels */ #define RPMH_REGULATOR_LEVEL_RETENTION 16 #define RPMH_REGULATOR_LEVEL_MIN_SVS 48 -- cgit v1.2.3 From 5808611cccb28044940d04ebd303dc90f33b77b1 Mon Sep 17 00:00:00 2001 From: Lakshmi Ramasubramanian Date: Wed, 11 Dec 2019 08:47:03 -0800 Subject: IMA: Add KEY_CHECK func to measure keys Measure keys loaded onto any keyring. This patch defines a new IMA policy func namely KEY_CHECK to measure keys. Updated ima_match_rules() to check for KEY_CHECK and ima_parse_rule() to handle KEY_CHECK. Signed-off-by: Lakshmi Ramasubramanian Signed-off-by: Mimi Zohar --- Documentation/ABI/testing/ima_policy | 6 +++++- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_policy.c | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 29aaedf33246..066d32797500 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -29,7 +29,7 @@ Description: base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] - [KEXEC_CMDLINE] + [KEXEC_CMDLINE] [KEY_CHECK] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] [[^]MAY_EXEC] fsmagic:= hex value @@ -113,3 +113,7 @@ Description: Example of appraise rule allowing modsig appended signatures: appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig + + Example of measure rule using KEY_CHECK to measure all keys: + + measure func=KEY_CHECK diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index df4ca482fb53..fe6c698617bd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -193,6 +193,7 @@ static inline unsigned long ima_hash_key(u8 *digest) hook(KEXEC_INITRAMFS_CHECK) \ hook(POLICY_CHECK) \ hook(KEXEC_CMDLINE) \ + hook(KEY_CHECK) \ hook(MAX_CHECK) #define __ima_hook_enumify(ENUM) ENUM, diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index f19a895ad7cd..1525a28fd705 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -373,7 +373,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, { int i; - if (func == KEXEC_CMDLINE) { + if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) { if ((rule->flags & IMA_FUNC) && (rule->func == func)) return true; return false; @@ -997,6 +997,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) entry->func = POLICY_CHECK; else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0) entry->func = KEXEC_CMDLINE; + else if (strcmp(args[0].from, "KEY_CHECK") == 0) + entry->func = KEY_CHECK; else result = -EINVAL; if (!result) -- cgit v1.2.3 From e9085e0ad38a333012629d815c203155d61ebe7e Mon Sep 17 00:00:00 2001 From: Lakshmi Ramasubramanian Date: Wed, 11 Dec 2019 08:47:06 -0800 Subject: IMA: Add support to limit measuring keys Limit measuring keys to those keys being loaded onto a given set of keyrings only and when the user id (uid) matches if uid is specified in the policy. This patch defines a new IMA policy option namely "keyrings=" that can be used to specify a set of keyrings. If this option is specified in the policy for "measure func=KEY_CHECK" then only the keys loaded onto a keyring given in the "keyrings=" option are measured. If uid is specified in the policy then the key is measured only if the current user id matches the one specified in the policy. Added a new parameter namely "keyring" (name of the keyring) to process_buffer_measurement(). The keyring name is passed to ima_get_action() to determine the required action. ima_match_rules() is updated to check keyring in the policy, if specified, for KEY_CHECK function. Signed-off-by: Lakshmi Ramasubramanian Signed-off-by: Mimi Zohar --- Documentation/ABI/testing/ima_policy | 10 ++++- security/integrity/ima/ima.h | 8 ++-- security/integrity/ima/ima_api.c | 8 ++-- security/integrity/ima/ima_appraise.c | 4 +- security/integrity/ima/ima_asymmetric_keys.c | 8 +++- security/integrity/ima/ima_main.c | 9 ++-- security/integrity/ima/ima_policy.c | 62 ++++++++++++++++++++++++++-- 7 files changed, 91 insertions(+), 18 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 066d32797500..cd572912c593 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -25,7 +25,7 @@ Description: lsm: [[subj_user=] [subj_role=] [subj_type=] [obj_user=] [obj_role=] [obj_type=]] option: [[appraise_type=]] [template=] [permit_directio] - [appraise_flag=] + [appraise_flag=] [keyrings=] base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] @@ -42,6 +42,9 @@ Description: appraise_flag:= [check_blacklist] Currently, blacklist check is only for files signed with appended signature. + keyrings:= list of keyrings + (eg, .builtin_trusted_keys|.ima). Only valid + when action is "measure" and func is KEY_CHECK. template:= name of a defined IMA template type (eg, ima-ng). Only valid when action is "measure". pcr:= decimal value @@ -117,3 +120,8 @@ Description: Example of measure rule using KEY_CHECK to measure all keys: measure func=KEY_CHECK + + Example of measure rule using KEY_CHECK to only measure + keys added to .builtin_trusted_keys or .ima keyring: + + measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index fe6c698617bd..f06238e41a7c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -208,7 +208,8 @@ struct modsig; /* LIM API function definitions */ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, - struct ima_template_desc **template_desc); + struct ima_template_desc **template_desc, + const char *keyring); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct integrity_iint_cache *iint, struct file *file, void *buf, loff_t size, @@ -220,7 +221,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, struct ima_template_desc *template_desc); void process_buffer_measurement(const void *buf, int size, const char *eventname, enum ima_hooks func, - int pcr); + int pcr, const char *keyring); void ima_audit_measurement(struct integrity_iint_cache *iint, const unsigned char *filename); int ima_alloc_init_template(struct ima_event_data *event_data, @@ -235,7 +236,8 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename); /* IMA policy related functions */ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, - struct ima_template_desc **template_desc); + struct ima_template_desc **template_desc, + const char *keyring); void ima_init_policy(void); void ima_update_policy(void); void ima_update_policy_flag(void); diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 610759fe63b8..f6bc00914aa5 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -169,12 +169,13 @@ err_out: * @func: caller identifier * @pcr: pointer filled in if matched measure policy sets pcr= * @template_desc: pointer filled in if matched measure policy sets template= + * @keyring: keyring name used to determine the action * * The policy is defined in terms of keypairs: * subj=, obj=, type=, func=, mask=, fsmagic= * subj,obj, and type: are LSM specific. * func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK - * | KEXEC_CMDLINE + * | KEXEC_CMDLINE | KEY_CHECK * mask: contains the permission mask * fsmagic: hex value * @@ -183,14 +184,15 @@ err_out: */ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, int mask, enum ima_hooks func, int *pcr, - struct ima_template_desc **template_desc) + struct ima_template_desc **template_desc, + const char *keyring) { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH; flags &= ima_policy_flag; return ima_match_policy(inode, cred, secid, func, mask, flags, pcr, - template_desc); + template_desc, keyring); } /* diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 300c8d2943c5..a9649b04b9f1 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -55,7 +55,7 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func) security_task_getsecid(current, &secid); return ima_match_policy(inode, current_cred(), secid, func, mask, - IMA_APPRAISE | IMA_HASH, NULL, NULL); + IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL); } static int ima_fix_xattr(struct dentry *dentry, @@ -330,7 +330,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint, if ((rc == -EPERM) && (iint->flags & IMA_MEASURE)) process_buffer_measurement(digest, digestsize, "blacklisted-hash", NONE, - pcr); + pcr, NULL); } return rc; diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c index 994d89d58af9..fea2e7dd3b09 100644 --- a/security/integrity/ima/ima_asymmetric_keys.c +++ b/security/integrity/ima/ima_asymmetric_keys.c @@ -46,7 +46,13 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key, * parameter to process_buffer_measurement() and is set * in the "eventname" field in ima_event_data for * the key measurement IMA event. + * + * The name of the keyring is also passed in the "keyring" + * parameter to process_buffer_measurement() to check + * if the IMA policy is configured to measure a key linked + * to the given keyring. */ process_buffer_measurement(payload, payload_len, - keyring->description, KEY_CHECK, 0); + keyring->description, KEY_CHECK, 0, + keyring->description); } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9b35db2fc777..2272c3255c7d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -215,7 +215,7 @@ static int process_measurement(struct file *file, const struct cred *cred, * Included is the appraise submask. */ action = ima_get_action(inode, cred, secid, mask, func, &pcr, - &template_desc); + &template_desc, NULL); violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) @@ -632,12 +632,13 @@ int ima_load_data(enum kernel_load_data_id id) * @eventname: event name to be used for the buffer entry. * @func: IMA hook * @pcr: pcr to extend the measurement + * @keyring: keyring name to determine the action to be performed * * Based on policy, the buffer is measured into the ima log. */ void process_buffer_measurement(const void *buf, int size, const char *eventname, enum ima_hooks func, - int pcr) + int pcr, const char *keyring) { int ret = 0; struct ima_template_entry *entry = NULL; @@ -668,7 +669,7 @@ void process_buffer_measurement(const void *buf, int size, if (func) { security_task_getsecid(current, &secid); action = ima_get_action(NULL, current_cred(), secid, 0, func, - &pcr, &template); + &pcr, &template, keyring); if (!(action & IMA_MEASURE)) return; } @@ -721,7 +722,7 @@ void ima_kexec_cmdline(const void *buf, int size) { if (buf && size != 0) process_buffer_measurement(buf, size, "kexec-cmdline", - KEXEC_CMDLINE, 0); + KEXEC_CMDLINE, 0, NULL); } static int __init init_ima(void) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 1525a28fd705..cca87c499c4f 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -79,6 +79,7 @@ struct ima_rule_entry { int type; /* audit type */ } lsm[MAX_LSM_RULES]; char *fsname; + char *keyrings; /* Measure keys added to these keyrings */ struct ima_template_desc *template; }; @@ -356,6 +357,50 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, return NOTIFY_OK; } +/** + * ima_match_keyring - determine whether the keyring matches the measure rule + * @rule: a pointer to a rule + * @keyring: name of the keyring to match against the measure rule + * @cred: a pointer to a credentials structure for user validation + * + * Returns true if keyring matches one in the rule, false otherwise. + */ +static bool ima_match_keyring(struct ima_rule_entry *rule, + const char *keyring, const struct cred *cred) +{ + char *keyrings, *next_keyring, *keyrings_ptr; + bool matched = false; + + if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid)) + return false; + + if (!rule->keyrings) + return true; + + if (!keyring) + return false; + + keyrings = kstrdup(rule->keyrings, GFP_KERNEL); + if (!keyrings) + return false; + + /* + * "keyrings=" is specified in the policy in the format below: + * keyrings=.builtin_trusted_keys|.ima|.evm + */ + keyrings_ptr = keyrings; + while ((next_keyring = strsep(&keyrings_ptr, "|")) != NULL) { + if (!strcmp(next_keyring, keyring)) { + matched = true; + break; + } + } + + kfree(keyrings); + + return matched; +} + /** * ima_match_rules - determine whether an inode matches the measure rule. * @rule: a pointer to a rule @@ -364,18 +409,23 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event, * @secid: the secid of the task to be validated * @func: LIM hook identifier * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) + * @keyring: keyring name to check in policy for KEY_CHECK func * * Returns true on rule match, false on failure. */ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, const struct cred *cred, u32 secid, - enum ima_hooks func, int mask) + enum ima_hooks func, int mask, + const char *keyring) { int i; if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) { - if ((rule->flags & IMA_FUNC) && (rule->func == func)) + if ((rule->flags & IMA_FUNC) && (rule->func == func)) { + if (func == KEY_CHECK) + return ima_match_keyring(rule, keyring, cred); return true; + } return false; } if ((rule->flags & IMA_FUNC) && @@ -479,6 +529,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) * @pcr: set the pcr to extend * @template_desc: the template that should be used for this rule + * @keyring: the keyring name, if given, to be used to check in the policy. + * keyring can be NULL if func is anything other than KEY_CHECK. * * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type) * conditions. @@ -489,7 +541,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) */ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, enum ima_hooks func, int mask, int flags, int *pcr, - struct ima_template_desc **template_desc) + struct ima_template_desc **template_desc, + const char *keyring) { struct ima_rule_entry *entry; int action = 0, actmask = flags | (flags << 1); @@ -503,7 +556,8 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, if (!(entry->action & actmask)) continue; - if (!ima_match_rules(entry, inode, cred, secid, func, mask)) + if (!ima_match_rules(entry, inode, cred, secid, func, mask, + keyring)) continue; action |= entry->flags & IMA_ACTION_FLAGS; -- cgit v1.2.3 From 7b575b6d8de03ca6b6ab85fa1dd53d2ce921a4a0 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 2 Dec 2019 12:46:17 +0100 Subject: media: vidioc-g-dv-timings.rst: fix wrong porch It is the vfrontporch of field 1 that is one half-line longer, not the backporch. The order of the vertical signals in an interlaced system is: Field 1: vsync vbackporch active video of field 1 vfrontporch + 0.5 Field 2: il_vsync il_vbackporch - 0.5 active video of field 2 il_vfrontporch Interlaced systems that use HALF_LINE set the il_ fields as follows: il_vfrontporch = vfrontporch il_vsync = vsync il_vbackporch = vbackporch + 1 So the total vertical blanking for field 1 is: vsync + vbackporch + vfrontporch + 0.5 and for field 2: vsync + vbackporch + 1 + vfrontporch - 0.5 == vsync + vbackporch + vfrontporch + 0.5 So each field has the same number of half-lines. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst b/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst index 5712bd48e687..5c675cbac4cf 100644 --- a/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst +++ b/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst @@ -279,7 +279,7 @@ EBUSY then it will set this flag to signal this to the application. * - ``V4L2_DV_FL_HALF_LINE`` - Specific to interlaced formats: if set, then the vertical - backporch of field 1 (aka the odd field) is really one half-line + frontporch of field 1 (aka the odd field) is really one half-line longer and the vertical backporch of field 2 (aka the even field) is really one half-line shorter, so each field has exactly the same number of half-lines. Whether half-lines can be detected or -- cgit v1.2.3 From 2b016c47f48f3d144816645822a09995063313a1 Mon Sep 17 00:00:00 2001 From: Daniel Gomez Date: Tue, 3 Dec 2019 16:12:00 +0100 Subject: media: v4l2: Fix fourcc names for BAYER12P Fix documentation fourcc names for the 12-bit packed Bayer formats. Signed-off-by: Daniel Gomez Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/pixfmt-srggb12p.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst b/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst index 960851275f23..7060a4ffad08 100644 --- a/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst +++ b/Documentation/media/uapi/v4l/pixfmt-srggb12p.rst @@ -13,7 +13,7 @@ .. _v4l2-pix-fmt-sgrbg12p: ******************************************************************************************************************************* -V4L2_PIX_FMT_SRGGB12P ('pRAA'), V4L2_PIX_FMT_SGRBG12P ('pgAA'), V4L2_PIX_FMT_SGBRG12P ('pGAA'), V4L2_PIX_FMT_SBGGR12P ('pBAA'), +V4L2_PIX_FMT_SRGGB12P ('pBCC'), V4L2_PIX_FMT_SGRBG12P ('pgCC'), V4L2_PIX_FMT_SGBRG12P ('pGCC'), V4L2_PIX_FMT_SBGGR12P ('pBCC'), ******************************************************************************************************************************* -- cgit v1.2.3 From 55f240a21eb13717da2872ebef2eb0af4007a5bd Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 4 Dec 2019 12:57:10 +0100 Subject: media: ivtv/cx18: remove ivtvdriver.org references That URL is no longer valid, so either remove references to it or replace it with linuxtv.org. Rather than updating the URL I've just dropped the cx18.rst driver documentation since it was really out of date. Signed-off-by: Hans Verkuil Acked-by: awalls@md.metrocast.net Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/pixfmt-reserved.rst | 3 +- Documentation/media/v4l-drivers/cx18.rst | 39 ------------------------ Documentation/media/v4l-drivers/index.rst | 1 - MAINTAINERS | 6 +--- drivers/media/pci/cx18/cx18-cards.c | 8 ++--- drivers/media/pci/cx18/cx18-driver.c | 2 +- drivers/media/pci/ivtv/Kconfig | 5 ++- drivers/media/pci/ivtv/ivtv-driver.c | 3 +- drivers/media/pci/ivtv/ivtv-driver.h | 1 - 9 files changed, 10 insertions(+), 58 deletions(-) delete mode 100644 Documentation/media/v4l-drivers/cx18.rst (limited to 'Documentation') diff --git a/Documentation/media/uapi/v4l/pixfmt-reserved.rst b/Documentation/media/uapi/v4l/pixfmt-reserved.rst index b2cd155e691b..7d98a7bf9f1f 100644 --- a/Documentation/media/uapi/v4l/pixfmt-reserved.rst +++ b/Documentation/media/uapi/v4l/pixfmt-reserved.rst @@ -55,8 +55,7 @@ please make a proposal on the linux-media mailing list. - ``V4L2_PIX_FMT_HM12`` - 'HM12' - - YUV 4:2:0 format used by the IVTV driver, - `http://www.ivtvdriver.org/ `__ + - YUV 4:2:0 format used by the IVTV driver. The format is documented in the kernel sources in the file ``Documentation/media/v4l-drivers/cx2341x.rst`` diff --git a/Documentation/media/v4l-drivers/cx18.rst b/Documentation/media/v4l-drivers/cx18.rst deleted file mode 100644 index 16895a734bae..000000000000 --- a/Documentation/media/v4l-drivers/cx18.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -The cx18 driver -=============== - -.. note:: - - This documentation is outdated. - -Some notes regarding the cx18 driver for the Conexant CX23418 MPEG -encoder chip: - -1) Currently supported are: - - - Hauppauge HVR-1600 - - Compro VideoMate H900 - - Yuan MPC718 - - Conexant Raptor PAL/SECAM devkit - -2) Some people have problems getting the i2c bus to work. - The symptom is that the eeprom cannot be read and the card is - unusable. This is probably fixed, but if you have problems - then post to the video4linux or ivtv-users mailing list. - -3) VBI (raw or sliced) has not yet been implemented. - -4) MPEG indexing is not yet implemented. - -5) The driver is still a bit rough around the edges, this should - improve over time. - - -Firmware: - -You can obtain the firmware files here: - -http://dl.ivtvdriver.org/ivtv/firmware/cx18-firmware.tar.gz - -Untar and copy the .fw files to your firmware directory. diff --git a/Documentation/media/v4l-drivers/index.rst b/Documentation/media/v4l-drivers/index.rst index c4c78a28654c..b41fea23fe5d 100644 --- a/Documentation/media/v4l-drivers/index.rst +++ b/Documentation/media/v4l-drivers/index.rst @@ -38,7 +38,6 @@ For more details see the file COPYING in the source distribution of Linux. bttv cafe_ccic cpia2 - cx18 cx2341x cx88 davinci-vpbe diff --git a/MAINTAINERS b/MAINTAINERS index eefa1e066655..87f3d89d44a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4427,13 +4427,10 @@ F: drivers/net/wireless/st/cw1200/ CX18 VIDEO4LINUX DRIVER M: Andy Walls -L: ivtv-devel@ivtvdriver.org (subscribers-only) L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git W: https://linuxtv.org -W: http://www.ivtvdriver.org/index.php/Cx18 S: Maintained -F: Documentation/media/v4l-drivers/cx18* F: drivers/media/pci/cx18/ F: include/uapi/linux/ivtv* @@ -8836,10 +8833,9 @@ F: drivers/media/tuners/it913x* IVTV VIDEO4LINUX DRIVER M: Andy Walls -L: ivtv-devel@ivtvdriver.org (subscribers-only) L: linux-media@vger.kernel.org T: git git://linuxtv.org/media_tree.git -W: http://www.ivtvdriver.org +W: https://linuxtv.org S: Maintained F: Documentation/media/v4l-drivers/ivtv* F: drivers/media/pci/ivtv/ diff --git a/drivers/media/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c index cf118760d124..ecbe76f1ca63 100644 --- a/drivers/media/pci/cx18/cx18-cards.c +++ b/drivers/media/pci/cx18/cx18-cards.c @@ -245,7 +245,7 @@ static const struct cx18_card cx18_card_mpc718 = { .type = CX18_CARD_YUAN_MPC718, .name = "Yuan MPC718 MiniPCI DVB-T/Analog", .comment = "Experimenters needed for device to work well.\n" - "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + "\tTo help, mail the linux-media list (www.linuxtv.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, @@ -305,7 +305,7 @@ static const struct cx18_card cx18_card_gotview_dvd3 = { .type = CX18_CARD_GOTVIEW_PCI_DVD3, .name = "GoTView PCI DVD3 Hybrid", .comment = "Experimenters needed for device to work well.\n" - "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + "\tTo help, mail the linux-media list (www.linuxtv.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, @@ -419,7 +419,7 @@ static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = { .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT, .name = "Toshiba Qosmio DVB-T/Analog", .comment = "Experimenters and photos needed for device to work well.\n" - "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + "\tTo help, mail the linux-media list (www.linuxtv.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL, @@ -462,7 +462,7 @@ static const struct cx18_card cx18_card_leadtek_pvr2100 = { .type = CX18_CARD_LEADTEK_PVR2100, .name = "Leadtek WinFast PVR2100", .comment = "Experimenters and photos needed for device to work well.\n" - "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n", + "\tTo help, mail the linux-media list (www.linuxtv.org).\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_418_AV, .hw_muxer = CX18_HW_GPIO_MUX, diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index fd47bd07ffd8..16119f4e9404 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -676,7 +676,7 @@ done: cx->pci_dev->subsystem_device); CX18_ERR("Defaulting to %s card\n", cx->card->name); CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); - CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n"); + CX18_ERR("card you have to the linux-media mailinglist (www.linuxtv.org)\n"); CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n"); } cx->v4l2_cap = cx->card->v4l2_capabilities; diff --git a/drivers/media/pci/ivtv/Kconfig b/drivers/media/pci/ivtv/Kconfig index 36c089103cf9..c729e54692c4 100644 --- a/drivers/media/pci/ivtv/Kconfig +++ b/drivers/media/pci/ivtv/Kconfig @@ -24,7 +24,7 @@ config VIDEO_IVTV PCI personal video recorder devices. This is used in devices such as the Hauppauge PVR-150/250/350/500 - cards. There is a driver homepage at . + cards. To compile this driver as a module, choose M here: the module will be called ivtv. @@ -67,8 +67,7 @@ config VIDEO_FB_IVTV This is a framebuffer driver for the Conexant cx23415 MPEG encoder/decoder. - This is used in the Hauppauge PVR-350 card. There is a driver - homepage at . + This is used in the Hauppauge PVR-350 card. To compile this driver as a module, choose M here: the module will be called ivtvfb. diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 3f3f40ea890b..88dec72f29dc 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -23,7 +23,6 @@ * Driver for the Conexant CX23415/CX23416 chip. * Author: Kevin Thayer (nufan_wfk at yahoo.com) * License: GPL - * http://www.ivtvdriver.org * * ----- * MPG600/MPG160 support by T.Adachi @@ -723,7 +722,7 @@ done: IVTV_ERR(" %s based\n", chipname); IVTV_ERR("Defaulting to %s card\n", itv->card->name); IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); - IVTV_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n"); + IVTV_ERR("card you have to the linux-media mailinglist (www.linuxtv.org)\n"); IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n"); } itv->v4l2_cap = itv->card->v4l2_capabilities; diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h index cafba6b1055d..e5efe525ad7b 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.h +++ b/drivers/media/pci/ivtv/ivtv-driver.h @@ -28,7 +28,6 @@ * Driver for the cx23415/6 chip. * Author: Kevin Thayer (nufan_wfk at yahoo.com) * License: GPL - * http://www.ivtvdriver.org * * ----- * MPG600/MPG160 support by T.Adachi -- cgit v1.2.3 From 887c7942ce31dcffecf53897598c766602f5e6f5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 5 Dec 2019 16:07:39 +0100 Subject: media: cec-ioc-g-mode.rst: remove trailing 'i' Remove spurious trailing 'i'. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/cec/cec-ioc-g-mode.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/media/uapi/cec/cec-ioc-g-mode.rst b/Documentation/media/uapi/cec/cec-ioc-g-mode.rst index d0902f356d65..2535b77e3459 100644 --- a/Documentation/media/uapi/cec/cec-ioc-g-mode.rst +++ b/Documentation/media/uapi/cec/cec-ioc-g-mode.rst @@ -177,7 +177,7 @@ Available follower modes are: - ``CEC_MODE_MONITOR`` - 0xe0 - Put the file descriptor into monitor mode. Can only be used in - combination with :ref:`CEC_MODE_NO_INITIATOR `,i + combination with :ref:`CEC_MODE_NO_INITIATOR `, otherwise the ``EINVAL`` error code will be returned. In monitor mode all messages this CEC device transmits and all messages it receives (both broadcast -- cgit v1.2.3 From 6f0ebdf45c0bb74cf004f6e195f31882bfbf058b Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Mon, 2 Dec 2019 16:44:26 +1030 Subject: dt-bindings: pinctrl: aspeed-g6: Add USB functions and groups The AST2600 provides two USB ports (A and B) that expose various host, device and HID functions. Signed-off-by: Andrew Jeffery Link: https://lore.kernel.org/r/20191202061432.3996-2-andrew@aj.id.au Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml index 064b7dfc4252..3749fa233e87 100644 --- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2600-pinctrl.yaml @@ -54,8 +54,9 @@ patternProperties: TACH10, TACH11, TACH12, TACH13, TACH14, TACH15, TACH2, TACH3, TACH4, TACH5, TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2, THRU3, TXD1, TXD2, TXD3, TXD4, UART10, UART11, UART12, UART13, - UART6, UART7, UART8, UART9, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, - WDTRST3, WDTRST4, ] + UART6, UART7, UART8, UART9, USBAD, USBADP, USB2AH, USB2AHP, + USB2BD, USB2BH, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3, + WDTRST4, ] groups: allOf: - $ref: "/schemas/types.yaml#/definitions/string" @@ -85,8 +86,8 @@ patternProperties: TACH10, TACH11, TACH12, TACH13, TACH14, TACH15, TACH2, TACH3, TACH4, TACH5, TACH6, TACH7, TACH8, TACH9, THRU0, THRU1, THRU2, THRU3, TXD1, TXD2, TXD3, TXD4, UART10, UART11, UART12G0, - UART12G1, UART13G0, UART13G1, UART6, UART7, UART8, UART9, VB, - VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3, WDTRST4, ] + UART12G1, UART13G0, UART13G1, UART6, UART7, UART8, UART9, USBA, + USBB, VB, VGAHS, VGAVS, WDTRST1, WDTRST2, WDTRST3, WDTRST4, ] required: - compatible -- cgit v1.2.3 From 885503fbea210bc8f4ac70fa530ed05fade4bc94 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 3 Dec 2019 15:12:40 +0100 Subject: dt-bindings: Add Xylon vendor prefix Xylon is an electronics company that produces FPGA hardware block designs optimized for Xilinx FPGAs. Signed-off-by: Paul Kocialkowski Acked-by: Rob Herring Link: https://lore.kernel.org/r/20191203141243.251058-2-paul.kocialkowski@bootlin.com Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6046f4555852..9cb3bc683db7 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1060,6 +1060,8 @@ patternProperties: description: Xilinx "^xunlong,.*": description: Shenzhen Xunlong Software CO.,Limited + "^xylon,.*": + description: Xylon "^yones-toptech,.*": description: Yones Toptech Co., Ltd. "^ysoft,.*": -- cgit v1.2.3 From e10781c118c986a3eb7c4b2edb4bdaba37bb5635 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 3 Dec 2019 15:12:41 +0100 Subject: dt-bindings: mfd: Document the Xylon LogiCVC multi-function device The LogiCVC is a display engine which also exposes GPIO functionality. For this reason, it is described as a multi-function device that is expected to provide register access to its children nodes for gpio and display. Signed-off-by: Paul Kocialkowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191203141243.251058-3-paul.kocialkowski@bootlin.com Signed-off-by: Linus Walleij --- .../devicetree/bindings/mfd/xylon,logicvc.yaml | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml b/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml new file mode 100644 index 000000000000..abc9937506e0 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/xylon,logicvc.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 Bootlin +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/mfd/xylon,logicvc.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Xylon LogiCVC multi-function device + +maintainers: + - Paul Kocialkowski + +description: | + The LogiCVC is a display controller that also contains a GPIO controller. + As a result, a multi-function device is exposed as parent of the display + and GPIO blocks. + +properties: + compatible: + items: + - enum: + - xylon,logicvc-3.02.a + - const: syscon + - const: simple-mfd + + reg: + maxItems: 1 + +select: + properties: + compatible: + contains: + enum: + - xylon,logicvc-3.02.a + + required: + - compatible + +required: + - compatible + - reg + +examples: + - | + logicvc: logicvc@43c00000 { + compatible = "xylon,logicvc-3.02.a", "syscon", "simple-mfd"; + reg = <0x43c00000 0x6000>; + #address-cells = <1>; + #size-cells = <1>; + }; -- cgit v1.2.3 From 6bdbe62c748c4b8cfe3555bb9b1daecc0d1e585a Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Tue, 3 Dec 2019 15:12:42 +0100 Subject: dt-bindings: gpio: Document the Xylon LogiCVC GPIO controller The Xylon LogiCVC display controller exports some GPIOs, which are exposed as a separate entity. Signed-off-by: Paul Kocialkowski Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191203141243.251058-4-paul.kocialkowski@bootlin.com Signed-off-by: Linus Walleij --- .../bindings/gpio/xylon,logicvc-gpio.yaml | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/xylon,logicvc-gpio.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/gpio/xylon,logicvc-gpio.yaml b/Documentation/devicetree/bindings/gpio/xylon,logicvc-gpio.yaml new file mode 100644 index 000000000000..d102888c1be7 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/xylon,logicvc-gpio.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 Bootlin +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/gpio/xylon,logicvc-gpio.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Xylon LogiCVC GPIO controller + +maintainers: + - Paul Kocialkowski + +description: | + The LogiCVC GPIO describes the GPIO block included in the LogiCVC display + controller. These are meant to be used for controlling display-related + signals. + + The controller exposes GPIOs from the display and power control registers, + which are mapped by the driver as follows: + - GPIO[4:0] (display control) mapped to index 0-4 + - EN_BLIGHT (power control) mapped to index 5 + - EN_VDD (power control) mapped to index 6 + - EN_VEE (power control) mapped to index 7 + - V_EN (power control) mapped to index 8 + +properties: + $nodename: + pattern: "^gpio@[0-9a-f]+$" + + compatible: + enum: + - xylon,logicvc-3.02.a-gpio + + reg: + maxItems: 1 + + "#gpio-cells": + const: 2 + + gpio-controller: true + + gpio-line-names: + minItems: 1 + maxItems: 9 + +required: + - compatible + - reg + - "#gpio-cells" + - gpio-controller + +examples: + - | + logicvc: logicvc@43c00000 { + compatible = "xylon,logicvc-3.02.a", "syscon", "simple-mfd"; + reg = <0x43c00000 0x6000>; + + #address-cells = <1>; + #size-cells = <1>; + + logicvc_gpio: gpio@40 { + compatible = "xylon,logicvc-3.02.a-gpio"; + reg = <0x40 0x40>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", + "EN_BLIGHT", "EN_VDD", "EN_VEE", "V_EN"; + }; + }; -- cgit v1.2.3 From 894731a5c9d0ea801a7ea1aba2f7c7b69fef6e85 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:39:12 +0100 Subject: dt-bindings: gpio: rcar: Document r8a77961 support Document support for the GPIO controller in the Renesas R-Car M3-W+ (R8A77961) SoC. Update all references to R-Car M3-W from "r8a7796" to "r8a77960", to avoid confusion between R-Car M3-W (R8A77960) and M3-W+. No driver update is needed. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20191205133912.6048-1-geert+renesas@glider.be Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt index 41e5fed0f842..10dce84b1545 100644 --- a/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt +++ b/Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt @@ -18,7 +18,8 @@ Required Properties: - "renesas,gpio-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller. - "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller. - "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) compatible GPIO controller. - - "renesas,gpio-r8a7796": for R8A7796 (R-Car M3-W) compatible GPIO controller. + - "renesas,gpio-r8a7796": for R8A77960 (R-Car M3-W) compatible GPIO controller. + - "renesas,gpio-r8a77961": for R8A77961 (R-Car M3-W+) compatible GPIO controller. - "renesas,gpio-r8a77965": for R8A77965 (R-Car M3-N) compatible GPIO controller. - "renesas,gpio-r8a77970": for R8A77970 (R-Car V3M) compatible GPIO controller. - "renesas,gpio-r8a77980": for R8A77980 (R-Car V3H) compatible GPIO controller. -- cgit v1.2.3 From 9482ae6ea7879f29221eb9cd10807d087517b38b Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 10 Dec 2019 15:41:37 +0100 Subject: dt-bindings: display/ingenic: Add compatible string for JZ4770 Add a compatible string for the LCD controller found in the JZ4770 SoC. v2: No change Signed-off-by: Paul Cercueil Acked-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20191210144142.33143-1-paul@crapouillou.net # *** extracted tags *** Acked-by: Sam Ravnborg --- Documentation/devicetree/bindings/display/ingenic,lcd.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/ingenic,lcd.txt b/Documentation/devicetree/bindings/display/ingenic,lcd.txt index 7b536c8c6dde..01e3261defb6 100644 --- a/Documentation/devicetree/bindings/display/ingenic,lcd.txt +++ b/Documentation/devicetree/bindings/display/ingenic,lcd.txt @@ -4,6 +4,7 @@ Required properties: - compatible: one of: * ingenic,jz4740-lcd * ingenic,jz4725b-lcd + * ingenic,jz4770-lcd - reg: LCD registers location and length - clocks: LCD pixclock and device clock specifiers. The device clock is only required on the JZ4740. -- cgit v1.2.3 From 59c3662b8f081832abaadfbc8a4bfb63c526aea8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 9 Dec 2019 21:32:46 +0100 Subject: iio: adc: ltc2496: provide device tree binding document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADC only requires the standard stuff for spi devices and a reference voltage. Signed-off-by: Uwe Kleine-König Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/adc/lltc,ltc2496.yaml | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml new file mode 100644 index 000000000000..59009997dca0 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/lltc,ltc2496.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Linear Technology / Analog Devices LTC2496 ADC + +maintainers: + - Lars-Peter Clausen + - Michael Hennerich + - Stefan Popa + +properties: + compatible: + enum: + - lltc,ltc2496 + + vref-supply: + description: phandle to an external regulator providing the reference voltage + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + reg: + description: spi chipselect number according to the usual spi bindings + + spi-max-frequency: + description: maximal spi bus frequency supported + +required: + - compatible + - vref-supply + - reg + +examples: + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "lltc,ltc2496"; + reg = <0>; + vref-supply = <<c2496_reg>; + spi-max-frequency = <2000000>; + }; + }; -- cgit v1.2.3 From 5b883564fcdee1aa5ded4354046f03a848aa2370 Mon Sep 17 00:00:00 2001 From: Rodrigo Carvalho Date: Sat, 7 Dec 2019 01:53:39 -0300 Subject: dt-bindings: iio: accel: add binding documentation for ADIS16240 This patch add device tree binding documentation for ADIS16240. Signed-off-by: Rodrigo Carvalho Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/accel/adi,adis16240.yaml | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml new file mode 100644 index 000000000000..4147f02b5e3c --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/accel/adi,adis16240.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ADIS16240 Programmable Impact Sensor and Recorder driver + +maintainers: + - Alexandru Ardelean + +description: | + ADIS16240 Programmable Impact Sensor and Recorder driver that supports + SPI interface. + https://www.analog.com/en/products/adis16240.html + +properties: + compatible: + enum: + - adi,adis16240 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + /* Example for a SPI device node */ + accelerometer@0 { + compatible = "adi,adis16240"; + reg = <0>; + spi-max-frequency = <2500000>; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; -- cgit v1.2.3 From 1a0013c62b33158dcb67a3c11872a03be50711a3 Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Tue, 19 Nov 2019 00:34:01 +0200 Subject: interconnect: Add interconnect_graph file to debugfs The interconnect graphs can be difficult to understand and the current "interconnect_summary" file doesn't even display links in any way. Add a new "interconnect_graph" file to debugfs in the graphviz "dot" format which describes interconnect providers, nodes and links. The file is human-readable and can be visualized by piping through graphviz. Example: ssh $TARGET cat /sys/kernel/debug/interconnect/interconnect_graph \ | dot -Tsvg > interconnect_graph.svg Signed-off-by: Leonard Crestez Reviewed-by: Greg Kroah-Hartman Reviewed-by: Bjorn Andersson Signed-off-by: Georgi Djakov --- Documentation/driver-api/interconnect.rst | 22 +++++++++++ drivers/interconnect/core.c | 66 +++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) (limited to 'Documentation') diff --git a/Documentation/driver-api/interconnect.rst b/Documentation/driver-api/interconnect.rst index cdeb5825f314..5ed4f57a6bac 100644 --- a/Documentation/driver-api/interconnect.rst +++ b/Documentation/driver-api/interconnect.rst @@ -91,3 +91,25 @@ Interconnect consumers are the clients which use the interconnect APIs to get paths between endpoints and set their bandwidth/latency/QoS requirements for these interconnect paths. These interfaces are not currently documented. + +Interconnect debugfs interfaces +------------------------------- + +Like several other subsystems interconnect will create some files for debugging +and introspection. Files in debugfs are not considered ABI so application +software shouldn't rely on format details change between kernel versions. + +``/sys/kernel/debug/interconnect/interconnect_summary``: + +Show all interconnect nodes in the system with their aggregated bandwidth +request. Indented under each node show bandwidth requests from each device. + +``/sys/kernel/debug/interconnect/interconnect_graph``: + +Show the interconnect graph in the graphviz dot format. It shows all +interconnect nodes and links in the system and groups together nodes from the +same provider as subgraphs. The format is human-readable and can also be piped +through dot to generate diagrams in many graphical formats:: + + $ cat /sys/kernel/debug/interconnect/interconnect_graph | \ + dot -Tsvg > interconnect_graph.svg diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 03625406c69f..63c164264b73 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -71,6 +71,70 @@ static int icc_summary_show(struct seq_file *s, void *data) } DEFINE_SHOW_ATTRIBUTE(icc_summary); +static void icc_graph_show_link(struct seq_file *s, int level, + struct icc_node *n, struct icc_node *m) +{ + seq_printf(s, "%s\"%d:%s\" -> \"%d:%s\"\n", + level == 2 ? "\t\t" : "\t", + n->id, n->name, m->id, m->name); +} + +static void icc_graph_show_node(struct seq_file *s, struct icc_node *n) +{ + seq_printf(s, "\t\t\"%d:%s\" [label=\"%d:%s", + n->id, n->name, n->id, n->name); + seq_printf(s, "\n\t\t\t|avg_bw=%ukBps", n->avg_bw); + seq_printf(s, "\n\t\t\t|peak_bw=%ukBps", n->peak_bw); + seq_puts(s, "\"]\n"); +} + +static int icc_graph_show(struct seq_file *s, void *data) +{ + struct icc_provider *provider; + struct icc_node *n; + int cluster_index = 0; + int i; + + seq_puts(s, "digraph {\n\trankdir = LR\n\tnode [shape = record]\n"); + mutex_lock(&icc_lock); + + /* draw providers as cluster subgraphs */ + cluster_index = 0; + list_for_each_entry(provider, &icc_providers, provider_list) { + seq_printf(s, "\tsubgraph cluster_%d {\n", ++cluster_index); + if (provider->dev) + seq_printf(s, "\t\tlabel = \"%s\"\n", + dev_name(provider->dev)); + + /* draw nodes */ + list_for_each_entry(n, &provider->nodes, node_list) + icc_graph_show_node(s, n); + + /* draw internal links */ + list_for_each_entry(n, &provider->nodes, node_list) + for (i = 0; i < n->num_links; ++i) + if (n->provider == n->links[i]->provider) + icc_graph_show_link(s, 2, n, + n->links[i]); + + seq_puts(s, "\t}\n"); + } + + /* draw external links */ + list_for_each_entry(provider, &icc_providers, provider_list) + list_for_each_entry(n, &provider->nodes, node_list) + for (i = 0; i < n->num_links; ++i) + if (n->provider != n->links[i]->provider) + icc_graph_show_link(s, 1, n, + n->links[i]); + + mutex_unlock(&icc_lock); + seq_puts(s, "}"); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(icc_graph); + static struct icc_node *node_find(const int id) { return idr_find(&icc_idr, id); @@ -827,6 +891,8 @@ static int __init icc_init(void) icc_debugfs_dir = debugfs_create_dir("interconnect", NULL); debugfs_create_file("interconnect_summary", 0444, icc_debugfs_dir, NULL, &icc_summary_fops); + debugfs_create_file("interconnect_graph", 0444, + icc_debugfs_dir, NULL, &icc_graph_fops); return 0; } -- cgit v1.2.3 From 22440461b19e773fe75b41fc6e3388d2319ff3be Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Wed, 11 Dec 2019 05:24:24 +0000 Subject: dt-bindings: pinctrl: qcom: Add new qup functions for sc7180 Add new qup functions for qup02/04/11 and qup13 wherein multiple functions (for i2c and uart) share the same pin. This allows users to identify which specific qup function for the instance one needs to use for the pin. Signed-off-by: Rajendra Nayak Link: https://lore.kernel.org/r/0101016ef36a5c54-2907cf32-2269-4a8c-9447-b086e7c86d98-000000@us-west-2.amazonses.com Reviewed-by: Bjorn Andersson Reviewed-by: Stephen Boyd Reviewed-by: Douglas Anderson Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt index b5767ee82ee6..6ffeac9801df 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt @@ -125,8 +125,9 @@ to specify in a pin configuration subnode: mi2s_1, mi2s_2, mss_lte, m_voc, pa_indicator, phase_flag, PLL_BIST, pll_bypassnl, pll_reset, prng_rosc, qdss, qdss_cti, qlink_enable, qlink_request, qspi_clk, qspi_cs, - qspi_data, qup00, qup01, qup02, qup03, qup04, qup05, - qup10, qup11, qup12, qup13, qup14, qup15, sdc1_tb, + qspi_data, qup00, qup01, qup02_i2c, qup02_uart, qup03, + qup04_i2c, qup04_uart, qup05, qup10, qup11_i2c, qup11_uart, + qup12, qup13_i2c, qup13_uart, qup14, qup15, sdc1_tb, sdc2_tb, sd_write, sp_cmu, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3, tsense_pwm1, tsense_pwm2, uim1, uim2, uim_batt, usb_phy, vfr_1, _V_GPIO, _V_PPS_IN, _V_PPS_OUT, -- cgit v1.2.3 From 2156873f08c7893811f34177aa923ab1ea486591 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 9 Dec 2019 16:42:14 +0200 Subject: drm/tilcdc: Remove obsolete bundled tilcdc tfp410 driver Remove obsolete bundled tfp410 driver with its "ti,tilcdc,tfp410" devicetree binding. No platform has ever used this driver in the mainline kernel and if anybody connects tfp410 to tilcdc he or she should use the generic drm tfp410 bridge driver. Signed-off-by: Jyri Sarha Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/6e2db6c328467cc51e8d633ecb0ffa7c5736f2e8.1575901747.git.jsarha@ti.com --- .../devicetree/bindings/display/tilcdc/tfp410.txt | 21 -- drivers/gpu/drm/tilcdc/Makefile | 1 - drivers/gpu/drm/tilcdc/tilcdc_drv.c | 3 - drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 381 --------------------- drivers/gpu/drm/tilcdc/tilcdc_tfp410.h | 15 - 5 files changed, 421 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/tilcdc/tfp410.txt delete mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.c delete mode 100644 drivers/gpu/drm/tilcdc/tilcdc_tfp410.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/tilcdc/tfp410.txt b/Documentation/devicetree/bindings/display/tilcdc/tfp410.txt deleted file mode 100644 index a58ae7756fc6..000000000000 --- a/Documentation/devicetree/bindings/display/tilcdc/tfp410.txt +++ /dev/null @@ -1,21 +0,0 @@ -Device-Tree bindings for tilcdc DRM TFP410 output driver - -Required properties: - - compatible: value should be "ti,tilcdc,tfp410". - - i2c: the phandle for the i2c device to use for DDC - -Recommended properties: - - pinctrl-names, pinctrl-0: the pincontrol settings to configure - muxing properly for pins that connect to TFP410 device - - powerdn-gpio: the powerdown GPIO, pulled low to power down the - TFP410 device (for DPMS_OFF) - -Example: - - dvicape { - compatible = "ti,tilcdc,tfp410"; - i2c = <&i2c2>; - pinctrl-names = "default"; - pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>; - powerdn-gpio = <&gpio2 31 0>; - }; diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile index 87f9480e43b0..662bf3a348c9 100644 --- a/drivers/gpu/drm/tilcdc/Makefile +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -6,7 +6,6 @@ endif tilcdc-y := \ tilcdc_plane.o \ tilcdc_crtc.o \ - tilcdc_tfp410.o \ tilcdc_panel.o \ tilcdc_external.o \ tilcdc_drv.o diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index a160880bea0a..c18a28df6e2c 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -30,7 +30,6 @@ #include "tilcdc_external.h" #include "tilcdc_panel.h" #include "tilcdc_regs.h" -#include "tilcdc_tfp410.h" static LIST_HEAD(module_list); @@ -643,7 +642,6 @@ static struct platform_driver tilcdc_platform_driver = { static int __init tilcdc_drm_init(void) { DBG("init"); - tilcdc_tfp410_init(); tilcdc_panel_init(); return platform_driver_register(&tilcdc_platform_driver); } @@ -653,7 +651,6 @@ static void __exit tilcdc_drm_fini(void) DBG("fini"); platform_driver_unregister(&tilcdc_platform_driver); tilcdc_panel_fini(); - tilcdc_tfp410_fini(); } module_init(tilcdc_drm_init); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c deleted file mode 100644 index 562e98ab43cd..000000000000 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ /dev/null @@ -1,381 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2012 Texas Instruments - * Author: Rob Clark - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "tilcdc_drv.h" -#include "tilcdc_tfp410.h" - -struct tfp410_module { - struct tilcdc_module base; - struct i2c_adapter *i2c; - int gpio; -}; -#define to_tfp410_module(x) container_of(x, struct tfp410_module, base) - - -static const struct tilcdc_panel_info dvi_info = { - .ac_bias = 255, - .ac_bias_intrpt = 0, - .dma_burst_sz = 16, - .bpp = 16, - .fdd = 0x80, - .tft_alt_mode = 0, - .sync_edge = 0, - .sync_ctrl = 1, - .raster_order = 0, -}; - -/* - * Encoder: - */ - -struct tfp410_encoder { - struct drm_encoder base; - struct tfp410_module *mod; - int dpms; -}; -#define to_tfp410_encoder(x) container_of(x, struct tfp410_encoder, base) - -static void tfp410_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct tfp410_encoder *tfp410_encoder = to_tfp410_encoder(encoder); - - if (tfp410_encoder->dpms == mode) - return; - - if (mode == DRM_MODE_DPMS_ON) { - DBG("Power on"); - gpio_direction_output(tfp410_encoder->mod->gpio, 1); - } else { - DBG("Power off"); - gpio_direction_output(tfp410_encoder->mod->gpio, 0); - } - - tfp410_encoder->dpms = mode; -} - -static void tfp410_encoder_prepare(struct drm_encoder *encoder) -{ - tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); -} - -static void tfp410_encoder_commit(struct drm_encoder *encoder) -{ - tfp410_encoder_dpms(encoder, DRM_MODE_DPMS_ON); -} - -static void tfp410_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - /* nothing needed */ -} - -static const struct drm_encoder_funcs tfp410_encoder_funcs = { - .destroy = drm_encoder_cleanup, -}; - -static const struct drm_encoder_helper_funcs tfp410_encoder_helper_funcs = { - .dpms = tfp410_encoder_dpms, - .prepare = tfp410_encoder_prepare, - .commit = tfp410_encoder_commit, - .mode_set = tfp410_encoder_mode_set, -}; - -static struct drm_encoder *tfp410_encoder_create(struct drm_device *dev, - struct tfp410_module *mod) -{ - struct tfp410_encoder *tfp410_encoder; - struct drm_encoder *encoder; - int ret; - - tfp410_encoder = devm_kzalloc(dev->dev, sizeof(*tfp410_encoder), - GFP_KERNEL); - if (!tfp410_encoder) - return NULL; - - tfp410_encoder->dpms = DRM_MODE_DPMS_OFF; - tfp410_encoder->mod = mod; - - encoder = &tfp410_encoder->base; - encoder->possible_crtcs = 1; - - ret = drm_encoder_init(dev, encoder, &tfp410_encoder_funcs, - DRM_MODE_ENCODER_TMDS, NULL); - if (ret < 0) - goto fail; - - drm_encoder_helper_add(encoder, &tfp410_encoder_helper_funcs); - - return encoder; - -fail: - drm_encoder_cleanup(encoder); - return NULL; -} - -/* - * Connector: - */ - -struct tfp410_connector { - struct drm_connector base; - - struct drm_encoder *encoder; /* our connected encoder */ - struct tfp410_module *mod; -}; -#define to_tfp410_connector(x) container_of(x, struct tfp410_connector, base) - - -static void tfp410_connector_destroy(struct drm_connector *connector) -{ - drm_connector_unregister(connector); - drm_connector_cleanup(connector); -} - -static enum drm_connector_status tfp410_connector_detect( - struct drm_connector *connector, - bool force) -{ - struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector); - - if (drm_probe_ddc(tfp410_connector->mod->i2c)) - return connector_status_connected; - - return connector_status_unknown; -} - -static int tfp410_connector_get_modes(struct drm_connector *connector) -{ - struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector); - struct edid *edid; - int ret = 0; - - edid = drm_get_edid(connector, tfp410_connector->mod->i2c); - - drm_connector_update_edid_property(connector, edid); - - if (edid) { - ret = drm_add_edid_modes(connector, edid); - kfree(edid); - } - - return ret; -} - -static struct drm_encoder *tfp410_connector_best_encoder( - struct drm_connector *connector) -{ - struct tfp410_connector *tfp410_connector = to_tfp410_connector(connector); - return tfp410_connector->encoder; -} - -static const struct drm_connector_funcs tfp410_connector_funcs = { - .destroy = tfp410_connector_destroy, - .detect = tfp410_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .reset = drm_atomic_helper_connector_reset, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = { - .get_modes = tfp410_connector_get_modes, - .best_encoder = tfp410_connector_best_encoder, -}; - -static struct drm_connector *tfp410_connector_create(struct drm_device *dev, - struct tfp410_module *mod, struct drm_encoder *encoder) -{ - struct tfp410_connector *tfp410_connector; - struct drm_connector *connector; - int ret; - - tfp410_connector = devm_kzalloc(dev->dev, sizeof(*tfp410_connector), - GFP_KERNEL); - if (!tfp410_connector) - return NULL; - - tfp410_connector->encoder = encoder; - tfp410_connector->mod = mod; - - connector = &tfp410_connector->base; - - drm_connector_init_with_ddc(dev, connector, - &tfp410_connector_funcs, - DRM_MODE_CONNECTOR_DVID, - mod->i2c); - drm_connector_helper_add(connector, &tfp410_connector_helper_funcs); - - connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - ret = drm_connector_attach_encoder(connector, encoder); - if (ret) - goto fail; - - return connector; - -fail: - tfp410_connector_destroy(connector); - return NULL; -} - -/* - * Module: - */ - -static int tfp410_modeset_init(struct tilcdc_module *mod, struct drm_device *dev) -{ - struct tfp410_module *tfp410_mod = to_tfp410_module(mod); - struct tilcdc_drm_private *priv = dev->dev_private; - struct drm_encoder *encoder; - struct drm_connector *connector; - - encoder = tfp410_encoder_create(dev, tfp410_mod); - if (!encoder) - return -ENOMEM; - - connector = tfp410_connector_create(dev, tfp410_mod, encoder); - if (!connector) - return -ENOMEM; - - priv->encoders[priv->num_encoders++] = encoder; - priv->connectors[priv->num_connectors++] = connector; - - tilcdc_crtc_set_panel_info(priv->crtc, &dvi_info); - return 0; -} - -static const struct tilcdc_module_ops tfp410_module_ops = { - .modeset_init = tfp410_modeset_init, -}; - -/* - * Device: - */ - -static int tfp410_probe(struct platform_device *pdev) -{ - struct device_node *node = pdev->dev.of_node; - struct device_node *i2c_node; - struct tfp410_module *tfp410_mod; - struct tilcdc_module *mod; - struct pinctrl *pinctrl; - uint32_t i2c_phandle; - int ret = -EINVAL; - - /* bail out early if no DT data: */ - if (!node) { - dev_err(&pdev->dev, "device-tree data is missing\n"); - return -ENXIO; - } - - tfp410_mod = devm_kzalloc(&pdev->dev, sizeof(*tfp410_mod), GFP_KERNEL); - if (!tfp410_mod) - return -ENOMEM; - - mod = &tfp410_mod->base; - pdev->dev.platform_data = mod; - - tilcdc_module_init(mod, "tfp410", &tfp410_module_ops); - - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, "pins are not configured\n"); - - if (of_property_read_u32(node, "i2c", &i2c_phandle)) { - dev_err(&pdev->dev, "could not get i2c bus phandle\n"); - goto fail; - } - - i2c_node = of_find_node_by_phandle(i2c_phandle); - if (!i2c_node) { - dev_err(&pdev->dev, "could not get i2c bus node\n"); - goto fail; - } - - tfp410_mod->i2c = of_find_i2c_adapter_by_node(i2c_node); - if (!tfp410_mod->i2c) { - dev_err(&pdev->dev, "could not get i2c\n"); - of_node_put(i2c_node); - goto fail; - } - - of_node_put(i2c_node); - - tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio", - 0, NULL); - if (tfp410_mod->gpio < 0) { - dev_warn(&pdev->dev, "No power down GPIO\n"); - } else { - ret = gpio_request(tfp410_mod->gpio, "DVI_PDn"); - if (ret) { - dev_err(&pdev->dev, "could not get DVI_PDn gpio\n"); - goto fail_adapter; - } - } - - return 0; - -fail_adapter: - i2c_put_adapter(tfp410_mod->i2c); - -fail: - tilcdc_module_cleanup(mod); - return ret; -} - -static int tfp410_remove(struct platform_device *pdev) -{ - struct tilcdc_module *mod = dev_get_platdata(&pdev->dev); - struct tfp410_module *tfp410_mod = to_tfp410_module(mod); - - i2c_put_adapter(tfp410_mod->i2c); - gpio_free(tfp410_mod->gpio); - - tilcdc_module_cleanup(mod); - - return 0; -} - -static const struct of_device_id tfp410_of_match[] = { - { .compatible = "ti,tilcdc,tfp410", }, - { }, -}; - -struct platform_driver tfp410_driver = { - .probe = tfp410_probe, - .remove = tfp410_remove, - .driver = { - .owner = THIS_MODULE, - .name = "tfp410", - .of_match_table = tfp410_of_match, - }, -}; - -int __init tilcdc_tfp410_init(void) -{ - return platform_driver_register(&tfp410_driver); -} - -void __exit tilcdc_tfp410_fini(void) -{ - platform_driver_unregister(&tfp410_driver); -} diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h deleted file mode 100644 index f9aaf6911ffc..000000000000 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2012 Texas Instruments - * Author: Rob Clark - */ - -#ifndef __TILCDC_TFP410_H__ -#define __TILCDC_TFP410_H__ - -/* sub-module for tfp410 dvi adaptor */ - -int tilcdc_tfp410_init(void); -void tilcdc_tfp410_fini(void); - -#endif /* __TILCDC_TFP410_H__ */ -- cgit v1.2.3 From 604bd5ae91d9c6ba849e4e704b759bd29000dcb2 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 5 Dec 2019 16:34:05 +0100 Subject: media: dt-bindings: media: amlogic,vdec: convert to yaml Now that we have the DT validation in place, let's convert the device tree bindings for the Amlogic Video Controller over to YAML schemas. This yaml bindings will then be extended to support new SoCs. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/amlogic,gx-vdec.yaml | 107 +++++++++++++++++++++ .../devicetree/bindings/media/amlogic,vdec.txt | 72 -------------- 2 files changed, 107 insertions(+), 72 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml delete mode 100644 Documentation/devicetree/bindings/media/amlogic,vdec.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml b/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml new file mode 100644 index 000000000000..878944867d6e --- /dev/null +++ b/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 BayLibre, SAS +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/media/amlogic,gx-vdec.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Amlogic Video Decoder + +maintainers: + - Neil Armstrong + - Maxime Jourdan + +description: | + The video decoding IP lies within the DOS memory region, + except for the hardware bitstream parser that makes use of an undocumented + region. + + It makes use of the following blocks: + - ESPARSER is a bitstream parser that outputs to a VIFIFO. Further VDEC blocks + then feed from this VIFIFO. + - VDEC_1 can decode MPEG-1, MPEG-2, MPEG-4 part 2, MJPEG, H.263, H.264, VC-1. + - VDEC_HEVC can decode HEVC and VP9. + + Both VDEC_1 and VDEC_HEVC share the "vdec" IRQ and as such cannot run + concurrently. + +properties: + compatible: + items: + - enum: + - amlogic,gxbb-vdec # GXBB (S905) + - amlogic,gxl-vdec # GXL (S905X, S905D) + - amlogic,gxm-vdec # GXM (S912) + - const: amlogic,gx-vdec + + interrupts: + minItems: 2 + + interrupt-names: + items: + - const: vdec + - const: esparser + + reg: + minItems: 2 + + reg-names: + items: + - const: dos + - const: esparser + + resets: + maxItems: 1 + + reset-names: + items: + - const: esparser + + clocks: + minItems: 4 + + clock-names: + items: + - const: dos_parser + - const: dos + - const: vdec_1 + - const: vdec_hevc + + amlogic,ao-sysctrl: + description: should point to the AOBUS sysctrl node + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + + amlogic,canvas: + description: should point to a canvas provider node + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + - clocks + - clock-names + - resets + - reset-names + - amlogic,ao-sysctrl + - amlogic,canvas + +examples: + - | + vdec: video-decoder@c8820000 { + compatible = "amlogic,gxl-vdec", "amlogic,gx-vdec"; + reg = <0xc8820000 0x10000>, <0xc110a580 0xe4>; + reg-names = "dos", "esparser"; + interrupts = <44>, <32>; + interrupt-names = "vdec", "esparser"; + clocks = <&clk_dos_parser> ,<&clk_dos>, <&clk_vdec_1>, <&clk_vdec_hevc>; + clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc"; + resets = <&reset_parser>; + reset-names = "esparser"; + amlogic,ao-sysctrl = <&sysctrl_AO>; + amlogic,canvas = <&canvas>; + }; diff --git a/Documentation/devicetree/bindings/media/amlogic,vdec.txt b/Documentation/devicetree/bindings/media/amlogic,vdec.txt deleted file mode 100644 index 9b6aace86ca7..000000000000 --- a/Documentation/devicetree/bindings/media/amlogic,vdec.txt +++ /dev/null @@ -1,72 +0,0 @@ -Amlogic Video Decoder -================================ - -The video decoding IP lies within the DOS memory region, -except for the hardware bitstream parser that makes use of an undocumented -region. - -It makes use of the following blocks: - -- ESPARSER is a bitstream parser that outputs to a VIFIFO. Further VDEC blocks -then feed from this VIFIFO. -- VDEC_1 can decode MPEG-1, MPEG-2, MPEG-4 part 2, MJPEG, H.263, H.264, VC-1. -- VDEC_HEVC can decode HEVC and VP9. - -Both VDEC_1 and VDEC_HEVC share the "vdec" IRQ and as such cannot run -concurrently. - -Device Tree Bindings: ---------------------- - -VDEC: Video Decoder --------------------------- - -Required properties: -- compatible: value should be different for each SoC family as : - - GXBB (S905) : "amlogic,gxbb-vdec" - - GXL (S905X, S905D) : "amlogic,gxl-vdec" - - GXM (S912) : "amlogic,gxm-vdec" - followed by the common "amlogic,gx-vdec" -- reg: base address and size of he following memory-mapped regions : - - dos - - esparser -- reg-names: should contain the names of the previous memory regions -- interrupts: should contain the following IRQs: - - vdec - - esparser -- interrupt-names: should contain the names of the previous interrupts -- amlogic,ao-sysctrl: should point to the AOBUS sysctrl node -- amlogic,canvas: should point to a canvas provider node -- clocks: should contain the following clocks : - - dos_parser - - dos - - vdec_1 - - vdec_hevc -- clock-names: should contain the names of the previous clocks -- resets: should contain the parser reset -- reset-names: should be "esparser" - -Example: - -vdec: video-codec@c8820000 { - compatible = "amlogic,gxbb-vdec", "amlogic,gx-vdec"; - reg = <0x0 0xc8820000 0x0 0x10000>, - <0x0 0xc110a580 0x0 0xe4>; - reg-names = "dos", "esparser"; - - interrupts = , - ; - interrupt-names = "vdec", "esparser"; - - amlogic,ao-sysctrl = <&sysctrl_AO>; - amlogic,canvas = <&canvas>; - - clocks = <&clkc CLKID_DOS_PARSER>, - <&clkc CLKID_DOS>, - <&clkc CLKID_VDEC_1>, - <&clkc CLKID_VDEC_HEVC>; - clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc"; - - resets = <&reset RESET_PARSER>; - reset-names = "esparser"; -}; -- cgit v1.2.3 From 70ae805a0bb9b926d5c92321ee8018f99638a9a0 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 5 Dec 2019 16:34:06 +0100 Subject: media: dt-bindings: media: amlogic,gx-vdec: add bindings for G12A family Add bindings to support the Amlogic Video Decoder on the Amlogic G12A family. For the G12A family, a supplementary clock is needed to operate the HEVC/VP9 decoder. Signed-off-by: Neil Armstrong Reviewed-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/amlogic,gx-vdec.yaml | 42 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml b/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml index 878944867d6e..cc8dc264fc72 100644 --- a/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml +++ b/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml @@ -27,12 +27,15 @@ description: | properties: compatible: - items: + oneOf: + - items: + - enum: + - amlogic,gxbb-vdec # GXBB (S905) + - amlogic,gxl-vdec # GXL (S905X, S905D) + - amlogic,gxm-vdec # GXM (S912) + - const: amlogic,gx-vdec - enum: - - amlogic,gxbb-vdec # GXBB (S905) - - amlogic,gxl-vdec # GXL (S905X, S905D) - - amlogic,gxm-vdec # GXM (S912) - - const: amlogic,gx-vdec + - amlogic,g12a-vdec # G12A (S905X2, S905D2) interrupts: minItems: 2 @@ -59,13 +62,17 @@ properties: clocks: minItems: 4 + maxItems: 5 clock-names: + minItems: 4 + maxItems: 5 items: - const: dos_parser - const: dos - const: vdec_1 - const: vdec_hevc + - const: vdec_hevcf amlogic,ao-sysctrl: description: should point to the AOBUS sysctrl node @@ -77,6 +84,31 @@ properties: allOf: - $ref: /schemas/types.yaml#/definitions/phandle +allOf: + - if: + properties: + compatible: + contains: + enum: + - amlogic,gx-vdec + + then: + properties: + clock-names: + maxItems: 4 + + - if: + properties: + compatible: + contains: + enum: + - amlogic,g12a-vdec + + then: + properties: + clock-names: + minItems: 5 + required: - compatible - reg -- cgit v1.2.3 From 3d8af3b40d2a3b899a07119dc90e8e6821a094b9 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 21 Nov 2019 11:14:27 +0100 Subject: media: dt-bindings: media: amlogic,gx-vdec: add bindings for SM1 family Add bindings to support the Amlogic Video Decoder on the Amlogic SM1 family. SM1 has a slightly different power management handling, thus needing a separate compatible. Signed-off-by: Neil Armstrong Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml b/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml index cc8dc264fc72..335717e15970 100644 --- a/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml +++ b/Documentation/devicetree/bindings/media/amlogic,gx-vdec.yaml @@ -36,6 +36,7 @@ properties: - const: amlogic,gx-vdec - enum: - amlogic,g12a-vdec # G12A (S905X2, S905D2) + - amlogic,sm1-vdec # SM1 (S905X3, S905D3) interrupts: minItems: 2 @@ -103,6 +104,7 @@ allOf: contains: enum: - amlogic,g12a-vdec + - amlogic,sm1-vdec then: properties: -- cgit v1.2.3 From 9f9dc4755e5497d491c24c78d34090993d623230 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 8 Nov 2019 03:16:07 +0100 Subject: media: dt-bindings: rcar-vin: Remove paragraph about aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It might be convenient to have aliases but it's not required, drop the sentence as it's not true and not used in Gen3 DTS files. Signed-off-by: Niklas Söderlund Acked-by: Geert Uytterhoeven Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,vin.txt | 3 --- 1 file changed, 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/renesas,vin.txt b/Documentation/devicetree/bindings/media/renesas,vin.txt index e30b0d4eefdd..e6136d43b077 100644 --- a/Documentation/devicetree/bindings/media/renesas,vin.txt +++ b/Documentation/devicetree/bindings/media/renesas,vin.txt @@ -41,9 +41,6 @@ on Gen3 and RZ/G2 platforms to a CSI-2 receiver. - interrupts: the interrupt for the device - clocks: Reference to the parent clock -Additionally, an alias named vinX will need to be created to specify -which video input device this is. - The per-board settings for Gen2 and RZ/G1 platforms: - port - sub-node describing a single endpoint connected to the VIN -- cgit v1.2.3 From a36807784b74a5218977e829c16e05b2fc98f8ff Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 8 Nov 2019 03:16:08 +0100 Subject: media: dt-bindings: rcar-vin: Document compatibility string for R8A77470 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When adding the compatibility string for R8A77470 (RZ/G1C) to the rcar-vin driver the string was never documented in the bindings, add it now. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,vin.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/renesas,vin.txt b/Documentation/devicetree/bindings/media/renesas,vin.txt index e6136d43b077..5eefd62ac5c5 100644 --- a/Documentation/devicetree/bindings/media/renesas,vin.txt +++ b/Documentation/devicetree/bindings/media/renesas,vin.txt @@ -13,6 +13,7 @@ on Gen3 and RZ/G2 platforms to a CSI-2 receiver. - "renesas,vin-r8a7743" for the R8A7743 device - "renesas,vin-r8a7744" for the R8A7744 device - "renesas,vin-r8a7745" for the R8A7745 device + - "renesas,vin-r8a77470" for the R8A77470 device - "renesas,vin-r8a774a1" for the R8A774A1 device - "renesas,vin-r8a774b1" for the R8A774B1 device - "renesas,vin-r8a774c0" for the R8A774C0 device -- cgit v1.2.3 From 94010145a58f169e73e6c7e88b57017112814955 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 19 Nov 2019 11:51:16 +0100 Subject: media: pixfmt-tch-td16/tu16.rst: document that this is little endian Testing with the rmi_f54 driver on the Lenovo X1 Carbon 6th gen laptop showed that the data is in little endian format. Update the documentation accordingly. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/pixfmt-tch-td16.rst | 34 ++++++++++++------------ Documentation/media/uapi/v4l/pixfmt-tch-tu16.rst | 34 ++++++++++++------------ 2 files changed, 34 insertions(+), 34 deletions(-) (limited to 'Documentation') diff --git a/Documentation/media/uapi/v4l/pixfmt-tch-td16.rst b/Documentation/media/uapi/v4l/pixfmt-tch-td16.rst index 4031b175257c..6f1be873bec1 100644 --- a/Documentation/media/uapi/v4l/pixfmt-tch-td16.rst +++ b/Documentation/media/uapi/v4l/pixfmt-tch-td16.rst @@ -15,7 +15,7 @@ V4L2_TCH_FMT_DELTA_TD16 ('TD16') *man V4L2_TCH_FMT_DELTA_TD16(2)* -16-bit signed Touch Delta +16-bit signed little endian Touch Delta Description @@ -37,38 +37,38 @@ Each cell is one byte. :widths: 2 1 1 1 1 1 1 1 1 * - start + 0: - - D'\ :sub:`00high` - D'\ :sub:`00low` - - D'\ :sub:`01high` + - D'\ :sub:`00high` - D'\ :sub:`01low` - - D'\ :sub:`02high` + - D'\ :sub:`01high` - D'\ :sub:`02low` - - D'\ :sub:`03high` + - D'\ :sub:`02high` - D'\ :sub:`03low` + - D'\ :sub:`03high` * - start + 8: - - D'\ :sub:`10high` - D'\ :sub:`10low` - - D'\ :sub:`11high` + - D'\ :sub:`10high` - D'\ :sub:`11low` - - D'\ :sub:`12high` + - D'\ :sub:`11high` - D'\ :sub:`12low` - - D'\ :sub:`13high` + - D'\ :sub:`12high` - D'\ :sub:`13low` + - D'\ :sub:`13high` * - start + 16: - - D'\ :sub:`20high` - D'\ :sub:`20low` - - D'\ :sub:`21high` + - D'\ :sub:`20high` - D'\ :sub:`21low` - - D'\ :sub:`22high` + - D'\ :sub:`21high` - D'\ :sub:`22low` - - D'\ :sub:`23high` + - D'\ :sub:`22high` - D'\ :sub:`23low` + - D'\ :sub:`23high` * - start + 24: - - D'\ :sub:`30high` - D'\ :sub:`30low` - - D'\ :sub:`31high` + - D'\ :sub:`30high` - D'\ :sub:`31low` - - D'\ :sub:`32high` + - D'\ :sub:`31high` - D'\ :sub:`32low` - - D'\ :sub:`33high` + - D'\ :sub:`32high` - D'\ :sub:`33low` + - D'\ :sub:`33high` diff --git a/Documentation/media/uapi/v4l/pixfmt-tch-tu16.rst b/Documentation/media/uapi/v4l/pixfmt-tch-tu16.rst index 8278543be99a..cb3da6687a58 100644 --- a/Documentation/media/uapi/v4l/pixfmt-tch-tu16.rst +++ b/Documentation/media/uapi/v4l/pixfmt-tch-tu16.rst @@ -15,7 +15,7 @@ V4L2_TCH_FMT_TU16 ('TU16') *man V4L2_TCH_FMT_TU16(2)* -16-bit unsigned raw touch data +16-bit unsigned little endian raw touch data Description @@ -36,38 +36,38 @@ Each cell is one byte. :widths: 2 1 1 1 1 1 1 1 1 * - start + 0: - - R'\ :sub:`00high` - R'\ :sub:`00low` - - R'\ :sub:`01high` + - R'\ :sub:`00high` - R'\ :sub:`01low` - - R'\ :sub:`02high` + - R'\ :sub:`01high` - R'\ :sub:`02low` - - R'\ :sub:`03high` + - R'\ :sub:`02high` - R'\ :sub:`03low` + - R'\ :sub:`03high` * - start + 8: - - R'\ :sub:`10high` - R'\ :sub:`10low` - - R'\ :sub:`11high` + - R'\ :sub:`10high` - R'\ :sub:`11low` - - R'\ :sub:`12high` + - R'\ :sub:`11high` - R'\ :sub:`12low` - - R'\ :sub:`13high` + - R'\ :sub:`12high` - R'\ :sub:`13low` + - R'\ :sub:`13high` * - start + 16: - - R'\ :sub:`20high` - R'\ :sub:`20low` - - R'\ :sub:`21high` + - R'\ :sub:`20high` - R'\ :sub:`21low` - - R'\ :sub:`22high` + - R'\ :sub:`21high` - R'\ :sub:`22low` - - R'\ :sub:`23high` + - R'\ :sub:`22high` - R'\ :sub:`23low` + - R'\ :sub:`23high` * - start + 24: - - R'\ :sub:`30high` - R'\ :sub:`30low` - - R'\ :sub:`31high` + - R'\ :sub:`30high` - R'\ :sub:`31low` - - R'\ :sub:`32high` + - R'\ :sub:`31high` - R'\ :sub:`32low` - - R'\ :sub:`33high` + - R'\ :sub:`32high` - R'\ :sub:`33low` + - R'\ :sub:`33high` -- cgit v1.2.3 From 0fb36893c6c129d48965332a23fa4ea6b075ad0c Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 5 Dec 2019 15:24:40 +0100 Subject: media: vidioc-enum-fmt.rst: clarify format preference It has been decided to use the ENUM_FMT index value as a hint for driver preference. This is defined purposedly in a very liberal way, letting drivers define what "preference" means. For instance, the Hantro VPU driver indicates additional processing to output a given format, and thus implicates more CPU usage, which is enumerated after native (non-processed) formats. Signed-off-by: Ezequiel Garcia Reviewed-by: Boris Brezillon Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/v4l/vidioc-enum-fmt.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst b/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst index 399ef1062bac..8ca6ab701e4a 100644 --- a/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst +++ b/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst @@ -44,7 +44,9 @@ To enumerate image formats applications initialize the ``type`` and the :ref:`VIDIOC_ENUM_FMT` ioctl with a pointer to this structure. Drivers fill the rest of the structure or return an ``EINVAL`` error code. All formats are enumerable by beginning at index zero and incrementing by -one until ``EINVAL`` is returned. +one until ``EINVAL`` is returned. If applicable, drivers shall return +formats in preference order, where preferred formats are returned before +(that is, with lower ``index`` value) less-preferred formats. .. note:: -- cgit v1.2.3 From ad848dd53385b61f3c2b94d3466bf799f31035a7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 8 Dec 2019 15:55:06 +0100 Subject: dt-bindings: gpu: mali-bifrost: Add Rockchip PX30 Define a compatible string for the Mali Bifrost GPU found in Rockchip's PX30 SoCs. Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20191208145508.3124-1-heiko@sntech.de --- Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml index 0c426e371e71..4ea6a8789699 100644 --- a/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml +++ b/Documentation/devicetree/bindings/gpu/arm,mali-bifrost.yaml @@ -18,6 +18,7 @@ properties: - enum: - amlogic,meson-g12a-mali - realtek,rtd1619-mali + - rockchip,px30-mali - const: arm,mali-bifrost # Mali Bifrost GPU model/revision is fully discoverable reg: -- cgit v1.2.3 From c2753d15d2b33f980ef4dbb657373a3f327533eb Mon Sep 17 00:00:00 2001 From: Katsuhiro Suzuki Date: Mon, 2 Dec 2019 14:59:29 +0900 Subject: arm64: dts: rockchip: split rk3399-rockpro64 for v2 and v2.1 boards This patch splits rk3399-rockpro64 dts file to 2 files for v2 and v2.1 boards. Both v2 and v2.1 boards can use almost same settings but we find a difference in I2C address of audio CODEC ES8136. Reported-by: Vasily Khoruzhick Signed-off-by: Katsuhiro Suzuki Link: https://lore.kernel.org/r/20191202055929.26540-1-katsuhiro@katsuster.net [put pine64,rockpro64-v2.* into an enum] Signed-off-by: Heiko Stuebner --- .../devicetree/bindings/arm/rockchip.yaml | 3 + arch/arm64/boot/dts/rockchip/Makefile | 1 + .../boot/dts/rockchip/rk3399-rockpro64-v2.dts | 30 + arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts | 759 +------------------- arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi | 763 +++++++++++++++++++++ 5 files changed, 801 insertions(+), 755 deletions(-) create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-rockpro64-v2.dts create mode 100644 arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index d9847b306b83..86307c66b4bd 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -409,6 +409,9 @@ properties: - description: Pine64 RockPro64 items: + - enum: + - pine64,rockpro64-v2.1 + - pine64,rockpro64-v2.0 - const: pine64,rockpro64 - const: rockchip,rk3399 diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile index 48fb631d5451..ee67175f3e78 100644 --- a/arch/arm64/boot/dts/rockchip/Makefile +++ b/arch/arm64/boot/dts/rockchip/Makefile @@ -33,6 +33,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc-mezzanine.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock960.dtb +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64-v2.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64-v2.dts b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64-v2.dts new file mode 100644 index 000000000000..304e3c51391c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64-v2.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (c) 2018 Akash Gajjar + * Copyright (c) 2019 Katsuhiro Suzuki + */ + +/dts-v1/; +#include "rk3399-rockpro64.dtsi" + +/ { + model = "Pine64 RockPro64 v2.0"; + compatible = "pine64,rockpro64-v2.0", "pine64,rockpro64", "rockchip,rk3399"; +}; + +&i2c1 { + es8316: codec@10 { + compatible = "everest,es8316"; + reg = <0x10>; + clocks = <&cru SCLK_I2S_8CH_OUT>; + clock-names = "mclk"; + #sound-dai-cells = <0>; + + port { + es8316_p0_0: endpoint { + remote-endpoint = <&i2s1_p0_0>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts index 7f4b2eba31d4..4b42717800f7 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dts @@ -2,481 +2,18 @@ /* * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. * Copyright (c) 2018 Akash Gajjar + * Copyright (c) 2019 Katsuhiro Suzuki */ /dts-v1/; -#include -#include -#include "rk3399.dtsi" -#include "rk3399-opp.dtsi" +#include "rk3399-rockpro64.dtsi" / { - model = "Pine64 RockPro64"; - compatible = "pine64,rockpro64", "rockchip,rk3399"; - - chosen { - stdout-path = "serial2:1500000n8"; - }; - - clkin_gmac: external-gmac-clock { - compatible = "fixed-clock"; - clock-frequency = <125000000>; - clock-output-names = "clkin_gmac"; - #clock-cells = <0>; - }; - - gpio-keys { - compatible = "gpio-keys"; - autorepeat; - pinctrl-names = "default"; - pinctrl-0 = <&pwrbtn>; - - power { - debounce-interval = <100>; - gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; - label = "GPIO Key Power"; - linux,code = ; - wakeup-source; - }; - }; - - leds { - compatible = "gpio-leds"; - pinctrl-names = "default"; - pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>; - - work-led { - label = "work"; - default-state = "on"; - gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; - }; - - diy-led { - label = "diy"; - default-state = "off"; - gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; - }; - }; - - fan: pwm-fan { - compatible = "pwm-fan"; - #cooling-cells = <2>; - fan-supply = <&vcc12v_dcin>; - pwms = <&pwm1 0 50000 0>; - }; - - sdio_pwrseq: sdio-pwrseq { - compatible = "mmc-pwrseq-simple"; - clocks = <&rk808 1>; - clock-names = "ext_clock"; - pinctrl-names = "default"; - pinctrl-0 = <&wifi_enable_h>; - - /* - * On the module itself this is one of these (depending - * on the actual card populated): - * - SDIO_RESET_L_WL_REG_ON - * - PDN (power down when low) - */ - reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; - }; - - sound { - compatible = "audio-graph-card"; - label = "rockchip,rk3399"; - dais = <&i2s1_p0>; - }; - - vcc12v_dcin: vcc12v-dcin { - compatible = "regulator-fixed"; - regulator-name = "vcc12v_dcin"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <12000000>; - regulator-max-microvolt = <12000000>; - }; - - /* switched by pmic_sleep */ - vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 { - compatible = "regulator-fixed"; - regulator-name = "vcc1v8_s3"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - vin-supply = <&vcc_1v8>; - }; - - vcc3v3_pcie: vcc3v3-pcie-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_pwr_en>; - regulator-name = "vcc3v3_pcie"; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc12v_dcin>; - }; - - vcc3v3_sys: vcc3v3-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc3v3_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - vin-supply = <&vcc5v0_sys>; - }; - - /* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */ - vcc5v0_host: vcc5v0-host-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_host_en>; - regulator-name = "vcc5v0_host"; - regulator-always-on; - vin-supply = <&vcc5v0_usb>; - }; - - vcc5v0_typec: vcc5v0-typec-regulator { - compatible = "regulator-fixed"; - enable-active-high; - gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; - pinctrl-names = "default"; - pinctrl-0 = <&vcc5v0_typec_en>; - regulator-name = "vcc5v0_typec"; - regulator-always-on; - vin-supply = <&vcc5v0_usb>; - }; - - vcc5v0_sys: vcc5v0-sys { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_sys"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc12v_dcin>; - }; - - vcc5v0_usb: vcc5v0-usb { - compatible = "regulator-fixed"; - regulator-name = "vcc5v0_usb"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - vin-supply = <&vcc12v_dcin>; - }; - - vdd_log: vdd-log { - compatible = "pwm-regulator"; - pwms = <&pwm2 0 25000 1>; - regulator-name = "vdd_log"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <800000>; - regulator-max-microvolt = <1700000>; - vin-supply = <&vcc5v0_sys>; - }; -}; - -&cpu_l0 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_l1 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_l2 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_l3 { - cpu-supply = <&vdd_cpu_l>; -}; - -&cpu_b0 { - cpu-supply = <&vdd_cpu_b>; -}; - -&cpu_b1 { - cpu-supply = <&vdd_cpu_b>; -}; - -&emmc_phy { - status = "okay"; -}; - -&gmac { - assigned-clocks = <&cru SCLK_RMII_SRC>; - assigned-clock-parents = <&clkin_gmac>; - clock_in_out = "input"; - phy-supply = <&vcc_lan>; - phy-mode = "rgmii"; - pinctrl-names = "default"; - pinctrl-0 = <&rgmii_pins>; - snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; - snps,reset-active-low; - snps,reset-delays-us = <0 10000 50000>; - tx_delay = <0x28>; - rx_delay = <0x11>; - status = "okay"; -}; - -&hdmi { - ddc-i2c-bus = <&i2c3>; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_cec>; - status = "okay"; -}; - -&hdmi_sound { - status = "okay"; -}; - -&gpu { - mali-supply = <&vdd_gpu>; - status = "okay"; -}; - -&i2c0 { - clock-frequency = <400000>; - i2c-scl-rising-time-ns = <168>; - i2c-scl-falling-time-ns = <4>; - status = "okay"; - - rk808: pmic@1b { - compatible = "rockchip,rk808"; - reg = <0x1b>; - interrupt-parent = <&gpio3>; - interrupts = <10 IRQ_TYPE_LEVEL_LOW>; - #clock-cells = <1>; - clock-output-names = "xin32k", "rk808-clkout2"; - pinctrl-names = "default"; - pinctrl-0 = <&pmic_int_l>; - rockchip,system-power-controller; - wakeup-source; - - vcc1-supply = <&vcc5v0_sys>; - vcc2-supply = <&vcc5v0_sys>; - vcc3-supply = <&vcc5v0_sys>; - vcc4-supply = <&vcc5v0_sys>; - vcc6-supply = <&vcc5v0_sys>; - vcc7-supply = <&vcc5v0_sys>; - vcc8-supply = <&vcc3v3_sys>; - vcc9-supply = <&vcc5v0_sys>; - vcc10-supply = <&vcc5v0_sys>; - vcc11-supply = <&vcc5v0_sys>; - vcc12-supply = <&vcc3v3_sys>; - vddio-supply = <&vcca_1v8>; - - regulators { - vdd_center: DCDC_REG1 { - regulator-name = "vdd_center"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_cpu_l: DCDC_REG2 { - regulator-name = "vdd_cpu_l"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <750000>; - regulator-max-microvolt = <1350000>; - regulator-ramp-delay = <6001>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_ddr: DCDC_REG3 { - regulator-name = "vcc_ddr"; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-on-in-suspend; - }; - }; - - vcc_1v8: DCDC_REG4 { - regulator-name = "vcc_1v8"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc1v8_dvp: LDO_REG1 { - regulator-name = "vcc1v8_dvp"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc3v0_touch: LDO_REG2 { - regulator-name = "vcc3v0_touch"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcca_1v8: LDO_REG3 { - regulator-name = "vcca_1v8"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1800000>; - }; - }; - - vcc_sdio: LDO_REG4 { - regulator-name = "vcc_sdio"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3000000>; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; - }; - }; - - vcca3v0_codec: LDO_REG5 { - regulator-name = "vcca3v0_codec"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_1v5: LDO_REG6 { - regulator-name = "vcc_1v5"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <1500000>; - }; - }; - - vcca1v8_codec: LDO_REG7 { - regulator-name = "vcca1v8_codec"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc_3v0: LDO_REG8 { - regulator-name = "vcc_3v0"; - regulator-always-on; - regulator-boot-on; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-state-mem { - regulator-on-in-suspend; - regulator-suspend-microvolt = <3000000>; - }; - }; - - vcc3v3_s3: vcc_lan: SWITCH_REG1 { - regulator-name = "vcc3v3_s3"; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vcc3v3_s0: SWITCH_REG2 { - regulator-name = "vcc3v3_s0"; - regulator-always-on; - regulator-boot-on; - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - }; - }; - - vdd_cpu_b: regulator@40 { - compatible = "silergy,syr827"; - reg = <0x40>; - fcs,suspend-voltage-selector = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&vsel1_gpio>; - regulator-name = "vdd_cpu_b"; - regulator-min-microvolt = <712500>; - regulator-max-microvolt = <1500000>; - regulator-ramp-delay = <1000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc5v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; - - vdd_gpu: regulator@41 { - compatible = "silergy,syr828"; - reg = <0x41>; - fcs,suspend-voltage-selector = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&vsel2_gpio>; - regulator-name = "vdd_gpu"; - regulator-min-microvolt = <712500>; - regulator-max-microvolt = <1500000>; - regulator-ramp-delay = <1000>; - regulator-always-on; - regulator-boot-on; - vin-supply = <&vcc5v0_sys>; - - regulator-state-mem { - regulator-off-in-suspend; - }; - }; + model = "Pine64 RockPro64 v2.1"; + compatible = "pine64,rockpro64-v2.1", "pine64,rockpro64", "rockchip,rk3399"; }; &i2c1 { - i2c-scl-rising-time-ns = <300>; - i2c-scl-falling-time-ns = <15>; - status = "okay"; - es8316: codec@11 { compatible = "everest,es8316"; reg = <0x11>; @@ -491,291 +28,3 @@ }; }; }; - -&i2c3 { - i2c-scl-rising-time-ns = <450>; - i2c-scl-falling-time-ns = <15>; - status = "okay"; -}; - -&i2c4 { - i2c-scl-rising-time-ns = <600>; - i2c-scl-falling-time-ns = <20>; - status = "okay"; - - fusb0: typec-portc@22 { - compatible = "fcs,fusb302"; - reg = <0x22>; - interrupt-parent = <&gpio1>; - interrupts = ; - pinctrl-names = "default"; - pinctrl-0 = <&fusb0_int>; - vbus-supply = <&vcc5v0_typec>; - status = "okay"; - }; -}; - -&i2s0 { - rockchip,playback-channels = <8>; - rockchip,capture-channels = <8>; - status = "okay"; -}; - -&i2s1 { - rockchip,playback-channels = <2>; - rockchip,capture-channels = <2>; - status = "okay"; - - i2s1_p0: port { - i2s1_p0_0: endpoint { - dai-format = "i2s"; - mclk-fs = <256>; - remote-endpoint = <&es8316_p0_0>; - }; - }; -}; - -&i2s2 { - status = "okay"; -}; - -&io_domains { - status = "okay"; - - bt656-supply = <&vcc1v8_dvp>; - audio-supply = <&vcc_3v0>; - sdmmc-supply = <&vcc_sdio>; - gpio1830-supply = <&vcc_3v0>; -}; - -&pcie0 { - ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>; - num-lanes = <4>; - pinctrl-names = "default"; - pinctrl-0 = <&pcie_perst>; - vpcie12v-supply = <&vcc12v_dcin>; - vpcie3v3-supply = <&vcc3v3_pcie>; - status = "okay"; -}; - -&pcie_phy { - status = "okay"; -}; - -&pmu_io_domains { - pmu1830-supply = <&vcc_3v0>; - status = "okay"; -}; - -&pinctrl { - buttons { - pwrbtn: pwrbtn { - rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - fusb302x { - fusb0_int: fusb0-int { - rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - leds { - work_led_gpio: work_led-gpio { - rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - diy_led_gpio: diy_led-gpio { - rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - pcie { - pcie_perst: pcie-perst { - rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; - }; - - pcie_pwr_en: pcie-pwr-en { - rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - pmic { - pmic_int_l: pmic-int-l { - rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; - }; - - vsel1_gpio: vsel1-gpio { - rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; - }; - - vsel2_gpio: vsel2-gpio { - rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; - }; - }; - - sdio-pwrseq { - wifi_enable_h: wifi-enable-h { - rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; - - usb-typec { - vcc5v0_typec_en: vcc5v0_typec_en { - rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; - - usb2 { - vcc5v0_host_en: vcc5v0-host-en { - rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; - }; - }; -}; - -&pwm0 { - status = "okay"; -}; - -&pwm1 { - status = "okay"; -}; - -&pwm2 { - status = "okay"; -}; - -&saradc { - vref-supply = <&vcca1v8_s3>; - status = "okay"; -}; - -&sdmmc { - bus-width = <4>; - cap-sd-highspeed; - cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; - disable-wp; - max-frequency = <150000000>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; - status = "okay"; -}; - -&sdhci { - bus-width = <8>; - mmc-hs200-1_8v; - non-removable; - status = "okay"; -}; - -&spi1 { - status = "okay"; - - flash@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <10000000>; - }; -}; - -&tcphy0 { - status = "okay"; -}; - -&tcphy1 { - status = "okay"; -}; - -&tsadc { - /* tshut mode 0:CRU 1:GPIO */ - rockchip,hw-tshut-mode = <1>; - /* tshut polarity 0:LOW 1:HIGH */ - rockchip,hw-tshut-polarity = <1>; - status = "okay"; -}; - -&u2phy0 { - status = "okay"; - - u2phy0_otg: otg-port { - status = "okay"; - }; - - u2phy0_host: host-port { - phy-supply = <&vcc5v0_host>; - status = "okay"; - }; -}; - -&u2phy1 { - status = "okay"; - - u2phy1_otg: otg-port { - status = "okay"; - }; - - u2phy1_host: host-port { - phy-supply = <&vcc5v0_host>; - status = "okay"; - }; -}; - -&uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_xfer &uart0_cts>; - status = "okay"; -}; - -&uart2 { - status = "okay"; -}; - -&usb_host0_ehci { - status = "okay"; -}; - -&usb_host0_ohci { - status = "okay"; -}; - -&usb_host1_ehci { - status = "okay"; -}; - -&usb_host1_ohci { - status = "okay"; -}; - -&usbdrd3_0 { - status = "okay"; -}; - -&usbdrd_dwc3_0 { - status = "okay"; - dr_mode = "otg"; -}; - -&usbdrd3_1 { - status = "okay"; -}; - -&usbdrd_dwc3_1 { - status = "okay"; - dr_mode = "host"; -}; - -&vopb { - status = "okay"; -}; - -&vopb_mmu { - status = "okay"; -}; - -&vopl { - status = "okay"; -}; - -&vopl_mmu { - status = "okay"; -}; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi new file mode 100644 index 000000000000..183eda4ffb9c --- /dev/null +++ b/arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi @@ -0,0 +1,763 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + * Copyright (c) 2018 Akash Gajjar + */ + +#include +#include +#include "rk3399.dtsi" +#include "rk3399-opp.dtsi" + +/ { + chosen { + stdout-path = "serial2:1500000n8"; + }; + + clkin_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "clkin_gmac"; + #clock-cells = <0>; + }; + + gpio-keys { + compatible = "gpio-keys"; + autorepeat; + pinctrl-names = "default"; + pinctrl-0 = <&pwrbtn>; + + power { + debounce-interval = <100>; + gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>; + label = "GPIO Key Power"; + linux,code = ; + wakeup-source; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>; + + work-led { + label = "work"; + default-state = "on"; + gpios = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>; + }; + + diy-led { + label = "diy"; + default-state = "off"; + gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; + }; + }; + + fan: pwm-fan { + compatible = "pwm-fan"; + #cooling-cells = <2>; + fan-supply = <&vcc12v_dcin>; + pwms = <&pwm1 0 50000 0>; + }; + + sdio_pwrseq: sdio-pwrseq { + compatible = "mmc-pwrseq-simple"; + clocks = <&rk808 1>; + clock-names = "ext_clock"; + pinctrl-names = "default"; + pinctrl-0 = <&wifi_enable_h>; + + /* + * On the module itself this is one of these (depending + * on the actual card populated): + * - SDIO_RESET_L_WL_REG_ON + * - PDN (power down when low) + */ + reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>; + }; + + sound { + compatible = "audio-graph-card"; + label = "rockchip,rk3399"; + dais = <&i2s1_p0>; + }; + + vcc12v_dcin: vcc12v-dcin { + compatible = "regulator-fixed"; + regulator-name = "vcc12v_dcin"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + /* switched by pmic_sleep */ + vcc1v8_s3: vcca1v8_s3: vcc1v8-s3 { + compatible = "regulator-fixed"; + regulator-name = "vcc1v8_s3"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc_1v8>; + }; + + vcc3v3_pcie: vcc3v3-pcie-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pwr_en>; + regulator-name = "vcc3v3_pcie"; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc12v_dcin>; + }; + + vcc3v3_sys: vcc3v3-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vcc5v0_sys>; + }; + + /* Actually 3 regulators (host0, 1, 2) controlled by the same gpio */ + vcc5v0_host: vcc5v0-host-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio4 RK_PD2 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + regulator-name = "vcc5v0_host"; + regulator-always-on; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_typec: vcc5v0-typec-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_typec_en>; + regulator-name = "vcc5v0_typec"; + regulator-always-on; + vin-supply = <&vcc5v0_usb>; + }; + + vcc5v0_sys: vcc5v0-sys { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_sys"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vcc5v0_usb: vcc5v0-usb { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0_usb"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; + + vdd_log: vdd-log { + compatible = "pwm-regulator"; + pwms = <&pwm2 0 25000 1>; + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1700000>; + vin-supply = <&vcc5v0_sys>; + }; +}; + +&cpu_l0 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l1 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l2 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_l3 { + cpu-supply = <&vdd_cpu_l>; +}; + +&cpu_b0 { + cpu-supply = <&vdd_cpu_b>; +}; + +&cpu_b1 { + cpu-supply = <&vdd_cpu_b>; +}; + +&emmc_phy { + status = "okay"; +}; + +&gmac { + assigned-clocks = <&cru SCLK_RMII_SRC>; + assigned-clock-parents = <&clkin_gmac>; + clock_in_out = "input"; + phy-supply = <&vcc_lan>; + phy-mode = "rgmii"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 50000>; + tx_delay = <0x28>; + rx_delay = <0x11>; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c3>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_cec>; + status = "okay"; +}; + +&hdmi_sound { + status = "okay"; +}; + +&gpu { + mali-supply = <&vdd_gpu>; + status = "okay"; +}; + +&i2c0 { + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <168>; + i2c-scl-falling-time-ns = <4>; + status = "okay"; + + rk808: pmic@1b { + compatible = "rockchip,rk808"; + reg = <0x1b>; + interrupt-parent = <&gpio3>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <1>; + clock-output-names = "xin32k", "rk808-clkout2"; + pinctrl-names = "default"; + pinctrl-0 = <&pmic_int_l>; + rockchip,system-power-controller; + wakeup-source; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc3v3_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc5v0_sys>; + vcc12-supply = <&vcc3v3_sys>; + vddio-supply = <&vcca_1v8>; + + regulators { + vdd_center: DCDC_REG1 { + regulator-name = "vdd_center"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_cpu_l: DCDC_REG2 { + regulator-name = "vdd_cpu_l"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <1350000>; + regulator-ramp-delay = <6001>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_ddr: DCDC_REG3 { + regulator-name = "vcc_ddr"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v8: DCDC_REG4 { + regulator-name = "vcc_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc1v8_dvp: LDO_REG1 { + regulator-name = "vcc1v8_dvp"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v0_touch: LDO_REG2 { + regulator-name = "vcc3v0_touch"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcca_1v8: LDO_REG3 { + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_sdio: LDO_REG4 { + regulator-name = "vcc_sdio"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcca3v0_codec: LDO_REG5 { + regulator-name = "vcca3v0_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_1v5: LDO_REG6 { + regulator-name = "vcc_1v5"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1500000>; + }; + }; + + vcca1v8_codec: LDO_REG7 { + regulator-name = "vcca1v8_codec"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_3v0: LDO_REG8 { + regulator-name = "vcc_3v0"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3000000>; + }; + }; + + vcc3v3_s3: vcc_lan: SWITCH_REG1 { + regulator-name = "vcc3v3_s3"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc3v3_s0: SWITCH_REG2 { + regulator-name = "vcc3v3_s0"; + regulator-always-on; + regulator-boot-on; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + + vdd_cpu_b: regulator@40 { + compatible = "silergy,syr827"; + reg = <0x40>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&vsel1_gpio>; + regulator-name = "vdd_cpu_b"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu: regulator@41 { + compatible = "silergy,syr828"; + reg = <0x41>; + fcs,suspend-voltage-selector = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&vsel2_gpio>; + regulator-name = "vdd_gpu"; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1500000>; + regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vcc5v0_sys>; + + regulator-state-mem { + regulator-off-in-suspend; + }; + }; +}; + +&i2c1 { + i2c-scl-rising-time-ns = <300>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c3 { + i2c-scl-rising-time-ns = <450>; + i2c-scl-falling-time-ns = <15>; + status = "okay"; +}; + +&i2c4 { + i2c-scl-rising-time-ns = <600>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + fusb0: typec-portc@22 { + compatible = "fcs,fusb302"; + reg = <0x22>; + interrupt-parent = <&gpio1>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&fusb0_int>; + vbus-supply = <&vcc5v0_typec>; + status = "okay"; + }; +}; + +&i2s0 { + rockchip,playback-channels = <8>; + rockchip,capture-channels = <8>; + status = "okay"; +}; + +&i2s1 { + rockchip,playback-channels = <2>; + rockchip,capture-channels = <2>; + status = "okay"; + + i2s1_p0: port { + i2s1_p0_0: endpoint { + dai-format = "i2s"; + mclk-fs = <256>; + remote-endpoint = <&es8316_p0_0>; + }; + }; +}; + +&i2s2 { + status = "okay"; +}; + +&io_domains { + status = "okay"; + + bt656-supply = <&vcc1v8_dvp>; + audio-supply = <&vcc_3v0>; + sdmmc-supply = <&vcc_sdio>; + gpio1830-supply = <&vcc_3v0>; +}; + +&pcie0 { + ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>; + num-lanes = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&pcie_perst>; + vpcie12v-supply = <&vcc12v_dcin>; + vpcie3v3-supply = <&vcc3v3_pcie>; + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +&pmu_io_domains { + pmu1830-supply = <&vcc_3v0>; + status = "okay"; +}; + +&pinctrl { + buttons { + pwrbtn: pwrbtn { + rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + fusb302x { + fusb0_int: fusb0-int { + rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + leds { + work_led_gpio: work_led-gpio { + rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + diy_led_gpio: diy_led-gpio { + rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pcie { + pcie_perst: pcie-perst { + rockchip,pins = <2 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>; + }; + + pcie_pwr_en: pcie-pwr-en { + rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + pmic { + pmic_int_l: pmic-int-l { + rockchip,pins = <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>; + }; + + vsel1_gpio: vsel1-gpio { + rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>; + }; + + vsel2_gpio: vsel2-gpio { + rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>; + }; + }; + + sdio-pwrseq { + wifi_enable_h: wifi-enable-h { + rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + + usb-typec { + vcc5v0_typec_en: vcc5v0_typec_en { + rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + + usb2 { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; +}; + +&pwm0 { + status = "okay"; +}; + +&pwm1 { + status = "okay"; +}; + +&pwm2 { + status = "okay"; +}; + +&saradc { + vref-supply = <&vcca1v8_s3>; + status = "okay"; +}; + +&sdmmc { + bus-width = <4>; + cap-sd-highspeed; + cd-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + disable-wp; + max-frequency = <150000000>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>; + status = "okay"; +}; + +&sdhci { + bus-width = <8>; + mmc-hs200-1_8v; + non-removable; + status = "okay"; +}; + +&spi1 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + }; +}; + +&tcphy0 { + status = "okay"; +}; + +&tcphy1 { + status = "okay"; +}; + +&tsadc { + /* tshut mode 0:CRU 1:GPIO */ + rockchip,hw-tshut-mode = <1>; + /* tshut polarity 0:LOW 1:HIGH */ + rockchip,hw-tshut-polarity = <1>; + status = "okay"; +}; + +&u2phy0 { + status = "okay"; + + u2phy0_otg: otg-port { + status = "okay"; + }; + + u2phy0_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&u2phy1 { + status = "okay"; + + u2phy1_otg: otg-port { + status = "okay"; + }; + + u2phy1_host: host-port { + phy-supply = <&vcc5v0_host>; + status = "okay"; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_xfer &uart0_cts>; + status = "okay"; +}; + +&uart2 { + status = "okay"; +}; + +&usb_host0_ehci { + status = "okay"; +}; + +&usb_host0_ohci { + status = "okay"; +}; + +&usb_host1_ehci { + status = "okay"; +}; + +&usb_host1_ohci { + status = "okay"; +}; + +&usbdrd3_0 { + status = "okay"; +}; + +&usbdrd_dwc3_0 { + status = "okay"; + dr_mode = "otg"; +}; + +&usbdrd3_1 { + status = "okay"; +}; + +&usbdrd_dwc3_1 { + status = "okay"; + dr_mode = "host"; +}; + +&vopb { + status = "okay"; +}; + +&vopb_mmu { + status = "okay"; +}; + +&vopl { + status = "okay"; +}; + +&vopl_mmu { + status = "okay"; +}; -- cgit v1.2.3 From 0606f9b67e8c8727c1369096b3b142dd74dc0a39 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:27 +0100 Subject: dt-bindings: display: rockchip-dsi: document external phys Some dw-mipi-dsi instances in Rockchip SoCs use external dphys. In these cases the needs clock will also be generated externally so these don't need the ref-clock as well. changes in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Reviewed-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-4-heiko@sntech.de --- .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index ce4c1fc9116c..1ba9237d0ac0 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt @@ -9,8 +9,9 @@ Required properties: - reg: Represent the physical address range of the controller. - interrupts: Represent the controller's interrupt to the CPU(s). - clocks, clock-names: Phandles to the controller's pll reference - clock(ref) and APB clock(pclk). For RK3399, a phy config clock - (phy_cfg) and a grf clock(grf) are required. As described in [1]. + clock(ref) when using an internal dphy and APB clock(pclk). + For RK3399, a phy config clock (phy_cfg) and a grf clock(grf) + are required. As described in [1]. - rockchip,grf: this soc should set GRF regs to mux vopl/vopb. - ports: contain a port node with endpoint definitions as defined in [2]. For vopb,set the reg = <0> and set the reg = <1> for vopl. @@ -18,6 +19,8 @@ Required properties: - video port 1 for either a panel or subsequent encoder Optional properties: +- phys: from general PHY binding: the phandle for the PHY device. +- phy-names: Should be "dphy" if phys references an external phy. - power-domains: a phandle to mipi dsi power domain node. - resets: list of phandle + reset specifier pairs, as described in [3]. - reset-names: string reset name, must be "apb". -- cgit v1.2.3 From 95da672f386c937cc22f892fadb019de3b2c2f0d Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Mon, 9 Dec 2019 15:31:29 +0100 Subject: dt-bindings: display: rockchip-dsi: add px30 compatible The px30 SoC also uses a dw-mipi-dsi controller, so add the compatible value for it. changes in v5: - rebased on top of 5.5-rc1 - merged with dsi timing change to prevent ordering conflicts Signed-off-by: Heiko Stuebner Acked-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20191209143130.4553-6-heiko@sntech.de --- .../devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt index 1ba9237d0ac0..151be3bba06f 100644 --- a/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt +++ b/Documentation/devicetree/bindings/display/rockchip/dw_mipi_dsi_rockchip.txt @@ -4,8 +4,10 @@ Rockchip specific extensions to the Synopsys Designware MIPI DSI Required properties: - #address-cells: Should be <1>. - #size-cells: Should be <0>. -- compatible: "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi". - "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi". +- compatible: one of + "rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi" + "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi" + "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi" - reg: Represent the physical address range of the controller. - interrupts: Represent the controller's interrupt to the CPU(s). - clocks, clock-names: Phandles to the controller's pll reference -- cgit v1.2.3 From 4e7a4a6fbdc669c44e6079f9d5eb25673749455f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 18 Nov 2019 16:51:30 +0100 Subject: drm/modes: parse_cmdline: Add support for specifying panel_orientation (v2) Sometimes we want to override a connector's panel_orientation from the kernel commandline. Either for testing and for special cases, e.g. a kiosk like setup which uses a TV mounted in portrait mode. Users can already specify a "rotate" option through a video= kernel cmdline option. But that only supports 0/180 degrees (see drm_client_modeset TODO) and only works for in kernel modeset clients, not for userspace kms users. The "panel-orientation" connector property OTOH does support 90/270 degrees as it leaves dealing with the rotation up to userspace and this does work for userspace kms clients (at least those which support this property). Changes in v2: -Add missing ':' after @panel_orientation (reported by kbuild test robot) BugLink: https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/83 Acked-by: Maxime Ripard Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20191118155134.30468-9-hdegoede@redhat.com --- Documentation/fb/modedb.rst | 3 ++ drivers/gpu/drm/drm_modes.c | 32 ++++++++++++++++++++++ drivers/gpu/drm/selftests/drm_cmdline_selftests.h | 1 + .../gpu/drm/selftests/test-drm_cmdline_parser.c | 22 +++++++++++++++ include/drm/drm_connector.h | 8 ++++++ 5 files changed, 66 insertions(+) (limited to 'Documentation') diff --git a/Documentation/fb/modedb.rst b/Documentation/fb/modedb.rst index 9c4e3fd39e6d..624d08fd2856 100644 --- a/Documentation/fb/modedb.rst +++ b/Documentation/fb/modedb.rst @@ -65,6 +65,9 @@ Valid options are:: - reflect_y (boolean): Perform an axial symmetry on the Y axis - rotate (integer): Rotate the initial framebuffer by x degrees. Valid values are 0, 90, 180 and 270. + - panel_orientation, one of "normal", "upside_down", "left_side_up", or + "right_side_up". For KMS drivers only, this sets the "panel orientation" + property on the kms connector as hint for kms users. ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 2e82603f5d0a..119fed7ab815 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1591,6 +1591,33 @@ static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret) return 0; } +static int drm_mode_parse_panel_orientation(const char *delim, + struct drm_cmdline_mode *mode) +{ + const char *value; + + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + delim = strchr(value, ','); + if (!delim) + delim = value + strlen(value); + + if (!strncmp(value, "normal", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL; + else if (!strncmp(value, "upside_down", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP; + else if (!strncmp(value, "left_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP; + else if (!strncmp(value, "right_side_up", delim - value)) + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP; + else + return -EINVAL; + + return 0; +} + static int drm_mode_parse_cmdline_options(const char *str, bool freestanding, const struct drm_connector *connector, @@ -1657,6 +1684,9 @@ static int drm_mode_parse_cmdline_options(const char *str, return -EINVAL; mode->tv_margins.bottom = margin; + } else if (!strncmp(option, "panel_orientation", delim - option)) { + if (drm_mode_parse_panel_orientation(delim, mode)) + return -EINVAL; } else { return -EINVAL; } @@ -1715,6 +1745,8 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; int i, len, ret; + mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + #ifdef CONFIG_FB if (!mode_option) mode_option = fb_mode_option; diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h index aee92ac2cc21..ceac7af9a172 100644 --- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h +++ b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h @@ -64,3 +64,4 @@ cmdline_test(drm_cmdline_test_bpp_extra_and_option) cmdline_test(drm_cmdline_test_extra_and_option) cmdline_test(drm_cmdline_test_freestanding_options) cmdline_test(drm_cmdline_test_freestanding_force_e_and_options) +cmdline_test(drm_cmdline_test_panel_orientation) diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c index 8248d4aa5aaa..520f3e66a384 100644 --- a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c +++ b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c @@ -1092,6 +1092,28 @@ static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored) return 0; } +static int drm_cmdline_test_panel_orientation(void *ignored) +{ + struct drm_cmdline_mode mode = { }; + + FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down", + &no_connector, + &mode)); + FAIL_ON(mode.specified); + FAIL_ON(mode.refresh_specified); + FAIL_ON(mode.bpp_specified); + + FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP); + + FAIL_ON(mode.rb); + FAIL_ON(mode.cvt); + FAIL_ON(mode.interlace); + FAIL_ON(mode.margins); + FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED); + + return 0; +} + #include "drm_selftest.c" static int __init test_drm_cmdline_init(void) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 17b728d9c73d..221910948b37 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1069,6 +1069,14 @@ struct drm_cmdline_mode { */ unsigned int rotation_reflection; + /** + * @panel_orientation: + * + * drm-connector "panel orientation" property override value, + * DRM_MODE_PANEL_ORIENTATION_UNKNOWN if not set. + */ + enum drm_panel_orientation panel_orientation; + /** * @tv_margins: TV margins to apply to the mode. */ -- cgit v1.2.3 From efcc69b261f00ab01afecb2c0ca6cb95f17e740b Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Wed, 27 Nov 2019 11:49:59 +0000 Subject: dt-bindings: mmc: sdhci-msm: Add compatible string for sc7180 Add sc7180 SoC specific compatible strings for qcom-sdhci controller. Signed-off-by: Veerabhadrarao Badiganti Acked-by: Rob Herring Link: https://lore.kernel.org/r/0101016eacb255af-3985262d-9b7e-4813-88c2-61838406e12c-000000@us-west-2.amazonses.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt index da4edb146a98..7ee639b1af03 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt @@ -19,6 +19,7 @@ Required properties: "qcom,msm8996-sdhci", "qcom,sdhci-msm-v4" "qcom,sdm845-sdhci", "qcom,sdhci-msm-v5" "qcom,qcs404-sdhci", "qcom,sdhci-msm-v5" + "qcom,sc7180-sdhci", "qcom,sdhci-msm-v5"; NOTE that some old device tree files may be floating around that only have the string "qcom,sdhci-msm-v4" without the SoC compatible string but doing that should be considered a deprecated practice. -- cgit v1.2.3 From d684be14457fb69a5fd6af32ca2e232cb43c5efc Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 28 Nov 2019 08:45:20 +0100 Subject: dt-bindings: sdhci-of-at91: new compatible string and update properties There is a new compatible string for the SAM9X60 sdhci device. It involves an update of the properties about the clocks stuff. Signed-off-by: Ludovic Desroches Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191128074522.69706-1-ludovic.desroches@microchip.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-atmel.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt b/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt index 503c6dbac1b2..69edfd4d3922 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-atmel.txt @@ -5,11 +5,16 @@ Documentation/devicetree/bindings/mmc/mmc.txt and the properties used by the sdhci-of-at91 driver. Required properties: -- compatible: Must be "atmel,sama5d2-sdhci". +- compatible: Must be "atmel,sama5d2-sdhci" or "microchip,sam9x60-sdhci". - clocks: Phandlers to the clocks. -- clock-names: Must be "hclock", "multclk", "baseclk"; +- clock-names: Must be "hclock", "multclk", "baseclk" for + "atmel,sama5d2-sdhci". + Must be "hclock", "multclk" for "microchip,sam9x60-sdhci". Optional properties: +- assigned-clocks: The same with "multclk". +- assigned-clock-rates The rate of "multclk" in order to not rely on the + gck configuration set by previous components. - microchip,sdcal-inverted: when present, polarity on the SDCAL SoC pin is inverted. The default polarity for this signal is described in the datasheet. For instance on SAMA5D2, the pin is usually tied to the GND with a resistor @@ -17,10 +22,12 @@ Optional properties: Example: -sdmmc0: sdio-host@a0000000 { +mmc0: sdio-host@a0000000 { compatible = "atmel,sama5d2-sdhci"; reg = <0xa0000000 0x300>; interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&sdmmc0_hclk>, <&sdmmc0_gclk>, <&main>; clock-names = "hclock", "multclk", "baseclk"; + assigned-clocks = <&sdmmc0_gclk>; + assigned-clock-rates = <480000000>; }; -- cgit v1.2.3 From de27e978dc82ea22ef0f7999dfe870a087073907 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:43:48 +0100 Subject: dt-bindings: mmc: renesas_sdhi: Document r8a77961 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document support for the SDHI controller in the Renesas R-Car M3-W+ (R8A77961) SoC. Update all references to R-Car M3-W from "r8a7796" to "r8a77960", to avoid confusion between R-Car M3-W (R8A77960) and M3-W+. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20191205134349.6410-2-geert+renesas@glider.be Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/renesas,sdhi.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt b/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt index bc08fc43a9be..e6cc47844207 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt @@ -23,7 +23,8 @@ Required properties: "renesas,sdhi-r8a7793" - SDHI IP on R8A7793 SoC "renesas,sdhi-r8a7794" - SDHI IP on R8A7794 SoC "renesas,sdhi-r8a7795" - SDHI IP on R8A7795 SoC - "renesas,sdhi-r8a7796" - SDHI IP on R8A7796 SoC + "renesas,sdhi-r8a7796" - SDHI IP on R8A77960 SoC + "renesas,sdhi-r8a77961" - SDHI IP on R8A77961 SoC "renesas,sdhi-r8a77965" - SDHI IP on R8A77965 SoC "renesas,sdhi-r8a77970" - SDHI IP on R8A77970 SoC "renesas,sdhi-r8a77980" - SDHI IP on R8A77980 SoC -- cgit v1.2.3 From 6cc1d4568120bc8013b52873d9a40bdc6ae7802a Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 11 Dec 2019 11:47:57 +0200 Subject: docs: driver-model: Add missing managed GPIO array get functions devm_gpiod_get_array and devm_gpiod_get_array_optional were missing from the list. Add them. Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/f56dce4fcb71592cbcf0fc48a841f86f52770d4c.1576054779.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Linus Walleij --- Documentation/driver-api/driver-model/devres.rst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 13046fcf0a5d..f37d9ded8ddc 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -267,6 +267,8 @@ DRM GPIO devm_gpiod_get() + devm_gpiod_get_array() + devm_gpiod_get_array_optional() devm_gpiod_get_index() devm_gpiod_get_index_optional() devm_gpiod_get_optional() -- cgit v1.2.3 From 04a55fb2ff70c8b513e52305dc87b64689446bbd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:35:56 +0100 Subject: dt-bindings: clocks: Convert Allwinner DE2 clocks to a schema The newer Allwinner SoCs have a DE2 clocks controller that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Stephen Boyd Signed-off-by: Maxime Ripard --- .../clock/allwinner,sun8i-a83t-de2-clk.yaml | 76 ++++++++++++++++++++++ .../devicetree/bindings/clock/sun8i-de2.txt | 34 ---------- 2 files changed, 76 insertions(+), 34 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml delete mode 100644 Documentation/devicetree/bindings/clock/sun8i-de2.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml new file mode 100644 index 000000000000..3f995d2b30eb --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-a83t-de2-clk.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: GPL-2.0+ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun8i-a83t-de2-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A83t Display Engine 2/3 Clock Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + compatible: + oneOf: + - const: allwinner,sun8i-a83t-de2-clk + - const: allwinner,sun8i-h3-de2-clk + - const: allwinner,sun8i-v3s-de2-clk + - const: allwinner,sun50i-a64-de2-clk + - const: allwinner,sun50i-h5-de2-clk + - const: allwinner,sun50i-h6-de2-clk + - items: + - const: allwinner,sun8i-r40-de2-clk + - const: allwinner,sun8i-h3-de2-clk + + reg: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: bus + - const: mod + + resets: + maxItems: 1 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + + de2_clocks: clock@1000000 { + compatible = "allwinner,sun8i-h3-de2-clk"; + reg = <0x01000000 0x100000>; + clocks = <&ccu CLK_BUS_DE>, + <&ccu CLK_DE>; + clock-names = "bus", + "mod"; + resets = <&ccu RST_BUS_DE>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/sun8i-de2.txt b/Documentation/devicetree/bindings/clock/sun8i-de2.txt deleted file mode 100644 index 41a52c2acffd..000000000000 --- a/Documentation/devicetree/bindings/clock/sun8i-de2.txt +++ /dev/null @@ -1,34 +0,0 @@ -Allwinner Display Engine 2.0/3.0 Clock Control Binding ------------------------------------------------------- - -Required properties : -- compatible: must contain one of the following compatibles: - - "allwinner,sun8i-a83t-de2-clk" - - "allwinner,sun8i-h3-de2-clk" - - "allwinner,sun8i-v3s-de2-clk" - - "allwinner,sun50i-a64-de2-clk" - - "allwinner,sun50i-h5-de2-clk" - - "allwinner,sun50i-h6-de3-clk" - -- reg: Must contain the registers base address and length -- clocks: phandle to the clocks feeding the display engine subsystem. - Three are needed: - - "mod": the display engine module clock (on A83T it's the DE PLL) - - "bus": the bus clock for the whole display engine subsystem -- clock-names: Must contain the clock names described just above -- resets: phandle to the reset control for the display engine subsystem. -- #clock-cells : must contain 1 -- #reset-cells : must contain 1 - -Example: -de2_clocks: clock@1000000 { - compatible = "allwinner,sun8i-h3-de2-clk"; - reg = <0x01000000 0x100000>; - clocks = <&ccu CLK_BUS_DE>, - <&ccu CLK_DE>; - clock-names = "bus", - "mod"; - resets = <&ccu RST_BUS_DE>; - #clock-cells = <1>; - #reset-cells = <1>; -}; -- cgit v1.2.3 From c82f30306cddd201e6dbe0ce67a63fd69670ada3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:35:57 +0100 Subject: dt-bindings: clocks: Convert Allwinner A80 USB clocks to a schema The Allwinner A80 SoC has a USB clocks controller that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Stephen Boyd Signed-off-by: Maxime Ripard --- .../clock/allwinner,sun9i-a80-usb-clocks.yaml | 59 ++++++++++++++++++++++ .../devicetree/bindings/clock/sun9i-usb.txt | 24 --------- 2 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-clocks.yaml delete mode 100644 Documentation/devicetree/bindings/clock/sun9i-usb.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-clocks.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-clocks.yaml new file mode 100644 index 000000000000..fa0ee03a527f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-clocks.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: GPL-2.0+ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-usb-clocks.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 USB Clock Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + compatible: + const: allwinner,sun9i-a80-usb-clocks + + reg: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: High Frequency Oscillator + + clock-names: + items: + - const: bus + - const: hosc + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + + usb_clocks: clock@a08000 { + compatible = "allwinner,sun9i-a80-usb-clks"; + reg = <0x00a08000 0x8>; + clocks = <&ccu CLK_BUS_USB>, <&osc24M>; + clock-names = "bus", "hosc"; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/sun9i-usb.txt b/Documentation/devicetree/bindings/clock/sun9i-usb.txt deleted file mode 100644 index 3564bd4f2a20..000000000000 --- a/Documentation/devicetree/bindings/clock/sun9i-usb.txt +++ /dev/null @@ -1,24 +0,0 @@ -Allwinner A80 USB Clock Control Binding ---------------------------------------- - -Required properties : -- compatible: must contain one of the following compatibles: - - "allwinner,sun9i-a80-usb-clocks" - -- reg: Must contain the registers base address and length -- clocks: phandle to the clocks feeding the USB subsystem. Two are needed: - - "bus": the bus clock for the whole USB subsystem - - "hosc": the high frequency oscillator (usually at 24MHz) -- clock-names: Must contain the clock names described just above -- #clock-cells : must contain 1 -- #reset-cells : must contain 1 - -Example: -usb_clocks: clock@a08000 { - compatible = "allwinner,sun9i-a80-usb-clks"; - reg = <0x00a08000 0x8>; - clocks = <&ccu CLK_BUS_USB>, <&osc24M>; - clock-names = "bus", "hosc"; - #clock-cells = <1>; - #reset-cells = <1>; -}; -- cgit v1.2.3 From c1cc29f2a04552d140c40fbe084f3e75cebccdd9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:35:58 +0100 Subject: dt-bindings: clocks: Convert Allwinner A80 DE clocks to a schema The Allwinner A80 SoC has a display clocks controller that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Reviewed-by: Stephen Boyd Signed-off-by: Maxime Ripard --- .../clock/allwinner,sun9i-a80-de-clks.yaml | 67 ++++++++++++++++++++++ .../devicetree/bindings/clock/sun9i-de.txt | 28 --------- 2 files changed, 67 insertions(+), 28 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-de-clks.yaml delete mode 100644 Documentation/devicetree/bindings/clock/sun9i-de.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-de-clks.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-de-clks.yaml new file mode 100644 index 000000000000..a82c7c7e942b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-de-clks.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0+ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-de-clks.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 Display Engine Clock Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + compatible: + const: allwinner,sun9i-a80-de-clks + + reg: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: RAM Bus Clock + - description: Module Clock + + clock-names: + items: + - const: mod + - const: dram + - const: bus + + resets: + maxItems: 1 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + + de_clocks: clock@3000000 { + compatible = "allwinner,sun9i-a80-de-clks"; + reg = <0x03000000 0x30>; + clocks = <&ccu CLK_DE>, <&ccu CLK_SDRAM>, <&ccu CLK_BUS_DE>; + clock-names = "mod", "dram", "bus"; + resets = <&ccu RST_BUS_DE>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/sun9i-de.txt b/Documentation/devicetree/bindings/clock/sun9i-de.txt deleted file mode 100644 index fb18f327b97a..000000000000 --- a/Documentation/devicetree/bindings/clock/sun9i-de.txt +++ /dev/null @@ -1,28 +0,0 @@ -Allwinner A80 Display Engine Clock Control Binding --------------------------------------------------- - -Required properties : -- compatible: must contain one of the following compatibles: - - "allwinner,sun9i-a80-de-clks" - -- reg: Must contain the registers base address and length -- clocks: phandle to the clocks feeding the display engine subsystem. - Three are needed: - - "mod": the display engine module clock - - "dram": the DRAM bus clock for the system - - "bus": the bus clock for the whole display engine subsystem -- clock-names: Must contain the clock names described just above -- resets: phandle to the reset control for the display engine subsystem. -- #clock-cells : must contain 1 -- #reset-cells : must contain 1 - -Example: -de_clocks: clock@3000000 { - compatible = "allwinner,sun9i-a80-de-clks"; - reg = <0x03000000 0x30>; - clocks = <&ccu CLK_DE>, <&ccu CLK_SDRAM>, <&ccu CLK_BUS_DE>; - clock-names = "mod", "dram", "bus"; - resets = <&ccu RST_BUS_DE>; - #clock-cells = <1>; - #reset-cells = <1>; -}; -- cgit v1.2.3 From 727d01cb17c8a8e593ace9d136cb382a2c0d9e94 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 9 Dec 2019 15:38:35 +0100 Subject: dt-bindings: arm: amlogic: add libretech-pc bindings Add the board bindings for the libretech PC form factor Signed-off-by: Jerome Brunet Signed-off-by: Kevin Hilman --- Documentation/devicetree/bindings/arm/amlogic.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml index 8e693c6e0cc4..f74aba48cec1 100644 --- a/Documentation/devicetree/bindings/arm/amlogic.yaml +++ b/Documentation/devicetree/bindings/arm/amlogic.yaml @@ -105,6 +105,7 @@ properties: - enum: - amlogic,p230 - amlogic,p231 + - libretech,aml-s905d-pc - phicomm,n1 - const: amlogic,s905d - const: amlogic,meson-gxl @@ -116,6 +117,7 @@ properties: - amlogic,q201 - khadas,vim2 - kingnovel,r-box-pro + - libretech,aml-s912-pc - nexbox,a1 - tronsmart,vega-s96 - const: amlogic,s912 -- cgit v1.2.3 From faced7e0806cf44095a2833ad53ff59c39e6748d Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 16 Dec 2019 20:38:31 +0100 Subject: mm: hugetlb controller for cgroups v2 In the effort of supporting cgroups v2 into Kubernetes, I stumped on the lack of the hugetlb controller. When the controller is enabled, it exposes four new files for each hugetlb size on non-root cgroups: - hugetlb..current - hugetlb..max - hugetlb..events - hugetlb..events.local The differences with the legacy hierarchy are in the file names and using the value "max" instead of "-1" to disable a limit. The file .limit_in_bytes is renamed to .max. The file .usage_in_bytes is renamed to .current. .failcnt is not provided as a single file anymore, but its value can be read through the new flat-keyed files .events and .events.local, through the "max" key. Signed-off-by: Giuseppe Scrivano Signed-off-by: Tejun Heo --- Documentation/admin-guide/cgroup-v2.rst | 29 +++++ include/linux/hugetlb.h | 3 +- mm/hugetlb_cgroup.c | 198 ++++++++++++++++++++++++++++++-- 3 files changed, 218 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 0636bcb60b5a..3f801461f0f3 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -61,6 +61,8 @@ v1 is available under Documentation/admin-guide/cgroup-v1/. 5-6. Device 5-7. RDMA 5-7-1. RDMA Interface Files + 5-8. HugeTLB + 5.8-1. HugeTLB Interface Files 5-8. Misc 5-8-1. perf_event 5-N. Non-normative information @@ -2056,6 +2058,33 @@ RDMA Interface Files mlx4_0 hca_handle=1 hca_object=20 ocrdma1 hca_handle=1 hca_object=23 +HugeTLB +------- + +The HugeTLB controller allows to limit the HugeTLB usage per control group and +enforces the controller limit during page fault. + +HugeTLB Interface Files +~~~~~~~~~~~~~~~~~~~~~~~ + + hugetlb..current + Show current usage for "hugepagesize" hugetlb. It exists for all + the cgroup except root. + + hugetlb..max + Set/show the hard limit of "hugepagesize" hugetlb usage. + The default value is "max". It exists for all the cgroup except root. + + hugetlb..events + A read-only flat-keyed file which exists on non-root cgroups. + + max + The number of allocation failure due to HugeTLB limit + + hugetlb..events.local + Similar to hugetlb..events but the fields in the file + are local to the cgroup i.e. not hierarchical. The file modified event + generated on this file reflects only the local events. Misc ---- diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 31d4920994b9..1e897e4168ac 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -432,7 +432,8 @@ struct hstate { unsigned int surplus_huge_pages_node[MAX_NUMNODES]; #ifdef CONFIG_CGROUP_HUGETLB /* cgroup control files */ - struct cftype cgroup_files[5]; + struct cftype cgroup_files_dfl[5]; + struct cftype cgroup_files_legacy[5]; #endif char name[HSTATE_NAME_LEN]; }; diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c index 2ac38bdc18a1..e434b05416c6 100644 --- a/mm/hugetlb_cgroup.c +++ b/mm/hugetlb_cgroup.c @@ -3,6 +3,10 @@ * Copyright IBM Corporation, 2012 * Author Aneesh Kumar K.V * + * Cgroup v2 + * Copyright (C) 2019 Red Hat, Inc. + * Author: Giuseppe Scrivano + * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. @@ -19,18 +23,36 @@ #include #include +enum hugetlb_memory_event { + HUGETLB_MAX, + HUGETLB_NR_MEMORY_EVENTS, +}; + struct hugetlb_cgroup { struct cgroup_subsys_state css; + /* * the counter to account for hugepages from hugetlb. */ struct page_counter hugepage[HUGE_MAX_HSTATE]; + + atomic_long_t events[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS]; + atomic_long_t events_local[HUGE_MAX_HSTATE][HUGETLB_NR_MEMORY_EVENTS]; + + /* Handle for "hugetlb.events" */ + struct cgroup_file events_file[HUGE_MAX_HSTATE]; + + /* Handle for "hugetlb.events.local" */ + struct cgroup_file events_local_file[HUGE_MAX_HSTATE]; }; #define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val)) #define MEMFILE_IDX(val) (((val) >> 16) & 0xffff) #define MEMFILE_ATTR(val) ((val) & 0xffff) +#define hugetlb_cgroup_from_counter(counter, idx) \ + container_of(counter, struct hugetlb_cgroup, hugepage[idx]) + static struct hugetlb_cgroup *root_h_cgroup __read_mostly; static inline @@ -178,6 +200,19 @@ static void hugetlb_cgroup_css_offline(struct cgroup_subsys_state *css) } while (hugetlb_cgroup_have_usage(h_cg)); } +static inline void hugetlb_event(struct hugetlb_cgroup *hugetlb, int idx, + enum hugetlb_memory_event event) +{ + atomic_long_inc(&hugetlb->events_local[idx][event]); + cgroup_file_notify(&hugetlb->events_local_file[idx]); + + do { + atomic_long_inc(&hugetlb->events[idx][event]); + cgroup_file_notify(&hugetlb->events_file[idx]); + } while ((hugetlb = parent_hugetlb_cgroup(hugetlb)) && + !hugetlb_cgroup_is_root(hugetlb)); +} + int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages, struct hugetlb_cgroup **ptr) { @@ -202,8 +237,12 @@ again: } rcu_read_unlock(); - if (!page_counter_try_charge(&h_cg->hugepage[idx], nr_pages, &counter)) + if (!page_counter_try_charge(&h_cg->hugepage[idx], nr_pages, + &counter)) { ret = -ENOMEM; + hugetlb_event(hugetlb_cgroup_from_counter(counter, idx), idx, + HUGETLB_MAX); + } css_put(&h_cg->css); done: *ptr = h_cg; @@ -283,10 +322,45 @@ static u64 hugetlb_cgroup_read_u64(struct cgroup_subsys_state *css, } } +static int hugetlb_cgroup_read_u64_max(struct seq_file *seq, void *v) +{ + int idx; + u64 val; + struct cftype *cft = seq_cft(seq); + unsigned long limit; + struct page_counter *counter; + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(seq_css(seq)); + + idx = MEMFILE_IDX(cft->private); + counter = &h_cg->hugepage[idx]; + + limit = round_down(PAGE_COUNTER_MAX, + 1 << huge_page_order(&hstates[idx])); + + switch (MEMFILE_ATTR(cft->private)) { + case RES_USAGE: + val = (u64)page_counter_read(counter); + seq_printf(seq, "%llu\n", val * PAGE_SIZE); + break; + case RES_LIMIT: + val = (u64)counter->max; + if (val == limit) + seq_puts(seq, "max\n"); + else + seq_printf(seq, "%llu\n", val * PAGE_SIZE); + break; + default: + BUG(); + } + + return 0; +} + static DEFINE_MUTEX(hugetlb_limit_mutex); static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off) + char *buf, size_t nbytes, loff_t off, + const char *max) { int ret, idx; unsigned long nr_pages; @@ -296,7 +370,7 @@ static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of, return -EINVAL; buf = strstrip(buf); - ret = page_counter_memparse(buf, "-1", &nr_pages); + ret = page_counter_memparse(buf, max, &nr_pages); if (ret) return ret; @@ -316,6 +390,18 @@ static ssize_t hugetlb_cgroup_write(struct kernfs_open_file *of, return ret ?: nbytes; } +static ssize_t hugetlb_cgroup_write_legacy(struct kernfs_open_file *of, + char *buf, size_t nbytes, loff_t off) +{ + return hugetlb_cgroup_write(of, buf, nbytes, off, "-1"); +} + +static ssize_t hugetlb_cgroup_write_dfl(struct kernfs_open_file *of, + char *buf, size_t nbytes, loff_t off) +{ + return hugetlb_cgroup_write(of, buf, nbytes, off, "max"); +} + static ssize_t hugetlb_cgroup_reset(struct kernfs_open_file *of, char *buf, size_t nbytes, loff_t off) { @@ -350,7 +436,36 @@ static char *mem_fmt(char *buf, int size, unsigned long hsize) return buf; } -static void __init __hugetlb_cgroup_file_init(int idx) +static int __hugetlb_events_show(struct seq_file *seq, bool local) +{ + int idx; + long max; + struct cftype *cft = seq_cft(seq); + struct hugetlb_cgroup *h_cg = hugetlb_cgroup_from_css(seq_css(seq)); + + idx = MEMFILE_IDX(cft->private); + + if (local) + max = atomic_long_read(&h_cg->events_local[idx][HUGETLB_MAX]); + else + max = atomic_long_read(&h_cg->events[idx][HUGETLB_MAX]); + + seq_printf(seq, "max %lu\n", max); + + return 0; +} + +static int hugetlb_events_show(struct seq_file *seq, void *v) +{ + return __hugetlb_events_show(seq, false); +} + +static int hugetlb_events_local_show(struct seq_file *seq, void *v) +{ + return __hugetlb_events_show(seq, true); +} + +static void __init __hugetlb_cgroup_file_dfl_init(int idx) { char buf[32]; struct cftype *cft; @@ -360,38 +475,93 @@ static void __init __hugetlb_cgroup_file_init(int idx) mem_fmt(buf, 32, huge_page_size(h)); /* Add the limit file */ - cft = &h->cgroup_files[0]; + cft = &h->cgroup_files_dfl[0]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max", buf); + cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT); + cft->seq_show = hugetlb_cgroup_read_u64_max; + cft->write = hugetlb_cgroup_write_dfl; + cft->flags = CFTYPE_NOT_ON_ROOT; + + /* Add the current usage file */ + cft = &h->cgroup_files_dfl[1]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.current", buf); + cft->private = MEMFILE_PRIVATE(idx, RES_USAGE); + cft->seq_show = hugetlb_cgroup_read_u64_max; + cft->flags = CFTYPE_NOT_ON_ROOT; + + /* Add the events file */ + cft = &h->cgroup_files_dfl[2]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.events", buf); + cft->private = MEMFILE_PRIVATE(idx, 0); + cft->seq_show = hugetlb_events_show; + cft->file_offset = offsetof(struct hugetlb_cgroup, events_file[idx]), + cft->flags = CFTYPE_NOT_ON_ROOT; + + /* Add the events.local file */ + cft = &h->cgroup_files_dfl[3]; + snprintf(cft->name, MAX_CFTYPE_NAME, "%s.events.local", buf); + cft->private = MEMFILE_PRIVATE(idx, 0); + cft->seq_show = hugetlb_events_local_show; + cft->file_offset = offsetof(struct hugetlb_cgroup, + events_local_file[idx]), + cft->flags = CFTYPE_NOT_ON_ROOT; + + /* NULL terminate the last cft */ + cft = &h->cgroup_files_dfl[4]; + memset(cft, 0, sizeof(*cft)); + + WARN_ON(cgroup_add_dfl_cftypes(&hugetlb_cgrp_subsys, + h->cgroup_files_dfl)); +} + +static void __init __hugetlb_cgroup_file_legacy_init(int idx) +{ + char buf[32]; + struct cftype *cft; + struct hstate *h = &hstates[idx]; + + /* format the size */ + mem_fmt(buf, 32, huge_page_size(h)); + + /* Add the limit file */ + cft = &h->cgroup_files_legacy[0]; snprintf(cft->name, MAX_CFTYPE_NAME, "%s.limit_in_bytes", buf); cft->private = MEMFILE_PRIVATE(idx, RES_LIMIT); cft->read_u64 = hugetlb_cgroup_read_u64; - cft->write = hugetlb_cgroup_write; + cft->write = hugetlb_cgroup_write_legacy; /* Add the usage file */ - cft = &h->cgroup_files[1]; + cft = &h->cgroup_files_legacy[1]; snprintf(cft->name, MAX_CFTYPE_NAME, "%s.usage_in_bytes", buf); cft->private = MEMFILE_PRIVATE(idx, RES_USAGE); cft->read_u64 = hugetlb_cgroup_read_u64; /* Add the MAX usage file */ - cft = &h->cgroup_files[2]; + cft = &h->cgroup_files_legacy[2]; snprintf(cft->name, MAX_CFTYPE_NAME, "%s.max_usage_in_bytes", buf); cft->private = MEMFILE_PRIVATE(idx, RES_MAX_USAGE); cft->write = hugetlb_cgroup_reset; cft->read_u64 = hugetlb_cgroup_read_u64; /* Add the failcntfile */ - cft = &h->cgroup_files[3]; + cft = &h->cgroup_files_legacy[3]; snprintf(cft->name, MAX_CFTYPE_NAME, "%s.failcnt", buf); cft->private = MEMFILE_PRIVATE(idx, RES_FAILCNT); cft->write = hugetlb_cgroup_reset; cft->read_u64 = hugetlb_cgroup_read_u64; /* NULL terminate the last cft */ - cft = &h->cgroup_files[4]; + cft = &h->cgroup_files_legacy[4]; memset(cft, 0, sizeof(*cft)); WARN_ON(cgroup_add_legacy_cftypes(&hugetlb_cgrp_subsys, - h->cgroup_files)); + h->cgroup_files_legacy)); +} + +static void __init __hugetlb_cgroup_file_init(int idx) +{ + __hugetlb_cgroup_file_dfl_init(idx); + __hugetlb_cgroup_file_legacy_init(idx); } void __init hugetlb_cgroup_file_init(void) @@ -433,8 +603,14 @@ void hugetlb_cgroup_migrate(struct page *oldhpage, struct page *newhpage) return; } +static struct cftype hugetlb_files[] = { + {} /* terminate */ +}; + struct cgroup_subsys hugetlb_cgrp_subsys = { .css_alloc = hugetlb_cgroup_css_alloc, .css_offline = hugetlb_cgroup_css_offline, .css_free = hugetlb_cgroup_css_free, + .dfl_cftypes = hugetlb_files, + .legacy_cftypes = hugetlb_files, }; -- cgit v1.2.3 From 7dce4d6f151de852925feb1dd6e42d91dab14951 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Sun, 17 Nov 2019 20:58:48 +0800 Subject: dt-bindings: mmc: fsl-imx-esdhc: add imx8qm compatible string Add imx8qm compatible string. Signed-off-by: Dong Aisheng Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt index 2fb466ca2a9d..e1043f30de54 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -21,6 +21,7 @@ Required properties: "fsl,imx8mq-usdhc" "fsl,imx8mm-usdhc" "fsl,imx8mn-usdhc" + "fsl,imx8qm-usdhc" "fsl,imx8qxp-usdhc" Optional properties: -- cgit v1.2.3 From 6a86e9f57a51f700ca775cb17114b9707a321e16 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Sun, 17 Nov 2019 20:58:49 +0800 Subject: dt-bindings: serial: lpuart: add imx8qm compatible string Add imx8qm compatible string. Signed-off-by: Dong Aisheng Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/serial/fsl-lpuart.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt index f5f5ab0fd14e..c904e2e68332 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.txt +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.txt @@ -10,6 +10,8 @@ Required properties: on i.MX7ULP SoC with 32-bit little-endian register organization - "fsl,imx8qxp-lpuart" for lpuart compatible with the one integrated on i.MX8QXP SoC with 32-bit little-endian register organization + - "fsl,imx8qm-lpuart" for lpuart compatible with the one integrated + on i.MX8QM SoC with 32-bit little-endian register organization - reg : Address and length of the register set for the device - interrupts : Should contain uart interrupt - clocks : phandle + clock specifier pairs, one for each entry in clock-names -- cgit v1.2.3 From 40a4711a704f26fbef39166147caeb66885fbfef Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Sun, 17 Nov 2019 20:58:50 +0800 Subject: dt-bindings: i2c: lpi2c: add imx8qm compatible string Add imx8qm compatible string. Signed-off-by: Dong Aisheng Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt index b245363d6d60..f0c072ff9eca 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt @@ -4,6 +4,7 @@ Required properties: - compatible : - "fsl,imx7ulp-lpi2c" for LPI2C compatible with the one integrated on i.MX7ULP soc - "fsl,imx8qxp-lpi2c" for LPI2C compatible with the one integrated on i.MX8QXP soc + - "fsl,imx8qm-lpi2c" for LPI2C compatible with the one integrated on i.MX8QM soc - reg : address and length of the lpi2c master registers - interrupts : lpi2c interrupt - clocks : lpi2c clock specifier -- cgit v1.2.3 From 50ce01f3f62949bc80ebe7a0ec103eb7622c912d Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 20 Nov 2019 19:18:54 +0100 Subject: dt-bindings: vendor-prefixes: Add yet another for ST-Ericsson Unfortunately the vendor prefix for ST-Ericsson is used very inconsistently. "ste," and "stericsson," are already documented, but some things in the kernel use "st-ericsson," which is not documented yet. st-ericsson,u8500 is documented in bindings/arm/ux500/boards.txt, and is used to match the machine code and the generic DT cpufreq driver. Add it to the list of vendor prefixes. Signed-off-by: Stephan Gerhold Reviewed-by: Linus Walleij Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 6046f4555852..8c727a4e6ea9 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -913,6 +913,8 @@ patternProperties: description: ST-Ericsson "^stericsson,.*": description: ST-Ericsson + "^st-ericsson,.*": + description: ST-Ericsson "^summit,.*": description: Summit microelectronics "^sunchip,.*": -- cgit v1.2.3 From ef43406e6714ef81864831ed5053142fc1087126 Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 20 Nov 2019 19:18:55 +0100 Subject: dt-bindings: vendor-prefixes: Deprecate "ste" and "st-ericsson" Until now, device tree bindings for ST-Ericsson have been added inconsistently with one of 3 possible vendor prefixes. "stericsson" is the most commonly used vendor prefix, so deprecate "ste" and "st-ericsson". Suggested-by: Rob Herring Signed-off-by: Stephan Gerhold Reviewed-by: Linus Walleij Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 8c727a4e6ea9..8782672b189a 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -911,10 +911,12 @@ patternProperties: description: Startek "^ste,.*": description: ST-Ericsson + deprecated: true "^stericsson,.*": description: ST-Ericsson "^st-ericsson,.*": description: ST-Ericsson + deprecated: true "^summit,.*": description: Summit microelectronics "^sunchip,.*": -- cgit v1.2.3 From bece4258502e88faa9f03ae2040f5427a257280c Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Wed, 20 Nov 2019 19:18:56 +0100 Subject: dt-bindings: vendor-prefixes: Add "calaosystems" for CALAO Systems SAS The Snowball SBC supported by arch/arm/boot/dts/ste-snowball.dts was made by CALAO Systems and uses the "calaosystems,snowball-a9500" compatible. Prepare for documenting the compatible by adding "calaosystems" to the list of vendor prefixes. Signed-off-by: Stephan Gerhold Reviewed-by: Linus Walleij Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 8782672b189a..69151c8ebda4 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -157,6 +157,8 @@ patternProperties: description: B&R Industrial Automation GmbH "^bticino,.*": description: Bticino International + "^calaosystems,.*": + description: CALAO Systems SAS "^calxeda,.*": description: Calxeda "^capella,.*": -- cgit v1.2.3 From 70a97443d96682770895131632f2aa0d2ef62bae Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Fri, 22 Nov 2019 11:39:42 +0100 Subject: dt-bindings: arm: stm32: Convert stm32-syscon to json-schema Convert the STM32 syscon binding to DT schema format using json-schema. Signed-off-by: Alexandre Torgue Signed-off-by: Rob Herring --- .../bindings/arm/stm32/st,stm32-syscon.yaml | 41 ++++++++++++++++++++++ .../devicetree/bindings/arm/stm32/stm32-syscon.txt | 16 --------- 2 files changed, 41 insertions(+), 16 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml delete mode 100644 Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml new file mode 100644 index 000000000000..0dedf94c8578 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/arm/stm32/st,stm32-syscon.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: STMicroelectronics STM32 Platforms System Controller bindings + +maintainers: + - Alexandre Torgue + - Christophe Roullier + +properties: + compatible: + oneOf: + - items: + - enum: + - st,stm32mp157-syscfg + - const: syscon + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - reg + - clocks + +examples: + - | + #include + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + +... diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt b/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt deleted file mode 100644 index c92d411fd023..000000000000 --- a/Documentation/devicetree/bindings/arm/stm32/stm32-syscon.txt +++ /dev/null @@ -1,16 +0,0 @@ -STMicroelectronics STM32 Platforms System Controller - -Properties: - - compatible : should contain two values. First value must be : - - " st,stm32mp157-syscfg " - for stm32mp157 based SoCs, - second value must be always "syscon". - - reg : offset and length of the register set. - - clocks: phandle to the syscfg clock - - Example: - syscfg: syscon@50020000 { - compatible = "st,stm32mp157-syscfg", "syscon"; - reg = <0x50020000 0x400>; - clocks = <&rcc SYSCFG>; - }; - -- cgit v1.2.3 From 20107d7328cc2caea01587ba0571c61fb62efe41 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Mon, 2 Dec 2019 16:03:43 +0100 Subject: dt-bindings: rcc: Convert stm32mp1 rcc bindings to json-schema Convert the STM32MP1 RCC binding to DT schema format using json-schema. Signed-off-by: Gabriel Fernandez Signed-off-by: Rob Herring --- .../devicetree/bindings/clock/st,stm32mp1-rcc.txt | 60 ---------------- .../devicetree/bindings/clock/st,stm32mp1-rcc.yaml | 79 ++++++++++++++++++++++ 2 files changed, 79 insertions(+), 60 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt create mode 100644 Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt deleted file mode 100644 index fb9495ea582c..000000000000 --- a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.txt +++ /dev/null @@ -1,60 +0,0 @@ -STMicroelectronics STM32 Peripheral Reset Clock Controller -========================================================== - -The RCC IP is both a reset and a clock controller. - -RCC makes also power management (resume/supend and wakeup interrupt). - -Please also refer to reset.txt for common reset controller binding usage. - -Please also refer to clock-bindings.txt for common clock controller -binding usage. - - -Required properties: -- compatible: "st,stm32mp1-rcc", "syscon" -- reg: should be register base and length as documented in the datasheet -- #clock-cells: 1, device nodes should specify the clock in their - "clocks" property, containing a phandle to the clock device node, - an index specifying the clock to use. -- #reset-cells: Shall be 1 -- interrupts: Should contain a general interrupt line and a interrupt line - to the wake-up of processor (CSTOP). - -Example: - rcc: rcc@50000000 { - compatible = "st,stm32mp1-rcc", "syscon"; - reg = <0x50000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - interrupts = , - ; - }; - -Specifying clocks -================= - -All available clocks are defined as preprocessor macros in -dt-bindings/clock/stm32mp1-clks.h header and can be used in device -tree sources. - -Specifying softreset control of devices -======================================= - -Device nodes should specify the reset channel required in their "resets" -property, containing a phandle to the reset device node and an index specifying -which channel to use. -The index is the bit number within the RCC registers bank, starting from RCC -base address. -It is calculated as: index = register_offset / 4 * 32 + bit_offset. -Where bit_offset is the bit offset within the register. - -For example on STM32MP1, for LTDC reset: - ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset - = 0x180 / 4 * 32 + 0 = 3072 - -The list of valid indices for STM32MP1 is available in: -include/dt-bindings/reset-controller/stm32mp1-resets.h - -This file implements defines like: -#define LTDC_R 3072 diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml new file mode 100644 index 000000000000..b8f91e444d2f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/st,stm32mp1-rcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Reset Clock Controller Binding + +maintainers: + - Gabriel Fernandez + +description: | + The RCC IP is both a reset and a clock controller. + RCC makes also power management (resume/supend and wakeup interrupt). + Please also refer to reset.txt for common reset controller binding usage. + + This binding uses common clock bindings + Documentation/devicetree/bindings/clock/clock-bindings.txt + + Specifying clocks + ================= + + All available clocks are defined as preprocessor macros in + dt-bindings/clock/stm32mp1-clks.h header and can be used in device + tree sources. + + Specifying softreset control of devices + ======================================= + + Device nodes should specify the reset channel required in their "resets" + property, containing a phandle to the reset device node and an index specifying + which channel to use. + The index is the bit number within the RCC registers bank, starting from RCC + base address. + It is calculated as: index = register_offset / 4 * 32 + bit_offset. + Where bit_offset is the bit offset within the register. + + For example on STM32MP1, for LTDC reset: + ltdc = APB4_RSTSETR_offset / 4 * 32 + LTDC_bit_offset + = 0x180 / 4 * 32 + 0 = 3072 + + The list of valid indices for STM32MP1 is available in: + include/dt-bindings/reset-controller/stm32mp1-resets.h + + This file implements defines like: + #define LTDC_R 3072 + +properties: + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + compatible: + items: + - const: st,stm32mp1-rcc + - const: syscon + + reg: + maxItems: 1 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + +additionalProperties: false + +examples: + - | + rcc: rcc@50000000 { + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; +... -- cgit v1.2.3 From eb843ab59134af588c35a71125aa1563acbc8e7e Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Mon, 2 Dec 2019 10:22:03 -0700 Subject: dt-bindings: vendor-prefixes: Add a broadmobi entry Add Shanghai Broadmobi Communication Technology Co.,Ltd. for their modem dts entries. Signed-off-by: Angus Ainslie (Purism) Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 69151c8ebda4..711f27a3013b 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -149,6 +149,8 @@ patternProperties: description: Bosch Sensortec GmbH "^boundary,.*": description: Boundary Devices Inc. + "^broadmobi,.*": + description: Shanghai Broadmobi Communication Technology Co.,Ltd. "^brcm,.*": description: Broadcom Corporation "^buffalo,.*": -- cgit v1.2.3 From 89d6d772f613690eec9540a24b6b0ce60a99540c Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Tue, 3 Dec 2019 22:34:02 +1030 Subject: dt-bindings: pinctrl: aspeed: Add reg property as a hint The pinctrl node sits under a syscon device, and can assume offsets from the base of the syscon based on the compatible. However, for devicetree correctness allow a reg property to be specified, which an associated driver may choose to use to discover associated resources. Cc: Linus Walleij Cc: linux-gpio@vger.kernel.org Signed-off-by: Andrew Jeffery Acked-by: Linus Walleij Reviewed-by: Joel Stanley Signed-off-by: Joel Stanley --- Documentation/devicetree/bindings/pinctrl/aspeed,ast2400-pinctrl.yaml | 3 +++ Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml | 3 +++ 2 files changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2400-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2400-pinctrl.yaml index 39ad8657d018..bb690e20c368 100644 --- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2400-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2400-pinctrl.yaml @@ -22,6 +22,9 @@ description: |+ properties: compatible: const: aspeed,ast2400-pinctrl + reg: + description: | + A hint for the memory regions associated with the pin-controller patternProperties: '^.*$': diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml index 3c6405be07ed..f7f5d57f2c9a 100644 --- a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2500-pinctrl.yaml @@ -23,6 +23,9 @@ description: |+ properties: compatible: const: aspeed,ast2500-pinctrl + reg: + description: | + A hint for the memory regions associated with the pin-controller aspeed,external-nodes: minItems: 2 maxItems: 2 -- cgit v1.2.3 From ce885265ef297b074b0cccfae3a929760e8fa6e7 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Tue, 3 Dec 2019 22:34:03 +1030 Subject: dt-bindings: misc: Document reg for aspeed, p2a-ctrl nodes The P2A controller node sits under a syscon device, and can assume offsets from the base of the syscon based on the compatible. However, for devicetree correctness allow a reg property to be specified, which an associated driver may choose to use to discover associated resources. Cc: Patrick Venture Cc: Greg Kroah-Hartman Signed-off-by: Andrew Jeffery Reviewed-by: Joel Stanley Signed-off-by: Joel Stanley --- Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt b/Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt index 0e1fa5bc6a30..f2e2e28b317c 100644 --- a/Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt +++ b/Documentation/devicetree/bindings/misc/aspeed-p2a-ctrl.txt @@ -18,6 +18,7 @@ Required properties: Optional properties: =================== +- reg: A hint for the memory regions associated with the P2A controller - memory-region: A phandle to a reserved_memory region to be used for the PCI to AHB mapping -- cgit v1.2.3 From 22f517e04dc99e750f45ff86e460af2e2fcf2eb2 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 18 Nov 2019 21:43:34 +0000 Subject: dt-bindings: remoteproc: qcom: Add power-domain bindings for Q6V5 PAS Add power-domain bindings for Q6V5 PAS on MSM8974/MSM8996/QCS404/SDM845 SoCs. Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/0101016e80788d28-7370e0e3-7380-4cc7-9233-40b9fd76e8f3-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/qcom,adsp.txt | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt index 292dfda9770d..fea25b8b050e 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt @@ -67,6 +67,29 @@ on the Qualcomm ADSP Hexagon core. Definition: reference to the px regulator to be held on behalf of the booting Hexagon core +- power-domains: + Usage: required + Value type: + Definition: reference to power-domains that match the power-domain-names + +- power-domain-names: + Usage: required + Value type: + Definition: The power-domains needed depend on the compatible string: + qcom,msm8974-adsp-pil: + qcom,msm8996-adsp-pil: + must be "cx" + qcom,msm8996-slpi-pil: + must be "ss_cx" + qcom,qcs404-adsp-pas: + must be "lpi_cx" + qcom,qcs404-cdsp-pas: + qcom,qcs404-wcss-pas: + must be "mx" + qcom,sdm845-adsp-pas: + qcom,sdm845-cdsp-pas: + must be "cx", "load_state" + - memory-region: Usage: required Value type: -- cgit v1.2.3 From 27c303a456aa8e08d4fd8457e6223acbcdb5b50d Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Mon, 18 Nov 2019 21:43:54 +0000 Subject: dt-bindings: remoteproc: qcom: SM8150 Add ADSP, CDSP, MPSS and SLPI support Add ADSP, CDSP, MPSS and SLPI compatibles for SM8150 SoC. Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/0101016e8078dad4-458c8501-93fd-4daa-8938-d01027f248cb-000000@us-west-2.amazonses.com Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt index fea25b8b050e..a54465d938f6 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt @@ -15,6 +15,10 @@ on the Qualcomm ADSP Hexagon core. "qcom,qcs404-wcss-pas" "qcom,sdm845-adsp-pas" "qcom,sdm845-cdsp-pas" + "qcom,sm8150-adsp-pas" + "qcom,sm8150-cdsp-pas" + "qcom,sm8150-mpss-pas" + "qcom,sm8150-slpi-pas" - interrupts-extended: Usage: required @@ -33,8 +37,12 @@ on the Qualcomm ADSP Hexagon core. qcom,qcs404-cdsp-pas: qcom,sdm845-adsp-pas: qcom,sdm845-cdsp-pas: + qcom,sm8150-adsp-pas: + qcom,sm8150-cdsp-pas: + qcom,sm8150-slpi-pas: must be "wdog", "fatal", "ready", "handover", "stop-ack" qcom,qcs404-wcss-pas: + qcom,sm8150-mpss-pas: must be "wdog", "fatal", "ready", "handover", "stop-ack", "shutdown-ack" @@ -88,7 +96,13 @@ on the Qualcomm ADSP Hexagon core. must be "mx" qcom,sdm845-adsp-pas: qcom,sdm845-cdsp-pas: + qcom,sm8150-adsp-pas: + qcom,sm8150-cdsp-pas: must be "cx", "load_state" + qcom,sm8150-mpss-pas: + must be "cx", "load_state", "mss" + qcom,sm8150-slpi-pas: + must be "lcx", "lmx", "load_state" - memory-region: Usage: required -- cgit v1.2.3 From d8cac6207ec1abd3c85cff2625dd3898d59c4df5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 17 Dec 2019 09:14:48 +0100 Subject: ALSA: cmipci: Allow disabling MPU port via module option Patrick May reported that his sound card with CMI8378 chip causes a crash / reboot when accessing the MIDI port that isn't actually present on the board. Moreover, despite of the documentation, passing mpu_port=0 doesn't disable the MIDI port on this board. It implies that the chip is a newer revision and the MPU401 port is integrated and mapped on the PCI register. For this chip model, the driver enables the MPU port unconditionally, so far. Although fixing the unexpected reboot would be the best solution, it's not so trivial to identify the cause. So, as a plan B, this patch extends the existing mpu_port option usage to allow disabling the port by specifying the value 0, just like we applied for fm_port option in commit 2f24d159d5ac ("[ALSA] cmipci - Allow to disable integrated FM port"). As default, the MPU port is still enabled, but user can pass mpu_port=0 to disable it. Reported-and-tested-by: Patrick May Link: https://lore.kernel.org/r/20191217081448.1144-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- Documentation/sound/alsa-configuration.rst | 3 ++- sound/pci/cmipci.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst index 02aacd69ab96..392875a1b94e 100644 --- a/Documentation/sound/alsa-configuration.rst +++ b/Documentation/sound/alsa-configuration.rst @@ -495,7 +495,8 @@ Module for C-Media CMI8338/8738/8768/8770 PCI sound cards. mpu_port port address of MIDI interface (8338 only): 0x300,0x310,0x320,0x330 = legacy port, - 0 = disable (default) + 1 = integrated PCI port (default on 8738), + 0 = disable fm_port port address of OPL-3 FM synthesizer (8x38 only): 0x388 = legacy port, diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 4bfab21c53f4..266c4cf28b78 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -42,7 +42,7 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738}," static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ -static long mpu_port[SNDRV_CARDS]; +static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1}; static bool soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1}; #ifdef SUPPORT_JOYSTICK @@ -3132,7 +3132,8 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci, if (cm->chip_version >= 39) { val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1); if (val != 0x00 && val != 0xff) { - iomidi = cm->iobase + CM_REG_MPU_PCI; + if (mpu_port[dev]) + iomidi = cm->iobase + CM_REG_MPU_PCI; integrated_midi = 1; } } -- cgit v1.2.3 From 84a867c078136887dea64fa6e336333b657bc6a1 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Wed, 11 Dec 2019 11:35:57 +0200 Subject: dt-bindings: regulator: Document ROHM BD71282 regulator bindings Document ROHM BD71828 PMIC regulator device tree bindings. Signed-off-by: Matti Vaittinen Link: https://lore.kernel.org/r/0985fec1cce98b1db66e5df2d9bcf2dfd9c224a7.1576054779.git.matti.vaittinen@fi.rohmeurope.com Signed-off-by: Mark Brown --- .../bindings/regulator/rohm,bd71828-regulator.yaml | 107 +++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml new file mode 100644 index 000000000000..71ce032b8cf8 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/rohm,bd71828-regulator.yaml @@ -0,0 +1,107 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/rohm,bd71828-regulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ROHM BD71828 Power Management Integrated Circuit regulators + +maintainers: + - Matti Vaittinen + +description: | + This module is part of the ROHM BD71828 MFD device. For more details + see Documentation/devicetree/bindings/mfd/rohm,bd71828-pmic.yaml. + + The regulator controller is represented as a sub-node of the PMIC node + on the device tree. + + Regulator nodes should be named to BUCK_ and LDO_. + The valid names for BD71828 regulator nodes are + BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7 + LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7 + +patternProperties: + "^LDO[1-7]$": + type: object + allOf: + - $ref: regulator.yaml# + description: + Properties for single LDO regulator. + + properties: + regulator-name: + pattern: "^ldo[1-7]$" + description: + should be "ldo1", ..., "ldo7" + + "^BUCK[1-7]$": + type: object + allOf: + - $ref: regulator.yaml# + description: + Properties for single BUCK regulator. + + properties: + regulator-name: + pattern: "^buck[1-7]$" + description: + should be "buck1", ..., "buck7" + + rohm,dvs-run-voltage: + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + maximum: 3300000 + description: + PMIC default "RUN" state voltage in uV. See below table for + bucks which support this. 0 means disabled. + + rohm,dvs-idle-voltage: + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + maximum: 3300000 + description: + PMIC default "IDLE" state voltage in uV. See below table for + bucks which support this. 0 means disabled. + + rohm,dvs-suspend-voltage: + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + maximum: 3300000 + description: + PMIC default "SUSPEND" state voltage in uV. See below table for + bucks which support this. 0 means disabled. + + rohm,dvs-lpsr-voltage: + allOf: + - $ref: "/schemas/types.yaml#/definitions/uint32" + - minimum: 0 + maximum: 3300000 + description: + PMIC default "LPSR" state voltage in uV. See below table for + bucks which support this. 0 means disabled. + + # Supported default DVS states: + # buck | run | idle | suspend | lpsr + #-------------------------------------------------------------- + # 1, 2, 6, and 7 | supported | supported | supported (*) + #-------------------------------------------------------------- + # 3, 4, and 5 | supported (**) + #-------------------------------------------------------------- + # + #(*) LPSR and SUSPEND states use same voltage but both states have own + # enable / + # disable settings. Voltage 0 can be specified for a state to make + # regulator disabled on that state. + # + #(**) All states use same voltage but have own enable / disable + # settings. Voltage 0 can be specified for a state to make + # regulator disabled on that state. + + required: + - regulator-name + additionalProperties: false +additionalProperties: false -- cgit v1.2.3 From 8b183f5b85e0be4f94fa9309da5504bb7ba3367e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:39:56 +0100 Subject: dt-bindings: i2c: rcar: Document r8a77961 support Document support for the I2C controller in the Renesas R-Car M3-W+ (R8A77961) SoC. Update all references to R-Car M3-W from "r8a7796" to "r8a77960", to avoid confusion between R-Car M3-W (R8A77960) and M3-W+. No driver update is needed. Signed-off-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/renesas,i2c.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/renesas,i2c.txt b/Documentation/devicetree/bindings/i2c/renesas,i2c.txt index 0660a3eb2547..c359965d0724 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,i2c.txt +++ b/Documentation/devicetree/bindings/i2c/renesas,i2c.txt @@ -17,7 +17,8 @@ Required properties: "renesas,i2c-r8a7793" if the device is a part of a R8A7793 SoC. "renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC. "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC. - "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC. + "renesas,i2c-r8a7796" if the device is a part of a R8A77960 SoC. + "renesas,i2c-r8a77961" if the device is a part of a R8A77961 SoC. "renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC. "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC. "renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC. -- cgit v1.2.3 From 15c0677162b77636899ac668f3bc2055c941b9b7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:40:25 +0100 Subject: dt-bindings: i2c: sh_mobile: Document r8a77961 support Document support for the IIC controller in the Renesas R-Car M3-W+ (R8A77961) SoC. No driver update is needed. Signed-off-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/renesas,iic.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/renesas,iic.txt b/Documentation/devicetree/bindings/i2c/renesas,iic.txt index 64d11ffb07c4..ffe085c9947e 100644 --- a/Documentation/devicetree/bindings/i2c/renesas,iic.txt +++ b/Documentation/devicetree/bindings/i2c/renesas,iic.txt @@ -17,6 +17,7 @@ Required properties: - "renesas,iic-r8a7794" (R-Car E2) - "renesas,iic-r8a7795" (R-Car H3) - "renesas,iic-r8a7796" (R-Car M3-W) + - "renesas,iic-r8a77961" (R-Car M3-W+) - "renesas,iic-r8a77965" (R-Car M3-N) - "renesas,iic-r8a77990" (R-Car E3) - "renesas,iic-sh73a0" (SH-Mobile AG5) -- cgit v1.2.3 From 882007ed783211c27e859234e78328d35ded03c7 Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Mon, 16 Dec 2019 13:39:58 +0800 Subject: net-next: dt-binding: dwmac-mediatek: add more description for RMII MT2712 SoC can provide RMII reference clock, so add corresponding description in dt-binding. Signed-off-by: Biao Huang Signed-off-by: David S. Miller --- .../devicetree/bindings/net/mediatek-dwmac.txt | 33 +++++++++++++++------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/mediatek-dwmac.txt b/Documentation/devicetree/bindings/net/mediatek-dwmac.txt index 8a08621a5b54..afbcaebf062e 100644 --- a/Documentation/devicetree/bindings/net/mediatek-dwmac.txt +++ b/Documentation/devicetree/bindings/net/mediatek-dwmac.txt @@ -14,7 +14,7 @@ Required properties: Should be "macirq" for the main MAC IRQ - clocks: Must contain a phandle for each entry in clock-names. - clock-names: The name of the clock listed in the clocks property. These are - "axi", "apb", "mac_main", "ptp_ref" for MT2712 SoC + "axi", "apb", "mac_main", "ptp_ref", "rmii_internal" for MT2712 SoC. - mac-address: See ethernet.txt in the same directory - phy-mode: See ethernet.txt in the same directory - mediatek,pericfg: A phandle to the syscon node that control ethernet @@ -23,8 +23,10 @@ Required properties: Optional properties: - mediatek,tx-delay-ps: TX clock delay macro value. Default is 0. It should be defined for RGMII/MII interface. + It should be defined for RMII interface when the reference clock is from MT2712 SoC. - mediatek,rx-delay-ps: RX clock delay macro value. Default is 0. - It should be defined for RGMII/MII/RMII interface. + It should be defined for RGMII/MII interface. + It should be defined for RMII interface. Both delay properties need to be a multiple of 170 for RGMII interface, or will round down. Range 0~31*170. Both delay properties need to be a multiple of 550 for MII/RMII interface, @@ -34,13 +36,20 @@ or will round down. Range 0~31*550. reference clock, which is from external PHYs, is connected to RXC pin on MT2712 SoC. Otherwise, is connected to TXC pin. +- mediatek,rmii-clk-from-mac: boolean property, if present indicates that + MT2712 SoC provides the RMII reference clock, which outputs to TXC pin only. - mediatek,txc-inverse: boolean property, if present indicates that 1. tx clock will be inversed in MII/RGMII case, 2. tx clock inside MAC will be inversed relative to reference clock which is from external PHYs in RMII case, and it rarely happen. + 3. the reference clock, which outputs to TXC pin will be inversed in RMII case + when the reference clock is from MT2712 SoC. - mediatek,rxc-inverse: boolean property, if present indicates that 1. rx clock will be inversed in MII/RGMII case. - 2. reference clock will be inversed when arrived at MAC in RMII case. + 2. reference clock will be inversed when arrived at MAC in RMII case, when + the reference clock is from external PHYs. + 3. the inside clock, which be sent to MAC, will be inversed in RMII case when + the reference clock is from MT2712 SoC. - assigned-clocks: mac_main and ptp_ref clocks - assigned-clock-parents: parent clocks of the assigned clocks @@ -50,29 +59,33 @@ Example: reg = <0 0x1101c000 0 0x1300>; interrupts = ; interrupt-names = "macirq"; - phy-mode ="rgmii"; + phy-mode ="rgmii-rxid"; mac-address = [00 55 7b b5 7d f7]; clock-names = "axi", "apb", "mac_main", "ptp_ref", - "ptp_top"; + "rmii_internal"; clocks = <&pericfg CLK_PERI_GMAC>, <&pericfg CLK_PERI_GMAC_PCLK>, <&topckgen CLK_TOP_ETHER_125M_SEL>, - <&topckgen CLK_TOP_ETHER_50M_SEL>; + <&topckgen CLK_TOP_ETHER_50M_SEL>, + <&topckgen CLK_TOP_ETHER_50M_RMII_SEL>; assigned-clocks = <&topckgen CLK_TOP_ETHER_125M_SEL>, - <&topckgen CLK_TOP_ETHER_50M_SEL>; + <&topckgen CLK_TOP_ETHER_50M_SEL>, + <&topckgen CLK_TOP_ETHER_50M_RMII_SEL>; assigned-clock-parents = <&topckgen CLK_TOP_ETHERPLL_125M>, - <&topckgen CLK_TOP_APLL1_D3>; + <&topckgen CLK_TOP_APLL1_D3>, + <&topckgen CLK_TOP_ETHERPLL_50M>; + power-domains = <&scpsys MT2712_POWER_DOMAIN_AUDIO>; mediatek,pericfg = <&pericfg>; mediatek,tx-delay-ps = <1530>; mediatek,rx-delay-ps = <1530>; mediatek,rmii-rxc; mediatek,txc-inverse; mediatek,rxc-inverse; - snps,txpbl = <32>; - snps,rxpbl = <32>; + snps,txpbl = <1>; + snps,rxpbl = <1>; snps,reset-gpio = <&pio 87 GPIO_ACTIVE_LOW>; snps,reset-active-low; }; -- cgit v1.2.3 From 887d1d69d67ad405f3d08271aa4b6a5184888606 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Sat, 14 Dec 2019 10:00:25 +0100 Subject: dt-bindings: rtc: Convert stm32 rtc bindings to json-schema Convert the STM32 RTC binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../devicetree/bindings/rtc/st,stm32-rtc.txt | 61 --------- .../devicetree/bindings/rtc/st,stm32-rtc.yaml | 139 +++++++++++++++++++++ 2 files changed, 139 insertions(+), 61 deletions(-) delete mode 100644 Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt create mode 100644 Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt deleted file mode 100644 index 130ca5b98253..000000000000 --- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt +++ /dev/null @@ -1,61 +0,0 @@ -STM32 Real Time Clock - -Required properties: -- compatible: can be one of the following: - - "st,stm32-rtc" for devices compatible with stm32(f4/f7). - - "st,stm32h7-rtc" for devices compatible with stm32h7. - - "st,stm32mp1-rtc" for devices compatible with stm32mp1. -- reg: address range of rtc register set. -- clocks: can use up to two clocks, depending on part used: - - "rtc_ck": RTC clock source. - - "pclk": RTC APB interface clock. - It is not present on stm32(f4/f7). - It is required on stm32(h7/mp1). -- clock-names: must be "rtc_ck" and "pclk". - It is required on stm32(h7/mp1). -- interrupts: rtc alarm interrupt. On stm32mp1, a second interrupt is required - for rtc alarm wakeup interrupt. -- st,syscfg: phandle/offset/mask triplet. The phandle to pwrcfg used to - access control register at offset, and change the dbp (Disable Backup - Protection) bit represented by the mask, mandatory to disable/enable backup - domain (RTC registers) write protection. - It is required on stm32(f4/f7/h7). - -Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7): -- assigned-clocks: reference to the rtc_ck clock entry. -- assigned-clock-parents: phandle of the new parent clock of rtc_ck. - -Example: - - rtc: rtc@40002800 { - compatible = "st,stm32-rtc"; - reg = <0x40002800 0x400>; - clocks = <&rcc 1 CLK_RTC>; - assigned-clocks = <&rcc 1 CLK_RTC>; - assigned-clock-parents = <&rcc 1 CLK_LSE>; - interrupt-parent = <&exti>; - interrupts = <17 1>; - st,syscfg = <&pwrcfg 0x00 0x100>; - }; - - rtc: rtc@58004000 { - compatible = "st,stm32h7-rtc"; - reg = <0x58004000 0x400>; - clocks = <&rcc RTCAPB_CK>, <&rcc RTC_CK>; - clock-names = "pclk", "rtc_ck"; - assigned-clocks = <&rcc RTC_CK>; - assigned-clock-parents = <&rcc LSE_CK>; - interrupt-parent = <&exti>; - interrupts = <17 1>; - interrupt-names = "alarm"; - st,syscfg = <&pwrcfg 0x00 0x100>; - }; - - rtc: rtc@5c004000 { - compatible = "st,stm32mp1-rtc"; - reg = <0x5c004000 0x400>; - clocks = <&rcc RTCAPB>, <&rcc RTC>; - clock-names = "pclk", "rtc_ck"; - interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>, - <&exti 19 1>; - }; diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml new file mode 100644 index 000000000000..0a54296d7218 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml @@ -0,0 +1,139 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/rtc/st,stm32-rtc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Real Time Clock Bindings + +maintainers: + - Gabriel Fernandez + +properties: + compatible: + enum: + - st,stm32-rtc + - st,stm32h7-rtc + - st,stm32mp1-rtc + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + + clock-names: + items: + - const: pclk + - const: rtc_ck + + interrupts: + maxItems: 1 + + st,syscfg: + allOf: + - $ref: "/schemas/types.yaml#/definitions/phandle-array" + - items: + minItems: 3 + maxItems: 3 + description: | + Phandle/offset/mask triplet. The phandle to pwrcfg used to + access control register at offset, and change the dbp (Disable Backup + Protection) bit represented by the mask, mandatory to disable/enable backup + domain (RTC registers) write protection. + + assigned-clocks: + description: | + override default rtc_ck parent clock reference to the rtc_ck clock entry + maxItems: 1 + + assigned-clock-parents: + description: | + override default rtc_ck parent clock phandle of the new parent clock of rtc_ck + maxItems: 1 + +allOf: + - if: + properties: + compatible: + contains: + const: st,stm32-rtc + + then: + properties: + clocks: + minItems: 1 + maxItems: 1 + + clock-names: false + + required: + - st,syscfg + + - if: + properties: + compatible: + contains: + const: st,stm32h7-rtc + + then: + properties: + clocks: + minItems: 2 + maxItems: 2 + + required: + - clock-names + - st,syscfg + + - if: + properties: + compatible: + contains: + const: st,stm32mp1-rtc + + then: + properties: + clocks: + minItems: 2 + maxItems: 2 + + assigned-clocks: false + assigned-clock-parents: false + + required: + - clock-names + +required: + - compatible + - reg + - clocks + - interrupts + +examples: + - | + #include + #include + rtc@40002800 { + compatible = "st,stm32-rtc"; + reg = <0x40002800 0x400>; + clocks = <&rcc 1 CLK_RTC>; + assigned-clocks = <&rcc 1 CLK_RTC>; + assigned-clock-parents = <&rcc 1 CLK_LSE>; + interrupt-parent = <&exti>; + interrupts = <17 1>; + st,syscfg = <&pwrcfg 0x00 0x100>; + }; + + #include + #include + rtc@5c004000 { + compatible = "st,stm32mp1-rtc"; + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; + interrupts = ; + }; + +... -- cgit v1.2.3 From 34566e4f2d681570c271bf71f8405e0c78251127 Mon Sep 17 00:00:00 2001 From: Arnaud Pouliquen Date: Tue, 17 Dec 2019 09:24:15 +0100 Subject: dt-bindings: stm32: convert mlahb to json-schema Convert the ML-AHB bus bindings to DT schema format using json-schema Signed-off-by: Arnaud Pouliquen Signed-off-by: Rob Herring --- .../devicetree/bindings/arm/stm32/mlahb.txt | 37 ------------ .../devicetree/bindings/arm/stm32/st,mlahb.yaml | 70 ++++++++++++++++++++++ 2 files changed, 70 insertions(+), 37 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/stm32/mlahb.txt create mode 100644 Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/stm32/mlahb.txt b/Documentation/devicetree/bindings/arm/stm32/mlahb.txt deleted file mode 100644 index 25307aa1eb9b..000000000000 --- a/Documentation/devicetree/bindings/arm/stm32/mlahb.txt +++ /dev/null @@ -1,37 +0,0 @@ -ML-AHB interconnect bindings - -These bindings describe the STM32 SoCs ML-AHB interconnect bus which connects -a Cortex-M subsystem with dedicated memories. -The MCU SRAM and RETRAM memory parts can be accessed through different addresses -(see "RAM aliases" in [1]) using different buses (see [2]) : balancing the -Cortex-M firmware accesses among those ports allows to tune the system -performance. - -[1]: https://www.st.com/resource/en/reference_manual/dm00327659.pdf -[2]: https://wiki.st.com/stm32mpu/wiki/STM32MP15_RAM_mapping - -Required properties: -- compatible: should be "simple-bus" -- dma-ranges: describes memory addresses translation between the local CPU and - the remote Cortex-M processor. Each memory region, is declared with - 3 parameters: - - param 1: device base address (Cortex-M processor address) - - param 2: physical base address (local CPU address) - - param 3: size of the memory region. - -The Cortex-M remote processor accessed via the mlahb interconnect is described -by a child node. - -Example: -mlahb { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - dma-ranges = <0x00000000 0x38000000 0x10000>, - <0x10000000 0x10000000 0x60000>, - <0x30000000 0x30000000 0x60000>; - - m4_rproc: m4@10000000 { - ... - }; -}; diff --git a/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml b/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml new file mode 100644 index 000000000000..68917bb7c7e8 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/arm/stm32/st,mlahb.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: STMicroelectronics STM32 ML-AHB interconnect bindings + +maintainers: + - Fabien Dessenne + - Arnaud Pouliquen + +description: | + These bindings describe the STM32 SoCs ML-AHB interconnect bus which connects + a Cortex-M subsystem with dedicated memories. The MCU SRAM and RETRAM memory + parts can be accessed through different addresses (see "RAM aliases" in [1]) + using different buses (see [2]): balancing the Cortex-M firmware accesses + among those ports allows to tune the system performance. + [1]: https://www.st.com/resource/en/reference_manual/dm00327659.pdf + [2]: https://wiki.st.com/stm32mpu/wiki/STM32MP15_RAM_mapping + +allOf: + - $ref: /schemas/simple-bus.yaml# + +properties: + compatible: + contains: + enum: + - st,mlahb + + dma-ranges: + description: | + Describe memory addresses translation between the local CPU and the + remote Cortex-M processor. Each memory region, is declared with + 3 parameters: + - param 1: device base address (Cortex-M processor address) + - param 2: physical base address (local CPU address) + - param 3: size of the memory region. + maxItems: 3 + + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + +required: + - compatible + - '#address-cells' + - '#size-cells' + - dma-ranges + +examples: + - | + mlahb: ahb { + compatible = "st,mlahb", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x10000000 0x40000>; + ranges; + dma-ranges = <0x00000000 0x38000000 0x10000>, + <0x10000000 0x10000000 0x60000>, + <0x30000000 0x30000000 0x60000>; + + m4_rproc: m4@10000000 { + reg = <0x10000000 0x40000>; + }; + }; + +... -- cgit v1.2.3 From b80103f60b0d3b69d7640c7806c641930f5665a2 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 17 Dec 2019 10:21:56 +0100 Subject: dt-bindings: dma: Convert stm32 DMA bindings to json-schema Convert the STM32 DMA binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../devicetree/bindings/dma/st,stm32-dma.yaml | 102 +++++++++++++++++++++ .../devicetree/bindings/dma/stm32-dma.txt | 83 ----------------- 2 files changed, 102 insertions(+), 83 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/st,stm32-dma.yaml delete mode 100644 Documentation/devicetree/bindings/dma/stm32-dma.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml new file mode 100644 index 000000000000..0c0ac11ad55f --- /dev/null +++ b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/st,stm32-dma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 DMA Controller bindings + +description: | + The STM32 DMA is a general-purpose direct memory access controller capable of + supporting 8 independent DMA channels. Each channel can have up to 8 requests. + DMA clients connected to the STM32 DMA controller must use the format + described in the dma.txt file, using a four-cell specifier for each + channel: a phandle to the DMA controller plus the following four integer cells: + 1. The channel id + 2. The request line number + 3. A 32bit mask specifying the DMA channel configuration which are device + dependent: + -bit 9: Peripheral Increment Address + 0x0: no address increment between transfers + 0x1: increment address between transfers + -bit 10: Memory Increment Address + 0x0: no address increment between transfers + 0x1: increment address between transfers + -bit 15: Peripheral Increment Offset Size + 0x0: offset size is linked to the peripheral bus width + 0x1: offset size is fixed to 4 (32-bit alignment) + -bit 16-17: Priority level + 0x0: low + 0x1: medium + 0x2: high + 0x3: very high + 4. A 32bit bitfield value specifying DMA features which are device dependent: + -bit 0-1: DMA FIFO threshold selection + 0x0: 1/4 full FIFO + 0x1: 1/2 full FIFO + 0x2: 3/4 full FIFO + 0x3: full FIFO + +maintainers: + - Amelie Delaunay + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 4 + + compatible: + const: st,stm32-dma + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 8 + description: Should contain all of the per-channel DMA + interrupts in ascending order with respect to the + DMA channel index. + + resets: + maxItems: 1 + + st,mem2mem: + $ref: /schemas/types.yaml#/definitions/flag + description: if defined, it indicates that the controller + supports memory-to-memory transfer + +required: + - compatible + - reg + - clocks + - interrupts + +examples: + - | + #include + #include + #include + dma-controller@40026400 { + compatible = "st,stm32-dma"; + reg = <0x40026400 0x400>; + interrupts = <56>, + <57>, + <58>, + <59>, + <60>, + <68>, + <69>, + <70>; + clocks = <&clk_hclk>; + #dma-cells = <4>; + st,mem2mem; + resets = <&rcc 150>; + dma-requests = <8>; + }; + +... diff --git a/Documentation/devicetree/bindings/dma/stm32-dma.txt b/Documentation/devicetree/bindings/dma/stm32-dma.txt deleted file mode 100644 index c5f519097204..000000000000 --- a/Documentation/devicetree/bindings/dma/stm32-dma.txt +++ /dev/null @@ -1,83 +0,0 @@ -* STMicroelectronics STM32 DMA controller - -The STM32 DMA is a general-purpose direct memory access controller capable of -supporting 8 independent DMA channels. Each channel can have up to 8 requests. - -Required properties: -- compatible: Should be "st,stm32-dma" -- reg: Should contain DMA registers location and length. This should include - all of the per-channel registers. -- interrupts: Should contain all of the per-channel DMA interrupts in - ascending order with respect to the DMA channel index. -- clocks: Should contain the input clock of the DMA instance. -- #dma-cells : Must be <4>. See DMA client paragraph for more details. - -Optional properties: -- dma-requests : Number of DMA requests supported. -- resets: Reference to a reset controller asserting the DMA controller -- st,mem2mem: boolean; if defined, it indicates that the controller supports - memory-to-memory transfer - -Example: - - dma2: dma-controller@40026400 { - compatible = "st,stm32-dma"; - reg = <0x40026400 0x400>; - interrupts = <56>, - <57>, - <58>, - <59>, - <60>, - <68>, - <69>, - <70>; - clocks = <&clk_hclk>; - #dma-cells = <4>; - st,mem2mem; - resets = <&rcc 150>; - dma-requests = <8>; - }; - -* DMA client - -DMA clients connected to the STM32 DMA controller must use the format -described in the dma.txt file, using a four-cell specifier for each -channel: a phandle to the DMA controller plus the following four integer cells: - -1. The channel id -2. The request line number -3. A 32bit mask specifying the DMA channel configuration which are device - dependent: - -bit 9: Peripheral Increment Address - 0x0: no address increment between transfers - 0x1: increment address between transfers - -bit 10: Memory Increment Address - 0x0: no address increment between transfers - 0x1: increment address between transfers - -bit 15: Peripheral Increment Offset Size - 0x0: offset size is linked to the peripheral bus width - 0x1: offset size is fixed to 4 (32-bit alignment) - -bit 16-17: Priority level - 0x0: low - 0x1: medium - 0x2: high - 0x3: very high -4. A 32bit bitfield value specifying DMA features which are device dependent: - -bit 0-1: DMA FIFO threshold selection - 0x0: 1/4 full FIFO - 0x1: 1/2 full FIFO - 0x2: 3/4 full FIFO - 0x3: full FIFO - - -Example: - - usart1: serial@40011000 { - compatible = "st,stm32-uart"; - reg = <0x40011000 0x400>; - interrupts = <37>; - clocks = <&clk_pclk2>; - dmas = <&dma2 2 4 0x10400 0x3>, - <&dma2 7 5 0x10200 0x3>; - dma-names = "rx", "tx"; - }; -- cgit v1.2.3 From 71021f3fd3af00482d55e4c62a23cc6148f6347d Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 17 Dec 2019 10:21:57 +0100 Subject: dt-bindings: dma: Convert stm32 MDMA bindings to json-schema Convert the STM32 MDMA binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../devicetree/bindings/dma/st,stm32-mdma.yaml | 105 +++++++++++++++++++++ .../devicetree/bindings/dma/stm32-mdma.txt | 94 ------------------ 2 files changed, 105 insertions(+), 94 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml delete mode 100644 Documentation/devicetree/bindings/dma/stm32-mdma.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml new file mode 100644 index 000000000000..c66543d0c267 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/st,stm32-mdma.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 MDMA Controller bindings + +description: | + The STM32 MDMA is a general-purpose direct memory access controller capable of + supporting 64 independent DMA channels with 256 HW requests. + DMA clients connected to the STM32 MDMA controller must use the format + described in the dma.txt file, using a five-cell specifier for each channel: + a phandle to the MDMA controller plus the following five integer cells: + 1. The request line number + 2. The priority level + 0x0: Low + 0x1: Medium + 0x2: High + 0x3: Very high + 3. A 32bit mask specifying the DMA channel configuration + -bit 0-1: Source increment mode + 0x0: Source address pointer is fixed + 0x2: Source address pointer is incremented after each data transfer + 0x3: Source address pointer is decremented after each data transfer + -bit 2-3: Destination increment mode + 0x0: Destination address pointer is fixed + 0x2: Destination address pointer is incremented after each data transfer + 0x3: Destination address pointer is decremented after each data transfer + -bit 8-9: Source increment offset size + 0x0: byte (8bit) + 0x1: half-word (16bit) + 0x2: word (32bit) + 0x3: double-word (64bit) + -bit 10-11: Destination increment offset size + 0x0: byte (8bit) + 0x1: half-word (16bit) + 0x2: word (32bit) + 0x3: double-word (64bit) + -bit 25-18: The number of bytes to be transferred in a single transfer + (min = 1 byte, max = 128 bytes) + -bit 29:28: Trigger Mode + 0x00: Each MDMA request triggers a buffer transfer (max 128 bytes) + 0x1: Each MDMA request triggers a block transfer (max 64K bytes) + 0x2: Each MDMA request triggers a repeated block transfer + 0x3: Each MDMA request triggers a linked list transfer + 4. A 32bit value specifying the register to be used to acknowledge the request + if no HW ack signal is used by the MDMA client + 5. A 32bit mask specifying the value to be written to acknowledge the request + if no HW ack signal is used by the MDMA client + +maintainers: + - Amelie Delaunay + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 5 + + compatible: + const: st,stm32h7-mdma + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + st,ahb-addr-masks: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: Array of u32 mask to list memory devices addressed via AHB bus. + +required: + - compatible + - reg + - clocks + - interrupts + +examples: + - | + #include + #include + #include + dma-controller@52000000 { + compatible = "st,stm32h7-mdma"; + reg = <0x52000000 0x1000>; + interrupts = <122>; + clocks = <&timer_clk>; + resets = <&rcc 992>; + #dma-cells = <5>; + dma-channels = <16>; + dma-requests = <32>; + st,ahb-addr-masks = <0x20000000>, <0x00000000>; + }; + +... + diff --git a/Documentation/devicetree/bindings/dma/stm32-mdma.txt b/Documentation/devicetree/bindings/dma/stm32-mdma.txt deleted file mode 100644 index d18772d6bc65..000000000000 --- a/Documentation/devicetree/bindings/dma/stm32-mdma.txt +++ /dev/null @@ -1,94 +0,0 @@ -* STMicroelectronics STM32 MDMA controller - -The STM32 MDMA is a general-purpose direct memory access controller capable of -supporting 64 independent DMA channels with 256 HW requests. - -Required properties: -- compatible: Should be "st,stm32h7-mdma" -- reg: Should contain MDMA registers location and length. This should include - all of the per-channel registers. -- interrupts: Should contain the MDMA interrupt. -- clocks: Should contain the input clock of the DMA instance. -- resets: Reference to a reset controller asserting the DMA controller. -- #dma-cells : Must be <5>. See DMA client paragraph for more details. - -Optional properties: -- dma-channels: Number of DMA channels supported by the controller. -- dma-requests: Number of DMA request signals supported by the controller. -- st,ahb-addr-masks: Array of u32 mask to list memory devices addressed via - AHB bus. - -Example: - - mdma1: dma@52000000 { - compatible = "st,stm32h7-mdma"; - reg = <0x52000000 0x1000>; - interrupts = <122>; - clocks = <&timer_clk>; - resets = <&rcc 992>; - #dma-cells = <5>; - dma-channels = <16>; - dma-requests = <32>; - st,ahb-addr-masks = <0x20000000>, <0x00000000>; - }; - -* DMA client - -DMA clients connected to the STM32 MDMA controller must use the format -described in the dma.txt file, using a five-cell specifier for each channel: -a phandle to the MDMA controller plus the following five integer cells: - -1. The request line number -2. The priority level - 0x00: Low - 0x01: Medium - 0x10: High - 0x11: Very high -3. A 32bit mask specifying the DMA channel configuration - -bit 0-1: Source increment mode - 0x00: Source address pointer is fixed - 0x10: Source address pointer is incremented after each data transfer - 0x11: Source address pointer is decremented after each data transfer - -bit 2-3: Destination increment mode - 0x00: Destination address pointer is fixed - 0x10: Destination address pointer is incremented after each data - transfer - 0x11: Destination address pointer is decremented after each data - transfer - -bit 8-9: Source increment offset size - 0x00: byte (8bit) - 0x01: half-word (16bit) - 0x10: word (32bit) - 0x11: double-word (64bit) - -bit 10-11: Destination increment offset size - 0x00: byte (8bit) - 0x01: half-word (16bit) - 0x10: word (32bit) - 0x11: double-word (64bit) --bit 25-18: The number of bytes to be transferred in a single transfer - (min = 1 byte, max = 128 bytes) --bit 29:28: Trigger Mode - 0x00: Each MDMA request triggers a buffer transfer (max 128 bytes) - 0x01: Each MDMA request triggers a block transfer (max 64K bytes) - 0x10: Each MDMA request triggers a repeated block transfer - 0x11: Each MDMA request triggers a linked list transfer -4. A 32bit value specifying the register to be used to acknowledge the request - if no HW ack signal is used by the MDMA client -5. A 32bit mask specifying the value to be written to acknowledge the request - if no HW ack signal is used by the MDMA client - -Example: - - i2c4: i2c@5c002000 { - compatible = "st,stm32f7-i2c"; - reg = <0x5c002000 0x400>; - interrupts = <95>, - <96>; - clocks = <&timer_clk>; - #address-cells = <1>; - #size-cells = <0>; - dmas = <&mdma1 36 0x0 0x40008 0x0 0x0>, - <&mdma1 37 0x0 0x40002 0x0 0x0>; - dma-names = "rx", "tx"; - status = "disabled"; - }; -- cgit v1.2.3 From 0b7c446fa9f72fe14fd87154d9e183baa958c979 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 17 Dec 2019 10:21:58 +0100 Subject: dt-bindings: dma: Convert stm32 DMAMUX bindings to json-schema Convert the STM32 DMAMUX binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../devicetree/bindings/dma/st,stm32-dmamux.yaml | 52 ++++++++++++++ .../devicetree/bindings/dma/stm32-dmamux.txt | 84 ---------------------- 2 files changed, 52 insertions(+), 84 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml delete mode 100644 Documentation/devicetree/bindings/dma/stm32-dmamux.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml new file mode 100644 index 000000000000..915bc4af9568 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/st,stm32-dmamux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 DMA MUX (DMA request router) bindings + +maintainers: + - Amelie Delaunay + +allOf: + - $ref: "dma-router.yaml#" + +properties: + "#dma-cells": + const: 3 + + compatible: + const: st,stm32h7-dmamux + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + resets: + maxItems: 1 + +required: + - compatible + - reg + - dma-masters + +examples: + - | + #include + #include + #include + dma-router@40020800 { + compatible = "st,stm32h7-dmamux"; + reg = <0x40020800 0x3c>; + #dma-cells = <3>; + dma-requests = <128>; + dma-channels = <16>; + dma-masters = <&dma1 &dma2>; + clocks = <&timer_clk>; + }; + +... + diff --git a/Documentation/devicetree/bindings/dma/stm32-dmamux.txt b/Documentation/devicetree/bindings/dma/stm32-dmamux.txt deleted file mode 100644 index 1b893b235507..000000000000 --- a/Documentation/devicetree/bindings/dma/stm32-dmamux.txt +++ /dev/null @@ -1,84 +0,0 @@ -STM32 DMA MUX (DMA request router) - -Required properties: -- compatible: "st,stm32h7-dmamux" -- reg: Memory map for accessing module -- #dma-cells: Should be set to <3>. - First parameter is request line number. - Second is DMA channel configuration - Third is Fifo threshold - For more details about the three cells, please see - stm32-dma.txt documentation binding file -- dma-masters: Phandle pointing to the DMA controllers. - Several controllers are allowed. Only "st,stm32-dma" DMA - compatible are supported. - -Optional properties: -- dma-channels : Number of DMA requests supported. -- dma-requests : Number of DMAMUX requests supported. -- resets: Reference to a reset controller asserting the DMA controller -- clocks: Input clock of the DMAMUX instance. - -Example: - -/* DMA controller 1 */ -dma1: dma-controller@40020000 { - compatible = "st,stm32-dma"; - reg = <0x40020000 0x400>; - interrupts = <11>, - <12>, - <13>, - <14>, - <15>, - <16>, - <17>, - <47>; - clocks = <&timer_clk>; - #dma-cells = <4>; - st,mem2mem; - resets = <&rcc 150>; - dma-channels = <8>; - dma-requests = <8>; -}; - -/* DMA controller 1 */ -dma2: dma@40020400 { - compatible = "st,stm32-dma"; - reg = <0x40020400 0x400>; - interrupts = <56>, - <57>, - <58>, - <59>, - <60>, - <68>, - <69>, - <70>; - clocks = <&timer_clk>; - #dma-cells = <4>; - st,mem2mem; - resets = <&rcc 150>; - dma-channels = <8>; - dma-requests = <8>; -}; - -/* DMA mux */ -dmamux1: dma-router@40020800 { - compatible = "st,stm32h7-dmamux"; - reg = <0x40020800 0x3c>; - #dma-cells = <3>; - dma-requests = <128>; - dma-channels = <16>; - dma-masters = <&dma1 &dma2>; - clocks = <&timer_clk>; -}; - -/* DMA client */ -usart1: serial@40011000 { - compatible = "st,stm32-usart", "st,stm32-uart"; - reg = <0x40011000 0x400>; - interrupts = <37>; - clocks = <&timer_clk>; - dmas = <&dmamux1 41 0x414 0>, - <&dmamux1 42 0x414 0>; - dma-names = "rx", "tx"; -}; -- cgit v1.2.3 From 7f7b9455b35290a1032c73222261bfd784cc3702 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Wed, 16 Oct 2019 10:55:41 +0200 Subject: dt-bindings: display: renesas,cmm: Add R-Car CMM documentation Add device tree bindings documentation for the Renesas R-Car Display Unit Color Management Module. CMM is the image enhancement module available on each R-Car DU video channel on R-Car Gen2 and Gen3 SoCs (V3H and V3M excluded). Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Reviewed-by: Rob Herring Signed-off-by: Laurent Pinchart --- .../devicetree/bindings/display/renesas,cmm.yaml | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/renesas,cmm.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/renesas,cmm.yaml b/Documentation/devicetree/bindings/display/renesas,cmm.yaml new file mode 100644 index 000000000000..a57037b9e9ba --- /dev/null +++ b/Documentation/devicetree/bindings/display/renesas,cmm.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/renesas,cmm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas R-Car Color Management Module (CMM) + +maintainers: + - Laurent Pinchart + - Kieran Bingham + - Jacopo Mondi + +description: |+ + Renesas R-Car color management module connected to R-Car DU video channels. + It provides image enhancement functions such as 1-D look-up tables (LUT), + 3-D look-up tables (CLU), 1D-histogram generation (HGO), and color + space conversion (CSC). + +properties: + compatible: + oneOf: + - items: + - enum: + - renesas,r8a7795-cmm + - renesas,r8a7796-cmm + - renesas,r8a77965-cmm + - renesas,r8a77990-cmm + - renesas,r8a77995-cmm + - const: renesas,rcar-gen3-cmm + - items: + - const: renesas,rcar-gen2-cmm + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + resets: + maxItems: 1 + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - resets + - power-domains + +additionalProperties: false + +examples: + - | + #include + #include + + cmm0: cmm@fea40000 { + compatible = "renesas,r8a7796-cmm", + "renesas,rcar-gen3-cmm"; + reg = <0 0xfea40000 0 0x1000>; + power-domains = <&sysc R8A7796_PD_ALWAYS_ON>; + clocks = <&cpg CPG_MOD 711>; + resets = <&cpg 711>; + }; -- cgit v1.2.3 From 6e2258b58f819e73aad229fd0af7d8274ef22669 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Wed, 16 Oct 2019 10:55:42 +0200 Subject: dt-bindings: display: renesas,du: Document cmms property Document the newly added 'renesas,cmms' property which accepts a list of phandle and channel index pairs that point to the CMM units available for each Display Unit output video channel. Reviewed-by: Rob Herring Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi Signed-off-by: Laurent Pinchart --- Documentation/devicetree/bindings/display/renesas,du.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index 17cb2771364b..f6fdaa67c257 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -46,6 +46,10 @@ Required Properties: instance that serves the DU channel, and the channel index identifies the LIF instance in that VSP. + - renesas,cmms: A list of phandles to the CMM instances present in the SoC, + one for each available DU channel. The property shall not be specified for + SoCs that do not provide any CMM (such as V3M and V3H). + Required nodes: The connections to the DU output video ports are modeled using the OF graph @@ -93,6 +97,7 @@ Example: R8A7795 (R-Car H3) ES2.0 DU <&cpg CPG_MOD 721>; clock-names = "du.0", "du.1", "du.2", "du.3"; vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>; + renesas,cmms = <&cmm0>, <&cmm1>, <&cmm2>, <&cmm3>; ports { #address-cells = <1>; -- cgit v1.2.3 From c81456d2452da72891688edb81d2f0749c2db568 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 5 Nov 2019 19:35:02 +0100 Subject: dt-bindings: display: renesas: du: Add vendor prefix to vsps property The Renesas-specific "vsps" property lacks a vendor prefix. Add a "renesas," prefix to comply with DT best practises. Move "renesas,vsps" below "renesas,cmms" to preserve alphabetical sort order. Fixes: 06711e6385a4ab4c ("drm: rcar-du: Document the vsps property in the DT bindings") Signed-off-by: Geert Uytterhoeven Acked-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Laurent Pinchart --- Documentation/devicetree/bindings/display/renesas,du.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/renesas,du.txt b/Documentation/devicetree/bindings/display/renesas,du.txt index f6fdaa67c257..eb4ae41fe41f 100644 --- a/Documentation/devicetree/bindings/display/renesas,du.txt +++ b/Documentation/devicetree/bindings/display/renesas,du.txt @@ -41,15 +41,15 @@ Required Properties: supplied they must be named "dclkin.x" with "x" being the input clock numerical index. - - vsps: A list of phandle and channel index tuples to the VSPs that handle - the memory interfaces for the DU channels. The phandle identifies the VSP - instance that serves the DU channel, and the channel index identifies the - LIF instance in that VSP. - - renesas,cmms: A list of phandles to the CMM instances present in the SoC, one for each available DU channel. The property shall not be specified for SoCs that do not provide any CMM (such as V3M and V3H). + - renesas,vsps: A list of phandle and channel index tuples to the VSPs that + handle the memory interfaces for the DU channels. The phandle identifies the + VSP instance that serves the DU channel, and the channel index identifies + the LIF instance in that VSP. + Required nodes: The connections to the DU output video ports are modeled using the OF graph @@ -96,8 +96,8 @@ Example: R8A7795 (R-Car H3) ES2.0 DU <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>; clock-names = "du.0", "du.1", "du.2", "du.3"; - vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>; renesas,cmms = <&cmm0>, <&cmm1>, <&cmm2>, <&cmm3>; + renesas,vsps = <&vspd0 0>, <&vspd1 0>, <&vspd2 0>, <&vspd0 1>; ports { #address-cells = <1>; -- cgit v1.2.3 From 0b2f7ad1f2f65fd9d0488f98eb680e7cbc640e3f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:33:40 +0100 Subject: dt-bindings: usb: Convert Allwinner USB PHY controller to a schema The Allwinner SoCs have a USB PHY controller that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../bindings/phy/allwinner,sun4i-a10-usb-phy.yaml | 105 ++++++++++++++++ .../bindings/phy/allwinner,sun50i-a64-usb-phy.yaml | 106 ++++++++++++++++ .../bindings/phy/allwinner,sun50i-h6-usb-phy.yaml | 105 ++++++++++++++++ .../bindings/phy/allwinner,sun5i-a13-usb-phy.yaml | 93 ++++++++++++++ .../bindings/phy/allwinner,sun6i-a31-usb-phy.yaml | 119 ++++++++++++++++++ .../bindings/phy/allwinner,sun8i-a23-usb-phy.yaml | 102 +++++++++++++++ .../bindings/phy/allwinner,sun8i-a83t-usb-phy.yaml | 122 ++++++++++++++++++ .../bindings/phy/allwinner,sun8i-h3-usb-phy.yaml | 137 +++++++++++++++++++++ .../bindings/phy/allwinner,sun8i-r40-usb-phy.yaml | 119 ++++++++++++++++++ .../bindings/phy/allwinner,sun8i-v3s-usb-phy.yaml | 86 +++++++++++++ .../devicetree/bindings/phy/sun4i-usb-phy.txt | 68 ---------- 11 files changed, 1094 insertions(+), 68 deletions(-) create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun4i-a10-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun50i-h6-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun5i-a13-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-a23-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-a83t-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v3s-usb-phy.yaml delete mode 100644 Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun4i-a10-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun4i-a10-usb-phy.yaml new file mode 100644 index 000000000000..020ef9e4c411 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun4i-a10-usb-phy.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun4i-a10-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + enum: + - allwinner,sun4i-a10-usb-phy + - allwinner,sun7i-a20-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU1 registers + - description: PHY PMU2 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu1 + - const: pmu2 + + clocks: + maxItems: 1 + description: USB PHY bus clock + + clock-names: + const: usb_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + - description: USB Host 2 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + - const: usb2_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + + usb2_vbus-supply: + description: Regulator controlling USB2 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + usbphy: phy@01c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun4i-a10-usb-phy"; + reg = <0x01c13400 0x10>, <0x01c14800 0x4>, <0x01c1c800 0x4>; + reg-names = "phy_ctrl", "pmu1", "pmu2"; + clocks = <&ccu CLK_USB_PHY>; + clock-names = "usb_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>, + <&ccu RST_USB_PHY2>; + reset-names = "usb0_reset", "usb1_reset", "usb2_reset"; + usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; + usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml new file mode 100644 index 000000000000..fd6e126fcf18 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a64-usb-phy.yaml @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun50i-a64-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A64 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun50i-a64-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU0 registers + - description: PHY PMU1 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu0 + - const: pmu1 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + + clock-names: + items: + - const: usb0_phy + - const: usb1_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c19400 { + #phy-cells = <1>; + compatible = "allwinner,sun50i-a64-usb-phy"; + reg = <0x01c19400 0x14>, + <0x01c1a800 0x4>, + <0x01c1b800 0x4>; + reg-names = "phy_ctrl", + "pmu0", + "pmu1"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>; + clock-names = "usb0_phy", + "usb1_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>; + reset-names = "usb0_reset", + "usb1_reset"; + usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_usb1_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-h6-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-h6-usb-phy.yaml new file mode 100644 index 000000000000..7670411002c9 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-h6-usb-phy.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun50i-h6-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner H6 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun50i-h6-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU0 registers + - description: PHY PMU3 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu0 + - const: pmu3 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host PHY bus clock + + clock-names: + items: + - const: usb0_phy + - const: usb3_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb3_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb3_vbus-supply: + description: Regulator controlling USB3 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@5100400 { + #phy-cells = <1>; + compatible = "allwinner,sun50i-h6-usb-phy"; + reg = <0x05100400 0x24>, + <0x05101800 0x4>, + <0x05311800 0x4>; + reg-names = "phy_ctrl", + "pmu0", + "pmu3"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY3>; + clock-names = "usb0_phy", + "usb3_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY3>; + reset-names = "usb0_reset", + "usb3_reset"; + usb0_id_det-gpios = <&pio 2 6 GPIO_ACTIVE_HIGH>; /* PC6 */ + usb0_vbus-supply = <®_vcc5v>; + usb3_vbus-supply = <®_vcc5v>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun5i-a13-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun5i-a13-usb-phy.yaml new file mode 100644 index 000000000000..9b319381d1ad --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun5i-a13-usb-phy.yaml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun5i-a13-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A13 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun5i-a13-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU1 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu1 + + clocks: + maxItems: 1 + description: USB OTG PHY bus clock + + clock-names: + const: usb_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun5i-a13-usb-phy"; + reg = <0x01c13400 0x10>, <0x01c14800 0x4>; + reg-names = "phy_ctrl", "pmu1"; + clocks = <&ccu CLK_USB_PHY0>; + clock-names = "usb_phy"; + resets = <&ccu RST_USB_PHY0>, <&ccu RST_USB_PHY1>; + reset-names = "usb0_reset", "usb1_reset"; + usb0_id_det-gpios = <&pio 6 2 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PG2 */ + usb0_vbus_det-gpios = <&pio 6 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; /* PG1 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-usb-phy.yaml new file mode 100644 index 000000000000..b0ed01bbf3db --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-usb-phy.yaml @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun6i-a31-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun6i-a31-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU1 registers + - description: PHY PMU2 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu1 + - const: pmu2 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + - description: USB Host 1 PHY bus clock + + clock-names: + items: + - const: usb0_phy + - const: usb1_phy + - const: usb2_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + - description: USB Host 2 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + - const: usb2_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + + usb2_vbus-supply: + description: Regulator controlling USB2 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c19400 { + #phy-cells = <1>; + compatible = "allwinner,sun6i-a31-usb-phy"; + reg = <0x01c19400 0x10>, + <0x01c1a800 0x4>, + <0x01c1b800 0x4>; + reg-names = "phy_ctrl", + "pmu1", + "pmu2"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>, + <&ccu CLK_USB_PHY2>; + clock-names = "usb0_phy", + "usb1_phy", + "usb2_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>, + <&ccu RST_USB_PHY2>; + reset-names = "usb0_reset", + "usb1_reset", + "usb2_reset"; + usb0_id_det-gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>; /* PA15 */ + usb0_vbus_det-gpios = <&pio 0 16 GPIO_ACTIVE_HIGH>; /* PA16 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-a23-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-a23-usb-phy.yaml new file mode 100644 index 000000000000..b0674406f8aa --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-a23-usb-phy.yaml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-a23-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A23 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + enum: + - allwinner,sun8i-a23-usb-phy + - allwinner,sun8i-a33-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU1 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu1 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + + clock-names: + items: + - const: usb0_phy + - const: usb1_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c19400 { + #phy-cells = <1>; + compatible = "allwinner,sun8i-a23-usb-phy"; + reg = <0x01c19400 0x10>, <0x01c1a800 0x4>; + reg-names = "phy_ctrl", "pmu1"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>; + clock-names = "usb0_phy", + "usb1_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>; + reset-names = "usb0_reset", + "usb1_reset"; + usb0_id_det-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_usb1_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-a83t-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-a83t-usb-phy.yaml new file mode 100644 index 000000000000..48dc9c834a9b --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-a83t-usb-phy.yaml @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-a83t-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A83t USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun8i-a83t-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU1 registers + - description: PHY PMU2 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu1 + - const: pmu2 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + - description: USB Host 1 PHY bus clock + - description: USB HSIC 12MHz clock + + clock-names: + items: + - const: usb0_phy + - const: usb1_phy + - const: usb2_phy + - const: usb2_hsic_12M + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + - description: USB Host 2 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + - const: usb2_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + + usb2_vbus-supply: + description: Regulator controlling USB2 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c19400 { + #phy-cells = <1>; + compatible = "allwinner,sun8i-a83t-usb-phy"; + reg = <0x01c19400 0x10>, + <0x01c1a800 0x14>, + <0x01c1b800 0x14>; + reg-names = "phy_ctrl", + "pmu1", + "pmu2"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>, + <&ccu CLK_USB_HSIC>, + <&ccu CLK_USB_HSIC_12M>; + clock-names = "usb0_phy", + "usb1_phy", + "usb2_phy", + "usb2_hsic_12M"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>, + <&ccu RST_USB_HSIC>; + reset-names = "usb0_reset", + "usb1_reset", + "usb2_reset"; + usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */ + usb0_vbus_power-supply = <&usb_power_supply>; + usb0_vbus-supply = <®_drivevbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml new file mode 100644 index 000000000000..60c344585276 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml @@ -0,0 +1,137 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-h3-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner H3 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun8i-h3-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU0 registers + - description: PHY PMU1 registers + - description: PHY PMU2 registers + - description: PHY PMU3 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu0 + - const: pmu1 + - const: pmu2 + - const: pmu3 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + - description: USB Host 1 PHY bus clock + - description: USB Host 2 PHY bus clock + + clock-names: + items: + - const: usb0_phy + - const: usb1_phy + - const: usb2_phy + - const: usb3_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + - description: USB Host 2 Controller reset + - description: USB Host 3 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + - const: usb2_reset + - const: usb3_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + + usb2_vbus-supply: + description: Regulator controlling USB2 Host controller + + usb3_vbus-supply: + description: Regulator controlling USB3 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c19400 { + #phy-cells = <1>; + compatible = "allwinner,sun8i-h3-usb-phy"; + reg = <0x01c19400 0x2c>, + <0x01c1a800 0x4>, + <0x01c1b800 0x4>, + <0x01c1c800 0x4>, + <0x01c1d800 0x4>; + reg-names = "phy_ctrl", + "pmu0", + "pmu1", + "pmu2", + "pmu3"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>, + <&ccu CLK_USB_PHY2>, + <&ccu CLK_USB_PHY3>; + clock-names = "usb0_phy", + "usb1_phy", + "usb2_phy", + "usb3_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>, + <&ccu RST_USB_PHY2>, + <&ccu RST_USB_PHY3>; + reset-names = "usb0_reset", + "usb1_reset", + "usb2_reset", + "usb3_reset"; + usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */ + usb0_vbus-supply = <®_usb0_vbus>; + usb1_vbus-supply = <®_usb1_vbus>; + usb2_vbus-supply = <®_usb2_vbus>; + usb3_vbus-supply = <®_usb3_vbus>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml new file mode 100644 index 000000000000..a2bb36790fbd --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-r40-usb-phy.yaml @@ -0,0 +1,119 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-r40-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner R40 USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun8i-r40-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU0 registers + - description: PHY PMU1 registers + - description: PHY PMU2 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu0 + - const: pmu1 + - const: pmu2 + + clocks: + items: + - description: USB OTG PHY bus clock + - description: USB Host 0 PHY bus clock + - description: USB Host 1 PHY bus clock + + clock-names: + items: + - const: usb0_phy + - const: usb1_phy + - const: usb2_phy + + resets: + items: + - description: USB OTG reset + - description: USB Host 1 Controller reset + - description: USB Host 2 Controller reset + + reset-names: + items: + - const: usb0_reset + - const: usb1_reset + - const: usb2_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + + usb1_vbus-supply: + description: Regulator controlling USB1 Host controller + + usb2_vbus-supply: + description: Regulator controlling USB2 Host controller + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c13400 { + #phy-cells = <1>; + compatible = "allwinner,sun8i-r40-usb-phy"; + reg = <0x01c13400 0x14>, + <0x01c14800 0x4>, + <0x01c19800 0x4>, + <0x01c1c800 0x4>; + reg-names = "phy_ctrl", + "pmu0", + "pmu1", + "pmu2"; + clocks = <&ccu CLK_USB_PHY0>, + <&ccu CLK_USB_PHY1>, + <&ccu CLK_USB_PHY2>; + clock-names = "usb0_phy", + "usb1_phy", + "usb2_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>, + <&ccu RST_USB_PHY2>; + reset-names = "usb0_reset", + "usb1_reset", + "usb2_reset"; + usb1_vbus-supply = <®_vcc5v0>; + usb2_vbus-supply = <®_vcc5v0>; + }; diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-v3s-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v3s-usb-phy.yaml new file mode 100644 index 000000000000..eadfd0c9493c --- /dev/null +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v3s-usb-phy.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-v3s-usb-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner V3s USB PHY Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#phy-cells": + const: 1 + + compatible: + const: allwinner,sun8i-v3s-usb-phy + + reg: + items: + - description: PHY Control registers + - description: PHY PMU0 registers + + reg-names: + items: + - const: phy_ctrl + - const: pmu0 + + clocks: + maxItems: 1 + description: USB OTG PHY bus clock + + clock-names: + const: usb0_phy + + resets: + maxItems: 1 + description: USB OTG reset + + reset-names: + const: usb0_reset + + usb0_id_det-gpios: + description: GPIO to the USB OTG ID pin + + usb0_vbus_det-gpios: + description: GPIO to the USB OTG VBUS detect pin + + usb0_vbus_power-supply: + description: Power supply to detect the USB OTG VBUS + + usb0_vbus-supply: + description: Regulator controlling USB OTG VBUS + +required: + - "#phy-cells" + - compatible + - clocks + - clock-names + - reg + - reg-names + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + phy@1c19400 { + #phy-cells = <1>; + compatible = "allwinner,sun8i-v3s-usb-phy"; + reg = <0x01c19400 0x2c>, + <0x01c1a800 0x4>; + reg-names = "phy_ctrl", + "pmu0"; + clocks = <&ccu CLK_USB_PHY0>; + clock-names = "usb0_phy"; + resets = <&ccu RST_USB_PHY0>; + reset-names = "usb0_reset"; + usb0_id_det-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; + }; diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt deleted file mode 100644 index f2e120af17f0..000000000000 --- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +++ /dev/null @@ -1,68 +0,0 @@ -Allwinner sun4i USB PHY ------------------------ - -Required properties: -- compatible : should be one of - * allwinner,sun4i-a10-usb-phy - * allwinner,sun5i-a13-usb-phy - * allwinner,sun6i-a31-usb-phy - * allwinner,sun7i-a20-usb-phy - * allwinner,sun8i-a23-usb-phy - * allwinner,sun8i-a33-usb-phy - * allwinner,sun8i-a83t-usb-phy - * allwinner,sun8i-h3-usb-phy - * allwinner,sun8i-r40-usb-phy - * allwinner,sun8i-v3s-usb-phy - * allwinner,sun50i-a64-usb-phy - * allwinner,sun50i-h6-usb-phy -- reg : a list of offset + length pairs -- reg-names : - * "phy_ctrl" - * "pmu0" for H3, V3s, A64 or H6 - * "pmu1" - * "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 - * "pmu3" for sun8i-h3 or sun50i-h6 -- #phy-cells : from the generic phy bindings, must be 1 -- clocks : phandle + clock specifier for the phy clocks -- clock-names : - * "usb_phy" for sun4i, sun5i or sun7i - * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i - * "usb0_phy", "usb1_phy" for sun8i - * "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t - * "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3 - * "usb0_phy" and "usb3_phy" for sun50i-h6 -- resets : a list of phandle + reset specifier pairs -- reset-names : - * "usb0_reset" - * "usb1_reset" - * "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 - * "usb3_reset" for sun8i-h3 and sun50i-h6 - -Optional properties: -- usb0_id_det-gpios : gpio phandle for reading the otg id pin value -- usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus -- usb0_vbus_power-supply: power-supply phandle for usb0 vbus presence detect -- usb0_vbus-supply : regulator phandle for controller usb0 vbus -- usb1_vbus-supply : regulator phandle for controller usb1 vbus -- usb2_vbus-supply : regulator phandle for controller usb2 vbus -- usb3_vbus-supply : regulator phandle for controller usb3 vbus - -Example: - usbphy: phy@01c13400 { - #phy-cells = <1>; - compatible = "allwinner,sun4i-a10-usb-phy"; - /* phy base regs, phy1 pmu reg, phy2 pmu reg */ - reg = <0x01c13400 0x10 0x01c14800 0x4 0x01c1c800 0x4>; - reg-names = "phy_ctrl", "pmu1", "pmu2"; - clocks = <&usb_clk 8>; - clock-names = "usb_phy"; - resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>; - reset-names = "usb0_reset", "usb1_reset", "usb2_reset"; - pinctrl-names = "default"; - pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>; - usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */ - usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */ - usb0_vbus-supply = <®_usb0_vbus>; - usb1_vbus-supply = <®_usb1_vbus>; - usb2_vbus-supply = <®_usb2_vbus>; - }; -- cgit v1.2.3 From b19da6636c4ae90e3da360b7dd8797365e58b97b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:34:38 +0100 Subject: dt-bindings: sram: Allow for the childs nodes to be called sections The generic SRAM binding currently only allows for child nodes of an SRAM to be called sram too. However, these are also called sections in a number of device tree, which seems a bit more accurate. Let's change the name pattern to allow both. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/sram/sram.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index ee2287a1b14d..83e3bc64d6fc 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -55,7 +55,7 @@ properties: type: boolean patternProperties: - "^([a-z]*-)?sram@[a-f0-9]+$": + "^([a-z]*-)?sram(-section)?@[a-f0-9]+$": type: object description: Each child of the sram node specifies a region of reserved memory. -- cgit v1.2.3 From df45bdd9f615eb7973f8e40a988e55bb5d3832c4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:34:39 +0100 Subject: dt-bindings: sram: Allow for more specific compatibles Even though the generic mmio-sram binding has a list of the sections compatible allowed, most device trees have more specific compatibles attached to those generic ones. This creates warnings at the moment, and we don't really want to cripple the generic binding with all the vendor specific combinations that would prove to be hard to maintain. Let's allow additional compatibles for the sections, and then we can have the vendor-specific bindings to reduce the scope of what's allowed exactly. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/sram/sram.yaml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index 83e3bc64d6fc..9ffef983510b 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -64,15 +64,16 @@ patternProperties: description: Should contain a vendor specific string in the form ,[-] - enum: - - allwinner,sun9i-a80-smp-sram - - amlogic,meson8-smp-sram - - amlogic,meson8b-smp-sram - - renesas,smp-sram - - rockchip,rk3066-smp-sram - - samsung,exynos4210-sysram - - samsung,exynos4210-sysram-ns - - socionext,milbeaut-smp-sram + contains: + enum: + - allwinner,sun9i-a80-smp-sram + - amlogic,meson8-smp-sram + - amlogic,meson8b-smp-sram + - renesas,smp-sram + - rockchip,rk3066-smp-sram + - samsung,exynos4210-sysram + - samsung,exynos4210-sysram-ns + - socionext,milbeaut-smp-sram reg: description: -- cgit v1.2.3 From 3538129cabaa6b57744196a2e084efa022244b00 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:34:40 +0100 Subject: dt-bindings: sram: Add Allwinner SRAM compatibles The mmio-sram binding was added missing a few SRAM sections compatible for allwinner SoCs. Let's add them. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/sram/sram.yaml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml index 9ffef983510b..7b83cc6c9bfa 100644 --- a/Documentation/devicetree/bindings/sram/sram.yaml +++ b/Documentation/devicetree/bindings/sram/sram.yaml @@ -66,7 +66,11 @@ patternProperties: ,[-] contains: enum: + - allwinner,sun4i-a10-sram-a3-a4 + - allwinner,sun4i-a10-sram-c1 + - allwinner,sun4i-a10-sram-d - allwinner,sun9i-a80-smp-sram + - allwinner,sun50i-a64-sram-c - amlogic,meson8-smp-sram - amlogic,meson8b-smp-sram - renesas,smp-sram -- cgit v1.2.3 From e4597da1d685aff534d04fb149a9b8e79563ce7f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 9 Dec 2019 10:34:41 +0100 Subject: dt-bindings: sram: Convert Allwinner A10 system controller to a schema The older Allwinner SoCs have a system controller that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard [robh: fixup missing 'properties'] Signed-off-by: Rob Herring --- .../sram/allwinner,sun4i-a10-system-control.yaml | 140 +++++++++++++++++++++ .../devicetree/bindings/sram/sunxi-sram.txt | 113 ----------------- 2 files changed, 140 insertions(+), 113 deletions(-) create mode 100644 Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml delete mode 100644 Documentation/devicetree/bindings/sram/sunxi-sram.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml new file mode 100644 index 000000000000..80bac7a182d5 --- /dev/null +++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml @@ -0,0 +1,140 @@ +# SPDX-License-Identifier: GPL-2.0+ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sram/allwinner,sun4i-a10-system-control.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 System Control Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +description: + The SRAM controller found on most Allwinner devices is represented + by a regular node for the SRAM controller itself, with sub-nodes + representing the SRAM handled by the SRAM controller. + +properties: + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + compatible: + oneOf: + - const: allwinner,sun4i-a10-sram-controller + deprecated: true + - const: allwinner,sun4i-a10-system-control + - const: allwinner,sun5i-a13-system-control + - items: + - const: allwinner,sun7i-a20-system-control + - const: allwinner,sun4i-a10-system-control + - const: allwinner,sun8i-a23-system-control + - const: allwinner,sun8i-h3-system-control + - const: allwinner,sun50i-a64-sram-controller + deprecated: true + - const: allwinner,sun50i-a64-system-control + - const: allwinner,sun50i-h5-system-control + - items: + - const: allwinner,sun50i-h6-system-control + - const: allwinner,sun50i-a64-system-control + - items: + - const: allwinner,suniv-f1c100s-system-control + - const: allwinner,sun4i-a10-system-control + + reg: + maxItems: 1 + + ranges: true + +patternProperties: + "^sram@[a-z0-9]+": + type: object + + properties: + compatible: + const: mmio-sram + + patternProperties: + "^sram-section?@[a-f0-9]+$": + type: object + + properties: + compatible: + oneOf: + - const: allwinner,sun4i-a10-sram-a3-a4 + - const: allwinner,sun4i-a10-sram-c1 + - const: allwinner,sun4i-a10-sram-d + - const: allwinner,sun50i-a64-sram-c + - items: + - const: allwinner,sun5i-a13-sram-a3-a4 + - const: allwinner,sun4i-a10-sram-a3-a4 + - items: + - const: allwinner,sun7i-a20-sram-a3-a4 + - const: allwinner,sun4i-a10-sram-a3-a4 + - items: + - const: allwinner,sun5i-a13-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun7i-a20-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun8i-a23-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun8i-h3-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun50i-a64-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun50i-h5-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun50i-h6-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun5i-a13-sram-d + - const: allwinner,sun4i-a10-sram-d + - items: + - const: allwinner,sun7i-a20-sram-d + - const: allwinner,sun4i-a10-sram-d + - items: + - const: allwinner,suniv-f1c100s-sram-d + - const: allwinner,sun4i-a10-sram-d + - items: + - const: allwinner,sun50i-h6-sram-c + - const: allwinner,sun50i-a64-sram-c + +required: + - "#address-cells" + - "#size-cells" + - compatible + - reg + +additionalProperties: false + +examples: + - | + system-control@1c00000 { + compatible = "allwinner,sun4i-a10-system-control"; + reg = <0x01c00000 0x30>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + sram_a: sram@00000000 { + compatible = "mmio-sram"; + reg = <0x00000000 0xc000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x00000000 0xc000>; + + emac_sram: sram-section@8000 { + compatible = "allwinner,sun4i-a10-sram-a3-a4"; + reg = <0x8000 0x4000>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/sram/sunxi-sram.txt b/Documentation/devicetree/bindings/sram/sunxi-sram.txt deleted file mode 100644 index 380246a805f2..000000000000 --- a/Documentation/devicetree/bindings/sram/sunxi-sram.txt +++ /dev/null @@ -1,113 +0,0 @@ -Allwinnner SoC SRAM controllers ------------------------------------------------------ - -The SRAM controller found on most Allwinner devices is represented by -a regular node for the SRAM controller itself, with sub-nodes -reprensenting the SRAM handled by the SRAM controller. - -Controller Node ---------------- - -Required properties: -- compatible : should be: - - "allwinner,sun4i-a10-sram-controller" (deprecated) - - "allwinner,sun4i-a10-system-control" - - "allwinner,sun5i-a13-system-control" - - "allwinner,sun7i-a20-system-control", "allwinner,sun4i-a10-system-control" - - "allwinner,sun8i-a23-system-control" - - "allwinner,sun8i-h3-system-control" - - "allwinner,sun50i-a64-sram-controller" (deprecated) - - "allwinner,sun50i-a64-system-control" - - "allwinner,sun50i-h5-system-control" - - "allwinner,sun50i-h6-system-control", "allwinner,sun50i-a64-system-control" - - "allwinner,suniv-f1c100s-system-control", "allwinner,sun4i-a10-system-control" -- reg : sram controller register offset + length - -SRAM nodes ----------- - -Each SRAM is described using the mmio-sram bindings documented in -Documentation/devicetree/bindings/sram/sram.txt - -Each SRAM will have SRAM sections that are going to be handled by the -SRAM controller as subnodes. These sections are represented following -once again the representation described in the mmio-sram binding. - -The valid sections compatible for A10 are: - - allwinner,sun4i-a10-sram-a3-a4 - - allwinner,sun4i-a10-sram-c1 - - allwinner,sun4i-a10-sram-d - -The valid sections compatible for A13 are: - - allwinner,sun5i-a13-sram-a3-a4, allwinner,sun4i-a10-sram-a3-a4 - - allwinner,sun5i-a13-sram-c1, allwinner,sun4i-a10-sram-c1 - - allwinner,sun5i-a13-sram-d, allwinner,sun4i-a10-sram-d - -The valid sections compatible for A20 are: - - allwinner,sun7i-a20-sram-a3-a4, allwinner,sun4i-a10-sram-a3-a4 - - allwinner,sun7i-a20-sram-c1, allwinner,sun4i-a10-sram-c1 - - allwinner,sun7i-a20-sram-d, allwinner,sun4i-a10-sram-d - -The valid sections compatible for A23/A33 are: - - allwinner,sun8i-a23-sram-c1, allwinner,sun4i-a10-sram-c1 - -The valid sections compatible for H3 are: - - allwinner,sun8i-h3-sram-c1, allwinner,sun4i-a10-sram-c1 - -The valid sections compatible for A64 are: - - allwinner,sun50i-a64-sram-c - - allwinner,sun50i-a64-sram-c1, allwinner,sun4i-a10-sram-c1 - -The valid sections compatible for H5 are: - - allwinner,sun50i-h5-sram-c1, allwinner,sun4i-a10-sram-c1 - -The valid sections compatible for H6 are: - - allwinner,sun50i-h6-sram-c, allwinner,sun50i-a64-sram-c - - allwinner,sun50i-h6-sram-c1, allwinner,sun4i-a10-sram-c1 - -The valid sections compatible for F1C100s are: - - allwinner,suniv-f1c100s-sram-d, allwinner,sun4i-a10-sram-d - -Devices using SRAM sections ---------------------------- - -Some devices need to request to the SRAM controller to map an SRAM for -their exclusive use. - -The relationship between such a device and an SRAM section is -expressed through the allwinner,sram property, that will take a -phandle and an argument. - -This valid values for this argument are: - - 0: CPU - - 1: Device - -Example -------- -system-control@1c00000 { - compatible = "allwinner,sun4i-a10-system-control"; - reg = <0x01c00000 0x30>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - sram_a: sram@00000000 { - compatible = "mmio-sram"; - reg = <0x00000000 0xc000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0 0x00000000 0xc000>; - - emac_sram: sram-section@8000 { - compatible = "allwinner,sun4i-a10-sram-a3-a4"; - reg = <0x8000 0x4000>; - }; - }; -}; - -emac: ethernet@1c0b000 { - compatible = "allwinner,sun4i-a10-emac"; - ... - - allwinner,sram = <&emac_sram 1>; -}; -- cgit v1.2.3 From fc0b90f63e7f7583813c2e86b3d0757e45882347 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 13 Dec 2019 08:40:55 +0100 Subject: dt-bindings: media: Convert Allwinner hardware codec to a schema The Allwinner SoCs have a hardware video codec that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../media/allwinner,sun4i-a10-video-engine.yaml | 83 ++++++++++++++++++++++ Documentation/devicetree/bindings/media/cedrus.txt | 57 --------------- 2 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml delete mode 100644 Documentation/devicetree/bindings/media/cedrus.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml new file mode 100644 index 000000000000..526593c8c614 --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/allwinner,sun4i-a10-video-engine.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Video Engine Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + compatible: + enum: + - allwinner,sun4i-a10-video-engine + - allwinner,sun5i-a13-video-engine + - allwinner,sun7i-a20-video-engine + - allwinner,sun8i-a33-video-engine + - allwinner,sun8i-h3-video-engine + - allwinner,sun50i-a64-video-engine + - allwinner,sun50i-h5-video-engine + - allwinner,sun50i-h6-video-engine + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + - description: RAM Clock + + clock-names: + items: + - const: ahb + - const: mod + - const: ram + + resets: + maxItems: 1 + + allwinner,sram: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: Phandle to the device SRAM + + memory-region: + description: + CMA pool to use for buffers allocation instead of the default + CMA pool. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + - allwinner,sram + +additionalProperties: false + +examples: + - | + #include + #include + #include + + video-codec@1c0e000 { + compatible = "allwinner,sun7i-a20-video-engine"; + reg = <0x01c0e000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>, + <&ccu CLK_DRAM_VE>; + clock-names = "ahb", "mod", "ram"; + resets = <&ccu RST_VE>; + allwinner,sram = <&ve_sram 1>; + }; + +... diff --git a/Documentation/devicetree/bindings/media/cedrus.txt b/Documentation/devicetree/bindings/media/cedrus.txt deleted file mode 100644 index 20c82fb0c343..000000000000 --- a/Documentation/devicetree/bindings/media/cedrus.txt +++ /dev/null @@ -1,57 +0,0 @@ -Device-tree bindings for the VPU found in Allwinner SoCs, referred to as the -Video Engine (VE) in Allwinner literature. - -The VPU can only access the first 256 MiB of DRAM, that are DMA-mapped starting -from the DRAM base. This requires specific memory allocation and handling. - -Required properties: -- compatible : must be one of the following compatibles: - - "allwinner,sun4i-a10-video-engine" - - "allwinner,sun5i-a13-video-engine" - - "allwinner,sun7i-a20-video-engine" - - "allwinner,sun8i-a33-video-engine" - - "allwinner,sun8i-h3-video-engine" - - "allwinner,sun50i-a64-video-engine" - - "allwinner,sun50i-h5-video-engine" - - "allwinner,sun50i-h6-video-engine" -- reg : register base and length of VE; -- clocks : list of clock specifiers, corresponding to entries in - the clock-names property; -- clock-names : should contain "ahb", "mod" and "ram" entries; -- resets : phandle for reset; -- interrupts : VE interrupt number; -- allwinner,sram : SRAM region to use with the VE. - -Optional properties: -- memory-region : CMA pool to use for buffers allocation instead of the - default CMA pool. - -Example: - -reserved-memory { - #address-cells = <1>; - #size-cells = <1>; - ranges; - - /* Address must be kept in the lower 256 MiBs of DRAM for VE. */ - cma_pool: default-pool { - compatible = "shared-dma-pool"; - size = <0x6000000>; - alloc-ranges = <0x4a000000 0x6000000>; - reusable; - linux,cma-default; - }; -}; - -video-codec@1c0e000 { - compatible = "allwinner,sun7i-a20-video-engine"; - reg = <0x01c0e000 0x1000>; - - clocks = <&ccu CLK_AHB_VE>, <&ccu CLK_VE>, - <&ccu CLK_DRAM_VE>; - clock-names = "ahb", "mod", "ram"; - - resets = <&ccu RST_VE>; - interrupts = ; - allwinner,sram = <&ve_sram 1>; -}; -- cgit v1.2.3 From f78ed3c5bd3259c3841ae0b90740462371086487 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 13 Dec 2019 08:43:55 +0100 Subject: dt-bindings: media: Convert Allwinner A31 CSI to a schema The newer Allwinner SoCs have a camera controller that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../bindings/media/allwinner,sun6i-a31-csi.yaml | 115 +++++++++++++++++++++ .../devicetree/bindings/media/sun6i-csi.txt | 61 ----------- 2 files changed, 115 insertions(+), 61 deletions(-) create mode 100644 Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml delete mode 100644 Documentation/devicetree/bindings/media/sun6i-csi.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml new file mode 100644 index 000000000000..1fd9b5532a21 --- /dev/null +++ b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/allwinner,sun6i-a31-csi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 CMOS Sensor Interface (CSI) Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + compatible: + enum: + - allwinner,sun6i-a31-csi + - allwinner,sun8i-a83t-csi + - allwinner,sun8i-h3-csi + - allwinner,sun8i-v3s-csi + - allwinner,sun50i-a64-csi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Bus Clock + - description: Module Clock + - description: DRAM Clock + + clock-names: + items: + - const: bus + - const: mod + - const: ram + + resets: + maxItems: 1 + + # See ./video-interfaces.txt for details + port: + type: object + + properties: + endpoint: + type: object + + properties: + remote-endpoint: true + + bus-width: + enum: [ 8, 10, 12, 16 ] + + pclk-sample: true + hsync-active: true + vsync-active: true + + required: + - bus-width + - remote-endpoint + + required: + - endpoint + + additionalProperties: false + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + +additionalProperties: false + +examples: + - | + #include + #include + #include + + csi1: csi@1cb4000 { + compatible = "allwinner,sun8i-v3s-csi"; + reg = <0x01cb4000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_CSI>, + <&ccu CLK_CSI1_SCLK>, + <&ccu CLK_DRAM_CSI>; + clock-names = "bus", + "mod", + "ram"; + resets = <&ccu RST_BUS_CSI>; + + port { + /* Parallel bus endpoint */ + csi1_ep: endpoint { + remote-endpoint = <&adv7611_ep>; + bus-width = <16>; + + /* + * If hsync-active/vsync-active are missing, + * embedded BT.656 sync is used. + */ + hsync-active = <0>; /* Active low */ + vsync-active = <0>; /* Active low */ + pclk-sample = <1>; /* Rising */ + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/media/sun6i-csi.txt b/Documentation/devicetree/bindings/media/sun6i-csi.txt deleted file mode 100644 index a2e3e56f0257..000000000000 --- a/Documentation/devicetree/bindings/media/sun6i-csi.txt +++ /dev/null @@ -1,61 +0,0 @@ -Allwinner V3s Camera Sensor Interface -------------------------------------- - -Allwinner V3s SoC features a CSI module(CSI1) with parallel interface. - -Required properties: - - compatible: value must be one of: - * "allwinner,sun6i-a31-csi" - * "allwinner,sun8i-a83t-csi" - * "allwinner,sun8i-h3-csi" - * "allwinner,sun8i-v3s-csi" - * "allwinner,sun50i-a64-csi" - - reg: base address and size of the memory-mapped region. - - interrupts: interrupt associated to this IP - - clocks: phandles to the clocks feeding the CSI - * bus: the CSI interface clock - * mod: the CSI module clock - * ram: the CSI DRAM clock - - clock-names: the clock names mentioned above - - resets: phandles to the reset line driving the CSI - -The CSI node should contain one 'port' child node with one child 'endpoint' -node, according to the bindings defined in -Documentation/devicetree/bindings/media/video-interfaces.txt. - -Endpoint node properties for CSI ---------------------------------- -See the video-interfaces.txt for a detailed description of these properties. -- remote-endpoint : (required) a phandle to the bus receiver's endpoint - node -- bus-width: : (required) must be 8, 10, 12 or 16 -- pclk-sample : (optional) (default: sample on falling edge) -- hsync-active : (required; parallel-only) -- vsync-active : (required; parallel-only) - -Example: - -csi1: csi@1cb4000 { - compatible = "allwinner,sun8i-v3s-csi"; - reg = <0x01cb4000 0x1000>; - interrupts = ; - clocks = <&ccu CLK_BUS_CSI>, - <&ccu CLK_CSI1_SCLK>, - <&ccu CLK_DRAM_CSI>; - clock-names = "bus", "mod", "ram"; - resets = <&ccu RST_BUS_CSI>; - - port { - /* Parallel bus endpoint */ - csi1_ep: endpoint { - remote-endpoint = <&adv7611_ep>; - bus-width = <16>; - - /* If hsync-active/vsync-active are missing, - embedded BT.656 sync is used */ - hsync-active = <0>; /* Active low */ - vsync-active = <0>; /* Active low */ - pclk-sample = <1>; /* Rising */ - }; - }; -}; -- cgit v1.2.3 From 2609a1271d50847e7d5499d000097fc9b8802ffa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 13 Dec 2019 08:45:33 +0100 Subject: dt-bindings: interconnect: Convert Allwinner MBUS controller to a schema The older Allwinner SoCs have an MBUS controller that is used by Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../arm/sunxi/allwinner,sun4i-a10-mbus.yaml | 65 ++++++++++++++++++++++ .../devicetree/bindings/arm/sunxi/sunxi-mbus.txt | 37 ------------ 2 files changed, 65 insertions(+), 37 deletions(-) create mode 100644 Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml delete mode 100644 Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml b/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml new file mode 100644 index 000000000000..9370e64992dd --- /dev/null +++ b/Documentation/devicetree/bindings/arm/sunxi/allwinner,sun4i-a10-mbus.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/sunxi/allwinner,sun4i-a10-mbus.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner Memory Bus (MBUS) controller + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +description: | + The MBUS controller drives the MBUS that other devices in the SoC + will use to perform DMA. It also has a register interface that + allows to monitor and control the bandwidth and priorities for + masters on that bus. + + Each device having to perform their DMA through the MBUS must have + the interconnects and interconnect-names properties set to the MBUS + controller and with "dma-mem" as the interconnect name. + +properties: + "#interconnect-cells": + const: 1 + description: + The content of the cell is the MBUS ID. + + compatible: + enum: + - allwinner,sun5i-a13-mbus + - allwinner,sun8i-h3-mbus + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + dma-ranges: + description: + See section 2.3.9 of the DeviceTree Specification. + +required: + - "#interconnect-cells" + - compatible + - reg + - clocks + - dma-ranges + +additionalProperties: false + +examples: + - | + #include + + mbus: dram-controller@1c01000 { + compatible = "allwinner,sun5i-a13-mbus"; + reg = <0x01c01000 0x1000>; + clocks = <&ccu CLK_MBUS>; + dma-ranges = <0x00000000 0x40000000 0x20000000>; + #interconnect-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt b/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt deleted file mode 100644 index 2005bb486705..000000000000 --- a/Documentation/devicetree/bindings/arm/sunxi/sunxi-mbus.txt +++ /dev/null @@ -1,37 +0,0 @@ -Allwinner Memory Bus (MBUS) controller - -The MBUS controller drives the MBUS that other devices in the SoC will -use to perform DMA. It also has a register interface that allows to -monitor and control the bandwidth and priorities for masters on that -bus. - -Required properties: - - compatible: Must be one of: - - allwinner,sun5i-a13-mbus - - allwinner,sun8i-h3-mbus - - reg: Offset and length of the register set for the controller - - clocks: phandle to the clock driving the controller - - dma-ranges: See section 2.3.9 of the DeviceTree Specification - - #interconnect-cells: Must be one, with the argument being the MBUS - port ID - -Each device having to perform their DMA through the MBUS must have the -interconnects and interconnect-names properties set to the MBUS -controller and with "dma-mem" as the interconnect name. - -Example: - -mbus: dram-controller@1c01000 { - compatible = "allwinner,sun5i-a13-mbus"; - reg = <0x01c01000 0x1000>; - clocks = <&ccu CLK_MBUS>; - dma-ranges = <0x00000000 0x40000000 0x20000000>; - #interconnect-cells = <1>; -}; - -fe0: display-frontend@1e00000 { - compatible = "allwinner,sun5i-a13-display-frontend"; - ... - interconnects = <&mbus 19>; - interconnect-names = "dma-mem"; -}; -- cgit v1.2.3 From fe96df93f86c9006f9c76d53779445dffa4f3b2d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 13 Dec 2019 08:49:38 +0100 Subject: dt-bindings: ata: Convert Allwinner AHCI controller to a schema The Allwinner SoCs have a AHCI controllers that is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard [robh: 'maxItems: 1' for resets] Signed-off-by: Rob Herring --- .../devicetree/bindings/ata/ahci-platform.txt | 12 ---- .../bindings/ata/allwinner,sun4i-a10-ahci.yaml | 47 +++++++++++++++ .../bindings/ata/allwinner,sun8i-r40-ahci.yaml | 67 ++++++++++++++++++++++ 3 files changed, 114 insertions(+), 12 deletions(-) create mode 100644 Documentation/devicetree/bindings/ata/allwinner,sun4i-a10-ahci.yaml create mode 100644 Documentation/devicetree/bindings/ata/allwinner,sun8i-r40-ahci.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt index 55c6fab1b373..77091a277642 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.txt +++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt @@ -9,8 +9,6 @@ PHYs. Required properties: - compatible : compatible string, one of: - - "allwinner,sun4i-a10-ahci" - - "allwinner,sun8i-r40-ahci" - "brcm,iproc-ahci" - "hisilicon,hisi-ahci" - "cavium,octeon-7130-ahci" @@ -45,8 +43,6 @@ Required properties when using sub-nodes: - #address-cells : number of cells to encode an address - #size-cells : number of cells representing the size of an address -For allwinner,sun8i-r40-ahci, the reset property must be present. - Sub-nodes required properties: - reg : the port number And at least one of the following properties: @@ -60,14 +56,6 @@ Examples: interrupts = <115>; }; - ahci: sata@1c18000 { - compatible = "allwinner,sun4i-a10-ahci"; - reg = <0x01c18000 0x1000>; - interrupts = <56>; - clocks = <&pll6 0>, <&ahb_gates 25>; - target-supply = <®_ahci_5v>; - }; - With sub-nodes: sata@f7e90000 { compatible = "marvell,berlin2q-achi", "generic-ahci"; diff --git a/Documentation/devicetree/bindings/ata/allwinner,sun4i-a10-ahci.yaml b/Documentation/devicetree/bindings/ata/allwinner,sun4i-a10-ahci.yaml new file mode 100644 index 000000000000..cb530b46beff --- /dev/null +++ b/Documentation/devicetree/bindings/ata/allwinner,sun4i-a10-ahci.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ata/allwinner,sun4i-a10-ahci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 AHCI SATA Controller bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + compatible: + const: allwinner,sun4i-a10-ahci + + reg: + maxItems: 1 + + clocks: + items: + - description: AHCI Bus Clock + - description: AHCI Module Clock + + interrupts: + maxItems: 1 + + target-supply: + description: Regulator for SATA target power + +required: + - compatible + - reg + - clocks + - interrupts + +additionalProperties: false + +examples: + - | + ahci: sata@1c18000 { + compatible = "allwinner,sun4i-a10-ahci"; + reg = <0x01c18000 0x1000>; + interrupts = <56>; + clocks = <&pll6 0>, <&ahb_gates 25>; + target-supply = <®_ahci_5v>; + }; diff --git a/Documentation/devicetree/bindings/ata/allwinner,sun8i-r40-ahci.yaml b/Documentation/devicetree/bindings/ata/allwinner,sun8i-r40-ahci.yaml new file mode 100644 index 000000000000..e6b42a113ff1 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/allwinner,sun8i-r40-ahci.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ata/allwinner,sun8i-r40-ahci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner R40 AHCI SATA Controller bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + compatible: + const: allwinner,sun8i-r40-ahci + + reg: + maxItems: 1 + + clocks: + items: + - description: AHCI Bus Clock + - description: AHCI Module Clock + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + reset-names: + const: ahci + + ahci-supply: + description: Regulator for the AHCI controller + + phy-supply: + description: Regulator for the SATA PHY power + +required: + - compatible + - reg + - clocks + - interrupts + - resets + - reset-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + ahci: sata@1c18000 { + compatible = "allwinner,sun8i-r40-ahci"; + reg = <0x01c18000 0x1000>; + interrupts = ; + clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>; + resets = <&ccu RST_BUS_SATA>; + reset-names = "ahci"; + ahci-supply = <®_dldo4>; + phy-supply = <®_eldo3>; + }; + +... -- cgit v1.2.3 From d8c1bdb5288da433e1dc486f5e847e24a48d632b Mon Sep 17 00:00:00 2001 From: Peng Ma Date: Thu, 12 Dec 2019 03:38:19 +0000 Subject: dt-bindings: dma: fsl-edma: add new fsl,fsl,ls1028a-edma QORIQ LS1028A soc used fsl,vf610-edma, but it has a little bit different from others, so add new compatible to distinguish them. Signed-off-by: Peng Ma Link: https://lore.kernel.org/r/20191212033714.4090-3-peng.ma@nxp.com Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/fsl-edma.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/dma/fsl-edma.txt b/Documentation/devicetree/bindings/dma/fsl-edma.txt index 29dd3ccb1235..e77b08ebcd06 100644 --- a/Documentation/devicetree/bindings/dma/fsl-edma.txt +++ b/Documentation/devicetree/bindings/dma/fsl-edma.txt @@ -10,6 +10,7 @@ Required properties: - compatible : - "fsl,vf610-edma" for eDMA used similar to that on Vybrid vf610 SoC - "fsl,imx7ulp-edma" for eDMA2 used similar to that on i.mx7ulp + - "fsl,fsl,ls1028a-edma" for eDMA used similar to that on Vybrid vf610 SoC - reg : Specifies base physical address(s) and size of the eDMA registers. The 1st region is eDMA control register's address and size. The 2nd and the 3rd regions are programmable channel multiplexing -- cgit v1.2.3 From 790a19f18a70bf1e30b6b4d00559e1bb8a3f7e23 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Sat, 14 Dec 2019 23:02:44 +0100 Subject: rtc: Document RTC_VL_READ and RTC_VL_CLR ioctls RTC_VL_READ and RTC_VL_CLR have been introduced in 2012 with commit 0f20b767e20a ("drivers/rtc/rtc-pcf8563.c: add RTC_VL_READ/RTC_VL_CLR ioctl feature") Document them now that they have been unified. Link: https://lore.kernel.org/r/20191214220259.621996-3-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni --- Documentation/ABI/testing/rtc-cdev | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/rtc-cdev b/Documentation/ABI/testing/rtc-cdev index 97447283f13b..25910c3c3d7e 100644 --- a/Documentation/ABI/testing/rtc-cdev +++ b/Documentation/ABI/testing/rtc-cdev @@ -33,6 +33,14 @@ Description: Requires a separate RTC_PIE_ON call to enable the periodic interrupts. + * RTC_VL_READ: Read the voltage inputs status of the RTC when + supported. The value is a bit field of RTC_VL_*, giving the + status of the main and backup voltages. + + * RTC_VL_CLEAR: Clear the voltage status of the RTC. Some RTCs + need user interaction when the backup power provider is + replaced or charged to be able to clear the status. + The ioctl() calls supported by the older /dev/rtc interface are also supported by the newer RTC class framework. However, because the chips and systems are not standardized, some PC/AT -- cgit v1.2.3 From a7738c08cf269461da69f81db42279b57c68b2bb Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:20 +0000 Subject: dt-bindings: display: bridge: Convert lvds-transmitter binding to json-schema Convert the lvds-transmitter binding to DT schema format using json-schema. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-2-git-send-email-fabrizio.castro@bp.renesas.com --- .../bindings/display/bridge/lvds-transmitter.txt | 66 ---------------- .../bindings/display/bridge/lvds-transmitter.yaml | 91 ++++++++++++++++++++++ 2 files changed, 91 insertions(+), 66 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt deleted file mode 100644 index 60091db5dfa5..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.txt +++ /dev/null @@ -1,66 +0,0 @@ -Parallel to LVDS Encoder ------------------------- - -This binding supports the parallel to LVDS encoders that don't require any -configuration. - -LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple -incompatible data link layers have been used over time to transmit image data -to LVDS panels. This binding targets devices compatible with the following -specifications only. - -[JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February -1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) -[LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National -Semiconductor -[VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video -Electronics Standards Association (VESA) - -Those devices have been marketed under the FPD-Link and FlatLink brand names -among others. - - -Required properties: - -- compatible: Must be "lvds-encoder" - - Any encoder compatible with this generic binding, but with additional - properties not listed here, must list a device specific compatible first - followed by this generic compatible. - -Required nodes: - -This device has two video ports. Their connections are modeled using the OF -graph bindings specified in Documentation/devicetree/bindings/graph.txt. - -- Video port 0 for parallel input -- Video port 1 for LVDS output - - -Example -------- - -lvds-encoder { - compatible = "lvds-encoder"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint { - remote-endpoint = <&display_out_rgb>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint { - remote-endpoint = <&lvds_panel_in>; - }; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml new file mode 100644 index 000000000000..b5dd0da71394 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/lvds-transmitter.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Parallel to LVDS Encoder + +maintainers: + - Laurent Pinchart + +description: | + This binding supports the parallel to LVDS encoders that don't require any + configuration. + + LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple + incompatible data link layers have been used over time to transmit image data + to LVDS panels. This binding targets devices compatible with the following + specifications only. + + [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February + 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) + [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National + Semiconductor + [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video + Electronics Standards Association (VESA) + + Those devices have been marketed under the FPD-Link and FlatLink brand names + among others. + +properties: + compatible: + description: | + Any encoder compatible with this generic binding, but with additional + properties not listed here, must define its own binding and list a device + specific compatible first followed by the generic compatible. + enum: + - lvds-encoder + + ports: + type: object + description: | + This device has two video ports. Their connections are modeled using the + OF graph bindings specified in Documentation/devicetree/bindings/graph.txt + properties: + port@0: + type: object + description: | + Port 0 is for parallel input + + port@1: + type: object + description: | + Port 1 is for LVDS output + + required: + - port@0 + - port@1 + +required: + - compatible + - ports + +examples: + - | + lvds-encoder { + compatible = "lvds-encoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lvds_enc_in: endpoint { + remote-endpoint = <&display_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + + lvds_enc_out: endpoint { + remote-endpoint = <&lvds_panel_in>; + }; + }; + }; + }; + +... -- cgit v1.2.3 From 9acfa9d30ad71a64049b1f1b61c7f937e12531df Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:21 +0000 Subject: dt-bindings: display: bridge: lvds-transmitter: Document powerdown-gpios Add documentation for property powerdown-gpios. The property is optional. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-3-git-send-email-fabrizio.castro@bp.renesas.com --- .../devicetree/bindings/display/bridge/lvds-transmitter.yaml | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml index b5dd0da71394..2484737233f6 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -57,6 +57,11 @@ properties: - port@0 - port@1 + powerdown-gpios: + description: + The GPIO used to control the power down line of this device. + maxItems: 1 + required: - compatible - ports -- cgit v1.2.3 From 5240272d4323c20265329a6b85b799bddf9827df Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:22 +0000 Subject: dt-bindings: display: bridge: lvds-transmitter: Absorb ti, ds90c185.txt ti,ds90c185.txt documents LVDS encoders using the same driver as the one documented by lvds-transmitter.yaml. Since the properties listed in ti,ds90c185.txt are the same as the ones listed in lvds-transmitter.yaml, absorb the dt-binding into lvds-transmitter.yaml. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-4-git-send-email-fabrizio.castro@bp.renesas.com --- .../bindings/display/bridge/lvds-transmitter.yaml | 14 +++--- .../bindings/display/bridge/ti,ds90c185.txt | 55 ---------------------- 2 files changed, 8 insertions(+), 61 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml index 2484737233f6..a8326ceec9fd 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -31,11 +31,13 @@ description: | properties: compatible: description: | - Any encoder compatible with this generic binding, but with additional - properties not listed here, must define its own binding and list a device - specific compatible first followed by the generic compatible. - enum: - - lvds-encoder + Must list the device specific compatible string first, followed by the + generic compatible string. + items: + - enum: + - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer + - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer + - const: lvds-encoder # Generic LVDS encoder compatible fallback ports: type: object @@ -69,7 +71,7 @@ required: examples: - | lvds-encoder { - compatible = "lvds-encoder"; + compatible = "ti,ds90c185", "lvds-encoder"; ports { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt b/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt deleted file mode 100644 index e575f996959a..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/ti,ds90c185.txt +++ /dev/null @@ -1,55 +0,0 @@ -Texas Instruments FPD-Link (LVDS) Serializer --------------------------------------------- - -The DS90C185 and DS90C187 are low-power serializers for portable -battery-powered applications that reduces the size of the RGB -interface between the host GPU and the display. - -Required properties: - -- compatible: Should be - "ti,ds90c185", "lvds-encoder" for the TI DS90C185 FPD-Link Serializer - "ti,ds90c187", "lvds-encoder" for the TI DS90C187 FPD-Link Serializer - -Optional properties: - -- powerdown-gpios: Power down control GPIO (the PDB pin, active-low) - -Required nodes: - -The devices have two video ports. Their connections are modeled using the OF -graph bindings specified in Documentation/devicetree/bindings/graph.txt. - -- Video port 0 for parallel input -- Video port 1 for LVDS output - - -Example -------- - -lvds-encoder { - compatible = "ti,ds90c185", "lvds-encoder"; - - powerdown-gpios = <&gpio 17 GPIO_ACTIVE_LOW>; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint { - remote-endpoint = <&lcdc_out_rgb>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint { - remote-endpoint = <&lvds_panel_in>; - }; - }; - }; -}; -- cgit v1.2.3 From 4788f4e11d1d3dc304b119b993d3ce39a5fd22c3 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:23 +0000 Subject: dt-bindings: display: bridge: lvds-transmitter: Document "ti, sn75lvds83" Compatible string "ti,sn75lvds83" is being used by device tree rk3188-bqedison2qc.dts, but it's not documented anywhere, therefore document it within lvds-transmitter.yaml. Signed-off-by: Fabrizio Castro Acked-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-5-git-send-email-fabrizio.castro@bp.renesas.com --- Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml index a8326ceec9fd..27de616a1973 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml @@ -37,6 +37,7 @@ properties: - enum: - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer + - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter - const: lvds-encoder # Generic LVDS encoder compatible fallback ports: -- cgit v1.2.3 From e156c6176c9d6e69e166fb20e3b4e9f85ead8d77 Mon Sep 17 00:00:00 2001 From: Enrico Weigelt Date: Tue, 3 Dec 2019 12:33:14 +0100 Subject: Documentation/x86/boot: Fix typo s/Fileds/Fields/g Signed-off-by: Enrico Weigelt, metux IT consult Signed-off-by: Borislav Petkov Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Cc: Thomas Gleixner Cc: x86-ml Link: https://lkml.kernel.org/r/20191203113314.26810-1-info@metux.net --- Documentation/x86/boot.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/x86/boot.rst b/Documentation/x86/boot.rst index 90bb8f5ab384..692ce57ac140 100644 --- a/Documentation/x86/boot.rst +++ b/Documentation/x86/boot.rst @@ -251,7 +251,7 @@ setting fields in the header, you must make sure only to set fields supported by the protocol version in use. -Details of Harder Fileds +Details of Header Fields ======================== For each field, some are information from the kernel to the bootloader -- cgit v1.2.3 From 575af8ecd1943d432ede9891e1419d001fa67c5d Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:27 +0000 Subject: dt-bindings: display: bridge: Repurpose lvds-encoder In an effort to repurpose lvds-encoder.c to also serve the function of LVDS decoders, we ended up defining a new "generic" compatible string ("lvds-decoder"), therefore adapt the dt schema to allow for the new compatible string. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart [narmstrong: fixed port descriptions as acked with lpinchart] Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-9-git-send-email-fabrizio.castro@bp.renesas.com --- .../bindings/display/bridge/lvds-codec.yaml | 129 +++++++++++++++++++++ .../bindings/display/bridge/lvds-transmitter.yaml | 99 ---------------- 2 files changed, 129 insertions(+), 99 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml delete mode 100644 Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml new file mode 100644 index 000000000000..f714fbd2814d --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -0,0 +1,129 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/lvds-codec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Transparent LVDS encoders and decoders + +maintainers: + - Laurent Pinchart + +description: | + This binding supports transparent LVDS encoders and decoders that don't + require any configuration. + + LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple + incompatible data link layers have been used over time to transmit image data + to LVDS panels. This binding targets devices compatible with the following + specifications only. + + [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February + 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) + [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National + Semiconductor + [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video + Electronics Standards Association (VESA) + + Those devices have been marketed under the FPD-Link and FlatLink brand names + among others. + +properties: + compatible: + description: | + Must list the device specific compatible string first, followed by the + generic compatible string. + oneOf: + - items: + - enum: + - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer + - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer + - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter + - const: lvds-encoder # Generic LVDS encoder compatible fallback + - const: lvds-decoder # Generic LVDS decoders compatible fallback + + ports: + type: object + description: | + This device has two video ports. Their connections are modeled using the + OF graph bindings specified in Documentation/devicetree/bindings/graph.txt + properties: + port@0: + type: object + description: | + For LVDS encoders, port 0 is the parallel input + For LVDS decoders, port 0 is the LVDS input + + port@1: + type: object + description: | + For LVDS encoders, port 1 is the LVDS output + For LVDS decoders, port 1 is the parallel output + + required: + - port@0 + - port@1 + + powerdown-gpios: + description: + The GPIO used to control the power down line of this device. + maxItems: 1 + +required: + - compatible + - ports + +examples: + - | + lvds-encoder { + compatible = "ti,ds90c185", "lvds-encoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lvds_enc_in: endpoint { + remote-endpoint = <&display_out_rgb>; + }; + }; + + port@1 { + reg = <1>; + + lvds_enc_out: endpoint { + remote-endpoint = <&lvds_panel_in>; + }; + }; + }; + }; + + - | + lvds-decoder { + compatible = "lvds-decoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lvds_dec_in: endpoint { + remote-endpoint = <&display_out_lvds>; + }; + }; + + port@1 { + reg = <1>; + + lvds_dec_out: endpoint { + remote-endpoint = <&rgb_panel_in>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml deleted file mode 100644 index 27de616a1973..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/lvds-transmitter.yaml +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/display/bridge/lvds-transmitter.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Parallel to LVDS Encoder - -maintainers: - - Laurent Pinchart - -description: | - This binding supports the parallel to LVDS encoders that don't require any - configuration. - - LVDS is a physical layer specification defined in ANSI/TIA/EIA-644-A. Multiple - incompatible data link layers have been used over time to transmit image data - to LVDS panels. This binding targets devices compatible with the following - specifications only. - - [JEIDA] "Digital Interface Standards for Monitor", JEIDA-59-1999, February - 1999 (Version 1.0), Japan Electronic Industry Development Association (JEIDA) - [LDI] "Open LVDS Display Interface", May 1999 (Version 0.95), National - Semiconductor - [VESA] "VESA Notebook Panel Standard", October 2007 (Version 1.0), Video - Electronics Standards Association (VESA) - - Those devices have been marketed under the FPD-Link and FlatLink brand names - among others. - -properties: - compatible: - description: | - Must list the device specific compatible string first, followed by the - generic compatible string. - items: - - enum: - - ti,ds90c185 # For the TI DS90C185 FPD-Link Serializer - - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer - - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter - - const: lvds-encoder # Generic LVDS encoder compatible fallback - - ports: - type: object - description: | - This device has two video ports. Their connections are modeled using the - OF graph bindings specified in Documentation/devicetree/bindings/graph.txt - properties: - port@0: - type: object - description: | - Port 0 is for parallel input - - port@1: - type: object - description: | - Port 1 is for LVDS output - - required: - - port@0 - - port@1 - - powerdown-gpios: - description: - The GPIO used to control the power down line of this device. - maxItems: 1 - -required: - - compatible - - ports - -examples: - - | - lvds-encoder { - compatible = "ti,ds90c185", "lvds-encoder"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint { - remote-endpoint = <&display_out_rgb>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint { - remote-endpoint = <&lvds_panel_in>; - }; - }; - }; - }; - -... -- cgit v1.2.3 From b7de4ba7dbe962d38768e0396f7acd11eff7628b Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:28 +0000 Subject: dt-bindings: display: bridge: lvds-codec: Document ti, ds90cf384a The DS90CF384A from TI is a transparent LVDS receiver (decoder), and therefore it is compatible with the lvds-codec driver and bindings. Document the ti,ds90cf384a compatible string with the dt-bindings. No driver change required. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1573660292-10629-10-git-send-email-fabrizio.castro@bp.renesas.com --- Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index f714fbd2814d..9f27d4d91a10 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -40,7 +40,10 @@ properties: - ti,ds90c187 # For the TI DS90C187 FPD-Link Serializer - ti,sn75lvds83 # For the TI SN75LVDS83 FlatLink transmitter - const: lvds-encoder # Generic LVDS encoder compatible fallback - - const: lvds-decoder # Generic LVDS decoders compatible fallback + - items: + - enum: + - ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver + - const: lvds-decoder # Generic LVDS decoders compatible fallback ports: type: object @@ -102,7 +105,7 @@ examples: - | lvds-decoder { - compatible = "lvds-decoder"; + compatible = "ti,ds90cf384a", "lvds-decoder"; ports { #address-cells = <1>; -- cgit v1.2.3 From cad8c44a9ff0da507f1e225e0ad342d69dbbc4cd Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Wed, 13 Nov 2019 15:51:32 +0000 Subject: dt-bindings: display: bridge: lvds-codec: Absorb thine, thc63lvdm83d.txt At this point in time, compatible string "thine,thc63lvdm83d" is backed by the lvds-codec driver, and the documentation contained in thine,thc63lvdm83d.txt is basically the same as the one contained in lvds-codec.yaml (generic fallback compatible string aside), therefore absorb thine,thc63lvdm83d.txt. Signed-off-by: Fabrizio Castro Reviewed-by: Rob Herring Reviewed-by: Laurent Pinchart Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/ <1573660292-10629-14-git-send-email-fabrizio.castro@bp.renesas.com --- .../bindings/display/bridge/lvds-codec.yaml | 5 +-- .../bindings/display/bridge/thine,thc63lvdm83d.txt | 50 ---------------------- 2 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml index 9f27d4d91a10..8f373029f5d2 100644 --- a/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml +++ b/Documentation/devicetree/bindings/display/bridge/lvds-codec.yaml @@ -30,9 +30,6 @@ description: | properties: compatible: - description: | - Must list the device specific compatible string first, followed by the - generic compatible string. oneOf: - items: - enum: @@ -44,6 +41,8 @@ properties: - enum: - ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver - const: lvds-decoder # Generic LVDS decoders compatible fallback + - enum: + - thine,thc63lvdm83d # For the THC63LVDM83D LVDS serializer ports: type: object diff --git a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt b/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt deleted file mode 100644 index fee3c88e1a17..000000000000 --- a/Documentation/devicetree/bindings/display/bridge/thine,thc63lvdm83d.txt +++ /dev/null @@ -1,50 +0,0 @@ -THine Electronics THC63LVDM83D LVDS serializer ----------------------------------------------- - -The THC63LVDM83D is an LVDS serializer designed to support pixel data -transmission between a host and a flat panel. - -Required properties: - -- compatible: Should be "thine,thc63lvdm83d" - -Optional properties: - -- powerdown-gpios: Power down control GPIO (the /PWDN pin, active low). - -Required nodes: - -The THC63LVDM83D has two video ports. Their connections are modeled using the -OFgraph bindings specified in Documentation/devicetree/bindings/graph.txt. - -- Video port 0 for CMOS/TTL input -- Video port 1 for LVDS output - - -Example -------- - - lvds_enc: encoder@0 { - compatible = "thine,thc63lvdm83d"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - lvds_enc_in: endpoint@0 { - remote-endpoint = <&rgb_out>; - }; - }; - - port@1 { - reg = <1>; - - lvds_enc_out: endpoint@0 { - remote-endpoint = <&panel_in>; - }; - }; - }; - }; -- cgit v1.2.3 From ea81896dc98f324ff3fb9b1e74b4915a1beb3296 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 17 Dec 2019 15:33:45 +0300 Subject: thunderbolt: Update documentation with the USB4 information Update user's and administrator's guide to mention USB4, how it relates to Thunderbolt and and how it is supported in Linux. While there add the missing SPDX identifier to the document. Signed-off-by: Mika Westerberg Link: https://lore.kernel.org/r/20191217123345.31850-10-mika.westerberg@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/admin-guide/thunderbolt.rst | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/admin-guide/thunderbolt.rst b/Documentation/admin-guide/thunderbolt.rst index 898ad78f3cc7..10c4f0ce2ad0 100644 --- a/Documentation/admin-guide/thunderbolt.rst +++ b/Documentation/admin-guide/thunderbolt.rst @@ -1,6 +1,28 @@ -============= - Thunderbolt -============= +.. SPDX-License-Identifier: GPL-2.0 + +====================== + USB4 and Thunderbolt +====================== +USB4 is the public specification based on Thunderbolt 3 protocol with +some differences at the register level among other things. Connection +manager is an entity running on the host router (host controller) +responsible for enumerating routers and establishing tunnels. A +connection manager can be implemented either in firmware or software. +Typically PCs come with a firmware connection manager for Thunderbolt 3 +and early USB4 capable systems. Apple systems on the other hand use +software connection manager and the later USB4 compliant devices follow +the suit. + +The Linux Thunderbolt driver supports both and can detect at runtime which +connection manager implementation is to be used. To be on the safe side the +software connection manager in Linux also advertises security level +``user`` which means PCIe tunneling is disabled by default. The +documentation below applies to both implementations with the exception that +the software connection manager only supports ``user`` security level and +is expected to be accompanied with an IOMMU based DMA protection. + +Security levels and how to use them +----------------------------------- The interface presented here is not meant for end users. Instead there should be a userspace tool that handles all the low-level details, keeps a database of the authorized devices and prompts users for new connections. @@ -18,8 +40,6 @@ This will authorize all devices automatically when they appear. However, keep in mind that this bypasses the security levels and makes the system vulnerable to DMA attacks. -Security levels and how to use them ------------------------------------ Starting with Intel Falcon Ridge Thunderbolt controller there are 4 security levels available. Intel Titan Ridge added one more security level (usbonly). The reason for these is the fact that the connected devices can -- cgit v1.2.3 From fb522dbb4531c14193115a09905c6c31b37dbfc5 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 18 Dec 2019 18:24:18 +0100 Subject: ASoC: meson: axg-fifo: add fifo depth to the bindings documentation Add a new property with the depth of the fifo in bytes. This is useful since some instance of the fifo, even on the same SoC, may have different depth. The depth is useful is set some parameters of the fifo. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20191218172420.1199117-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt index 3080979350a0..fa4545ed81ca 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt @@ -17,6 +17,9 @@ Required properties: * "arb" : memory ARB line (required) * "rst" : dedicated device reset line (optional) - #sound-dai-cells: must be 0. +- amlogic,fifo-depth: The size of the controller's fifo in bytes. This + is useful for determining certain configuration such + as the flush threshold of the fifo Example of FRDDR A on the A113 SoC: @@ -27,4 +30,5 @@ frddr_a: audio-controller@1c0 { interrupts = ; clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; resets = <&arb AXG_ARB_FRDDR_A>; + fifo-depth = <512>; }; -- cgit v1.2.3 From ef32b63bf13e531479a3b1ef6eb2daaf4fcf787a Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Tue, 17 Dec 2019 10:07:15 +0100 Subject: dt-bindings: spi: Convert stm32 spi bindings to json-schema Convert the STM32 spi binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard CC: Erwan Leray CC: Fabrice Gasnier CC: Amelie Delaunay Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191217090715.13334-1-benjamin.gaignard@st.com Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-stm32.txt | 62 ------------ .../devicetree/bindings/spi/st,stm32-spi.yaml | 105 +++++++++++++++++++++ 2 files changed, 105 insertions(+), 62 deletions(-) delete mode 100644 Documentation/devicetree/bindings/spi/spi-stm32.txt create mode 100644 Documentation/devicetree/bindings/spi/st,stm32-spi.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/spi/spi-stm32.txt b/Documentation/devicetree/bindings/spi/spi-stm32.txt deleted file mode 100644 index d82755c63eaf..000000000000 --- a/Documentation/devicetree/bindings/spi/spi-stm32.txt +++ /dev/null @@ -1,62 +0,0 @@ -STMicroelectronics STM32 SPI Controller - -The STM32 SPI controller is used to communicate with external devices using -the Serial Peripheral Interface. It supports full-duplex, half-duplex and -simplex synchronous serial communication with external devices. It supports -from 4 to 32-bit data size. Although it can be configured as master or slave, -only master is supported by the driver. - -Required properties: -- compatible: Should be one of: - "st,stm32h7-spi" - "st,stm32f4-spi" -- reg: Offset and length of the device's register set. -- interrupts: Must contain the interrupt id. -- clocks: Must contain an entry for spiclk (which feeds the internal clock - generator). -- #address-cells: Number of cells required to define a chip select address. -- #size-cells: Should be zero. - -Optional properties: -- resets: Must contain the phandle to the reset controller. -- A pinctrl state named "default" may be defined to set pins in mode of - operation for SPI transfer. -- dmas: DMA specifiers for tx and rx dma. DMA fifo mode must be used. See the - STM32 DMA bindings, Documentation/devicetree/bindings/dma/stm32-dma.txt. -- dma-names: DMA request names should include "tx" and "rx" if present. -- cs-gpios: list of GPIO chip selects. See the SPI bus bindings, - Documentation/devicetree/bindings/spi/spi-bus.txt - - -Child nodes represent devices on the SPI bus - See ../spi/spi-bus.txt - -Optional properties: -- st,spi-midi-ns: Only for STM32H7, (Master Inter-Data Idleness) minimum time - delay in nanoseconds inserted between two consecutive data - frames. - - -Example: - spi2: spi@40003800 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "st,stm32h7-spi"; - reg = <0x40003800 0x400>; - interrupts = <36>; - clocks = <&rcc SPI2_CK>; - resets = <&rcc 1166>; - dmas = <&dmamux1 0 39 0x400 0x01>, - <&dmamux1 1 40 0x400 0x01>; - dma-names = "rx", "tx"; - pinctrl-0 = <&spi2_pins_b>; - pinctrl-names = "default"; - cs-gpios = <&gpioa 11 0>; - - aardvark@0 { - compatible = "totalphase,aardvark"; - reg = <0>; - spi-max-frequency = <4000000>; - st,spi-midi-ns = <4000>; - }; - }; diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml new file mode 100644 index 000000000000..f0d979664f07 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/st,stm32-spi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 SPI Controller bindings + +description: | + The STM32 SPI controller is used to communicate with external devices using + the Serial Peripheral Interface. It supports full-duplex, half-duplex and + simplex synchronous serial communication with external devices. It supports + from 4 to 32-bit data size. + +maintainers: + - Erwan Leray + - Fabrice Gasnier + +allOf: + - $ref: "spi-controller.yaml#" + - if: + properties: + compatible: + contains: + const: st,stm32f4-spi + + then: + properties: + st,spi-midi-ns: false + +properties: + compatible: + enum: + - st,stm32f4-spi + - st,stm32h7-spi + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + description: | + DMA specifiers for tx and rx dma. DMA fifo mode must be used. See + the STM32 DMA bindings Documentation/devicetree/bindings/dma/stm32-dma.txt. + items: + - description: rx DMA channel + - description: tx DMA channel + + dma-names: + items: + - const: rx + - const: tx + +patternProperties: + "^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-f]+$": + type: object + # SPI slave nodes must be children of the SPI master node and can + # contain the following properties. + properties: + st,spi-midi-ns: + description: | + Only for STM32H7, (Master Inter-Data Idleness) minimum time + delay in nanoseconds inserted between two consecutive data frames. + +required: + - compatible + - reg + - clocks + - interrupts + +examples: + - | + #include + #include + #include + spi@4000b000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x4000b000 0x400>; + interrupts = ; + clocks = <&rcc SPI2_K>; + resets = <&rcc SPI2_R>; + dmas = <&dmamux1 0 39 0x400 0x05>, + <&dmamux1 1 40 0x400 0x05>; + dma-names = "rx", "tx"; + cs-gpios = <&gpioa 11 0>; + + aardvark@0 { + compatible = "totalphase,aardvark"; + reg = <0>; + spi-max-frequency = <4000000>; + st,spi-midi-ns = <4000>; + }; + }; + +... -- cgit v1.2.3 From 47a34db3d5d2c04592f2b800b8ba39bcbf48e366 Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Sat, 14 Dec 2019 07:27:55 -0800 Subject: device-tree: bindings: max17042_battery: add all of the compatible strings The bindings are missing documentation for some of the compatible strings. Signed-off-by: Angus Ainslie (Purism) Reviewed-by: Krzysztof Kozlowski Acked-by: Rob Herring Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/power/supply/max17042_battery.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/supply/max17042_battery.txt b/Documentation/devicetree/bindings/power/supply/max17042_battery.txt index 3f3894aaeebc..f34c5daae9af 100644 --- a/Documentation/devicetree/bindings/power/supply/max17042_battery.txt +++ b/Documentation/devicetree/bindings/power/supply/max17042_battery.txt @@ -2,7 +2,11 @@ max17042_battery ~~~~~~~~~~~~~~~~ Required properties : - - compatible : "maxim,max17042" + - compatible : one of the following + * "maxim,max17042" + * "maxim,max17047" + * "maxim,max17050" + * "maxim,max17055" Optional properties : - maxim,rsns-microohm : Resistance of rsns resistor in micro Ohms -- cgit v1.2.3 From 9a056a879111f88149dad428e7cc4f85c87a62bc Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 9 Dec 2019 11:56:21 +0800 Subject: dt-bindings: power: Introduce one property to describe the battery resistance with temperature changes Since the battery internal resistance can be changed as the temperature changes, thus add one table to describe the battery resistance percent in different temperatures to get a accurate battery internal resistance. Reviewed-by: Rob Herring Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/power/supply/battery.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/supply/battery.txt b/Documentation/devicetree/bindings/power/supply/battery.txt index 5c913d4cf36c..3049cf88bdcf 100644 --- a/Documentation/devicetree/bindings/power/supply/battery.txt +++ b/Documentation/devicetree/bindings/power/supply/battery.txt @@ -35,6 +35,10 @@ Optional Properties: for each of the battery capacity lookup table. The first temperature value specifies the OCV table 0, and the second temperature value specifies the OCV table 1, and so on. + - resistance-temp-table: An array providing the temperature in degree Celsius + and corresponding battery internal resistance percent, which is used to look + up the resistance percent according to current temperature to get a accurate + batterty internal resistance in different temperatures. Battery properties are named, where possible, for the corresponding elements in enum power_supply_property, defined in @@ -61,6 +65,7 @@ Example: ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...; ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...; ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...; + resistance-temp-table = <20 100>, <10 90>, <0 80>, <(-10) 60>; }; charger: charger@11 { -- cgit v1.2.3 From 7772d22e4b0681b5d0ff1bf4127c1b35e7641d07 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Mon, 9 Dec 2019 11:56:24 +0800 Subject: dt-bindings: power: sc27xx: Add a new property to describe the real resistance of coulomb counter chip Add a new property to describe the real resistance of coulomb counter chip, which is used to calibrate the accuracy of the coulomb counter chip. Acked-by: Rob Herring Signed-off-by: Baolin Wang Signed-off-by: Baolin Wang Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt b/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt index 0a5705b8b592..b6359b590383 100644 --- a/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt +++ b/Documentation/devicetree/bindings/power/supply/sc27xx-fg.txt @@ -13,6 +13,8 @@ Required properties: - io-channel-names: Should be "bat-temp" or "charge-vol". - nvmem-cells: A phandle to the calibration cells provided by eFuse device. - nvmem-cell-names: Should be "fgu_calib". +- sprd,calib-resistance-micro-ohms: Specify the real resistance of coulomb counter + chip in micro Ohms. - monitored-battery: Phandle of battery characteristics devicetree node. See Documentation/devicetree/bindings/power/supply/battery.txt @@ -52,5 +54,6 @@ Example: nvmem-cells = <&fgu_calib>; nvmem-cell-names = "fgu_calib"; monitored-battery = <&bat>; + sprd,calib-resistance-micro-ohms = <21500>; }; }; -- cgit v1.2.3 From 7a8bac169a65e0fb7e5da8ef3277b4016b5d1ffe Mon Sep 17 00:00:00 2001 From: Matheus Castello Date: Thu, 5 Dec 2019 12:44:07 -0300 Subject: dt-bindings: power: supply: max17040: Add DT bindings for max17040 fuel gauge Documentation of max17040 based fuel gauge characteristics. For configure low level state of charge threshold alert signaled from max17043/max17044 we add "maxim,alert-low-soc-level" property. Signed-off-by: Matheus Castello Reviewed-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Signed-off-by: Sebastian Reichel --- .../bindings/power/supply/max17040_battery.txt | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/max17040_battery.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/supply/max17040_battery.txt b/Documentation/devicetree/bindings/power/supply/max17040_battery.txt new file mode 100644 index 000000000000..4e0186b8380f --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/max17040_battery.txt @@ -0,0 +1,33 @@ +max17040_battery +~~~~~~~~~~~~~~~~ + +Required properties : + - compatible : "maxim,max17040" or "maxim,max77836-battery" + - reg: i2c slave address + +Optional properties : +- maxim,alert-low-soc-level : The alert threshold that sets the state of + charge level (%) where an interrupt is + generated. Can be configured from 1 up to 32 + (%). If skipped the power up default value of + 4 (%) will be used. +- interrupts : Interrupt line see Documentation/devicetree/ + bindings/interrupt-controller/interrupts.txt +- wakeup-source : This device has wakeup capabilities. Use this + property to use alert low SOC level interrupt + as wake up source. + +Optional properties support interrupt functionality for alert low state of +charge level, present in some ICs in the same family, and should be used with +compatible "maxim,max77836-battery". + +Example: + + battery-fuel-gauge@36 { + compatible = "maxim,max77836-battery"; + reg = <0x36>; + maxim,alert-low-soc-level = <10>; + interrupt-parent = <&gpio7>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + wakeup-source; + }; -- cgit v1.2.3 From d109ea0970cfca28c4ab1c0d6295551434ca2a7a Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Tue, 17 Dec 2019 08:19:47 -0700 Subject: dt-bindings: clock: Document external clocks for MSM8998 gcc The global clock controller on MSM8998 can consume a number of external clocks. Document them. For 7180 and 8150, the hardware always exists, so no clocks are truly optional. Therefore, simplify the binding by removing the min/max qualifiers to clocks. Also, fixup an example so that dt_binding_check passes. Signed-off-by: Jeffrey Hugo Reviewed-by: Rob Herring Link: https://lkml.kernel.org/r/1576595987-10043-1-git-send-email-jhugo@codeaurora.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gcc.yaml | 73 +++++++++++++++++----- 1 file changed, 59 insertions(+), 14 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml index e73a56fb60ca..f2b5cd6fe0fe 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml @@ -40,20 +40,40 @@ properties: - qcom,gcc-sm8150 clocks: - minItems: 1 - maxItems: 3 - items: - - description: Board XO source - - description: Board active XO source - - description: Sleep clock source + oneOf: + #qcom,gcc-sm8150 + #qcom,gcc-sc7180 + - items: + - description: Board XO source + - description: Board active XO source + - description: Sleep clock source + #qcom,gcc-msm8998 + - items: + - description: Board XO source + - description: Sleep clock source + - description: USB 3.0 phy pipe clock + - description: UFS phy rx symbol clock for pipe 0 + - description: UFS phy rx symbol clock for pipe 1 + - description: UFS phy tx symbol clock + - description: PCIE phy pipe clock clock-names: - minItems: 1 - maxItems: 3 - items: - - const: bi_tcxo - - const: bi_tcxo_ao - - const: sleep_clk + oneOf: + #qcom,gcc-sm8150 + #qcom,gcc-sc7180 + - items: + - const: bi_tcxo + - const: bi_tcxo_ao + - const: sleep_clk + #qcom,gcc-msm8998 + - items: + - const: xo + - const: sleep_clk + - const: usb3_pipe + - const: ufs_rx_symbol0 + - const: ufs_rx_symbol1 + - const: ufs_tx_symbol0 + - const: pcie0_pipe '#clock-cells': const: 1 @@ -118,6 +138,7 @@ else: compatible: contains: enum: + - qcom,gcc-msm8998 - qcom,gcc-sm8150 - qcom,gcc-sc7180 then: @@ -179,10 +200,34 @@ examples: clock-controller@100000 { compatible = "qcom,gcc-sc7180"; reg = <0x100000 0x1f0000>; - clocks = <&rpmhcc 0>, <&rpmhcc 1>; - clock-names = "bi_tcxo", "bi_tcxo_ao"; + clocks = <&rpmhcc 0>, <&rpmhcc 1>, <0>; + clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + # Example of MSM8998 GCC: + - | + clock-controller@100000 { + compatible = "qcom,gcc-msm8998"; #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; + reg = <0x00100000 0xb0000>; + clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, + <&sleep>, + <0>, + <0>, + <0>, + <0>, + <0>; + clock-names = "xo", + "sleep", + "usb3_pipe", + "ufs_rx_symbol0", + "ufs_rx_symbol1", + "ufs_tx_symbol0", + "pcie0_pipe"; }; ... -- cgit v1.2.3 From 8218c2cb815543f21e4da5b8a8b4a2402d796767 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Tue, 17 Dec 2019 08:20:03 -0700 Subject: dt-bindings: clock: Convert qcom,mmcc to DT schema Convert the qcom,mmcc-X clock controller binding to DT schema. Add the protected-clocks property to the schema to show that is it explicitly allowed, instead of relying on the generic, pre-schema binding. Signed-off-by: Jeffrey Hugo Reviewed-by: Rob Herring Link: https://lkml.kernel.org/r/1576596003-10093-1-git-send-email-jhugo@codeaurora.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,mmcc.txt | 28 ---------- .../devicetree/bindings/clock/qcom,mmcc.yaml | 60 ++++++++++++++++++++++ 2 files changed, 60 insertions(+), 28 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt deleted file mode 100644 index 8b0f7841af8d..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt +++ /dev/null @@ -1,28 +0,0 @@ -Qualcomm Multimedia Clock & Reset Controller Binding ----------------------------------------------------- - -Required properties : -- compatible : shall contain only one of the following: - - "qcom,mmcc-apq8064" - "qcom,mmcc-apq8084" - "qcom,mmcc-msm8660" - "qcom,mmcc-msm8960" - "qcom,mmcc-msm8974" - "qcom,mmcc-msm8996" - -- reg : shall contain base register location and length -- #clock-cells : shall contain 1 -- #reset-cells : shall contain 1 - -Optional properties : -- #power-domain-cells : shall contain 1 - -Example: - clock-controller@4000000 { - compatible = "qcom,mmcc-msm8960"; - reg = <0x4000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml new file mode 100644 index 000000000000..78b1a227a355 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/qcom,mmcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Multimedia Clock & Reset Controller Binding + +maintainers: + - Jeffrey Hugo + - Taniya Das + +description: | + Qualcomm multimedia clock control module which supports the clocks, resets and + power domains. + +properties: + compatible : + enum: + - qcom,mmcc-apq8064 + - qcom,mmcc-apq8084 + - qcom,mmcc-msm8660 + - qcom,mmcc-msm8960 + - qcom,mmcc-msm8974 + - qcom,mmcc-msm8996 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + + protected-clocks: + description: + Protected clock specifier list as per common clock binding + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +examples: + # Example for MMCC for MSM8960: + - | + clock-controller@4000000 { + compatible = "qcom,mmcc-msm8960"; + reg = <0x4000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... -- cgit v1.2.3 From e6494bf65a0f11aa378ac0fededeb14076177654 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Tue, 17 Dec 2019 08:20:18 -0700 Subject: dt-bindings: clock: Add support for the MSM8998 mmcc Document the multimedia clock controller found on MSM8998. Signed-off-by: Jeffrey Hugo Reviewed-by: Rob Herring Link: https://lkml.kernel.org/r/1576596018-10140-1-git-send-email-jhugo@codeaurora.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,mmcc.yaml | 38 ++++ include/dt-bindings/clock/qcom,mmcc-msm8998.h | 210 +++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,mmcc-msm8998.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml index 78b1a227a355..91101c915904 100644 --- a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml @@ -23,6 +23,33 @@ properties: - qcom,mmcc-msm8960 - qcom,mmcc-msm8974 - qcom,mmcc-msm8996 + - qcom,mmcc-msm8998 + + clocks: + items: + - description: Board XO source + - description: Board sleep source + - description: Global PLL 0 clock + - description: DSI phy instance 0 dsi clock + - description: DSI phy instance 0 byte clock + - description: DSI phy instance 1 dsi clock + - description: DSI phy instance 1 byte clock + - description: HDMI phy PLL clock + - description: DisplayPort phy PLL vco clock + - description: DisplayPort phy PLL link clock + + clock-names: + items: + - const: xo + - const: sleep + - const: gpll0 + - const: dsi0dsi + - const: dsi0byte + - const: dsi1dsi + - const: dsi1byte + - const: hdmipll + - const: dpvco + - const: dplink '#clock-cells': const: 1 @@ -47,6 +74,17 @@ required: - '#reset-cells' - '#power-domain-cells' +if: + properties: + compatible: + contains: + const: qcom,mmcc-msm8998 + +then: + required: + - clocks + - clock-names + examples: # Example for MMCC for MSM8960: - | diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8998.h b/include/dt-bindings/clock/qcom,mmcc-msm8998.h new file mode 100644 index 000000000000..ecbafdb930aa --- /dev/null +++ b/include/dt-bindings/clock/qcom,mmcc-msm8998.h @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_MSM_MMCC_8998_H +#define _DT_BINDINGS_CLK_MSM_MMCC_8998_H + +#define MMPLL0 0 +#define MMPLL0_OUT_EVEN 1 +#define MMPLL1 2 +#define MMPLL1_OUT_EVEN 3 +#define MMPLL3 4 +#define MMPLL3_OUT_EVEN 5 +#define MMPLL4 6 +#define MMPLL4_OUT_EVEN 7 +#define MMPLL5 8 +#define MMPLL5_OUT_EVEN 9 +#define MMPLL6 10 +#define MMPLL6_OUT_EVEN 11 +#define MMPLL7 12 +#define MMPLL7_OUT_EVEN 13 +#define MMPLL10 14 +#define MMPLL10_OUT_EVEN 15 +#define BYTE0_CLK_SRC 16 +#define BYTE1_CLK_SRC 17 +#define CCI_CLK_SRC 18 +#define CPP_CLK_SRC 19 +#define CSI0_CLK_SRC 20 +#define CSI1_CLK_SRC 21 +#define CSI2_CLK_SRC 22 +#define CSI3_CLK_SRC 23 +#define CSIPHY_CLK_SRC 24 +#define CSI0PHYTIMER_CLK_SRC 25 +#define CSI1PHYTIMER_CLK_SRC 26 +#define CSI2PHYTIMER_CLK_SRC 27 +#define DP_AUX_CLK_SRC 28 +#define DP_CRYPTO_CLK_SRC 29 +#define DP_LINK_CLK_SRC 30 +#define DP_PIXEL_CLK_SRC 31 +#define ESC0_CLK_SRC 32 +#define ESC1_CLK_SRC 33 +#define EXTPCLK_CLK_SRC 34 +#define FD_CORE_CLK_SRC 35 +#define HDMI_CLK_SRC 36 +#define JPEG0_CLK_SRC 37 +#define MAXI_CLK_SRC 38 +#define MCLK0_CLK_SRC 39 +#define MCLK1_CLK_SRC 40 +#define MCLK2_CLK_SRC 41 +#define MCLK3_CLK_SRC 42 +#define MDP_CLK_SRC 43 +#define VSYNC_CLK_SRC 44 +#define AHB_CLK_SRC 45 +#define AXI_CLK_SRC 46 +#define PCLK0_CLK_SRC 47 +#define PCLK1_CLK_SRC 48 +#define ROT_CLK_SRC 49 +#define VIDEO_CORE_CLK_SRC 50 +#define VIDEO_SUBCORE0_CLK_SRC 51 +#define VIDEO_SUBCORE1_CLK_SRC 52 +#define VFE0_CLK_SRC 53 +#define VFE1_CLK_SRC 54 +#define MISC_AHB_CLK 55 +#define VIDEO_CORE_CLK 56 +#define VIDEO_AHB_CLK 57 +#define VIDEO_AXI_CLK 58 +#define VIDEO_MAXI_CLK 59 +#define VIDEO_SUBCORE0_CLK 60 +#define VIDEO_SUBCORE1_CLK 61 +#define MDSS_AHB_CLK 62 +#define MDSS_HDMI_DP_AHB_CLK 63 +#define MDSS_AXI_CLK 64 +#define MDSS_PCLK0_CLK 65 +#define MDSS_PCLK1_CLK 66 +#define MDSS_MDP_CLK 67 +#define MDSS_MDP_LUT_CLK 68 +#define MDSS_EXTPCLK_CLK 69 +#define MDSS_VSYNC_CLK 70 +#define MDSS_HDMI_CLK 71 +#define MDSS_BYTE0_CLK 72 +#define MDSS_BYTE1_CLK 73 +#define MDSS_ESC0_CLK 74 +#define MDSS_ESC1_CLK 75 +#define MDSS_ROT_CLK 76 +#define MDSS_DP_LINK_CLK 77 +#define MDSS_DP_LINK_INTF_CLK 78 +#define MDSS_DP_CRYPTO_CLK 79 +#define MDSS_DP_PIXEL_CLK 80 +#define MDSS_DP_AUX_CLK 81 +#define MDSS_BYTE0_INTF_CLK 82 +#define MDSS_BYTE1_INTF_CLK 83 +#define CAMSS_CSI0PHYTIMER_CLK 84 +#define CAMSS_CSI1PHYTIMER_CLK 85 +#define CAMSS_CSI2PHYTIMER_CLK 86 +#define CAMSS_CSI0_CLK 87 +#define CAMSS_CSI0_AHB_CLK 88 +#define CAMSS_CSI0RDI_CLK 89 +#define CAMSS_CSI0PIX_CLK 90 +#define CAMSS_CSI1_CLK 91 +#define CAMSS_CSI1_AHB_CLK 92 +#define CAMSS_CSI1RDI_CLK 93 +#define CAMSS_CSI1PIX_CLK 94 +#define CAMSS_CSI2_CLK 95 +#define CAMSS_CSI2_AHB_CLK 96 +#define CAMSS_CSI2RDI_CLK 97 +#define CAMSS_CSI2PIX_CLK 98 +#define CAMSS_CSI3_CLK 99 +#define CAMSS_CSI3_AHB_CLK 100 +#define CAMSS_CSI3RDI_CLK 101 +#define CAMSS_CSI3PIX_CLK 102 +#define CAMSS_ISPIF_AHB_CLK 103 +#define CAMSS_CCI_CLK 104 +#define CAMSS_CCI_AHB_CLK 105 +#define CAMSS_MCLK0_CLK 106 +#define CAMSS_MCLK1_CLK 107 +#define CAMSS_MCLK2_CLK 108 +#define CAMSS_MCLK3_CLK 109 +#define CAMSS_TOP_AHB_CLK 110 +#define CAMSS_AHB_CLK 111 +#define CAMSS_MICRO_AHB_CLK 112 +#define CAMSS_JPEG0_CLK 113 +#define CAMSS_JPEG_AHB_CLK 114 +#define CAMSS_JPEG_AXI_CLK 115 +#define CAMSS_VFE0_AHB_CLK 116 +#define CAMSS_VFE1_AHB_CLK 117 +#define CAMSS_VFE0_CLK 118 +#define CAMSS_VFE1_CLK 119 +#define CAMSS_CPP_CLK 120 +#define CAMSS_CPP_AHB_CLK 121 +#define CAMSS_VFE_VBIF_AHB_CLK 122 +#define CAMSS_VFE_VBIF_AXI_CLK 123 +#define CAMSS_CPP_AXI_CLK 124 +#define CAMSS_CPP_VBIF_AHB_CLK 125 +#define CAMSS_CSI_VFE0_CLK 126 +#define CAMSS_CSI_VFE1_CLK 127 +#define CAMSS_VFE0_STREAM_CLK 128 +#define CAMSS_VFE1_STREAM_CLK 129 +#define CAMSS_CPHY_CSID0_CLK 130 +#define CAMSS_CPHY_CSID1_CLK 131 +#define CAMSS_CPHY_CSID2_CLK 132 +#define CAMSS_CPHY_CSID3_CLK 133 +#define CAMSS_CSIPHY0_CLK 134 +#define CAMSS_CSIPHY1_CLK 135 +#define CAMSS_CSIPHY2_CLK 136 +#define FD_CORE_CLK 137 +#define FD_CORE_UAR_CLK 138 +#define FD_AHB_CLK 139 +#define MNOC_AHB_CLK 140 +#define BIMC_SMMU_AHB_CLK 141 +#define BIMC_SMMU_AXI_CLK 142 +#define MNOC_MAXI_CLK 143 +#define VMEM_MAXI_CLK 144 +#define VMEM_AHB_CLK 145 + +#define SPDM_BCR 0 +#define SPDM_RM_BCR 1 +#define MISC_BCR 2 +#define VIDEO_TOP_BCR 3 +#define THROTTLE_VIDEO_BCR 4 +#define MDSS_BCR 5 +#define THROTTLE_MDSS_BCR 6 +#define CAMSS_PHY0_BCR 7 +#define CAMSS_PHY1_BCR 8 +#define CAMSS_PHY2_BCR 9 +#define CAMSS_CSI0_BCR 10 +#define CAMSS_CSI0RDI_BCR 11 +#define CAMSS_CSI0PIX_BCR 12 +#define CAMSS_CSI1_BCR 13 +#define CAMSS_CSI1RDI_BCR 14 +#define CAMSS_CSI1PIX_BCR 15 +#define CAMSS_CSI2_BCR 16 +#define CAMSS_CSI2RDI_BCR 17 +#define CAMSS_CSI2PIX_BCR 18 +#define CAMSS_CSI3_BCR 19 +#define CAMSS_CSI3RDI_BCR 20 +#define CAMSS_CSI3PIX_BCR 21 +#define CAMSS_ISPIF_BCR 22 +#define CAMSS_CCI_BCR 23 +#define CAMSS_TOP_BCR 24 +#define CAMSS_AHB_BCR 25 +#define CAMSS_MICRO_BCR 26 +#define CAMSS_JPEG_BCR 27 +#define CAMSS_VFE0_BCR 28 +#define CAMSS_VFE1_BCR 29 +#define CAMSS_VFE_VBIF_BCR 30 +#define CAMSS_CPP_TOP_BCR 31 +#define CAMSS_CPP_BCR 32 +#define CAMSS_CSI_VFE0_BCR 33 +#define CAMSS_CSI_VFE1_BCR 34 +#define CAMSS_FD_BCR 35 +#define THROTTLE_CAMSS_BCR 36 +#define MNOCAHB_BCR 37 +#define MNOCAXI_BCR 38 +#define BMIC_SMMU_BCR 39 +#define MNOC_MAXI_BCR 40 +#define VMEM_BCR 41 +#define BTO_BCR 42 + +#define VIDEO_TOP_GDSC 1 +#define VIDEO_SUBCORE0_GDSC 2 +#define VIDEO_SUBCORE1_GDSC 3 +#define MDSS_GDSC 4 +#define CAMSS_TOP_GDSC 5 +#define CAMSS_VFE0_GDSC 6 +#define CAMSS_VFE1_GDSC 7 +#define CAMSS_CPP_GDSC 8 +#define BIMC_SMMU_GDSC 9 + +#endif -- cgit v1.2.3 From 4316ec05da997c20f74005753d228765e369a1cb Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 25 Nov 2019 14:59:03 +0100 Subject: dt-bindings: mailbox: qcom: Add clock-name optional property When the APCS clock is registered (platform dependent), it retrieves its parent names from hardcoded values in the driver. The following commit allows the DT node to provide such clock names to the platform data based clock driver therefore avoiding having to explicitly embed those names in the clock driver source code. Co-developed-by: Niklas Cassel Signed-off-by: Niklas Cassel Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Rob Herring Reviewed-by: Bjorn Andersson Link: https://lkml.kernel.org/r/20191125135910.679310-2-niklas.cassel@linaro.org Signed-off-by: Stephen Boyd --- .../bindings/mailbox/qcom,apcs-kpss-global.txt | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt index 0278482af65c..beec612dbe6a 100644 --- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt +++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt @@ -21,10 +21,11 @@ platforms. Usage: required Value type: Definition: must specify the base address and size of the global block + - clocks: - Usage: required if #clocks-cells property is present - Value type: - Definition: phandle to the input PLL, which feeds the APCS mux/divider + Usage: required if #clock-names property is present + Value type: + Definition: phandles to the two parent clocks of the clock driver. - #mbox-cells: Usage: required @@ -36,6 +37,12 @@ platforms. Value type: Definition: as described in clock.txt, must be 0 +- clock-names: + Usage: required if the platform data based clock driver needs to + retrieve the parent clock names from device tree. + This will requires two mandatory clocks to be defined. + Value type: + Definition: must be "pll" and "aux" = EXAMPLE The following example describes the APCS HMSS found in MSM8996 and part of the @@ -68,3 +75,14 @@ Below is another example of the APCS binding on MSM8916 platforms: clocks = <&a53pll>; #clock-cells = <0>; }; + +Below is another example of the APCS binding on QCS404 platforms: + + apcs_glb: mailbox@b011000 { + compatible = "qcom,qcs404-apcs-apps-global", "syscon"; + reg = <0x0b011000 0x1000>; + #mbox-cells = <1>; + clocks = <&apcs_hfpll>, <&gcc GCC_GPLL0_AO_OUT_MAIN>; + clock-names = "pll", "aux"; + #clock-cells = <0>; + }; -- cgit v1.2.3 From e63318785234c9c33e97b7793e09a82c869e3ef0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:45:04 +0100 Subject: dt-bindings: net: ravb: Document r8a77961 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document support for the Ethernet AVB interface in the Renesas R-Car M3-W+ (R8A77961) SoC. Update all references to R-Car M3-W from "r8a7796" to "r8a77960", to avoid confusion between R-Car M3-W (R8A77960) and M3-W+. No driver update is needed. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Reviewed-by: Sergei Shtylyov Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/net/renesas,ravb.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/renesas,ravb.txt b/Documentation/devicetree/bindings/net/renesas,ravb.txt index 5df4aa7f6811..87dad2dd8ca0 100644 --- a/Documentation/devicetree/bindings/net/renesas,ravb.txt +++ b/Documentation/devicetree/bindings/net/renesas,ravb.txt @@ -21,7 +21,8 @@ Required properties: - "renesas,etheravb-r8a774b1" for the R8A774B1 SoC. - "renesas,etheravb-r8a774c0" for the R8A774C0 SoC. - "renesas,etheravb-r8a7795" for the R8A7795 SoC. - - "renesas,etheravb-r8a7796" for the R8A7796 SoC. + - "renesas,etheravb-r8a7796" for the R8A77960 SoC. + - "renesas,etheravb-r8a77961" for the R8A77961 SoC. - "renesas,etheravb-r8a77965" for the R8A77965 SoC. - "renesas,etheravb-r8a77970" for the R8A77970 SoC. - "renesas,etheravb-r8a77980" for the R8A77980 SoC. @@ -37,8 +38,8 @@ Required properties: - reg: Offset and length of (1) the register block and (2) the stream buffer. The region for the register block is mandatory. The region for the stream buffer is optional, as it is only present on - R-Car Gen2 and RZ/G1 SoCs, and on R-Car H3 (R8A7795), M3-W (R8A7796), - and M3-N (R8A77965). + R-Car Gen2 and RZ/G1 SoCs, and on R-Car H3 (R8A7795), M3-W (R8A77960), + M3-W+ (R8A77961), and M3-N (R8A77965). - interrupts: A list of interrupt-specifiers, one for each entry in interrupt-names. If interrupt-names is not present, an interrupt specifier -- cgit v1.2.3 From 26f1e12c714e9e7314e1a099fd8225473cb76ab8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Dec 2019 14:47:51 +0100 Subject: dt-bindings: watchdog: renesas-wdt: Document r8a77961 support Document support for the Watchdog Timer in the Renesas R-Car M3-W+ (R8A77961) SoC. No driver update is needed. Signed-off-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/watchdog/renesas,wdt.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/watchdog/renesas,wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas,wdt.txt index a5bf04dba410..79b3c62f183d 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.txt @@ -19,6 +19,7 @@ Required properties: - "renesas,r8a7794-wdt" (R-Car E2) - "renesas,r8a7795-wdt" (R-Car H3) - "renesas,r8a7796-wdt" (R-Car M3-W) + - "renesas,r8a77961-wdt" (R-Car M3-W+) - "renesas,r8a77965-wdt" (R-Car M3-N) - "renesas,r8a77970-wdt" (R-Car V3M) - "renesas,r8a77990-wdt" (R-Car E3) -- cgit v1.2.3 From d1c5b2541170df3816539f873ec0da388e3bf736 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 5 Dec 2019 12:22:59 -0800 Subject: dt-bindings: net: bluetooth: Add compatible string for WCN3991 Commit 7d250a062f75 ("Bluetooth: hci_qca: Add support for Qualcomm Bluetooth SoC WCN3991") added the compatible string 'qcom,wcn3991-bt' to the Qualcomm Bluetooth driver, however the string is not listed in the binding. Add the 'qcom,wcn3991-bt' to the supported compatible strings. Signed-off-by: Matthias Kaehlcke Reviewed-by: Simon Horman Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt index 68b67d9db63a..999aceadb985 100644 --- a/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt +++ b/Documentation/devicetree/bindings/net/qualcomm-bluetooth.txt @@ -11,6 +11,7 @@ Required properties: - compatible: should contain one of the following: * "qcom,qca6174-bt" * "qcom,wcn3990-bt" + * "qcom,wcn3991-bt" * "qcom,wcn3998-bt" Optional properties for compatible string qcom,qca6174-bt: -- cgit v1.2.3 From 0fa4f770977cf9b1776c433b5ed23d5b977c3556 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 8 Dec 2019 14:50:49 -0800 Subject: dt-bindings: Add MAX31730 as trivial device Maxim MAX31730 is a 3-Channel Remote Temperature Sensor. Signed-off-by: Guenter Roeck Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/trivial-devices.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 765fd1c170df..2ec9bccde79e 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -132,6 +132,8 @@ properties: - maxim,max6621 # 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface - maxim,max6625 + # 3-Channel Remote Temperature Sensor + - maxim,max31730 # mCube 3-axis 8-bit digital accelerometer - mcube,mc3230 # MEMSIC 2-axis 8-bit digital accelerometer -- cgit v1.2.3 From d693b2883c0b9b261d2c490a9933e703359b4542 Mon Sep 17 00:00:00 2001 From: "Frank A. Cancio Bello" Date: Wed, 18 Dec 2019 14:15:53 -0500 Subject: docs: ftrace: Specifies when buffers get clear Clarify a few places where the ring buffer and the "snapshot" buffer are cleared as a side effect of an operation. This will avoid users lost of tracing data because of these so far undocumented behavior. Signed-off-by: Frank A. Cancio Bello Reviewed-by: Steven Rostedt (VMware) Link: https://lore.kernel.org/r/20191218191553.q4lwyxmquvtjzjfz@frank-laptop Signed-off-by: Jonathan Corbet --- Documentation/trace/ftrace.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst index d2b5657ed33e..46df39300d22 100644 --- a/Documentation/trace/ftrace.rst +++ b/Documentation/trace/ftrace.rst @@ -95,7 +95,8 @@ of ftrace. Here is a list of some of the key files: current_tracer: This is used to set or display the current tracer - that is configured. + that is configured. Changing the current tracer clears + the ring buffer content as well as the "snapshot" buffer. available_tracers: @@ -126,7 +127,8 @@ of ftrace. Here is a list of some of the key files: This file holds the output of the trace in a human readable format (described below). Note, tracing is temporarily disabled when the file is open for reading. Once all readers - are closed, tracing is re-enabled. + are closed, tracing is re-enabled. Opening this file for + writing with the O_TRUNC flag clears the ring buffer content. trace_pipe: @@ -490,6 +492,9 @@ of ftrace. Here is a list of some of the key files: # echo global > trace_clock + Setting a clock clears the ring buffer content as well as the + "snapshot" buffer. + trace_marker: This is a very useful file for synchronizing user space -- cgit v1.2.3 From ab229d620263e2399c1bd611e64bde5250f72dae Mon Sep 17 00:00:00 2001 From: Konstantin Ryabitsev Date: Mon, 9 Dec 2019 14:26:11 -0500 Subject: Process: provide hardware-security list details Fill in "..." stubs with proper links to the mailing lists's encryption keys and service description URLs. Similarly, fix wording to specify that multiple members of Linux Foundation's IT team have access to internal kernel.org infrastructure, and that all of them have similar confidentiality obligations as the IT team director. Signed-off-by: Konstantin Ryabitsev Reviewed-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20191209192611.GA1688548@chatter.i7.local Signed-off-by: Jonathan Corbet --- .../process/embargoed-hardware-issues.rst | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index 799580acc8de..3d17de7e5aeb 100644 --- a/Documentation/process/embargoed-hardware-issues.rst +++ b/Documentation/process/embargoed-hardware-issues.rst @@ -36,7 +36,10 @@ issue according to our documented process. The list is encrypted and email to the list can be sent by either PGP or S/MIME encrypted and must be signed with the reporter's PGP key or S/MIME certificate. The list's PGP key and S/MIME certificate are available from -https://www.kernel.org/.... +the following URLs: + + - PGP: https://www.kernel.org/static/files/hardware-security.asc + - S/MIME: https://www.kernel.org/static/files/hardware-security.crt While hardware security issues are often handled by the affected hardware vendor, we welcome contact from researchers or individuals who have @@ -55,14 +58,14 @@ Operation of mailing-lists ^^^^^^^^^^^^^^^^^^^^^^^^^^ The encrypted mailing-lists which are used in our process are hosted on -Linux Foundation's IT infrastructure. By providing this service Linux -Foundation's director of IT Infrastructure security technically has the -ability to access the embargoed information, but is obliged to -confidentiality by his employment contract. Linux Foundation's director of -IT Infrastructure security is also responsible for the kernel.org -infrastructure. - -The Linux Foundation's current director of IT Infrastructure security is +Linux Foundation's IT infrastructure. By providing this service, members +of Linux Foundation's IT operations personnel technically have the +ability to access the embargoed information, but are obliged to +confidentiality by their employment contract. Linux Foundation IT +personnel are also responsible for operating and managing the rest of +kernel.org infrastructure. + +The Linux Foundation's current director of IT Project infrastructure is Konstantin Ryabitsev. @@ -274,7 +277,7 @@ software decrypts the email and re-encrypts it individually for each subscriber with the subscriber's PGP key or S/MIME certificate. Details about the mailing-list software and the setup which is used to ensure the security of the lists and protection of the data can be found here: -https://www.kernel.org/.... +https://korg.wiki.kernel.org/userdoc/remail. List keys ^^^^^^^^^ -- cgit v1.2.3 From 0854cbdb1829413680cc1bf072dc68254a5ffe7b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 8 Dec 2019 20:25:10 -0800 Subject: Documentation: x86: fix boot.rst warning and format Fix a Sphinx documentation format warning by breaking a long line into 2 lines. Also drop the ':' usage after the Protocol version numbers since other Protocol versions don't use colons. Documentation/x86/boot.rst:72: WARNING: Malformed table. Text in column margin in table line 57. Fixes: 2c33c27fd603 ("x86/boot: Introduce kernel_info") Fixes: 00cd1c154d56 ("x86/boot: Introduce kernel_info.setup_type_max") Signed-off-by: Randy Dunlap Reviewed-by: Daniel Kiper Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Link: https://lore.kernel.org/r/c6fbf592-0aca-69d9-e903-e869221a041a@infradead.org Signed-off-by: Jonathan Corbet --- Documentation/x86/boot.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/x86/boot.rst b/Documentation/x86/boot.rst index 90bb8f5ab384..e0dc2ffb7094 100644 --- a/Documentation/x86/boot.rst +++ b/Documentation/x86/boot.rst @@ -69,11 +69,12 @@ Protocol 2.13 (Kernel 3.14) Support 32- and 64-bit flags being set in xloadflags to support booting a 64-bit kernel from 32-bit EFI -Protocol 2.14: BURNT BY INCORRECT COMMIT ae7e1238e68f2a472a125673ab506d49158c1889 +Protocol 2.14 BURNT BY INCORRECT COMMIT + ae7e1238e68f2a472a125673ab506d49158c1889 (x86/boot: Add ACPI RSDP address to setup_header) DO NOT USE!!! ASSUME SAME AS 2.13. -Protocol 2.15: (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max. +Protocol 2.15 (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max. ============= ============================================================ .. note:: -- cgit v1.2.3 From eb43135117adc88ba3fd8b15a649c4bceff79962 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 8 Dec 2019 20:16:40 -0800 Subject: Documentation: fix Sphinx warning in xilinx_sdfec.rst Fix Sphinx format warning by adding a blank line. Documentation/misc-devices/xilinx_sdfec.rst:2: WARNING: Explicit markup ends without a blank line; unexpected unindent. Signed-off-by: Randy Dunlap Acked-by: Dragan Cvetic Link: https://lore.kernel.org/r/8d644cf1-fa7b-ec62-84cf-9b41d7c30eed@infradead.org Signed-off-by: Jonathan Corbet --- Documentation/misc-devices/xilinx_sdfec.rst | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/misc-devices/xilinx_sdfec.rst b/Documentation/misc-devices/xilinx_sdfec.rst index 2245fcfa224d..7a47075c171c 100644 --- a/Documentation/misc-devices/xilinx_sdfec.rst +++ b/Documentation/misc-devices/xilinx_sdfec.rst @@ -1,4 +1,5 @@ .. SPDX-License-Identifier: GPL-2.0+ + ==================== Xilinx SD-FEC Driver ==================== -- cgit v1.2.3 From 1d5c17e470286b8211e8a18d0f85ae89dec4e8d8 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Tue, 8 Oct 2019 18:06:37 -0700 Subject: RISC-V: Typo fixes in image header and documentation. There are some typos in boot image header and riscv boot documentation. Fix the typos. Signed-off-by: Atish Patra Reviewed-by: Palmer Dabbelt Link: https://lore.kernel.org/r/20191009010637.9955-1-atish.patra@wdc.com Signed-off-by: Jonathan Corbet --- Documentation/riscv/boot-image-header.rst | 4 ++-- arch/riscv/include/asm/image.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/riscv/boot-image-header.rst b/Documentation/riscv/boot-image-header.rst index 518d46d2389d..d7752533865f 100644 --- a/Documentation/riscv/boot-image-header.rst +++ b/Documentation/riscv/boot-image-header.rst @@ -22,7 +22,7 @@ The following 64-byte header is present in decompressed Linux kernel image:: u64 res2 = 0; /* Reserved */ u64 magic = 0x5643534952; /* Magic number, little endian, "RISCV" */ u32 magic2 = 0x05435352; /* Magic number 2, little endian, "RSC\x05" */ - u32 res4; /* Reserved for PE COFF offset */ + u32 res3; /* Reserved for PE COFF offset */ This header format is compliant with PE/COFF header and largely inspired from ARM64 header. Thus, both ARM64 & RISC-V header can be combined into one common @@ -34,7 +34,7 @@ Notes - This header can also be reused to support EFI stub for RISC-V in future. EFI specification needs PE/COFF image header in the beginning of the kernel image in order to load it as an EFI application. In order to support EFI stub, - code0 should be replaced with "MZ" magic string and res5(at offset 0x3c) should + code0 should be replaced with "MZ" magic string and res3(at offset 0x3c) should point to the rest of the PE/COFF header. - version field indicate header version number diff --git a/arch/riscv/include/asm/image.h b/arch/riscv/include/asm/image.h index 7b0f92ba0acc..e0b319af3681 100644 --- a/arch/riscv/include/asm/image.h +++ b/arch/riscv/include/asm/image.h @@ -42,7 +42,7 @@ * @res2: reserved * @magic: Magic number (RISC-V specific; deprecated) * @magic2: Magic number 2 (to match the ARM64 'magic' field pos) - * @res4: reserved (will be used for PE COFF offset) + * @res3: reserved (will be used for PE COFF offset) * * The intention is for this header format to be shared between multiple * architectures to avoid a proliferation of image header formats. @@ -59,7 +59,7 @@ struct riscv_image_header { u64 res2; u64 magic; u32 magic2; - u32 res4; + u32 res3; }; #endif /* __ASSEMBLY__ */ #endif /* _ASM_RISCV_IMAGE_H */ -- cgit v1.2.3 From a83aaf4979e799705781ceb86a1f29d2b29736b1 Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Wed, 4 Dec 2019 15:49:39 +0530 Subject: Documentation: filesystems: automount-support: Change reference to document autofs.txt to autofs.rst This patch fixes following documentation build warning: Warning: Documentation/filesystems/automount-support.txt references a file that doesn't exist: Documentation/filesystems/autofs.txt Signed-off-by: Madhuparna Bhowmik Link: https://lore.kernel.org/r/20191204101939.6939-1-madhuparnabhowmik04@gmail.com Signed-off-by: Jonathan Corbet --- Documentation/filesystems/automount-support.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/automount-support.txt b/Documentation/filesystems/automount-support.txt index b0afd3d55eaf..7d9f82607562 100644 --- a/Documentation/filesystems/automount-support.txt +++ b/Documentation/filesystems/automount-support.txt @@ -9,7 +9,7 @@ also be requested by userspace. IN-KERNEL AUTOMOUNTING ====================== -See section "Mount Traps" of Documentation/filesystems/autofs.txt +See section "Mount Traps" of Documentation/filesystems/autofs.rst Then from userspace, you can just do something like: -- cgit v1.2.3 From bc51a6d34c27bd1040fddaf2bdc61309f392f86a Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Wed, 4 Dec 2019 16:15:54 +0530 Subject: Documentation: kernel-hacking: hacking.rst: Change reference to document namespaces.rst to symbol-namespaces.rst This patch fixes the following documentation build warning: Warning: Documentation/kernel-hacking/hacking.rst references a file that doesn't exist: Documentation/kbuild/namespaces.rst According to the following patch: https://patchwork.kernel.org/patch/11178727/ (doc: move namespaces.rst from kbuild/ to core-api/) The file namespaces.rst was moved from kbuild to core-api and renamed to symbol-namespaces.rst. Therefore, this patch changes the reference to the document kbuild/namespaces.rst in hacking.rst to core-api/symbol-namespaces.rst Signed-off-by: Madhuparna Bhowmik Link: https://lore.kernel.org/r/20191204104554.9100-1-madhuparnabhowmik04@gmail.com Signed-off-by: Jonathan Corbet --- Documentation/kernel-hacking/hacking.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-hacking/hacking.rst b/Documentation/kernel-hacking/hacking.rst index a3ddb213a5e1..d62aacb2822a 100644 --- a/Documentation/kernel-hacking/hacking.rst +++ b/Documentation/kernel-hacking/hacking.rst @@ -601,7 +601,7 @@ Defined in ``include/linux/export.h`` This is the variant of `EXPORT_SYMBOL()` that allows specifying a symbol namespace. Symbol Namespaces are documented in -``Documentation/kbuild/namespaces.rst``. +``Documentation/core-api/symbol-namespaces.rst``. :c:func:`EXPORT_SYMBOL_NS_GPL()` -------------------------------- @@ -610,7 +610,7 @@ Defined in ``include/linux/export.h`` This is the variant of `EXPORT_SYMBOL_GPL()` that allows specifying a symbol namespace. Symbol Namespaces are documented in -``Documentation/kbuild/namespaces.rst``. +``Documentation/core-api/symbol-namespaces.rst``. Routines and Conventions ======================== -- cgit v1.2.3 From 3dbbeef42b6489ec7c10dba4d2b7805c9bbff773 Mon Sep 17 00:00:00 2001 From: Federico Vaga Date: Sun, 1 Dec 2019 13:19:41 +0100 Subject: doc:locking: fix locktorture parameter description The description was talking about two default values: I removed the wrong one. Signed-off-by: Federico Vaga Link: https://lore.kernel.org/r/20191201121941.6971-1-federico.vaga@vaga.pv.it Signed-off-by: Jonathan Corbet --- Documentation/locking/locktorture.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/locking/locktorture.rst b/Documentation/locking/locktorture.rst index e79eeeca3ac6..5bcb99ba7bd9 100644 --- a/Documentation/locking/locktorture.rst +++ b/Documentation/locking/locktorture.rst @@ -103,8 +103,7 @@ stat_interval Number of seconds between statistics-related printk()s. By default, locktorture will report stats every 60 seconds. Setting the interval to zero causes the statistics to - be printed -only- when the module is unloaded, and this - is the default. + be printed -only- when the module is unloaded. stutter The length of time to run the test before pausing for this -- cgit v1.2.3 From c1ccff45e54eb54fa4e437da197e6738b002f22d Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Fri, 29 Nov 2019 19:28:23 +0100 Subject: docs/memory-barriers.txt.kokr: Minor wordsmith MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As suggested by Paul, I got a review from another Korean hacker Yunjae.  From the review, I got not only 'Reviewed-by:' tags, but also found a few minor nits.  So I made a second version of the patchset but just realized that the first version has already sent to Linus.  I therefore send only the nit fixes as another patch. ----------------------------- >8 ---------------------------------------- docs/memory-barriers.txt.kokr: Minor wordsmith This commit fixes a couple of minor nits in the Korean translation of 'memory-barriers.txt'. Signed-off-by: SeongJae Park Reviewed-by: Yunjae Lee Link: https://lore.kernel.org/r/20191129182823.8710-1-sjpark@amazon.de Signed-off-by: Jonathan Corbet --- Documentation/translations/ko_KR/memory-barriers.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/translations/ko_KR/memory-barriers.txt b/Documentation/translations/ko_KR/memory-barriers.txt index f07c40a068b5..2e831ece6e26 100644 --- a/Documentation/translations/ko_KR/memory-barriers.txt +++ b/Documentation/translations/ko_KR/memory-barriers.txt @@ -2413,7 +2413,7 @@ _않습니다_. 알고 있는, - inb() 나 writel() 과 같은 - 적절한 액세스 루틴을 통해 이루어져야만 합니다. 이것들은 대부분의 경우에는 명시적 메모리 배리어 와 함께 사용될 필요가 없습니다만, 완화된 메모리 액세스 속성으로 I/O 메모리 윈도우로의 참조를 위해 -액세스 함수가 사용된다면 순서를 강제하기 위해 _madatory_ 메모리 배리어가 +액세스 함수가 사용된다면 순서를 강제하기 위해 _mandatory_ 메모리 배리어가 필요합니다. 더 많은 정보를 위해선 Documentation/driver-api/device-io.rst 를 참고하십시오. @@ -2528,7 +2528,7 @@ I/O 액세스를 통한 주변장치와의 통신은 아키텍쳐와 기기에 이것들은 readX() 와 writeX() 랑 비슷하지만, 더 완화된 메모리 순서 보장을 제공합니다. 구체적으로, 이것들은 일반적 메모리 액세스나 delay() 루프 (예:앞의 2-5 항목) 에 대해 순서를 보장하지 않습니다만 디폴트 I/O - 기능으로 매핑된 __iomem 포인터에 대해 동작할 때, 같은 CPU 쓰레드에 의해 + 기능으로 매핑된 __iomem 포인터에 대해 동작할 때, 같은 CPU 쓰레드에 의한 같은 주변장치로의 액세스에는 순서가 맞춰질 것이 보장됩니다. (*) readsX(), writesX(): -- cgit v1.2.3 From 93ccfa9a4eca482216c5caf88be77e5ffa0d744a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 19 Dec 2019 17:17:22 +0100 Subject: drm/todo: Updating logging todo Jani has merged a new set of logging functions, which we hope to be the One True solution now, pinky promises: commit fb6c7ab8718eb2543695d77ad8302ff81e8e1e32 Author: Jani Nikula Date: Tue Dec 10 14:30:43 2019 +0200 drm/print: introduce new struct drm_device based logging macros Update the todo entry to match the new preference. v2: Fix spelling issue Sam noticed. Cc: Jani Nikula Cc: Sean Paul Cc: Wambui Karuga Acked-by: Jani Nikula Acked-by: Sam Ravnborg Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20191219161722.2779994-1-daniel.vetter@ffwll.ch --- Documentation/gpu/todo.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 2d85f37284a1..bc869b23fc39 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -142,14 +142,14 @@ Contact: Daniel Vetter, respective driver maintainers Level: Advanced -Convert instances of dev_info/dev_err/dev_warn to their DRM_DEV_* equivalent ----------------------------------------------------------------------------- +Convert logging to drm_* functions with drm_device paramater +------------------------------------------------------------ For drivers which could have multiple instances, it is necessary to differentiate between which is which in the logs. Since DRM_INFO/WARN/ERROR don't do this, drivers used dev_info/warn/err to make this differentiation. We -now have DRM_DEV_* variants of the drm print macros, so we can start to convert -those drivers back to using drm-formwatted specific log messages. +now have drm_* variants of the drm print functions, so we can start to convert +those drivers back to using drm-formatted specific log messages. Before you start this conversion please contact the relevant maintainers to make sure your work will be merged - not everyone agrees that the DRM dmesg macros -- cgit v1.2.3 From d19e470b6605c900db21fc7b34c66b6891a79983 Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Fri, 13 Dec 2019 15:48:40 -0800 Subject: ACPI: fan: Expose fan performance state information When _FPS indicates variable speed fan support, the thermal cooling device for fan shows max performance state count as "max_state" (greater than or equal to 1). But the thermal cooling device doesn't expose the properties of each performance state. This is not enough for smart fan control user space software, which also considers speed, power and noise level. This change exposes the properties of the fan performance states in the sysfs directory of the ACPI device representing the fan, that is /sys/bus/acpi/devices/devices/INT3404:00 or /sys/bus/platform/devices/PNP0C0B:00. For example: $ ls /sys/bus/acpi/devices/INT3404\:00 description path state0 state11 state4 state7 status hid physical_node state1 state2 state5 state8 subsystem modalias power state10 state3 state6 state9 uevent uid wakeup where each state* attribute lists the properties of a fan performance state in the following format: control_percent:trip_point:speed_rpm:noise_level_mdb:power_mw $ cat /sys/bus/acpi/devices/INT3404\:00/state10 95:0:11600:47500:4500 as documented in Documentation/admin-guide/acpi/fan_performance_states.rst While at it, return the correct error code from acpi_fan_probe() when acpi_fan_get_fps() or acpi_fan_get_fif() fails. Suggested-by: Rafael J. Wysocki Signed-off-by: Srinivas Pandruvada [ rjw: Subject, changelog, documentation ] Signed-off-by: Rafael J. Wysocki --- .../admin-guide/acpi/fan_performance_states.rst | 62 ++++++++++++++ Documentation/admin-guide/acpi/index.rst | 1 + drivers/acpi/fan.c | 96 ++++++++++++++++++++-- 3 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 Documentation/admin-guide/acpi/fan_performance_states.rst (limited to 'Documentation') diff --git a/Documentation/admin-guide/acpi/fan_performance_states.rst b/Documentation/admin-guide/acpi/fan_performance_states.rst new file mode 100644 index 000000000000..21d233ca50d8 --- /dev/null +++ b/Documentation/admin-guide/acpi/fan_performance_states.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========================== +ACPI Fan Performance States +=========================== + +When the optional _FPS object is present under an ACPI device representing a +fan (for example, PNP0C0B or INT3404), the ACPI fan driver creates additional +"state*" attributes in the sysfs directory of the ACPI device in question. +These attributes list properties of fan performance states. + +For more information on _FPS refer to the ACPI specification at: + +http://uefi.org/specifications + +For instance, the contents of the INT3404 ACPI device sysfs directory +may look as follows:: + + $ ls -l /sys/bus/acpi/devices/INT3404:00/ + total 0 +... + -r--r--r-- 1 root root 4096 Dec 13 20:38 state0 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state1 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state10 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state11 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state2 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state3 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state4 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state5 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state6 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state7 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state8 + -r--r--r-- 1 root root 4096 Dec 13 20:38 state9 + -r--r--r-- 1 root root 4096 Dec 13 01:00 status + ... + +where each of the "state*" files represents one performance state of the fan +and contains a colon-separated list of 5 integer numbers (fields) with the +following interpretation:: + +control_percent:trip_point_index:speed_rpm:noise_level_mdb:power_mw + +* ``control_percent``: The percent value to be used to set the fan speed to a + specific level using the _FSL object (0-100). + +* ``trip_point_index``: The active cooling trip point number that corresponds + to this performance state (0-9). + +* ``speed_rpm``: Speed of the fan in rotations per minute. + +* ``noise_level_mdb``: Audible noise emitted by the fan in this state in + millidecibels. + +* ``power_mw``: Power draw of the fan in this state in milliwatts. + +For example:: + + $cat /sys/bus/acpi/devices/INT3404:00/state1 + 25:0:3200:12500:1250 + +When a given field is not populated or its value provided by the platform +firmware is invalid, the "not-defined" string is shown instead of the value. diff --git a/Documentation/admin-guide/acpi/index.rst b/Documentation/admin-guide/acpi/index.rst index 4d13eeea1eca..71277689ad97 100644 --- a/Documentation/admin-guide/acpi/index.rst +++ b/Documentation/admin-guide/acpi/index.rst @@ -12,3 +12,4 @@ the Linux ACPI support. dsdt-override ssdt-overlays cppc_sysfs + fan_performance_states diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 816b0803f7fb..86d2417953b5 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -44,12 +44,16 @@ static const struct dev_pm_ops acpi_fan_pm = { #define FAN_PM_OPS_PTR NULL #endif +#define ACPI_FPS_NAME_LEN 20 + struct acpi_fan_fps { u64 control; u64 trip_point; u64 speed; u64 noise_level; u64 power; + char name[ACPI_FPS_NAME_LEN]; + struct device_attribute dev_attr; }; struct acpi_fan_fif { @@ -265,6 +269,39 @@ static int acpi_fan_speed_cmp(const void *a, const void *b) return fps1->speed - fps2->speed; } +static ssize_t show_state(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct acpi_fan_fps *fps = container_of(attr, struct acpi_fan_fps, dev_attr); + int count; + + if (fps->control == 0xFFFFFFFF || fps->control > 100) + count = snprintf(buf, PAGE_SIZE, "not-defined:"); + else + count = snprintf(buf, PAGE_SIZE, "%lld:", fps->control); + + if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9) + count += snprintf(&buf[count], PAGE_SIZE, "not-defined:"); + else + count += snprintf(&buf[count], PAGE_SIZE, "%lld:", fps->trip_point); + + if (fps->speed == 0xFFFFFFFF) + count += snprintf(&buf[count], PAGE_SIZE, "not-defined:"); + else + count += snprintf(&buf[count], PAGE_SIZE, "%lld:", fps->speed); + + if (fps->noise_level == 0xFFFFFFFF) + count += snprintf(&buf[count], PAGE_SIZE, "not-defined:"); + else + count += snprintf(&buf[count], PAGE_SIZE, "%lld:", fps->noise_level * 100); + + if (fps->power == 0xFFFFFFFF) + count += snprintf(&buf[count], PAGE_SIZE, "not-defined\n"); + else + count += snprintf(&buf[count], PAGE_SIZE, "%lld\n", fps->power); + + return count; +} + static int acpi_fan_get_fps(struct acpi_device *device) { struct acpi_fan *fan = acpi_driver_data(device); @@ -295,12 +332,13 @@ static int acpi_fan_get_fps(struct acpi_device *device) } for (i = 0; i < fan->fps_count; i++) { struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" }; - struct acpi_buffer fps = { sizeof(fan->fps[i]), &fan->fps[i] }; + struct acpi_buffer fps = { offsetof(struct acpi_fan_fps, name), + &fan->fps[i] }; status = acpi_extract_package(&obj->package.elements[i + 1], &format, &fps); if (ACPI_FAILURE(status)) { dev_err(&device->dev, "Invalid _FPS element\n"); - break; + goto err; } } @@ -308,6 +346,24 @@ static int acpi_fan_get_fps(struct acpi_device *device) sort(fan->fps, fan->fps_count, sizeof(*fan->fps), acpi_fan_speed_cmp, NULL); + for (i = 0; i < fan->fps_count; ++i) { + struct acpi_fan_fps *fps = &fan->fps[i]; + + snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i); + fps->dev_attr.show = show_state; + fps->dev_attr.store = NULL; + fps->dev_attr.attr.name = fps->name; + fps->dev_attr.attr.mode = 0444; + status = sysfs_create_file(&device->dev.kobj, &fps->dev_attr.attr); + if (status) { + int j; + + for (j = 0; j < i; ++j) + sysfs_remove_file(&device->dev.kobj, &fan->fps[j].dev_attr.attr); + break; + } + } + err: kfree(obj); return status; @@ -330,14 +386,20 @@ static int acpi_fan_probe(struct platform_device *pdev) platform_set_drvdata(pdev, fan); if (acpi_fan_is_acpi4(device)) { - if (acpi_fan_get_fif(device) || acpi_fan_get_fps(device)) - goto end; + result = acpi_fan_get_fif(device); + if (result) + return result; + + result = acpi_fan_get_fps(device); + if (result) + return result; + fan->acpi4 = true; } else { result = acpi_device_update_power(device, NULL); if (result) { dev_err(&device->dev, "Failed to set initial power state\n"); - goto end; + goto err_end; } } @@ -350,7 +412,7 @@ static int acpi_fan_probe(struct platform_device *pdev) &fan_cooling_ops); if (IS_ERR(cdev)) { result = PTR_ERR(cdev); - goto end; + goto err_end; } dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id); @@ -365,10 +427,21 @@ static int acpi_fan_probe(struct platform_device *pdev) result = sysfs_create_link(&cdev->device.kobj, &pdev->dev.kobj, "device"); - if (result) + if (result) { dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n"); + goto err_end; + } + + return 0; + +err_end: + if (fan->acpi4) { + int i; + + for (i = 0; i < fan->fps_count; ++i) + sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr); + } -end: return result; } @@ -376,6 +449,13 @@ static int acpi_fan_remove(struct platform_device *pdev) { struct acpi_fan *fan = platform_get_drvdata(pdev); + if (fan->acpi4) { + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); + int i; + + for (i = 0; i < fan->fps_count; ++i) + sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr); + } sysfs_remove_link(&pdev->dev.kobj, "thermal_cooling"); sysfs_remove_link(&fan->cdev->device.kobj, "device"); thermal_cooling_device_unregister(fan->cdev); -- cgit v1.2.3 From 0435bcd9e185803402a2566e78c1067c615bc579 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 17 Dec 2019 12:48:56 +0200 Subject: docs: firmware-guide: ACPI: Replace dma_request_slave_channel() with dma_request_chan() dma_request_chan() is the preferred API to request slave channels. Signed-off-by: Peter Ujfalusi [ rjw: Subject ] Signed-off-by: Rafael J. Wysocki --- Documentation/firmware-guide/acpi/enumeration.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst index 0a72b6321f5f..c13fee8b02ba 100644 --- a/Documentation/firmware-guide/acpi/enumeration.rst +++ b/Documentation/firmware-guide/acpi/enumeration.rst @@ -71,8 +71,8 @@ DMA support DMA controllers enumerated via ACPI should be registered in the system to provide generic access to their resources. For example, a driver that would like to be accessible to slave devices via generic API call -dma_request_slave_channel() must register itself at the end of the probe -function like this:: +dma_request_chan() must register itself at the end of the probe function like +this:: err = devm_acpi_dma_controller_register(dev, xlate_func, dw); /* Handle the error if it's not a case of !CONFIG_ACPI */ @@ -112,15 +112,15 @@ could look like:: } #endif -dma_request_slave_channel() will call xlate_func() for each registered DMA -controller. In the xlate function the proper channel must be chosen based on +dma_request_chan() will call xlate_func() for each registered DMA controller. +In the xlate function the proper channel must be chosen based on information in struct acpi_dma_spec and the properties of the controller provided by struct acpi_dma. -Clients must call dma_request_slave_channel() with the string parameter that -corresponds to a specific FixedDMA resource. By default "tx" means the first -entry of the FixedDMA resource array, "rx" means the second entry. The table -below shows a layout:: +Clients must call dma_request_chan() with the string parameter that corresponds +to a specific FixedDMA resource. By default "tx" means the first entry of the +FixedDMA resource array, "rx" means the second entry. The table below shows a +layout:: Device (I2C0) { -- cgit v1.2.3 From c6d633a927499f35a06455a960ad6b5a59c87c2c Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 15 Dec 2019 15:51:19 -0800 Subject: crypto: algapi - make unregistration functions return void Some of the algorithm unregistration functions return -ENOENT when asked to unregister a non-registered algorithm, while others always return 0 or always return void. But no users check the return value, except for two of the bulk unregistration functions which print a message on error but still always return 0 to their caller, and crypto_del_alg() which calls crypto_unregister_instance() which always returns 0. Since unregistering a non-registered algorithm is always a kernel bug but there isn't anything callers should do to handle this situation at runtime, let's simplify things by making all the unregistration functions return void, and moving the error message into crypto_unregister_alg() and upgrading it to a WARN(). Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- Documentation/crypto/devel-algos.rst | 34 ++++++++++++---------------------- crypto/acompress.c | 4 ++-- crypto/ahash.c | 4 ++-- crypto/algapi.c | 25 ++++++++----------------- crypto/crypto_user_base.c | 3 ++- crypto/scompress.c | 4 ++-- crypto/shash.c | 19 ++++++------------- include/crypto/algapi.h | 2 +- include/crypto/internal/acompress.h | 4 +--- include/crypto/internal/hash.h | 6 +++--- include/crypto/internal/scompress.h | 4 +--- include/linux/crypto.h | 4 ++-- 12 files changed, 42 insertions(+), 71 deletions(-) (limited to 'Documentation') diff --git a/Documentation/crypto/devel-algos.rst b/Documentation/crypto/devel-algos.rst index fb6b7979a1de..f225a953ab4b 100644 --- a/Documentation/crypto/devel-algos.rst +++ b/Documentation/crypto/devel-algos.rst @@ -31,28 +31,18 @@ The counterparts to those functions are listed below. :: - int crypto_unregister_alg(struct crypto_alg *alg); - int crypto_unregister_algs(struct crypto_alg *algs, int count); + void crypto_unregister_alg(struct crypto_alg *alg); + void crypto_unregister_algs(struct crypto_alg *algs, int count); -Notice that both registration and unregistration functions do return a -value, so make sure to handle errors. A return code of zero implies -success. Any return code < 0 implies an error. +The registration functions return 0 on success, or a negative errno +value on failure. crypto_register_algs() succeeds only if it +successfully registered all the given algorithms; if it fails partway +through, then any changes are rolled back. -The bulk registration/unregistration functions register/unregister each -transformation in the given array of length count. They handle errors as -follows: - -- crypto_register_algs() succeeds if and only if it successfully - registers all the given transformations. If an error occurs partway - through, then it rolls back successful registrations before returning - the error code. Note that if a driver needs to handle registration - errors for individual transformations, then it will need to use the - non-bulk function crypto_register_alg() instead. - -- crypto_unregister_algs() tries to unregister all the given - transformations, continuing on error. It logs errors and always - returns zero. +The unregistration functions always succeed, so they don't have a +return value. Don't try to unregister algorithms that aren't +currently registered. Single-Block Symmetric Ciphers [CIPHER] --------------------------------------- @@ -169,10 +159,10 @@ are as follows: :: - int crypto_unregister_ahash(struct ahash_alg *alg); + void crypto_unregister_ahash(struct ahash_alg *alg); - int crypto_unregister_shash(struct shash_alg *alg); - int crypto_unregister_shashes(struct shash_alg *algs, int count); + void crypto_unregister_shash(struct shash_alg *alg); + void crypto_unregister_shashes(struct shash_alg *algs, int count); Cipher Definition With struct shash_alg and ahash_alg diff --git a/crypto/acompress.c b/crypto/acompress.c index abadcb035a41..84a76723e851 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -151,9 +151,9 @@ int crypto_register_acomp(struct acomp_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_acomp); -int crypto_unregister_acomp(struct acomp_alg *alg) +void crypto_unregister_acomp(struct acomp_alg *alg) { - return crypto_unregister_alg(&alg->base); + crypto_unregister_alg(&alg->base); } EXPORT_SYMBOL_GPL(crypto_unregister_acomp); diff --git a/crypto/ahash.c b/crypto/ahash.c index 3815b363a693..181bd851b429 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -598,9 +598,9 @@ int crypto_register_ahash(struct ahash_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_ahash); -int crypto_unregister_ahash(struct ahash_alg *alg) +void crypto_unregister_ahash(struct ahash_alg *alg) { - return crypto_unregister_alg(&alg->halg.base); + crypto_unregister_alg(&alg->halg.base); } EXPORT_SYMBOL_GPL(crypto_unregister_ahash); diff --git a/crypto/algapi.c b/crypto/algapi.c index 9589b3f0041b..fe57b4f696ac 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -442,7 +442,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) return 0; } -int crypto_unregister_alg(struct crypto_alg *alg) +void crypto_unregister_alg(struct crypto_alg *alg) { int ret; LIST_HEAD(list); @@ -451,15 +451,14 @@ int crypto_unregister_alg(struct crypto_alg *alg) ret = crypto_remove_alg(alg, &list); up_write(&crypto_alg_sem); - if (ret) - return ret; + if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name)) + return; BUG_ON(refcount_read(&alg->cra_refcnt) != 1); if (alg->cra_destroy) alg->cra_destroy(alg); crypto_remove_final(&list); - return 0; } EXPORT_SYMBOL_GPL(crypto_unregister_alg); @@ -483,18 +482,12 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_algs); -int crypto_unregister_algs(struct crypto_alg *algs, int count) +void crypto_unregister_algs(struct crypto_alg *algs, int count) { - int i, ret; - - for (i = 0; i < count; i++) { - ret = crypto_unregister_alg(&algs[i]); - if (ret) - pr_err("Failed to unregister %s %s: %d\n", - algs[i].cra_driver_name, algs[i].cra_name, ret); - } + int i; - return 0; + for (i = 0; i < count; i++) + crypto_unregister_alg(&algs[i]); } EXPORT_SYMBOL_GPL(crypto_unregister_algs); @@ -639,7 +632,7 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_instance); -int crypto_unregister_instance(struct crypto_instance *inst) +void crypto_unregister_instance(struct crypto_instance *inst) { LIST_HEAD(list); @@ -651,8 +644,6 @@ int crypto_unregister_instance(struct crypto_instance *inst) up_write(&crypto_alg_sem); crypto_remove_final(&list); - - return 0; } EXPORT_SYMBOL_GPL(crypto_unregister_instance); diff --git a/crypto/crypto_user_base.c b/crypto/crypto_user_base.c index b785c476de67..3fa20f12989f 100644 --- a/crypto/crypto_user_base.c +++ b/crypto/crypto_user_base.c @@ -323,7 +323,8 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, if (refcount_read(&alg->cra_refcnt) > 2) goto drop_alg; - err = crypto_unregister_instance((struct crypto_instance *)alg); + crypto_unregister_instance((struct crypto_instance *)alg); + err = 0; drop_alg: crypto_mod_put(alg); diff --git a/crypto/scompress.c b/crypto/scompress.c index 4d50750d01c6..738f4f8f0f41 100644 --- a/crypto/scompress.c +++ b/crypto/scompress.c @@ -266,9 +266,9 @@ int crypto_register_scomp(struct scomp_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_scomp); -int crypto_unregister_scomp(struct scomp_alg *alg) +void crypto_unregister_scomp(struct scomp_alg *alg) { - return crypto_unregister_alg(&alg->base); + crypto_unregister_alg(&alg->base); } EXPORT_SYMBOL_GPL(crypto_unregister_scomp); diff --git a/crypto/shash.c b/crypto/shash.c index 8042bb0df9c0..7243f60dab87 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -520,9 +520,9 @@ int crypto_register_shash(struct shash_alg *alg) } EXPORT_SYMBOL_GPL(crypto_register_shash); -int crypto_unregister_shash(struct shash_alg *alg) +void crypto_unregister_shash(struct shash_alg *alg) { - return crypto_unregister_alg(&alg->base); + crypto_unregister_alg(&alg->base); } EXPORT_SYMBOL_GPL(crypto_unregister_shash); @@ -546,19 +546,12 @@ err: } EXPORT_SYMBOL_GPL(crypto_register_shashes); -int crypto_unregister_shashes(struct shash_alg *algs, int count) +void crypto_unregister_shashes(struct shash_alg *algs, int count) { - int i, ret; - - for (i = count - 1; i >= 0; --i) { - ret = crypto_unregister_shash(&algs[i]); - if (ret) - pr_err("Failed to unregister %s %s: %d\n", - algs[i].base.cra_driver_name, - algs[i].base.cra_name, ret); - } + int i; - return 0; + for (i = count - 1; i >= 0; --i) + crypto_unregister_shash(&algs[i]); } EXPORT_SYMBOL_GPL(crypto_unregister_shashes); diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index 771a295ac755..25661b4650ec 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -96,7 +96,7 @@ struct crypto_template *crypto_lookup_template(const char *name); int crypto_register_instance(struct crypto_template *tmpl, struct crypto_instance *inst); -int crypto_unregister_instance(struct crypto_instance *inst); +void crypto_unregister_instance(struct crypto_instance *inst); int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, struct crypto_instance *inst, u32 mask); diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h index 9de57367afbb..cf478681b53e 100644 --- a/include/crypto/internal/acompress.h +++ b/include/crypto/internal/acompress.h @@ -68,10 +68,8 @@ int crypto_register_acomp(struct acomp_alg *alg); * compression algorithm * * @alg: algorithm definition - * - * Return: zero on success; error code in case of error */ -int crypto_unregister_acomp(struct acomp_alg *alg); +void crypto_unregister_acomp(struct acomp_alg *alg); int crypto_register_acomps(struct acomp_alg *algs, int count); void crypto_unregister_acomps(struct acomp_alg *algs, int count); diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index cf8d7f99c93d..d4b1be519590 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -70,7 +70,7 @@ static inline int crypto_ahash_walk_last(struct crypto_hash_walk *walk) } int crypto_register_ahash(struct ahash_alg *alg); -int crypto_unregister_ahash(struct ahash_alg *alg); +void crypto_unregister_ahash(struct ahash_alg *alg); int crypto_register_ahashes(struct ahash_alg *algs, int count); void crypto_unregister_ahashes(struct ahash_alg *algs, int count); int ahash_register_instance(struct crypto_template *tmpl, @@ -105,9 +105,9 @@ static inline void crypto_drop_ahash(struct crypto_ahash_spawn *spawn) struct hash_alg_common *ahash_attr_alg(struct rtattr *rta, u32 type, u32 mask); int crypto_register_shash(struct shash_alg *alg); -int crypto_unregister_shash(struct shash_alg *alg); +void crypto_unregister_shash(struct shash_alg *alg); int crypto_register_shashes(struct shash_alg *algs, int count); -int crypto_unregister_shashes(struct shash_alg *algs, int count); +void crypto_unregister_shashes(struct shash_alg *algs, int count); int shash_register_instance(struct crypto_template *tmpl, struct shash_instance *inst); void shash_free_instance(struct crypto_instance *inst); diff --git a/include/crypto/internal/scompress.h b/include/crypto/internal/scompress.h index 6727ef0fc4d1..f834274c2493 100644 --- a/include/crypto/internal/scompress.h +++ b/include/crypto/internal/scompress.h @@ -112,10 +112,8 @@ int crypto_register_scomp(struct scomp_alg *alg); * compression algorithm * * @alg: algorithm definition - * - * Return: zero on success; error code in case of error */ -int crypto_unregister_scomp(struct scomp_alg *alg); +void crypto_unregister_scomp(struct scomp_alg *alg); int crypto_register_scomps(struct scomp_alg *algs, int count); void crypto_unregister_scomps(struct scomp_alg *algs, int count); diff --git a/include/linux/crypto.h b/include/linux/crypto.h index c23f1eed7970..a905e524e332 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -584,9 +584,9 @@ static inline void crypto_init_wait(struct crypto_wait *wait) * Algorithm registration interface. */ int crypto_register_alg(struct crypto_alg *alg); -int crypto_unregister_alg(struct crypto_alg *alg); +void crypto_unregister_alg(struct crypto_alg *alg); int crypto_register_algs(struct crypto_alg *algs, int count); -int crypto_unregister_algs(struct crypto_alg *algs, int count); +void crypto_unregister_algs(struct crypto_alg *algs, int count); /* * Algorithm query interface. -- cgit v1.2.3 From 3185fe1d8a4557ec84d9617274a694af0cf4c7da Mon Sep 17 00:00:00 2001 From: Niklas Cassel Date: Fri, 29 Nov 2019 22:39:11 +0100 Subject: dt-bindings: power: avs: Add support for CPR (Core Power Reduction) Add DT bindings to describe the CPR HW found on certain Qualcomm SoCs. Co-developed-by: Jorge Ramirez-Ortiz Signed-off-by: Jorge Ramirez-Ortiz Signed-off-by: Niklas Cassel Reviewed-by: Rob Herring Reviewed-by: Bjorn Andersson Reviewed-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- .../devicetree/bindings/power/avs/qcom,cpr.txt | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/avs/qcom,cpr.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/avs/qcom,cpr.txt b/Documentation/devicetree/bindings/power/avs/qcom,cpr.txt new file mode 100644 index 000000000000..ab0d5ebbad4e --- /dev/null +++ b/Documentation/devicetree/bindings/power/avs/qcom,cpr.txt @@ -0,0 +1,130 @@ +QCOM CPR (Core Power Reduction) + +CPR (Core Power Reduction) is a technology to reduce core power on a CPU +or other device. Each OPP of a device corresponds to a "corner" that has +a range of valid voltages for a particular frequency. While the device is +running at a particular frequency, CPR monitors dynamic factors such as +temperature, etc. and suggests adjustments to the voltage to save power +and meet silicon characteristic requirements. + +- compatible: + Usage: required + Value type: + Definition: should be "qcom,qcs404-cpr", "qcom,cpr" for qcs404 + +- reg: + Usage: required + Value type: + Definition: base address and size of the rbcpr register region + +- interrupts: + Usage: required + Value type: + Definition: should specify the CPR interrupt + +- clocks: + Usage: required + Value type: + Definition: phandle to the reference clock + +- clock-names: + Usage: required + Value type: + Definition: must be "ref" + +- vdd-apc-supply: + Usage: required + Value type: + Definition: phandle to the vdd-apc-supply regulator + +- #power-domain-cells: + Usage: required + Value type: + Definition: should be 0 + +- operating-points-v2: + Usage: required + Value type: + Definition: A phandle to the OPP table containing the + performance states supported by the CPR + power domain + +- acc-syscon: + Usage: optional + Value type: + Definition: phandle to syscon for writing ACC settings + +- nvmem-cells: + Usage: required + Value type: + Definition: phandle to nvmem cells containing the data + that makes up a fuse corner, for each fuse corner. + As well as the CPR fuse revision. + +- nvmem-cell-names: + Usage: required + Value type: + Definition: should be "cpr_quotient_offset1", "cpr_quotient_offset2", + "cpr_quotient_offset3", "cpr_init_voltage1", + "cpr_init_voltage2", "cpr_init_voltage3", "cpr_quotient1", + "cpr_quotient2", "cpr_quotient3", "cpr_ring_osc1", + "cpr_ring_osc2", "cpr_ring_osc3", "cpr_fuse_revision" + for qcs404. + +Example: + + cpr_opp_table: cpr-opp-table { + compatible = "operating-points-v2-qcom-level"; + + cpr_opp1: opp1 { + opp-level = <1>; + qcom,opp-fuse-level = <1>; + }; + cpr_opp2: opp2 { + opp-level = <2>; + qcom,opp-fuse-level = <2>; + }; + cpr_opp3: opp3 { + opp-level = <3>; + qcom,opp-fuse-level = <3>; + }; + }; + + power-controller@b018000 { + compatible = "qcom,qcs404-cpr", "qcom,cpr"; + reg = <0x0b018000 0x1000>; + interrupts = <0 15 IRQ_TYPE_EDGE_RISING>; + clocks = <&xo_board>; + clock-names = "ref"; + vdd-apc-supply = <&pms405_s3>; + #power-domain-cells = <0>; + operating-points-v2 = <&cpr_opp_table>; + acc-syscon = <&tcsr>; + + nvmem-cells = <&cpr_efuse_quot_offset1>, + <&cpr_efuse_quot_offset2>, + <&cpr_efuse_quot_offset3>, + <&cpr_efuse_init_voltage1>, + <&cpr_efuse_init_voltage2>, + <&cpr_efuse_init_voltage3>, + <&cpr_efuse_quot1>, + <&cpr_efuse_quot2>, + <&cpr_efuse_quot3>, + <&cpr_efuse_ring1>, + <&cpr_efuse_ring2>, + <&cpr_efuse_ring3>, + <&cpr_efuse_revision>; + nvmem-cell-names = "cpr_quotient_offset1", + "cpr_quotient_offset2", + "cpr_quotient_offset3", + "cpr_init_voltage1", + "cpr_init_voltage2", + "cpr_init_voltage3", + "cpr_quotient1", + "cpr_quotient2", + "cpr_quotient3", + "cpr_ring_osc1", + "cpr_ring_osc2", + "cpr_ring_osc3", + "cpr_fuse_revision"; + }; -- cgit v1.2.3 From 130ac214294bcb5efc93229c7d10144c4992e90a Mon Sep 17 00:00:00 2001 From: Pascal Paillet Date: Thu, 5 Dec 2019 17:13:59 +0100 Subject: regulator: Convert stm32-pwr regulator to json-schema Convert the stm32-pwr regulator binding to DT schema format using json-schema. Signed-off-by: Pascal Paillet Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191205161359.20755-1-p.paillet@st.com Signed-off-by: Mark Brown --- .../bindings/regulator/st,stm32mp1-pwr-reg.txt | 43 --------------- .../bindings/regulator/st,stm32mp1-pwr-reg.yaml | 64 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 43 deletions(-) delete mode 100644 Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.txt create mode 100644 Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.txt b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.txt deleted file mode 100644 index e372dd3f0c8a..000000000000 --- a/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.txt +++ /dev/null @@ -1,43 +0,0 @@ -STM32MP1 PWR Regulators ------------------------ - -Available Regulators in STM32MP1 PWR block are: - - reg11 for regulator 1V1 - - reg18 for regulator 1V8 - - usb33 for the swtich USB3V3 - -Required properties: -- compatible: Must be "st,stm32mp1,pwr-reg" -- list of child nodes that specify the regulator reg11, reg18 or usb33 - initialization data for defined regulators. The definition for each of - these nodes is defined using the standard binding for regulators found at - Documentation/devicetree/bindings/regulator/regulator.txt. -- vdd-supply: phandle to the parent supply/regulator node for vdd input -- vdd_3v3_usbfs-supply: phandle to the parent supply/regulator node for usb33 - -Example: - -pwr_regulators: pwr@50001000 { - compatible = "st,stm32mp1,pwr-reg"; - reg = <0x50001000 0x10>; - vdd-supply = <&vdd>; - vdd_3v3_usbfs-supply = <&vdd_usb>; - - reg11: reg11 { - regulator-name = "reg11"; - regulator-min-microvolt = <1100000>; - regulator-max-microvolt = <1100000>; - }; - - reg18: reg18 { - regulator-name = "reg18"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1800000>; - }; - - usb33: usb33 { - regulator-name = "usb33"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - }; -}; diff --git a/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml new file mode 100644 index 000000000000..8d8f38fe85dc --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/st,stm32mp1-pwr-reg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STM32MP1 PWR voltage regulators + +maintainers: + - Pascal Paillet + +properties: + compatible: + const: st,stm32mp1,pwr-reg + + reg: + maxItems: 1 + + vdd-supply: + description: Input supply phandle(s) for vdd input + + vdd_3v3_usbfs-supply: + description: Input supply phandle(s) for vdd_3v3_usbfs input + +patternProperties: + "^(reg11|reg18|usb33)$": + type: object + + allOf: + - $ref: "regulator.yaml#" + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; + + reg11 { + regulator-name = "reg11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + reg18 { + regulator-name = "reg18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usb33 { + regulator-name = "usb33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; +... -- cgit v1.2.3 From 169e808eda2d747118fa3feb99881e346968c760 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Wed, 18 Dec 2019 12:59:44 +0000 Subject: dt-bindings: clock: renesas: cpg-mssr: Fix r8a774b1 typo This patch fixes the typo %s/r8a774a1/r8a774b1/. Fixes: 10003938a0c64 ("dt-bindings: clock: renesas: cpg-mssr: Document r8a774b1 binding") Signed-off-by: Biju Das Link: https://lore.kernel.org/r/1576673984-37752-1-git-send-email-biju.das@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt index c7674d0267a3..f4d153f24a0f 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt @@ -19,7 +19,7 @@ Required Properties: - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E) - "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C) - "renesas,r8a774a1-cpg-mssr" for the r8a774a1 SoC (RZ/G2M) - - "renesas,r8a774b1-cpg-mssr" for the r8a774a1 SoC (RZ/G2N) + - "renesas,r8a774b1-cpg-mssr" for the r8a774b1 SoC (RZ/G2N) - "renesas,r8a774c0-cpg-mssr" for the r8a774c0 SoC (RZ/G2E) - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2) - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W) -- cgit v1.2.3 From b32bfbc98a747e82d30cc8fd6e4b173a48c01530 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Thu, 10 Oct 2019 15:25:58 +0100 Subject: dt-bindings: can: rcar_can: document r8a774b1 support Document RZ/G2N (r8a774b1) SoC specific bindings. Signed-off-by: Fabrizio Castro Acked-by: Rob Herring Link: https://lore.kernel.org/r/1570717560-7431-2-git-send-email-fabrizio.castro@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_can.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/can/rcar_can.txt b/Documentation/devicetree/bindings/net/can/rcar_can.txt index 19e4a7d91511..85c6551b602a 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_can.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_can.txt @@ -7,6 +7,7 @@ Required properties: "renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC. "renesas,can-r8a77470" if CAN controller is a part of R8A77470 SoC. "renesas,can-r8a774a1" if CAN controller is a part of R8A774A1 SoC. + "renesas,can-r8a774b1" if CAN controller is a part of R8A774B1 SoC. "renesas,can-r8a774c0" if CAN controller is a part of R8A774C0 SoC. "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC. "renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC. @@ -36,8 +37,8 @@ Required properties: - pinctrl-0: pin control group to be used for this controller. - pinctrl-names: must be "default". -Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, -R8A77990, and R8A77995: +Required properties for R8A774A1, R8A774B1, R8A774C0, R8A7795, R8A7796, +R8A77965, R8A77990, and R8A77995: For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can be used by both CAN and CAN FD controller at the same time. It needs to be scaled to maximum frequency if any of these controllers use it. This is done -- cgit v1.2.3 From 837b7deb364c3cf927f922d88b6131c8a4f81d0e Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Thu, 10 Oct 2019 15:25:59 +0100 Subject: dt-bindings: can: rcar_canfd: document r8a774b1 support Document the support for rcar_canfd on R8A774B1 SoC devices. Signed-off-by: Fabrizio Castro Acked-by: Rob Herring Link: https://lore.kernel.org/r/1570717560-7431-3-git-send-email-fabrizio.castro@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- Documentation/devicetree/bindings/net/can/rcar_canfd.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt index a901cd9be29e..13a4e34c0c73 100644 --- a/Documentation/devicetree/bindings/net/can/rcar_canfd.txt +++ b/Documentation/devicetree/bindings/net/can/rcar_canfd.txt @@ -5,6 +5,7 @@ Required properties: - compatible: Must contain one or more of the following: - "renesas,rcar-gen3-canfd" for R-Car Gen3 and RZ/G2 compatible controllers. - "renesas,r8a774a1-canfd" for R8A774A1 (RZ/G2M) compatible controller. + - "renesas,r8a774b1-canfd" for R8A774B1 (RZ/G2N) compatible controller. - "renesas,r8a774c0-canfd" for R8A774C0 (RZ/G2E) compatible controller. - "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller. - "renesas,r8a7796-canfd" for R8A7796 (R-Car M3-W) compatible controller. @@ -31,8 +32,8 @@ The name of the child nodes are "channel0" and "channel1" respectively. Each child node supports the "status" property only, which is used to enable/disable the respective channel. -Required properties for R8A774A1, R8A774C0, R8A7795, R8A7796, R8A77965, -R8A77990, and R8A77995: +Required properties for R8A774A1, R8A774B1, R8A774C0, R8A7795, R8A7796, +R8A77965, R8A77990, and R8A77995: In the denoted SoCs, canfd clock is a div6 clock and can be used by both CAN and CAN FD controller at the same time. It needs to be scaled to maximum frequency if any of these controllers use it. This is done using the below -- cgit v1.2.3 From d9b6867e8a17e3629e910e84f9c4bbe67d1cff3d Mon Sep 17 00:00:00 2001 From: Kamel Bouhara Date: Fri, 20 Dec 2019 11:38:34 +0100 Subject: dt-bindings: arm: at91: Document Kizboxmini and Smartkiz boards binding Document devicetree's bindings for the Overkiz's Kizbox Mini and Smartkiz boards, based on a SAM9G25 Atmel SoC. Signed-off-by: Kamel Bouhara Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191220103835.160154-1-kamel.bouhara@bootlin.com Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/arm/atmel-at91.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.yaml b/Documentation/devicetree/bindings/arm/atmel-at91.yaml index 7b512be280ce..3584f0ec263f 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.yaml +++ b/Documentation/devicetree/bindings/arm/atmel-at91.yaml @@ -35,6 +35,16 @@ properties: - atmel,at91sam9x60 - const: atmel,at91sam9 + - items: + - enum: + - overkiz,kizboxmini-base # Overkiz kizbox Mini Base Board + - overkiz,kizboxmini-mb # Overkiz kizbox Mini Mother Board + - overkiz,kizboxmini-rd # Overkiz kizbox Mini RailDIN + - overkiz,smartkiz # Overkiz SmartKiz Board + - const: atmel,at91sam9g25 + - const: atmel,at91sam9x5 + - const: atmel,at91sam9 + - items: - enum: - atmel,at91sam9g15 -- cgit v1.2.3 From 4a58009c1768f58d36e8f6b62f47ea1a30542c45 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Wed, 18 Dec 2019 18:52:14 +0530 Subject: dt-bindings: remoteproc: qcom: Add ADSP and SLPI support for MSM8998 SoC Add ADSP and SLPI compatibles for MSM8998 SoC. Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20191218132217.28141-3-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt index a54465d938f6..9938918b2fea 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt @@ -10,6 +10,8 @@ on the Qualcomm ADSP Hexagon core. "qcom,msm8974-adsp-pil" "qcom,msm8996-adsp-pil" "qcom,msm8996-slpi-pil" + "qcom,msm8998-adsp-pas" + "qcom,msm8998-slpi-pas" "qcom,qcs404-adsp-pas" "qcom,qcs404-cdsp-pas" "qcom,qcs404-wcss-pas" @@ -33,6 +35,8 @@ on the Qualcomm ADSP Hexagon core. qcom,msm8974-adsp-pil: qcom,msm8996-adsp-pil: qcom,msm8996-slpi-pil: + qcom,msm8998-adsp-pas: + qcom,msm8998-slpi-pas: qcom,qcs404-adsp-pas: qcom,qcs404-cdsp-pas: qcom,sdm845-adsp-pas: @@ -86,9 +90,12 @@ on the Qualcomm ADSP Hexagon core. Definition: The power-domains needed depend on the compatible string: qcom,msm8974-adsp-pil: qcom,msm8996-adsp-pil: + qcom,msm8998-adsp-pas: must be "cx" qcom,msm8996-slpi-pil: must be "ss_cx" + qcom,msm8998-slpi-pas: + must be "ssc_cx" qcom,qcs404-adsp-pas: must be "lpi_cx" qcom,qcs404-cdsp-pas: -- cgit v1.2.3 From 65518e9cf5992f88eb43a3183dd82a6e55ae7f11 Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Thu, 19 Dec 2019 11:15:05 +0530 Subject: dt-bindings: remoteproc: qcom: Add Q6V5 Modem PIL binding for SC7180 Add a new modem compatible string for Qualcomm SC7180 SoCs and introduce the "qcom,halt-nav-regs" bindings needed by the modem sub-system running on SC7180 SoCs. Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20191219054506.20565-2-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/qcom,q6v5.txt | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt index c416746f93cf..88dfa3fc15f7 100644 --- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt +++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt @@ -13,6 +13,7 @@ on the Qualcomm Hexagon core. "qcom,msm8974-mss-pil" "qcom,msm8996-mss-pil" "qcom,msm8998-mss-pil" + "qcom,sc7180-mss-pil" "qcom,sdm845-mss-pil" - reg: @@ -43,6 +44,7 @@ on the Qualcomm Hexagon core. must be "wdog", "fatal", "ready", "handover", "stop-ack" qcom,msm8996-mss-pil: qcom,msm8998-mss-pil: + qcom,sc7180-mss-pil: qcom,sdm845-mss-pil: must be "wdog", "fatal", "ready", "handover", "stop-ack", "shutdown-ack" @@ -75,6 +77,9 @@ on the Qualcomm Hexagon core. qcom,msm8998-mss-pil: must be "iface", "bus", "mem", "xo", "gpll0_mss", "snoc_axi", "mnoc_axi", "qdss" + qcom,sc7180-mss-pil: + must be "iface", "bus", "xo", "snoc_axi", "mnoc_axi", + "mss_crypto", "mss_nav", "nav" qcom,sdm845-mss-pil: must be "iface", "bus", "mem", "xo", "gpll0_mss", "snoc_axi", "mnoc_axi", "prng" @@ -86,7 +91,7 @@ on the Qualcomm Hexagon core. reference to the list of 3 reset-controllers for the wcss sub-system reference to the list of 2 reset-controllers for the modem - sub-system on SDM845 SoCs + sub-system on SC7180, SDM845 SoCs - reset-names: Usage: required @@ -95,7 +100,7 @@ on the Qualcomm Hexagon core. must be "wcss_aon_reset", "wcss_reset", "wcss_q6_reset" for the wcss sub-system must be "mss_restart", "pdc_reset" for the modem - sub-system on SDM845 SoCs + sub-system on SC7180, SDM845 SoCs For the compatible strings below the following supplies are required: "qcom,q6v5-pil" @@ -144,6 +149,7 @@ For the compatible string below the following supplies are required: qcom,msm8996-mss-pil: qcom,msm8998-mss-pil: must be "cx", "mx" + qcom,sc7180-mss-pil: qcom,sdm845-mss-pil: must be "cx", "mx", "mss", "load_state" @@ -165,6 +171,19 @@ For the compatible string below the following supplies are required: by the three offsets within syscon for q6, modem and nc halt registers. +For the compatible strings below the following phandle references are required: + "qcom,sc7180-mss-pil" +- qcom,halt-nav-regs: + Usage: required + Value type: + Definition: reference to a list of 2 phandles with one offset each for + the modem sub-system running on SC7180 SoC. The first + phandle reference is to the mss clock node followed by the + offset within register space for nav halt register. The + second phandle reference is to a syscon representing TCSR + followed by the offset within syscon for conn_box_spare0 + register. + = SUBNODES: The Hexagon node must contain two subnodes, named "mba" and "mpss" representing the memory regions used by the Hexagon firmware. Each sub-node must contain: -- cgit v1.2.3 From 606f53b0880255bc476c797c4d92736ff4acf685 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Thu, 21 Nov 2019 09:43:16 +0100 Subject: dt-bindings: watchdog: Convert stm32 watchdog bindings to json-schema Convert the STM32 watchdog binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../devicetree/bindings/watchdog/st,stm32-iwdg.txt | 26 ---------- .../bindings/watchdog/st,stm32-iwdg.yaml | 57 ++++++++++++++++++++++ 2 files changed, 57 insertions(+), 26 deletions(-) delete mode 100644 Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt create mode 100644 Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt deleted file mode 100644 index d8f4430b0a13..000000000000 --- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt +++ /dev/null @@ -1,26 +0,0 @@ -STM32 Independent WatchDoG (IWDG) ---------------------------------- - -Required properties: -- compatible: Should be either: - - "st,stm32-iwdg" - - "st,stm32mp1-iwdg" -- reg: Physical base address and length of the registers set for the device -- clocks: Reference to the clock entry lsi. Additional pclk clock entry - is required only for st,stm32mp1-iwdg. -- clock-names: Name of the clocks used. - "lsi" for st,stm32-iwdg - "lsi", "pclk" for st,stm32mp1-iwdg - -Optional Properties: -- timeout-sec: Watchdog timeout value in seconds. - -Example: - -iwdg: watchdog@40003000 { - compatible = "st,stm32-iwdg"; - reg = <0x40003000 0x400>; - clocks = <&clk_lsi>; - clock-names = "lsi"; - timeout-sec = <32>; -}; diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml new file mode 100644 index 000000000000..a27c504e2e4f --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/st,stm32-iwdg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Independent WatchDoG (IWDG) bindings + +maintainers: + - Yannick Fertre + - Christophe Roullier + +allOf: + - $ref: "watchdog.yaml#" + +properties: + compatible: + enum: + - st,stm32-iwdg + - st,stm32mp1-iwdg + + reg: + maxItems: 1 + + clocks: + items: + - description: Low speed clock + - description: Optional peripheral clock + minItems: 1 + maxItems: 2 + + clock-names: + items: + enum: + - lsi + - pclk + minItems: 1 + maxItems: 2 + +required: + - compatible + - reg + - clocks + - clock-names + +examples: + - | + #include + watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + timeout-sec = <32>; + }; + +... -- cgit v1.2.3 From 58361eaa11d561f338e45558c4cfce03366817c8 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Wed, 11 Dec 2019 18:13:00 +0100 Subject: dt-bindings: media: renesas,ceu: Convert to yaml Convert the Renesas CEU bindings description to yaml schema and remove the existing textual bindings document. Signed-off-by: Jacopo Mondi Signed-off-by: Rob Herring --- .../devicetree/bindings/media/renesas,ceu.txt | 86 ---------------------- .../devicetree/bindings/media/renesas,ceu.yaml | 78 ++++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 79 insertions(+), 87 deletions(-) delete mode 100644 Documentation/devicetree/bindings/media/renesas,ceu.txt create mode 100644 Documentation/devicetree/bindings/media/renesas,ceu.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/renesas,ceu.txt b/Documentation/devicetree/bindings/media/renesas,ceu.txt deleted file mode 100644 index 3e2a2652eb19..000000000000 --- a/Documentation/devicetree/bindings/media/renesas,ceu.txt +++ /dev/null @@ -1,86 +0,0 @@ -Renesas Capture Engine Unit (CEU) ----------------------------------------------- - -The Capture Engine Unit is the image capture interface found in the Renesas -SH Mobile, R-Mobile and RZ SoCs. - -The interface supports a single parallel input with data bus width of 8 or 16 -bits. - -Required properties: -- compatible: Shall be one of the following values: - "renesas,r7s72100-ceu" for CEU units found in RZ/A1H and RZ/A1M SoCs - "renesas,r8a7740-ceu" for CEU units found in R-Mobile A1 R8A7740 SoCs -- reg: Registers address base and size. -- interrupts: The interrupt specifier. - -The CEU supports a single parallel input and should contain a single 'port' -subnode with a single 'endpoint'. Connection to input devices are modeled -according to the video interfaces OF bindings specified in: -[1] Documentation/devicetree/bindings/media/video-interfaces.txt - -Optional endpoint properties applicable to parallel input bus described in -the above mentioned "video-interfaces.txt" file are supported. - -- hsync-active: See [1] for description. If property is not present, - default is active high. -- vsync-active: See [1] for description. If property is not present, - default is active high. -- bus-width: See [1] for description. Accepted values are '8' and '16'. - If property is not present, default is '8'. -- field-even-active: See [1] for description. If property is not present, - an even field is identified by a logic 0 (active-low signal). - -Example: - -The example describes the connection between the Capture Engine Unit and an -OV7670 image sensor connected to i2c1 interface. - -ceu: ceu@e8210000 { - reg = <0xe8210000 0x209c>; - compatible = "renesas,r7s72100-ceu"; - interrupts = ; - - pinctrl-names = "default"; - pinctrl-0 = <&vio_pins>; - - status = "okay"; - - port { - ceu_in: endpoint { - remote-endpoint = <&ov7670_out>; - - hsync-active = <1>; - vsync-active = <0>; - }; - }; -}; - -i2c1: i2c@fcfee400 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; - - status = "okay"; - - clock-frequency = <100000>; - - ov7670: camera@21 { - compatible = "ovti,ov7670"; - reg = <0x21>; - - pinctrl-names = "default"; - pinctrl-0 = <&vio_pins>; - - reset-gpios = <&port3 11 GPIO_ACTIVE_LOW>; - powerdown-gpios = <&port3 12 GPIO_ACTIVE_HIGH>; - - port { - ov7670_out: endpoint { - remote-endpoint = <&ceu_in>; - - hsync-active = <1>; - vsync-active = <0>; - }; - }; - }; -}; diff --git a/Documentation/devicetree/bindings/media/renesas,ceu.yaml b/Documentation/devicetree/bindings/media/renesas,ceu.yaml new file mode 100644 index 000000000000..8e9251a0f9ef --- /dev/null +++ b/Documentation/devicetree/bindings/media/renesas,ceu.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/renesas,ceu.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas Capture Engine Unit (CEU) Bindings + +maintainers: + - Jacopo Mondi + - linux-renesas-soc@vger.kernel.org + +description: |+ + The Capture Engine Unit is the image capture interface found in the Renesas SH + Mobile, R-Mobile and RZ SoCs. The interface supports a single parallel input + with data bus width of 8 or 16 bits. + +properties: + compatible: + enum: + - renesas,r7s72100-ceu + - renesas,r8a7740-ceu + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + port: + type: object + additionalProperties: false + + properties: + endpoint: + type: object + additionalProperties: false + + # Properties described in + # Documentation/devicetree/bindings/media/video-interfaces.txt + properties: + remote-endpoint: true + hsync-active: true + vsync-active: true + field-even-active: false + bus-width: + enum: [8, 16] + default: 8 + + required: + - remote-endpoint + + required: + - endpoint + +required: + - compatible + - reg + - interrupts + - port + +examples: + - | + #include + + ceu: ceu@e8210000 { + reg = <0xe8210000 0x209c>; + compatible = "renesas,r7s72100-ceu"; + interrupts = ; + + port { + ceu_in: endpoint { + remote-endpoint = <&ov7670_out>; + hsync-active = <1>; + vsync-active = <0>; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index cc0a4a8ae06a..111340d7583f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10277,7 +10277,7 @@ L: linux-media@vger.kernel.org L: linux-renesas-soc@vger.kernel.org T: git git://linuxtv.org/media_tree.git S: Supported -F: Documentation/devicetree/bindings/media/renesas,ceu.txt +F: Documentation/devicetree/bindings/media/renesas,ceu.yaml F: drivers/media/platform/renesas-ceu.c F: include/media/drv-intf/renesas-ceu.h -- cgit v1.2.3 From dba261f35d16a8e4b70962d0f8391290510a8201 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Wed, 18 Dec 2019 09:02:12 +0100 Subject: dt-bindings: net: dsa: qca, ar9331 switch documentation Atheros AR9331 has built-in 5 port switch. The switch can be configured to use all 5 or 4 ports. One of built-in PHYs can be used by first built-in ethernet controller or to be used directly by the switch over second ethernet controller. Signed-off-by: Oleksij Rempel Signed-off-by: David S. Miller --- .../devicetree/bindings/net/dsa/ar9331.txt | 148 +++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/dsa/ar9331.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/dsa/ar9331.txt b/Documentation/devicetree/bindings/net/dsa/ar9331.txt new file mode 100644 index 000000000000..320607cbbb17 --- /dev/null +++ b/Documentation/devicetree/bindings/net/dsa/ar9331.txt @@ -0,0 +1,148 @@ +Atheros AR9331 built-in switch +============================= + +It is a switch built-in to Atheros AR9331 WiSoC and addressable over internal +MDIO bus. All PHYs are built-in as well. + +Required properties: + + - compatible: should be: "qca,ar9331-switch" + - reg: Address on the MII bus for the switch. + - resets : Must contain an entry for each entry in reset-names. + - reset-names : Must include the following entries: "switch" + - interrupt-parent: Phandle to the parent interrupt controller + - interrupts: IRQ line for the switch + - interrupt-controller: Indicates the switch is itself an interrupt + controller. This is used for the PHY interrupts. + - #interrupt-cells: must be 1 + - mdio: Container of PHY and devices on the switches MDIO bus. + +See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional +required and optional properties. +Examples: + +eth0: ethernet@19000000 { + compatible = "qca,ar9330-eth"; + reg = <0x19000000 0x200>; + interrupts = <4>; + + resets = <&rst 9>, <&rst 22>; + reset-names = "mac", "mdio"; + clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>; + clock-names = "eth", "mdio"; + + phy-mode = "mii"; + phy-handle = <&phy_port4>; +}; + +eth1: ethernet@1a000000 { + compatible = "qca,ar9330-eth"; + reg = <0x1a000000 0x200>; + interrupts = <5>; + resets = <&rst 13>, <&rst 23>; + reset-names = "mac", "mdio"; + clocks = <&pll ATH79_CLK_AHB>, <&pll ATH79_CLK_AHB>; + clock-names = "eth", "mdio"; + + phy-mode = "gmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + switch10: switch@10 { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qca,ar9331-switch"; + reg = <0x10>; + resets = <&rst 8>; + reset-names = "switch"; + + interrupt-parent = <&miscintc>; + interrupts = <12>; + + interrupt-controller; + #interrupt-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + switch_port0: port@0 { + reg = <0x0>; + label = "cpu"; + ethernet = <ð1>; + + phy-mode = "gmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + switch_port1: port@1 { + reg = <0x1>; + phy-handle = <&phy_port0>; + phy-mode = "internal"; + }; + + switch_port2: port@2 { + reg = <0x2>; + phy-handle = <&phy_port1>; + phy-mode = "internal"; + }; + + switch_port3: port@3 { + reg = <0x3>; + phy-handle = <&phy_port2>; + phy-mode = "internal"; + }; + + switch_port4: port@4 { + reg = <0x4>; + phy-handle = <&phy_port3>; + phy-mode = "internal"; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&switch10>; + + phy_port0: phy@0 { + reg = <0x0>; + interrupts = <0>; + }; + + phy_port1: phy@1 { + reg = <0x1>; + interrupts = <0>; + }; + + phy_port2: phy@2 { + reg = <0x2>; + interrupts = <0>; + }; + + phy_port3: phy@3 { + reg = <0x3>; + interrupts = <0>; + }; + + phy_port4: phy@4 { + reg = <0x4>; + interrupts = <0>; + }; + }; + }; + }; +}; -- cgit v1.2.3 From dc753369d12985c152f06331ce2e5e74f3337c59 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Mon, 16 Dec 2019 23:17:08 +0530 Subject: dt-bindings: arm: rockchip: Add Rock Pi N10 binding Rock Pi N10 is a Rockchip RK3399Pro based SBC, which has - VMARC RK3399Pro SOM (as per SMARC standard) from Vamrs. - Compatible carrier board from Radxa. VMARC RK3399Pro SOM need to mount on top of dalang carrier board for making Rock PI N10 SBC. Add dt-bindings for it. Signed-off-by: Jagan Teki Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191216174711.17856-2-jagan@amarulasolutions.com Signed-off-by: Heiko Stuebner --- Documentation/devicetree/bindings/arm/rockchip.yaml | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml index 86307c66b4bd..874b0eaa2a75 100644 --- a/Documentation/devicetree/bindings/arm/rockchip.yaml +++ b/Documentation/devicetree/bindings/arm/rockchip.yaml @@ -425,6 +425,12 @@ properties: - const: radxa,rockpi4 - const: rockchip,rk3399 + - description: Radxa ROCK Pi N10 + items: + - const: radxa,rockpi-n10 + - const: vamrs,rk3399pro-vmarc-som + - const: rockchip,rk3399pro + - description: Radxa Rock2 Square items: - const: radxa,rock2-square -- cgit v1.2.3 From 6bcf76316a146347ba4b72d0c34de631725d3b39 Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Mon, 16 Dec 2019 09:32:59 -0500 Subject: dt-bindings: mfd: update TI tps6105x chip bindings The driver has been extended to optionally get its operational mode, regulator init data and LED naming from the devicetree. Acked-by: Jacek Anaszewski Reviewed-by: Rob Herring Signed-off-by: Sven Van Asbroeck Signed-off-by: Pavel Machek --- Documentation/devicetree/bindings/mfd/tps6105x.txt | 47 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mfd/tps6105x.txt b/Documentation/devicetree/bindings/mfd/tps6105x.txt index 93602c7a19c8..dc448a9d5b4d 100644 --- a/Documentation/devicetree/bindings/mfd/tps6105x.txt +++ b/Documentation/devicetree/bindings/mfd/tps6105x.txt @@ -7,11 +7,56 @@ Required properties: - compatible: "ti,tps61050" or "ti,tps61052" - reg: Specifies the I2C slave address -Example: +Optional sub-node: + +This subnode selects the chip's operational mode. +There can be at most one single available subnode. + +- regulator: presence of this sub-node puts the chip in regulator mode. + see ../regulator/regulator.yaml + +- led: presence of this sub-node puts the chip in led mode. + Optional properties: + - function : see ../leds/common.txt + - color : see ../leds/common.txt + - label : see ../leds/common.txt + (deprecated) + +Example (GPIO operation only): + +i2c0 { + tps61052@33 { + compatible = "ti,tps61052"; + reg = <0x33>; + }; +}; + +Example (GPIO + regulator operation): i2c0 { tps61052@33 { compatible = "ti,tps61052"; reg = <0x33>; + + regulator { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + }; +}; + +Example (GPIO + led operation): + +#include + +i2c0 { + tps61052@33 { + compatible = "ti,tps61052"; + reg = <0x33>; + + led { + color = ; + }; }; }; -- cgit v1.2.3 From 031c8cd8bd24e716162aadeacda83f7c506144f8 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Mon, 2 Dec 2019 21:47:47 +0100 Subject: media: dt-bindings: media: fsl-pxp: add missing imx6sll i.MX6SLL also has a pxp, so mention it among others in the bindings doc. Signed-off-by: Andreas Kemnade Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/media/fsl-pxp.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/fsl-pxp.txt b/Documentation/devicetree/bindings/media/fsl-pxp.txt index 2477e7f87381..f8090e06530d 100644 --- a/Documentation/devicetree/bindings/media/fsl-pxp.txt +++ b/Documentation/devicetree/bindings/media/fsl-pxp.txt @@ -8,7 +8,7 @@ i.MX SoCs from i.MX23 to i.MX7. Required properties: - compatible: should be "fsl,-pxp", where SoC can be one of imx23, imx28, - imx6dl, imx6sl, imx6ul, imx6sx, imx6ull, or imx7d. + imx6dl, imx6sl, imx6sll, imx6ul, imx6sx, imx6ull, or imx7d. - reg: the register base and size for the device registers - interrupts: the PXP interrupt, two interrupts for imx6ull and imx7d. - clock-names: should be "axi" -- cgit v1.2.3 From 5f131c4848834a86343918ba502fce2d07b757ae Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 23 Dec 2019 10:48:58 +0800 Subject: bindings: fsl: document compatibles of lx2160a boards The lx2160a board compatibles "fsl,lx2160a-qds" and "fsl,lx2160a-rdb" have been in use. Let's document them. Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index 6f241a3b5a20..ee538f3a7f4d 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -389,6 +389,13 @@ properties: - fsl,ls2088a-rdb - const: fsl,ls2088a + - description: LX2160A based Boards + items: + - enum: + - fsl,lx2160a-qds + - fsl,lx2160a-rdb + - const: fsl,lx2160a + - description: S32V234 based Boards items: - enum: -- cgit v1.2.3 From a59666337f3b7c5c8721ce2d03c622bbe211aae5 Mon Sep 17 00:00:00 2001 From: Marco Antonio Franchi Date: Tue, 17 Dec 2019 13:36:14 +0000 Subject: dt-bindings: arm: Add Google Coral Edge TPU entry Add Google Coral Edge TPU, named as imx8mq-phanbell, to the imx8mq supported devices. Signed-off-by: Marco Franchi Reviewed-by: Fabio Estevam Acked-by: Rob Herring Signed-off-by: Shawn Guo --- Documentation/devicetree/bindings/arm/fsl.yaml | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml index ee538f3a7f4d..cdf8d037bfd9 100644 --- a/Documentation/devicetree/bindings/arm/fsl.yaml +++ b/Documentation/devicetree/bindings/arm/fsl.yaml @@ -288,6 +288,7 @@ properties: - enum: - boundary,imx8mq-nitrogen8m # i.MX8MQ NITROGEN Board - fsl,imx8mq-evk # i.MX8MQ EVK Board + - google,imx8mq-phanbell # Google Coral Edge TPU - purism,librem5-devkit # Purism Librem5 devkit - solidrun,hummingboard-pulse # SolidRun Hummingboard Pulse - technexion,pico-pi-imx8m # TechNexion PICO-PI-8M evk -- cgit v1.2.3 From b98900548b8db965990691716c117b738eaa9d5a Mon Sep 17 00:00:00 2001 From: "周琰杰 (Zhou Yanjie)" Date: Tue, 17 Dec 2019 21:58:59 +0800 Subject: dt-bindings: dmaengine: Add X1830 bindings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the dmaengine bindings for the X1830 Soc from Ingenic. Signed-off-by: 周琰杰 (Zhou Yanjie) Link: https://lore.kernel.org/r/1576591140-125668-3-git-send-email-zhouyanjie@wanyeetech.com Signed-off-by: Vinod Koul --- .../devicetree/bindings/dma/jz4780-dma.txt | 6 ++-- include/dt-bindings/dma/x1830-dma.h | 39 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 include/dt-bindings/dma/x1830-dma.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/dma/jz4780-dma.txt b/Documentation/devicetree/bindings/dma/jz4780-dma.txt index ec89782d9498..3459e77be294 100644 --- a/Documentation/devicetree/bindings/dma/jz4780-dma.txt +++ b/Documentation/devicetree/bindings/dma/jz4780-dma.txt @@ -1,4 +1,4 @@ -* Ingenic JZ4780 DMA Controller +* Ingenic XBurst DMA Controller Required properties: @@ -8,10 +8,12 @@ Required properties: * ingenic,jz4770-dma * ingenic,jz4780-dma * ingenic,x1000-dma + * ingenic,x1830-dma - reg: Should contain the DMA channel registers location and length, followed by the DMA controller registers location and length. - interrupts: Should contain the interrupt specifier of the DMA controller. -- clocks: Should contain a clock specifier for the JZ4780/X1000 PDMA clock. +- clocks: Should contain a clock specifier for the JZ4780/X1000/X1830 PDMA + clock. - #dma-cells: Must be <2>. Number of integer cells in the dmas property of DMA clients (see below). diff --git a/include/dt-bindings/dma/x1830-dma.h b/include/dt-bindings/dma/x1830-dma.h new file mode 100644 index 000000000000..35bcb8966ea4 --- /dev/null +++ b/include/dt-bindings/dma/x1830-dma.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * This header provides macros for X1830 DMA bindings. + * + * Copyright (c) 2019 周琰杰 (Zhou Yanjie) + */ + +#ifndef __DT_BINDINGS_DMA_X1830_DMA_H__ +#define __DT_BINDINGS_DMA_X1830_DMA_H__ + +/* + * Request type numbers for the X1830 DMA controller (written to the DRTn + * register for the channel). + */ +#define X1830_DMA_I2S0_TX 0x6 +#define X1830_DMA_I2S0_RX 0x7 +#define X1830_DMA_AUTO 0x8 +#define X1830_DMA_SADC_RX 0x9 +#define X1830_DMA_UART1_TX 0x12 +#define X1830_DMA_UART1_RX 0x13 +#define X1830_DMA_UART0_TX 0x14 +#define X1830_DMA_UART0_RX 0x15 +#define X1830_DMA_SSI0_TX 0x16 +#define X1830_DMA_SSI0_RX 0x17 +#define X1830_DMA_SSI1_TX 0x18 +#define X1830_DMA_SSI1_RX 0x19 +#define X1830_DMA_MSC0_TX 0x1a +#define X1830_DMA_MSC0_RX 0x1b +#define X1830_DMA_MSC1_TX 0x1c +#define X1830_DMA_MSC1_RX 0x1d +#define X1830_DMA_DMIC_RX 0x21 +#define X1830_DMA_SMB0_TX 0x24 +#define X1830_DMA_SMB0_RX 0x25 +#define X1830_DMA_SMB1_TX 0x26 +#define X1830_DMA_SMB1_RX 0x27 +#define X1830_DMA_DES_TX 0x2e +#define X1830_DMA_DES_RX 0x2f + +#endif /* __DT_BINDINGS_DMA_X1830_DMA_H__ */ -- cgit v1.2.3 From 5d28e44ba6302a1bf8bd66d9ae4be9e377188ff7 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 15 Nov 2019 15:34:03 +0530 Subject: dt-bindings: clock: Add YAML schemas for the QCOM DISPCC clock bindings The DISPCC clock provider have a bunch of generic properties that are needed in a device tree. Add a YAML schemas for those. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/1573812245-23827-2-git-send-email-tdas@codeaurora.org Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,dispcc.txt | 19 ------- .../devicetree/bindings/clock/qcom,dispcc.yaml | 66 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 19 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,dispcc.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,dispcc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc.txt b/Documentation/devicetree/bindings/clock/qcom,dispcc.txt deleted file mode 100644 index d639e18d0b85..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,dispcc.txt +++ /dev/null @@ -1,19 +0,0 @@ -Qualcomm Technologies, Inc. Display Clock Controller Binding ------------------------------------------------------------- - -Required properties : - -- compatible : shall contain "qcom,sdm845-dispcc" -- reg : shall contain base register location and length. -- #clock-cells : from common clock binding, shall contain 1. -- #reset-cells : from common reset binding, shall contain 1. -- #power-domain-cells : from generic power domain binding, shall contain 1. - -Example: - dispcc: clock-controller@af00000 { - compatible = "qcom,sdm845-dispcc"; - reg = <0xaf00000 0x100000>; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml new file mode 100644 index 000000000000..1185e49abf2d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/qcom,dispcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Display Clock & Reset Controller Binding + +maintainers: + - Taniya Das + +description: | + Qualcomm display clock control module which supports the clocks, resets and + power domains. + +properties: + compatible: + enum: + - qcom,sdm845-dispcc + + clocks: + minItems: 1 + maxItems: 2 + items: + - description: Board XO source + - description: GPLL0 source from GCC + + clock-names: + items: + - const: xo + - const: gpll0 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +examples: + # Example of DISPCC with clock node properties for SDM845: + - | + clock-controller@af00000 { + compatible = "qcom,sdm845-dispcc"; + reg = <0xaf00000 0x10000>; + clocks = <&rpmhcc 0>, <&gcc 24>; + clock-names = "xo", "gpll0"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... -- cgit v1.2.3 From 75616da71291ad37b7a46c9703c0b4206ef346ec Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 15 Nov 2019 15:34:04 +0530 Subject: dt-bindings: clock: Introduce QCOM sc7180 display clock bindings Add device tree bindings for display clock controller for Qualcomm Technology Inc's SC7180 SoCs. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/1573812245-23827-3-git-send-email-tdas@codeaurora.org Reviewed-by: Rob Herring [sboyd@kernel.org: Add sc7180 to subject] Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,dispcc.yaml | 1 + include/dt-bindings/clock/qcom,dispcc-sc7180.h | 46 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,dispcc-sc7180.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml index 1185e49abf2d..9c58e02a1de1 100644 --- a/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc.yaml @@ -16,6 +16,7 @@ description: | properties: compatible: enum: + - qcom,sc7180-dispcc - qcom,sdm845-dispcc clocks: diff --git a/include/dt-bindings/clock/qcom,dispcc-sc7180.h b/include/dt-bindings/clock/qcom,dispcc-sc7180.h new file mode 100644 index 000000000000..b9b51617a335 --- /dev/null +++ b/include/dt-bindings/clock/qcom,dispcc-sc7180.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_DISP_CC_SC7180_H +#define _DT_BINDINGS_CLK_QCOM_DISP_CC_SC7180_H + +#define DISP_CC_PLL0 0 +#define DISP_CC_PLL0_OUT_EVEN 1 +#define DISP_CC_MDSS_AHB_CLK 2 +#define DISP_CC_MDSS_AHB_CLK_SRC 3 +#define DISP_CC_MDSS_BYTE0_CLK 4 +#define DISP_CC_MDSS_BYTE0_CLK_SRC 5 +#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 6 +#define DISP_CC_MDSS_BYTE0_INTF_CLK 7 +#define DISP_CC_MDSS_DP_AUX_CLK 8 +#define DISP_CC_MDSS_DP_AUX_CLK_SRC 9 +#define DISP_CC_MDSS_DP_CRYPTO_CLK 10 +#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC 11 +#define DISP_CC_MDSS_DP_LINK_CLK 12 +#define DISP_CC_MDSS_DP_LINK_CLK_SRC 13 +#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC 14 +#define DISP_CC_MDSS_DP_LINK_INTF_CLK 15 +#define DISP_CC_MDSS_DP_PIXEL_CLK 16 +#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC 17 +#define DISP_CC_MDSS_ESC0_CLK 18 +#define DISP_CC_MDSS_ESC0_CLK_SRC 19 +#define DISP_CC_MDSS_MDP_CLK 20 +#define DISP_CC_MDSS_MDP_CLK_SRC 21 +#define DISP_CC_MDSS_MDP_LUT_CLK 22 +#define DISP_CC_MDSS_NON_GDSC_AHB_CLK 23 +#define DISP_CC_MDSS_PCLK0_CLK 24 +#define DISP_CC_MDSS_PCLK0_CLK_SRC 25 +#define DISP_CC_MDSS_ROT_CLK 26 +#define DISP_CC_MDSS_ROT_CLK_SRC 27 +#define DISP_CC_MDSS_RSCC_AHB_CLK 28 +#define DISP_CC_MDSS_RSCC_VSYNC_CLK 29 +#define DISP_CC_MDSS_VSYNC_CLK 30 +#define DISP_CC_MDSS_VSYNC_CLK_SRC 31 +#define DISP_CC_XO_CLK 32 + +/* DISP_CC GDSCR */ +#define MDSS_GDSC 0 + +#endif -- cgit v1.2.3 From afd36d28e4126342d7151d5f7e4a875ad2ace9f9 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 13 Dec 2019 19:00:18 +0100 Subject: dt-bindings: phy: Fix the PX30 DSI PHY compatible in the example Use the upstream compatible instead of the BSP one in the example section of the DT bindings for this IP. Fixes: 3817c7961179 ("dt-bindings: phy: add yaml binding for rockchip,px30-dsi-dphy") Signed-off-by: Miquel Raynal Reviewed-by: Heiko Stuebner Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml b/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml index bb0da87bcd84..6a2ed4ef5aac 100644 --- a/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml +++ b/Documentation/devicetree/bindings/phy/rockchip,px30-dsi-dphy.yaml @@ -62,7 +62,7 @@ additionalProperties: false examples: - | dsi_dphy: phy@ff2e0000 { - compatible = "rockchip,px30-video-phy"; + compatible = "rockchip,px30-dsi-dphy"; reg = <0x0 0xff2e0000 0x0 0x10000>; clocks = <&pmucru 13>, <&cru 12>; clock-names = "ref", "pclk"; -- cgit v1.2.3 From b30d8cf5e1717b3498056833d24971d9977bf3ab Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 19 Dec 2019 09:46:23 +0100 Subject: dt-bindings: opp: Convert Allwinner H6 OPP to a schema The Allwinner H6 SoCs use binning in order to provide binning to cpufreq which is supported in Linux, with a matching Device Tree binding. Now that we have the DT validation in place, let's convert the device tree bindings for that controller over to a YAML schemas. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../opp/allwinner,sun50i-h6-operating-points.yaml | 129 ++++++++++++++++ .../bindings/opp/sun50i-nvmem-cpufreq.txt | 167 --------------------- 2 files changed, 129 insertions(+), 167 deletions(-) create mode 100644 Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml delete mode 100644 Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml b/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml new file mode 100644 index 000000000000..aef87a33a7c9 --- /dev/null +++ b/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml @@ -0,0 +1,129 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/opp/allwinner,sun50i-h6-operating-points.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner H6 CPU OPP Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +description: | + For some SoCs, the CPU frequency subset and voltage value of each + OPP varies based on the silicon variant in use. Allwinner Process + Voltage Scaling Tables defines the voltage and frequency value based + on the speedbin blown in the efuse combination. The + sun50i-cpufreq-nvmem driver reads the efuse value from the SoC to + provide the OPP framework with required information. + +properties: + compatible: + const: allwinner,sun50i-h6-operating-points + + nvmem-cells: + description: | + A phandle pointing to a nvmem-cells node representing the efuse + registers that has information about the speedbin that is used + to select the right frequency/voltage value pair. Please refer + the for nvmem-cells bindings + Documentation/devicetree/bindings/nvmem/nvmem.txt and also + examples below. + +required: + - compatible + - nvmem-cells + +patternProperties: + "opp-[0-9]+": + type: object + + properties: + opp-hz: true + + patternProperties: + "opp-microvolt-.*": true + + required: + - opp-hz + - opp-microvolt-speed0 + - opp-microvolt-speed1 + - opp-microvolt-speed2 + + unevaluatedProperties: false + +unevaluatedProperties: false + +examples: + - | + cpu_opp_table: opp-table { + compatible = "allwinner,sun50i-h6-operating-points"; + nvmem-cells = <&speedbin_efuse>; + opp-shared; + + opp-480000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <480000000>; + + opp-microvolt-speed0 = <880000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp-720000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <720000000>; + + opp-microvolt-speed0 = <880000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp-816000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <816000000>; + + opp-microvolt-speed0 = <880000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp-888000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <888000000>; + + opp-microvolt-speed0 = <940000>; + opp-microvolt-speed1 = <820000>; + opp-microvolt-speed2 = <800000>; + }; + + opp-1080000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1080000000>; + + opp-microvolt-speed0 = <1060000>; + opp-microvolt-speed1 = <880000>; + opp-microvolt-speed2 = <840000>; + }; + + opp-1320000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1320000000>; + + opp-microvolt-speed0 = <1160000>; + opp-microvolt-speed1 = <940000>; + opp-microvolt-speed2 = <900000>; + }; + + opp-1488000000 { + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1488000000>; + + opp-microvolt-speed0 = <1160000>; + opp-microvolt-speed1 = <1000000>; + opp-microvolt-speed2 = <960000>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt b/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt deleted file mode 100644 index 7deae57a587b..000000000000 --- a/Documentation/devicetree/bindings/opp/sun50i-nvmem-cpufreq.txt +++ /dev/null @@ -1,167 +0,0 @@ -Allwinner Technologies, Inc. NVMEM CPUFreq and OPP bindings -=================================== - -For some SoCs, the CPU frequency subset and voltage value of each OPP -varies based on the silicon variant in use. Allwinner Process Voltage -Scaling Tables defines the voltage and frequency value based on the -speedbin blown in the efuse combination. The sun50i-cpufreq-nvmem driver -reads the efuse value from the SoC to provide the OPP framework with -required information. - -Required properties: --------------------- -In 'cpus' nodes: -- operating-points-v2: Phandle to the operating-points-v2 table to use. - -In 'operating-points-v2' table: -- compatible: Should be - - 'allwinner,sun50i-h6-operating-points'. -- nvmem-cells: A phandle pointing to a nvmem-cells node representing the - efuse registers that has information about the speedbin - that is used to select the right frequency/voltage value - pair. Please refer the for nvmem-cells bindings - Documentation/devicetree/bindings/nvmem/nvmem.txt and - also examples below. - -In every OPP node: -- opp-microvolt-: Voltage in micro Volts. - At runtime, the platform can pick a and - matching opp-microvolt- property. - [See: opp.txt] - HW: : - sun50i-h6 speed0 speed1 speed2 - -Example 1: ---------- - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - compatible = "arm,cortex-a53"; - device_type = "cpu"; - reg = <0>; - enable-method = "psci"; - clocks = <&ccu CLK_CPUX>; - clock-latency-ns = <244144>; /* 8 32k periods */ - operating-points-v2 = <&cpu_opp_table>; - #cooling-cells = <2>; - }; - - cpu1: cpu@1 { - compatible = "arm,cortex-a53"; - device_type = "cpu"; - reg = <1>; - enable-method = "psci"; - clocks = <&ccu CLK_CPUX>; - clock-latency-ns = <244144>; /* 8 32k periods */ - operating-points-v2 = <&cpu_opp_table>; - #cooling-cells = <2>; - }; - - cpu2: cpu@2 { - compatible = "arm,cortex-a53"; - device_type = "cpu"; - reg = <2>; - enable-method = "psci"; - clocks = <&ccu CLK_CPUX>; - clock-latency-ns = <244144>; /* 8 32k periods */ - operating-points-v2 = <&cpu_opp_table>; - #cooling-cells = <2>; - }; - - cpu3: cpu@3 { - compatible = "arm,cortex-a53"; - device_type = "cpu"; - reg = <3>; - enable-method = "psci"; - clocks = <&ccu CLK_CPUX>; - clock-latency-ns = <244144>; /* 8 32k periods */ - operating-points-v2 = <&cpu_opp_table>; - #cooling-cells = <2>; - }; - }; - - cpu_opp_table: opp_table { - compatible = "allwinner,sun50i-h6-operating-points"; - nvmem-cells = <&speedbin_efuse>; - opp-shared; - - opp@480000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <480000000>; - - opp-microvolt-speed0 = <880000>; - opp-microvolt-speed1 = <820000>; - opp-microvolt-speed2 = <800000>; - }; - - opp@720000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <720000000>; - - opp-microvolt-speed0 = <880000>; - opp-microvolt-speed1 = <820000>; - opp-microvolt-speed2 = <800000>; - }; - - opp@816000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <816000000>; - - opp-microvolt-speed0 = <880000>; - opp-microvolt-speed1 = <820000>; - opp-microvolt-speed2 = <800000>; - }; - - opp@888000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <888000000>; - - opp-microvolt-speed0 = <940000>; - opp-microvolt-speed1 = <820000>; - opp-microvolt-speed2 = <800000>; - }; - - opp@1080000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <1080000000>; - - opp-microvolt-speed0 = <1060000>; - opp-microvolt-speed1 = <880000>; - opp-microvolt-speed2 = <840000>; - }; - - opp@1320000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <1320000000>; - - opp-microvolt-speed0 = <1160000>; - opp-microvolt-speed1 = <940000>; - opp-microvolt-speed2 = <900000>; - }; - - opp@1488000000 { - clock-latency-ns = <244144>; /* 8 32k periods */ - opp-hz = /bits/ 64 <1488000000>; - - opp-microvolt-speed0 = <1160000>; - opp-microvolt-speed1 = <1000000>; - opp-microvolt-speed2 = <960000>; - }; - }; -.... -soc { -.... - sid: sid@3006000 { - compatible = "allwinner,sun50i-h6-sid"; - reg = <0x03006000 0x400>; - #address-cells = <1>; - #size-cells = <1>; - .... - speedbin_efuse: speed@1c { - reg = <0x1c 4>; - }; - }; -}; -- cgit v1.2.3 From f95cad74acdb9de3b61a95ae8203c5e78b7d3615 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 19 Dec 2019 10:07:10 +0100 Subject: dt-bindings: clocks: Convert Allwinner legacy clocks to schemas The Allwinner SoCs have a legacy set of bindings (and a framework to support it in Linux) for their clock controllers. Now that we have the DT validation in place, let's split into separate file and convert the device tree bindings for those clocks to schemas, and mark them all as deprecated. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../clock/allwinner,sun4i-a10-ahb-clk.yaml | 108 ++++++++++ .../clock/allwinner,sun4i-a10-apb0-clk.yaml | 50 +++++ .../clock/allwinner,sun4i-a10-apb1-clk.yaml | 52 +++++ .../clock/allwinner,sun4i-a10-axi-clk.yaml | 61 ++++++ .../clock/allwinner,sun4i-a10-cpu-clk.yaml | 52 +++++ .../clock/allwinner,sun4i-a10-display-clk.yaml | 57 ++++++ .../clock/allwinner,sun4i-a10-gates-clk.yaml | 152 ++++++++++++++ .../clock/allwinner,sun4i-a10-mbus-clk.yaml | 63 ++++++ .../clock/allwinner,sun4i-a10-mmc-clk.yaml | 87 ++++++++ .../clock/allwinner,sun4i-a10-mod0-clk.yaml | 80 ++++++++ .../clock/allwinner,sun4i-a10-mod1-clk.yaml | 57 ++++++ .../clock/allwinner,sun4i-a10-osc-clk.yaml | 51 +++++ .../clock/allwinner,sun4i-a10-pll1-clk.yaml | 71 +++++++ .../clock/allwinner,sun4i-a10-pll3-clk.yaml | 50 +++++ .../clock/allwinner,sun4i-a10-pll5-clk.yaml | 53 +++++ .../clock/allwinner,sun4i-a10-pll6-clk.yaml | 53 +++++ .../clock/allwinner,sun4i-a10-tcon-ch0-clk.yaml | 77 +++++++ .../clock/allwinner,sun4i-a10-usb-clk.yaml | 166 +++++++++++++++ .../bindings/clock/allwinner,sun4i-a10-ve-clk.yaml | 55 +++++ .../clock/allwinner,sun5i-a13-ahb-clk.yaml | 52 +++++ .../clock/allwinner,sun6i-a31-pll6-clk.yaml | 53 +++++ .../clock/allwinner,sun7i-a20-gmac-clk.yaml | 51 +++++ .../clock/allwinner,sun7i-a20-out-clk.yaml | 52 +++++ .../clock/allwinner,sun8i-h3-bus-gates-clk.yaml | 103 ++++++++++ .../clock/allwinner,sun9i-a80-ahb-clk.yaml | 52 +++++ .../clock/allwinner,sun9i-a80-apb0-clk.yaml | 63 ++++++ .../clock/allwinner,sun9i-a80-cpus-clk.yaml | 52 +++++ .../bindings/clock/allwinner,sun9i-a80-gt-clk.yaml | 52 +++++ .../clock/allwinner,sun9i-a80-mmc-config-clk.yaml | 68 +++++++ .../clock/allwinner,sun9i-a80-pll4-clk.yaml | 50 +++++ .../clock/allwinner,sun9i-a80-usb-mod-clk.yaml | 60 ++++++ .../clock/allwinner,sun9i-a80-usb-phy-clk.yaml | 60 ++++++ Documentation/devicetree/bindings/clock/sunxi.txt | 225 --------------------- 33 files changed, 2163 insertions(+), 225 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ahb-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb0-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb1-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-axi-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-cpu-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-display-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-gates-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mbus-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mmc-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod0-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod1-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-osc-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll3-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll5-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll6-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-tcon-ch0-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-usb-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ve-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun5i-a13-ahb-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun6i-a31-pll6-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-gmac-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-out-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun8i-h3-bus-gates-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-ahb-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-apb0-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-cpus-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-gt-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-mmc-config-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-pll4-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-mod-clk.yaml create mode 100644 Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-phy-clk.yaml delete mode 100644 Documentation/devicetree/bindings/clock/sunxi.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ahb-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ahb-clk.yaml new file mode 100644 index 000000000000..558db4b6ed17 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ahb-clk.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-ahb-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 AHB Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + enum: + - allwinner,sun4i-a10-ahb-clk + - allwinner,sun6i-a31-ahb1-clk + - allwinner,sun8i-h3-ahb2-clk + + reg: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun4i-a10-ahb-clk + + then: + properties: + clocks: + maxItems: 1 + + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-ahb1-clk + + then: + properties: + clocks: + maxItems: 4 + + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-h3-ahb2-clk + + then: + properties: + clocks: + maxItems: 2 + +examples: + - | + ahb@1c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>; + clock-output-names = "ahb"; + }; + + - | + ahb1@1c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun6i-a31-ahb1-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; + clock-output-names = "ahb1"; + }; + + - | + ahb2_clk@1c2005c { + #clock-cells = <0>; + compatible = "allwinner,sun8i-h3-ahb2-clk"; + reg = <0x01c2005c 0x4>; + clocks = <&ahb1>, <&pll6d2>; + clock-output-names = "ahb2"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb0-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb0-clk.yaml new file mode 100644 index 000000000000..b1e3d739beb2 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb0-clk.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-apb0-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 APB0 Bus Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-apb0-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + apb0@1c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-apb0-clk"; + reg = <0x01c20054 0x4>; + clocks = <&ahb>; + clock-output-names = "apb0"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb1-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb1-clk.yaml new file mode 100644 index 000000000000..51b7a6d4ea54 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-apb1-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-apb1-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 APB1 Bus Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-apb1-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20058 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-apb1-clk"; + reg = <0x01c20058 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&osc32k>; + clock-output-names = "apb1"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-axi-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-axi-clk.yaml new file mode 100644 index 000000000000..d801158e15de --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-axi-clk.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-axi-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 AXI Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + enum: + - allwinner,sun4i-a10-axi-clk + - allwinner,sun8i-a23-axi-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + axi@1c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-axi-clk"; + reg = <0x01c20054 0x4>; + clocks = <&cpu>; + clock-output-names = "axi"; + }; + + - | + axi_clk@1c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a23-axi-clk"; + reg = <0x01c20050 0x4>; + clocks = <&cpu>; + clock-output-names = "axi"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-cpu-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-cpu-clk.yaml new file mode 100644 index 000000000000..0dfafba1a168 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-cpu-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-cpu-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 CPU Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-cpu-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + cpu@1c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-cpu-clk"; + reg = <0x01c20054 0x4>; + clocks = <&osc32k>, <&osc24M>, <&pll1>, <&dummy>; + clock-output-names = "cpu"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-display-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-display-clk.yaml new file mode 100644 index 000000000000..7484a7ab7dea --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-display-clk.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-display-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Display Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + "#reset-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-display-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20104 { + #clock-cells = <0>; + #reset-cells = <0>; + compatible = "allwinner,sun4i-a10-display-clk"; + reg = <0x01c20104 0x4>; + clocks = <&pll3>, <&pll7>, <&pll5 1>; + clock-output-names = "de-be"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-gates-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-gates-clk.yaml new file mode 100644 index 000000000000..ed1b2126a81b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-gates-clk.yaml @@ -0,0 +1,152 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-gates-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Bus Gates Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + This additional argument passed to that clock is the offset of + the bit controlling this particular gate in the register. + + compatible: + oneOf: + - const: allwinner,sun4i-a10-gates-clk + - const: allwinner,sun4i-a10-axi-gates-clk + - const: allwinner,sun4i-a10-ahb-gates-clk + - const: allwinner,sun5i-a10s-ahb-gates-clk + - const: allwinner,sun5i-a13-ahb-gates-clk + - const: allwinner,sun7i-a20-ahb-gates-clk + - const: allwinner,sun6i-a31-ahb1-gates-clk + - const: allwinner,sun8i-a23-ahb1-gates-clk + - const: allwinner,sun9i-a80-ahb0-gates-clk + - const: allwinner,sun9i-a80-ahb1-gates-clk + - const: allwinner,sun9i-a80-ahb2-gates-clk + - const: allwinner,sun4i-a10-apb0-gates-clk + - const: allwinner,sun5i-a10s-apb0-gates-clk + - const: allwinner,sun5i-a13-apb0-gates-clk + - const: allwinner,sun7i-a20-apb0-gates-clk + - const: allwinner,sun9i-a80-apb0-gates-clk + - const: allwinner,sun8i-a83t-apb0-gates-clk + - const: allwinner,sun4i-a10-apb1-gates-clk + - const: allwinner,sun5i-a13-apb1-gates-clk + - const: allwinner,sun5i-a10s-apb1-gates-clk + - const: allwinner,sun6i-a31-apb1-gates-clk + - const: allwinner,sun7i-a20-apb1-gates-clk + - const: allwinner,sun8i-a23-apb1-gates-clk + - const: allwinner,sun9i-a80-apb1-gates-clk + - const: allwinner,sun6i-a31-apb2-gates-clk + - const: allwinner,sun8i-a23-apb2-gates-clk + - const: allwinner,sun8i-a83t-bus-gates-clk + - const: allwinner,sun9i-a80-apbs-gates-clk + - const: allwinner,sun4i-a10-dram-gates-clk + + - items: + - const: allwinner,sun5i-a13-dram-gates-clk + - const: allwinner,sun4i-a10-gates-clk + + - items: + - const: allwinner,sun8i-h3-apb0-gates-clk + - const: allwinner,sun4i-a10-gates-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-indices: + minItems: 1 + maxItems: 64 + + clock-output-names: + minItems: 1 + maxItems: 64 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-indices + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c2005c { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-axi-gates-clk"; + reg = <0x01c2005c 0x4>; + clocks = <&axi>; + clock-indices = <0>; + clock-output-names = "axi_dram"; + }; + + - | + clk@1c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-ahb-gates-clk"; + reg = <0x01c20060 0x8>; + clocks = <&ahb>; + clock-indices = <0>, <1>, + <2>, <3>, + <4>, <5>, <6>, + <7>, <8>, <9>, + <10>, <11>, <12>, + <13>, <14>, <16>, + <17>, <18>, <20>, + <21>, <22>, <23>, + <24>, <25>, <26>, + <32>, <33>, <34>, + <35>, <36>, <37>, + <40>, <41>, <43>, + <44>, <45>, + <46>, <47>, + <50>, <52>; + clock-output-names = "ahb_usb0", "ahb_ehci0", + "ahb_ohci0", "ahb_ehci1", + "ahb_ohci1", "ahb_ss", "ahb_dma", + "ahb_bist", "ahb_mmc0", "ahb_mmc1", + "ahb_mmc2", "ahb_mmc3", "ahb_ms", + "ahb_nand", "ahb_sdram", "ahb_ace", + "ahb_emac", "ahb_ts", "ahb_spi0", + "ahb_spi1", "ahb_spi2", "ahb_spi3", + "ahb_pata", "ahb_sata", "ahb_gps", + "ahb_ve", "ahb_tvd", "ahb_tve0", + "ahb_tve1", "ahb_lcd0", "ahb_lcd1", + "ahb_csi0", "ahb_csi1", "ahb_hdmi", + "ahb_de_be0", "ahb_de_be1", + "ahb_de_fe0", "ahb_de_fe1", + "ahb_mp", "ahb_mali400"; + }; + + + - | + clk@1c20068 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-apb0-gates-clk"; + reg = <0x01c20068 0x4>; + clocks = <&apb0>; + clock-indices = <0>, <1>, + <2>, <3>, + <5>, <6>, + <7>, <10>; + clock-output-names = "apb0_codec", "apb0_spdif", + "apb0_ac97", "apb0_iis", + "apb0_pio", "apb0_ir0", + "apb0_ir1", "apb0_keypad"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mbus-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mbus-clk.yaml new file mode 100644 index 000000000000..18f131e262b4 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mbus-clk.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-mbus-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 MBUS Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + enum: + - allwinner,sun5i-a13-mbus-clk + - allwinner,sun8i-a23-mbus-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun5i-a13-mbus-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mbus"; + }; + + - | + clk@1c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a23-mbus-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5>; + clock-output-names = "mbus"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mmc-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mmc-clk.yaml new file mode 100644 index 000000000000..5199285a661a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mmc-clk.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-mmc-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Module 1 Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + There is three different outputs: the main clock, with the ID 0, + and the output and sample clocks, with the IDs 1 and 2, + respectively. + + compatible: + enum: + - allwinner,sun4i-a10-mmc-clk + - allwinner,sun9i-a80-mmc-clk + + reg: + maxItems: 1 + + clocks: + minItems: 2 + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 3 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +if: + properties: + compatible: + contains: + const: allwinner,sun4i-a10-mmc-clk + +then: + properties: + clocks: + maxItems: 3 + +else: + properties: + clocks: + maxItems: 2 + +examples: + - | + clk@1c20088 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-mmc-clk"; + reg = <0x01c20088 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "mmc0", + "mmc0_output", + "mmc0_sample"; + }; + + - | + clk@6000410 { + #clock-cells = <1>; + compatible = "allwinner,sun9i-a80-mmc-clk"; + reg = <0x06000410 0x4>; + clocks = <&osc24M>, <&pll4>; + clock-output-names = "mmc0", "mmc0_output", + "mmc0_sample"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod0-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod0-clk.yaml new file mode 100644 index 000000000000..3e2abe3e67c1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod0-clk.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-mod0-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Module 0 Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +select: + properties: + compatible: + contains: + enum: + - allwinner,sun4i-a10-mod0-clk + - allwinner,sun9i-a80-mod0-clk + + # The PRCM on the A31 and A23 will have the reg property missing, + # since it's set at the upper level node, and will be validated by + # PRCM's schema. Make sure we only validate standalone nodes. + required: + - compatible + - reg + +properties: + "#clock-cells": + const: 0 + + compatible: + enum: + - allwinner,sun4i-a10-mod0-clk + - allwinner,sun9i-a80-mod0-clk + + reg: + maxItems: 1 + + clocks: + # On the A80, the PRCM mod0 clocks have 2 parents. + minItems: 2 + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20080 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x01c20080 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; + clock-output-names = "nand"; + }; + + - | + clk@8001454 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + reg = <0x08001454 0x4>; + clocks = <&osc32k>, <&osc24M>; + clock-output-names = "r_ir"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod1-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod1-clk.yaml new file mode 100644 index 000000000000..7ddb55c75cff --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-mod1-clk.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-mod1-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Module 1 Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-mod1-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + #include + + clk@1c200c0 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod1-clk"; + reg = <0x01c200c0 0x4>; + clocks = <&pll2 SUN4I_A10_PLL2_8X>, + <&pll2 SUN4I_A10_PLL2_4X>, + <&pll2 SUN4I_A10_PLL2_2X>, + <&pll2 SUN4I_A10_PLL2_1X>; + clock-output-names = "spdif"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-osc-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-osc-clk.yaml new file mode 100644 index 000000000000..69cfa4a3d562 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-osc-clk.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-osc-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Gatable Oscillator Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-osc-clk + + reg: + maxItems: 1 + + clock-frequency: + description: > + Frequency of the main oscillator. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clock-frequency + - clock-output-names + +additionalProperties: false + +examples: + - | + osc24M: clk@01c20050 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-osc-clk"; + reg = <0x01c20050 0x4>; + clock-frequency = <24000000>; + clock-output-names = "osc24M"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml new file mode 100644 index 000000000000..e9c4cf834aa7 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll1-clk.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-pll1-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 CPU PLL Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + enum: + - allwinner,sun4i-a10-pll1-clk + - allwinner,sun6i-a31-pll1-clk + - allwinner,sun8i-a23-pll1-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll1"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; + clock-output-names = "osc24M"; + }; + + - | + clk@1c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun6i-a31-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll1"; + }; + + - | + clk@1c20000 { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a23-pll1-clk"; + reg = <0x01c20000 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll1"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll3-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll3-clk.yaml new file mode 100644 index 000000000000..4b80a42fb3da --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll3-clk.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-pll3-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Video PLL Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-pll3-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20010 { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-pll3-clk"; + reg = <0x01c20010 0x4>; + clocks = <&osc3M>; + clock-output-names = "pll3"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll5-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll5-clk.yaml new file mode 100644 index 000000000000..415bd77de53d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll5-clk.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-pll5-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 DRAM PLL Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + The first output is the DRAM clock output, the second is meant + for peripherals on the SoC. + + compatible: + const: allwinner,sun4i-a10-pll5-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 2 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20020 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-pll5-clk"; + reg = <0x01c20020 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll5_ddr", "pll5_other"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll6-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll6-clk.yaml new file mode 100644 index 000000000000..ec5652f76027 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-pll6-clk.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-pll6-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Peripheral PLL Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + The first output is the SATA clock output, the second is the + regular PLL output, the third is a PLL output at twice the rate. + + compatible: + const: allwinner,sun4i-a10-pll6-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 3 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun4i-a10-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6_sata", "pll6_other", "pll6"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-tcon-ch0-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-tcon-ch0-clk.yaml new file mode 100644 index 000000000000..0a335c615efd --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-tcon-ch0-clk.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-tcon-ch0-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 TCON Channel 0 Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + "#reset-cells": + const: 1 + + compatible: + enum: + - allwinner,sun4i-a10-tcon-ch0-clk + - allwinner,sun4i-a10-tcon-ch1-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +if: + properties: + compatible: + contains: + const: allwinner,sun4i-a10-tcon-ch0-clk + +then: + required: + - "#reset-cells" + +additionalProperties: false + +examples: + - | + clk@1c20118 { + #clock-cells = <0>; + #reset-cells = <1>; + compatible = "allwinner,sun4i-a10-tcon-ch0-clk"; + reg = <0x01c20118 0x4>; + clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>; + clock-output-names = "tcon-ch0-sclk"; + }; + + - | + clk@1c2012c { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-tcon-ch1-clk"; + reg = <0x01c2012c 0x4>; + clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>; + clock-output-names = "tcon-ch1-sclk"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-usb-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-usb-clk.yaml new file mode 100644 index 000000000000..cd95d25bfe7c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-usb-clk.yaml @@ -0,0 +1,166 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-usb-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 USB Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + The additional ID argument passed to the clock shall refer to + the index of the output. + + "#reset-cells": + const: 1 + + compatible: + enum: + - allwinner,sun4i-a10-usb-clk + - allwinner,sun5i-a13-usb-clk + - allwinner,sun6i-a31-usb-clk + - allwinner,sun8i-a23-usb-clk + - allwinner,sun8i-h3-usb-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + minItems: 2 + maxItems: 8 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun4i-a10-usb-clk + + then: + properties: + clock-output-names: + maxItems: 3 + + - if: + properties: + compatible: + contains: + const: allwinner,sun5i-a13-usb-clk + + then: + properties: + clock-output-names: + maxItems: 2 + + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-usb-clk + + then: + properties: + clock-output-names: + maxItems: 6 + + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-a23-usb-clk + + then: + properties: + clock-output-names: + maxItems: 5 + + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-h3-usb-clk + + then: + properties: + clock-output-names: + maxItems: 8 + +examples: + - | + clk@1c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun4i-a10-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&pll6 1>; + clock-output-names = "usb_ohci0", "usb_ohci1", "usb_phy"; + }; + + - | + clk@1c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun5i-a13-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&pll6 1>; + clock-output-names = "usb_ohci0", "usb_phy"; + }; + + - | + clk@1c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&osc24M>; + clock-output-names = "usb_phy0", "usb_phy1", "usb_phy2", + "usb_ohci0", "usb_ohci1", + "usb_ohci2"; + }; + + - | + clk@1c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun8i-a23-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&osc24M>; + clock-output-names = "usb_phy0", "usb_phy1", "usb_hsic", + "usb_hsic_12M", "usb_ohci0"; + }; + + - | + clk@1c200cc { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun8i-h3-usb-clk"; + reg = <0x01c200cc 0x4>; + clocks = <&osc24M>; + clock-output-names = "usb_phy0", "usb_phy1", + "usb_phy2", "usb_phy3", + "usb_ohci0", "usb_ohci1", + "usb_ohci2", "usb_ohci3"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ve-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ve-clk.yaml new file mode 100644 index 000000000000..5dfd0c1c27b4 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ve-clk.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun4i-a10-ve-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Video Engine Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + "#reset-cells": + const: 0 + + compatible: + const: allwinner,sun4i-a10-ve-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c2013c { + #clock-cells = <0>; + #reset-cells = <0>; + compatible = "allwinner,sun4i-a10-ve-clk"; + reg = <0x01c2013c 0x4>; + clocks = <&pll4>; + clock-output-names = "ve"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun5i-a13-ahb-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun5i-a13-ahb-clk.yaml new file mode 100644 index 000000000000..99add7991c48 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun5i-a13-ahb-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun5i-a13-ahb-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A13 AHB Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun5i-a13-ahb-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + ahb@1c20054 { + #clock-cells = <0>; + compatible = "allwinner,sun5i-a13-ahb-clk"; + reg = <0x01c20054 0x4>; + clocks = <&axi>, <&cpu>, <&pll6 1>; + clock-output-names = "ahb"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun6i-a31-pll6-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun6i-a31-pll6-clk.yaml new file mode 100644 index 000000000000..5f377205af71 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun6i-a31-pll6-clk.yaml @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun6i-a31-pll6-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 Peripheral PLL Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + The first output is the regular PLL output, the second is a PLL + output at twice the rate. + + compatible: + const: allwinner,sun6i-a31-pll6-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 2 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6", "pll6x2"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-gmac-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-gmac-clk.yaml new file mode 100644 index 000000000000..59e5dce1b65a --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-gmac-clk.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun7i-a20-gmac-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A20 GMAC TX Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun7i-a20-gmac-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 2 + description: > + The parent clocks shall be fixed rate dummy clocks at 25 MHz and + 125 MHz, respectively. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20164 { + #clock-cells = <0>; + compatible = "allwinner,sun7i-a20-gmac-clk"; + reg = <0x01c20164 0x4>; + clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; + clock-output-names = "gmac_tx"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-out-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-out-clk.yaml new file mode 100644 index 000000000000..c745733bcf04 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun7i-a20-out-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun7i-a20-out-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A20 Output Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun7i-a20-out-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 3 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c201f0 { + #clock-cells = <0>; + compatible = "allwinner,sun7i-a20-out-clk"; + reg = <0x01c201f0 0x4>; + clocks = <&osc24M_32k>, <&osc32k>, <&osc24M>; + clock-output-names = "clk_out_a"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun8i-h3-bus-gates-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun8i-h3-bus-gates-clk.yaml new file mode 100644 index 000000000000..3eb2bf65b230 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun8i-h3-bus-gates-clk.yaml @@ -0,0 +1,103 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun8i-h3-bus-gates-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 Bus Gates Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + This additional argument passed to that clock is the offset of + the bit controlling this particular gate in the register. + + compatible: + const: allwinner,sun8i-h3-bus-gates-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + + clock-names: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-indices: + minItems: 1 + maxItems: 64 + + clock-output-names: + minItems: 1 + maxItems: 64 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-indices + - clock-names + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c20060 { + #clock-cells = <1>; + compatible = "allwinner,sun8i-h3-bus-gates-clk"; + reg = <0x01c20060 0x14>; + clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>; + clock-names = "ahb1", "ahb2", "apb1", "apb2"; + clock-indices = <5>, <6>, <8>, + <9>, <10>, <13>, + <14>, <17>, <18>, + <19>, <20>, + <21>, <23>, + <24>, <25>, + <26>, <27>, + <28>, <29>, + <30>, <31>, <32>, + <35>, <36>, <37>, + <40>, <41>, <43>, + <44>, <52>, <53>, + <54>, <64>, + <65>, <69>, <72>, + <76>, <77>, <78>, + <96>, <97>, <98>, + <112>, <113>, + <114>, <115>, + <116>, <128>, <135>; + clock-output-names = "bus_ce", "bus_dma", "bus_mmc0", + "bus_mmc1", "bus_mmc2", "bus_nand", + "bus_sdram", "bus_gmac", "bus_ts", + "bus_hstimer", "bus_spi0", + "bus_spi1", "bus_otg", + "bus_otg_ehci0", "bus_ehci1", + "bus_ehci2", "bus_ehci3", + "bus_otg_ohci0", "bus_ohci1", + "bus_ohci2", "bus_ohci3", "bus_ve", + "bus_lcd0", "bus_lcd1", "bus_deint", + "bus_csi", "bus_tve", "bus_hdmi", + "bus_de", "bus_gpu", "bus_msgbox", + "bus_spinlock", "bus_codec", + "bus_spdif", "bus_pio", "bus_ths", + "bus_i2s0", "bus_i2s1", "bus_i2s2", + "bus_i2c0", "bus_i2c1", "bus_i2c2", + "bus_uart0", "bus_uart1", + "bus_uart2", "bus_uart3", + "bus_scr", "bus_ephy", "bus_dbg"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-ahb-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-ahb-clk.yaml new file mode 100644 index 000000000000..d178da90aaec --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-ahb-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-ahb-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 AHB Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun9i-a80-ahb-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@6000060 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-ahb-clk"; + reg = <0x06000060 0x4>; + clocks = <>_clk>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "ahb0"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-apb0-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-apb0-clk.yaml new file mode 100644 index 000000000000..0351c79bd221 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-apb0-clk.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-apb0-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 APB0 Bus Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + enum: + - allwinner,sun9i-a80-apb0-clk + - allwinner,sun9i-a80-apb1-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 2 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@6000070 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-apb0-clk"; + reg = <0x06000070 0x4>; + clocks = <&osc24M>, <&pll4>; + clock-output-names = "apb0"; + }; + + - | + clk@6000074 { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-apb1-clk"; + reg = <0x06000074 0x4>; + clocks = <&osc24M>, <&pll4>; + clock-output-names = "apb1"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-cpus-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-cpus-clk.yaml new file mode 100644 index 000000000000..24d5b2f1a314 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-cpus-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-cpus-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 CPUS Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun9i-a80-cpus-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@8001410 { + compatible = "allwinner,sun9i-a80-cpus-clk"; + reg = <0x08001410 0x4>; + #clock-cells = <0>; + clocks = <&osc32k>, <&osc24M>, <&pll4>, <&pll3>; + clock-output-names = "cpus"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-gt-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-gt-clk.yaml new file mode 100644 index 000000000000..07f38def7dc3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-gt-clk.yaml @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-gt-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 GT Bus Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun9i-a80-gt-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming order. + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@0600005c { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-gt-clk"; + reg = <0x0600005c 0x4>; + clocks = <&osc24M>, <&pll4>, <&pll12>, <&pll12>; + clock-output-names = "gt"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-mmc-config-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-mmc-config-clk.yaml new file mode 100644 index 000000000000..20dc115fa211 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-mmc-config-clk.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-mmc-config-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 MMC Configuration Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +description: > + There is one clock/reset output per mmc controller. The number of + outputs is determined by the size of the address block, which is + related to the overall mmc block. + +properties: + "#clock-cells": + const: 1 + description: > + The additional ID argument passed to the clock shall refer to + the index of the output. + + "#reset-cells": + const: 1 + + compatible: + const: allwinner,sun9i-a80-mmc-config-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + resets: + maxItems: 1 + + clock-output-names: + maxItems: 4 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@1c13000 { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun9i-a80-mmc-config-clk"; + reg = <0x01c13000 0x10>; + clocks = <&ahb0_gates 8>; + resets = <&ahb0_resets 8>; + clock-output-names = "mmc0_config", "mmc1_config", + "mmc2_config", "mmc3_config"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-pll4-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-pll4-clk.yaml new file mode 100644 index 000000000000..b76bab6a30e9 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-pll4-clk.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-pll4-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 Peripheral PLL Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 0 + + compatible: + const: allwinner,sun9i-a80-pll4-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + +required: + - "#clock-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@600000c { + #clock-cells = <0>; + compatible = "allwinner,sun9i-a80-pll4-clk"; + reg = <0x0600000c 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll4"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-mod-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-mod-clk.yaml new file mode 100644 index 000000000000..15218d10e78e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-mod-clk.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-usb-mod-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 USB Module Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + The additional ID argument passed to the clock shall refer to + the index of the output. + + "#reset-cells": + const: 1 + + compatible: + const: allwinner,sun9i-a80-usb-mod-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 6 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@a08000 { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun9i-a80-usb-mod-clk"; + reg = <0x00a08000 0x4>; + clocks = <&ahb1_gates 1>; + clock-output-names = "usb0_ahb", "usb_ohci0", + "usb1_ahb", "usb_ohci1", + "usb2_ahb", "usb_ohci2"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-phy-clk.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-phy-clk.yaml new file mode 100644 index 000000000000..2569041684e6 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/allwinner,sun9i-a80-usb-phy-clk.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/allwinner,sun9i-a80-usb-phy-clk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A80 USB PHY Clock Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + "#clock-cells": + const: 1 + description: > + The additional ID argument passed to the clock shall refer to + the index of the output. + + "#reset-cells": + const: 1 + + compatible: + const: allwinner,sun9i-a80-usb-phy-clk + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 6 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + - clock-output-names + +additionalProperties: false + +examples: + - | + clk@a08004 { + #clock-cells = <1>; + #reset-cells = <1>; + compatible = "allwinner,sun9i-a80-usb-phy-clk"; + reg = <0x00a08004 0x4>; + clocks = <&ahb1_gates 1>; + clock-output-names = "usb_phy0", "usb_hsic1_480M", + "usb_phy1", "usb_hsic2_480M", + "usb_phy2", "usb_hsic_12M"; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt deleted file mode 100644 index 1a042e20b115..000000000000 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ /dev/null @@ -1,225 +0,0 @@ -Device Tree Clock bindings for arch-sunxi - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible : shall be one of the following: - "allwinner,sun4i-a10-osc-clk" - for a gatable oscillator - "allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4 - "allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31 - "allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23 - "allwinner,sun4i-a10-pll3-clk" - for the video PLL clock on A10 - "allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80 - "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock - "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock - "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31 - "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80 - "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock - "allwinner,sun4i-a10-axi-clk" - for the AXI clock - "allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23 - "allwinner,sun4i-a10-gates-clk" - for generic gates on all compatible SoCs - "allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates - "allwinner,sun4i-a10-ahb-clk" - for the AHB clock - "allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13 - "allwinner,sun9i-a80-ahb-clk" - for the AHB bus clocks on A80 - "allwinner,sun4i-a10-ahb-gates-clk" - for the AHB gates on A10 - "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 - "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s - "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 - "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 - "allwinner,sun9i-a80-cpus-clk" - for the CPUS on A80 - "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31 - "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3 - "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 - "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23 - "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80 - "allwinner,sun9i-a80-ahb1-gates-clk" - for the AHB1 gates on A80 - "allwinner,sun9i-a80-ahb2-gates-clk" - for the AHB2 gates on A80 - "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock - "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 - "allwinner,sun8i-a23-apb0-clk" - for the APB0 clock on A23 - "allwinner,sun9i-a80-apb0-clk" - for the APB0 bus clock on A80 - "allwinner,sun8i-a83t-apb0-gates-clk" - for the APB0 gates on A83T - "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 - "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 - "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s - "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31 - "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 - "allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23 - "allwinner,sun8i-h3-apb0-gates-clk" - for the APB0 gates on H3 - "allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80 - "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock - "allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80 - "allwinner,sun4i-a10-apb1-gates-clk" - for the APB1 gates on A10 - "allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13 - "allwinner,sun5i-a10s-apb1-gates-clk" - for the APB1 gates on A10s - "allwinner,sun6i-a31-apb1-gates-clk" - for the APB1 gates on A31 - "allwinner,sun7i-a20-apb1-gates-clk" - for the APB1 gates on A20 - "allwinner,sun8i-a23-apb1-gates-clk" - for the APB1 gates on A23 - "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80 - "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31 - "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23 - "allwinner,sun8i-a83t-bus-gates-clk" - for the bus gates on A83T - "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3 - "allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80 - "allwinner,sun4i-a10-display-clk" - for the display clocks on the A10 - "allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10 - "allwinner,sun5i-a13-dram-gates-clk" - for the DRAM gates on A13 - "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13 - "allwinner,sun4i-a10-mmc-clk" - for the MMC clock - "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80 - "allwinner,sun9i-a80-mmc-config-clk" - for mmc gates + resets on A80 - "allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks - "allwinner,sun9i-a80-mod0-clk" - for module 0 (storage) clocks on A80 - "allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23 - "allwinner,sun7i-a20-out-clk" - for the external output clocks - "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 - "allwinner,sun4i-a10-tcon-ch0-clk" - for the TCON channel 0 clock on the A10 - "allwinner,sun4i-a10-tcon-ch1-clk" - for the TCON channel 1 clock on the A10 - "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 - "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 - "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 - "allwinner,sun8i-a23-usb-clk" - for usb gates + resets on A23 - "allwinner,sun8i-h3-usb-clk" - for usb gates + resets on H3 - "allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80 - "allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80 - "allwinner,sun4i-a10-ve-clk" - for the Video Engine clock - "allwinner,sun6i-a31-display-clk" - for the display clocks - -Required properties for all clocks: -- reg : shall be the control register address for the clock. -- clocks : shall be the input parent clock(s) phandle for the clock. For - multiplexed clocks, the list order must match the hardware - programming order. -- #clock-cells : from common clock binding; shall be set to 0 except for - the following compatibles where it shall be set to 1: - "allwinner,*-gates-clk", "allwinner,sun4i-pll5-clk", - "allwinner,sun4i-pll6-clk", "allwinner,sun6i-a31-pll6-clk", - "allwinner,*-usb-clk", "allwinner,*-mmc-clk", - "allwinner,*-mmc-config-clk" -- clock-output-names : shall be the corresponding names of the outputs. - If the clock module only has one output, the name shall be the - module name. - -And "allwinner,*-usb-clk" clocks also require: -- reset-cells : shall be set to 1 - -The "allwinner,sun4i-a10-ve-clk" clock also requires: -- reset-cells : shall be set to 0 - -The "allwinner,sun9i-a80-mmc-config-clk" clock also requires: -- #reset-cells : shall be set to 1 -- resets : shall be the reset control phandle for the mmc block. - -For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate -dummy clocks at 25 MHz and 125 MHz, respectively. See example. - -Clock consumers should specify the desired clocks they use with a -"clocks" phandle cell. Consumers that are using a gated clock should -provide an additional ID in their clock property. This ID is the -offset of the bit controlling this particular gate in the register. -For the other clocks with "#clock-cells" = 1, the additional ID shall -refer to the index of the output. - -For "allwinner,sun6i-a31-pll6-clk", there are 2 outputs. The first output -is the normal PLL6 output, or "pll6". The second output is rate doubled -PLL6, or "pll6x2". - -The "allwinner,*-mmc-clk" clocks have three different outputs: the -main clock, with the ID 0, and the output and sample clocks, with the -IDs 1 and 2, respectively. - -The "allwinner,sun9i-a80-mmc-config-clk" clock has one clock/reset output -per mmc controller. The number of outputs is determined by the size of -the address block, which is related to the overall mmc block. - -For example: - -osc24M: clk@1c20050 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-osc-clk"; - reg = <0x01c20050 0x4>; - clocks = <&osc24M_fixed>; - clock-output-names = "osc24M"; -}; - -pll1: clk@1c20000 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-pll1-clk"; - reg = <0x01c20000 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll1"; -}; - -pll5: clk@1c20020 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-pll5-clk"; - reg = <0x01c20020 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll5_ddr", "pll5_other"; -}; - -pll6: clk@1c20028 { - #clock-cells = <1>; - compatible = "allwinner,sun6i-a31-pll6-clk"; - reg = <0x01c20028 0x4>; - clocks = <&osc24M>; - clock-output-names = "pll6", "pll6x2"; -}; - -cpu: cpu@1c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-cpu-clk"; - reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll1>; - clock-output-names = "cpu"; -}; - -mmc0_clk: clk@1c20088 { - #clock-cells = <1>; - compatible = "allwinner,sun4i-a10-mmc-clk"; - reg = <0x01c20088 0x4>; - clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; - clock-output-names = "mmc0", "mmc0_output", "mmc0_sample"; -}; - -mii_phy_tx_clk: clk@2 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <25000000>; - clock-output-names = "mii_phy_tx"; -}; - -gmac_int_tx_clk: clk@3 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <125000000>; - clock-output-names = "gmac_int_tx"; -}; - -gmac_clk: clk@1c20164 { - #clock-cells = <0>; - compatible = "allwinner,sun7i-a20-gmac-clk"; - reg = <0x01c20164 0x4>; - /* - * The first clock must be fixed at 25MHz; - * the second clock must be fixed at 125MHz - */ - clocks = <&mii_phy_tx_clk>, <&gmac_int_tx_clk>; - clock-output-names = "gmac"; -}; - -mmc_config_clk: clk@1c13000 { - compatible = "allwinner,sun9i-a80-mmc-config-clk"; - reg = <0x01c13000 0x10>; - clocks = <&ahb0_gates 8>; - clock-names = "ahb"; - resets = <&ahb0_resets 8>; - reset-names = "ahb"; - #clock-cells = <1>; - #reset-cells = <1>; - clock-output-names = "mmc0_config", "mmc1_config", - "mmc2_config", "mmc3_config"; -}; -- cgit v1.2.3 From af287ed02ffd3bb356f3f63ab9eacc60a65247fb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 19 Dec 2019 10:07:11 +0100 Subject: dt-bindings: mfd: Convert Allwinner legacy PRCM bindings to schemas The Allwinner SoCs have a legacy set of bindings (and a drivers to support it in Linux) to support the PRCM unit found in most recent SoCs. Now that we have the DT validation in place, let's split into separate file and convert the device tree bindings for those controllers to schemas, and mark them all as deprecated. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../bindings/mfd/allwinner,sun6i-a31-prcm.yaml | 219 +++++++++++++++++++++ .../bindings/mfd/allwinner,sun8i-a23-prcm.yaml | 200 +++++++++++++++++++ .../devicetree/bindings/mfd/sun6i-prcm.txt | 59 ------ 3 files changed, 419 insertions(+), 59 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml create mode 100644 Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml delete mode 100644 Documentation/devicetree/bindings/mfd/sun6i-prcm.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml new file mode 100644 index 000000000000..d131759ccaf3 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/allwinner,sun6i-a31-prcm.yaml @@ -0,0 +1,219 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/allwinner,sun6i-a31-prcm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 PRCM Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + compatible: + const: allwinner,sun6i-a31-prcm + + reg: + maxItems: 1 + +patternProperties: + "^.*_(clk|rst)$": + type: object + + properties: + compatible: + enum: + - allwinner,sun4i-a10-mod0-clk + - allwinner,sun6i-a31-apb0-clk + - allwinner,sun6i-a31-apb0-gates-clk + - allwinner,sun6i-a31-ar100-clk + - allwinner,sun6i-a31-clock-reset + - fixed-factor-clock + + allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-apb0-clk + + then: + properties: + "#clock-cells": + const: 0 + + # Already checked in the main schema + compatible: true + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + + phandle: true + + required: + - "#clock-cells" + - compatible + - clocks + - clock-output-names + + additionalProperties: false + + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-apb0-gates-clk + + then: + properties: + "#clock-cells": + const: 1 + description: > + This additional argument passed to that clock is the + offset of the bit controlling this particular gate in + the register. + + # Already checked in the main schema + compatible: true + + clocks: + maxItems: 1 + + clock-output-names: + minItems: 1 + maxItems: 32 + + phandle: true + + required: + - "#clock-cells" + - compatible + - clocks + - clock-output-names + + additionalProperties: false + + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-ar100-clk + + then: + properties: + "#clock-cells": + const: 0 + + # Already checked in the main schema + compatible: true + + clocks: + maxItems: 4 + description: > + The parent order must match the hardware programming + order. + + clock-output-names: + maxItems: 1 + + phandle: true + + required: + - "#clock-cells" + - compatible + - clocks + - clock-output-names + + additionalProperties: false + + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-clock-reset + + then: + properties: + "#reset-cells": + const: 1 + + # Already checked in the main schema + compatible: true + + phandle: true + + required: + - "#reset-cells" + - compatible + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + #include + + prcm@1f01400 { + compatible = "allwinner,sun6i-a31-prcm"; + reg = <0x01f01400 0x200>; + + ar100: ar100_clk { + compatible = "allwinner,sun6i-a31-ar100-clk"; + #clock-cells = <0>; + clocks = <&rtc 0>, <&osc24M>, + <&ccu CLK_PLL_PERIPH>, + <&ccu CLK_PLL_PERIPH>; + clock-output-names = "ar100"; + }; + + ahb0: ahb0_clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <1>; + clocks = <&ar100>; + clock-output-names = "ahb0"; + }; + + apb0: apb0_clk { + compatible = "allwinner,sun6i-a31-apb0-clk"; + #clock-cells = <0>; + clocks = <&ahb0>; + clock-output-names = "apb0"; + }; + + apb0_gates: apb0_gates_clk { + compatible = "allwinner,sun6i-a31-apb0-gates-clk"; + #clock-cells = <1>; + clocks = <&apb0>; + clock-output-names = "apb0_pio", "apb0_ir", + "apb0_timer", "apb0_p2wi", + "apb0_uart", "apb0_1wire", + "apb0_i2c"; + }; + + ir_clk: ir_clk { + #clock-cells = <0>; + compatible = "allwinner,sun4i-a10-mod0-clk"; + clocks = <&rtc 0>, <&osc24M>; + clock-output-names = "ir"; + }; + + apb0_rst: apb0_rst { + compatible = "allwinner,sun6i-a31-clock-reset"; + #reset-cells = <1>; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml b/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml new file mode 100644 index 000000000000..aa5e683b236c --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/allwinner,sun8i-a23-prcm.yaml @@ -0,0 +1,200 @@ +# SPDX-License-Identifier: GPL-2.0+ +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/allwinner,sun8i-a23-prcm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A23 PRCM Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +properties: + compatible: + const: allwinner,sun8i-a23-prcm + + reg: + maxItems: 1 + +patternProperties: + "^.*(clk|rst|codec).*$": + type: object + + properties: + compatible: + enum: + - fixed-factor-clock + - allwinner,sun8i-a23-apb0-clk + - allwinner,sun8i-a23-apb0-gates-clk + - allwinner,sun6i-a31-clock-reset + - allwinner,sun8i-a23-codec-analog + + required: + - compatible + + allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-a23-apb0-clk + + then: + properties: + "#clock-cells": + const: 0 + + # Already checked in the main schema + compatible: true + + clocks: + maxItems: 1 + + clock-output-names: + maxItems: 1 + + phandle: true + + required: + - "#clock-cells" + - compatible + - clocks + - clock-output-names + + additionalProperties: false + + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-a23-apb0-gates-clk + + then: + properties: + "#clock-cells": + const: 1 + description: > + This additional argument passed to that clock is the + offset of the bit controlling this particular gate in + the register. + + # Already checked in the main schema + compatible: true + + clocks: + maxItems: 1 + + clock-output-names: + minItems: 1 + maxItems: 32 + + phandle: true + + required: + - "#clock-cells" + - compatible + - clocks + - clock-output-names + + additionalProperties: false + + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-clock-reset + + then: + properties: + "#reset-cells": + const: 1 + + # Already checked in the main schema + compatible: true + + phandle: true + + required: + - "#reset-cells" + - compatible + + additionalProperties: false + + - if: + properties: + compatible: + contains: + const: allwinner,sun8i-a23-codec-analog + + then: + properties: + # Already checked in the main schema + compatible: true + + phandle: true + + required: + - compatible + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + prcm@1f01400 { + compatible = "allwinner,sun8i-a23-prcm"; + reg = <0x01f01400 0x200>; + + ar100: ar100_clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <1>; + clocks = <&osc24M>; + clock-output-names = "ar100"; + }; + + ahb0: ahb0_clk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <1>; + clock-mult = <1>; + clocks = <&ar100>; + clock-output-names = "ahb0"; + }; + + apb0: apb0_clk { + compatible = "allwinner,sun8i-a23-apb0-clk"; + #clock-cells = <0>; + clocks = <&ahb0>; + clock-output-names = "apb0"; + }; + + apb0_gates: apb0_gates_clk { + compatible = "allwinner,sun8i-a23-apb0-gates-clk"; + #clock-cells = <1>; + clocks = <&apb0>; + clock-output-names = "apb0_pio", "apb0_timer", + "apb0_rsb", "apb0_uart", + "apb0_i2c"; + }; + + apb0_rst: apb0_rst { + compatible = "allwinner,sun6i-a31-clock-reset"; + #reset-cells = <1>; + }; + + codec_analog: codec-analog { + compatible = "allwinner,sun8i-a23-codec-analog"; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt deleted file mode 100644 index daa091c2e67b..000000000000 --- a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt +++ /dev/null @@ -1,59 +0,0 @@ -* Allwinner PRCM (Power/Reset/Clock Management) Multi-Functional Device - -PRCM is an MFD device exposing several Power Management related devices -(like clks and reset controllers). - -Required properties: - - compatible: "allwinner,sun6i-a31-prcm" or "allwinner,sun8i-a23-prcm" - - reg: The PRCM registers range - -The prcm node may contain several subdevices definitions: - - see Documentation/devicetree/bindings/clock/sunxi.txt for clock devices - - see Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt for reset - controller devices - - -Example: - - prcm: prcm@1f01400 { - compatible = "allwinner,sun6i-a31-prcm"; - reg = <0x01f01400 0x200>; - - /* Put subdevices here */ - ar100: ar100_clk { - compatible = "allwinner,sun6i-a31-ar100-clk"; - #clock-cells = <0>; - clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>; - }; - - ahb0: ahb0_clk { - compatible = "fixed-factor-clock"; - #clock-cells = <0>; - clock-div = <1>; - clock-mult = <1>; - clocks = <&ar100_div>; - clock-output-names = "ahb0"; - }; - - apb0: apb0_clk { - compatible = "allwinner,sun6i-a31-apb0-clk"; - #clock-cells = <0>; - clocks = <&ahb0>; - clock-output-names = "apb0"; - }; - - apb0_gates: apb0_gates_clk { - compatible = "allwinner,sun6i-a31-apb0-gates-clk"; - #clock-cells = <1>; - clocks = <&apb0>; - clock-output-names = "apb0_pio", "apb0_ir", - "apb0_timer01", "apb0_p2wi", - "apb0_uart", "apb0_1wire", - "apb0_i2c"; - }; - - apb0_rst: apb0_rst { - compatible = "allwinner,sun6i-a31-clock-reset"; - #reset-cells = <1>; - }; - }; -- cgit v1.2.3 From 93adc6aef57f169c010071d732940b0f9f1fb5a7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 19 Dec 2019 10:07:12 +0100 Subject: dt-bindings: resets: Convert Allwinner legacy resets to schemas The Allwinner SoCs have a legacy set of bindings (and a framework to support it in Linux) for their reset controllers. Now that we have the DT validation in place, let's split into separate file and convert the device tree bindings for those resets to schemas, and mark them all as deprecated. Signed-off-by: Maxime Ripard Signed-off-by: Rob Herring --- .../reset/allwinner,sun6i-a31-clock-reset.yaml | 68 ++++++++++++++++++++++ .../bindings/reset/allwinner,sunxi-clock-reset.txt | 21 ------- 2 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 Documentation/devicetree/bindings/reset/allwinner,sun6i-a31-clock-reset.yaml delete mode 100644 Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/reset/allwinner,sun6i-a31-clock-reset.yaml b/Documentation/devicetree/bindings/reset/allwinner,sun6i-a31-clock-reset.yaml new file mode 100644 index 000000000000..001c0d2a8c1f --- /dev/null +++ b/Documentation/devicetree/bindings/reset/allwinner,sun6i-a31-clock-reset.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/allwinner,sun6i-a31-clock-reset.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A31 Peripheral Reset Controller Device Tree Bindings + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +deprecated: true + +select: + properties: + compatible: + contains: + enum: + - allwinner,sun6i-a31-ahb1-reset + - allwinner,sun6i-a31-clock-reset + + # The PRCM on the A31 and A23 will have the reg property missing, + # since it's set at the upper level node, and will be validated by + # PRCM's schema. Make sure we only validate standalone nodes. + required: + - compatible + - reg + +properties: + "#reset-cells": + const: 1 + description: > + This additional argument passed to that reset controller is the + offset of the bit controlling this particular reset line in the + register. + + compatible: + enum: + - allwinner,sun6i-a31-ahb1-reset + - allwinner,sun6i-a31-clock-reset + + reg: + maxItems: 1 + +required: + - "#reset-cells" + - compatible + - reg + +additionalProperties: false + +examples: + - | + ahb1_rst: reset@1c202c0 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-ahb1-reset"; + reg = <0x01c202c0 0xc>; + }; + + - | + apbs_rst: reset@80014b0 { + #reset-cells = <1>; + compatible = "allwinner,sun6i-a31-clock-reset"; + reg = <0x080014b0 0x4>; + }; + +... diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt deleted file mode 100644 index 4ca66c96fe97..000000000000 --- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt +++ /dev/null @@ -1,21 +0,0 @@ -Allwinner sunxi Peripheral Reset Controller -=========================================== - -Please also refer to reset.txt in this directory for common reset -controller binding usage. - -Required properties: -- compatible: Should be one of the following: - "allwinner,sun6i-a31-ahb1-reset" - "allwinner,sun6i-a31-clock-reset" -- reg: should be register base and length as documented in the - datasheet -- #reset-cells: 1, see below - -example: - -ahb1_rst: reset@1c202c0 { - #reset-cells = <1>; - compatible = "allwinner,sun6i-a31-ahb1-reset"; - reg = <0x01c202c0 0xc>; -}; -- cgit v1.2.3 From c5a05bd6455a358d9063f6e7a8c3fdcc60a61b32 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 18 Dec 2019 15:26:13 +0100 Subject: dt-bindings: usb: amlogic, meson-g12a-usb-ctrl: fix clock names dwc2 bindings require clock-names to be "otg". Fix the example in amlogic,meson-g12a-usb-ctrl to follow this requirement. Signed-off-by: Benjamin Gaignard Acked-by: Neil Armstrong Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml b/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml index 4efb77b653ab..267fce165994 100644 --- a/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml +++ b/Documentation/devicetree/bindings/usb/amlogic,meson-g12a-usb-ctrl.yaml @@ -107,7 +107,7 @@ examples: reg = <0xff400000 0x40000>; interrupts = <31>; clocks = <&clkc_usb1>; - clock-names = "ddr"; + clock-names = "otg"; phys = <&usb2_phy1>; dr_mode = "peripheral"; g-rx-fifo-size = <192>; -- cgit v1.2.3 From 6ffdc742156887f8959733866adab5d486b751a5 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Thu, 19 Dec 2019 15:41:15 +0100 Subject: dt-bindings: nvmem: Convert STM32 ROMEM to json-schema Convert the STM32 ROMEM binding to DT schema format using json-schema Signed-off-by: Benjamin Gaignard Signed-off-by: Rob Herring --- .../devicetree/bindings/nvmem/st,stm32-romem.txt | 31 --------------- .../devicetree/bindings/nvmem/st,stm32-romem.yaml | 46 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 31 deletions(-) delete mode 100644 Documentation/devicetree/bindings/nvmem/st,stm32-romem.txt create mode 100644 Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.txt b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.txt deleted file mode 100644 index 142a51d5a9be..000000000000 --- a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.txt +++ /dev/null @@ -1,31 +0,0 @@ -STMicroelectronics STM32 Factory-programmed data device tree bindings - -This represents STM32 Factory-programmed read only non-volatile area: locked -flash, OTP, read-only HW regs... This contains various information such as: -analog calibration data for temperature sensor (e.g. TS_CAL1, TS_CAL2), -internal vref (VREFIN_CAL), unique device ID... - -Required properties: -- compatible: Should be one of: - "st,stm32f4-otp" - "st,stm32mp15-bsec" -- reg: Offset and length of factory-programmed area. -- #address-cells: Should be '<1>'. -- #size-cells: Should be '<1>'. - -Optional Data cells: -- Must be child nodes as described in nvmem.txt. - -Example on stm32f4: - romem: nvmem@1fff7800 { - compatible = "st,stm32f4-otp"; - reg = <0x1fff7800 0x400>; - #address-cells = <1>; - #size-cells = <1>; - - /* Data cells: ts_cal1 at 0x1fff7a2c */ - ts_cal1: calib@22c { - reg = <0x22c 0x2>; - }; - ... - }; diff --git a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml new file mode 100644 index 000000000000..d84deb4774a4 --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/nvmem/st,stm32-romem.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Factory-programmed data bindings + +description: | + This represents STM32 Factory-programmed read only non-volatile area: locked + flash, OTP, read-only HW regs... This contains various information such as: + analog calibration data for temperature sensor (e.g. TS_CAL1, TS_CAL2), + internal vref (VREFIN_CAL), unique device ID... + +maintainers: + - Fabrice Gasnier + +allOf: + - $ref: "nvmem.yaml#" + +properties: + compatible: + enum: + - st,stm32f4-otp + - st,stm32mp15-bsec + +required: + - "#address-cells" + - "#size-cells" + - compatible + - reg + +examples: + - | + efuse@1fff7800 { + compatible = "st,stm32f4-otp"; + reg = <0x1fff7800 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + calib@22c { + reg = <0x22c 0x2>; + }; + }; + +... -- cgit v1.2.3 From bb9ee1eacb2dfcdf419f14c739b866c3eba4dc1f Mon Sep 17 00:00:00 2001 From: "Angus Ainslie (Purism)" Date: Mon, 23 Dec 2019 07:47:12 -0800 Subject: dt-bindings: sound: gtm601: add the broadmobi interface The Broadmobi BM818 uses a different sample rate and channels from the option modem. Signed-off-by: Angus Ainslie (Purism) Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191223154712.18581-3-angus@akkea.ca Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/gtm601.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sound/gtm601.txt b/Documentation/devicetree/bindings/sound/gtm601.txt index 5efc8c068de0..efa32a486c4a 100644 --- a/Documentation/devicetree/bindings/sound/gtm601.txt +++ b/Documentation/devicetree/bindings/sound/gtm601.txt @@ -1,10 +1,16 @@ GTM601 UMTS modem audio interface CODEC -This device has no configuration interface. Sample rate is fixed - 8kHz. +This device has no configuration interface. The sample rate and channels are +based on the compatible string + "option,gtm601" = 8kHz mono + "broadmobi,bm818" = 48KHz stereo Required properties: - - compatible : "option,gtm601" + - compatible : one of + "option,gtm601" + "broadmobi,bm818" + Example: -- cgit v1.2.3 From a6b748713205242d1483a78662bf147b1aa7d90b Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 19 Dec 2019 10:31:43 +0000 Subject: ASoC: dt-bindings: add dt bindings for WCD9340/WCD9341 audio codec This patch adds bindings for wcd9340/wcd9341 audio codec which can support both SLIMbus and I2S/I2C interface. Signed-off-by: Srinivas Kandagatla Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20191219103153.14875-2-srinivas.kandagatla@linaro.org Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/qcom,wcd934x.yaml | 175 +++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml new file mode 100644 index 000000000000..38eaf0c028f9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/qcom,wcd934x.yaml @@ -0,0 +1,175 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/qcom,wcd934x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bindings for Qualcomm WCD9340/WCD9341 Audio Codec + +maintainers: + - Srinivas Kandagatla + +description: | + Qualcomm WCD9340/WCD9341 Codec is a standalone Hi-Fi audio codec IC. + It has in-built Soundwire controller, pin controller, interrupt mux and + supports both I2S/I2C and SLIMbus audio interfaces. + +properties: + compatible: + const: slim217,250 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + reset-gpios: + description: GPIO spec for reset line to use + maxItems: 1 + + slim-ifc-dev: true + + clocks: + maxItems: 1 + + clock-names: + const: extclk + + vdd-buck-supply: + description: A reference to the 1.8V buck supply + + vdd-buck-sido-supply: + description: A reference to the 1.8V SIDO buck supply + + vdd-rx-supply: + description: A reference to the 1.8V rx supply + + vdd-tx-supply: + description: A reference to the 1.8V tx supply + + vdd-vbat-supply: + description: A reference to the vbat supply + + vdd-io-supply: + description: A reference to the 1.8V I/O supply + + vdd-micbias-supply: + description: A reference to the micbias supply + + qcom,micbias1-microvolt: + description: micbias1 voltage + minimum: 1800000 + maximum: 2850000 + + qcom,micbias2-microvolt: + description: micbias2 voltage + minimum: 1800000 + maximum: 2850000 + + qcom,micbias3-microvolt: + description: micbias3 voltage + minimum: 1800000 + maximum: 2850000 + + qcom,micbias4-microvolt: + description: micbias4 voltage + minimum: 1800000 + maximum: 2850000 + + clock-output-names: + const: mclk + + clock-frequency: + description: Clock frequency of output clk in Hz + + interrupt-controller: true + + '#interrupt-cells': + const: 1 + + '#clock-cells': + const: 0 + + '#sound-dai-cells': + const: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + gpio@42: + type: object + allOf: + - $ref: ../gpio/qcom,wcd934x-gpio.yaml# + +patternProperties: + "^.*@[0-9a-f]+$": + type: object + description: | + WCD934x subnode for each slave devices. Bindings of each subnodes + depends on the specific driver providing the functionality and + documented in their respective bindings. + + properties: + reg: + maxItems: 1 + + required: + - reg + +required: + - compatible + - reg + - reset-gpios + - slim-ifc-dev + - interrupts + - interrupt-controller + - clock-frequency + - clock-output-names + - qcom,micbias1-microvolt + - qcom,micbias2-microvolt + - qcom,micbias3-microvolt + - qcom,micbias4-microvolt + - "#interrupt-cells" + - "#clock-cells" + - "#sound-dai-cells" + - "#address-cells" + - "#size-cells" + +examples: + - | + codec@1,0{ + compatible = "slim217,250"; + reg = <1 0>; + reset-gpios = <&tlmm 64 0>; + slim-ifc-dev = <&wcd9340_ifd>; + #sound-dai-cells = <1>; + interrupt-parent = <&tlmm>; + interrupts = <54 4>; + interrupt-controller; + #interrupt-cells = <1>; + #clock-cells = <0>; + clock-frequency = <9600000>; + clock-output-names = "mclk"; + qcom,micbias1-microvolt = <1800000>; + qcom,micbias2-microvolt = <1800000>; + qcom,micbias3-microvolt = <1800000>; + qcom,micbias4-microvolt = <1800000>; + clock-names = "extclk"; + clocks = <&rpmhcc 2>; + + #address-cells = <1>; + #size-cells = <1>; + + gpio@42 { + compatible = "qcom,wcd9340-gpio"; + reg = <0x42 0x2>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + +... -- cgit v1.2.3 From 834d899794f4ec3bbf9836c85e8f76b7de6e8a59 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 19 Dec 2019 10:31:52 +0000 Subject: ASoC: qcom: dt-bindings: Add compatible for DB845c and Lenovo Yoga This patch adds compatible strings for DB845c and Lenovo Yoga C630 soundcard. Based on this compatible strings common machine driver will be in better position to setup board specific configuration. Signed-off-by: Srinivas Kandagatla Acked-by: Rob Herring Link: https://lore.kernel.org/r/20191219103153.14875-11-srinivas.kandagatla@linaro.org Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/qcom,sdm845.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/sound/qcom,sdm845.txt b/Documentation/devicetree/bindings/sound/qcom,sdm845.txt index 408c4837e6d5..ca8c89e88bfa 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sdm845.txt +++ b/Documentation/devicetree/bindings/sound/qcom,sdm845.txt @@ -5,7 +5,10 @@ This binding describes the SDM845 sound card, which uses qdsp for audio. - compatible: Usage: required Value type: - Definition: must be "qcom,sdm845-sndcard" + Definition: must be one of this + "qcom,sdm845-sndcard" + "qcom,db845c-sndcard" + "lenovo,yoga-c630-sndcard" - audio-routing: Usage: Optional -- cgit v1.2.3 From 92ac62e1c3efc87d40ffec3e3626d28a408c508d Mon Sep 17 00:00:00 2001 From: Stephan Gerhold Date: Thu, 19 Dec 2019 21:20:46 +0100 Subject: dt-bindings: arm: ux500: Document samsung,golden compatible The Samsung Galaxy S III mini ("samsung-golden") can now boot mainline Linux; document the samsung,golden compatible that is used in its device tree. Signed-off-by: Stephan Gerhold Link: https://lore.kernel.org/r/20191219202052.19039-4-stephan@gerhold.net Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/arm/ux500.yaml | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/ux500.yaml b/Documentation/devicetree/bindings/arm/ux500.yaml index 006cb4a5f331..accaee906050 100644 --- a/Documentation/devicetree/bindings/arm/ux500.yaml +++ b/Documentation/devicetree/bindings/arm/ux500.yaml @@ -29,3 +29,8 @@ properties: items: - const: calaosystems,snowball-a9500 - const: st-ericsson,u9500 + + - description: Samsung Galaxy S III mini (GT-I8190) + items: + - const: samsung,golden + - const: st-ericsson,u8500 -- cgit v1.2.3 From 52fa562db5ecd2c4ae91a1106844877b02af7031 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 10 Dec 2019 10:53:50 -0800 Subject: dt-bindings: ata: Document BCM7216 AHCI controller compatible The BCM7216 AHCI controller makes use of a specific reset controller line/name, document the compatible string and the optional reset properties. Reviewed-by: Rob Herring Reviewed-by: Hans de Goede Signed-off-by: Florian Fainelli Signed-off-by: Jens Axboe --- Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt index 7713a413c6a7..b9ae4ce4a0a0 100644 --- a/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt +++ b/Documentation/devicetree/bindings/ata/brcm,sata-brcm.txt @@ -5,6 +5,7 @@ Each SATA controller should have its own node. Required properties: - compatible : should be one or more of + "brcm,bcm7216-ahci" "brcm,bcm7425-ahci" "brcm,bcm7445-ahci" "brcm,bcm-nsp-ahci" @@ -14,6 +15,12 @@ Required properties: - reg-names : "ahci" and "top-ctrl" - interrupts : interrupt mapping for SATA IRQ +Optional properties: + +- reset: for "brcm,bcm7216-ahci" must be a valid reset phandle + pointing to the RESCAL reset controller provider node. +- reset-names: for "brcm,bcm7216-ahci", must be "rescal". + Also see ahci-platform.txt. Example: -- cgit v1.2.3 From 25d12e1dde28fafd2ac37afadd24252fa19b80cd Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Wed, 25 Dec 2019 18:16:17 -0800 Subject: dt-bindings: ptp: Introduce MII time stamping devices. This patch add a new binding that allows non-PHY MII time stamping devices to find their buses. The new documentation covers both the generic binding and one upcoming user. Signed-off-by: Richard Cochran Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/ptp/ptp-ines.txt | 35 ++++++++++++++++++ .../devicetree/bindings/ptp/timestamper.txt | 42 ++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 Documentation/devicetree/bindings/ptp/ptp-ines.txt create mode 100644 Documentation/devicetree/bindings/ptp/timestamper.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/ptp/ptp-ines.txt b/Documentation/devicetree/bindings/ptp/ptp-ines.txt new file mode 100644 index 000000000000..4c242bd1ce9c --- /dev/null +++ b/Documentation/devicetree/bindings/ptp/ptp-ines.txt @@ -0,0 +1,35 @@ +ZHAW InES PTP time stamping IP core + +The IP core needs two different kinds of nodes. The control node +lives somewhere in the memory map and specifies the address of the +control registers. There can be up to three port handles placed as +attributes of PHY nodes. These associate a particular MII bus with a +port index within the IP core. + +Required properties of the control node: + +- compatible: "ines,ptp-ctrl" +- reg: physical address and size of the register bank + +Required format of the port handle within the PHY node: + +- timestamper: provides control node reference and + the port channel within the IP core + +Example: + + tstamper: timestamper@60000000 { + compatible = "ines,ptp-ctrl"; + reg = <0x60000000 0x80>; + }; + + ethernet@80000000 { + ... + mdio { + ... + ethernet-phy@3 { + ... + timestamper = <&tstamper 0>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/ptp/timestamper.txt b/Documentation/devicetree/bindings/ptp/timestamper.txt new file mode 100644 index 000000000000..fc550ce4d4ea --- /dev/null +++ b/Documentation/devicetree/bindings/ptp/timestamper.txt @@ -0,0 +1,42 @@ +Time stamps from MII bus snooping devices + +This binding supports non-PHY devices that snoop the MII bus and +provide time stamps. In contrast to PHY time stamping drivers (which +can simply attach their interface directly to the PHY instance), stand +alone MII time stamping drivers use this binding to specify the +connection between the snooping device and a given network interface. + +Non-PHY MII time stamping drivers typically talk to the control +interface over another bus like I2C, SPI, UART, or via a memory mapped +peripheral. This controller device is associated with one or more +time stamping channels, each of which snoops on a MII bus. + +The "timestamper" property lives in a phy node and links a time +stamping channel from the controller device to that phy's MII bus. + +Example: + + tstamper: timestamper@10000000 { + compatible = "ines,ptp-ctrl"; + reg = <0x10000000 0x80>; + }; + + ethernet@20000000 { + mdio { + ethernet-phy@1 { + timestamper = <&tstamper 0>; + }; + }; + }; + + ethernet@30000000 { + mdio { + ethernet-phy@2 { + timestamper = <&tstamper 1>; + }; + }; + }; + +In this example, time stamps from the MII bus attached to phy@1 will +appear on time stamp channel 0 (zero), and those from phy@2 appear on +channel 1. -- cgit v1.2.3 From fe5040f2843a638d847282520e5eeaa61a4769e2 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:23 +0530 Subject: dt-bindings: sun6i-dsi: Document A64 MIPI-DSI controller The MIPI DSI controller in Allwinner A64 is similar to A33. But unlike A33, A64 doesn't have DSI_SCLK gating so it is valid to have separate compatible for A64 on the same driver. DSI_SCLK uses mod clock-names on dt-bindings, so the same is not required for A64. On that note - A64 require minimum of 1 clock like the bus clock - A33 require minimum of 2 clocks like both bus, mod clocks So, update dt-bindings so-that it can document both A33, A64 bindings requirements. Reviewed-by: Rob Herring Signed-off-by: Jagan Teki Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-2-jagan@amarulasolutions.com --- .../display/allwinner,sun6i-a31-mipi-dsi.yaml | 33 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml index dafc0980c4fa..d41ecb5e7f7c 100644 --- a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml +++ b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml @@ -15,7 +15,9 @@ properties: "#size-cells": true compatible: - const: allwinner,sun6i-a31-mipi-dsi + enum: + - allwinner,sun6i-a31-mipi-dsi + - allwinner,sun50i-a64-mipi-dsi reg: maxItems: 1 @@ -24,6 +26,8 @@ properties: maxItems: 1 clocks: + minItems: 1 + maxItems: 2 items: - description: Bus Clock - description: Module Clock @@ -63,13 +67,38 @@ required: - reg - interrupts - clocks - - clock-names - phys - phy-names - resets - vcc-dsi-supply - port +allOf: + - if: + properties: + compatible: + contains: + const: allwinner,sun6i-a31-mipi-dsi + + then: + properties: + clocks: + minItems: 2 + + required: + - clock-names + + - if: + properties: + compatible: + contains: + const: allwinner,sun50i-a64-mipi-dsi + + then: + properties: + clocks: + minItems: 1 + additionalProperties: false examples: -- cgit v1.2.3 From db08ca5a64d208645301600e79f34e441e5da986 Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Sun, 22 Dec 2019 18:52:24 +0530 Subject: dt-bindings: sun6i-dsi: Add A64 DPHY compatible (w/ A31 fallback) The MIPI DSI PHY controller on Allwinner A64 is similar on the one on A31. Add A64 compatible and append A31 compatible as fallback. Reviewed-by: Rob Herring Signed-off-by: Jagan Teki Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20191222132229.30276-3-jagan@amarulasolutions.com --- .../devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml index fa46670de299..8841938050b2 100644 --- a/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml +++ b/Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml @@ -15,7 +15,11 @@ properties: const: 0 compatible: - const: allwinner,sun6i-a31-mipi-dphy + oneOf: + - const: allwinner,sun6i-a31-mipi-dphy + - items: + - const: allwinner,sun50i-a64-mipi-dphy + - const: allwinner,sun6i-a31-mipi-dphy reg: maxItems: 1 -- cgit v1.2.3 From 1b27080ab24506263d9b789e2f5e998cf618b92c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 24 Dec 2019 14:15:55 +0800 Subject: ARM: dts: sunxi: Add Libre Computer ALL-H3-IT H5 board The Libre Computer ALL-H3-IT board is a small single board computer that is roughly the same size as the Raspberry Pi Zero, or around 20% smaller than a credit card. The board features: - H2, H3, or H5 SoC from Allwinner - 2 DDR3 DRAM chips - Realtek RTL8821CU based WiFi module - 128 Mbit SPI-NOR flash - micro-SD card slot - micro HDMI video output - FPC connector for camera sensor module - generic Raspberri-Pi style 40 pin GPIO header - additional pin headers for extra USB host ports, ananlog audio and IR receiver Only H5 variant test samples were made available, but the vendor does have plans to include at least an H3 variant. Thus the device tree is split much like the ALL-H3-CC, with a common dtsi file for the board design, and separate dts files including the common board file and the SoC dtsi file. The other variants will be added as they are made available. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 + arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi | 180 +++++++++++++++++++++ arch/arm64/boot/dts/allwinner/Makefile | 1 + .../allwinner/sun50i-h5-libretech-all-h3-it.dts | 11 ++ 4 files changed, 197 insertions(+) create mode 100644 arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index eaa042fc090f..a2edf5299e48 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -342,6 +342,11 @@ properties: - const: libretech,all-h3-cc-h5 - const: allwinner,sun50i-h5 + - description: Libre Computer Board ALL-H3-IT H5 + items: + - const: libretech,all-h3-it-h5 + - const: allwinner,sun50i-h5 + - description: Lichee Pi One items: - const: licheepi,licheepi-one diff --git a/arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi b/arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi new file mode 100644 index 000000000000..204fba3614f9 --- /dev/null +++ b/arch/arm/boot/dts/sunxi-libretech-all-h3-it.dtsi @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2019 Chen-Yu Tsai + +#include +#include + +/ { + aliases { + serial0 = &uart0; + spi0 = &spi0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + connector { + compatible = "hdmi-connector"; + type = "d"; + + port { + hdmi_con_in: endpoint { + remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + status_led { + label = "librecomputer:blue:status"; + gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA7 */ + }; + }; + + reg_vcc3v3: vcc3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc5v0>; + }; + + /* This represents the board's 5V input */ + reg_vcc5v0: vcc5v0 { + compatible = "regulator-fixed"; + regulator-name = "vcc5v0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + regulator-boot-on; + }; + + reg_vcc_dram: vcc-dram { + compatible = "regulator-fixed"; + regulator-name = "vcc-dram"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc5v0>; + gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */ + enable-active-high; + }; + + reg_vcc_io: vcc-io { + compatible = "regulator-fixed"; + regulator-name = "vcc-io"; + /* This is simply a MOSFET switch */ + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc3v3>; + gpio = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */ + }; + + reg_vcc_usbwifi: vcc-usbwifi { + compatible = "regulator-fixed"; + regulator-name = "vcc-usbwifi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_vcc5v0>; + gpio = <&pio 6 4 GPIO_ACTIVE_HIGH>; /* PG4 */ + enable-active-high; + }; + + reg_vdd_cpux: vdd-cpux { + compatible = "regulator-fixed"; + regulator-name = "vdd-cpux"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <®_vcc5v0>; + gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ + enable-active-high; + }; +}; + +&cpu0 { + cpu-supply = <®_vdd_cpux>; +}; + +&cpu1 { + cpu-supply = <®_vdd_cpux>; +}; + +&cpu2 { + cpu-supply = <®_vdd_cpux>; +}; + +&cpu3 { + cpu-supply = <®_vdd_cpux>; +}; + +&de { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&hdmi { + status = "okay"; +}; + +&hdmi_out { + hdmi_out_con: endpoint { + remote-endpoint = <&hdmi_con_in>; + }; +}; + +&mmc0 { + vmmc-supply = <®_vcc_io>; + bus-width = <4>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + status = "okay"; +}; + +&pio { + vcc-pa-supply = <®_vcc_io>; + vcc-pc-supply = <®_vcc_io>; + vcc-pd-supply = <®_vcc_io>; + vcc-pe-supply = <®_vcc_io>; + vcc-pf-supply = <®_vcc_io>; + vcc-pg-supply = <®_vcc_io>; +}; + +&r_pio { + vcc-pl-supply = <®_vcc3v3>; +}; + +&spi0 { + status = "okay"; + + spiflash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pa_pins>; + status = "okay"; +}; + +&usb_otg { + dr_mode = "peripheral"; + status = "okay"; +}; + +&usbphy { + usb1_vbus-supply = <®_vcc_usbwifi>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index 62bc43f187bf..a7fdf04ffca2 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -15,6 +15,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus-v1.2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-emlid-neutis-n5-devboard.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-cc.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-it.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts new file mode 100644 index 000000000000..e59d68b525fc --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dts @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2019 Chen-Yu Tsai + +/dts-v1/; +#include "sun50i-h5.dtsi" +#include + +/ { + model = "Libre Computer Board ALL-H3-IT H5"; + compatible = "libretech,all-h3-it-h5", "allwinner,sun50i-h5"; +}; -- cgit v1.2.3 From 75a80267410e38ab76c4ceb39753f96d72113781 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 13 Dec 2019 09:56:13 +0100 Subject: cpuidle: Allow idle states to be disabled by default In certain situations it may be useful to prevent some idle states from being used by default while allowing user space to enable them later on. For this purpose, introduce a new state flag, CPUIDLE_FLAG_OFF, to mark idle states that should be disabled by default, make the core set CPUIDLE_STATE_DISABLED_BY_USER for those states at the initialization time and add a new state attribute in sysfs, "default_status", to inform user space of the initial status of the given idle state ("disabled" if CPUIDLE_FLAG_OFF is set for it, "enabled" otherwise). Signed-off-by: Rafael J. Wysocki --- Documentation/ABI/testing/sysfs-devices-system-cpu | 6 ++++++ Documentation/admin-guide/pm/cpuidle.rst | 3 +++ drivers/cpuidle/cpuidle.c | 6 +++++- drivers/cpuidle/sysfs.c | 10 ++++++++++ include/linux/cpuidle.h | 1 + 5 files changed, 25 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index fc20cde63d1e..2e0e3b45d02a 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -196,6 +196,12 @@ Description: does not reflect it. Likewise, if one enables a deep state but a lighter state still is disabled, then this has no effect. +What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/default_status +Date: December 2019 +KernelVersion: v5.6 +Contact: Linux power management list +Description: + (RO) The default status of this state, "enabled" or "disabled". What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/residency Date: March 2014 diff --git a/Documentation/admin-guide/pm/cpuidle.rst b/Documentation/admin-guide/pm/cpuidle.rst index e70b365dbc60..311cd7cc2b75 100644 --- a/Documentation/admin-guide/pm/cpuidle.rst +++ b/Documentation/admin-guide/pm/cpuidle.rst @@ -506,6 +506,9 @@ object corresponding to it, as follows: ``disable`` Whether or not this idle state is disabled. +``default_status`` + The default status of this state, "enabled" or "disabled". + ``latency`` Exit latency of the idle state in microseconds. diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 33d19c8eb027..a2af7bb8f0a5 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -572,10 +572,14 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) if (!try_module_get(drv->owner)) return -EINVAL; - for (i = 0; i < drv->state_count; i++) + for (i = 0; i < drv->state_count; i++) { if (drv->states[i].flags & CPUIDLE_FLAG_UNUSABLE) dev->states_usage[i].disable |= CPUIDLE_STATE_DISABLED_BY_DRIVER; + if (drv->states[i].flags & CPUIDLE_FLAG_OFF) + dev->states_usage[i].disable |= CPUIDLE_STATE_DISABLED_BY_USER; + } + per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 38ef770be90d..254d1560dc19 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -327,6 +327,14 @@ static ssize_t store_state_disable(struct cpuidle_state *state, return size; } +static ssize_t show_state_default_status(struct cpuidle_state *state, + struct cpuidle_state_usage *state_usage, + char *buf) +{ + return sprintf(buf, "%s\n", + state->flags & CPUIDLE_FLAG_OFF ? "disabled" : "enabled"); +} + define_one_state_ro(name, show_state_name); define_one_state_ro(desc, show_state_desc); define_one_state_ro(latency, show_state_exit_latency); @@ -337,6 +345,7 @@ define_one_state_ro(time, show_state_time); define_one_state_rw(disable, show_state_disable, store_state_disable); define_one_state_ro(above, show_state_above); define_one_state_ro(below, show_state_below); +define_one_state_ro(default_status, show_state_default_status); static struct attribute *cpuidle_state_default_attrs[] = { &attr_name.attr, @@ -349,6 +358,7 @@ static struct attribute *cpuidle_state_default_attrs[] = { &attr_disable.attr, &attr_above.attr, &attr_below.attr, + &attr_default_status.attr, NULL }; diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 1dabe36bd011..ebfb52b3ffbf 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -77,6 +77,7 @@ struct cpuidle_state { #define CPUIDLE_FLAG_COUPLED BIT(1) /* state applies to multiple cpus */ #define CPUIDLE_FLAG_TIMER_STOP BIT(2) /* timer is stopped on this state */ #define CPUIDLE_FLAG_UNUSABLE BIT(3) /* avoid using this state */ +#define CPUIDLE_FLAG_OFF BIT(4) /* disable this state by default */ struct cpuidle_device_kobj; struct cpuidle_state_kobj; -- cgit v1.2.3 From 2b4a8990b7df55875745a80a609a1ceaaf51f322 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:55:18 +0100 Subject: ethtool: introduce ethtool netlink interface Basic genetlink and init infrastructure for the netlink interface, register genetlink family "ethtool". Add CONFIG_ETHTOOL_NETLINK Kconfig option to make the build optional. Add initial overall interface description into Documentation/networking/ethtool-netlink.rst, further patches will add more detailed information. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 216 +++++++++++++++++++++++++++ Documentation/networking/index.rst | 1 + include/linux/ethtool_netlink.h | 9 ++ include/uapi/linux/ethtool_netlink.h | 36 +++++ net/Kconfig | 8 + net/ethtool/Makefile | 6 +- net/ethtool/netlink.c | 33 ++++ net/ethtool/netlink.h | 10 ++ 8 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 Documentation/networking/ethtool-netlink.rst create mode 100644 include/linux/ethtool_netlink.h create mode 100644 include/uapi/linux/ethtool_netlink.h create mode 100644 net/ethtool/netlink.c create mode 100644 net/ethtool/netlink.h (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst new file mode 100644 index 000000000000..9448442ad293 --- /dev/null +++ b/Documentation/networking/ethtool-netlink.rst @@ -0,0 +1,216 @@ +============================= +Netlink interface for ethtool +============================= + + +Basic information +================= + +Netlink interface for ethtool uses generic netlink family ``ethtool`` +(userspace application should use macros ``ETHTOOL_GENL_NAME`` and +``ETHTOOL_GENL_VERSION`` defined in ```` uapi +header). This family does not use a specific header, all information in +requests and replies is passed using netlink attributes. + +The ethtool netlink interface uses extended ACK for error and warning +reporting, userspace application developers are encouraged to make these +messages available to user in a suitable way. + +Requests can be divided into three categories: "get" (retrieving information), +"set" (setting parameters) and "action" (invoking an action). + +All "set" and "action" type requests require admin privileges +(``CAP_NET_ADMIN`` in the namespace). Most "get" type requests are allowed for +anyone but there are exceptions (where the response contains sensitive +information). In some cases, the request as such is allowed for anyone but +unprivileged users have attributes with sensitive information (e.g. +wake-on-lan password) omitted. + + +Conventions +=========== + +Attributes which represent a boolean value usually use NLA_U8 type so that we +can distinguish three states: "on", "off" and "not present" (meaning the +information is not available in "get" requests or value is not to be changed +in "set" requests). For these attributes, the "true" value should be passed as +number 1 but any non-zero value should be understood as "true" by recipient. +In the tables below, "bool" denotes NLA_U8 attributes interpreted in this way. + +In the message structure descriptions below, if an attribute name is suffixed +with "+", parent nest can contain multiple attributes of the same type. This +implements an array of entries. + + +Request header +============== + +Each request or reply message contains a nested attribute with common header. +Structure of this header is + + ============================== ====== ============================= + ``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex + ``ETHTOOL_A_HEADER_DEV_NAME`` string device name + ``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests + ============================== ====== ============================= + +``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the +device message relates to. One of them is sufficient in requests, if both are +used, they must identify the same device. Some requests, e.g. global string +sets, do not require device identification. Most ``GET`` requests also allow +dump requests without device identification to query the same information for +all devices providing it (each device in a separate message). + +``ETHTOOL_A_HEADER_FLAGS`` is a bitmap of request flags common for all request +types. The interpretation of these flags is the same for all request types but +the flags may not apply to requests. Recognized flags are: + + ================================= =================================== + ``ETHTOOL_FLAG_COMPACT_BITSETS`` use compact format bitsets in reply + ``ETHTOOL_FLAG_OMIT_REPLY`` omit optional reply (_SET and _ACT) + ================================= =================================== + +New request flags should follow the general idea that if the flag is not set, +the behaviour is backward compatible, i.e. requests from old clients not aware +of the flag should be interpreted the way the client expects. A client must +not set flags it does not understand. + + +List of message types +===================== + +All constants identifying message types use ``ETHTOOL_CMD_`` prefix and suffix +according to message purpose: + + ============== ====================================== + ``_GET`` userspace request to retrieve data + ``_SET`` userspace request to set data + ``_ACT`` userspace request to perform an action + ``_GET_REPLY`` kernel reply to a ``GET`` request + ``_SET_REPLY`` kernel reply to a ``SET`` request + ``_ACT_REPLY`` kernel reply to an ``ACT`` request + ``_NTF`` kernel notification + ============== ====================================== + +``GET`` requests are sent by userspace applications to retrieve device +information. They usually do not contain any message specific attributes. +Kernel replies with corresponding "GET_REPLY" message. For most types, ``GET`` +request with ``NLM_F_DUMP`` and no device identification can be used to query +the information for all devices supporting the request. + +If the data can be also modified, corresponding ``SET`` message with the same +layout as corresponding ``GET_REPLY`` is used to request changes. Only +attributes where a change is requested are included in such request (also, not +all attributes may be changed). Replies to most ``SET`` request consist only +of error code and extack; if kernel provides additional data, it is sent in +the form of corresponding ``SET_REPLY`` message which can be suppressed by +setting ``ETHTOOL_FLAG_OMIT_REPLY`` flag in request header. + +Data modification also triggers sending a ``NTF`` message with a notification. +These usually bear only a subset of attributes which was affected by the +change. The same notification is issued if the data is modified using other +means (mostly ioctl ethtool interface). Unlike notifications from ethtool +netlink code which are only sent if something actually changed, notifications +triggered by ioctl interface may be sent even if the request did not actually +change any data. + +``ACT`` messages request kernel (driver) to perform a specific action. If some +information is reported by kernel (which can be suppressed by setting +``ETHTOOL_FLAG_OMIT_REPLY`` flag in request header), the reply takes form of +an ``ACT_REPLY`` message. Performing an action also triggers a notification +(``NTF`` message). + +Later sections describe the format and semantics of these messages. + + +Request translation +=================== + +The following table maps ioctl commands to netlink commands providing their +functionality. Entries with "n/a" in right column are commands which do not +have their netlink replacement yet. + + =================================== ===================================== + ioctl command netlink command + =================================== ===================================== + ``ETHTOOL_GSET`` n/a + ``ETHTOOL_SSET`` n/a + ``ETHTOOL_GDRVINFO`` n/a + ``ETHTOOL_GREGS`` n/a + ``ETHTOOL_GWOL`` n/a + ``ETHTOOL_SWOL`` n/a + ``ETHTOOL_GMSGLVL`` n/a + ``ETHTOOL_SMSGLVL`` n/a + ``ETHTOOL_NWAY_RST`` n/a + ``ETHTOOL_GLINK`` n/a + ``ETHTOOL_GEEPROM`` n/a + ``ETHTOOL_SEEPROM`` n/a + ``ETHTOOL_GCOALESCE`` n/a + ``ETHTOOL_SCOALESCE`` n/a + ``ETHTOOL_GRINGPARAM`` n/a + ``ETHTOOL_SRINGPARAM`` n/a + ``ETHTOOL_GPAUSEPARAM`` n/a + ``ETHTOOL_SPAUSEPARAM`` n/a + ``ETHTOOL_GRXCSUM`` n/a + ``ETHTOOL_SRXCSUM`` n/a + ``ETHTOOL_GTXCSUM`` n/a + ``ETHTOOL_STXCSUM`` n/a + ``ETHTOOL_GSG`` n/a + ``ETHTOOL_SSG`` n/a + ``ETHTOOL_TEST`` n/a + ``ETHTOOL_GSTRINGS`` n/a + ``ETHTOOL_PHYS_ID`` n/a + ``ETHTOOL_GSTATS`` n/a + ``ETHTOOL_GTSO`` n/a + ``ETHTOOL_STSO`` n/a + ``ETHTOOL_GPERMADDR`` rtnetlink ``RTM_GETLINK`` + ``ETHTOOL_GUFO`` n/a + ``ETHTOOL_SUFO`` n/a + ``ETHTOOL_GGSO`` n/a + ``ETHTOOL_SGSO`` n/a + ``ETHTOOL_GFLAGS`` n/a + ``ETHTOOL_SFLAGS`` n/a + ``ETHTOOL_GPFLAGS`` n/a + ``ETHTOOL_SPFLAGS`` n/a + ``ETHTOOL_GRXFH`` n/a + ``ETHTOOL_SRXFH`` n/a + ``ETHTOOL_GGRO`` n/a + ``ETHTOOL_SGRO`` n/a + ``ETHTOOL_GRXRINGS`` n/a + ``ETHTOOL_GRXCLSRLCNT`` n/a + ``ETHTOOL_GRXCLSRULE`` n/a + ``ETHTOOL_GRXCLSRLALL`` n/a + ``ETHTOOL_SRXCLSRLDEL`` n/a + ``ETHTOOL_SRXCLSRLINS`` n/a + ``ETHTOOL_FLASHDEV`` n/a + ``ETHTOOL_RESET`` n/a + ``ETHTOOL_SRXNTUPLE`` n/a + ``ETHTOOL_GRXNTUPLE`` n/a + ``ETHTOOL_GSSET_INFO`` n/a + ``ETHTOOL_GRXFHINDIR`` n/a + ``ETHTOOL_SRXFHINDIR`` n/a + ``ETHTOOL_GFEATURES`` n/a + ``ETHTOOL_SFEATURES`` n/a + ``ETHTOOL_GCHANNELS`` n/a + ``ETHTOOL_SCHANNELS`` n/a + ``ETHTOOL_SET_DUMP`` n/a + ``ETHTOOL_GET_DUMP_FLAG`` n/a + ``ETHTOOL_GET_DUMP_DATA`` n/a + ``ETHTOOL_GET_TS_INFO`` n/a + ``ETHTOOL_GMODULEINFO`` n/a + ``ETHTOOL_GMODULEEEPROM`` n/a + ``ETHTOOL_GEEE`` n/a + ``ETHTOOL_SEEE`` n/a + ``ETHTOOL_GRSSH`` n/a + ``ETHTOOL_SRSSH`` n/a + ``ETHTOOL_GTUNABLE`` n/a + ``ETHTOOL_STUNABLE`` n/a + ``ETHTOOL_GPHYSTATS`` n/a + ``ETHTOOL_PERQUEUE`` n/a + ``ETHTOOL_GLINKSETTINGS`` n/a + ``ETHTOOL_SLINKSETTINGS`` n/a + ``ETHTOOL_PHY_GTUNABLE`` n/a + ``ETHTOOL_PHY_STUNABLE`` n/a + ``ETHTOOL_GFECPARAM`` n/a + ``ETHTOOL_SFECPARAM`` n/a + =================================== ===================================== diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst index 5acab1290e03..bee73be7af93 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -16,6 +16,7 @@ Contents: devlink-info-versions devlink-trap devlink-trap-netdevsim + ethtool-netlink ieee802154 j1939 kapi diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h new file mode 100644 index 000000000000..f27e92b5f344 --- /dev/null +++ b/include/linux/ethtool_netlink.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _LINUX_ETHTOOL_NETLINK_H_ +#define _LINUX_ETHTOOL_NETLINK_H_ + +#include +#include + +#endif /* _LINUX_ETHTOOL_NETLINK_H_ */ diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h new file mode 100644 index 000000000000..3c93276ba066 --- /dev/null +++ b/include/uapi/linux/ethtool_netlink.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * include/uapi/linux/ethtool_netlink.h - netlink interface for ethtool + * + * See Documentation/networking/ethtool-netlink.txt in kernel source tree for + * doucumentation of the interface. + */ + +#ifndef _UAPI_LINUX_ETHTOOL_NETLINK_H_ +#define _UAPI_LINUX_ETHTOOL_NETLINK_H_ + +#include + +/* message types - userspace to kernel */ +enum { + ETHTOOL_MSG_USER_NONE, + + /* add new constants above here */ + __ETHTOOL_MSG_USER_CNT, + ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1 +}; + +/* message types - kernel to userspace */ +enum { + ETHTOOL_MSG_KERNEL_NONE, + + /* add new constants above here */ + __ETHTOOL_MSG_KERNEL_CNT, + ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1 +}; + +/* generic netlink info */ +#define ETHTOOL_GENL_NAME "ethtool" +#define ETHTOOL_GENL_VERSION 1 + +#endif /* _UAPI_LINUX_ETHTOOL_NETLINK_H_ */ diff --git a/net/Kconfig b/net/Kconfig index 52af65e5d28c..54916b7adb9b 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -449,6 +449,14 @@ config FAILOVER migration of VMs with direct attached VFs by failing over to the paravirtual datapath when the VF is unplugged. +config ETHTOOL_NETLINK + bool "Netlink interface for ethtool" + default y + help + An alternative userspace interface for ethtool based on generic + netlink. It provides better extensibility and some new features, + e.g. notification messages. + endif # if NET # Used by archs to tell that they support BPF JIT compiler plus which flavour. diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index f68387618973..59d5ee230c29 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -1,3 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y += ioctl.o common.o +obj-y += ioctl.o common.o + +obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o + +ethtool_nl-y := netlink.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c new file mode 100644 index 000000000000..59e1ebde2f15 --- /dev/null +++ b/net/ethtool/netlink.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include "netlink.h" + +/* genetlink setup */ + +static const struct genl_ops ethtool_genl_ops[] = { +}; + +static struct genl_family ethtool_genl_family = { + .name = ETHTOOL_GENL_NAME, + .version = ETHTOOL_GENL_VERSION, + .netnsok = true, + .parallel_ops = true, + .ops = ethtool_genl_ops, + .n_ops = ARRAY_SIZE(ethtool_genl_ops), +}; + +/* module setup */ + +static int __init ethnl_init(void) +{ + int ret; + + ret = genl_register_family(ðtool_genl_family); + if (WARN(ret < 0, "ethtool: genetlink family registration failed")) + return ret; + + return 0; +} + +subsys_initcall(ethnl_init); diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h new file mode 100644 index 000000000000..e4220780d368 --- /dev/null +++ b/net/ethtool/netlink.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _NET_ETHTOOL_NETLINK_H +#define _NET_ETHTOOL_NETLINK_H + +#include +#include +#include + +#endif /* _NET_ETHTOOL_NETLINK_H */ -- cgit v1.2.3 From 10b518d4e6dd5390e40f7d8de0f08753c1195a7e Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:55:28 +0100 Subject: ethtool: netlink bitset handling The ethtool netlink code uses common framework for passing arbitrary length bit sets to allow future extensions. A bitset can be a list (only one bitmap) or can consist of value and mask pair (used e.g. when client want to modify only some bits). A bitset can use one of two formats: verbose (bit by bit) or compact. Verbose format consists of bitset size (number of bits), list flag and an array of bit nests, telling which bits are part of the list or which bits are in the mask and which of them are to be set. In requests, bits can be identified by index (position) or by name. In replies, kernel provides both index and name. Verbose format is suitable for "one shot" applications like standard ethtool command as it avoids the need to either keep bit names (e.g. link modes) in sync with kernel or having to add an extra roundtrip for string set request (e.g. for private flags). Compact format uses one (list) or two (value/mask) arrays of 32-bit words to store the bitmap(s). It is more suitable for long running applications (ethtool in monitor mode or network management daemons) which can retrieve the names once and then pass only compact bitmaps to save space. Userspace requests can use either format; ETHTOOL_FLAG_COMPACT_BITSETS flag in request header tells kernel which format to use in reply. Notifications always use compact format. As some code uses arrays of unsigned long for internal representation and some arrays of u32 (or even a single u32), two sets of parse/compose helpers are introduced. To avoid code duplication, helpers for unsigned long arrays are implemented as wrappers around helpers for u32 arrays. There are two reasons for this choice: (1) u32 arrays are more frequent in ethtool code and (2) unsigned long array can be always interpreted as an u32 array on little endian 64-bit and all 32-bit architectures while we would need special handling for odd number of u32 words in the opposite direction. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 84 +++ include/uapi/linux/ethtool_netlink.h | 35 ++ net/ethtool/Makefile | 2 +- net/ethtool/bitset.c | 735 +++++++++++++++++++++++++++ net/ethtool/bitset.h | 28 + 5 files changed, 883 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/bitset.c create mode 100644 net/ethtool/bitset.h (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 9448442ad293..7797f1237472 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -76,6 +76,90 @@ of the flag should be interpreted the way the client expects. A client must not set flags it does not understand. +Bit sets +======== + +For short bitmaps of (reasonably) fixed length, standard ``NLA_BITFIELD32`` +type is used. For arbitrary length bitmaps, ethtool netlink uses a nested +attribute with contents of one of two forms: compact (two binary bitmaps +representing bit values and mask of affected bits) and bit-by-bit (list of +bits identified by either index or name). + +Verbose (bit-by-bit) bitsets allow sending symbolic names for bits together +with their values which saves a round trip (when the bitset is passed in a +request) or at least a second request (when the bitset is in a reply). This is +useful for one shot applications like traditional ethtool command. On the +other hand, long running applications like ethtool monitor (displaying +notifications) or network management daemons may prefer fetching the names +only once and using compact form to save message size. Notifications from +ethtool netlink interface always use compact form for bitsets. + +A bitset can represent either a value/mask pair (``ETHTOOL_A_BITSET_NOMASK`` +not set) or a single bitmap (``ETHTOOL_A_BITSET_NOMASK`` set). In requests +modifying a bitmap, the former changes the bit set in mask to values set in +value and preserves the rest; the latter sets the bits set in the bitmap and +clears the rest. + +Compact form: nested (bitset) atrribute contents: + + ============================ ====== ============================ + ``ETHTOOL_A_BITSET_NOMASK`` flag no mask, only a list + ``ETHTOOL_A_BITSET_SIZE`` u32 number of significant bits + ``ETHTOOL_A_BITSET_VALUE`` binary bitmap of bit values + ``ETHTOOL_A_BITSET_MASK`` binary bitmap of valid bits + ============================ ====== ============================ + +Value and mask must have length at least ``ETHTOOL_A_BITSET_SIZE`` bits +rounded up to a multiple of 32 bits. They consist of 32-bit words in host byte +order, words ordered from least significant to most significant (i.e. the same +way as bitmaps are passed with ioctl interface). + +For compact form, ``ETHTOOL_A_BITSET_SIZE`` and ``ETHTOOL_A_BITSET_VALUE`` are +mandatory. ``ETHTOOL_A_BITSET_MASK`` attribute is mandatory if +``ETHTOOL_A_BITSET_NOMASK`` is not set (bitset represents a value/mask pair); +if ``ETHTOOL_A_BITSET_NOMASK`` is not set, ``ETHTOOL_A_BITSET_MASK`` is not +allowed (bitset represents a single bitmap. + +Kernel bit set length may differ from userspace length if older application is +used on newer kernel or vice versa. If userspace bitmap is longer, an error is +issued only if the request actually tries to set values of some bits not +recognized by kernel. + +Bit-by-bit form: nested (bitset) attribute contents: + + +------------------------------------+--------+-----------------------------+ + | ``ETHTOOL_A_BITSET_NOMASK`` | flag | no mask, only a list | + +------------------------------------+--------+-----------------------------+ + | ``ETHTOOL_A_BITSET_SIZE`` | u32 | number of significant bits | + +------------------------------------+--------+-----------------------------+ + | ``ETHTOOL_A_BITSET_BITS`` | nested | array of bits | + +-+----------------------------------+--------+-----------------------------+ + | | ``ETHTOOL_A_BITSET_BITS_BIT+`` | nested | one bit | + +-+-+--------------------------------+--------+-----------------------------+ + | | | ``ETHTOOL_A_BITSET_BIT_INDEX`` | u32 | bit index (0 for LSB) | + +-+-+--------------------------------+--------+-----------------------------+ + | | | ``ETHTOOL_A_BITSET_BIT_NAME`` | string | bit name | + +-+-+--------------------------------+--------+-----------------------------+ + | | | ``ETHTOOL_A_BITSET_BIT_VALUE`` | flag | present if bit is set | + +-+-+--------------------------------+--------+-----------------------------+ + +Bit size is optional for bit-by-bit form. ``ETHTOOL_A_BITSET_BITS`` nest can +only contain ``ETHTOOL_A_BITSET_BITS_BIT`` attributes but there can be an +arbitrary number of them. A bit may be identified by its index or by its +name. When used in requests, listed bits are set to 0 or 1 according to +``ETHTOOL_A_BITSET_BIT_VALUE``, the rest is preserved. A request fails if +index exceeds kernel bit length or if name is not recognized. + +When ``ETHTOOL_A_BITSET_NOMASK`` flag is present, bitset is interpreted as +a simple bitmap. ``ETHTOOL_A_BITSET_BIT_VALUE`` attributes are not used in +such case. Such bitset represents a bitmap with listed bits set and the rest +zero. + +In requests, application can use either form. Form used by kernel in reply is +determined by ``ETHTOOL_FLAG_COMPACT_BITSETS`` flag in flags field of request +header. Semantics of value and mask depends on the attribute. + + List of message types ===================== diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 82fc3b5f41c9..951203049615 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -50,6 +50,41 @@ enum { ETHTOOL_A_HEADER_MAX = __ETHTOOL_A_HEADER_CNT - 1 }; +/* bit sets */ + +enum { + ETHTOOL_A_BITSET_BIT_UNSPEC, + ETHTOOL_A_BITSET_BIT_INDEX, /* u32 */ + ETHTOOL_A_BITSET_BIT_NAME, /* string */ + ETHTOOL_A_BITSET_BIT_VALUE, /* flag */ + + /* add new constants above here */ + __ETHTOOL_A_BITSET_BIT_CNT, + ETHTOOL_A_BITSET_BIT_MAX = __ETHTOOL_A_BITSET_BIT_CNT - 1 +}; + +enum { + ETHTOOL_A_BITSET_BITS_UNSPEC, + ETHTOOL_A_BITSET_BITS_BIT, /* nest - _A_BITSET_BIT_* */ + + /* add new constants above here */ + __ETHTOOL_A_BITSET_BITS_CNT, + ETHTOOL_A_BITSET_BITS_MAX = __ETHTOOL_A_BITSET_BITS_CNT - 1 +}; + +enum { + ETHTOOL_A_BITSET_UNSPEC, + ETHTOOL_A_BITSET_NOMASK, /* flag */ + ETHTOOL_A_BITSET_SIZE, /* u32 */ + ETHTOOL_A_BITSET_BITS, /* nest - _A_BITSET_BITS_* */ + ETHTOOL_A_BITSET_VALUE, /* binary */ + ETHTOOL_A_BITSET_MASK, /* binary */ + + /* add new constants above here */ + __ETHTOOL_A_BITSET_CNT, + ETHTOOL_A_BITSET_MAX = __ETHTOOL_A_BITSET_CNT - 1 +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index 59d5ee230c29..a7e6c2c85db9 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -4,4 +4,4 @@ obj-y += ioctl.o common.o obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o -ethtool_nl-y := netlink.o +ethtool_nl-y := netlink.o bitset.o diff --git a/net/ethtool/bitset.c b/net/ethtool/bitset.c new file mode 100644 index 000000000000..fce45dac4205 --- /dev/null +++ b/net/ethtool/bitset.c @@ -0,0 +1,735 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include "netlink.h" +#include "bitset.h" + +/* Some bitmaps are internally represented as an array of unsigned long, some + * as an array of u32 (some even as single u32 for now). To avoid the need of + * wrappers on caller side, we provide two set of functions: those with "32" + * suffix in their names expect u32 based bitmaps, those without it expect + * unsigned long bitmaps. + */ + +static u32 ethnl_lower_bits(unsigned int n) +{ + return ~(u32)0 >> (32 - n % 32); +} + +static u32 ethnl_upper_bits(unsigned int n) +{ + return ~(u32)0 << (n % 32); +} + +/** + * ethnl_bitmap32_clear() - Clear u32 based bitmap + * @dst: bitmap to clear + * @start: beginning of the interval + * @end: end of the interval + * @mod: set if bitmap was modified + * + * Clear @nbits bits of a bitmap with indices @start <= i < @end + */ +static void ethnl_bitmap32_clear(u32 *dst, unsigned int start, unsigned int end, + bool *mod) +{ + unsigned int start_word = start / 32; + unsigned int end_word = end / 32; + unsigned int i; + u32 mask; + + if (end <= start) + return; + + if (start % 32) { + mask = ethnl_upper_bits(start); + if (end_word == start_word) { + mask &= ethnl_lower_bits(end); + if (dst[start_word] & mask) { + dst[start_word] &= ~mask; + *mod = true; + } + return; + } + if (dst[start_word] & mask) { + dst[start_word] &= ~mask; + *mod = true; + } + start_word++; + } + + for (i = start_word; i < end_word; i++) { + if (dst[i]) { + dst[i] = 0; + *mod = true; + } + } + if (end % 32) { + mask = ethnl_lower_bits(end); + if (dst[end_word] & mask) { + dst[end_word] &= ~mask; + *mod = true; + } + } +} + +/** + * ethnl_bitmap32_not_zero() - Check if any bit is set in an interval + * @map: bitmap to test + * @start: beginning of the interval + * @end: end of the interval + * + * Return: true if there is non-zero bit with index @start <= i < @end, + * false if the whole interval is zero + */ +static bool ethnl_bitmap32_not_zero(const u32 *map, unsigned int start, + unsigned int end) +{ + unsigned int start_word = start / 32; + unsigned int end_word = end / 32; + u32 mask; + + if (end <= start) + return true; + + if (start % 32) { + mask = ethnl_upper_bits(start); + if (end_word == start_word) { + mask &= ethnl_lower_bits(end); + return map[start_word] & mask; + } + if (map[start_word] & mask) + return true; + start_word++; + } + + if (!memchr_inv(map + start_word, '\0', + (end_word - start_word) * sizeof(u32))) + return true; + if (end % 32 == 0) + return true; + return map[end_word] & ethnl_lower_bits(end); +} + +/** + * ethnl_bitmap32_update() - Modify u32 based bitmap according to value/mask + * pair + * @dst: bitmap to update + * @nbits: bit size of the bitmap + * @value: values to set + * @mask: mask of bits to set + * @mod: set to true if bitmap is modified, preserve if not + * + * Set bits in @dst bitmap which are set in @mask to values from @value, leave + * the rest untouched. If destination bitmap was modified, set @mod to true, + * leave as it is if not. + */ +static void ethnl_bitmap32_update(u32 *dst, unsigned int nbits, + const u32 *value, const u32 *mask, bool *mod) +{ + while (nbits > 0) { + u32 real_mask = mask ? *mask : ~(u32)0; + u32 new_value; + + if (nbits < 32) + real_mask &= ethnl_lower_bits(nbits); + new_value = (*dst & ~real_mask) | (*value & real_mask); + if (new_value != *dst) { + *dst = new_value; + *mod = true; + } + + if (nbits <= 32) + break; + dst++; + nbits -= 32; + value++; + if (mask) + mask++; + } +} + +static bool ethnl_bitmap32_test_bit(const u32 *map, unsigned int index) +{ + return map[index / 32] & (1U << (index % 32)); +} + +/** + * ethnl_bitset32_size() - Calculate size of bitset nested attribute + * @val: value bitmap (u32 based) + * @mask: mask bitmap (u32 based, optional) + * @nbits: bit length of the bitset + * @names: array of bit names (optional) + * @compact: assume compact format for output + * + * Estimate length of netlink attribute composed by a later call to + * ethnl_put_bitset32() call with the same arguments. + * + * Return: negative error code or attribute length estimate + */ +int ethnl_bitset32_size(const u32 *val, const u32 *mask, unsigned int nbits, + ethnl_string_array_t names, bool compact) +{ + unsigned int len = 0; + + /* list flag */ + if (!mask) + len += nla_total_size(sizeof(u32)); + /* size */ + len += nla_total_size(sizeof(u32)); + + if (compact) { + unsigned int nwords = DIV_ROUND_UP(nbits, 32); + + /* value, mask */ + len += (mask ? 2 : 1) * nla_total_size(nwords * sizeof(u32)); + } else { + unsigned int bits_len = 0; + unsigned int bit_len, i; + + for (i = 0; i < nbits; i++) { + const char *name = names ? names[i] : NULL; + + if (!ethnl_bitmap32_test_bit(mask ?: val, i)) + continue; + /* index */ + bit_len = nla_total_size(sizeof(u32)); + /* name */ + if (name) + bit_len += ethnl_strz_size(name); + /* value */ + if (mask && ethnl_bitmap32_test_bit(val, i)) + bit_len += nla_total_size(0); + + /* bit nest */ + bits_len += nla_total_size(bit_len); + } + /* bits nest */ + len += nla_total_size(bits_len); + } + + /* outermost nest */ + return nla_total_size(len); +} + +/** + * ethnl_put_bitset32() - Put a bitset nest into a message + * @skb: skb with the message + * @attrtype: attribute type for the bitset nest + * @val: value bitmap (u32 based) + * @mask: mask bitmap (u32 based, optional) + * @nbits: bit length of the bitset + * @names: array of bit names (optional) + * @compact: use compact format for the output + * + * Compose a nested attribute representing a bitset. If @mask is null, simple + * bitmap (bit list) is created, if @mask is provided, represent a value/mask + * pair. Bit names are only used in verbose mode and when provided by calller. + * + * Return: 0 on success, negative error value on error + */ +int ethnl_put_bitset32(struct sk_buff *skb, int attrtype, const u32 *val, + const u32 *mask, unsigned int nbits, + ethnl_string_array_t names, bool compact) +{ + struct nlattr *nest; + struct nlattr *attr; + + nest = nla_nest_start(skb, attrtype); + if (!nest) + return -EMSGSIZE; + + if (!mask && nla_put_flag(skb, ETHTOOL_A_BITSET_NOMASK)) + goto nla_put_failure; + if (nla_put_u32(skb, ETHTOOL_A_BITSET_SIZE, nbits)) + goto nla_put_failure; + if (compact) { + unsigned int nwords = DIV_ROUND_UP(nbits, 32); + unsigned int nbytes = nwords * sizeof(u32); + u32 *dst; + + attr = nla_reserve(skb, ETHTOOL_A_BITSET_VALUE, nbytes); + if (!attr) + goto nla_put_failure; + dst = nla_data(attr); + memcpy(dst, val, nbytes); + if (nbits % 32) + dst[nwords - 1] &= ethnl_lower_bits(nbits); + + if (mask) { + attr = nla_reserve(skb, ETHTOOL_A_BITSET_MASK, nbytes); + if (!attr) + goto nla_put_failure; + dst = nla_data(attr); + memcpy(dst, mask, nbytes); + if (nbits % 32) + dst[nwords - 1] &= ethnl_lower_bits(nbits); + } + } else { + struct nlattr *bits; + unsigned int i; + + bits = nla_nest_start(skb, ETHTOOL_A_BITSET_BITS); + if (!bits) + goto nla_put_failure; + for (i = 0; i < nbits; i++) { + const char *name = names ? names[i] : NULL; + + if (!ethnl_bitmap32_test_bit(mask ?: val, i)) + continue; + attr = nla_nest_start(skb, ETHTOOL_A_BITSET_BITS_BIT); + if (!attr) + goto nla_put_failure; + if (nla_put_u32(skb, ETHTOOL_A_BITSET_BIT_INDEX, i)) + goto nla_put_failure; + if (name && + ethnl_put_strz(skb, ETHTOOL_A_BITSET_BIT_NAME, name)) + goto nla_put_failure; + if (mask && ethnl_bitmap32_test_bit(val, i) && + nla_put_flag(skb, ETHTOOL_A_BITSET_BIT_VALUE)) + goto nla_put_failure; + nla_nest_end(skb, attr); + } + nla_nest_end(skb, bits); + } + + nla_nest_end(skb, nest); + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nest); + return -EMSGSIZE; +} + +static const struct nla_policy bitset_policy[ETHTOOL_A_BITSET_MAX + 1] = { + [ETHTOOL_A_BITSET_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG }, + [ETHTOOL_A_BITSET_SIZE] = { .type = NLA_U32 }, + [ETHTOOL_A_BITSET_BITS] = { .type = NLA_NESTED }, + [ETHTOOL_A_BITSET_VALUE] = { .type = NLA_BINARY }, + [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY }, +}; + +static const struct nla_policy bit_policy[ETHTOOL_A_BITSET_BIT_MAX + 1] = { + [ETHTOOL_A_BITSET_BIT_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_BITSET_BIT_INDEX] = { .type = NLA_U32 }, + [ETHTOOL_A_BITSET_BIT_NAME] = { .type = NLA_NUL_STRING }, + [ETHTOOL_A_BITSET_BIT_VALUE] = { .type = NLA_FLAG }, +}; + +/** + * ethnl_bitset_is_compact() - check if bitset attribute represents a compact + * bitset + * @bitset: nested attribute representing a bitset + * @compact: pointer for return value + * + * Return: 0 on success, negative error code on failure + */ +int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact) +{ + struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1]; + int ret; + + ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, bitset, + bitset_policy, NULL); + if (ret < 0) + return ret; + + if (tb[ETHTOOL_A_BITSET_BITS]) { + if (tb[ETHTOOL_A_BITSET_VALUE] || tb[ETHTOOL_A_BITSET_MASK]) + return -EINVAL; + *compact = false; + return 0; + } + if (!tb[ETHTOOL_A_BITSET_SIZE] || !tb[ETHTOOL_A_BITSET_VALUE]) + return -EINVAL; + + *compact = true; + return 0; +} + +/** + * ethnl_name_to_idx() - look up string index for a name + * @names: array of ETH_GSTRING_LEN sized strings + * @n_names: number of strings in the array + * @name: name to look up + * + * Return: index of the string if found, -ENOENT if not found + */ +static int ethnl_name_to_idx(ethnl_string_array_t names, unsigned int n_names, + const char *name) +{ + unsigned int i; + + if (!names) + return -ENOENT; + + for (i = 0; i < n_names; i++) { + /* names[i] may not be null terminated */ + if (!strncmp(names[i], name, ETH_GSTRING_LEN) && + strlen(name) <= ETH_GSTRING_LEN) + return i; + } + + return -ENOENT; +} + +static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits, + const struct nlattr *bit_attr, bool no_mask, + ethnl_string_array_t names, + struct netlink_ext_ack *extack) +{ + struct nlattr *tb[ETHTOOL_A_BITSET_BIT_MAX + 1]; + int ret, idx; + + ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_BIT_MAX, bit_attr, + bit_policy, extack); + if (ret < 0) + return ret; + + if (tb[ETHTOOL_A_BITSET_BIT_INDEX]) { + const char *name; + + idx = nla_get_u32(tb[ETHTOOL_A_BITSET_BIT_INDEX]); + if (idx >= nbits) { + NL_SET_ERR_MSG_ATTR(extack, + tb[ETHTOOL_A_BITSET_BIT_INDEX], + "bit index too high"); + return -EOPNOTSUPP; + } + name = names ? names[idx] : NULL; + if (tb[ETHTOOL_A_BITSET_BIT_NAME] && name && + strncmp(nla_data(tb[ETHTOOL_A_BITSET_BIT_NAME]), name, + nla_len(tb[ETHTOOL_A_BITSET_BIT_NAME]))) { + NL_SET_ERR_MSG_ATTR(extack, bit_attr, + "bit index and name mismatch"); + return -EINVAL; + } + } else if (tb[ETHTOOL_A_BITSET_BIT_NAME]) { + idx = ethnl_name_to_idx(names, nbits, + nla_data(tb[ETHTOOL_A_BITSET_BIT_NAME])); + if (idx < 0) { + NL_SET_ERR_MSG_ATTR(extack, + tb[ETHTOOL_A_BITSET_BIT_NAME], + "bit name not found"); + return -EOPNOTSUPP; + } + } else { + NL_SET_ERR_MSG_ATTR(extack, bit_attr, + "neither bit index nor name specified"); + return -EINVAL; + } + + *index = idx; + *val = no_mask || tb[ETHTOOL_A_BITSET_BIT_VALUE]; + return 0; +} + +static int +ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, + const struct nlattr *attr, struct nlattr **tb, + ethnl_string_array_t names, + struct netlink_ext_ack *extack, bool *mod) +{ + struct nlattr *bit_attr; + bool no_mask; + int rem; + int ret; + + if (tb[ETHTOOL_A_BITSET_VALUE]) { + NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE], + "value only allowed in compact bitset"); + return -EINVAL; + } + if (tb[ETHTOOL_A_BITSET_MASK]) { + NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK], + "mask only allowed in compact bitset"); + return -EINVAL; + } + no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; + + nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) { + bool old_val, new_val; + unsigned int idx; + + if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) { + NL_SET_ERR_MSG_ATTR(extack, bit_attr, + "only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS"); + return -EINVAL; + } + ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask, + names, extack); + if (ret < 0) + return ret; + old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32)); + if (new_val != old_val) { + if (new_val) + bitmap[idx / 32] |= ((u32)1 << (idx % 32)); + else + bitmap[idx / 32] &= ~((u32)1 << (idx % 32)); + *mod = true; + } + } + + return 0; +} + +static int ethnl_compact_sanity_checks(unsigned int nbits, + const struct nlattr *nest, + struct nlattr **tb, + struct netlink_ext_ack *extack) +{ + bool no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; + unsigned int attr_nbits, attr_nwords; + const struct nlattr *test_attr; + + if (no_mask && tb[ETHTOOL_A_BITSET_MASK]) { + NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK], + "mask not allowed in list bitset"); + return -EINVAL; + } + if (!tb[ETHTOOL_A_BITSET_SIZE]) { + NL_SET_ERR_MSG_ATTR(extack, nest, + "missing size in compact bitset"); + return -EINVAL; + } + if (!tb[ETHTOOL_A_BITSET_VALUE]) { + NL_SET_ERR_MSG_ATTR(extack, nest, + "missing value in compact bitset"); + return -EINVAL; + } + if (!no_mask && !tb[ETHTOOL_A_BITSET_MASK]) { + NL_SET_ERR_MSG_ATTR(extack, nest, + "missing mask in compact nonlist bitset"); + return -EINVAL; + } + + attr_nbits = nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]); + attr_nwords = DIV_ROUND_UP(attr_nbits, 32); + if (nla_len(tb[ETHTOOL_A_BITSET_VALUE]) != attr_nwords * sizeof(u32)) { + NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE], + "bitset value length does not match size"); + return -EINVAL; + } + if (tb[ETHTOOL_A_BITSET_MASK] && + nla_len(tb[ETHTOOL_A_BITSET_MASK]) != attr_nwords * sizeof(u32)) { + NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK], + "bitset mask length does not match size"); + return -EINVAL; + } + if (attr_nbits <= nbits) + return 0; + + test_attr = no_mask ? tb[ETHTOOL_A_BITSET_VALUE] : + tb[ETHTOOL_A_BITSET_MASK]; + if (ethnl_bitmap32_not_zero(nla_data(test_attr), nbits, attr_nbits)) { + NL_SET_ERR_MSG_ATTR(extack, test_attr, + "cannot modify bits past kernel bitset size"); + return -EINVAL; + } + return 0; +} + +/** + * ethnl_update_bitset32() - Apply a bitset nest to a u32 based bitmap + * @bitmap: bitmap to update + * @nbits: size of the updated bitmap in bits + * @attr: nest attribute to parse and apply + * @names: array of bit names; may be null for compact format + * @extack: extack for error reporting + * @mod: set this to true if bitmap is modified, leave as it is if not + * + * Apply bitset netsted attribute to a bitmap. If the attribute represents + * a bit list, @bitmap is set to its contents; otherwise, bits in mask are + * set to values from value. Bitmaps in the attribute may be longer than + * @nbits but the message must not request modifying any bits past @nbits. + * + * Return: negative error code on failure, 0 on success + */ +int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits, + const struct nlattr *attr, ethnl_string_array_t names, + struct netlink_ext_ack *extack, bool *mod) +{ + struct nlattr *tb[ETHTOOL_A_BITSET_MAX + 1]; + unsigned int change_bits; + bool no_mask; + int ret; + + if (!attr) + return 0; + ret = nla_parse_nested(tb, ETHTOOL_A_BITSET_MAX, attr, bitset_policy, + extack); + if (ret < 0) + return ret; + + if (tb[ETHTOOL_A_BITSET_BITS]) + return ethnl_update_bitset32_verbose(bitmap, nbits, attr, tb, + names, extack, mod); + ret = ethnl_compact_sanity_checks(nbits, attr, tb, extack); + if (ret < 0) + return ret; + + no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; + change_bits = min_t(unsigned int, + nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]), nbits); + ethnl_bitmap32_update(bitmap, change_bits, + nla_data(tb[ETHTOOL_A_BITSET_VALUE]), + no_mask ? NULL : + nla_data(tb[ETHTOOL_A_BITSET_MASK]), + mod); + if (no_mask && change_bits < nbits) + ethnl_bitmap32_clear(bitmap, change_bits, nbits, mod); + + return 0; +} + +#if BITS_PER_LONG == 64 && defined(__BIG_ENDIAN) + +/* 64-bit big endian architectures are the only case when u32 based bitmaps + * and unsigned long based bitmaps have different memory layout so that we + * cannot simply cast the latter to the former and need actual wrappers + * converting the latter to the former. + * + * To reduce the number of slab allocations, the wrappers use fixed size local + * variables for bitmaps up to ETHNL_SMALL_BITMAP_BITS bits which is the + * majority of bitmaps used by ethtool. + */ +#define ETHNL_SMALL_BITMAP_BITS 128 +#define ETHNL_SMALL_BITMAP_WORDS DIV_ROUND_UP(ETHNL_SMALL_BITMAP_BITS, 32) + +int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask, + unsigned int nbits, ethnl_string_array_t names, + bool compact) +{ + u32 small_mask32[ETHNL_SMALL_BITMAP_WORDS]; + u32 small_val32[ETHNL_SMALL_BITMAP_WORDS]; + u32 *mask32; + u32 *val32; + int ret; + + if (nbits > ETHNL_SMALL_BITMAP_BITS) { + unsigned int nwords = DIV_ROUND_UP(nbits, 32); + + val32 = kmalloc_array(2 * nwords, sizeof(u32), GFP_KERNEL); + if (!val32) + return -ENOMEM; + mask32 = val32 + nwords; + } else { + val32 = small_val32; + mask32 = small_mask32; + } + + bitmap_to_arr32(val32, val, nbits); + if (mask) + bitmap_to_arr32(mask32, mask, nbits); + else + mask32 = NULL; + ret = ethnl_bitset32_size(val32, mask32, nbits, names, compact); + + if (nbits > ETHNL_SMALL_BITMAP_BITS) + kfree(val32); + + return ret; +} + +int ethnl_put_bitset(struct sk_buff *skb, int attrtype, + const unsigned long *val, const unsigned long *mask, + unsigned int nbits, ethnl_string_array_t names, + bool compact) +{ + u32 small_mask32[ETHNL_SMALL_BITMAP_WORDS]; + u32 small_val32[ETHNL_SMALL_BITMAP_WORDS]; + u32 *mask32; + u32 *val32; + int ret; + + if (nbits > ETHNL_SMALL_BITMAP_BITS) { + unsigned int nwords = DIV_ROUND_UP(nbits, 32); + + val32 = kmalloc_array(2 * nwords, sizeof(u32), GFP_KERNEL); + if (!val32) + return -ENOMEM; + mask32 = val32 + nwords; + } else { + val32 = small_val32; + mask32 = small_mask32; + } + + bitmap_to_arr32(val32, val, nbits); + if (mask) + bitmap_to_arr32(mask32, mask, nbits); + else + mask32 = NULL; + ret = ethnl_put_bitset32(skb, attrtype, val32, mask32, nbits, names, + compact); + + if (nbits > ETHNL_SMALL_BITMAP_BITS) + kfree(val32); + + return ret; +} + +int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits, + const struct nlattr *attr, ethnl_string_array_t names, + struct netlink_ext_ack *extack, bool *mod) +{ + u32 small_bitmap32[ETHNL_SMALL_BITMAP_WORDS]; + u32 *bitmap32 = small_bitmap32; + bool u32_mod = false; + int ret; + + if (nbits > ETHNL_SMALL_BITMAP_BITS) { + unsigned int dst_words = DIV_ROUND_UP(nbits, 32); + + bitmap32 = kmalloc_array(dst_words, sizeof(u32), GFP_KERNEL); + if (!bitmap32) + return -ENOMEM; + } + + bitmap_to_arr32(bitmap32, bitmap, nbits); + ret = ethnl_update_bitset32(bitmap32, nbits, attr, names, extack, + &u32_mod); + if (u32_mod) { + bitmap_from_arr32(bitmap, bitmap32, nbits); + *mod = true; + } + + if (nbits > ETHNL_SMALL_BITMAP_BITS) + kfree(bitmap32); + + return ret; +} + +#else + +/* On little endian 64-bit and all 32-bit architectures, an unsigned long + * based bitmap can be interpreted as u32 based one using a simple cast. + */ + +int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask, + unsigned int nbits, ethnl_string_array_t names, + bool compact) +{ + return ethnl_bitset32_size((const u32 *)val, (const u32 *)mask, nbits, + names, compact); +} + +int ethnl_put_bitset(struct sk_buff *skb, int attrtype, + const unsigned long *val, const unsigned long *mask, + unsigned int nbits, ethnl_string_array_t names, + bool compact) +{ + return ethnl_put_bitset32(skb, attrtype, (const u32 *)val, + (const u32 *)mask, nbits, names, compact); +} + +int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits, + const struct nlattr *attr, ethnl_string_array_t names, + struct netlink_ext_ack *extack, bool *mod) +{ + return ethnl_update_bitset32((u32 *)bitmap, nbits, attr, names, extack, + mod); +} + +#endif /* BITS_PER_LONG == 64 && defined(__BIG_ENDIAN) */ diff --git a/net/ethtool/bitset.h b/net/ethtool/bitset.h new file mode 100644 index 000000000000..b8247e34109d --- /dev/null +++ b/net/ethtool/bitset.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _NET_ETHTOOL_BITSET_H +#define _NET_ETHTOOL_BITSET_H + +typedef const char (*const ethnl_string_array_t)[ETH_GSTRING_LEN]; + +int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact); +int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask, + unsigned int nbits, ethnl_string_array_t names, + bool compact); +int ethnl_bitset32_size(const u32 *val, const u32 *mask, unsigned int nbits, + ethnl_string_array_t names, bool compact); +int ethnl_put_bitset(struct sk_buff *skb, int attrtype, + const unsigned long *val, const unsigned long *mask, + unsigned int nbits, ethnl_string_array_t names, + bool compact); +int ethnl_put_bitset32(struct sk_buff *skb, int attrtype, const u32 *val, + const u32 *mask, unsigned int nbits, + ethnl_string_array_t names, bool compact); +int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits, + const struct nlattr *attr, ethnl_string_array_t names, + struct netlink_ext_ack *extack, bool *mod); +int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits, + const struct nlattr *attr, ethnl_string_array_t names, + struct netlink_ext_ack *extack, bool *mod); + +#endif /* _NET_ETHTOOL_BITSET_H */ -- cgit v1.2.3 From 71921690f9745fef60a2bad425f30adf8cdc9da0 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:55:43 +0100 Subject: ethtool: provide string sets with STRSET_GET request Requests a contents of one or more string sets, i.e. indexed arrays of strings; this information is provided by ETHTOOL_GSSET_INFO and ETHTOOL_GSTRINGS commands of ioctl interface. Unlike ioctl interface, all information can be retrieved with one request and mulitple string sets can be requested at once. There are three types of requests: - no NLM_F_DUMP, no device: get "global" stringsets - no NLM_F_DUMP, with device: get string sets related to the device - NLM_F_DUMP, no device: get device related string sets for all devices Client can request either all string sets of given type (global or device related) or only specific sets. With ETHTOOL_A_STRSET_COUNTS flag set, only set sizes (numbers of strings) are returned. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 75 ++++- include/uapi/linux/ethtool.h | 3 + include/uapi/linux/ethtool_netlink.h | 56 ++++ net/ethtool/Makefile | 2 +- net/ethtool/netlink.c | 8 + net/ethtool/netlink.h | 4 + net/ethtool/strset.c | 425 +++++++++++++++++++++++++++ 7 files changed, 570 insertions(+), 3 deletions(-) create mode 100644 net/ethtool/strset.c (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 7797f1237472..3912cb0eb9c6 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -176,6 +176,18 @@ according to message purpose: ``_NTF`` kernel notification ============== ====================================== +Userspace to kernel: + + ===================================== ================================ + ``ETHTOOL_MSG_STRSET_GET`` get string set + ===================================== ================================ + +Kernel to userspace: + + ===================================== ================================ + ``ETHTOOL_MSG_STRSET_GET_REPLY`` string set contents + ===================================== ================================ + ``GET`` requests are sent by userspace applications to retrieve device information. They usually do not contain any message specific attributes. Kernel replies with corresponding "GET_REPLY" message. For most types, ``GET`` @@ -207,6 +219,65 @@ an ``ACT_REPLY`` message. Performing an action also triggers a notification Later sections describe the format and semantics of these messages. +STRSET_GET +========== + +Requests contents of a string set as provided by ioctl commands +``ETHTOOL_GSSET_INFO`` and ``ETHTOOL_GSTRINGS.`` String sets are not user +writeable so that the corresponding ``STRSET_SET`` message is only used in +kernel replies. There are two types of string sets: global (independent of +a device, e.g. device feature names) and device specific (e.g. device private +flags). + +Request contents: + + +---------------------------------------+--------+------------------------+ + | ``ETHTOOL_A_STRSET_HEADER`` | nested | request header | + +---------------------------------------+--------+------------------------+ + | ``ETHTOOL_A_STRSET_STRINGSETS`` | nested | string set to request | + +-+-------------------------------------+--------+------------------------+ + | | ``ETHTOOL_A_STRINGSETS_STRINGSET+`` | nested | one string set | + +-+-+-----------------------------------+--------+------------------------+ + | | | ``ETHTOOL_A_STRINGSET_ID`` | u32 | set id | + +-+-+-----------------------------------+--------+------------------------+ + +Kernel response contents: + + +---------------------------------------+--------+-----------------------+ + | ``ETHTOOL_A_STRSET_HEADER`` | nested | reply header | + +---------------------------------------+--------+-----------------------+ + | ``ETHTOOL_A_STRSET_STRINGSETS`` | nested | array of string sets | + +-+-------------------------------------+--------+-----------------------+ + | | ``ETHTOOL_A_STRINGSETS_STRINGSET+`` | nested | one string set | + +-+-+-----------------------------------+--------+-----------------------+ + | | | ``ETHTOOL_A_STRINGSET_ID`` | u32 | set id | + +-+-+-----------------------------------+--------+-----------------------+ + | | | ``ETHTOOL_A_STRINGSET_COUNT`` | u32 | number of strings | + +-+-+-----------------------------------+--------+-----------------------+ + | | | ``ETHTOOL_A_STRINGSET_STRINGS`` | nested | array of strings | + +-+-+-+---------------------------------+--------+-----------------------+ + | | | | ``ETHTOOL_A_STRINGS_STRING+`` | nested | one string | + +-+-+-+-+-------------------------------+--------+-----------------------+ + | | | | | ``ETHTOOL_A_STRING_INDEX`` | u32 | string index | + +-+-+-+-+-------------------------------+--------+-----------------------+ + | | | | | ``ETHTOOL_A_STRING_VALUE`` | string | string value | + +-+-+-+-+-------------------------------+--------+-----------------------+ + | ``ETHTOOL_A_STRSET_COUNTS_ONLY`` | flag | return only counts | + +---------------------------------------+--------+-----------------------+ + +Device identification in request header is optional. Depending on its presence +a and ``NLM_F_DUMP`` flag, there are three type of ``STRSET_GET`` requests: + + - no ``NLM_F_DUMP,`` no device: get "global" stringsets + - no ``NLM_F_DUMP``, with device: get string sets related to the device + - ``NLM_F_DUMP``, no device: get device related string sets for all devices + +If there is no ``ETHTOOL_A_STRSET_STRINGSETS`` array, all string sets of +requested type are returned, otherwise only those specified in the request. +Flag ``ETHTOOL_A_STRSET_COUNTS_ONLY`` tells kernel to only return string +counts of the sets, not the actual strings. + + Request translation =================== @@ -242,7 +313,7 @@ have their netlink replacement yet. ``ETHTOOL_GSG`` n/a ``ETHTOOL_SSG`` n/a ``ETHTOOL_TEST`` n/a - ``ETHTOOL_GSTRINGS`` n/a + ``ETHTOOL_GSTRINGS`` ``ETHTOOL_MSG_STRSET_GET`` ``ETHTOOL_PHYS_ID`` n/a ``ETHTOOL_GSTATS`` n/a ``ETHTOOL_GTSO`` n/a @@ -270,7 +341,7 @@ have their netlink replacement yet. ``ETHTOOL_RESET`` n/a ``ETHTOOL_SRXNTUPLE`` n/a ``ETHTOOL_GRXNTUPLE`` n/a - ``ETHTOOL_GSSET_INFO`` n/a + ``ETHTOOL_GSSET_INFO`` ``ETHTOOL_MSG_STRSET_GET`` ``ETHTOOL_GRXFHINDIR`` n/a ``ETHTOOL_SRXFHINDIR`` n/a ``ETHTOOL_GFEATURES`` n/a diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index f44155840b07..116bcbf09c74 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -606,6 +606,9 @@ enum ethtool_stringset { ETH_SS_PHY_STATS, ETH_SS_PHY_TUNABLES, ETH_SS_LINK_MODES, + + /* add new constants above here */ + ETH_SS_COUNT }; /** diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index d530ccb6f7e6..cabef1fec42a 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -14,6 +14,7 @@ /* message types - userspace to kernel */ enum { ETHTOOL_MSG_USER_NONE, + ETHTOOL_MSG_STRSET_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -23,6 +24,7 @@ enum { /* message types - kernel to userspace */ enum { ETHTOOL_MSG_KERNEL_NONE, + ETHTOOL_MSG_STRSET_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -85,6 +87,60 @@ enum { ETHTOOL_A_BITSET_MAX = __ETHTOOL_A_BITSET_CNT - 1 }; +/* string sets */ + +enum { + ETHTOOL_A_STRING_UNSPEC, + ETHTOOL_A_STRING_INDEX, /* u32 */ + ETHTOOL_A_STRING_VALUE, /* string */ + + /* add new constants above here */ + __ETHTOOL_A_STRING_CNT, + ETHTOOL_A_STRING_MAX = __ETHTOOL_A_STRING_CNT - 1 +}; + +enum { + ETHTOOL_A_STRINGS_UNSPEC, + ETHTOOL_A_STRINGS_STRING, /* nest - _A_STRINGS_* */ + + /* add new constants above here */ + __ETHTOOL_A_STRINGS_CNT, + ETHTOOL_A_STRINGS_MAX = __ETHTOOL_A_STRINGS_CNT - 1 +}; + +enum { + ETHTOOL_A_STRINGSET_UNSPEC, + ETHTOOL_A_STRINGSET_ID, /* u32 */ + ETHTOOL_A_STRINGSET_COUNT, /* u32 */ + ETHTOOL_A_STRINGSET_STRINGS, /* nest - _A_STRINGS_* */ + + /* add new constants above here */ + __ETHTOOL_A_STRINGSET_CNT, + ETHTOOL_A_STRINGSET_MAX = __ETHTOOL_A_STRINGSET_CNT - 1 +}; + +enum { + ETHTOOL_A_STRINGSETS_UNSPEC, + ETHTOOL_A_STRINGSETS_STRINGSET, /* nest - _A_STRINGSET_* */ + + /* add new constants above here */ + __ETHTOOL_A_STRINGSETS_CNT, + ETHTOOL_A_STRINGSETS_MAX = __ETHTOOL_A_STRINGSETS_CNT - 1 +}; + +/* STRSET */ + +enum { + ETHTOOL_A_STRSET_UNSPEC, + ETHTOOL_A_STRSET_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_STRSET_STRINGSETS, /* nest - _A_STRINGSETS_* */ + ETHTOOL_A_STRSET_COUNTS_ONLY, /* flag */ + + /* add new constants above here */ + __ETHTOOL_A_STRSET_CNT, + ETHTOOL_A_STRSET_MAX = __ETHTOOL_A_STRSET_CNT - 1 +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index a7e6c2c85db9..efcc42c34d62 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -4,4 +4,4 @@ obj-y += ioctl.o common.o obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o -ethtool_nl-y := netlink.o bitset.o +ethtool_nl-y := netlink.o bitset.o strset.o diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index ae63e8423072..7dc082bde670 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -194,6 +194,7 @@ struct ethnl_dump_ctx { static const struct ethnl_request_ops * ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { + [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -518,6 +519,13 @@ EXPORT_SYMBOL(ethtool_notify); /* genetlink setup */ static const struct genl_ops ethtool_genl_ops[] = { + { + .cmd = ETHTOOL_MSG_STRSET_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 6ec0dd06277f..44e9f63aefb7 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -326,4 +326,8 @@ struct ethnl_request_ops { void (*cleanup_data)(struct ethnl_reply_data *reply_data); }; +/* request handlers */ + +extern const struct ethnl_request_ops ethnl_strset_request_ops; + #endif /* _NET_ETHTOOL_NETLINK_H */ diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c new file mode 100644 index 000000000000..9f2243329015 --- /dev/null +++ b/net/ethtool/strset.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include "netlink.h" +#include "common.h" + +struct strset_info { + bool per_dev; + bool free_strings; + unsigned int count; + const char (*strings)[ETH_GSTRING_LEN]; +}; + +static const struct strset_info info_template[] = { + [ETH_SS_TEST] = { + .per_dev = true, + }, + [ETH_SS_STATS] = { + .per_dev = true, + }, + [ETH_SS_PRIV_FLAGS] = { + .per_dev = true, + }, + [ETH_SS_FEATURES] = { + .per_dev = false, + .count = ARRAY_SIZE(netdev_features_strings), + .strings = netdev_features_strings, + }, + [ETH_SS_RSS_HASH_FUNCS] = { + .per_dev = false, + .count = ARRAY_SIZE(rss_hash_func_strings), + .strings = rss_hash_func_strings, + }, + [ETH_SS_TUNABLES] = { + .per_dev = false, + .count = ARRAY_SIZE(tunable_strings), + .strings = tunable_strings, + }, + [ETH_SS_PHY_STATS] = { + .per_dev = true, + }, + [ETH_SS_PHY_TUNABLES] = { + .per_dev = false, + .count = ARRAY_SIZE(phy_tunable_strings), + .strings = phy_tunable_strings, + }, + [ETH_SS_LINK_MODES] = { + .per_dev = false, + .count = __ETHTOOL_LINK_MODE_MASK_NBITS, + .strings = link_mode_names, + }, +}; + +struct strset_req_info { + struct ethnl_req_info base; + u32 req_ids; + bool counts_only; +}; + +#define STRSET_REQINFO(__req_base) \ + container_of(__req_base, struct strset_req_info, base) + +struct strset_reply_data { + struct ethnl_reply_data base; + struct strset_info sets[ETH_SS_COUNT]; +}; + +#define STRSET_REPDATA(__reply_base) \ + container_of(__reply_base, struct strset_reply_data, base) + +static const struct nla_policy strset_get_policy[ETHTOOL_A_STRSET_MAX + 1] = { + [ETHTOOL_A_STRSET_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_STRSET_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_STRSET_STRINGSETS] = { .type = NLA_NESTED }, +}; + +static const struct nla_policy +get_stringset_policy[ETHTOOL_A_STRINGSET_MAX + 1] = { + [ETHTOOL_A_STRINGSET_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_STRINGSET_ID] = { .type = NLA_U32 }, + [ETHTOOL_A_STRINGSET_COUNT] = { .type = NLA_REJECT }, + [ETHTOOL_A_STRINGSET_STRINGS] = { .type = NLA_REJECT }, +}; + +/** + * strset_include() - test if a string set should be included in reply + * @data: pointer to request data structure + * @id: id of string set to check (ETH_SS_* constants) + */ +static bool strset_include(const struct strset_req_info *info, + const struct strset_reply_data *data, u32 id) +{ + bool per_dev; + + BUILD_BUG_ON(ETH_SS_COUNT >= BITS_PER_BYTE * sizeof(info->req_ids)); + + if (info->req_ids) + return info->req_ids & (1U << id); + per_dev = data->sets[id].per_dev; + if (!per_dev && !data->sets[id].strings) + return false; + + return data->base.dev ? per_dev : !per_dev; +} + +static int strset_get_id(const struct nlattr *nest, u32 *val, + struct netlink_ext_ack *extack) +{ + struct nlattr *tb[ETHTOOL_A_STRINGSET_MAX + 1]; + int ret; + + ret = nla_parse_nested(tb, ETHTOOL_A_STRINGSET_MAX, nest, + get_stringset_policy, extack); + if (ret < 0) + return ret; + if (!tb[ETHTOOL_A_STRINGSET_ID]) + return -EINVAL; + + *val = nla_get_u32(tb[ETHTOOL_A_STRINGSET_ID]); + return 0; +} + +static const struct nla_policy +strset_stringsets_policy[ETHTOOL_A_STRINGSETS_MAX + 1] = { + [ETHTOOL_A_STRINGSETS_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_STRINGSETS_STRINGSET] = { .type = NLA_NESTED }, +}; + +static int strset_parse_request(struct ethnl_req_info *req_base, + struct nlattr **tb, + struct netlink_ext_ack *extack) +{ + struct strset_req_info *req_info = STRSET_REQINFO(req_base); + struct nlattr *nest = tb[ETHTOOL_A_STRSET_STRINGSETS]; + struct nlattr *attr; + int rem, ret; + + if (!nest) + return 0; + ret = nla_validate_nested(nest, ETHTOOL_A_STRINGSETS_MAX, + strset_stringsets_policy, extack); + if (ret < 0) + return ret; + + req_info->counts_only = tb[ETHTOOL_A_STRSET_COUNTS_ONLY]; + nla_for_each_nested(attr, nest, rem) { + u32 id; + + if (WARN_ONCE(nla_type(attr) != ETHTOOL_A_STRINGSETS_STRINGSET, + "unexpected attrtype %u in ETHTOOL_A_STRSET_STRINGSETS\n", + nla_type(attr))) + return -EINVAL; + + ret = strset_get_id(attr, &id, extack); + if (ret < 0) + return ret; + if (ret >= ETH_SS_COUNT) { + NL_SET_ERR_MSG_ATTR(extack, attr, + "unknown string set id"); + return -EOPNOTSUPP; + } + + req_info->req_ids |= (1U << id); + } + + return 0; +} + +static void strset_cleanup_data(struct ethnl_reply_data *reply_base) +{ + struct strset_reply_data *data = STRSET_REPDATA(reply_base); + unsigned int i; + + for (i = 0; i < ETH_SS_COUNT; i++) + if (data->sets[i].free_strings) { + kfree(data->sets[i].strings); + data->sets[i].strings = NULL; + data->sets[i].free_strings = false; + } +} + +static int strset_prepare_set(struct strset_info *info, struct net_device *dev, + unsigned int id, bool counts_only) +{ + const struct ethtool_ops *ops = dev->ethtool_ops; + void *strings; + int count, ret; + + if (id == ETH_SS_PHY_STATS && dev->phydev && + !ops->get_ethtool_phy_stats) + ret = phy_ethtool_get_sset_count(dev->phydev); + else if (ops->get_sset_count && ops->get_strings) + ret = ops->get_sset_count(dev, id); + else + ret = -EOPNOTSUPP; + if (ret <= 0) { + info->count = 0; + return 0; + } + + count = ret; + if (!counts_only) { + strings = kcalloc(count, ETH_GSTRING_LEN, GFP_KERNEL); + if (!strings) + return -ENOMEM; + if (id == ETH_SS_PHY_STATS && dev->phydev && + !ops->get_ethtool_phy_stats) + phy_ethtool_get_strings(dev->phydev, strings); + else + ops->get_strings(dev, id, strings); + info->strings = strings; + info->free_strings = true; + } + info->count = count; + + return 0; +} + +static int strset_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + const struct strset_req_info *req_info = STRSET_REQINFO(req_base); + struct strset_reply_data *data = STRSET_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + unsigned int i; + int ret; + + BUILD_BUG_ON(ARRAY_SIZE(info_template) != ETH_SS_COUNT); + memcpy(&data->sets, &info_template, sizeof(data->sets)); + + if (!dev) { + for (i = 0; i < ETH_SS_COUNT; i++) { + if ((req_info->req_ids & (1U << i)) && + data->sets[i].per_dev) { + if (info) + GENL_SET_ERR_MSG(info, "requested per device strings without dev"); + return -EINVAL; + } + } + } + + ret = ethnl_ops_begin(dev); + if (ret < 0) + goto err_strset; + for (i = 0; i < ETH_SS_COUNT; i++) { + if (!strset_include(req_info, data, i) || + !data->sets[i].per_dev) + continue; + + ret = strset_prepare_set(&data->sets[i], dev, i, + req_info->counts_only); + if (ret < 0) + goto err_ops; + } + ethnl_ops_complete(dev); + + return 0; +err_ops: + ethnl_ops_complete(dev); +err_strset: + strset_cleanup_data(reply_base); + return ret; +} + +/* calculate size of ETHTOOL_A_STRSET_STRINGSET nest for one string set */ +static int strset_set_size(const struct strset_info *info, bool counts_only) +{ + unsigned int len = 0; + unsigned int i; + + if (info->count == 0) + return 0; + if (counts_only) + return nla_total_size(2 * nla_total_size(sizeof(u32))); + + for (i = 0; i < info->count; i++) { + const char *str = info->strings[i]; + + /* ETHTOOL_A_STRING_INDEX, ETHTOOL_A_STRING_VALUE, nest */ + len += nla_total_size(nla_total_size(sizeof(u32)) + + ethnl_strz_size(str)); + } + /* ETHTOOL_A_STRINGSET_ID, ETHTOOL_A_STRINGSET_COUNT */ + len = 2 * nla_total_size(sizeof(u32)) + nla_total_size(len); + + return nla_total_size(len); +} + +static int strset_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct strset_req_info *req_info = STRSET_REQINFO(req_base); + const struct strset_reply_data *data = STRSET_REPDATA(reply_base); + unsigned int i; + int len = 0; + int ret; + + len += ethnl_reply_header_size(); + for (i = 0; i < ETH_SS_COUNT; i++) { + const struct strset_info *set_info = &data->sets[i]; + + if (!strset_include(req_info, data, i)) + continue; + + ret = strset_set_size(set_info, req_info->counts_only); + if (ret < 0) + return ret; + len += ret; + } + + return len; +} + +/* fill one string into reply */ +static int strset_fill_string(struct sk_buff *skb, + const struct strset_info *set_info, u32 idx) +{ + struct nlattr *string_attr; + const char *value; + + value = set_info->strings[idx]; + + string_attr = nla_nest_start(skb, ETHTOOL_A_STRINGS_STRING); + if (!string_attr) + return -EMSGSIZE; + if (nla_put_u32(skb, ETHTOOL_A_STRING_INDEX, idx) || + ethnl_put_strz(skb, ETHTOOL_A_STRING_VALUE, value)) + goto nla_put_failure; + nla_nest_end(skb, string_attr); + + return 0; +nla_put_failure: + nla_nest_cancel(skb, string_attr); + return -EMSGSIZE; +} + +/* fill one string set into reply */ +static int strset_fill_set(struct sk_buff *skb, + const struct strset_info *set_info, u32 id, + bool counts_only) +{ + struct nlattr *stringset_attr; + struct nlattr *strings_attr; + unsigned int i; + + if (!set_info->per_dev && !set_info->strings) + return -EOPNOTSUPP; + if (set_info->count == 0) + return 0; + stringset_attr = nla_nest_start(skb, ETHTOOL_A_STRINGSETS_STRINGSET); + if (!stringset_attr) + return -EMSGSIZE; + + if (nla_put_u32(skb, ETHTOOL_A_STRINGSET_ID, id) || + nla_put_u32(skb, ETHTOOL_A_STRINGSET_COUNT, set_info->count)) + goto nla_put_failure; + + if (!counts_only) { + strings_attr = nla_nest_start(skb, ETHTOOL_A_STRINGSET_STRINGS); + if (!strings_attr) + goto nla_put_failure; + for (i = 0; i < set_info->count; i++) { + if (strset_fill_string(skb, set_info, i) < 0) + goto nla_put_failure; + } + nla_nest_end(skb, strings_attr); + } + + nla_nest_end(skb, stringset_attr); + return 0; + +nla_put_failure: + nla_nest_cancel(skb, stringset_attr); + return -EMSGSIZE; +} + +static int strset_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct strset_req_info *req_info = STRSET_REQINFO(req_base); + const struct strset_reply_data *data = STRSET_REPDATA(reply_base); + struct nlattr *nest; + unsigned int i; + int ret; + + nest = nla_nest_start(skb, ETHTOOL_A_STRSET_STRINGSETS); + if (!nest) + return -EMSGSIZE; + + for (i = 0; i < ETH_SS_COUNT; i++) { + if (strset_include(req_info, data, i)) { + ret = strset_fill_set(skb, &data->sets[i], i, + req_info->counts_only); + if (ret < 0) + goto nla_put_failure; + } + } + + nla_nest_end(skb, nest); + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nest); + return ret; +} + +const struct ethnl_request_ops ethnl_strset_request_ops = { + .request_cmd = ETHTOOL_MSG_STRSET_GET, + .reply_cmd = ETHTOOL_MSG_STRSET_GET_REPLY, + .hdr_attr = ETHTOOL_A_STRSET_HEADER, + .max_attr = ETHTOOL_A_STRSET_MAX, + .req_info_size = sizeof(struct strset_req_info), + .reply_data_size = sizeof(struct strset_reply_data), + .request_policy = strset_get_policy, + .allow_nodev_do = true, + + .parse_request = strset_parse_request, + .prepare_data = strset_prepare_data, + .reply_size = strset_reply_size, + .fill_reply = strset_fill_reply, + .cleanup_data = strset_cleanup_data, +}; -- cgit v1.2.3 From 459e0b81b37043545d90629fdfb243444151e77d Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:55:48 +0100 Subject: ethtool: provide link settings with LINKINFO_GET request Implement LINKINFO_GET netlink request to get basic link settings provided by ETHTOOL_GLINKSETTINGS and ETHTOOL_GSET ioctl commands. This request provides settings not directly related to autonegotiation and link mode selection: physical port, phy MDIO address, MDI(-X) status, MDI(-X) control and transceiver. LINKINFO_GET request can be used with NLM_F_DUMP (without device identification) to request the information for all devices in current network namespace providing the data. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 37 ++++++++++- include/uapi/linux/ethtool_netlink.h | 18 ++++++ net/ethtool/Makefile | 2 +- net/ethtool/common.c | 48 ++++++++++++++ net/ethtool/common.h | 4 ++ net/ethtool/ioctl.c | 48 -------------- net/ethtool/linkinfo.c | 94 ++++++++++++++++++++++++++++ net/ethtool/netlink.c | 8 +++ net/ethtool/netlink.h | 1 + 9 files changed, 209 insertions(+), 51 deletions(-) create mode 100644 net/ethtool/linkinfo.c (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 3912cb0eb9c6..60684786a92c 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -180,12 +180,14 @@ Userspace to kernel: ===================================== ================================ ``ETHTOOL_MSG_STRSET_GET`` get string set + ``ETHTOOL_MSG_LINKINFO_GET`` get link settings ===================================== ================================ Kernel to userspace: ===================================== ================================ ``ETHTOOL_MSG_STRSET_GET_REPLY`` string set contents + ``ETHTOOL_MSG_LINKINFO_GET_REPLY`` link settings ===================================== ================================ ``GET`` requests are sent by userspace applications to retrieve device @@ -278,6 +280,37 @@ Flag ``ETHTOOL_A_STRSET_COUNTS_ONLY`` tells kernel to only return string counts of the sets, not the actual strings. +LINKINFO_GET +============ + +Requests link settings as provided by ``ETHTOOL_GLINKSETTINGS`` except for +link modes and autonegotiation related information. The request does not use +any attributes. + +Request contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKINFO_HEADER`` nested request header + ==================================== ====== ========================== + +Kernel response contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKINFO_HEADER`` nested reply header + ``ETHTOOL_A_LINKINFO_PORT`` u8 physical port + ``ETHTOOL_A_LINKINFO_PHYADDR`` u8 phy MDIO address + ``ETHTOOL_A_LINKINFO_TP_MDIX`` u8 MDI(-X) status + ``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL`` u8 MDI(-X) control + ``ETHTOOL_A_LINKINFO_TRANSCEIVER`` u8 transceiver + ==================================== ====== ========================== + +Attributes and their values have the same meaning as matching members of the +corresponding ioctl structures. + +``LINKINFO_GET`` allows dump requests (kernel returns reply message for all +devices supporting the request). + + Request translation =================== @@ -288,7 +321,7 @@ have their netlink replacement yet. =================================== ===================================== ioctl command netlink command =================================== ===================================== - ``ETHTOOL_GSET`` n/a + ``ETHTOOL_GSET`` ``ETHTOOL_MSG_LINKINFO_GET`` ``ETHTOOL_SSET`` n/a ``ETHTOOL_GDRVINFO`` n/a ``ETHTOOL_GREGS`` n/a @@ -362,7 +395,7 @@ have their netlink replacement yet. ``ETHTOOL_STUNABLE`` n/a ``ETHTOOL_GPHYSTATS`` n/a ``ETHTOOL_PERQUEUE`` n/a - ``ETHTOOL_GLINKSETTINGS`` n/a + ``ETHTOOL_GLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_GET`` ``ETHTOOL_SLINKSETTINGS`` n/a ``ETHTOOL_PHY_GTUNABLE`` n/a ``ETHTOOL_PHY_STUNABLE`` n/a diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index cabef1fec42a..1966532993e5 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -15,6 +15,7 @@ enum { ETHTOOL_MSG_USER_NONE, ETHTOOL_MSG_STRSET_GET, + ETHTOOL_MSG_LINKINFO_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -25,6 +26,7 @@ enum { enum { ETHTOOL_MSG_KERNEL_NONE, ETHTOOL_MSG_STRSET_GET_REPLY, + ETHTOOL_MSG_LINKINFO_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -141,6 +143,22 @@ enum { ETHTOOL_A_STRSET_MAX = __ETHTOOL_A_STRSET_CNT - 1 }; +/* LINKINFO */ + +enum { + ETHTOOL_A_LINKINFO_UNSPEC, + ETHTOOL_A_LINKINFO_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_LINKINFO_PORT, /* u8 */ + ETHTOOL_A_LINKINFO_PHYADDR, /* u8 */ + ETHTOOL_A_LINKINFO_TP_MDIX, /* u8 */ + ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, /* u8 */ + ETHTOOL_A_LINKINFO_TRANSCEIVER, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_LINKINFO_CNT, + ETHTOOL_A_LINKINFO_MAX = __ETHTOOL_A_LINKINFO_CNT - 1 +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index efcc42c34d62..765736ec52c0 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -4,4 +4,4 @@ obj-y += ioctl.o common.o obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o -ethtool_nl-y := netlink.o bitset.o strset.o +ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 0a8728565356..1d4a0aeff2cb 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -169,3 +169,51 @@ const char link_mode_names[][ETH_GSTRING_LEN] = { __DEFINE_LINK_MODE_NAME(400000, CR8, Full), }; static_assert(ARRAY_SIZE(link_mode_names) == __ETHTOOL_LINK_MODE_MASK_NBITS); + +/* return false if legacy contained non-0 deprecated fields + * maxtxpkt/maxrxpkt. rest of ksettings always updated + */ +bool +convert_legacy_settings_to_link_ksettings( + struct ethtool_link_ksettings *link_ksettings, + const struct ethtool_cmd *legacy_settings) +{ + bool retval = true; + + memset(link_ksettings, 0, sizeof(*link_ksettings)); + + /* This is used to tell users that driver is still using these + * deprecated legacy fields, and they should not use + * %ETHTOOL_GLINKSETTINGS/%ETHTOOL_SLINKSETTINGS + */ + if (legacy_settings->maxtxpkt || + legacy_settings->maxrxpkt) + retval = false; + + ethtool_convert_legacy_u32_to_link_mode( + link_ksettings->link_modes.supported, + legacy_settings->supported); + ethtool_convert_legacy_u32_to_link_mode( + link_ksettings->link_modes.advertising, + legacy_settings->advertising); + ethtool_convert_legacy_u32_to_link_mode( + link_ksettings->link_modes.lp_advertising, + legacy_settings->lp_advertising); + link_ksettings->base.speed + = ethtool_cmd_speed(legacy_settings); + link_ksettings->base.duplex + = legacy_settings->duplex; + link_ksettings->base.port + = legacy_settings->port; + link_ksettings->base.phy_address + = legacy_settings->phy_address; + link_ksettings->base.autoneg + = legacy_settings->autoneg; + link_ksettings->base.mdio_support + = legacy_settings->mdio_support; + link_ksettings->base.eth_tp_mdix + = legacy_settings->eth_tp_mdix; + link_ksettings->base.eth_tp_mdix_ctrl + = legacy_settings->eth_tp_mdix_ctrl; + return retval; +} diff --git a/net/ethtool/common.h b/net/ethtool/common.h index bbb788908cb1..c8a237402729 100644 --- a/net/ethtool/common.h +++ b/net/ethtool/common.h @@ -19,4 +19,8 @@ extern const char phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN]; extern const char link_mode_names[][ETH_GSTRING_LEN]; +bool convert_legacy_settings_to_link_ksettings( + struct ethtool_link_ksettings *link_ksettings, + const struct ethtool_cmd *legacy_settings); + #endif /* _ETHTOOL_COMMON_H */ diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 88f7cddf5a6f..8a0a13b478e0 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -358,54 +358,6 @@ bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, } EXPORT_SYMBOL(ethtool_convert_link_mode_to_legacy_u32); -/* return false if legacy contained non-0 deprecated fields - * maxtxpkt/maxrxpkt. rest of ksettings always updated - */ -static bool -convert_legacy_settings_to_link_ksettings( - struct ethtool_link_ksettings *link_ksettings, - const struct ethtool_cmd *legacy_settings) -{ - bool retval = true; - - memset(link_ksettings, 0, sizeof(*link_ksettings)); - - /* This is used to tell users that driver is still using these - * deprecated legacy fields, and they should not use - * %ETHTOOL_GLINKSETTINGS/%ETHTOOL_SLINKSETTINGS - */ - if (legacy_settings->maxtxpkt || - legacy_settings->maxrxpkt) - retval = false; - - ethtool_convert_legacy_u32_to_link_mode( - link_ksettings->link_modes.supported, - legacy_settings->supported); - ethtool_convert_legacy_u32_to_link_mode( - link_ksettings->link_modes.advertising, - legacy_settings->advertising); - ethtool_convert_legacy_u32_to_link_mode( - link_ksettings->link_modes.lp_advertising, - legacy_settings->lp_advertising); - link_ksettings->base.speed - = ethtool_cmd_speed(legacy_settings); - link_ksettings->base.duplex - = legacy_settings->duplex; - link_ksettings->base.port - = legacy_settings->port; - link_ksettings->base.phy_address - = legacy_settings->phy_address; - link_ksettings->base.autoneg - = legacy_settings->autoneg; - link_ksettings->base.mdio_support - = legacy_settings->mdio_support; - link_ksettings->base.eth_tp_mdix - = legacy_settings->eth_tp_mdix; - link_ksettings->base.eth_tp_mdix_ctrl - = legacy_settings->eth_tp_mdix_ctrl; - return retval; -} - /* return false if ksettings link modes had higher bits * set. legacy_settings always updated (best effort) */ diff --git a/net/ethtool/linkinfo.c b/net/ethtool/linkinfo.c new file mode 100644 index 000000000000..f52a31af6fff --- /dev/null +++ b/net/ethtool/linkinfo.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "netlink.h" +#include "common.h" + +struct linkinfo_req_info { + struct ethnl_req_info base; +}; + +struct linkinfo_reply_data { + struct ethnl_reply_data base; + struct ethtool_link_ksettings ksettings; + struct ethtool_link_settings *lsettings; +}; + +#define LINKINFO_REPDATA(__reply_base) \ + container_of(__reply_base, struct linkinfo_reply_data, base) + +static const struct nla_policy +linkinfo_get_policy[ETHTOOL_A_LINKINFO_MAX + 1] = { + [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT }, +}; + +static int linkinfo_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct linkinfo_reply_data *data = LINKINFO_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + int ret; + + data->lsettings = &data->ksettings.base; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + ret = __ethtool_get_link_ksettings(dev, &data->ksettings); + if (ret < 0 && info) + GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); + ethnl_ops_complete(dev); + + return ret; +} + +static int linkinfo_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + return nla_total_size(sizeof(u8)) /* LINKINFO_PORT */ + + nla_total_size(sizeof(u8)) /* LINKINFO_PHYADDR */ + + nla_total_size(sizeof(u8)) /* LINKINFO_TP_MDIX */ + + nla_total_size(sizeof(u8)) /* LINKINFO_TP_MDIX_CTRL */ + + nla_total_size(sizeof(u8)) /* LINKINFO_TRANSCEIVER */ + + 0; +} + +static int linkinfo_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct linkinfo_reply_data *data = LINKINFO_REPDATA(reply_base); + + if (nla_put_u8(skb, ETHTOOL_A_LINKINFO_PORT, data->lsettings->port) || + nla_put_u8(skb, ETHTOOL_A_LINKINFO_PHYADDR, + data->lsettings->phy_address) || + nla_put_u8(skb, ETHTOOL_A_LINKINFO_TP_MDIX, + data->lsettings->eth_tp_mdix) || + nla_put_u8(skb, ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, + data->lsettings->eth_tp_mdix_ctrl) || + nla_put_u8(skb, ETHTOOL_A_LINKINFO_TRANSCEIVER, + data->lsettings->transceiver)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_linkinfo_request_ops = { + .request_cmd = ETHTOOL_MSG_LINKINFO_GET, + .reply_cmd = ETHTOOL_MSG_LINKINFO_GET_REPLY, + .hdr_attr = ETHTOOL_A_LINKINFO_HEADER, + .max_attr = ETHTOOL_A_LINKINFO_MAX, + .req_info_size = sizeof(struct linkinfo_req_info), + .reply_data_size = sizeof(struct linkinfo_reply_data), + .request_policy = linkinfo_get_policy, + + .prepare_data = linkinfo_prepare_data, + .reply_size = linkinfo_reply_size, + .fill_reply = linkinfo_fill_reply, +}; diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 7dc082bde670..ce86d97c922e 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -195,6 +195,7 @@ struct ethnl_dump_ctx { static const struct ethnl_request_ops * ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops, + [ETHTOOL_MSG_LINKINFO_GET] = ðnl_linkinfo_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -526,6 +527,13 @@ static const struct genl_ops ethtool_genl_ops[] = { .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, }, + { + .cmd = ETHTOOL_MSG_LINKINFO_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 44e9f63aefb7..9fc8f94d8dce 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -329,5 +329,6 @@ struct ethnl_request_ops { /* request handlers */ extern const struct ethnl_request_ops ethnl_strset_request_ops; +extern const struct ethnl_request_ops ethnl_linkinfo_request_ops; #endif /* _NET_ETHTOOL_NETLINK_H */ -- cgit v1.2.3 From a53f3d41e4d3df46aba254ba51e7fbe45470fece Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:55:53 +0100 Subject: ethtool: set link settings with LINKINFO_SET request Implement LINKINFO_SET netlink request to set link settings queried by LINKINFO_GET message. Only physical port, phy MDIO address and MDI(-X) control can be set, attempt to modify MDI(-X) status and transceiver is rejected. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 24 +++++++++- include/uapi/linux/ethtool_netlink.h | 1 + net/ethtool/linkinfo.c | 71 ++++++++++++++++++++++++++++ net/ethtool/netlink.c | 5 ++ net/ethtool/netlink.h | 2 + 5 files changed, 101 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 60684786a92c..39c4aba324c3 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -181,6 +181,7 @@ Userspace to kernel: ===================================== ================================ ``ETHTOOL_MSG_STRSET_GET`` get string set ``ETHTOOL_MSG_LINKINFO_GET`` get link settings + ``ETHTOOL_MSG_LINKINFO_SET`` set link settings ===================================== ================================ Kernel to userspace: @@ -311,6 +312,25 @@ corresponding ioctl structures. devices supporting the request). +LINKINFO_SET +============ + +``LINKINFO_SET`` request allows setting some of the attributes reported by +``LINKINFO_GET``. + +Request contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKINFO_HEADER`` nested request header + ``ETHTOOL_A_LINKINFO_PORT`` u8 physical port + ``ETHTOOL_A_LINKINFO_PHYADDR`` u8 phy MDIO address + ``ETHTOOL_A_LINKINFO_TP_MDIX_CTRL`` u8 MDI(-X) control + ==================================== ====== ========================== + +MDI(-X) status and transceiver cannot be set, request with the corresponding +attributes is rejected. + + Request translation =================== @@ -322,7 +342,7 @@ have their netlink replacement yet. ioctl command netlink command =================================== ===================================== ``ETHTOOL_GSET`` ``ETHTOOL_MSG_LINKINFO_GET`` - ``ETHTOOL_SSET`` n/a + ``ETHTOOL_SSET`` ``ETHTOOL_MSG_LINKINFO_SET`` ``ETHTOOL_GDRVINFO`` n/a ``ETHTOOL_GREGS`` n/a ``ETHTOOL_GWOL`` n/a @@ -396,7 +416,7 @@ have their netlink replacement yet. ``ETHTOOL_GPHYSTATS`` n/a ``ETHTOOL_PERQUEUE`` n/a ``ETHTOOL_GLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_GET`` - ``ETHTOOL_SLINKSETTINGS`` n/a + ``ETHTOOL_SLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_SET`` ``ETHTOOL_PHY_GTUNABLE`` n/a ``ETHTOOL_PHY_STUNABLE`` n/a ``ETHTOOL_GFECPARAM`` n/a diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 1966532993e5..5b7806a5bef8 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -16,6 +16,7 @@ enum { ETHTOOL_MSG_USER_NONE, ETHTOOL_MSG_STRSET_GET, ETHTOOL_MSG_LINKINFO_GET, + ETHTOOL_MSG_LINKINFO_SET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, diff --git a/net/ethtool/linkinfo.c b/net/ethtool/linkinfo.c index f52a31af6fff..8a5f68f92425 100644 --- a/net/ethtool/linkinfo.c +++ b/net/ethtool/linkinfo.c @@ -92,3 +92,74 @@ const struct ethnl_request_ops ethnl_linkinfo_request_ops = { .reply_size = linkinfo_reply_size, .fill_reply = linkinfo_fill_reply, }; + +/* LINKINFO_SET */ + +static const struct nla_policy +linkinfo_set_policy[ETHTOOL_A_LINKINFO_MAX + 1] = { + [ETHTOOL_A_LINKINFO_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_LINKINFO_PORT] = { .type = NLA_U8 }, + [ETHTOOL_A_LINKINFO_PHYADDR] = { .type = NLA_U8 }, + [ETHTOOL_A_LINKINFO_TP_MDIX] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKINFO_TP_MDIX_CTRL] = { .type = NLA_U8 }, + [ETHTOOL_A_LINKINFO_TRANSCEIVER] = { .type = NLA_REJECT }, +}; + +int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *tb[ETHTOOL_A_LINKINFO_MAX + 1]; + struct ethtool_link_ksettings ksettings = {}; + struct ethtool_link_settings *lsettings; + struct ethnl_req_info req_info = {}; + struct net_device *dev; + bool mod = false; + int ret; + + ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, + ETHTOOL_A_LINKINFO_MAX, linkinfo_set_policy, + info->extack); + if (ret < 0) + return ret; + ret = ethnl_parse_header(&req_info, tb[ETHTOOL_A_LINKINFO_HEADER], + genl_info_net(info), info->extack, true); + if (ret < 0) + return ret; + dev = req_info.dev; + if (!dev->ethtool_ops->get_link_ksettings || + !dev->ethtool_ops->set_link_ksettings) + return -EOPNOTSUPP; + + rtnl_lock(); + ret = ethnl_ops_begin(dev); + if (ret < 0) + goto out_rtnl; + + ret = __ethtool_get_link_ksettings(dev, &ksettings); + if (ret < 0) { + if (info) + GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); + goto out_ops; + } + lsettings = &ksettings.base; + + ethnl_update_u8(&lsettings->port, tb[ETHTOOL_A_LINKINFO_PORT], &mod); + ethnl_update_u8(&lsettings->phy_address, tb[ETHTOOL_A_LINKINFO_PHYADDR], + &mod); + ethnl_update_u8(&lsettings->eth_tp_mdix_ctrl, + tb[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL], &mod); + ret = 0; + if (!mod) + goto out_ops; + + ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings); + if (ret < 0) + GENL_SET_ERR_MSG(info, "link settings update failed"); + +out_ops: + ethnl_ops_complete(dev); +out_rtnl: + rtnl_unlock(); + dev_put(dev); + return ret; +} diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index ce86d97c922e..7867425956f6 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -534,6 +534,11 @@ static const struct genl_ops ethtool_genl_ops[] = { .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, }, + { + .cmd = ETHTOOL_MSG_LINKINFO_SET, + .flags = GENL_UNS_ADMIN_PERM, + .doit = ethnl_set_linkinfo, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 9fc8f94d8dce..bbe5fe60a023 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -331,4 +331,6 @@ struct ethnl_request_ops { extern const struct ethnl_request_ops ethnl_strset_request_ops; extern const struct ethnl_request_ops ethnl_linkinfo_request_ops; +int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); + #endif /* _NET_ETHTOOL_NETLINK_H */ -- cgit v1.2.3 From 73286734c1b0d009fd317c2a74e173cb22233dad Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:56:03 +0100 Subject: ethtool: add LINKINFO_NTF notification Send ETHTOOL_MSG_LINKINFO_NTF notification message whenever device link settings are modified using ETHTOOL_MSG_LINKINFO_SET netlink message or ETHTOOL_SLINKSETTINGS or ETHTOOL_SSET ioctl commands. The notification message has the same format as reply to LINKINFO_GET request. ETHTOOL_MSG_LINKINFO_SET netlink request only triggers the notification if there is a change but the ioctl command handlers do not check if there is an actual change and trigger the notification whenever the commands are executed. As all work is done by ethnl_default_notify() handler and callback functions introduced to handle LINKINFO_GET requests, all that remains is adding entries for ETHTOOL_MSG_LINKINFO_NTF into ethnl_notify_handlers and ethnl_default_notify_ops lookup tables and calls to ethtool_notify() where needed. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 1 + include/uapi/linux/ethtool_netlink.h | 1 + net/ethtool/ioctl.c | 12 ++++++++++-- net/ethtool/linkinfo.c | 2 ++ net/ethtool/netlink.c | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 39c4aba324c3..34254482d295 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -189,6 +189,7 @@ Kernel to userspace: ===================================== ================================ ``ETHTOOL_MSG_STRSET_GET_REPLY`` string set contents ``ETHTOOL_MSG_LINKINFO_GET_REPLY`` link settings + ``ETHTOOL_MSG_LINKINFO_NTF`` link settings notification ===================================== ================================ ``GET`` requests are sent by userspace applications to retrieve device diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 5b7806a5bef8..d530fa30de36 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -28,6 +28,7 @@ enum { ETHTOOL_MSG_KERNEL_NONE, ETHTOOL_MSG_STRSET_GET_REPLY, ETHTOOL_MSG_LINKINFO_GET_REPLY, + ETHTOOL_MSG_LINKINFO_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 8a0a13b478e0..11a467294a33 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "common.h" @@ -571,7 +572,10 @@ static int ethtool_set_link_ksettings(struct net_device *dev, != link_ksettings.base.link_mode_masks_nwords) return -EINVAL; - return dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); + err = dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); + if (err >= 0) + ethtool_notify(dev, ETHTOOL_MSG_LINKINFO_NTF, NULL); + return err; } /* Query device for its ethtool_cmd settings. @@ -620,6 +624,7 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) { struct ethtool_link_ksettings link_ksettings; struct ethtool_cmd cmd; + int ret; ASSERT_RTNL(); @@ -632,7 +637,10 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) return -EINVAL; link_ksettings.base.link_mode_masks_nwords = __ETHTOOL_LINK_MODE_MASK_NU32; - return dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); + ret = dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); + if (ret >= 0) + ethtool_notify(dev, ETHTOOL_MSG_LINKINFO_NTF, NULL); + return ret; } static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, diff --git a/net/ethtool/linkinfo.c b/net/ethtool/linkinfo.c index 8a5f68f92425..5d16cb4e8693 100644 --- a/net/ethtool/linkinfo.c +++ b/net/ethtool/linkinfo.c @@ -155,6 +155,8 @@ int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info) ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings); if (ret < 0) GENL_SET_ERR_MSG(info, "link settings update failed"); + else + ethtool_notify(dev, ETHTOOL_MSG_LINKINFO_NTF, NULL); out_ops: ethnl_ops_complete(dev); diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 057b67f8ba8c..942da4ebdfe9 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -509,6 +509,7 @@ static int ethnl_default_done(struct netlink_callback *cb) static const struct ethnl_request_ops * ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { + [ETHTOOL_MSG_LINKINFO_NTF] = ðnl_linkinfo_request_ops, }; /* default notification handler */ @@ -589,6 +590,7 @@ typedef void (*ethnl_notify_handler_t)(struct net_device *dev, unsigned int cmd, const void *data); static const ethnl_notify_handler_t ethnl_notify_handlers[] = { + [ETHTOOL_MSG_LINKINFO_NTF] = ethnl_default_notify, }; void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data) -- cgit v1.2.3 From f625aa9be8c10f2e4dc677837e240730a25feda7 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:56:08 +0100 Subject: ethtool: provide link mode information with LINKMODES_GET request Implement LINKMODES_GET netlink request to get link modes related information provided by ETHTOOL_GLINKSETTINGS and ETHTOOL_GSET ioctl commands. This request provides supported, advertised and peer advertised link modes, autonegotiation flag, speed and duplex. LINKMODES_GET request can be used with NLM_F_DUMP (without device identification) to request the information for all devices in current network namespace providing the data. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 36 +++++++ include/linux/ethtool_netlink.h | 3 + include/uapi/linux/ethtool_netlink.h | 18 ++++ net/ethtool/Makefile | 2 +- net/ethtool/linkmodes.c | 140 +++++++++++++++++++++++++++ net/ethtool/netlink.c | 8 ++ net/ethtool/netlink.h | 1 + 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 net/ethtool/linkmodes.c (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 34254482d295..04c55be0264c 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -182,6 +182,7 @@ Userspace to kernel: ``ETHTOOL_MSG_STRSET_GET`` get string set ``ETHTOOL_MSG_LINKINFO_GET`` get link settings ``ETHTOOL_MSG_LINKINFO_SET`` set link settings + ``ETHTOOL_MSG_LINKMODES_GET`` get link modes info ===================================== ================================ Kernel to userspace: @@ -190,6 +191,7 @@ Kernel to userspace: ``ETHTOOL_MSG_STRSET_GET_REPLY`` string set contents ``ETHTOOL_MSG_LINKINFO_GET_REPLY`` link settings ``ETHTOOL_MSG_LINKINFO_NTF`` link settings notification + ``ETHTOOL_MSG_LINKMODES_GET_REPLY`` link modes info ===================================== ================================ ``GET`` requests are sent by userspace applications to retrieve device @@ -332,6 +334,38 @@ MDI(-X) status and transceiver cannot be set, request with the corresponding attributes is rejected. +LINKMODES_GET +============= + +Requests link modes (supported, advertised and peer advertised) and related +information (autonegotiation status, link speed and duplex) as provided by +``ETHTOOL_GLINKSETTINGS``. The request does not use any attributes. + +Request contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKMODES_HEADER`` nested request header + ==================================== ====== ========================== + +Kernel response contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKMODES_HEADER`` nested reply header + ``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status + ``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes + ``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes + ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode + ==================================== ====== ========================== + +For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask +represents supported modes. ``ETHTOOL_A_LINKMODES_PEER`` in the reply is a bit +list. + +``LINKMODES_GET`` allows dump requests (kernel returns reply messages for all +devices supporting the request). + + Request translation =================== @@ -343,6 +377,7 @@ have their netlink replacement yet. ioctl command netlink command =================================== ===================================== ``ETHTOOL_GSET`` ``ETHTOOL_MSG_LINKINFO_GET`` + ``ETHTOOL_MSG_LINKMODES_GET`` ``ETHTOOL_SSET`` ``ETHTOOL_MSG_LINKINFO_SET`` ``ETHTOOL_GDRVINFO`` n/a ``ETHTOOL_GREGS`` n/a @@ -417,6 +452,7 @@ have their netlink replacement yet. ``ETHTOOL_GPHYSTATS`` n/a ``ETHTOOL_PERQUEUE`` n/a ``ETHTOOL_GLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_GET`` + ``ETHTOOL_MSG_LINKMODES_GET`` ``ETHTOOL_SLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_SET`` ``ETHTOOL_PHY_GTUNABLE`` n/a ``ETHTOOL_PHY_STUNABLE`` n/a diff --git a/include/linux/ethtool_netlink.h b/include/linux/ethtool_netlink.h index c98f6852c8eb..d01b77887f82 100644 --- a/include/linux/ethtool_netlink.h +++ b/include/linux/ethtool_netlink.h @@ -7,6 +7,9 @@ #include #include +#define __ETHTOOL_LINK_MODE_MASK_NWORDS \ + DIV_ROUND_UP(__ETHTOOL_LINK_MODE_MASK_NBITS, 32) + enum ethtool_multicast_groups { ETHNL_MCGRP_MONITOR, }; diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index d530fa30de36..dc1cae052eee 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -17,6 +17,7 @@ enum { ETHTOOL_MSG_STRSET_GET, ETHTOOL_MSG_LINKINFO_GET, ETHTOOL_MSG_LINKINFO_SET, + ETHTOOL_MSG_LINKMODES_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -29,6 +30,7 @@ enum { ETHTOOL_MSG_STRSET_GET_REPLY, ETHTOOL_MSG_LINKINFO_GET_REPLY, ETHTOOL_MSG_LINKINFO_NTF, + ETHTOOL_MSG_LINKMODES_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -161,6 +163,22 @@ enum { ETHTOOL_A_LINKINFO_MAX = __ETHTOOL_A_LINKINFO_CNT - 1 }; +/* LINKMODES */ + +enum { + ETHTOOL_A_LINKMODES_UNSPEC, + ETHTOOL_A_LINKMODES_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_LINKMODES_AUTONEG, /* u8 */ + ETHTOOL_A_LINKMODES_OURS, /* bitset */ + ETHTOOL_A_LINKMODES_PEER, /* bitset */ + ETHTOOL_A_LINKMODES_SPEED, /* u32 */ + ETHTOOL_A_LINKMODES_DUPLEX, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_LINKMODES_CNT, + ETHTOOL_A_LINKMODES_MAX = __ETHTOOL_A_LINKMODES_CNT - 1 +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index 765736ec52c0..8023da6672ce 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -4,4 +4,4 @@ obj-y += ioctl.o common.o obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o -ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o +ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c new file mode 100644 index 000000000000..81856fa1e632 --- /dev/null +++ b/net/ethtool/linkmodes.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "netlink.h" +#include "common.h" +#include "bitset.h" + +struct linkmodes_req_info { + struct ethnl_req_info base; +}; + +struct linkmodes_reply_data { + struct ethnl_reply_data base; + struct ethtool_link_ksettings ksettings; + struct ethtool_link_settings *lsettings; + bool peer_empty; +}; + +#define LINKMODES_REPDATA(__reply_base) \ + container_of(__reply_base, struct linkmodes_reply_data, base) + +static const struct nla_policy +linkmodes_get_policy[ETHTOOL_A_LINKMODES_MAX + 1] = { + [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_REJECT }, +}; + +static int linkmodes_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct linkmodes_reply_data *data = LINKMODES_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + int ret; + + data->lsettings = &data->ksettings.base; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + + ret = __ethtool_get_link_ksettings(dev, &data->ksettings); + if (ret < 0 && info) { + GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); + goto out; + } + + data->peer_empty = + bitmap_empty(data->ksettings.link_modes.lp_advertising, + __ETHTOOL_LINK_MODE_MASK_NBITS); + +out: + ethnl_ops_complete(dev); + return ret; +} + +static int linkmodes_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct linkmodes_reply_data *data = LINKMODES_REPDATA(reply_base); + const struct ethtool_link_ksettings *ksettings = &data->ksettings; + bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; + int len, ret; + + len = nla_total_size(sizeof(u8)) /* LINKMODES_AUTONEG */ + + nla_total_size(sizeof(u32)) /* LINKMODES_SPEED */ + + nla_total_size(sizeof(u8)) /* LINKMODES_DUPLEX */ + + 0; + ret = ethnl_bitset_size(ksettings->link_modes.advertising, + ksettings->link_modes.supported, + __ETHTOOL_LINK_MODE_MASK_NBITS, + link_mode_names, compact); + if (ret < 0) + return ret; + len += ret; + if (!data->peer_empty) { + ret = ethnl_bitset_size(ksettings->link_modes.lp_advertising, + NULL, __ETHTOOL_LINK_MODE_MASK_NBITS, + link_mode_names, compact); + if (ret < 0) + return ret; + len += ret; + } + + return len; +} + +static int linkmodes_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + const struct linkmodes_reply_data *data = LINKMODES_REPDATA(reply_base); + const struct ethtool_link_ksettings *ksettings = &data->ksettings; + const struct ethtool_link_settings *lsettings = &ksettings->base; + bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS; + int ret; + + if (nla_put_u8(skb, ETHTOOL_A_LINKMODES_AUTONEG, lsettings->autoneg)) + return -EMSGSIZE; + + ret = ethnl_put_bitset(skb, ETHTOOL_A_LINKMODES_OURS, + ksettings->link_modes.advertising, + ksettings->link_modes.supported, + __ETHTOOL_LINK_MODE_MASK_NBITS, link_mode_names, + compact); + if (ret < 0) + return -EMSGSIZE; + if (!data->peer_empty) { + ret = ethnl_put_bitset(skb, ETHTOOL_A_LINKMODES_PEER, + ksettings->link_modes.lp_advertising, + NULL, __ETHTOOL_LINK_MODE_MASK_NBITS, + link_mode_names, compact); + if (ret < 0) + return -EMSGSIZE; + } + + if (nla_put_u32(skb, ETHTOOL_A_LINKMODES_SPEED, lsettings->speed) || + nla_put_u8(skb, ETHTOOL_A_LINKMODES_DUPLEX, lsettings->duplex)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_linkmodes_request_ops = { + .request_cmd = ETHTOOL_MSG_LINKMODES_GET, + .reply_cmd = ETHTOOL_MSG_LINKMODES_GET_REPLY, + .hdr_attr = ETHTOOL_A_LINKMODES_HEADER, + .max_attr = ETHTOOL_A_LINKMODES_MAX, + .req_info_size = sizeof(struct linkmodes_req_info), + .reply_data_size = sizeof(struct linkmodes_reply_data), + .request_policy = linkmodes_get_policy, + + .prepare_data = linkmodes_prepare_data, + .reply_size = linkmodes_reply_size, + .fill_reply = linkmodes_fill_reply, +}; diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 942da4ebdfe9..703ff3a227a4 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -209,6 +209,7 @@ static const struct ethnl_request_ops * ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops, [ETHTOOL_MSG_LINKINFO_GET] = ðnl_linkinfo_request_ops, + [ETHTOOL_MSG_LINKMODES_GET] = ðnl_linkmodes_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -630,6 +631,13 @@ static const struct genl_ops ethtool_genl_ops[] = { .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_linkinfo, }, + { + .cmd = ETHTOOL_MSG_LINKMODES_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 5d56d7779a06..256d38972d1e 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -332,6 +332,7 @@ struct ethnl_request_ops { extern const struct ethnl_request_ops ethnl_strset_request_ops; extern const struct ethnl_request_ops ethnl_linkinfo_request_ops; +extern const struct ethnl_request_ops ethnl_linkmodes_request_ops; int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); -- cgit v1.2.3 From bfbcfe2032e70bd8598d680d39ac177d507e39ac Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:56:13 +0100 Subject: ethtool: set link modes related data with LINKMODES_SET request Implement LINKMODES_SET netlink request to set advertised linkmodes and related attributes as ETHTOOL_SLINKSETTINGS and ETHTOOL_SSET commands do. The request allows setting autonegotiation flag, speed, duplex and advertised link modes. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 27 +++ include/uapi/linux/ethtool_netlink.h | 1 + net/ethtool/linkmodes.c | 235 +++++++++++++++++++++++++++ net/ethtool/netlink.c | 5 + net/ethtool/netlink.h | 1 + 5 files changed, 269 insertions(+) (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 04c55be0264c..625c80183563 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -183,6 +183,7 @@ Userspace to kernel: ``ETHTOOL_MSG_LINKINFO_GET`` get link settings ``ETHTOOL_MSG_LINKINFO_SET`` set link settings ``ETHTOOL_MSG_LINKMODES_GET`` get link modes info + ``ETHTOOL_MSG_LINKMODES_SET`` set link modes info ===================================== ================================ Kernel to userspace: @@ -366,6 +367,30 @@ list. devices supporting the request). +LINKMODES_SET +============= + +Request contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKMODES_HEADER`` nested request header + ``ETHTOOL_A_LINKMODES_AUTONEG`` u8 autonegotiation status + ``ETHTOOL_A_LINKMODES_OURS`` bitset advertised link modes + ``ETHTOOL_A_LINKMODES_PEER`` bitset partner link modes + ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s) + ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode + ==================================== ====== ========================== + +``ETHTOOL_A_LINKMODES_OURS`` bit set allows setting advertised link modes. If +autonegotiation is on (either set now or kept from before), advertised modes +are not changed (no ``ETHTOOL_A_LINKMODES_OURS`` attribute) and at least one +of speed and duplex is specified, kernel adjusts advertised modes to all +supported modes matching speed, duplex or both (whatever is specified). This +autoselection is done on ethtool side with ioctl interface, netlink interface +is supposed to allow requesting changes without knowing what exactly kernel +supports. + + Request translation =================== @@ -379,6 +404,7 @@ have their netlink replacement yet. ``ETHTOOL_GSET`` ``ETHTOOL_MSG_LINKINFO_GET`` ``ETHTOOL_MSG_LINKMODES_GET`` ``ETHTOOL_SSET`` ``ETHTOOL_MSG_LINKINFO_SET`` + ``ETHTOOL_MSG_LINKMODES_SET`` ``ETHTOOL_GDRVINFO`` n/a ``ETHTOOL_GREGS`` n/a ``ETHTOOL_GWOL`` n/a @@ -454,6 +480,7 @@ have their netlink replacement yet. ``ETHTOOL_GLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_GET`` ``ETHTOOL_MSG_LINKMODES_GET`` ``ETHTOOL_SLINKSETTINGS`` ``ETHTOOL_MSG_LINKINFO_SET`` + ``ETHTOOL_MSG_LINKMODES_SET`` ``ETHTOOL_PHY_GTUNABLE`` n/a ``ETHTOOL_PHY_STUNABLE`` n/a ``ETHTOOL_GFECPARAM`` n/a diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index dc1cae052eee..cddf978b98df 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -18,6 +18,7 @@ enum { ETHTOOL_MSG_LINKINFO_GET, ETHTOOL_MSG_LINKINFO_SET, ETHTOOL_MSG_LINKMODES_GET, + ETHTOOL_MSG_LINKMODES_SET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c index 81856fa1e632..790b60771d0e 100644 --- a/net/ethtool/linkmodes.c +++ b/net/ethtool/linkmodes.c @@ -138,3 +138,238 @@ const struct ethnl_request_ops ethnl_linkmodes_request_ops = { .reply_size = linkmodes_reply_size, .fill_reply = linkmodes_fill_reply, }; + +/* LINKMODES_SET */ + +struct link_mode_info { + int speed; + u8 duplex; +}; + +#define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex) \ + [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \ + .speed = SPEED_ ## _speed, \ + .duplex = __DUPLEX_ ## _duplex \ + } +#define __DUPLEX_Half DUPLEX_HALF +#define __DUPLEX_Full DUPLEX_FULL +#define __DEFINE_SPECIAL_MODE_PARAMS(_mode) \ + [ETHTOOL_LINK_MODE_ ## _mode ## _BIT] = { \ + .speed = SPEED_UNKNOWN, \ + .duplex = DUPLEX_UNKNOWN, \ + } + +static const struct link_mode_info link_mode_params[] = { + __DEFINE_LINK_MODE_PARAMS(10, T, Half), + __DEFINE_LINK_MODE_PARAMS(10, T, Full), + __DEFINE_LINK_MODE_PARAMS(100, T, Half), + __DEFINE_LINK_MODE_PARAMS(100, T, Full), + __DEFINE_LINK_MODE_PARAMS(1000, T, Half), + __DEFINE_LINK_MODE_PARAMS(1000, T, Full), + __DEFINE_SPECIAL_MODE_PARAMS(Autoneg), + __DEFINE_SPECIAL_MODE_PARAMS(TP), + __DEFINE_SPECIAL_MODE_PARAMS(AUI), + __DEFINE_SPECIAL_MODE_PARAMS(MII), + __DEFINE_SPECIAL_MODE_PARAMS(FIBRE), + __DEFINE_SPECIAL_MODE_PARAMS(BNC), + __DEFINE_LINK_MODE_PARAMS(10000, T, Full), + __DEFINE_SPECIAL_MODE_PARAMS(Pause), + __DEFINE_SPECIAL_MODE_PARAMS(Asym_Pause), + __DEFINE_LINK_MODE_PARAMS(2500, X, Full), + __DEFINE_SPECIAL_MODE_PARAMS(Backplane), + __DEFINE_LINK_MODE_PARAMS(1000, KX, Full), + __DEFINE_LINK_MODE_PARAMS(10000, KX4, Full), + __DEFINE_LINK_MODE_PARAMS(10000, KR, Full), + [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = { + .speed = SPEED_10000, + .duplex = DUPLEX_FULL, + }, + __DEFINE_LINK_MODE_PARAMS(20000, MLD2, Full), + __DEFINE_LINK_MODE_PARAMS(20000, KR2, Full), + __DEFINE_LINK_MODE_PARAMS(40000, KR4, Full), + __DEFINE_LINK_MODE_PARAMS(40000, CR4, Full), + __DEFINE_LINK_MODE_PARAMS(40000, SR4, Full), + __DEFINE_LINK_MODE_PARAMS(40000, LR4, Full), + __DEFINE_LINK_MODE_PARAMS(56000, KR4, Full), + __DEFINE_LINK_MODE_PARAMS(56000, CR4, Full), + __DEFINE_LINK_MODE_PARAMS(56000, SR4, Full), + __DEFINE_LINK_MODE_PARAMS(56000, LR4, Full), + __DEFINE_LINK_MODE_PARAMS(25000, CR, Full), + __DEFINE_LINK_MODE_PARAMS(25000, KR, Full), + __DEFINE_LINK_MODE_PARAMS(25000, SR, Full), + __DEFINE_LINK_MODE_PARAMS(50000, CR2, Full), + __DEFINE_LINK_MODE_PARAMS(50000, KR2, Full), + __DEFINE_LINK_MODE_PARAMS(100000, KR4, Full), + __DEFINE_LINK_MODE_PARAMS(100000, SR4, Full), + __DEFINE_LINK_MODE_PARAMS(100000, CR4, Full), + __DEFINE_LINK_MODE_PARAMS(100000, LR4_ER4, Full), + __DEFINE_LINK_MODE_PARAMS(50000, SR2, Full), + __DEFINE_LINK_MODE_PARAMS(1000, X, Full), + __DEFINE_LINK_MODE_PARAMS(10000, CR, Full), + __DEFINE_LINK_MODE_PARAMS(10000, SR, Full), + __DEFINE_LINK_MODE_PARAMS(10000, LR, Full), + __DEFINE_LINK_MODE_PARAMS(10000, LRM, Full), + __DEFINE_LINK_MODE_PARAMS(10000, ER, Full), + __DEFINE_LINK_MODE_PARAMS(2500, T, Full), + __DEFINE_LINK_MODE_PARAMS(5000, T, Full), + __DEFINE_SPECIAL_MODE_PARAMS(FEC_NONE), + __DEFINE_SPECIAL_MODE_PARAMS(FEC_RS), + __DEFINE_SPECIAL_MODE_PARAMS(FEC_BASER), + __DEFINE_LINK_MODE_PARAMS(50000, KR, Full), + __DEFINE_LINK_MODE_PARAMS(50000, SR, Full), + __DEFINE_LINK_MODE_PARAMS(50000, CR, Full), + __DEFINE_LINK_MODE_PARAMS(50000, LR_ER_FR, Full), + __DEFINE_LINK_MODE_PARAMS(50000, DR, Full), + __DEFINE_LINK_MODE_PARAMS(100000, KR2, Full), + __DEFINE_LINK_MODE_PARAMS(100000, SR2, Full), + __DEFINE_LINK_MODE_PARAMS(100000, CR2, Full), + __DEFINE_LINK_MODE_PARAMS(100000, LR2_ER2_FR2, Full), + __DEFINE_LINK_MODE_PARAMS(100000, DR2, Full), + __DEFINE_LINK_MODE_PARAMS(200000, KR4, Full), + __DEFINE_LINK_MODE_PARAMS(200000, SR4, Full), + __DEFINE_LINK_MODE_PARAMS(200000, LR4_ER4_FR4, Full), + __DEFINE_LINK_MODE_PARAMS(200000, DR4, Full), + __DEFINE_LINK_MODE_PARAMS(200000, CR4, Full), + __DEFINE_LINK_MODE_PARAMS(100, T1, Full), + __DEFINE_LINK_MODE_PARAMS(1000, T1, Full), + __DEFINE_LINK_MODE_PARAMS(400000, KR8, Full), + __DEFINE_LINK_MODE_PARAMS(400000, SR8, Full), + __DEFINE_LINK_MODE_PARAMS(400000, LR8_ER8_FR8, Full), + __DEFINE_LINK_MODE_PARAMS(400000, DR8, Full), + __DEFINE_LINK_MODE_PARAMS(400000, CR8, Full), +}; + +static const struct nla_policy +linkmodes_set_policy[ETHTOOL_A_LINKMODES_MAX + 1] = { + [ETHTOOL_A_LINKMODES_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_LINKMODES_AUTONEG] = { .type = NLA_U8 }, + [ETHTOOL_A_LINKMODES_OURS] = { .type = NLA_NESTED }, + [ETHTOOL_A_LINKMODES_PEER] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKMODES_SPEED] = { .type = NLA_U32 }, + [ETHTOOL_A_LINKMODES_DUPLEX] = { .type = NLA_U8 }, +}; + +/* Set advertised link modes to all supported modes matching requested speed + * and duplex values. Called when autonegotiation is on, speed or duplex is + * requested but no link mode change. This is done in userspace with ioctl() + * interface, move it into kernel for netlink. + * Returns true if advertised modes bitmap was modified. + */ +static bool ethnl_auto_linkmodes(struct ethtool_link_ksettings *ksettings, + bool req_speed, bool req_duplex) +{ + unsigned long *advertising = ksettings->link_modes.advertising; + unsigned long *supported = ksettings->link_modes.supported; + DECLARE_BITMAP(old_adv, __ETHTOOL_LINK_MODE_MASK_NBITS); + unsigned int i; + + BUILD_BUG_ON(ARRAY_SIZE(link_mode_params) != + __ETHTOOL_LINK_MODE_MASK_NBITS); + + bitmap_copy(old_adv, advertising, __ETHTOOL_LINK_MODE_MASK_NBITS); + + for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) { + const struct link_mode_info *info = &link_mode_params[i]; + + if (info->speed == SPEED_UNKNOWN) + continue; + if (test_bit(i, supported) && + (!req_speed || info->speed == ksettings->base.speed) && + (!req_duplex || info->duplex == ksettings->base.duplex)) + set_bit(i, advertising); + else + clear_bit(i, advertising); + } + + return !bitmap_equal(old_adv, advertising, + __ETHTOOL_LINK_MODE_MASK_NBITS); +} + +static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb, + struct ethtool_link_ksettings *ksettings, + bool *mod) +{ + struct ethtool_link_settings *lsettings = &ksettings->base; + bool req_speed, req_duplex; + int ret; + + *mod = false; + req_speed = tb[ETHTOOL_A_LINKMODES_SPEED]; + req_duplex = tb[ETHTOOL_A_LINKMODES_DUPLEX]; + + ethnl_update_u8(&lsettings->autoneg, tb[ETHTOOL_A_LINKMODES_AUTONEG], + mod); + ret = ethnl_update_bitset(ksettings->link_modes.advertising, + __ETHTOOL_LINK_MODE_MASK_NBITS, + tb[ETHTOOL_A_LINKMODES_OURS], link_mode_names, + info->extack, mod); + if (ret < 0) + return ret; + ethnl_update_u32(&lsettings->speed, tb[ETHTOOL_A_LINKMODES_SPEED], + mod); + ethnl_update_u8(&lsettings->duplex, tb[ETHTOOL_A_LINKMODES_DUPLEX], + mod); + + if (!tb[ETHTOOL_A_LINKMODES_OURS] && lsettings->autoneg && + (req_speed || req_duplex) && + ethnl_auto_linkmodes(ksettings, req_speed, req_duplex)) + *mod = true; + + return 0; +} + +int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *tb[ETHTOOL_A_LINKMODES_MAX + 1]; + struct ethtool_link_ksettings ksettings = {}; + struct ethtool_link_settings *lsettings; + struct ethnl_req_info req_info = {}; + struct net_device *dev; + bool mod = false; + int ret; + + ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, + ETHTOOL_A_LINKMODES_MAX, linkmodes_set_policy, + info->extack); + if (ret < 0) + return ret; + ret = ethnl_parse_header(&req_info, tb[ETHTOOL_A_LINKMODES_HEADER], + genl_info_net(info), info->extack, true); + if (ret < 0) + return ret; + dev = req_info.dev; + if (!dev->ethtool_ops->get_link_ksettings || + !dev->ethtool_ops->set_link_ksettings) + return -EOPNOTSUPP; + + rtnl_lock(); + ret = ethnl_ops_begin(dev); + if (ret < 0) + goto out_rtnl; + + ret = __ethtool_get_link_ksettings(dev, &ksettings); + if (ret < 0) { + if (info) + GENL_SET_ERR_MSG(info, "failed to retrieve link settings"); + goto out_ops; + } + lsettings = &ksettings.base; + + ret = ethnl_update_linkmodes(info, tb, &ksettings, &mod); + if (ret < 0) + goto out_ops; + + if (mod) { + ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings); + if (ret < 0) + GENL_SET_ERR_MSG(info, "link settings update failed"); + } + +out_ops: + ethnl_ops_complete(dev); +out_rtnl: + rtnl_unlock(); + dev_put(dev); + return ret; +} diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 703ff3a227a4..5f28f3cb022d 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -638,6 +638,11 @@ static const struct genl_ops ethtool_genl_ops[] = { .dumpit = ethnl_default_dumpit, .done = ethnl_default_done, }, + { + .cmd = ETHTOOL_MSG_LINKMODES_SET, + .flags = GENL_UNS_ADMIN_PERM, + .doit = ethnl_set_linkmodes, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 256d38972d1e..1269cca8a002 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -335,5 +335,6 @@ extern const struct ethnl_request_ops ethnl_linkinfo_request_ops; extern const struct ethnl_request_ops ethnl_linkmodes_request_ops; int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); +int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); #endif /* _NET_ETHTOOL_NETLINK_H */ -- cgit v1.2.3 From 1b1b1847c8505df2e1dd8804838526bed22a8bd4 Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:56:18 +0100 Subject: ethtool: add LINKMODES_NTF notification Send ETHTOOL_MSG_LINKMODES_NTF notification message whenever device link settings or advertised modes are modified using ETHTOOL_MSG_LINKMODES_SET netlink message or ETHTOOL_SLINKSETTINGS or ETHTOOL_SSET ioctl commands. The notification message has the same format as reply to LINKMODES_GET request. ETHTOOL_MSG_LINKMODES_SET netlink request only triggers the notification if there is a change but the ioctl command handlers do not check if there is an actual change and trigger the notification whenever the commands are executed. As all work is done by ethnl_default_notify() handler and callback functions introduced to handle LINKMODES_GET requests, all that remains is adding entries for ETHTOOL_MSG_LINKMODES_NTF into ethnl_notify_handlers and ethnl_default_notify_ops lookup tables and calls to ethtool_notify() where needed. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 1 + include/uapi/linux/ethtool_netlink.h | 1 + net/ethtool/ioctl.c | 8 ++++++-- net/ethtool/linkmodes.c | 2 ++ net/ethtool/netlink.c | 2 ++ 5 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 625c80183563..9d96d51e9360 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -193,6 +193,7 @@ Kernel to userspace: ``ETHTOOL_MSG_LINKINFO_GET_REPLY`` link settings ``ETHTOOL_MSG_LINKINFO_NTF`` link settings notification ``ETHTOOL_MSG_LINKMODES_GET_REPLY`` link modes info + ``ETHTOOL_MSG_LINKMODES_NTF`` link modes notification ===================================== ================================ ``GET`` requests are sent by userspace applications to retrieve device diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index cddf978b98df..35948df6d6e3 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -32,6 +32,7 @@ enum { ETHTOOL_MSG_LINKINFO_GET_REPLY, ETHTOOL_MSG_LINKINFO_NTF, ETHTOOL_MSG_LINKMODES_GET_REPLY, + ETHTOOL_MSG_LINKMODES_NTF, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 11a467294a33..36e2ef2d900d 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -573,8 +573,10 @@ static int ethtool_set_link_ksettings(struct net_device *dev, return -EINVAL; err = dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); - if (err >= 0) + if (err >= 0) { ethtool_notify(dev, ETHTOOL_MSG_LINKINFO_NTF, NULL); + ethtool_notify(dev, ETHTOOL_MSG_LINKMODES_NTF, NULL); + } return err; } @@ -638,8 +640,10 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) link_ksettings.base.link_mode_masks_nwords = __ETHTOOL_LINK_MODE_MASK_NU32; ret = dev->ethtool_ops->set_link_ksettings(dev, &link_ksettings); - if (ret >= 0) + if (ret >= 0) { ethtool_notify(dev, ETHTOOL_MSG_LINKINFO_NTF, NULL); + ethtool_notify(dev, ETHTOOL_MSG_LINKMODES_NTF, NULL); + } return ret; } diff --git a/net/ethtool/linkmodes.c b/net/ethtool/linkmodes.c index 790b60771d0e..0b99f494ad3b 100644 --- a/net/ethtool/linkmodes.c +++ b/net/ethtool/linkmodes.c @@ -364,6 +364,8 @@ int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info) ret = dev->ethtool_ops->set_link_ksettings(dev, &ksettings); if (ret < 0) GENL_SET_ERR_MSG(info, "link settings update failed"); + else + ethtool_notify(dev, ETHTOOL_MSG_LINKMODES_NTF, NULL); } out_ops: diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 5f28f3cb022d..1b5e1bd26504 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -511,6 +511,7 @@ static int ethnl_default_done(struct netlink_callback *cb) static const struct ethnl_request_ops * ethnl_default_notify_ops[ETHTOOL_MSG_KERNEL_MAX + 1] = { [ETHTOOL_MSG_LINKINFO_NTF] = ðnl_linkinfo_request_ops, + [ETHTOOL_MSG_LINKMODES_NTF] = ðnl_linkmodes_request_ops, }; /* default notification handler */ @@ -592,6 +593,7 @@ typedef void (*ethnl_notify_handler_t)(struct net_device *dev, unsigned int cmd, static const ethnl_notify_handler_t ethnl_notify_handlers[] = { [ETHTOOL_MSG_LINKINFO_NTF] = ethnl_default_notify, + [ETHTOOL_MSG_LINKMODES_NTF] = ethnl_default_notify, }; void ethtool_notify(struct net_device *dev, unsigned int cmd, const void *data) -- cgit v1.2.3 From 3d2b847fb99cf2b28aa046e486636e555bc6ed1c Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Fri, 27 Dec 2019 15:56:23 +0100 Subject: ethtool: provide link state with LINKSTATE_GET request Implement LINKSTATE_GET netlink request to get link state information. At the moment, only link up flag as provided by ETHTOOL_GLINK ioctl command is returned. LINKSTATE_GET request can be used with NLM_F_DUMP (without device identification) to request the information for all devices in current network namespace providing the data. Signed-off-by: Michal Kubecek Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 33 ++++++++++++- include/uapi/linux/ethtool_netlink.h | 14 ++++++ net/ethtool/Makefile | 3 +- net/ethtool/common.c | 8 +++ net/ethtool/common.h | 3 ++ net/ethtool/ioctl.c | 8 +-- net/ethtool/linkstate.c | 74 ++++++++++++++++++++++++++++ net/ethtool/netlink.c | 8 +++ net/ethtool/netlink.h | 1 + 9 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 net/ethtool/linkstate.c (limited to 'Documentation') diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 9d96d51e9360..c60afba69e3c 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -184,6 +184,7 @@ Userspace to kernel: ``ETHTOOL_MSG_LINKINFO_SET`` set link settings ``ETHTOOL_MSG_LINKMODES_GET`` get link modes info ``ETHTOOL_MSG_LINKMODES_SET`` set link modes info + ``ETHTOOL_MSG_LINKSTATE_GET`` get link state ===================================== ================================ Kernel to userspace: @@ -194,6 +195,7 @@ Kernel to userspace: ``ETHTOOL_MSG_LINKINFO_NTF`` link settings notification ``ETHTOOL_MSG_LINKMODES_GET_REPLY`` link modes info ``ETHTOOL_MSG_LINKMODES_NTF`` link modes notification + ``ETHTOOL_MSG_LINKSTATE_GET_REPLY`` link state info ===================================== ================================ ``GET`` requests are sent by userspace applications to retrieve device @@ -392,6 +394,35 @@ is supposed to allow requesting changes without knowing what exactly kernel supports. +LINKSTATE_GET +============= + +Requests link state information. At the moment, only link up/down flag (as +provided by ``ETHTOOL_GLINK`` ioctl command) is provided but some future +extensions are planned (e.g. link down reason). This request does not have any +attributes. + +Request contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKSTATE_HEADER`` nested request header + ==================================== ====== ========================== + +Kernel response contents: + + ==================================== ====== ========================== + ``ETHTOOL_A_LINKSTATE_HEADER`` nested reply header + ``ETHTOOL_A_LINKSTATE_LINK`` bool link state (up/down) + ==================================== ====== ========================== + +For most NIC drivers, the value of ``ETHTOOL_A_LINKSTATE_LINK`` returns +carrier flag provided by ``netif_carrier_ok()`` but there are drivers which +define their own handler. + +``LINKSTATE_GET`` allows dump requests (kernel returns reply messages for all +devices supporting the request). + + Request translation =================== @@ -413,7 +444,7 @@ have their netlink replacement yet. ``ETHTOOL_GMSGLVL`` n/a ``ETHTOOL_SMSGLVL`` n/a ``ETHTOOL_NWAY_RST`` n/a - ``ETHTOOL_GLINK`` n/a + ``ETHTOOL_GLINK`` ``ETHTOOL_MSG_LINKSTATE_GET`` ``ETHTOOL_GEEPROM`` n/a ``ETHTOOL_SEEPROM`` n/a ``ETHTOOL_GCOALESCE`` n/a diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h index 35948df6d6e3..02f82f42a889 100644 --- a/include/uapi/linux/ethtool_netlink.h +++ b/include/uapi/linux/ethtool_netlink.h @@ -19,6 +19,7 @@ enum { ETHTOOL_MSG_LINKINFO_SET, ETHTOOL_MSG_LINKMODES_GET, ETHTOOL_MSG_LINKMODES_SET, + ETHTOOL_MSG_LINKSTATE_GET, /* add new constants above here */ __ETHTOOL_MSG_USER_CNT, @@ -33,6 +34,7 @@ enum { ETHTOOL_MSG_LINKINFO_NTF, ETHTOOL_MSG_LINKMODES_GET_REPLY, ETHTOOL_MSG_LINKMODES_NTF, + ETHTOOL_MSG_LINKSTATE_GET_REPLY, /* add new constants above here */ __ETHTOOL_MSG_KERNEL_CNT, @@ -181,6 +183,18 @@ enum { ETHTOOL_A_LINKMODES_MAX = __ETHTOOL_A_LINKMODES_CNT - 1 }; +/* LINKSTATE */ + +enum { + ETHTOOL_A_LINKSTATE_UNSPEC, + ETHTOOL_A_LINKSTATE_HEADER, /* nest - _A_HEADER_* */ + ETHTOOL_A_LINKSTATE_LINK, /* u8 */ + + /* add new constants above here */ + __ETHTOOL_A_LINKSTATE_CNT, + ETHTOOL_A_LINKSTATE_MAX = __ETHTOOL_A_LINKSTATE_CNT - 1 +}; + /* generic netlink info */ #define ETHTOOL_GENL_NAME "ethtool" #define ETHTOOL_GENL_VERSION 1 diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile index 8023da6672ce..9a1332fb0cc6 100644 --- a/net/ethtool/Makefile +++ b/net/ethtool/Makefile @@ -4,4 +4,5 @@ obj-y += ioctl.o common.o obj-$(CONFIG_ETHTOOL_NETLINK) += ethtool_nl.o -ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o +ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o \ + linkstate.o diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 1d4a0aeff2cb..e621b1694d2f 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -217,3 +217,11 @@ convert_legacy_settings_to_link_ksettings( = legacy_settings->eth_tp_mdix_ctrl; return retval; } + +int __ethtool_get_link(struct net_device *dev) +{ + if (!dev->ethtool_ops->get_link) + return -EOPNOTSUPP; + + return netif_running(dev) && dev->ethtool_ops->get_link(dev); +} diff --git a/net/ethtool/common.h b/net/ethtool/common.h index c8a237402729..5c5f7dc90cd4 100644 --- a/net/ethtool/common.h +++ b/net/ethtool/common.h @@ -3,6 +3,7 @@ #ifndef _ETHTOOL_COMMON_H #define _ETHTOOL_COMMON_H +#include #include /* compose link mode index from speed, type and duplex */ @@ -19,6 +20,8 @@ extern const char phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN]; extern const char link_mode_names[][ETH_GSTRING_LEN]; +int __ethtool_get_link(struct net_device *dev); + bool convert_legacy_settings_to_link_ksettings( struct ethtool_link_ksettings *link_ksettings, const struct ethtool_cmd *legacy_settings); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 36e2ef2d900d..182bffbffa78 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1365,12 +1365,12 @@ static int ethtool_nway_reset(struct net_device *dev) static int ethtool_get_link(struct net_device *dev, char __user *useraddr) { struct ethtool_value edata = { .cmd = ETHTOOL_GLINK }; + int link = __ethtool_get_link(dev); - if (!dev->ethtool_ops->get_link) - return -EOPNOTSUPP; - - edata.data = netif_running(dev) && dev->ethtool_ops->get_link(dev); + if (link < 0) + return link; + edata.data = link; if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c new file mode 100644 index 000000000000..2740cde0a182 --- /dev/null +++ b/net/ethtool/linkstate.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include "netlink.h" +#include "common.h" + +struct linkstate_req_info { + struct ethnl_req_info base; +}; + +struct linkstate_reply_data { + struct ethnl_reply_data base; + int link; +}; + +#define LINKSTATE_REPDATA(__reply_base) \ + container_of(__reply_base, struct linkstate_reply_data, base) + +static const struct nla_policy +linkstate_get_policy[ETHTOOL_A_LINKSTATE_MAX + 1] = { + [ETHTOOL_A_LINKSTATE_UNSPEC] = { .type = NLA_REJECT }, + [ETHTOOL_A_LINKSTATE_HEADER] = { .type = NLA_NESTED }, + [ETHTOOL_A_LINKSTATE_LINK] = { .type = NLA_REJECT }, +}; + +static int linkstate_prepare_data(const struct ethnl_req_info *req_base, + struct ethnl_reply_data *reply_base, + struct genl_info *info) +{ + struct linkstate_reply_data *data = LINKSTATE_REPDATA(reply_base); + struct net_device *dev = reply_base->dev; + int ret; + + ret = ethnl_ops_begin(dev); + if (ret < 0) + return ret; + data->link = __ethtool_get_link(dev); + ethnl_ops_complete(dev); + + return 0; +} + +static int linkstate_reply_size(const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + return nla_total_size(sizeof(u8)) /* LINKSTATE_LINK */ + + 0; +} + +static int linkstate_fill_reply(struct sk_buff *skb, + const struct ethnl_req_info *req_base, + const struct ethnl_reply_data *reply_base) +{ + struct linkstate_reply_data *data = LINKSTATE_REPDATA(reply_base); + + if (data->link >= 0 && + nla_put_u8(skb, ETHTOOL_A_LINKSTATE_LINK, !!data->link)) + return -EMSGSIZE; + + return 0; +} + +const struct ethnl_request_ops ethnl_linkstate_request_ops = { + .request_cmd = ETHTOOL_MSG_LINKSTATE_GET, + .reply_cmd = ETHTOOL_MSG_LINKSTATE_GET_REPLY, + .hdr_attr = ETHTOOL_A_LINKSTATE_HEADER, + .max_attr = ETHTOOL_A_LINKSTATE_MAX, + .req_info_size = sizeof(struct linkstate_req_info), + .reply_data_size = sizeof(struct linkstate_reply_data), + .request_policy = linkstate_get_policy, + + .prepare_data = linkstate_prepare_data, + .reply_size = linkstate_reply_size, + .fill_reply = linkstate_fill_reply, +}; diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 1b5e1bd26504..4ca96c7b86b3 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -210,6 +210,7 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = { [ETHTOOL_MSG_STRSET_GET] = ðnl_strset_request_ops, [ETHTOOL_MSG_LINKINFO_GET] = ðnl_linkinfo_request_ops, [ETHTOOL_MSG_LINKMODES_GET] = ðnl_linkmodes_request_ops, + [ETHTOOL_MSG_LINKSTATE_GET] = ðnl_linkstate_request_ops, }; static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) @@ -645,6 +646,13 @@ static const struct genl_ops ethtool_genl_ops[] = { .flags = GENL_UNS_ADMIN_PERM, .doit = ethnl_set_linkmodes, }, + { + .cmd = ETHTOOL_MSG_LINKSTATE_GET, + .doit = ethnl_default_doit, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, + }, }; static const struct genl_multicast_group ethtool_nl_mcgrps[] = { diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 1269cca8a002..da9d6521a4eb 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -333,6 +333,7 @@ struct ethnl_request_ops { extern const struct ethnl_request_ops ethnl_strset_request_ops; extern const struct ethnl_request_ops ethnl_linkinfo_request_ops; extern const struct ethnl_request_ops ethnl_linkmodes_request_ops; +extern const struct ethnl_request_ops ethnl_linkstate_request_ops; int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info); int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info); -- cgit v1.2.3 From 5264c5f4c4690658922fcaddc1cdd925fb0069fd Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Fri, 20 Dec 2019 16:00:49 +0000 Subject: dt-bindings: iio: accel: bma400: add bindings Add devicetree binding for the Bosch BMA400 3-axes ultra-low power accelerometer sensor. Signed-off-by: Dan Robertson Reviewed-by: Linus Walleij Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/accel/bosch,bma400.yaml | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml b/Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml new file mode 100644 index 000000000000..c1c6d6f223cf --- /dev/null +++ b/Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/accel/bosch,bma400.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Bosch BMA400 triaxial acceleration sensor + +maintainers: + - Dan Robertson + +description: | + Acceleration and temperature iio sensors with an i2c interface + + Specifications about the sensor can be found at: + https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMA400-DS000.pdf + +properties: + compatible: + enum: + - bosch,bma400 + + reg: + maxItems: 1 + + vdd-supply: + description: phandle to the regulator that provides power to the accelerometer + + vddio-supply: + description: phandle to the regulator that provides power to the sensor's IO + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + #include + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + accelerometer@14 { + compatible = "bosch,bma400"; + reg = <0x14>; + vdd-supply = <&vdd>; + vddio-supply = <&vddio>; + interrupt-parent = <&gpio0>; + interrupts = <0 IRQ_TYPE_LEVEL_HIGH>; + }; + }; -- cgit v1.2.3 From 2d983e084b415748d4eb7c6a571635dd609387e1 Mon Sep 17 00:00:00 2001 From: Tomislav Denis Date: Wed, 11 Dec 2019 10:59:45 +0100 Subject: dt-bindings: Add asc vendor All Sensors Corporation is a manufacturer of MEMS piezoresitive ultra low pressure sensors and pressure transducers. Signed-off-by: Tomislav Denis Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index d3f9690e1e4b..de886aa45823 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -109,6 +109,8 @@ patternProperties: description: Artesyn Embedded Technologies Inc. "^asahi-kasei,.*": description: Asahi Kasei Corp. + "^asc,.*": + description: All Sensors Corporation "^aspeed,.*": description: ASPEED Technology Inc. "^asus,.*": -- cgit v1.2.3 From 2a4fb4def9577cde9d541693a0304e9aab86904b Mon Sep 17 00:00:00 2001 From: Tomislav Denis Date: Wed, 11 Dec 2019 10:59:46 +0100 Subject: bindings: iio: pressure: Add documentation for dlh driver Add a device tree binding documentation for DLH series pressure sensors. Signed-off-by: Tomislav Denis Signed-off-by: Jonathan Cameron --- .../bindings/iio/pressure/asc,dlhl60d.yaml | 51 ++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml b/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml new file mode 100644 index 000000000000..9f5ca9c42025 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/pressure/asc,dlhl60d.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: All Sensors DLH series low voltage digital pressure sensors + +maintainers: + - Tomislav Denis + +description: | + Bindings for the All Sensors DLH series pressure sensors. + + Specifications about the sensors can be found at: + http://www.allsensors.com/cad/DS-0355_Rev_B.PDF + +properties: + compatible: + enum: + - asc,dlhl60d + - asc,dlhl60g + + reg: + description: I2C device address + maxItems: 1 + + interrupts: + description: interrupt mapping for EOC(data ready) pin + maxItems: 1 + +required: + - compatible + - reg + +examples: + - | + #include + + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + pressure@29 { + compatible = "asc,dlhl60d"; + reg = <0x29>; + interrupt-parent = <&gpio0>; + interrupts = <10 IRQ_TYPE_EDGE_RISING>; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 0a479418cf5c..ec05a06d7ddb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -674,6 +674,7 @@ W: http://www.allsensors.com/ S: Maintained L: linux-iio@vger.kernel.org F: drivers/iio/pressure/dlhl60d.c +F: Documentation/devicetree/bindings/iio/pressure/asc,dlhl60d.yaml ALLEGRO DVT VIDEO IP CORE DRIVER M: Michael Tretter -- cgit v1.2.3 From 4538c185680996d7328beac629dbdb7dd3f8f34e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 11 Dec 2019 13:56:15 +0200 Subject: iio: buffer-dmaengine: Report buffer length requirements The dmaengine buffer has some length alignment requirements that can differ from platform to platform. If the length alignment requirements are not met unexpected behavior like dropping of samples can occur. Currently these requirements are not reported and applications need to know the requirements of the platform by some out-of-band means. Add a new buffer attribute that reports the length alignment requirements called `length_align_bytes`. The reported length alignment is in bytes that means the buffer length alignment in sample sets depends on the number of enabled channels and the bytes per channel. Applications using this attribute to determine the buffer size requirements need to consider this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Alexandru Ardelean Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio-dma-buffer | 19 +++++++++++++++++++ drivers/iio/buffer/industrialio-buffer-dmaengine.c | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-dma-buffer (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-iio-dma-buffer b/Documentation/ABI/testing/sysfs-bus-iio-dma-buffer new file mode 100644 index 000000000000..d526e6571001 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-dma-buffer @@ -0,0 +1,19 @@ +What: /sys/bus/iio/devices/iio:deviceX/buffer/length_align_bytes +KernelVersion: 5.4 +Contact: linux-iio@vger.kernel.org +Description: + DMA buffers tend to have a alignment requirement for the + buffers. If this alignment requirement is not met samples might + be dropped from the buffer. + + This property reports the alignment requirements in bytes. + This means that the buffer size in bytes needs to be a integer + multiple of the number reported by this file. + + The alignment requirements in number of sample sets will depend + on the enabled channels and the bytes per channel. This means + that the alignment requirement in samples sets might change + depending on which and how many channels are enabled. Whereas + the alignment requirement reported in bytes by this property + will remain static and does not depend on which channels are + enabled. diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index e0b92f3dec0e..744abd7e1269 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -126,6 +127,24 @@ static const struct iio_dma_buffer_ops iio_dmaengine_default_ops = { .abort = iio_dmaengine_buffer_abort, }; +static ssize_t iio_dmaengine_buffer_get_length_align(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct dmaengine_buffer *dmaengine_buffer = + iio_buffer_to_dmaengine_buffer(indio_dev->buffer); + + return sprintf(buf, "%u\n", dmaengine_buffer->align); +} + +static IIO_DEVICE_ATTR(length_align_bytes, 0444, + iio_dmaengine_buffer_get_length_align, NULL, 0); + +static const struct attribute *iio_dmaengine_buffer_attrs[] = { + &iio_dev_attr_length_align_bytes.dev_attr.attr, + NULL, +}; + /** * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine * @dev: Parent device for the buffer @@ -179,6 +198,8 @@ struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, iio_dma_buffer_init(&dmaengine_buffer->queue, chan->device->dev, &iio_dmaengine_default_ops); + iio_buffer_set_attrs(&dmaengine_buffer->queue.buffer, + iio_dmaengine_buffer_attrs); dmaengine_buffer->queue.buffer.access = &iio_dmaengine_buffer_ops; -- cgit v1.2.3 From 57b8879c0c1af5ac4cfc9dd1260d40b13dd6027d Mon Sep 17 00:00:00 2001 From: Olivier Moysan Date: Fri, 6 Dec 2019 11:00:58 +0100 Subject: dt-bindings: iio: adc: convert sd modulator to json-schema Convert the sigma delta modulator bindings to DT schema format using json-schema. Signed-off-by: Olivier Moysan Reviewed-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/sigma-delta-modulator.txt | 13 -------- .../bindings/iio/adc/sigma-delta-modulator.yaml | 37 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 13 deletions(-) delete mode 100644 Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt create mode 100644 Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt deleted file mode 100644 index 59b92cd32552..000000000000 --- a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt +++ /dev/null @@ -1,13 +0,0 @@ -Device-Tree bindings for sigma delta modulator - -Required properties: -- compatible: should be "ads1201", "sd-modulator". "sd-modulator" can be use - as a generic SD modulator if modulator not specified in compatible list. -- #io-channel-cells = <0>: See the IIO bindings section "IIO consumers". - -Example node: - - ads1202: adc { - compatible = "sd-modulator"; - #io-channel-cells = <0>; - }; diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml new file mode 100644 index 000000000000..a390343d0c2a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/sigma-delta-modulator.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Device-Tree bindings for sigma delta modulator + +maintainers: + - Arnaud Pouliquen + +properties: + compatible: + description: | + "sd-modulator" can be used as a generic SD modulator, + if the modulator is not specified in the compatible list. + enum: + - sd-modulator + - ads1201 + + '#io-channel-cells': + const: 0 + +required: + - compatible + - '#io-channel-cells' + +additionalProperties: false + +examples: + - | + ads1202: adc { + compatible = "sd-modulator"; + #io-channel-cells = <0>; + }; + +... -- cgit v1.2.3 From c49a5d0968690a08378fd14371678c3479f269aa Mon Sep 17 00:00:00 2001 From: Leonard Crestez Date: Fri, 22 Nov 2019 23:45:02 +0200 Subject: dt-bindings: memory: Add bindings for imx8m ddr controller Add devicetree bindings for the i.MX DDR Controller on imx8m series chips. It supports dynamic frequency switching between multiple data rates and this is exposed to Linux via the devfreq subsystem. Signed-off-by: Leonard Crestez Acked-by: Chanwoo Choi Reviewed-by: Rob Herring Signed-off-by: Chanwoo Choi --- .../memory-controllers/fsl/imx8m-ddrc.yaml | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Documentation/devicetree/bindings/memory-controllers/fsl/imx8m-ddrc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/imx8m-ddrc.yaml b/Documentation/devicetree/bindings/memory-controllers/fsl/imx8m-ddrc.yaml new file mode 100644 index 000000000000..c9e6c22cb5be --- /dev/null +++ b/Documentation/devicetree/bindings/memory-controllers/fsl/imx8m-ddrc.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/memory-controllers/fsl/imx8m-ddrc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: i.MX8M DDR Controller + +maintainers: + - Leonard Crestez + +description: + The DDRC block is integrated in i.MX8M for interfacing with DDR based + memories. + + It supports switching between different frequencies at runtime but during + this process RAM itself becomes briefly inaccessible so actual frequency + switching is implemented by TF-A code which runs from a SRAM area. + + The Linux driver for the DDRC doesn't even map registers (they're included + for the sake of "describing hardware"), it mostly just exposes firmware + capabilities through standard Linux mechanism like devfreq and OPP tables. + +properties: + compatible: + items: + - enum: + - fsl,imx8mn-ddrc + - fsl,imx8mm-ddrc + - fsl,imx8mq-ddrc + - const: fsl,imx8m-ddrc + + reg: + maxItems: 1 + description: + Base address and size of DDRC CTL area. + This is not currently mapped by the imx8m-ddrc driver. + + clocks: + maxItems: 4 + + clock-names: + items: + - const: core + - const: pll + - const: alt + - const: apb + + operating-points-v2: true + opp-table: true + +required: + - reg + - compatible + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + ddrc: memory-controller@3d400000 { + compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc"; + reg = <0x3d400000 0x400000>; + clock-names = "core", "pll", "alt", "apb"; + clocks = <&clk IMX8MM_CLK_DRAM_CORE>, + <&clk IMX8MM_DRAM_PLL>, + <&clk IMX8MM_CLK_DRAM_ALT>, + <&clk IMX8MM_CLK_DRAM_APB>; + operating-points-v2 = <&ddrc_opp_table>; + }; -- cgit v1.2.3 From 2fee1a7cc6b1ce6634bb0f025be2c94a58dfa34d Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Tue, 5 Nov 2019 18:18:03 +0900 Subject: PM / devfreq: Add new name attribute for sysfs The commit 4585fbcb5331 ("PM / devfreq: Modify the device name as devfreq(X) for sysfs") changed the node name to devfreq(x). After this commit, it is not possible to get the device name through /sys/class/devfreq/devfreq(X)/*. Add new name attribute in order to get device name. Cc: stable@vger.kernel.org Fixes: 4585fbcb5331 ("PM / devfreq: Modify the device name as devfreq(X) for sysfs") Signed-off-by: Chanwoo Choi --- Documentation/ABI/testing/sysfs-class-devfreq | 7 +++++++ drivers/devfreq/devfreq.c | 9 +++++++++ 2 files changed, 16 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq index 01196e19afca..75897e2fde43 100644 --- a/Documentation/ABI/testing/sysfs-class-devfreq +++ b/Documentation/ABI/testing/sysfs-class-devfreq @@ -7,6 +7,13 @@ Description: The name of devfreq object denoted as ... is same as the name of device using devfreq. +What: /sys/class/devfreq/.../name +Date: November 2019 +Contact: Chanwoo Choi +Description: + The /sys/class/devfreq/.../name shows the name of device + of the corresponding devfreq object. + What: /sys/class/devfreq/.../governor Date: September 2011 Contact: MyungJoo Ham diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 57f6944d65a6..07602083c743 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -1259,6 +1259,14 @@ err_out: } EXPORT_SYMBOL(devfreq_remove_governor); +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct devfreq *devfreq = to_devfreq(dev); + return sprintf(buf, "%s\n", dev_name(devfreq->dev.parent)); +} +static DEVICE_ATTR_RO(name); + static ssize_t governor_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1592,6 +1600,7 @@ static ssize_t trans_stat_show(struct device *dev, static DEVICE_ATTR_RO(trans_stat); static struct attribute *devfreq_attrs[] = { + &dev_attr_name.attr, &dev_attr_governor.attr, &dev_attr_available_governors.attr, &dev_attr_cur_freq.attr, -- cgit v1.2.3 From 14a34396819960865ff737c665c6e46b64d0e04a Mon Sep 17 00:00:00 2001 From: Kamil Konieczny Date: Thu, 5 Dec 2019 15:55:26 +0100 Subject: PM / devfreq: Add clearing transitions stats Add clearing transition table and time in states devfreq statistics by writing 0 (zero) to trans_stat file in devfreq sysfs. An example use is like following: echo 0 > /sys/class/devfreq/devfreqX/trans_stat Signed-off-by: Kamil Konieczny [cw00.choi: Edit return value if entering the wrong value for reset and use arrary3_size() to get the size of 3-dimensional array] Signed-off-by: Chanwoo Choi --- Documentation/ABI/testing/sysfs-class-devfreq | 11 ++++++---- drivers/devfreq/devfreq.c | 29 ++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq index 75897e2fde43..9758eb85ade3 100644 --- a/Documentation/ABI/testing/sysfs-class-devfreq +++ b/Documentation/ABI/testing/sysfs-class-devfreq @@ -55,12 +55,15 @@ What: /sys/class/devfreq/.../trans_stat Date: October 2012 Contact: MyungJoo Ham Description: - This ABI shows the statistics of devfreq behavior on a - specific device. It shows the time spent in each state and - the number of transitions between states. + This ABI shows or clears the statistics of devfreq behavior + on a specific device. It shows the time spent in each state + and the number of transitions between states. In order to activate this ABI, the devfreq target device driver should provide the list of available frequencies - with its profile. + with its profile. If need to reset the statistics of devfreq + behavior on a specific device, enter 0(zero) to 'trans_stat' + as following: + echo 0 > /sys/class/devfreq/.../trans_stat What: /sys/class/devfreq/.../userspace/set_freq Date: September 2011 diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 554d155106a5..af5bd521a734 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -1597,7 +1597,34 @@ static ssize_t trans_stat_show(struct device *dev, devfreq->total_trans); return len; } -static DEVICE_ATTR_RO(trans_stat); + +static ssize_t trans_stat_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct devfreq *df = to_devfreq(dev); + int err, value; + + if (df->profile->max_state == 0) + return count; + + err = kstrtoint(buf, 10, &value); + if (err || value != 0) + return -EINVAL; + + mutex_lock(&df->lock); + memset(df->time_in_state, 0, (df->profile->max_state * + sizeof(*df->time_in_state))); + memset(df->trans_table, 0, array3_size(sizeof(unsigned int), + df->profile->max_state, + df->profile->max_state)); + df->total_trans = 0; + df->last_stat_updated = get_jiffies_64(); + mutex_unlock(&df->lock); + + return count; +} +static DEVICE_ATTR_RW(trans_stat); static struct attribute *devfreq_attrs[] = { &dev_attr_name.attr, -- cgit v1.2.3 From 7730c3be06e255082077594f60aae77f9914c5ad Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Mon, 30 Dec 2019 21:14:28 +0800 Subject: Documentation: PCI: Fix pci_alloc_irq_vectors() function name typo Documentation/PCI/msi-howto.rst referred to pci_irq_alloc_vectors() when it should refer to pci_alloc_irq_vectors(). Fix the typo. Link: https://lore.kernel.org/r/20191230131428.1200-1-yuzenghui@huawei.com Signed-off-by: Zenghui Yu Signed-off-by: Bjorn Helgaas Reviewed-by: Andrew Murray --- Documentation/PCI/msi-howto.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/PCI/msi-howto.rst b/Documentation/PCI/msi-howto.rst index 994cbb660ade..aa2046af69f7 100644 --- a/Documentation/PCI/msi-howto.rst +++ b/Documentation/PCI/msi-howto.rst @@ -283,5 +283,5 @@ or disabled (0). If 0 is found in any of the msi_bus files belonging to bridges between the PCI root and the device, MSIs are disabled. It is also worth checking the device driver to see whether it supports MSIs. -For example, it may contain calls to pci_irq_alloc_vectors() with the +For example, it may contain calls to pci_alloc_irq_vectors() with the PCI_IRQ_MSI or PCI_IRQ_MSIX flags. -- cgit v1.2.3 From c1d1c4a62db5c4745b9e15cfee0daf0f774f73fc Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 11 Dec 2019 22:38:19 +0100 Subject: iio: accel: bma180: BMA254 support This adds support for the BMA254 variant of this accelerometer. The only difference for the simple IIO driver is that values are 12 bit and the temperature offset differs by 1 degree. Whilst wildcards in naming are normally frowned upon: The cases where I have labeled variables "25x" is where the models are identical, so as to make things easier for people that want to add support for BMA253 and BMA255. Cc: Peter Meerwald Cc: Oleksandr Kravchenko Cc: devicetree@vger.kernel.org Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/bma180.txt | 7 +- drivers/iio/accel/Kconfig | 4 +- drivers/iio/accel/bma180.c | 108 ++++++++++++++++++--- 3 files changed, 100 insertions(+), 19 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/iio/accel/bma180.txt b/Documentation/devicetree/bindings/iio/accel/bma180.txt index 3b25b4c4d446..f53237270b32 100644 --- a/Documentation/devicetree/bindings/iio/accel/bma180.txt +++ b/Documentation/devicetree/bindings/iio/accel/bma180.txt @@ -1,11 +1,14 @@ -* Bosch BMA180 / BMA250 triaxial acceleration sensor +* Bosch BMA180 / BMA25x triaxial acceleration sensor http://omapworld.com/BMA180_111_1002839.pdf http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf Required properties: - - compatible : should be "bosch,bma180" or "bosch,bma250" + - compatible : should be one of: + "bosch,bma180" + "bosch,bma250" + "bosch,bma254" - reg : the I2C address of the sensor Optional properties: diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index 670e60568033..5d91a6dda894 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -89,13 +89,13 @@ config ADXL372_I2C module will be called adxl372_i2c. config BMA180 - tristate "Bosch BMA180/BMA250 3-Axis Accelerometer Driver" + tristate "Bosch BMA180/BMA25x 3-Axis Accelerometer Driver" depends on I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER help Say Y here if you want to build a driver for the Bosch BMA180 or - BMA250 triaxial acceleration sensor. + BMA25x triaxial acceleration sensor. To compile this driver as a module, choose M here: the module will be called bma180. diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 45dd096c0220..fcd91d5f05fd 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -9,6 +9,7 @@ * SPI is not supported by driver * BMA180: 7-bit I2C slave address 0x40 or 0x41 * BMA250: 7-bit I2C slave address 0x18 or 0x19 + * BMA254: 7-bit I2C slave address 0x18 or 0x19 */ #include @@ -34,17 +35,20 @@ enum chip_ids { BMA180, BMA250, + BMA254, }; struct bma180_data; struct bma180_part_info { + u8 chip_id; const struct iio_chan_spec *channels; unsigned int num_channels; const int *scale_table; unsigned int num_scales; const int *bw_table; unsigned int num_bw; + int center_temp; u8 int_reset_reg, int_reset_mask; u8 sleep_reg, sleep_mask; @@ -52,6 +56,7 @@ struct bma180_part_info { u8 scale_reg, scale_mask; u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; + u8 int_map_reg, int_enable_dataready_int1_mask; u8 softreset_reg; int (*chip_config)(struct bma180_data *data); @@ -90,6 +95,8 @@ struct bma180_part_info { #define BMA180_RESET_VAL 0xb6 #define BMA180_ID_REG_VAL 0x03 +#define BMA250_ID_REG_VAL 0x03 +#define BMA254_ID_REG_VAL 0xfa /* 250 decimal */ /* Chip power modes */ #define BMA180_LOW_POWER 0x03 @@ -110,6 +117,23 @@ struct bma180_part_info { #define BMA250_INT1_DATA_MASK BIT(0) #define BMA250_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ +#define BMA254_RANGE_REG 0x0f +#define BMA254_BW_REG 0x10 +#define BMA254_POWER_REG 0x11 +#define BMA254_RESET_REG 0x14 +#define BMA254_INT_ENABLE_REG 0x17 +#define BMA254_INT_MAP_REG 0x1a +#define BMA254_INT_RESET_REG 0x21 + +#define BMA254_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ +#define BMA254_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ +#define BMA254_SUSPEND_MASK BIT(7) /* chip will sleep */ +#define BMA254_LOWPOWER_MASK BIT(6) +#define BMA254_DATA_INTEN_MASK BIT(4) +#define BMA254_INT2_DATA_MASK BIT(7) +#define BMA254_INT1_DATA_MASK BIT(0) +#define BMA254_INT_RESET_MASK BIT(7) /* Reset pending interrupts */ + struct bma180_data { struct regulator *vdd_supply; struct regulator *vddio_supply; @@ -135,8 +159,8 @@ enum bma180_chan { static int bma180_bw_table[] = { 10, 20, 40, 75, 150, 300 }; /* Hz */ static int bma180_scale_table[] = { 1275, 1863, 2452, 3727, 4903, 9709, 19417 }; -static int bma250_bw_table[] = { 8, 16, 31, 63, 125, 250 }; /* Hz */ -static int bma250_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, +static int bma25x_bw_table[] = { 8, 16, 31, 63, 125, 250 }; /* Hz */ +static int bma25x_scale_table[] = { 0, 0, 0, 38344, 0, 76590, 0, 0, 153180, 0, 0, 0, 306458 }; static int bma180_get_data_reg(struct bma180_data *data, enum bma180_chan chan) @@ -310,8 +334,11 @@ static int bma180_chip_init(struct bma180_data *data) if (ret < 0) return ret; - if (ret != BMA180_ID_REG_VAL) + if (ret != data->part_info->chip_id) { + dev_err(&data->client->dev, "wrong chip ID %d expected %d\n", + ret, data->part_info->chip_id); return -ENODEV; + } ret = bma180_soft_reset(data); if (ret) @@ -358,7 +385,7 @@ err: return ret; } -static int bma250_chip_config(struct bma180_data *data) +static int bma25x_chip_config(struct bma180_data *data) { int ret = bma180_chip_init(data); @@ -370,8 +397,12 @@ static int bma250_chip_config(struct bma180_data *data) ret = bma180_set_scale(data, 38344); /* 2 G */ if (ret) goto err; - ret = bma180_set_bits(data, BMA250_INT_MAP_REG, - BMA250_INT1_DATA_MASK, 1); + /* + * This enables dataready interrupt on the INT1 pin + * FIXME: support using the INT2 pin + */ + ret = bma180_set_bits(data, data->part_info->int_map_reg, + data->part_info->int_enable_dataready_int1_mask, 1); if (ret) goto err; @@ -397,7 +428,7 @@ err: dev_err(&data->client->dev, "failed to disable the chip\n"); } -static void bma250_chip_disable(struct bma180_data *data) +static void bma25x_chip_disable(struct bma180_data *data) { if (bma180_set_new_data_intr_state(data, false)) goto err; @@ -500,7 +531,7 @@ static int bma180_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_OFFSET: - *val = 48; /* 0 LSB @ 24 degree C */ + *val = data->part_info->center_temp; return IIO_VAL_INT; default: return -EINVAL; @@ -630,14 +661,24 @@ static const struct iio_chan_spec bma250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(4), }; +static const struct iio_chan_spec bma254_channels[] = { + BMA180_ACC_CHANNEL(X, 12), + BMA180_ACC_CHANNEL(Y, 12), + BMA180_ACC_CHANNEL(Z, 12), + BMA180_TEMP_CHANNEL, + IIO_CHAN_SOFT_TIMESTAMP(4), +}; + static const struct bma180_part_info bma180_part_info[] = { [BMA180] = { + .chip_id = BMA180_ID_REG_VAL, .channels = bma180_channels, .num_channels = ARRAY_SIZE(bma180_channels), .scale_table = bma180_scale_table, .num_scales = ARRAY_SIZE(bma180_scale_table), .bw_table = bma180_bw_table, .num_bw = ARRAY_SIZE(bma180_bw_table), + .center_temp = 48, /* 0 LSB @ 24 degree C */ .int_reset_reg = BMA180_CTRL_REG0, .int_reset_mask = BMA180_RESET_INT, .sleep_reg = BMA180_CTRL_REG0, @@ -656,12 +697,14 @@ static const struct bma180_part_info bma180_part_info[] = { .chip_disable = bma180_chip_disable, }, [BMA250] = { + .chip_id = BMA250_ID_REG_VAL, .channels = bma250_channels, .num_channels = ARRAY_SIZE(bma250_channels), - .scale_table = bma250_scale_table, - .num_scales = ARRAY_SIZE(bma250_scale_table), - .bw_table = bma250_bw_table, - .num_bw = ARRAY_SIZE(bma250_bw_table), + .scale_table = bma25x_scale_table, + .num_scales = ARRAY_SIZE(bma25x_scale_table), + .bw_table = bma25x_bw_table, + .num_bw = ARRAY_SIZE(bma25x_bw_table), + .center_temp = 48, /* 0 LSB @ 24 degree C */ .int_reset_reg = BMA250_INT_RESET_REG, .int_reset_mask = BMA250_INT_RESET_MASK, .sleep_reg = BMA250_POWER_REG, @@ -675,9 +718,39 @@ static const struct bma180_part_info bma180_part_info[] = { .lowpower_val = 1, .int_enable_reg = BMA250_INT_ENABLE_REG, .int_enable_mask = BMA250_DATA_INTEN_MASK, + .int_map_reg = BMA250_INT_MAP_REG, + .int_enable_dataready_int1_mask = BMA250_INT1_DATA_MASK, .softreset_reg = BMA250_RESET_REG, - .chip_config = bma250_chip_config, - .chip_disable = bma250_chip_disable, + .chip_config = bma25x_chip_config, + .chip_disable = bma25x_chip_disable, + }, + [BMA254] = { + .chip_id = BMA254_ID_REG_VAL, + .channels = bma254_channels, + .num_channels = ARRAY_SIZE(bma254_channels), + .scale_table = bma25x_scale_table, + .num_scales = ARRAY_SIZE(bma25x_scale_table), + .bw_table = bma25x_bw_table, + .num_bw = ARRAY_SIZE(bma25x_bw_table), + .center_temp = 46, /* 0 LSB @ 23 degree C */ + .int_reset_reg = BMA254_INT_RESET_REG, + .int_reset_mask = BMA254_INT_RESET_MASK, + .sleep_reg = BMA254_POWER_REG, + .sleep_mask = BMA254_SUSPEND_MASK, + .bw_reg = BMA254_BW_REG, + .bw_mask = BMA254_BW_MASK, + .scale_reg = BMA254_RANGE_REG, + .scale_mask = BMA254_RANGE_MASK, + .power_reg = BMA254_POWER_REG, + .power_mask = BMA254_LOWPOWER_MASK, + .lowpower_val = 1, + .int_enable_reg = BMA254_INT_ENABLE_REG, + .int_enable_mask = BMA254_DATA_INTEN_MASK, + .int_map_reg = BMA254_INT_MAP_REG, + .int_enable_dataready_int1_mask = BMA254_INT1_DATA_MASK, + .softreset_reg = BMA254_RESET_REG, + .chip_config = bma25x_chip_config, + .chip_disable = bma25x_chip_disable, }, }; @@ -919,6 +992,7 @@ static SIMPLE_DEV_PM_OPS(bma180_pm_ops, bma180_suspend, bma180_resume); static const struct i2c_device_id bma180_ids[] = { { "bma180", BMA180 }, { "bma250", BMA250 }, + { "bma254", BMA254 }, { } }; @@ -933,6 +1007,10 @@ static const struct of_device_id bma180_of_match[] = { .compatible = "bosch,bma250", .data = (void *)BMA250 }, + { + .compatible = "bosch,bma254", + .data = (void *)BMA254 + }, { } }; MODULE_DEVICE_TABLE(of, bma180_of_match); @@ -952,5 +1030,5 @@ module_i2c_driver(bma180_driver); MODULE_AUTHOR("Kravchenko Oleksandr "); MODULE_AUTHOR("Texas Instruments, Inc."); -MODULE_DESCRIPTION("Bosch BMA180/BMA250 triaxial acceleration sensor"); +MODULE_DESCRIPTION("Bosch BMA180/BMA25x triaxial acceleration sensor"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 7c737c64b0ff08c7427007c239922df7aef2748e Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Fri, 27 Dec 2019 01:21:38 +0900 Subject: Doc: x86: Fix a typo in mm.rst Fix a spelling typo in mm.rst. Signed-off-by: Masanari Iida Link: https://lore.kernel.org/r/20191226162138.17601-1-standby24x7@gmail.com Signed-off-by: Jonathan Corbet --- Documentation/x86/x86_64/mm.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/x86/x86_64/mm.rst b/Documentation/x86/x86_64/mm.rst index 267fc4808945..e5053404a1ae 100644 --- a/Documentation/x86/x86_64/mm.rst +++ b/Documentation/x86/x86_64/mm.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -================ -Memory Managment -================ +================= +Memory Management +================= Complete virtual memory map with 4-level page tables ==================================================== -- cgit v1.2.3 From 6c23821c19305d9f9e3166492483425845b84f3a Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Thu, 26 Dec 2019 01:55:34 +0900 Subject: docs: w1: Fix a typo in omap-hdq.rst Fix a spelling typo in omap-hdq.rst Signed-off-by: Masanari Iida Link: https://lore.kernel.org/r/20191225165534.9395-1-standby24x7@gmail.com Signed-off-by: Jonathan Corbet --- Documentation/w1/masters/omap-hdq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/w1/masters/omap-hdq.rst b/Documentation/w1/masters/omap-hdq.rst index 345298a59e50..5347b5d9e90a 100644 --- a/Documentation/w1/masters/omap-hdq.rst +++ b/Documentation/w1/masters/omap-hdq.rst @@ -44,7 +44,7 @@ that the ID used should be same for both master and slave driver loading. e.g:: insmod omap_hdq.ko W1_ID=2 - inamod w1_bq27000.ko F_ID=2 + insmod w1_bq27000.ko F_ID=2 The driver also supports 1-wire mode. In this mode, there is no need to pass slave ID as parameter. The driver will auto-detect slaves connected -- cgit v1.2.3 From dec6224bb9d6fde8058b02ac441fbfbf5c224aa0 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Fri, 20 Dec 2019 11:04:43 +0800 Subject: docs/zh_CN: add Chinese version of embargoed hardware issues Embargoed hardware issues is a necessary process guide, but leak of Chinese version, since there is more Chinese hardware vendors in market. We'd better have a Chinese version of this guide. This patch translate the guide, add it into toctree. and also add a link stub for the original doc. Signed-off-by: Alex Shi Cc: Fengguang Wu Cc: lizefan@huawei.com Cc: Jonathan Corbet Cc: Harry Wei Cc: Greg Kroah-Hartman Cc: Sasha Levin Cc: Dave Hansen Cc: Thomas Gleixner Cc: Ben Hutchings Cc: Tom Lendacky Cc: Tony Luck Cc: Kees Cook Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/1576811085-30544-1-git-send-email-alex.shi@linux.alibaba.com Signed-off-by: Jonathan Corbet --- .../process/embargoed-hardware-issues.rst | 2 + .../zh_CN/process/embargoed-hardware-issues.rst | 228 +++++++++++++++++++++ Documentation/translations/zh_CN/process/index.rst | 1 + 3 files changed, 231 insertions(+) create mode 100644 Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst (limited to 'Documentation') diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index 3d17de7e5aeb..3bc44a7932ee 100644 --- a/Documentation/process/embargoed-hardware-issues.rst +++ b/Documentation/process/embargoed-hardware-issues.rst @@ -1,3 +1,5 @@ +.. _embargoed_hardware_issues: + Embargoed hardware issues ========================= diff --git a/Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst b/Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst new file mode 100644 index 000000000000..b93f1af68261 --- /dev/null +++ b/Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst @@ -0,0 +1,228 @@ +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/embargoed-hardware-issues.rst ` +:Translator: Alex Shi + +被限制的硬件问题 +================ + +范围 +---- + +导致安全问题的硬件问题与只影响Linux内核的纯软件错误是不同的安全错误类别。 + +必须区别对待诸如熔毁(Meltdown)、Spectre、L1TF等硬件问题,因为它们通常会影响 +所有操作系统(“OS”),因此需要在不同的OS供应商、发行版、硬件供应商和其他各方 +之间进行协调。对于某些问题,软件缓解可能依赖于微码或固件更新,这需要进一步的 +协调。 + +.. _zh_Contact: + +接触 +---- + +Linux内核硬件安全小组独立于普通的Linux内核安全小组。 + +该小组只负责协调被限制的硬件安全问题。Linux内核中纯软件安全漏洞的报告不由该 +小组处理,报告者将被引导至常规Linux内核安全小组(:ref:`Documentation/admin-guide/ +`)联系。 + +可以通过电子邮件 与小组联系。这是一份私密的安全 +官名单,他们将帮助您根据我们的文档化流程协调问题。 + +邮件列表是加密的,发送到列表的电子邮件可以通过PGP或S/MIME加密,并且必须使用报告 +者的PGP密钥或S/MIME证书签名。该列表的PGP密钥和S/MIME证书可从 +https://www.kernel.org/.... 获得。 + +虽然硬件安全问题通常由受影响的硬件供应商处理,但我们欢迎发现潜在硬件缺陷的研究 +人员或个人与我们联系。 + +硬件安全官 +^^^^^^^^^^ + +目前的硬件安全官小组: + + - Linus Torvalds(Linux基金会院士) + - Greg Kroah Hartman(Linux基金会院士) + - Thomas Gleixner(Linux基金会院士) + +邮件列表的操作 +^^^^^^^^^^^^^^ + +处理流程中使用的加密邮件列表托管在Linux Foundation的IT基础设施上。通过提供这项 +服务,Linux基金会的IT基础设施安全总监在技术上有能力访问被限制的信息,但根据他 +的雇佣合同,他必须保密。Linux基金会的IT基础设施安全总监还负责 kernel.org 基础 +设施。 + +Linux基金会目前的IT基础设施安全总监是 Konstantin Ryabitsev。 + +保密协议 +-------- + +Linux内核硬件安全小组不是正式的机构,因此无法签订任何保密协议。核心社区意识到 +这些问题的敏感性,并提供了一份谅解备忘录。 + +谅解备忘录 +---------- + +Linux内核社区深刻理解在不同操作系统供应商、发行商、硬件供应商和其他各方之间 +进行协调时,保持硬件安全问题处于限制状态的要求。 + +Linux内核社区在过去已经成功地处理了硬件安全问题,并且有必要的机制允许在限制 +限制下进行符合社区的开发。 + +Linux内核社区有一个专门的硬件安全小组负责初始联系,并监督在限制规则下处理 +此类问题的过程。 + +硬件安全小组确定开发人员(领域专家),他们将组成特定问题的初始响应小组。最初 +的响应小组可以引入更多的开发人员(领域专家)以最佳的技术方式解决这个问题。 + +所有相关开发商承诺遵守限制规定,并对收到的信息保密。违反承诺将导致立即从当前 +问题中排除,并从所有相关邮件列表中删除。此外,硬件安全小组还将把违反者排除在 +未来的问题之外。这一后果的影响在我们社区是一种非常有效的威慑。如果发生违规 +情况,硬件安全小组将立即通知相关方。如果您或任何人发现潜在的违规行为,请立即 +向硬件安全人员报告。 + +流程 +^^^^ + +由于Linux内核开发的全球分布式特性,面对面的会议几乎不可能解决硬件安全问题。 +由于时区和其他因素,电话会议很难协调,只能在绝对必要时使用。加密电子邮件已被 +证明是解决此类问题的最有效和最安全的通信方法。 + +开始披露 +"""""""" + +披露内容首先通过电子邮件联系Linux内核硬件安全小组。此初始联系人应包含问题的 +描述和任何已知受影响硬件的列表。如果您的组织制造或分发受影响的硬件,我们建议 +您也考虑哪些其他硬件可能会受到影响。 + +硬件安全小组将提供一个特定于事件的加密邮件列表,用于与报告者进行初步讨论、 +进一步披露和协调。 + +硬件安全小组将向披露方提供一份开发人员(领域专家)名单,在与开发人员确认他们 +将遵守本谅解备忘录和文件化流程后,应首先告知开发人员有关该问题的信息。这些开发 +人员组成初始响应小组,并在初始接触后负责处理问题。硬件安全小组支持响应小组, +但不一定参与缓解开发过程。 + +虽然个别开发人员可能通过其雇主受到保密协议的保护,但他们不能以Linux内核开发 +人员的身份签订个别保密协议。但是,他们将同意遵守这一书面程序和谅解备忘录。 + +披露方应提供已经或应该被告知该问题的所有其他实体的联系人名单。这有几个目的: + + - 披露的实体列表允许跨行业通信,例如其他操作系统供应商、硬件供应商等。 + + - 可联系已披露的实体,指定应参与缓解措施开发的专家。 + + - 如果需要处理某一问题的专家受雇于某一上市实体或某一上市实体的成员,则响应 + 小组可要求该实体披露该专家。这确保专家也是实体反应小组的一部分。 + +披露 +"""" + +披露方通过特定的加密邮件列表向初始响应小组提供详细信息。 + +根据我们的经验,这些问题的技术文档通常是一个足够的起点,最好通过电子邮件进行 +进一步的技术澄清。 + +缓解开发 +"""""""" + +初始响应小组设置加密邮件列表,或在适当的情况下重新修改现有邮件列表。 + +使用邮件列表接近于正常的Linux开发过程,并且在过去已经成功地用于为各种硬件安全 +问题开发缓解措施。 + +邮件列表的操作方式与正常的Linux开发相同。发布、讨论和审查修补程序,如果同意, +则应用于非公共git存储库,参与开发人员只能通过安全连接访问该存储库。存储库包含 +针对主线内核的主开发分支,并根据需要为稳定的内核版本提供向后移植分支。 + +最初的响应小组将根据需要从Linux内核开发人员社区中确定更多的专家。引进专家可以 +在开发过程中的任何时候发生,需要及时处理。 + +如果专家受雇于披露方提供的披露清单上的实体或其成员,则相关实体将要求其参与。 + +否则,披露方将被告知专家参与的情况。谅解备忘录涵盖了专家,要求披露方确认参与。 +如果披露方有令人信服的理由提出异议,则必须在五个工作日内提出异议,并立即与事件 +小组解决。如果披露方在五个工作日内未作出回应,则视为默许。 + +在确认或解决异议后,专家由事件小组披露,并进入开发过程。 + +协调发布 +"""""""" + +有关各方将协商限制结束的日期和时间。此时,准备好的缓解措施集成到相关的内核树中 +并发布。 + +虽然我们理解硬件安全问题需要协调限制时间,但限制时间应限制在所有有关各方制定、 +测试和准备缓解措施所需的最短时间内。人为地延长限制时间以满足会议讨论日期或其他 +非技术原因,会给相关的开发人员和响应小组带来了更多的工作和负担,因为补丁需要 +保持最新,以便跟踪正在进行的上游内核开发,这可能会造成冲突的更改。 + +CVE分配 +""""""" + +硬件安全小组和初始响应小组都不分配CVE,开发过程也不需要CVE。如果CVE是由披露方 +提供的,则可用于文档中。 + +流程专使 +-------- + +为了协助这一进程,我们在各组织设立了专使,他们可以回答有关报告流程和进一步处理 +的问题或提供指导。专使不参与特定问题的披露,除非响应小组或相关披露方提出要求。 +现任专使名单: + + ============= ======================================================== + ARM + AMD Tom Lendacky + IBM + Intel Tony Luck + Qualcomm Trilok Soni + + Microsoft Sasha Levin + VMware + Xen Andrew Cooper + + Canonical Tyler Hicks + Debian Ben Hutchings + Oracle Konrad Rzeszutek Wilk + Red Hat Josh Poimboeuf + SUSE Jiri Kosina + + Amazon + Google Kees Cook + ============= ======================================================== + +如果要将您的组织添加到专使名单中,请与硬件安全小组联系。被提名的专使必须完全 +理解和支持我们的过程,并且在Linux内核社区中很容易联系。 + +加密邮件列表 +------------ + +我们使用加密邮件列表进行通信。这些列表的工作原理是,发送到列表的电子邮件使用 +列表的PGP密钥或列表的/MIME证书进行加密。邮件列表软件对电子邮件进行解密,并 +使用订阅者的PGP密钥或S/MIME证书为每个订阅者分别对其进行重新加密。有关邮件列表 +软件和用于确保列表安全和数据保护的设置的详细信息,请访问: +https://www.kernel.org/.... + +关键点 +^^^^^^ + +初次接触见 :ref:`zh_Contact`. 对于特定于事件的邮件列表,密钥和S/MIME证书通过 +特定列表发送的电子邮件传递给订阅者。 + +订阅事件特定列表 +^^^^^^^^^^^^^^^^ + +订阅由响应小组处理。希望参与通信的披露方将潜在订户的列表发送给响应组,以便 +响应组可以验证订阅请求。 + +每个订户都需要通过电子邮件向响应小组发送订阅请求。电子邮件必须使用订阅服务器 +的PGP密钥或S/MIME证书签名。如果使用PGP密钥,则必须从公钥服务器获得该密钥, +并且理想情况下该密钥连接到Linux内核的PGP信任网。另请参见: +https://www.kernel.org/signature.html. + +响应小组验证订阅者,并将订阅者添加到列表中。订阅后,订阅者将收到来自邮件列表 +的电子邮件,该邮件列表使用列表的PGP密钥或列表的/MIME证书签名。订阅者的电子邮件 +客户端可以从签名中提取PGP密钥或S/MIME证书,以便订阅者可以向列表发送加密电子 +邮件。 diff --git a/Documentation/translations/zh_CN/process/index.rst b/Documentation/translations/zh_CN/process/index.rst index be1e764a80d2..f7a84eff6e93 100644 --- a/Documentation/translations/zh_CN/process/index.rst +++ b/Documentation/translations/zh_CN/process/index.rst @@ -43,6 +43,7 @@ stable-api-nonsense stable-kernel-rules management-style + embargoed-hardware-issues 这些是一些总体技术指南,由于缺乏更好的地方,现在已经放在这里 -- cgit v1.2.3 From fdfb5dfa747fb58976d18af9fb20bec8981f6564 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Fri, 20 Dec 2019 11:04:44 +0800 Subject: docs/zh_CN: translate kernel driver statement into Chinese kernel driver statement is a great statement in kernel community. This patch translate the statement into Chinese and add it into toctree. Signed-off-by: Alex Shi Cc: Harry Wei Cc: lizefan@huawei.com Cc: Fengguang Wu Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/1576811085-30544-2-git-send-email-alex.shi@linux.alibaba.com Signed-off-by: Jonathan Corbet --- Documentation/translations/zh_CN/process/index.rst | 1 + .../zh_CN/process/kernel-driver-statement.rst | 199 +++++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100644 Documentation/translations/zh_CN/process/kernel-driver-statement.rst (limited to 'Documentation') diff --git a/Documentation/translations/zh_CN/process/index.rst b/Documentation/translations/zh_CN/process/index.rst index f7a84eff6e93..47a2af54fb13 100644 --- a/Documentation/translations/zh_CN/process/index.rst +++ b/Documentation/translations/zh_CN/process/index.rst @@ -31,6 +31,7 @@ development-process email-clients license-rules + kernel-driver-statement 其它大多数开发人员感兴趣的社区指南: diff --git a/Documentation/translations/zh_CN/process/kernel-driver-statement.rst b/Documentation/translations/zh_CN/process/kernel-driver-statement.rst new file mode 100644 index 000000000000..2b3375bcccfd --- /dev/null +++ b/Documentation/translations/zh_CN/process/kernel-driver-statement.rst @@ -0,0 +1,199 @@ +.. _cn_process_statement_driver: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/kernel-driver-statement.rst ` +:Translator: Alex Shi + +内核驱动声明 +------------ + +关于Linux内核模块的立场声明 +=========================== + +我们,以下署名的Linux内核开发人员,认为任何封闭源Linux内核模块或驱动程序都是 +有害的和不可取的。我们已经一再发现它们对Linux用户,企业和更大的Linux生态系统 +有害。这样的模块否定了Linux开发模型的开放性,稳定性,灵活性和可维护性,并使 +他们的用户无法使用Linux社区的专业知识。提供闭源内核模块的供应商迫使其客户 +放弃Linux的主要优势或选择新的供应商。因此,为了充分利用开源所提供的成本节省和 +共享支持优势,我们敦促供应商采取措施,以开源内核代码在Linux上为其客户提供支持。 + +我们只为自己说话,而不是我们今天可能会为之工作,过去或将来会为之工作的任何公司。 + + - Dave Airlie + - Nick Andrew + - Jens Axboe + - Ralf Baechle + - Felipe Balbi + - Ohad Ben-Cohen + - Muli Ben-Yehuda + - Jiri Benc + - Arnd Bergmann + - Thomas Bogendoerfer + - Vitaly Bordug + - James Bottomley + - Josh Boyer + - Neil Brown + - Mark Brown + - David Brownell + - Michael Buesch + - Franck Bui-Huu + - Adrian Bunk + - François Cami + - Ralph Campbell + - Luiz Fernando N. Capitulino + - Mauro Carvalho Chehab + - Denis Cheng + - Jonathan Corbet + - Glauber Costa + - Alan Cox + - Magnus Damm + - Ahmed S. Darwish + - Robert P. J. Day + - Hans de Goede + - Arnaldo Carvalho de Melo + - Helge Deller + - Jean Delvare + - Mathieu Desnoyers + - Sven-Thorsten Dietrich + - Alexey Dobriyan + - Daniel Drake + - Alex Dubov + - Randy Dunlap + - Michael Ellerman + - Pekka Enberg + - Jan Engelhardt + - Mark Fasheh + - J. Bruce Fields + - Larry Finger + - Jeremy Fitzhardinge + - Mike Frysinger + - Kumar Gala + - Robin Getz + - Liam Girdwood + - Jan-Benedict Glaw + - Thomas Gleixner + - Brice Goglin + - Cyrill Gorcunov + - Andy Gospodarek + - Thomas Graf + - Krzysztof Halasa + - Harvey Harrison + - Stephen Hemminger + - Michael Hennerich + - Tejun Heo + - Benjamin Herrenschmidt + - Kristian Høgsberg + - Henrique de Moraes Holschuh + - Marcel Holtmann + - Mike Isely + - Takashi Iwai + - Olof Johansson + - Dave Jones + - Jesper Juhl + - Matthias Kaehlcke + - Kenji Kaneshige + - Jan Kara + - Jeremy Kerr + - Russell King + - Olaf Kirch + - Roel Kluin + - Hans-Jürgen Koch + - Auke Kok + - Peter Korsgaard + - Jiri Kosina + - Aaro Koskinen + - Mariusz Kozlowski + - Greg Kroah-Hartman + - Michael Krufky + - Aneesh Kumar + - Clemens Ladisch + - Christoph Lameter + - Gunnar Larisch + - Anders Larsen + - Grant Likely + - John W. Linville + - Yinghai Lu + - Tony Luck + - Pavel Machek + - Matt Mackall + - Paul Mackerras + - Roland McGrath + - Patrick McHardy + - Kyle McMartin + - Paul Menage + - Thierry Merle + - Eric Miao + - Akinobu Mita + - Ingo Molnar + - James Morris + - Andrew Morton + - Paul Mundt + - Oleg Nesterov + - Luca Olivetti + - S.Çağlar Onur + - Pierre Ossman + - Keith Owens + - Venkatesh Pallipadi + - Nick Piggin + - Nicolas Pitre + - Evgeniy Polyakov + - Richard Purdie + - Mike Rapoport + - Sam Ravnborg + - Gerrit Renker + - Stefan Richter + - David Rientjes + - Luis R. Rodriguez + - Stefan Roese + - Francois Romieu + - Rami Rosen + - Stephen Rothwell + - Maciej W. Rozycki + - Mark Salyzyn + - Yoshinori Sato + - Deepak Saxena + - Holger Schurig + - Amit Shah + - Yoshihiro Shimoda + - Sergei Shtylyov + - Kay Sievers + - Sebastian Siewior + - Rik Snel + - Jes Sorensen + - Alexey Starikovskiy + - Alan Stern + - Timur Tabi + - Hirokazu Takata + - Eliezer Tamir + - Eugene Teo + - Doug Thompson + - FUJITA Tomonori + - Dmitry Torokhov + - Marcelo Tosatti + - Steven Toth + - Theodore Tso + - Matthias Urlichs + - Geert Uytterhoeven + - Arjan van de Ven + - Ivo van Doorn + - Rik van Riel + - Wim Van Sebroeck + - Hans Verkuil + - Horst H. von Brand + - Dmitri Vorobiev + - Anton Vorontsov + - Daniel Walker + - Johannes Weiner + - Harald Welte + - Matthew Wilcox + - Dan J. Williams + - Darrick J. Wong + - David Woodhouse + - Chris Wright + - Bryan Wu + - Rafael J. Wysocki + - Herbert Xu + - Vlad Yasevich + - Peter Zijlstra + - Bartlomiej Zolnierkiewicz -- cgit v1.2.3 From 3697aa15563f3bb06c27af135dd7be77af4fe71a Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Fri, 20 Dec 2019 11:04:45 +0800 Subject: docs/zh_CN: translate kernel enforcement statement kernel enforcement statement is a important statement to show a kind of attitude in kernel community. This patch translate it into Chinese and add it into toctree. Signed-off-by: Alex Shi Cc: Fengguang Wu Cc: Li Zefan Cc: Harry Wei Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/1576811085-30544-3-git-send-email-alex.shi@linux.alibaba.com Signed-off-by: Jonathan Corbet --- Documentation/translations/zh_CN/process/index.rst | 1 + .../zh_CN/process/kernel-enforcement-statement.rst | 151 +++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst (limited to 'Documentation') diff --git a/Documentation/translations/zh_CN/process/index.rst b/Documentation/translations/zh_CN/process/index.rst index 47a2af54fb13..8051a7b322c5 100644 --- a/Documentation/translations/zh_CN/process/index.rst +++ b/Documentation/translations/zh_CN/process/index.rst @@ -31,6 +31,7 @@ development-process email-clients license-rules + kernel-enforcement-statement kernel-driver-statement 其它大多数开发人员感兴趣的社区指南: diff --git a/Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst b/Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst new file mode 100644 index 000000000000..75f7b7b9137c --- /dev/null +++ b/Documentation/translations/zh_CN/process/kernel-enforcement-statement.rst @@ -0,0 +1,151 @@ +.. _cn_process_statement_kernel: + +.. include:: ../disclaimer-zh_CN.rst + +:Original: :ref:`Documentation/process/kernel-enforcement-statement.rst ` +:Translator: Alex Shi + +Linux 内核执行声明 +------------------ + +作为Linux内核的开发人员,我们对如何使用我们的软件以及如何实施软件许可证有着 +浓厚的兴趣。遵守GPL-2.0的互惠共享义务对我们软件和社区的长期可持续性至关重要。 + +虽然有权强制执行对我们社区的贡献中的单独版权权益,但我们有共同的利益,即确保 +个人强制执行行动的方式有利于我们的社区,不会对我们软件生态系统的健康和增长 +产生意外的负面影响。为了阻止无益的执法行动,我们同意代表我们自己和我们版权 +利益的任何继承人对Linux内核用户作出以下符合我们开发社区最大利益的承诺: + + 尽管有GPL-2.0的终止条款,我们同意,采用以下GPL-3.0条款作为我们许可证下的 + 附加许可,作为任何对许可证下权利的非防御性主张,这符合我们开发社区的最佳 + 利益。 + + 但是,如果您停止所有违反本许可证的行为,则您从特定版权持有人处获得的 + 许可证将被恢复:(a)暂时恢复,除非版权持有人明确并最终终止您的许可证; + 以及(b)永久恢复, 如果版权持有人未能在你终止违反后60天内以合理方式 + 通知您违反本许可证的行为,则永久恢复您的许可证。 + + 此外,如果版权所有者以某种合理的方式通知您违反了本许可,这是您第一次 + 从该版权所有者处收到违反本许可的通知(对于任何作品),并且您在收到通知 + 后的30天内纠正违规行为。则您从特定版权所有者处获得的许可将永久恢复. + +我们提供这些保证的目的是鼓励更多地使用该软件。我们希望公司和个人使用、修改和 +分发此软件。我们希望以公开和透明的方式与用户合作,以消除我们对法规遵从性或强制 +执行的任何不确定性,这些不确定性可能会限制我们软件的采用。我们将法律行动视为 +最后手段,只有在其他社区努力未能解决这一问题时才采取行动。 + +最后,一旦一个不合规问题得到解决,我们希望用户会感到欢迎,加入我们为之努力的 +这个项目。共同努力,我们会更强大。 + +除了下面提到的以外,我们只为自己说话,而不是为今天、过去或将来可能为之工作的 +任何公司说话。 + + - Laura Abbott + - Bjorn Andersson (Linaro) + - Andrea Arcangeli + - Neil Armstrong + - Jens Axboe + - Pablo Neira Ayuso + - Khalid Aziz + - Ralf Baechle + - Felipe Balbi + - Arnd Bergmann + - Ard Biesheuvel + - Tim Bird + - Paolo Bonzini + - Christian Borntraeger + - Mark Brown (Linaro) + - Paul Burton + - Javier Martinez Canillas + - Rob Clark + - Kees Cook (Google) + - Jonathan Corbet + - Dennis Dalessandro + - Vivien Didelot (Savoir-faire Linux) + - Hans de Goede + - Mel Gorman (SUSE) + - Sven Eckelmann + - Alex Elder (Linaro) + - Fabio Estevam + - Larry Finger + - Bhumika Goyal + - Andy Gross + - Juergen Gross + - Shawn Guo + - Ulf Hansson + - Stephen Hemminger (Microsoft) + - Tejun Heo + - Rob Herring + - Masami Hiramatsu + - Michal Hocko + - Simon Horman + - Johan Hovold (Hovold Consulting AB) + - Christophe JAILLET + - Olof Johansson + - Lee Jones (Linaro) + - Heiner Kallweit + - Srinivas Kandagatla + - Jan Kara + - Shuah Khan (Samsung) + - David Kershner + - Jaegeuk Kim + - Namhyung Kim + - Colin Ian King + - Jeff Kirsher + - Greg Kroah-Hartman (Linux Foundation) + - Christian König + - Vinod Koul + - Krzysztof Kozlowski + - Viresh Kumar + - Aneesh Kumar K.V + - Julia Lawall + - Doug Ledford + - Chuck Lever (Oracle) + - Daniel Lezcano + - Shaohua Li + - Xin Long + - Tony Luck + - Catalin Marinas (Arm Ltd) + - Mike Marshall + - Chris Mason + - Paul E. McKenney + - Arnaldo Carvalho de Melo + - David S. Miller + - Ingo Molnar + - Kuninori Morimoto + - Trond Myklebust + - Martin K. Petersen (Oracle) + - Borislav Petkov + - Jiri Pirko + - Josh Poimboeuf + - Sebastian Reichel (Collabora) + - Guenter Roeck + - Joerg Roedel + - Leon Romanovsky + - Steven Rostedt (VMware) + - Frank Rowand + - Ivan Safonov + - Anna Schumaker + - Jes Sorensen + - K.Y. Srinivasan + - David Sterba (SUSE) + - Heiko Stuebner + - Jiri Kosina (SUSE) + - Willy Tarreau + - Dmitry Torokhov + - Linus Torvalds + - Thierry Reding + - Rik van Riel + - Luis R. Rodriguez + - Geert Uytterhoeven (Glider bvba) + - Eduardo Valentin (Amazon.com) + - Daniel Vetter + - Linus Walleij + - Richard Weinberger + - Dan Williams + - Rafael J. Wysocki + - Arvind Yadav + - Masahiro Yamada + - Wei Yongjun + - Lv Zheng + - Marc Zyngier (Arm Ltd) -- cgit v1.2.3 From 93edd392cad7485097c2e9068c764ae30083bb05 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 19 Nov 2019 14:24:47 -0800 Subject: fscrypt: support passing a keyring key to FS_IOC_ADD_ENCRYPTION_KEY Extend the FS_IOC_ADD_ENCRYPTION_KEY ioctl to allow the raw key to be specified by a Linux keyring key, rather than specified directly. This is useful because fscrypt keys belong to a particular filesystem instance, so they are destroyed when that filesystem is unmounted. Usually this is desired. But in some cases, userspace may need to unmount and re-mount the filesystem while keeping the keys, e.g. during a system update. This requires keeping the keys somewhere else too. The keys could be kept in memory in a userspace daemon. But depending on the security architecture and assumptions, it can be preferable to keep them only in kernel memory, where they are unreadable by userspace. We also can't solve this by going back to the original fscrypt API (where for each file, the master key was looked up in the process's keyring hierarchy) because that caused lots of problems of its own. Therefore, add the ability for FS_IOC_ADD_ENCRYPTION_KEY to accept a Linux keyring key. This solves the problem by allowing userspace to (if needed) save the keys securely in a Linux keyring for re-provisioning, while still using the new fscrypt key management ioctls. This is analogous to how dm-crypt accepts a Linux keyring key, but the key is then stored internally in the dm-crypt data structures rather than being looked up again each time the dm-crypt device is accessed. Use a custom key type "fscrypt-provisioning" rather than one of the existing key types such as "logon". This is strongly desired because it enforces that these keys are only usable for a particular purpose: for fscrypt as input to a particular KDF. Otherwise, the keys could also be passed to any kernel API that accepts a "logon" key with any service prefix, e.g. dm-crypt, UBIFS, or (recently proposed) AF_ALG. This would risk leaking information about the raw key despite it ostensibly being unreadable. Of course, this mistake has already been made for multiple kernel APIs; but since this is a new API, let's do it right. This patch has been tested using an xfstest which I wrote to test it. Link: https://lore.kernel.org/r/20191119222447.226853-1-ebiggers@kernel.org Signed-off-by: Eric Biggers --- Documentation/filesystems/fscrypt.rst | 35 ++++++++- fs/crypto/keyring.c | 132 +++++++++++++++++++++++++++++++--- include/uapi/linux/fscrypt.h | 13 +++- 3 files changed, 168 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst index 68c2bc8275cf..9c53336d06a4 100644 --- a/Documentation/filesystems/fscrypt.rst +++ b/Documentation/filesystems/fscrypt.rst @@ -638,7 +638,8 @@ follows:: struct fscrypt_add_key_arg { struct fscrypt_key_specifier key_spec; __u32 raw_size; - __u32 __reserved[9]; + __u32 key_id; + __u32 __reserved[8]; __u8 raw[]; }; @@ -655,6 +656,12 @@ follows:: } u; }; + struct fscrypt_provisioning_key_payload { + __u32 type; + __u32 __reserved; + __u8 raw[]; + }; + :c:type:`struct fscrypt_add_key_arg` must be zeroed, then initialized as follows: @@ -677,9 +684,26 @@ as follows: ``Documentation/security/keys/core.rst``). - ``raw_size`` must be the size of the ``raw`` key provided, in bytes. + Alternatively, if ``key_id`` is nonzero, this field must be 0, since + in that case the size is implied by the specified Linux keyring key. + +- ``key_id`` is 0 if the raw key is given directly in the ``raw`` + field. Otherwise ``key_id`` is the ID of a Linux keyring key of + type "fscrypt-provisioning" whose payload is a :c:type:`struct + fscrypt_provisioning_key_payload` whose ``raw`` field contains the + raw key and whose ``type`` field matches ``key_spec.type``. Since + ``raw`` is variable-length, the total size of this key's payload + must be ``sizeof(struct fscrypt_provisioning_key_payload)`` plus the + raw key size. The process must have Search permission on this key. + + Most users should leave this 0 and specify the raw key directly. + The support for specifying a Linux keyring key is intended mainly to + allow re-adding keys after a filesystem is unmounted and re-mounted, + without having to store the raw keys in userspace memory. - ``raw`` is a variable-length field which must contain the actual - key, ``raw_size`` bytes long. + key, ``raw_size`` bytes long. Alternatively, if ``key_id`` is + nonzero, then this field is unused. For v2 policy keys, the kernel keeps track of which user (identified by effective user ID) added the key, and only allows the key to be @@ -701,11 +725,16 @@ FS_IOC_ADD_ENCRYPTION_KEY can fail with the following errors: - ``EACCES``: FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR was specified, but the caller does not have the CAP_SYS_ADMIN capability in the initial - user namespace + user namespace; or the raw key was specified by Linux key ID but the + process lacks Search permission on the key. - ``EDQUOT``: the key quota for this user would be exceeded by adding the key - ``EINVAL``: invalid key size or key specifier type, or reserved bits were set +- ``EKEYREJECTED``: the raw key was specified by Linux key ID, but the + key has the wrong type +- ``ENOKEY``: the raw key was specified by Linux key ID, but no key + exists with that ID - ``ENOTTY``: this type of filesystem does not implement encryption - ``EOPNOTSUPP``: the kernel was not configured with encryption support for this filesystem, or the filesystem superblock has not diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 40cca351273f..098ff2e0f0bb 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -465,6 +465,109 @@ out_unlock: return err; } +static int fscrypt_provisioning_key_preparse(struct key_preparsed_payload *prep) +{ + const struct fscrypt_provisioning_key_payload *payload = prep->data; + + if (prep->datalen < sizeof(*payload) + FSCRYPT_MIN_KEY_SIZE || + prep->datalen > sizeof(*payload) + FSCRYPT_MAX_KEY_SIZE) + return -EINVAL; + + if (payload->type != FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR && + payload->type != FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) + return -EINVAL; + + if (payload->__reserved) + return -EINVAL; + + prep->payload.data[0] = kmemdup(payload, prep->datalen, GFP_KERNEL); + if (!prep->payload.data[0]) + return -ENOMEM; + + prep->quotalen = prep->datalen; + return 0; +} + +static void fscrypt_provisioning_key_free_preparse( + struct key_preparsed_payload *prep) +{ + kzfree(prep->payload.data[0]); +} + +static void fscrypt_provisioning_key_describe(const struct key *key, + struct seq_file *m) +{ + seq_puts(m, key->description); + if (key_is_positive(key)) { + const struct fscrypt_provisioning_key_payload *payload = + key->payload.data[0]; + + seq_printf(m, ": %u [%u]", key->datalen, payload->type); + } +} + +static void fscrypt_provisioning_key_destroy(struct key *key) +{ + kzfree(key->payload.data[0]); +} + +static struct key_type key_type_fscrypt_provisioning = { + .name = "fscrypt-provisioning", + .preparse = fscrypt_provisioning_key_preparse, + .free_preparse = fscrypt_provisioning_key_free_preparse, + .instantiate = generic_key_instantiate, + .describe = fscrypt_provisioning_key_describe, + .destroy = fscrypt_provisioning_key_destroy, +}; + +/* + * Retrieve the raw key from the Linux keyring key specified by 'key_id', and + * store it into 'secret'. + * + * The key must be of type "fscrypt-provisioning" and must have the field + * fscrypt_provisioning_key_payload::type set to 'type', indicating that it's + * only usable with fscrypt with the particular KDF version identified by + * 'type'. We don't use the "logon" key type because there's no way to + * completely restrict the use of such keys; they can be used by any kernel API + * that accepts "logon" keys and doesn't require a specific service prefix. + * + * The ability to specify the key via Linux keyring key is intended for cases + * where userspace needs to re-add keys after the filesystem is unmounted and + * re-mounted. Most users should just provide the raw key directly instead. + */ +static int get_keyring_key(u32 key_id, u32 type, + struct fscrypt_master_key_secret *secret) +{ + key_ref_t ref; + struct key *key; + const struct fscrypt_provisioning_key_payload *payload; + int err; + + ref = lookup_user_key(key_id, 0, KEY_NEED_SEARCH); + if (IS_ERR(ref)) + return PTR_ERR(ref); + key = key_ref_to_ptr(ref); + + if (key->type != &key_type_fscrypt_provisioning) + goto bad_key; + payload = key->payload.data[0]; + + /* Don't allow fscrypt v1 keys to be used as v2 keys and vice versa. */ + if (payload->type != type) + goto bad_key; + + secret->size = key->datalen - sizeof(*payload); + memcpy(secret->raw, payload->raw, secret->size); + err = 0; + goto out_put; + +bad_key: + err = -EKEYREJECTED; +out_put: + key_ref_put(ref); + return err; +} + /* * Add a master encryption key to the filesystem, causing all files which were * encrypted with it to appear "unlocked" (decrypted) when accessed. @@ -503,18 +606,25 @@ int fscrypt_ioctl_add_key(struct file *filp, void __user *_uarg) if (!valid_key_spec(&arg.key_spec)) return -EINVAL; - if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || - arg.raw_size > FSCRYPT_MAX_KEY_SIZE) - return -EINVAL; - if (memchr_inv(arg.__reserved, 0, sizeof(arg.__reserved))) return -EINVAL; memset(&secret, 0, sizeof(secret)); - secret.size = arg.raw_size; - err = -EFAULT; - if (copy_from_user(secret.raw, uarg->raw, secret.size)) - goto out_wipe_secret; + if (arg.key_id) { + if (arg.raw_size != 0) + return -EINVAL; + err = get_keyring_key(arg.key_id, arg.key_spec.type, &secret); + if (err) + goto out_wipe_secret; + } else { + if (arg.raw_size < FSCRYPT_MIN_KEY_SIZE || + arg.raw_size > FSCRYPT_MAX_KEY_SIZE) + return -EINVAL; + secret.size = arg.raw_size; + err = -EFAULT; + if (copy_from_user(secret.raw, uarg->raw, secret.size)) + goto out_wipe_secret; + } switch (arg.key_spec.type) { case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: @@ -978,8 +1088,14 @@ int __init fscrypt_init_keyring(void) if (err) goto err_unregister_fscrypt; + err = register_key_type(&key_type_fscrypt_provisioning); + if (err) + goto err_unregister_fscrypt_user; + return 0; +err_unregister_fscrypt_user: + unregister_key_type(&key_type_fscrypt_user); err_unregister_fscrypt: unregister_key_type(&key_type_fscrypt); return err; diff --git a/include/uapi/linux/fscrypt.h b/include/uapi/linux/fscrypt.h index 1beb174ad950..d5112a24e8b9 100644 --- a/include/uapi/linux/fscrypt.h +++ b/include/uapi/linux/fscrypt.h @@ -109,11 +109,22 @@ struct fscrypt_key_specifier { } u; }; +/* + * Payload of Linux keyring key of type "fscrypt-provisioning", referenced by + * fscrypt_add_key_arg::key_id as an alternative to fscrypt_add_key_arg::raw. + */ +struct fscrypt_provisioning_key_payload { + __u32 type; + __u32 __reserved; + __u8 raw[]; +}; + /* Struct passed to FS_IOC_ADD_ENCRYPTION_KEY */ struct fscrypt_add_key_arg { struct fscrypt_key_specifier key_spec; __u32 raw_size; - __u32 __reserved[9]; + __u32 key_id; + __u32 __reserved[8]; __u8 raw[]; }; -- cgit v1.2.3 From c6ed90b54f0869bddcd3f4c200edfcec3d1b9ae8 Mon Sep 17 00:00:00 2001 From: Tomer Maimon Date: Wed, 6 Nov 2019 16:53:29 +0200 Subject: dt-bindings: reset: add NPCM reset controller documentation Added device tree binding documentation for Nuvoton BMC NPCM reset controller. Signed-off-by: Tomer Maimon Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../bindings/reset/nuvoton,npcm-reset.txt | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/nuvoton,npcm-reset.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/reset/nuvoton,npcm-reset.txt b/Documentation/devicetree/bindings/reset/nuvoton,npcm-reset.txt new file mode 100644 index 000000000000..6e802703af60 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/nuvoton,npcm-reset.txt @@ -0,0 +1,32 @@ +Nuvoton NPCM Reset controller + +Required properties: +- compatible : "nuvoton,npcm750-reset" for NPCM7XX BMC +- reg : specifies physical base address and size of the register. +- #reset-cells: must be set to 2 + +Optional property: +- nuvoton,sw-reset-number - Contains the software reset number to restart the SoC. + NPCM7xx contain four software reset that represent numbers 1 to 4. + + If 'nuvoton,sw-reset-number' is not specfied software reset is disabled. + +Example: + rstc: rstc@f0801000 { + compatible = "nuvoton,npcm750-reset"; + reg = <0xf0801000 0x70>; + #reset-cells = <2>; + nuvoton,sw-reset-number = <2>; + }; + +Specifying reset lines connected to IP NPCM7XX modules +====================================================== +example: + + spi0: spi@..... { + ... + resets = <&rstc NPCM7XX_RESET_IPSRST2 NPCM7XX_RESET_PSPI1>; + ... + }; + +The index could be found in . -- cgit v1.2.3 From a3f048b5424e68f0f7218c51e84d7b84ab0143cb Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 10 Oct 2019 12:01:48 +0200 Subject: dt: psci: Update DT bindings to support hierarchical PSCI states Update PSCI DT bindings to allow to represent idle states for CPUs and the CPU topology, by using a hierarchical layout. Primarily this is done by re-using the existing DT bindings for PM domains [1] and for PM domain idle states [2]. Let's also add an example into the document for the PSCI DT bindings, to clearly show the new hierarchical based layout. The currently supported flattened layout, is already described in the ARM idle states bindings [3], so let's leave that as is. [1] Documentation/devicetree/bindings/power/power_domain.txt [2] Documentation/devicetree/bindings/power/domain-idle-state.txt [3] Documentation/devicetree/bindings/arm/idle-states.txt Co-developed-by: Lina Iyer Signed-off-by: Lina Iyer Reviewed-by: Sudeep Holla Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/arm/cpus.yaml | 15 ++++ Documentation/devicetree/bindings/arm/psci.yaml | 104 ++++++++++++++++++++++++ 2 files changed, 119 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml index c23c24ff7575..7a9c3ce2dbef 100644 --- a/Documentation/devicetree/bindings/arm/cpus.yaml +++ b/Documentation/devicetree/bindings/arm/cpus.yaml @@ -242,6 +242,21 @@ properties: where voltage is in V, frequency is in MHz. + power-domains: + $ref: '/schemas/types.yaml#/definitions/phandle-array' + description: + List of phandles and PM domain specifiers, as defined by bindings of the + PM domain provider (see also ../power_domain.txt). + + power-domain-names: + $ref: '/schemas/types.yaml#/definitions/string-array' + description: + A list of power domain name strings sorted in the same order as the + power-domains property. + + For PSCI based platforms, the name corresponding to the index of the PSCI + PM domain provider, must be "psci". + qcom,saw: $ref: '/schemas/types.yaml#/definitions/phandle' description: | diff --git a/Documentation/devicetree/bindings/arm/psci.yaml b/Documentation/devicetree/bindings/arm/psci.yaml index 7abdf58b335e..8ef85420b2ab 100644 --- a/Documentation/devicetree/bindings/arm/psci.yaml +++ b/Documentation/devicetree/bindings/arm/psci.yaml @@ -102,6 +102,34 @@ properties: [1] Kernel documentation - ARM idle states bindings Documentation/devicetree/bindings/arm/idle-states.txt + "#power-domain-cells": + description: + The number of cells in a PM domain specifier as per binding in [3]. + Must be 0 as to represent a single PM domain. + + ARM systems can have multiple cores, sometimes in an hierarchical + arrangement. This often, but not always, maps directly to the processor + power topology of the system. Individual nodes in a topology have their + own specific power states and can be better represented hierarchically. + + For these cases, the definitions of the idle states for the CPUs and the + CPU topology, must conform to the binding in [3]. The idle states + themselves must conform to the binding in [4] and must specify the + arm,psci-suspend-param property. + + It should also be noted that, in PSCI firmware v1.0 the OS-Initiated + (OSI) CPU suspend mode is introduced. Using a hierarchical representation + helps to implement support for OSI mode and OS implementations may choose + to mandate it. + + [3] Documentation/devicetree/bindings/power/power_domain.txt + [4] Documentation/devicetree/bindings/power/domain-idle-state.txt + + power-domains: + $ref: '/schemas/types.yaml#/definitions/phandle-array' + description: + List of phandles and PM domain specifiers, as defined by bindings of the + PM domain provider. required: - compatible @@ -160,4 +188,80 @@ examples: cpu_on = <0x95c10002>; cpu_off = <0x95c10001>; }; + + - |+ + + // Case 4: CPUs and CPU idle states described using the hierarchical model. + + cpus { + #size-cells = <0>; + #address-cells = <1>; + + CPU0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + power-domains = <&CPU_PD0>; + power-domain-names = "psci"; + }; + + CPU1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + power-domains = <&CPU_PD1>; + power-domain-names = "psci"; + }; + + idle-states { + + CPU_PWRDN: cpu-power-down { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0000001>; + entry-latency-us = <10>; + exit-latency-us = <10>; + min-residency-us = <100>; + }; + + CLUSTER_RET: cluster-retention { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x1000011>; + entry-latency-us = <500>; + exit-latency-us = <500>; + min-residency-us = <2000>; + }; + + CLUSTER_PWRDN: cluster-power-down { + compatible = "domain-idle-state"; + arm,psci-suspend-param = <0x1000031>; + entry-latency-us = <2000>; + exit-latency-us = <2000>; + min-residency-us = <6000>; + }; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + + CPU_PD0: cpu-pd0 { + #power-domain-cells = <0>; + domain-idle-states = <&CPU_PWRDN>; + power-domains = <&CLUSTER_PD>; + }; + + CPU_PD1: cpu-pd1 { + #power-domain-cells = <0>; + domain-idle-states = <&CPU_PWRDN>; + power-domains = <&CLUSTER_PD>; + }; + + CLUSTER_PD: cluster-pd { + #power-domain-cells = <0>; + domain-idle-states = <&CLUSTER_RET>, <&CLUSTER_PWRDN>; + }; + }; ... -- cgit v1.2.3 From b435f8b4f6a08f5bbf001cfd4bed22070e3774fd Mon Sep 17 00:00:00 2001 From: Brian Masney Date: Thu, 21 Nov 2019 20:26:42 -0500 Subject: dt-bindings: drm/msm/gpu: document second interconnect Some A3xx and all A4xx Adreno GPUs do not have GMEM inside the GPU core and must use the On Chip MEMory (OCMEM) in order to be functional. There's a separate interconnect path that needs to be setup to OCMEM. Let's document this second interconnect path that's available. Since there's now two available interconnects, let's add the interconnect-names property. Signed-off-by: Brian Masney Acked-by: Rob Herring Reviewed-by: Bjorn Andersson Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/gpu.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/msm/gpu.txt b/Documentation/devicetree/bindings/display/msm/gpu.txt index 2b8fd26c43b0..3e6cd3f64a78 100644 --- a/Documentation/devicetree/bindings/display/msm/gpu.txt +++ b/Documentation/devicetree/bindings/display/msm/gpu.txt @@ -23,7 +23,10 @@ Required properties: - iommus: optional phandle to an adreno iommu instance - operating-points-v2: optional phandle to the OPP operating points - interconnects: optional phandle to an interconnect provider. See - ../interconnect/interconnect.txt for details. + ../interconnect/interconnect.txt for details. Some A3xx and all A4xx platforms + will have two paths; all others will have one path. +- interconnect-names: The names of the interconnect paths that correspond to the + interconnects property. Values must be gfx-mem and ocmem. - qcom,gmu: For GMU attached devices a phandle to the GMU device that will control the power for the GPU. Applicable targets: - qcom,adreno-630.2 @@ -76,6 +79,7 @@ Example a6xx (with GMU): operating-points-v2 = <&gpu_opp_table>; interconnects = <&rsc_hlos MASTER_GFX3D &rsc_hlos SLAVE_EBI1>; + interconnect-names = "gfx-mem"; qcom,gmu = <&gmu>; -- cgit v1.2.3 From 854f94226a91010e81e09d79ba7ea253e64e6091 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Mon, 25 Nov 2019 17:29:26 +0530 Subject: dt-bindings: msm:disp: add sc7180 DPU variant Add a compatible string to support sc7180 dpu version. Signed-off-by: Kalyan Thota Acked-by: Rob Herring Signed-off-by: Rob Clark --- Documentation/devicetree/bindings/display/msm/dpu.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/msm/dpu.txt b/Documentation/devicetree/bindings/display/msm/dpu.txt index a61dd40f3792..551ae26f60da 100644 --- a/Documentation/devicetree/bindings/display/msm/dpu.txt +++ b/Documentation/devicetree/bindings/display/msm/dpu.txt @@ -8,7 +8,7 @@ The DPU display controller is found in SDM845 SoC. MDSS: Required properties: -- compatible: "qcom,sdm845-mdss" +- compatible: "qcom,sdm845-mdss", "qcom,sc7180-mdss" - reg: physical base address and length of contoller's registers. - reg-names: register region names. The following region is required: * "mdss" @@ -41,7 +41,7 @@ Optional properties: MDP: Required properties: -- compatible: "qcom,sdm845-dpu" +- compatible: "qcom,sdm845-dpu", "qcom,sc7180-dpu" - reg: physical base address and length of controller's registers. - reg-names : register region names. The following region is required: * "mdp" -- cgit v1.2.3 From e382d7fcfc3ff21c8ba97a29bd451a289f57b757 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Jan 2020 09:16:35 +0100 Subject: ALSA: docs: Constify snd_device_ops definitions Update the documentation for adding the const prefix to snd_device_ops definitions as well. Link: https://lore.kernel.org/r/20200103081714.9560-20-tiwai@suse.de Signed-off-by: Takashi Iwai --- Documentation/sound/kernel-api/writing-an-alsa-driver.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index f169d58ca019..7b1ba1e447b9 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst @@ -259,7 +259,7 @@ to details explained in the following section. { struct mychip *chip; int err; - static struct snd_device_ops ops = { + static const struct snd_device_ops ops = { .dev_free = snd_mychip_dev_free, }; @@ -675,7 +675,7 @@ low-level device with a specified ``ops``, :: - static struct snd_device_ops ops = { + static const struct snd_device_ops ops = { .dev_free = snd_mychip_dev_free, }; .... @@ -761,7 +761,7 @@ destructor and PCI entries. Example code is shown first, below. { struct mychip *chip; int err; - static struct snd_device_ops ops = { + static const struct snd_device_ops ops = { .dev_free = snd_mychip_dev_free, }; -- cgit v1.2.3 From d25ff26840bd0af3283d8e478669abc104bb873a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 3 Jan 2020 09:16:44 +0100 Subject: ALSA: info: Make snd_info_entry_ops as const The reference to snd_info_entry_ops is rather read-only, so declare it as a const pointer. This allows a bit more optimization. There should be no functional changes by this patch. Link: https://lore.kernel.org/r/20200103081714.9560-29-tiwai@suse.de Signed-off-by: Takashi Iwai --- Documentation/sound/kernel-api/writing-an-alsa-driver.rst | 2 +- include/sound/info.h | 2 +- sound/drivers/opl4/opl4_proc.c | 2 +- sound/isa/gus/gus_mem_proc.c | 2 +- sound/pci/cs4281.c | 4 ++-- sound/pci/cs46xx/cs46xx_lib.c | 2 +- sound/pci/emu10k1/emuproc.c | 2 +- sound/pci/mixart/mixart.c | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index 7b1ba1e447b9..8204e3b6fea6 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst @@ -3912,7 +3912,7 @@ For a raw-data proc-file, set the attributes as follows: :: - static struct snd_info_entry_ops my_file_io_ops = { + static const struct snd_info_entry_ops my_file_io_ops = { .read = my_file_io_read, }; diff --git a/include/sound/info.h b/include/sound/info.h index b01a22913400..7c13bf52cc81 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -64,7 +64,7 @@ struct snd_info_entry { unsigned short content; union { struct snd_info_entry_text text; - struct snd_info_entry_ops *ops; + const struct snd_info_entry_ops *ops; } c; struct snd_info_entry *parent; struct module *module; diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c index e0516e532969..f2149091e10a 100644 --- a/sound/drivers/opl4/opl4_proc.c +++ b/sound/drivers/opl4/opl4_proc.c @@ -76,7 +76,7 @@ static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry, return count; } -static struct snd_info_entry_ops snd_opl4_mem_proc_ops = { +static const struct snd_info_entry_ops snd_opl4_mem_proc_ops = { .open = snd_opl4_mem_proc_open, .release = snd_opl4_mem_proc_release, .read = snd_opl4_mem_proc_read, diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c index 54510e2d78c2..b5e1d1649500 100644 --- a/sound/isa/gus/gus_mem_proc.c +++ b/sound/isa/gus/gus_mem_proc.c @@ -37,7 +37,7 @@ static void snd_gf1_mem_proc_free(struct snd_info_entry *entry) kfree(priv); } -static struct snd_info_entry_ops snd_gf1_mem_proc_ops = { +static const struct snd_info_entry_ops snd_gf1_mem_proc_ops = { .read = snd_gf1_mem_proc_dump, }; diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 8fd64dab372d..dc89ef906c9b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1129,11 +1129,11 @@ static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry, return count; } -static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { +static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = { .read = snd_cs4281_BA0_read, }; -static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = { +static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = { .read = snd_cs4281_BA1_read, }; diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 3f2fe26efee3..5bb84303f577 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -2815,7 +2815,7 @@ static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry, return count; } -static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { +static const struct snd_info_entry_ops snd_cs46xx_proc_io_ops = { .read = snd_cs46xx_io_read, }; diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index d32f256af809..637446f19598 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c @@ -545,7 +545,7 @@ static void snd_emu_proc_ptr_reg_read20c(struct snd_info_entry *entry, } #endif -static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { +static const struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = { .read = snd_emu10k1_fx8010_read, }; diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 44009c555322..7ba487443c7f 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c @@ -1153,11 +1153,11 @@ static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry, return count; } -static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { +static const struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = { .read = snd_mixart_BA0_read, }; -static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { +static const struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = { .read = snd_mixart_BA1_read, }; -- cgit v1.2.3 From 8ce156deca71808de5884d6cf951688cbf4f4a67 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 3 Dec 2019 10:57:23 +0100 Subject: Documentation: document ioctl interfaces better Documentation/process/botching-up-ioctls.rst was orignally written as a blog post for DRM driver writers, so it it misses some points while going into a lot of detail on others. Try to provide a replacement that addresses typical issues across a wider range of subsystems, and follows the style of the core-api documentation better. Many improvements to the document are suggested by Ben Hutchings , Jonathan Corbet and Geert Uytterhoeven . Reviewed-by: Ben Hutchings Signed-off-by: Arnd Bergmann --- Documentation/core-api/index.rst | 1 + Documentation/core-api/ioctl.rst | 253 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+) create mode 100644 Documentation/core-api/ioctl.rst (limited to 'Documentation') diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index ab0eae1c153a..3f28b2f668be 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -39,6 +39,7 @@ Core utilities ../RCU/index gcc-plugins symbol-namespaces + ioctl Interfaces for kernel debugging diff --git a/Documentation/core-api/ioctl.rst b/Documentation/core-api/ioctl.rst new file mode 100644 index 000000000000..c455db0e1627 --- /dev/null +++ b/Documentation/core-api/ioctl.rst @@ -0,0 +1,253 @@ +====================== +ioctl based interfaces +====================== + +ioctl() is the most common way for applications to interface +with device drivers. It is flexible and easily extended by adding new +commands and can be passed through character devices, block devices as +well as sockets and other special file descriptors. + +However, it is also very easy to get ioctl command definitions wrong, +and hard to fix them later without breaking existing applications, +so this documentation tries to help developers get it right. + +Command number definitions +========================== + +The command number, or request number, is the second argument passed to +the ioctl system call. While this can be any 32-bit number that uniquely +identifies an action for a particular driver, there are a number of +conventions around defining them. + +``include/uapi/asm-generic/ioctl.h`` provides four macros for defining +ioctl commands that follow modern conventions: ``_IO``, ``_IOR``, +``_IOW``, and ``_IOWR``. These should be used for all new commands, +with the correct parameters: + +_IO/_IOR/_IOW/_IOWR + The macro name specifies how the argument will be used.  It may be a + pointer to data to be passed into the kernel (_IOW), out of the kernel + (_IOR), or both (_IOWR).  _IO can indicate either commands with no + argument or those passing an integer value instead of a pointer. + It is recommended to only use _IO for commands without arguments, + and use pointers for passing data. + +type + An 8-bit number, often a character literal, specific to a subsystem + or driver, and listed in :doc:`../userspace-api/ioctl/ioctl-number` + +nr + An 8-bit number identifying the specific command, unique for a give + value of 'type' + +data_type + The name of the data type pointed to by the argument, the command number + encodes the ``sizeof(data_type)`` value in a 13-bit or 14-bit integer, + leading to a limit of 8191 bytes for the maximum size of the argument. + Note: do not pass sizeof(data_type) type into _IOR/_IOW/IOWR, as that + will lead to encoding sizeof(sizeof(data_type)), i.e. sizeof(size_t). + _IO does not have a data_type parameter. + + +Interface versions +================== + +Some subsystems use version numbers in data structures to overload +commands with different interpretations of the argument. + +This is generally a bad idea, since changes to existing commands tend +to break existing applications. + +A better approach is to add a new ioctl command with a new number. The +old command still needs to be implemented in the kernel for compatibility, +but this can be a wrapper around the new implementation. + +Return code +=========== + +ioctl commands can return negative error codes as documented in errno(3); +these get turned into errno values in user space. On success, the return +code should be zero. It is also possible but not recommended to return +a positive 'long' value. + +When the ioctl callback is called with an unknown command number, the +handler returns either -ENOTTY or -ENOIOCTLCMD, which also results in +-ENOTTY being returned from the system call. Some subsystems return +-ENOSYS or -EINVAL here for historic reasons, but this is wrong. + +Prior to Linux 5.5, compat_ioctl handlers were required to return +-ENOIOCTLCMD in order to use the fallback conversion into native +commands. As all subsystems are now responsible for handling compat +mode themselves, this is no longer needed, but it may be important to +consider when backporting bug fixes to older kernels. + +Timestamps +========== + +Traditionally, timestamps and timeout values are passed as ``struct +timespec`` or ``struct timeval``, but these are problematic because of +incompatible definitions of these structures in user space after the +move to 64-bit time_t. + +The ``struct __kernel_timespec`` type can be used instead to be embedded +in other data structures when separate second/nanosecond values are +desired, or passed to user space directly. This is still not ideal though, +as the structure matches neither the kernel's timespec64 nor the user +space timespec exactly. The get_timespec64() and put_timespec64() helper +functions can be used to ensure that the layout remains compatible with +user space and the padding is treated correctly. + +As it is cheap to convert seconds to nanoseconds, but the opposite +requires an expensive 64-bit division, a simple __u64 nanosecond value +can be simpler and more efficient. + +Timeout values and timestamps should ideally use CLOCK_MONOTONIC time, +as returned by ktime_get_ns() or ktime_get_ts64(). Unlike +CLOCK_REALTIME, this makes the timestamps immune from jumping backwards +or forwards due to leap second adjustments and clock_settime() calls. + +ktime_get_real_ns() can be used for CLOCK_REALTIME timestamps that +need to be persistent across a reboot or between multiple machines. + +32-bit compat mode +================== + +In order to support 32-bit user space running on a 64-bit machine, each +subsystem or driver that implements an ioctl callback handler must also +implement the corresponding compat_ioctl handler. + +As long as all the rules for data structures are followed, this is as +easy as setting the .compat_ioctl pointer to a helper function such as +compat_ptr_ioctl() or blkdev_compat_ptr_ioctl(). + +compat_ptr() +------------ + +On the s390 architecture, 31-bit user space has ambiguous representations +for data pointers, with the upper bit being ignored. When running such +a process in compat mode, the compat_ptr() helper must be used to +clear the upper bit of a compat_uptr_t and turn it into a valid 64-bit +pointer. On other architectures, this macro only performs a cast to a +``void __user *`` pointer. + +In an compat_ioctl() callback, the last argument is an unsigned long, +which can be interpreted as either a pointer or a scalar depending on +the command. If it is a scalar, then compat_ptr() must not be used, to +ensure that the 64-bit kernel behaves the same way as a 32-bit kernel +for arguments with the upper bit set. + +The compat_ptr_ioctl() helper can be used in place of a custom +compat_ioctl file operation for drivers that only take arguments that +are pointers to compatible data structures. + +Structure layout +---------------- + +Compatible data structures have the same layout on all architectures, +avoiding all problematic members: + +* ``long`` and ``unsigned long`` are the size of a register, so + they can be either 32-bit or 64-bit wide and cannot be used in portable + data structures. Fixed-length replacements are ``__s32``, ``__u32``, + ``__s64`` and ``__u64``. + +* Pointers have the same problem, in addition to requiring the + use of compat_ptr(). The best workaround is to use ``__u64`` + in place of pointers, which requires a cast to ``uintptr_t`` in user + space, and the use of u64_to_user_ptr() in the kernel to convert + it back into a user pointer. + +* On the x86-32 (i386) architecture, the alignment of 64-bit variables + is only 32-bit, but they are naturally aligned on most other + architectures including x86-64. This means a structure like:: + + struct foo { + __u32 a; + __u64 b; + __u32 c; + }; + + has four bytes of padding between a and b on x86-64, plus another four + bytes of padding at the end, but no padding on i386, and it needs a + compat_ioctl conversion handler to translate between the two formats. + + To avoid this problem, all structures should have their members + naturally aligned, or explicit reserved fields added in place of the + implicit padding. The ``pahole`` tool can be used for checking the + alignment. + +* On ARM OABI user space, structures are padded to multiples of 32-bit, + making some structs incompatible with modern EABI kernels if they + do not end on a 32-bit boundary. + +* On the m68k architecture, struct members are not guaranteed to have an + alignment greater than 16-bit, which is a problem when relying on + implicit padding. + +* Bitfields and enums generally work as one would expect them to, + but some properties of them are implementation-defined, so it is better + to avoid them completely in ioctl interfaces. + +* ``char`` members can be either signed or unsigned, depending on + the architecture, so the __u8 and __s8 types should be used for 8-bit + integer values, though char arrays are clearer for fixed-length strings. + +Information leaks +================= + +Uninitialized data must not be copied back to user space, as this can +cause an information leak, which can be used to defeat kernel address +space layout randomization (KASLR), helping in an attack. + +For this reason (and for compat support) it is best to avoid any +implicit padding in data structures.  Where there is implicit padding +in an existing structure, kernel drivers must be careful to fully +initialize an instance of the structure before copying it to user +space.  This is usually done by calling memset() before assigning to +individual members. + +Subsystem abstractions +====================== + +While some device drivers implement their own ioctl function, most +subsystems implement the same command for multiple drivers. Ideally the +subsystem has an .ioctl() handler that copies the arguments from and +to user space, passing them into subsystem specific callback functions +through normal kernel pointers. + +This helps in various ways: + +* Applications written for one driver are more likely to work for + another one in the same subsystem if there are no subtle differences + in the user space ABI. + +* The complexity of user space access and data structure layout is done + in one place, reducing the potential for implementation bugs. + +* It is more likely to be reviewed by experienced developers + that can spot problems in the interface when the ioctl is shared + between multiple drivers than when it is only used in a single driver. + +Alternatives to ioctl +===================== + +There are many cases in which ioctl is not the best solution for a +problem. Alternatives include: + +* System calls are a better choice for a system-wide feature that + is not tied to a physical device or constrained by the file system + permissions of a character device node + +* netlink is the preferred way of configuring any network related + objects through sockets. + +* debugfs is used for ad-hoc interfaces for debugging functionality + that does not need to be exposed as a stable interface to applications. + +* sysfs is a good way to expose the state of an in-kernel object + that is not tied to a file descriptor. + +* configfs can be used for more complex configuration than sysfs + +* A custom file system can provide extra flexibility with a simple + user interface but adds a lot of complexity to the implementation. -- cgit v1.2.3 From b7ab0cb00d086b690e81589bfb9deccb686a3bda Mon Sep 17 00:00:00 2001 From: Dilip Kota Date: Fri, 3 Jan 2020 18:00:17 +0800 Subject: dt-bindings: reset: Add YAML schemas for the Intel Reset controller Add YAML schemas for the reset controller on Intel Gateway SoC. Signed-off-by: Dilip Kota Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../devicetree/bindings/reset/intel,rcu-gw.yaml | 63 ++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml b/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml new file mode 100644 index 000000000000..246dea8a2ec9 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/intel,rcu-gw.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/reset/intel,rcu-gw.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: System Reset Controller on Intel Gateway SoCs + +maintainers: + - Dilip Kota + +properties: + compatible: + enum: + - intel,rcu-lgm + - intel,rcu-xrx200 + + reg: + description: Reset controller registers. + maxItems: 1 + + intel,global-reset: + description: Global reset register offset and bit offset. + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32-array + - maxItems: 2 + + "#reset-cells": + minimum: 2 + maximum: 3 + description: | + First cell is reset request register offset. + Second cell is bit offset in reset request register. + Third cell is bit offset in reset status register. + For LGM SoC, reset cell count is 2 as bit offset in + reset request and reset status registers is same. Whereas + 3 for legacy SoCs as bit offset differs. + +required: + - compatible + - reg + - intel,global-reset + - "#reset-cells" + +additionalProperties: false + +examples: + - | + rcu0: reset-controller@e0000000 { + compatible = "intel,rcu-lgm"; + reg = <0xe0000000 0x20000>; + intel,global-reset = <0x10 30>; + #reset-cells = <2>; + }; + + pwm: pwm@e0d00000 { + status = "disabled"; + compatible = "intel,lgm-pwm"; + reg = <0xe0d00000 0x30>; + clocks = <&cgu0 1>; + #pwm-cells = <2>; + resets = <&rcu0 0x30 21>; + }; -- cgit v1.2.3 From fd933c00ebe220060e66fb136a7050a242456566 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 27 Aug 2019 11:09:16 +0000 Subject: fbdev: fix numbering of fbcon options Three shall be the number thou shalt count, and the number of the counting shall be three. Four shalt thou not count... One! Two! Five! Fixes: efb985f6b265 ("[PATCH] fbcon: Console Rotation - Add framebuffer console documentation") Signed-off-by: Peter Rosin Reviewed-by: Geert Uytterhoeven Cc: Jonathan Corbet Cc: Matthew Wilcox Signed-off-by: Bartlomiej Zolnierkiewicz Link: https://patchwork.freedesktop.org/patch/msgid/20190827110854.12574-2-peda@axentia.se --- Documentation/fb/fbcon.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/fb/fbcon.rst b/Documentation/fb/fbcon.rst index ebca41785abe..65ba40255137 100644 --- a/Documentation/fb/fbcon.rst +++ b/Documentation/fb/fbcon.rst @@ -127,7 +127,7 @@ C. Boot options is typically located on the same video card. Thus, the consoles that are controlled by the VGA console will be garbled. -4. fbcon=rotate: +5. fbcon=rotate: This option changes the orientation angle of the console display. The value 'n' accepts the following: @@ -152,21 +152,21 @@ C. Boot options Actually, the underlying fb driver is totally ignorant of console rotation. -5. fbcon=margin: +6. fbcon=margin: This option specifies the color of the margins. The margins are the leftover area at the right and the bottom of the screen that are not used by text. By default, this area will be black. The 'color' value is an integer number that depends on the framebuffer driver being used. -6. fbcon=nodefer +7. fbcon=nodefer If the kernel is compiled with deferred fbcon takeover support, normally the framebuffer contents, left in place by the firmware/bootloader, will be preserved until there actually is some text is output to the console. This option causes fbcon to bind immediately to the fbdev device. -7. fbcon=logo-pos: +8. fbcon=logo-pos: The only possible 'location' is 'center' (without quotes), and when given, the bootup logo is moved from the default top-left corner -- cgit v1.2.3 From 691f50ab2742556aea467a946e10393da2e8d9ef Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 27 Aug 2019 11:09:21 +0000 Subject: fbdev: fbmem: allow overriding the number of bootup logos Probably most useful if you want no logo at all, or if you only want one logo regardless of how many CPU cores you have. Signed-off-by: Peter Rosin Reviewed-by: Geert Uytterhoeven Cc: Jonathan Corbet Cc: Matthew Wilcox Signed-off-by: Bartlomiej Zolnierkiewicz Link: https://patchwork.freedesktop.org/patch/msgid/20190827110854.12574-3-peda@axentia.se --- Documentation/fb/fbcon.rst | 5 +++++ drivers/video/fbdev/core/fbcon.c | 7 +++++++ drivers/video/fbdev/core/fbmem.c | 12 +++++++++--- include/linux/fb.h | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/fb/fbcon.rst b/Documentation/fb/fbcon.rst index 65ba40255137..e57a3d1d085a 100644 --- a/Documentation/fb/fbcon.rst +++ b/Documentation/fb/fbcon.rst @@ -174,6 +174,11 @@ C. Boot options displayed due to multiple CPUs, the collected line of logos is moved as a whole. +9. fbcon=logo-count: + + The value 'n' overrides the number of bootup logos. 0 disables the + logo, and -1 gives the default which is the number of online CPUs. + C. Attaching, Detaching and Unloading Before going on to how to attach, detach and unload the framebuffer console, an diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index c9235a2f42f8..bb6ae995c2e5 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -536,6 +536,13 @@ static int __init fb_console_setup(char *this_opt) fb_center_logo = true; continue; } + + if (!strncmp(options, "logo-count:", 11)) { + options += 11; + if (*options) + fb_logo_count = simple_strtol(options, &options, 0); + continue; + } } return 1; } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 7ddeb90337bc..7ce21009f85d 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -56,6 +56,8 @@ EXPORT_SYMBOL(num_registered_fb); bool fb_center_logo __read_mostly; EXPORT_SYMBOL(fb_center_logo); +int fb_logo_count __read_mostly = -1; + static struct fb_info *get_fb_info(unsigned int idx) { struct fb_info *fb_info; @@ -620,7 +622,7 @@ int fb_prepare_logo(struct fb_info *info, int rotate) memset(&fb_logo, 0, sizeof(struct logo_data)); if (info->flags & FBINFO_MISC_TILEBLITTING || - info->fbops->owner) + info->fbops->owner || !fb_logo_count) return 0; if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { @@ -686,10 +688,14 @@ int fb_prepare_logo(struct fb_info *info, int rotate) int fb_show_logo(struct fb_info *info, int rotate) { + unsigned int count; int y; - y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, - num_online_cpus()); + if (!fb_logo_count) + return 0; + + count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count; + y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count); y = fb_show_extra_logos(info, y, rotate); return y; diff --git a/include/linux/fb.h b/include/linux/fb.h index 6557fabdea62..3b4b2f0c6994 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -625,6 +625,7 @@ extern int fb_new_modelist(struct fb_info *info); extern struct fb_info *registered_fb[FB_MAX]; extern int num_registered_fb; extern bool fb_center_logo; +extern int fb_logo_count; extern struct class *fb_class; #define for_each_registered_fb(i) \ -- cgit v1.2.3 From 0d1569a763faef9df0f08c19c31c6aea84a302ff Mon Sep 17 00:00:00 2001 From: Biwen Li Date: Wed, 25 Dec 2019 18:36:22 +0800 Subject: dt-bindings: i2c: support property idle-state This supports property idle-state Reviewed-by: Rob Herring Signed-off-by: Biwen Li Signed-off-by: Peter Rosin --- Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt index 30ac6a60f041..7abda506b828 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mux-pca954x.txt @@ -25,6 +25,8 @@ Required Properties: Optional Properties: - reset-gpios: Reference to the GPIO connected to the reset input. + - idle-state: if present, overrides i2c-mux-idle-disconnect, + Please refer to Documentation/devicetree/bindings/mux/mux-controller.txt - i2c-mux-idle-disconnect: Boolean; if defined, forces mux to disconnect all children in idle state. This is necessary for example, if there are several multiplexers on the bus and the devices behind them use same I2C addresses. -- cgit v1.2.3 From 71e37d2e4b3b9b5ab143ee52f9ebb43e01068594 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 16 Dec 2019 15:14:59 +0100 Subject: media: documentation: fix video_event description The type for the timestamp in video_event was changed to 'long' a long time ago, change the documentation to match. Signed-off-by: Arnd Bergmann Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/uapi/dvb/video-get-event.rst | 2 +- Documentation/media/uapi/dvb/video_types.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/media/uapi/dvb/video-get-event.rst b/Documentation/media/uapi/dvb/video-get-event.rst index def6c40db601..7f03fbe3d3b0 100644 --- a/Documentation/media/uapi/dvb/video-get-event.rst +++ b/Documentation/media/uapi/dvb/video-get-event.rst @@ -81,7 +81,7 @@ for this ioctl call. #define VIDEO_EVENT_FRAME_RATE_CHANGED 2 #define VIDEO_EVENT_DECODER_STOPPED 3 #define VIDEO_EVENT_VSYNC 4 - __kernel_time_t timestamp; + long timestamp; union { video_size_t size; unsigned int frame_rate; /* in frames per 1000sec */ diff --git a/Documentation/media/uapi/dvb/video_types.rst b/Documentation/media/uapi/dvb/video_types.rst index 479942ce6fb8..2697400ccf62 100644 --- a/Documentation/media/uapi/dvb/video_types.rst +++ b/Documentation/media/uapi/dvb/video_types.rst @@ -170,7 +170,7 @@ VIDEO_GET_EVENT call. #define VIDEO_EVENT_FRAME_RATE_CHANGED 2 #define VIDEO_EVENT_DECODER_STOPPED 3 #define VIDEO_EVENT_VSYNC 4 - __kernel_time_t timestamp; + long timestamp; union { video_size_t size; unsigned int frame_rate; /* in frames per 1000sec */ -- cgit v1.2.3 From 79bfa4e737f53ebb8fa0b1fe912889a034f6d92c Mon Sep 17 00:00:00 2001 From: Rijo Thomas Date: Fri, 27 Dec 2019 10:54:03 +0530 Subject: Documentation: tee: add AMD-TEE driver details Update tee.txt with AMD-TEE driver details. The driver is written to communicate with AMD's TEE. Acked-by: Jens Wiklander Co-developed-by: Devaraj Rangasamy Signed-off-by: Devaraj Rangasamy Signed-off-by: Rijo Thomas Reviewed-by: Gary R Hook Signed-off-by: Herbert Xu --- Documentation/tee.txt | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'Documentation') diff --git a/Documentation/tee.txt b/Documentation/tee.txt index afacdf2fd1de..c8fad81c4563 100644 --- a/Documentation/tee.txt +++ b/Documentation/tee.txt @@ -112,6 +112,83 @@ kernel are handled by the kernel driver. Other RPC messages will be forwarded to tee-supplicant without further involvement of the driver, except switching shared memory buffer representation. +AMD-TEE driver +============== + +The AMD-TEE driver handles the communication with AMD's TEE environment. The +TEE environment is provided by AMD Secure Processor. + +The AMD Secure Processor (formerly called Platform Security Processor or PSP) +is a dedicated processor that features ARM TrustZone technology, along with a +software-based Trusted Execution Environment (TEE) designed to enable +third-party Trusted Applications. This feature is currently enabled only for +APUs. + +The following picture shows a high level overview of AMD-TEE:: + + | + x86 | + | + User space (Kernel space) | AMD Secure Processor (PSP) + ~~~~~~~~~~ ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | + +--------+ | +-------------+ + | Client | | | Trusted | + +--------+ | | Application | + /\ | +-------------+ + || | /\ + || | || + || | \/ + || | +----------+ + || | | TEE | + || | | Internal | + \/ | | API | + +---------+ +-----------+---------+ +----------+ + | TEE | | TEE | AMD-TEE | | AMD-TEE | + | Client | | subsystem | driver | | Trusted | + | API | | | | | OS | + +---------+-----------+----+------+---------+---------+----------+ + | Generic TEE API | | ASP | Mailbox | + | IOCTL (TEE_IOC_*) | | driver | Register Protocol | + +--------------------------+ +---------+--------------------+ + +At the lowest level (in x86), the AMD Secure Processor (ASP) driver uses the +CPU to PSP mailbox regsister to submit commands to the PSP. The format of the +command buffer is opaque to the ASP driver. It's role is to submit commands to +the secure processor and return results to AMD-TEE driver. The interface +between AMD-TEE driver and AMD Secure Processor driver can be found in [6]. + +The AMD-TEE driver packages the command buffer payload for processing in TEE. +The command buffer format for the different TEE commands can be found in [7]. + +The TEE commands supported by AMD-TEE Trusted OS are: +* TEE_CMD_ID_LOAD_TA - loads a Trusted Application (TA) binary into + TEE environment. +* TEE_CMD_ID_UNLOAD_TA - unloads TA binary from TEE environment. +* TEE_CMD_ID_OPEN_SESSION - opens a session with a loaded TA. +* TEE_CMD_ID_CLOSE_SESSION - closes session with loaded TA +* TEE_CMD_ID_INVOKE_CMD - invokes a command with loaded TA +* TEE_CMD_ID_MAP_SHARED_MEM - maps shared memory +* TEE_CMD_ID_UNMAP_SHARED_MEM - unmaps shared memory + +AMD-TEE Trusted OS is the firmware running on AMD Secure Processor. + +The AMD-TEE driver registers itself with TEE subsystem and implements the +following driver function callbacks: + +* get_version - returns the driver implementation id and capability. +* open - sets up the driver context data structure. +* release - frees up driver resources. +* open_session - loads the TA binary and opens session with loaded TA. +* close_session - closes session with loaded TA and unloads it. +* invoke_func - invokes a command with loaded TA. + +cancel_req driver callback is not supported by AMD-TEE. + +The GlobalPlatform TEE Client API [5] can be used by the user space (client) to +talk to AMD's TEE. AMD's TEE provides a secure environment for loading, opening +a session, invoking commands and clossing session with TA. + References ========== @@ -125,3 +202,7 @@ References [5] http://www.globalplatform.org/specificationsdevice.asp look for "TEE Client API Specification v1.0" and click download. + +[6] include/linux/psp-tee.h + +[7] drivers/tee/amdtee/amdtee_if.h -- cgit v1.2.3 From e878742c83ec26ef256ebb6b36a4d44644548f25 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Mon, 30 Dec 2019 10:26:25 +0100 Subject: media: staging/intel-ipu3: make imgu use fixed running mode Currently, the imgu running mode need user to set by v4l2 ctrl. However, imgu only support 2 pipes and 2 operation modes - video and still. This patch make the first imgu subdev running as video and second one running as still, it will make the user understand easily, it can also cover current camera use cases requirement. The running mode is set during subdev registering, no race-condition after change, so it is safe to change the mode data type to integer. Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/media/v4l-drivers/ipu3.rst | 6 +- drivers/staging/media/ipu3/include/intel-ipu3.h | 4 -- drivers/staging/media/ipu3/ipu3-v4l2.c | 74 +++---------------------- drivers/staging/media/ipu3/ipu3.h | 5 +- 4 files changed, 12 insertions(+), 77 deletions(-) (limited to 'Documentation') diff --git a/Documentation/media/v4l-drivers/ipu3.rst b/Documentation/media/v4l-drivers/ipu3.rst index e4904ab44e60..50bd264a3408 100644 --- a/Documentation/media/v4l-drivers/ipu3.rst +++ b/Documentation/media/v4l-drivers/ipu3.rst @@ -234,9 +234,9 @@ The IPU3 ImgU pipelines can be configured using the Media Controller, defined at Firmware binary selection ------------------------- -The firmware binary is selected using the V4L2_CID_INTEL_IPU3_MODE, currently -defined in drivers/staging/media/ipu3/include/intel-ipu3.h . "VIDEO" and "STILL" -modes are available. +The firmware binary is selected according to the running mode of imgu. There are +2 modes are available - "video" and "still". "ipu3-imgu video" are running under +"video" mode and "ipu3-imgu still" is running under "still" mode. Processing the image in raw Bayer format ---------------------------------------- diff --git a/drivers/staging/media/ipu3/include/intel-ipu3.h b/drivers/staging/media/ipu3/include/intel-ipu3.h index 08eaa0bad0de..d30d9d6c92db 100644 --- a/drivers/staging/media/ipu3/include/intel-ipu3.h +++ b/drivers/staging/media/ipu3/include/intel-ipu3.h @@ -12,10 +12,6 @@ #define V4L2_META_FMT_IPU3_PARAMS v4l2_fourcc('i', 'p', '3', 'p') /* IPU3 processing parameters */ #define V4L2_META_FMT_IPU3_STAT_3A v4l2_fourcc('i', 'p', '3', 's') /* IPU3 3A statistics */ -/* from include/uapi/linux/v4l2-controls.h */ -#define V4L2_CID_INTEL_IPU3_BASE (V4L2_CID_USER_BASE + 0x10c0) -#define V4L2_CID_INTEL_IPU3_MODE (V4L2_CID_INTEL_IPU3_BASE + 1) - /******************* ipu3_uapi_stats_3a *******************/ #define IPU3_UAPI_MAX_STRIPES 2 diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c index 569e27b824c8..45de77baf080 100644 --- a/drivers/staging/media/ipu3/ipu3-v4l2.c +++ b/drivers/staging/media/ipu3/ipu3-v4l2.c @@ -67,8 +67,6 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable) struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe]; dev_dbg(dev, "%s %d for pipe %u", __func__, enable, pipe); - /* grab ctrl after streamon and return after off */ - v4l2_ctrl_grab(imgu_sd->ctrl, enable); if (!enable) { imgu_sd->active = false; @@ -96,7 +94,7 @@ static int imgu_subdev_s_stream(struct v4l2_subdev *sd, int enable) if (imgu_pipe->nodes[IMGU_NODE_VF].enabled) css_pipe->vf_output_en = true; - if (atomic_read(&imgu_sd->running_mode) == IPU3_RUNNING_MODE_VIDEO) + if (imgu_sd->running_mode == IPU3_RUNNING_MODE_VIDEO) css_pipe->pipe_id = IPU3_CSS_PIPE_ID_VIDEO; else css_pipe->pipe_id = IPU3_CSS_PIPE_ID_CAPTURE; @@ -668,7 +666,7 @@ static int imgu_fmt(struct imgu_device *imgu, unsigned int pipe, int node, if (imgu_pipe->nodes[IMGU_NODE_VF].enabled) css_pipe->vf_output_en = true; - if (atomic_read(&imgu_sd->running_mode) == IPU3_RUNNING_MODE_VIDEO) + if (imgu_sd->running_mode == IPU3_RUNNING_MODE_VIDEO) css_pipe->pipe_id = IPU3_CSS_PIPE_ID_VIDEO; else css_pipe->pipe_id = IPU3_CSS_PIPE_ID_CAPTURE; @@ -899,11 +897,6 @@ static struct v4l2_subdev_internal_ops imgu_subdev_internal_ops = { .open = imgu_subdev_open, }; -static const struct v4l2_subdev_core_ops imgu_subdev_core_ops = { - .subscribe_event = v4l2_ctrl_subdev_subscribe_event, - .unsubscribe_event = v4l2_event_subdev_unsubscribe, -}; - static const struct v4l2_subdev_video_ops imgu_subdev_video_ops = { .s_stream = imgu_subdev_s_stream, }; @@ -917,7 +910,6 @@ static const struct v4l2_subdev_pad_ops imgu_subdev_pad_ops = { }; static const struct v4l2_subdev_ops imgu_subdev_ops = { - .core = &imgu_subdev_core_ops, .video = &imgu_subdev_video_ops, .pad = &imgu_subdev_pad_ops, }; @@ -1011,44 +1003,6 @@ static const struct v4l2_ioctl_ops imgu_v4l2_meta_ioctl_ops = { .vidioc_expbuf = vb2_ioctl_expbuf, }; -static int imgu_sd_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct imgu_v4l2_subdev *imgu_sd = - container_of(ctrl->handler, struct imgu_v4l2_subdev, ctrl_handler); - struct imgu_device *imgu = v4l2_get_subdevdata(&imgu_sd->subdev); - struct device *dev = &imgu->pci_dev->dev; - - dev_dbg(dev, "set val %d to ctrl 0x%8x for subdev %u", - ctrl->val, ctrl->id, imgu_sd->pipe); - - switch (ctrl->id) { - case V4L2_CID_INTEL_IPU3_MODE: - atomic_set(&imgu_sd->running_mode, ctrl->val); - return 0; - default: - return -EINVAL; - } -} - -static const struct v4l2_ctrl_ops imgu_subdev_ctrl_ops = { - .s_ctrl = imgu_sd_s_ctrl, -}; - -static const char * const imgu_ctrl_mode_strings[] = { - "Video mode", - "Still mode", -}; - -static const struct v4l2_ctrl_config imgu_subdev_ctrl_mode = { - .ops = &imgu_subdev_ctrl_ops, - .id = V4L2_CID_INTEL_IPU3_MODE, - .name = "IPU3 Pipe Mode", - .type = V4L2_CTRL_TYPE_MENU, - .max = ARRAY_SIZE(imgu_ctrl_mode_strings) - 1, - .def = IPU3_RUNNING_MODE_VIDEO, - .qmenu = imgu_ctrl_mode_strings, -}; - /******************** Framework registration ********************/ /* helper function to config node's video properties */ @@ -1094,7 +1048,6 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu, unsigned int pipe) { int i, r; - struct v4l2_ctrl_handler *hdl = &imgu_sd->ctrl_handler; struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe]; /* Initialize subdev media entity */ @@ -1115,21 +1068,12 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu, v4l2_subdev_init(&imgu_sd->subdev, &imgu_subdev_ops); imgu_sd->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_STATISTICS; imgu_sd->subdev.internal_ops = &imgu_subdev_internal_ops; - imgu_sd->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | - V4L2_SUBDEV_FL_HAS_EVENTS; + imgu_sd->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(imgu_sd->subdev.name, sizeof(imgu_sd->subdev.name), - "%s %u", IMGU_NAME, pipe); + "%s %s", IMGU_NAME, pipe ? "still" : "video"); v4l2_set_subdevdata(&imgu_sd->subdev, imgu); - atomic_set(&imgu_sd->running_mode, IPU3_RUNNING_MODE_VIDEO); - v4l2_ctrl_handler_init(hdl, 1); - imgu_sd->subdev.ctrl_handler = hdl; - imgu_sd->ctrl = v4l2_ctrl_new_custom(hdl, &imgu_subdev_ctrl_mode, NULL); - if (hdl->error) { - r = hdl->error; - dev_err(&imgu->pci_dev->dev, - "failed to create subdev v4l2 ctrl with err %d", r); - goto fail_subdev; - } + imgu_sd->running_mode = + pipe ? IPU3_RUNNING_MODE_STILL : IPU3_RUNNING_MODE_VIDEO; r = v4l2_device_register_subdev(&imgu->v4l2_dev, &imgu_sd->subdev); if (r) { dev_err(&imgu->pci_dev->dev, @@ -1141,7 +1085,6 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu, return 0; fail_subdev: - v4l2_ctrl_handler_free(imgu_sd->subdev.ctrl_handler); media_entity_cleanup(&imgu_sd->subdev.entity); return r; @@ -1236,8 +1179,8 @@ static int imgu_v4l2_node_setup(struct imgu_device *imgu, unsigned int pipe, } /* Initialize vdev */ - snprintf(vdev->name, sizeof(vdev->name), "%s %u %s", - IMGU_NAME, pipe, node->name); + snprintf(vdev->name, sizeof(vdev->name), "%s %s %s", + IMGU_NAME, pipe ? "still" : "video", node->name); vdev->release = video_device_release_empty; vdev->fops = &imgu_v4l2_fops; vdev->lock = &node->lock; @@ -1312,7 +1255,6 @@ static void imgu_v4l2_subdev_cleanup(struct imgu_device *imgu, unsigned int i) struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[i]; v4l2_device_unregister_subdev(&imgu_pipe->imgu_sd.subdev); - v4l2_ctrl_handler_free(imgu_pipe->imgu_sd.subdev.ctrl_handler); media_entity_cleanup(&imgu_pipe->imgu_sd.subdev.entity); } diff --git a/drivers/staging/media/ipu3/ipu3.h b/drivers/staging/media/ipu3/ipu3.h index 73b123b2b8a2..de02a244732e 100644 --- a/drivers/staging/media/ipu3/ipu3.h +++ b/drivers/staging/media/ipu3/ipu3.h @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -96,9 +95,7 @@ struct imgu_v4l2_subdev { struct v4l2_rect bds; /* bayer-domain scaled resolution*/ struct v4l2_rect gdc; /* gdc output resolution */ } rect; - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_ctrl *ctrl; - atomic_t running_mode; + unsigned int running_mode; bool active; }; -- cgit v1.2.3 From 1de243b0766679e75f558943250614ccd3f60121 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 15 Dec 2019 17:59:11 +0100 Subject: media: dt-bindings: media: sun4i-csi: Add compatible for CSI1 on A10/A20 The CSI1 block has the same structure and layout as the CSI0 block. Differences include: - Only one channel in BT.656 instead of four in CSI0 - 10-bit raw data input vs 8-bit in CSI0 - 24-bit RGB888/YUV444 input vs 16-bit RGB565/YUV422 in CSI0 - No ISP hardware The hardware found in the A20 is the same as in the A10. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml index d3e423fcb6c2..221fe630c7d5 100644 --- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml @@ -16,7 +16,12 @@ description: |- properties: compatible: - const: allwinner,sun7i-a20-csi0 + oneOf: + - const: allwinner,sun4i-a10-csi1 + - const: allwinner,sun7i-a20-csi0 + - items: + - const: allwinner,sun7i-a20-csi1 + - const: allwinner,sun4i-a10-csi1 reg: maxItems: 1 @@ -25,12 +30,16 @@ properties: maxItems: 1 clocks: + minItems: 2 + maxItems: 3 items: - description: The CSI interface clock - description: The CSI ISP clock - description: The CSI DRAM clock clock-names: + minItems: 2 + maxItems: 3 items: - const: bus - const: isp -- cgit v1.2.3 From 7866d6903ce88b1b359202f4be0422aa6a70a4a2 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sun, 15 Dec 2019 17:59:12 +0100 Subject: media: dt-bindings: media: sun4i-csi: Add compatible for CSI0 on R40 The CSI0 block in the Allwinner R40 SoC looks to be the same as the one in the A20. The register maps line up, and they support the same features. The R40 appears to support BT.1120 based on the feature overview, but it is not mentioned anywhere else. Also like the A20, the ISP is not mentioned, but the CSI special clock needs to be enabled for the hardware to function. The manual does state that the CSI special clock is the TOP clock for all CSI hardware, but currently no hardware exists for us to test if CSI1 also depends on it or not. Add a compatible string for the CSI0 block in the R40, with the A20 compatible string as a fallback. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml index 221fe630c7d5..d486321b13f5 100644 --- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml @@ -22,6 +22,9 @@ properties: - items: - const: allwinner,sun7i-a20-csi1 - const: allwinner,sun4i-a10-csi1 + - items: + - const: allwinner,sun8i-r40-csi0 + - const: allwinner,sun7i-a20-csi0 reg: maxItems: 1 -- cgit v1.2.3 From 8b17fb9628dd91cf48b8d40fba4b4f7499bf2ee7 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 15 Dec 2019 21:52:53 +0300 Subject: dt-bindings: net: broadcom-bluetooth: Document BCM4329 support The BCM4329 is a 802.11 a/b/g/n WiFi + Bluetooth 2.1 chip which is found in Azurewave AW-NH611 WiFi+BT module. Signed-off-by: Dmitry Osipenko Signed-off-by: Marcel Holtmann --- Documentation/devicetree/bindings/net/broadcom-bluetooth.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt index b5eadee4a9a7..c44a30dbe43d 100644 --- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt +++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt @@ -11,6 +11,7 @@ Required properties: - compatible: should contain one of the following: * "brcm,bcm20702a1" + * "brcm,bcm4329-bt" * "brcm,bcm4330-bt" * "brcm,bcm43438-bt" * "brcm,bcm4345c5" -- cgit v1.2.3 From 3862c824de3aa73be5a5ba716f6df8085cc67473 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 24 Dec 2019 12:29:05 +0100 Subject: dt-bindings: Add vendor prefix for Xinpeng Technology Shenzhen Xinpeng Technology Co., Ltd produces for example display panels. Signed-off-by: Heiko Stuebner Acked-by: Sam Ravnborg Acked-by: Rob Herring Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191224112907.30758-1-heiko@sntech.de --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 967e78c5ec0a..d7c5c47dc47c 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1050,6 +1050,8 @@ patternProperties: description: Extreme Engineering Solutions (X-ES) "^xillybus,.*": description: Xillybus Ltd. + "^xinpeng,.*": + description: Shenzhen Xinpeng Technology Co., Ltd "^xlnx,.*": description: Xilinx "^xunlong,.*": -- cgit v1.2.3 From 01d53e327dabff04859f76e2917fd95ef1844d3e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 24 Dec 2019 12:29:06 +0100 Subject: dt-bindings: display: panel: Add binding document for Xinpeng XPP055C272 The XPP055C272 is a 5.5" 720x1280 DSI display. changes in v4: - fix id (Maxime) - drop port (Maxime) changes in v2: - add size info into binding title (Sam) - add more required properties (Sam) Signed-off-by: Heiko Stuebner Reviewed-by: Sam Ravnborg Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191224112907.30758-2-heiko@sntech.de --- .../bindings/display/panel/xinpeng,xpp055c272.yaml | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml b/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml new file mode 100644 index 000000000000..378cf9e2549d --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/xinpeng,xpp055c272.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xinpeng XPP055C272 5.5in 720x1280 DSI panel + +maintainers: + - Heiko Stuebner + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: xinpeng,xpp055c272 + reg: true + backlight: true + reset-gpios: true + iovcc-supply: + description: regulator that supplies the iovcc voltage + vci-supply: + description: regulator that supplies the vci voltage + +required: + - compatible + - reg + - backlight + - iovcc-supply + - vci-supply + +additionalProperties: false + +examples: + - | + dsi@ff450000 { + panel@0 { + compatible = "xinpeng,xpp055c272"; + reg = <0>; + backlight = <&backlight>; + iovcc-supply = <&vcc_1v8>; + vci-supply = <&vcc3v3_lcd>; + }; + }; + +... -- cgit v1.2.3 From e8d47c471b990db1459f386276089c4893ad28d4 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 24 Dec 2019 12:26:39 +0100 Subject: dt-bindings: Add vendor prefix for Leadtek Technology Shenzhen Leadtek Technology Co., Ltd. produces for example display and touch panels. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191224112641.30647-1-heiko@sntech.de --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index d7c5c47dc47c..2dd835af0994 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -511,6 +511,8 @@ patternProperties: description: Lantiq Semiconductor "^lattice,.*": description: Lattice Semiconductor + "^leadtek,.*": + description: Shenzhen Leadtek Technology Co., Ltd. "^leez,.*": description: Leez "^lego,.*": -- cgit v1.2.3 From eeb15a55d22bacc49814bfccf43e2397e6e5f476 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 24 Dec 2019 12:26:40 +0100 Subject: dt-bindings: display: panel: Add binding document for Leadtek LTK500HD1829 The LTK500HD1829 is a 5.0" 720x1280 DSI display. v3: - fixed example by adding address,size-cells (sam) changes in v2: - fix id (Maxime) - drop port (Maxime) Signed-off-by: Heiko Stuebner Acked-by: Maxime Ripard Reviewed-by: Rob Herring Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20191224112641.30647-2-heiko@sntech.de --- .../display/panel/leadtek,ltk500hd1829.yaml | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml b/Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml new file mode 100644 index 000000000000..4ebcea7d0c63 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/leadtek,ltk500hd1829.yaml @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/leadtek,ltk500hd1829.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Leadtek LTK500HD1829 5.0in 720x1280 DSI panel + +maintainers: + - Heiko Stuebner + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + const: leadtek,ltk500hd1829 + reg: true + backlight: true + reset-gpios: true + iovcc-supply: + description: regulator that supplies the iovcc voltage + vcc-supply: + description: regulator that supplies the vcc voltage + +required: + - compatible + - reg + - backlight + - iovcc-supply + - vcc-supply + +additionalProperties: false + +examples: + - | + dsi@ff450000 { + #address-cells = <1>; + #size-cells = <0>; + panel@0 { + compatible = "leadtek,ltk500hd1829"; + reg = <0>; + backlight = <&backlight>; + iovcc-supply = <&vcc_1v8>; + vcc-supply = <&vcc_2v8>; + }; + }; + +... -- cgit v1.2.3 From c17fc0c924aabbb6c9637770173659e11e0afbda Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 28 Dec 2019 10:30:58 +0100 Subject: dt-bindings: mmc: remove identical phrase in disable-wp text There are two identical phrases in the disable-wp text, so remove one of them. Signed-off-by: Johan Jonker Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mmc/mmc-controller.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index b130450c3b34..d668d0fbea75 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -96,8 +96,7 @@ properties: description: When set, no physical write-protect line is present. This property should only be specified when the controller has a - dedicated write-protect detection logic. If a GPIO is always - used for the write-protect detection. If a GPIO is always used + dedicated write-protect detection logic. If a GPIO is always used for the write-protect detection logic, it is sufficient to not specify the wp-gpios property in the absence of a write-protect line. -- cgit v1.2.3 From 6d7a1c83dc09bae02a5a87ffc64038f7695ac3c2 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sat, 28 Dec 2019 10:30:59 +0100 Subject: dt-bindings: mmc: clarify disable-wp text "disable-wp" has been removed from all Rockchip eMMC and SDIO dts nodes, but people still continue to submit new patches with "disable-wp" added to other nodes then for the SD card slot, what it was designed for in the first place. So clarify the "disable-wp" text by adding that this option should not be used in combination with eMMC or SDIO. Signed-off-by: Johan Jonker Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mmc/mmc-controller.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index d668d0fbea75..3c0df4016a12 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -99,7 +99,7 @@ properties: dedicated write-protect detection logic. If a GPIO is always used for the write-protect detection logic, it is sufficient to not specify the wp-gpios property in the absence of a write-protect - line. + line. Not used in combination with eMMC or SDIO. wp-gpios: description: -- cgit v1.2.3 From 5c6f3a36b913b24a0628a1cd6afd83eb8e73769c Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 27 Dec 2019 12:08:29 +0530 Subject: dt-bindings: clock: Add YAML schemas for the QCOM GPUCC clock bindings The GPUCC clock provider have a bunch of generic properties that are needed in a device tree. Add a YAML schemas for those. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/1577428714-17766-2-git-send-email-tdas@codeaurora.org Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gpucc.txt | 24 -------- .../devicetree/bindings/clock/qcom,gpucc.yaml | 71 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 24 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,gpucc.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,gpucc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt b/Documentation/devicetree/bindings/clock/qcom,gpucc.txt deleted file mode 100644 index 269afe8a757e..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,gpucc.txt +++ /dev/null @@ -1,24 +0,0 @@ -Qualcomm Graphics Clock & Reset Controller Binding --------------------------------------------------- - -Required properties : -- compatible : shall contain "qcom,sdm845-gpucc" or "qcom,msm8998-gpucc" -- reg : shall contain base register location and length -- #clock-cells : from common clock binding, shall contain 1 -- #reset-cells : from common reset binding, shall contain 1 -- #power-domain-cells : from generic power domain binding, shall contain 1 -- clocks : shall contain the XO clock - shall contain the gpll0 out main clock (msm8998) -- clock-names : shall be "xo" - shall be "gpll0" (msm8998) - -Example: - gpucc: clock-controller@5090000 { - compatible = "qcom,sdm845-gpucc"; - reg = <0x5090000 0x9000>; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - clocks = <&rpmhcc RPMH_CXO_CLK>; - clock-names = "xo"; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml new file mode 100644 index 000000000000..993913da8a0d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/qcom,gpucc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Graphics Clock & Reset Controller Binding + +maintainers: + - Taniya Das + +description: | + Qualcomm grpahics clock control module which supports the clocks, resets and + power domains. + +properties: + compatible: + enum: + - qcom,msm8998-gpucc + - qcom,sdm845-gpucc + + clocks: + minItems: 1 + maxItems: 3 + items: + - description: Board XO source + - description: GPLL0 main branch source from GCC(gcc_gpu_gpll0_clk_src) + - description: GPLL0 div branch source from GCC(gcc_gpu_gpll0_div_clk_src) + + clock-names: + minItems: 1 + maxItems: 3 + items: + - const: xo + - const: gpll0_main + - const: gpll0_div + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +examples: + # Example of GPUCC with clock node properties for SDM845: + - | + clock-controller@5090000 { + compatible = "qcom,sdm845-gpucc"; + reg = <0x5090000 0x9000>; + clocks = <&rpmhcc 0>, <&gcc 31>, <&gcc 32>; + clock-names = "xo", "gpll0_main", "gpll0_div"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... -- cgit v1.2.3 From 468e727d18cb3e8b8d817d8bb12cb897ae948bd2 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 27 Dec 2019 12:08:30 +0530 Subject: dt-bindings: clock: Introduce SC7180 QCOM Graphics clock bindings Add device tree bindings for graphics clock controller for Qualcomm Technology Inc's SC7180 SoCs. Signed-off-by: Taniya Das Reviewed-by: Rob Herring Link: https://lkml.kernel.org/r/1577428714-17766-3-git-send-email-tdas@codeaurora.org [sboyd@kernel.org: Indicate sc7180 in commit subject] Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gpucc.yaml | 1 + include/dt-bindings/clock/qcom,gpucc-sc7180.h | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,gpucc-sc7180.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml index 993913da8a0d..622845aa643f 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml @@ -17,6 +17,7 @@ properties: compatible: enum: - qcom,msm8998-gpucc + - qcom,sc7180-gpucc - qcom,sdm845-gpucc clocks: diff --git a/include/dt-bindings/clock/qcom,gpucc-sc7180.h b/include/dt-bindings/clock/qcom,gpucc-sc7180.h new file mode 100644 index 000000000000..0e4643b08b49 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gpucc-sc7180.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SC7180_H +#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SC7180_H + +#define GPU_CC_PLL1 0 +#define GPU_CC_AHB_CLK 1 +#define GPU_CC_CRC_AHB_CLK 2 +#define GPU_CC_CX_GMU_CLK 3 +#define GPU_CC_CX_SNOC_DVM_CLK 4 +#define GPU_CC_CXO_AON_CLK 5 +#define GPU_CC_CXO_CLK 6 +#define GPU_CC_GMU_CLK_SRC 7 + +/* CAM_CC GDSCRs */ +#define CX_GDSC 0 + +#endif -- cgit v1.2.3 From 35d26e9292e2e18e38a290e86ceba1842f94c522 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 27 Dec 2019 12:08:32 +0530 Subject: dt-bindings: clock: Add YAML schemas for the QCOM VIDEOCC clock bindings The VIDEOCC clock provider have a bunch of generic properties that are needed in a device tree. Add a YAML schemas for those. Signed-off-by: Taniya Das Reviewed-by: Rob Herring Link: https://lkml.kernel.org/r/1577428714-17766-5-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,videocc.txt | 18 ------- .../devicetree/bindings/clock/qcom,videocc.yaml | 61 ++++++++++++++++++++++ 2 files changed, 61 insertions(+), 18 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,videocc.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,videocc.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.txt b/Documentation/devicetree/bindings/clock/qcom,videocc.txt deleted file mode 100644 index 8a8622c65c5a..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,videocc.txt +++ /dev/null @@ -1,18 +0,0 @@ -Qualcomm Video Clock & Reset Controller Binding ------------------------------------------------ - -Required properties : -- compatible : shall contain "qcom,sdm845-videocc" -- reg : shall contain base register location and length -- #clock-cells : from common clock binding, shall contain 1. -- #power-domain-cells : from generic power domain binding, shall contain 1. -- #reset-cells : from common reset binding, shall contain 1. - -Example: - videocc: clock-controller@ab00000 { - compatible = "qcom,sdm845-videocc"; - reg = <0xab00000 0x10000>; - #clock-cells = <1>; - #power-domain-cells = <1>; - #reset-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml new file mode 100644 index 000000000000..fc3fcca61034 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/clock/qcom,videocc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Video Clock & Reset Controller Binding + +maintainers: + - Taniya Das + +description: | + Qualcomm video clock control module which supports the clocks, resets and + power domains. + +properties: + compatible: + enum: + - qcom,sdm845-videocc + + clocks: + maxItems: 1 + + clock-names: + items: + - const: xo + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +examples: + # Example of VIDEOCC with clock node properties for SDM845: + - | + clock-controller@ab00000 { + compatible = "qcom,sdm845-videocc"; + reg = <0xab00000 0x10000>; + clocks = <&rpmhcc 0>; + clock-names = "xo"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... -- cgit v1.2.3 From 4cc62ebd0cd8a061331b4e013193621605f2e63b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 27 Dec 2019 12:08:33 +0530 Subject: dt-bindings: clock: Introduce SC7180 QCOM Video clock bindings Add device tree bindings for video clock controller for Qualcomm Technology Inc's SC7180 SoCs. Signed-off-by: Taniya Das Reviewed-by: Rob Herring Link: https://lkml.kernel.org/r/1577428714-17766-6-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,videocc.yaml | 1 + include/dt-bindings/clock/qcom,videocc-sc7180.h | 23 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 include/dt-bindings/clock/qcom,videocc-sc7180.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml index fc3fcca61034..43cfc893a8d1 100644 --- a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml @@ -16,6 +16,7 @@ description: | properties: compatible: enum: + - qcom,sc7180-videocc - qcom,sdm845-videocc clocks: diff --git a/include/dt-bindings/clock/qcom,videocc-sc7180.h b/include/dt-bindings/clock/qcom,videocc-sc7180.h new file mode 100644 index 000000000000..7acaf1366b13 --- /dev/null +++ b/include/dt-bindings/clock/qcom,videocc-sc7180.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SC7180_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SC7180_H + +/* VIDEO_CC clocks */ +#define VIDEO_PLL0 0 +#define VIDEO_CC_VCODEC0_AXI_CLK 1 +#define VIDEO_CC_VCODEC0_CORE_CLK 2 +#define VIDEO_CC_VENUS_AHB_CLK 3 +#define VIDEO_CC_VENUS_CLK_SRC 4 +#define VIDEO_CC_VENUS_CTL_AXI_CLK 5 +#define VIDEO_CC_VENUS_CTL_CORE_CLK 6 +#define VIDEO_CC_XO_CLK 7 + +/* VIDEO_CC GDSCRs */ +#define VENUS_GDSC 0 +#define VCODEC0_GDSC 1 + +#endif -- cgit v1.2.3 From 461e58f034e5fbbcb9884b4fa6001831e5bd485c Mon Sep 17 00:00:00 2001 From: Sibi Sankar Date: Fri, 20 Dec 2019 12:18:22 +0530 Subject: dt-bindings: power: rpmpd: Convert rpmpd bindings to yaml Convert RPM/RPMH power-domain bindings to yaml. Reviewed-by: Rajendra Nayak Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Signed-off-by: Sibi Sankar Link: https://lore.kernel.org/r/20191220064823.6115-2-sibis@codeaurora.org Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/power/qcom,rpmpd.txt | 150 ------------------ .../devicetree/bindings/power/qcom,rpmpd.yaml | 170 +++++++++++++++++++++ 2 files changed, 170 insertions(+), 150 deletions(-) delete mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.txt create mode 100644 Documentation/devicetree/bindings/power/qcom,rpmpd.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt b/Documentation/devicetree/bindings/power/qcom,rpmpd.txt deleted file mode 100644 index 6346d00b1b40..000000000000 --- a/Documentation/devicetree/bindings/power/qcom,rpmpd.txt +++ /dev/null @@ -1,150 +0,0 @@ -Qualcomm RPM/RPMh Power domains - -For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh -which then translates it into a corresponding voltage on a rail - -Required Properties: - - compatible: Should be one of the following - * qcom,msm8976-rpmpd: RPM Power domain for the msm8976 family of SoC - * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC - * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC - * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC - * qcom,sc7180-rpmhpd: RPMh Power domain for the sc7180 family of SoC - * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC - * qcom,sm8150-rpmhpd: RPMh Power domain for the sm8150 family of SoC - - #power-domain-cells: number of cells in Power domain specifier - must be 1. - - operating-points-v2: Phandle to the OPP table for the Power domain. - Refer to Documentation/devicetree/bindings/power/power_domain.txt - and Documentation/devicetree/bindings/opp/opp.txt for more details - -Refer to for the level values for -various OPPs for different platforms as well as Power domain indexes - -Example: rpmh power domain controller and OPP table - -#include - -opp-level values specified in the OPP tables for RPMh power domains -should use the RPMH_REGULATOR_LEVEL_* constants from - - - rpmhpd: power-controller { - compatible = "qcom,sdm845-rpmhpd"; - #power-domain-cells = <1>; - operating-points-v2 = <&rpmhpd_opp_table>; - - rpmhpd_opp_table: opp-table { - compatible = "operating-points-v2"; - - rpmhpd_opp_ret: opp1 { - opp-level = ; - }; - - rpmhpd_opp_min_svs: opp2 { - opp-level = ; - }; - - rpmhpd_opp_low_svs: opp3 { - opp-level = ; - }; - - rpmhpd_opp_svs: opp4 { - opp-level = ; - }; - - rpmhpd_opp_svs_l1: opp5 { - opp-level = ; - }; - - rpmhpd_opp_nom: opp6 { - opp-level = ; - }; - - rpmhpd_opp_nom_l1: opp7 { - opp-level = ; - }; - - rpmhpd_opp_nom_l2: opp8 { - opp-level = ; - }; - - rpmhpd_opp_turbo: opp9 { - opp-level = ; - }; - - rpmhpd_opp_turbo_l1: opp10 { - opp-level = ; - }; - }; - }; - -Example: rpm power domain controller and OPP table - - rpmpd: power-controller { - compatible = "qcom,msm8996-rpmpd"; - #power-domain-cells = <1>; - operating-points-v2 = <&rpmpd_opp_table>; - - rpmpd_opp_table: opp-table { - compatible = "operating-points-v2"; - - rpmpd_opp_low: opp1 { - opp-level = <1>; - }; - - rpmpd_opp_ret: opp2 { - opp-level = <2>; - }; - - rpmpd_opp_svs: opp3 { - opp-level = <3>; - }; - - rpmpd_opp_normal: opp4 { - opp-level = <4>; - }; - - rpmpd_opp_high: opp5 { - opp-level = <5>; - }; - - rpmpd_opp_turbo: opp6 { - opp-level = <6>; - }; - }; - }; - -Example: Client/Consumer device using OPP table - - leaky-device0@12350000 { - compatible = "foo,i-leak-current"; - reg = <0x12350000 0x1000>; - power-domains = <&rpmhpd SDM845_MX>; - operating-points-v2 = <&leaky_opp_table>; - }; - - - leaky_opp_table: opp-table { - compatible = "operating-points-v2"; - - opp1 { - opp-hz = /bits/ 64 <144000>; - required-opps = <&rpmhpd_opp_low>; - }; - - opp2 { - opp-hz = /bits/ 64 <400000>; - required-opps = <&rpmhpd_opp_ret>; - }; - - opp3 { - opp-hz = /bits/ 64 <20000000>; - required-opps = <&rpmpd_opp_svs>; - }; - - opp4 { - opp-hz = /bits/ 64 <25000000>; - required-opps = <&rpmpd_opp_normal>; - }; - }; diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml new file mode 100644 index 000000000000..ba605310abeb --- /dev/null +++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml @@ -0,0 +1,170 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/power/qcom,rpmpd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm RPM/RPMh Power domains + +maintainers: + - Rajendra Nayak + +description: + For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh + which then translates it into a corresponding voltage on a rail. + +properties: + compatible: + enum: + - qcom,msm8976-rpmpd + - qcom,msm8996-rpmpd + - qcom,msm8998-rpmpd + - qcom,qcs404-rpmpd + - qcom,sc7180-rpmhpd + - qcom,sdm845-rpmhpd + - qcom,sm8150-rpmhpd + + '#power-domain-cells': + const: 1 + + operating-points-v2: true + + opp-table: + type: object + +required: + - compatible + - '#power-domain-cells' + - operating-points-v2 + +additionalProperties: false + +examples: + - | + + // Example 1 (rpmh power domain controller and OPP table): + + #include + + rpmhpd: power-controller { + compatible = "qcom,sdm845-rpmhpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmhpd_opp_table>; + + rpmhpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmhpd_opp_ret: opp1 { + opp-level = ; + }; + + rpmhpd_opp_min_svs: opp2 { + opp-level = ; + }; + + rpmhpd_opp_low_svs: opp3 { + opp-level = ; + }; + + rpmhpd_opp_svs: opp4 { + opp-level = ; + }; + + rpmhpd_opp_svs_l1: opp5 { + opp-level = ; + }; + + rpmhpd_opp_nom: opp6 { + opp-level = ; + }; + + rpmhpd_opp_nom_l1: opp7 { + opp-level = ; + }; + + rpmhpd_opp_nom_l2: opp8 { + opp-level = ; + }; + + rpmhpd_opp_turbo: opp9 { + opp-level = ; + }; + + rpmhpd_opp_turbo_l1: opp10 { + opp-level = ; + }; + }; + }; + + - | + + // Example 2 (rpm power domain controller and OPP table): + + rpmpd: power-controller { + compatible = "qcom,msm8996-rpmpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmpd_opp_table>; + + rpmpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmpd_opp_low: opp1 { + opp-level = <1>; + }; + + rpmpd_opp_ret: opp2 { + opp-level = <2>; + }; + + rpmpd_opp_svs: opp3 { + opp-level = <3>; + }; + + rpmpd_opp_normal: opp4 { + opp-level = <4>; + }; + + rpmpd_opp_high: opp5 { + opp-level = <5>; + }; + + rpmpd_opp_turbo: opp6 { + opp-level = <6>; + }; + }; + }; + + - | + + // Example 3 (Client/Consumer device using OPP table): + + leaky-device0@12350000 { + compatible = "foo,i-leak-current"; + reg = <0x12350000 0x1000>; + power-domains = <&rpmhpd 0>; + operating-points-v2 = <&leaky_opp_table>; + }; + + leaky_opp_table: opp-table { + compatible = "operating-points-v2"; + opp1 { + opp-hz = /bits/ 64 <144000>; + required-opps = <&rpmhpd_opp_low>; + }; + + opp2 { + opp-hz = /bits/ 64 <400000>; + required-opps = <&rpmhpd_opp_ret>; + }; + + opp3 { + opp-hz = /bits/ 64 <20000000>; + required-opps = <&rpmpd_opp_svs>; + }; + + opp4 { + opp-hz = /bits/ 64 <25000000>; + required-opps = <&rpmpd_opp_normal>; + }; + }; +... -- cgit v1.2.3 From d1dc01860a2a2e9a542485b732ece729402c2bd5 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 24 Dec 2019 15:38:50 +0100 Subject: dt-bindings: display: rockchip-lvds: Declare PX30 compatible Document the PX30 LVDS compatible. Signed-off-by: Miquel Raynal Acked-by: Rob Herring Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20191224143900.23567-2-miquel.raynal@bootlin.com --- Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt index 7849ff039229..aa5663a6fd42 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt @@ -4,6 +4,7 @@ Rockchip RK3288 LVDS interface Required properties: - compatible: matching the soc type, one of - "rockchip,rk3288-lvds"; + - "rockchip,px30-lvds"; - reg: physical base address of the controller and length of memory mapped region. -- cgit v1.2.3 From 1e0b0a0cf31a1c2d7770bed904c66c4e71e01311 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 24 Dec 2019 15:38:51 +0100 Subject: dt-bindings: display: rockchip-lvds: Document PX30 PHY PX30 SoCs use a single PHY shared by two display pipelines: MIPI DSI and LVDS. In the case of the LVDS IP, document the possibility to fill a PHY handle. Signed-off-by: Miquel Raynal Acked-by: Rob Herring Signed-off-by: Heiko Stuebner Link: https://patchwork.freedesktop.org/patch/msgid/20191224143900.23567-3-miquel.raynal@bootlin.com --- Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt index aa5663a6fd42..aaf8c44cf90f 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip-lvds.txt @@ -19,6 +19,9 @@ Required properties: - rockchip,grf: phandle to the general register files syscon - rockchip,output: "rgb", "lvds" or "duallvds", This describes the output interface +- phys: LVDS/DSI DPHY (px30 only) +- phy-names: name of the PHY, must be "dphy" (px30 only) + Optional properties: - pinctrl-names: must contain a "lcdc" entry. - pinctrl-0: pin control group to be used for this controller. -- cgit v1.2.3 From c114574ebfdf42f826776f717c8056a00fa94881 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 3 Jan 2020 20:43:17 +0000 Subject: net: phy: add PHY_INTERFACE_MODE_10GBASER Recent discussion has revealed that the use of PHY_INTERFACE_MODE_10GKR is incorrect. Add a 10GBASE-R definition, document both the -R and -KR versions, and the fact that 10GKR was used incorrectly. Reviewed-by: Andrew Lunn Signed-off-by: Russell King Signed-off-by: David S. Miller --- Documentation/networking/phy.rst | 18 ++++++++++++++++++ include/linux/phy.h | 12 ++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/phy.rst b/Documentation/networking/phy.rst index e0a7c7af6525..1e4735cc0553 100644 --- a/Documentation/networking/phy.rst +++ b/Documentation/networking/phy.rst @@ -267,6 +267,24 @@ Some of the interface modes are described below: duplex, pause or other settings. This is dependent on the MAC and/or PHY behaviour. +``PHY_INTERFACE_MODE_10GBASER`` + This is the IEEE 802.3 Clause 49 defined 10GBASE-R protocol used with + various different mediums. Please refer to the IEEE standard for a + definition of this. + + Note: 10GBASE-R is just one protocol that can be used with XFI and SFI. + XFI and SFI permit multiple protocols over a single SERDES lane, and + also defines the electrical characteristics of the signals with a host + compliance board plugged into the host XFP/SFP connector. Therefore, + XFI and SFI are not PHY interface types in their own right. + +``PHY_INTERFACE_MODE_10GKR`` + This is the IEEE 802.3 Clause 49 defined 10GBASE-R with Clause 73 + autonegotiation. Please refer to the IEEE standard for further + information. + + Note: due to legacy usage, some 10GBASE-R usage incorrectly makes + use of this definition. Pause frames / flow control =========================== diff --git a/include/linux/phy.h b/include/linux/phy.h index 30e599c454db..5932bb8e9c35 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -100,9 +100,11 @@ typedef enum { PHY_INTERFACE_MODE_2500BASEX, PHY_INTERFACE_MODE_RXAUI, PHY_INTERFACE_MODE_XAUI, - /* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */ - PHY_INTERFACE_MODE_10GKR, + /* 10GBASE-R, XFI, SFI - single lane 10G Serdes */ + PHY_INTERFACE_MODE_10GBASER, PHY_INTERFACE_MODE_USXGMII, + /* 10GBASE-KR - with Clause 73 AN */ + PHY_INTERFACE_MODE_10GKR, PHY_INTERFACE_MODE_MAX, } phy_interface_t; @@ -176,10 +178,12 @@ static inline const char *phy_modes(phy_interface_t interface) return "rxaui"; case PHY_INTERFACE_MODE_XAUI: return "xaui"; - case PHY_INTERFACE_MODE_10GKR: - return "10gbase-kr"; + case PHY_INTERFACE_MODE_10GBASER: + return "10gbase-r"; case PHY_INTERFACE_MODE_USXGMII: return "usxgmii"; + case PHY_INTERFACE_MODE_10GKR: + return "10gbase-kr"; default: return "unknown"; } -- cgit v1.2.3 From ebf59a4558c2c1629dff276da6fc9b0e77800fa6 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sat, 4 Jan 2020 11:54:17 +0100 Subject: dt: bindings: lm3692x: Add ti,ovp-microvolt property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to set the overvoltage protection to 17V, 21V, 25V or 29V. Signed-off-by: Guido Günther Acked-by: Pavel Machek Signed-off-by: Pavel Machek Reviewed-by: Rob Herring --- Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt index 4c2d923f8758..9b334695c410 100644 --- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt +++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt @@ -18,6 +18,10 @@ Required properties: Optional properties: - enable-gpios : gpio pin to enable/disable the device. - vled-supply : LED supply + - ti,ovp-microvolt: Overvoltage protection in + micro-volt, can be 17000000, 21000000, 25000000 or + 29000000. If ti,ovp-microvolt is not specified it + defaults to 29000000. Required child properties: - reg : 0 - Will enable all LED sync paths @@ -44,6 +48,7 @@ led-controller@36 { enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; vled-supply = <&vbatt>; + ti,ovp-microvolt = <29000000>; led@0 { reg = <0>; -- cgit v1.2.3 From 3e0801b62a30f5c83df0b7c75afce50061401e30 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Sat, 4 Jan 2020 11:54:21 +0100 Subject: dt: bindings: lm3692x: Add led-max-microamp property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This can be used to limit the current per LED strip. Signed-off-by: Guido Günther Acked-by: Pavel Machek Reviewed-by: Rob Herring Signed-off-by: Pavel Machek --- Documentation/devicetree/bindings/leds/leds-lm3692x.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt index 9b334695c410..501468aa4d38 100644 --- a/Documentation/devicetree/bindings/leds/leds-lm3692x.txt +++ b/Documentation/devicetree/bindings/leds/leds-lm3692x.txt @@ -35,6 +35,8 @@ Optional child properties: - label : see Documentation/devicetree/bindings/leds/common.txt (deprecated) - linux,default-trigger : see Documentation/devicetree/bindings/leds/common.txt + - led-max-microamp : + see Documentation/devicetree/bindings/leds/common.txt Example: @@ -55,6 +57,7 @@ led-controller@36 { function = LED_FUNCTION_BACKLIGHT; color = ; linux,default-trigger = "backlight"; + led-max-microamp = <20000>; }; } -- cgit v1.2.3 From 1a3ec143a90a4674e01099c3ba47c3268536a462 Mon Sep 17 00:00:00 2001 From: Anju T Sudhakar Date: Mon, 28 Oct 2019 21:08:16 +1100 Subject: powerpc/imc: Add documentation for IMC and trace-mode Documentation for IMC (In-Memory Collection Counters) infrastructure and trace-mode of IMC. Signed-off-by: Anju T Sudhakar [mpe: Convert to rst, minor rewording, make PMI example more concise] Signed-off-by: Michael Ellerman Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20191028100816.6270-1-mpe@ellerman.id.au --- Documentation/powerpc/imc.rst | 199 ++++++++++++++++++++++++++++++++++++++++ Documentation/powerpc/index.rst | 1 + 2 files changed, 200 insertions(+) create mode 100644 Documentation/powerpc/imc.rst (limited to 'Documentation') diff --git a/Documentation/powerpc/imc.rst b/Documentation/powerpc/imc.rst new file mode 100644 index 000000000000..633bcee7dc85 --- /dev/null +++ b/Documentation/powerpc/imc.rst @@ -0,0 +1,199 @@ +.. SPDX-License-Identifier: GPL-2.0 +.. _imc: + +=================================== +IMC (In-Memory Collection Counters) +=================================== + +Anju T Sudhakar, 10 May 2019 + +.. contents:: + :depth: 3 + + +Basic overview +============== + +IMC (In-Memory collection counters) is a hardware monitoring facility that +collects large numbers of hardware performance events at Nest level (these are +on-chip but off-core), Core level and Thread level. + +The Nest PMU counters are handled by a Nest IMC microcode which runs in the OCC +(On-Chip Controller) complex. The microcode collects the counter data and moves +the nest IMC counter data to memory. + +The Core and Thread IMC PMU counters are handled in the core. Core level PMU +counters give us the IMC counters' data per core and thread level PMU counters +give us the IMC counters' data per CPU thread. + +OPAL obtains the IMC PMU and supported events information from the IMC Catalog +and passes on to the kernel via the device tree. The event's information +contains: + +- Event name +- Event Offset +- Event description + +and possibly also: + +- Event scale +- Event unit + +Some PMUs may have a common scale and unit values for all their supported +events. For those cases, the scale and unit properties for those events must be +inherited from the PMU. + +The event offset in the memory is where the counter data gets accumulated. + +IMC catalog is available at: + https://github.com/open-power/ima-catalog + +The kernel discovers the IMC counters information in the device tree at the +`imc-counters` device node which has a compatible field +`ibm,opal-in-memory-counters`. From the device tree, the kernel parses the PMUs +and their event's information and register the PMU and its attributes in the +kernel. + +IMC example usage +================= + +.. code-block:: sh + + # perf list + [...] + nest_mcs01/PM_MCS01_64B_RD_DISP_PORT01/ [Kernel PMU event] + nest_mcs01/PM_MCS01_64B_RD_DISP_PORT23/ [Kernel PMU event] + [...] + core_imc/CPM_0THRD_NON_IDLE_PCYC/ [Kernel PMU event] + core_imc/CPM_1THRD_NON_IDLE_INST/ [Kernel PMU event] + [...] + thread_imc/CPM_0THRD_NON_IDLE_PCYC/ [Kernel PMU event] + thread_imc/CPM_1THRD_NON_IDLE_INST/ [Kernel PMU event] + +To see per chip data for nest_mcs0/PM_MCS_DOWN_128B_DATA_XFER_MC0/: + +.. code-block:: sh + + # ./perf stat -e "nest_mcs01/PM_MCS01_64B_WR_DISP_PORT01/" -a --per-socket + +To see non-idle instructions for core 0: + +.. code-block:: sh + + # ./perf stat -e "core_imc/CPM_NON_IDLE_INST/" -C 0 -I 1000 + +To see non-idle instructions for a "make": + +.. code-block:: sh + + # ./perf stat -e "thread_imc/CPM_NON_IDLE_PCYC/" make + + +IMC Trace-mode +=============== + +POWER9 supports two modes for IMC which are the Accumulation mode and Trace +mode. In Accumulation mode, event counts are accumulated in system Memory. +Hypervisor then reads the posted counts periodically or when requested. In IMC +Trace mode, the 64 bit trace SCOM value is initialized with the event +information. The CPMCxSEL and CPMC_LOAD in the trace SCOM, specifies the event +to be monitored and the sampling duration. On each overflow in the CPMCxSEL, +hardware snapshots the program counter along with event counts and writes into +memory pointed by LDBAR. + +LDBAR is a 64 bit special purpose per thread register, it has bits to indicate +whether hardware is configured for accumulation or trace mode. + +LDBAR Register Layout +--------------------- + + +-------+----------------------+ + | 0 | Enable/Disable | + +-------+----------------------+ + | 1 | 0: Accumulation Mode | + | +----------------------+ + | | 1: Trace Mode | + +-------+----------------------+ + | 2:3 | Reserved | + +-------+----------------------+ + | 4-6 | PB scope | + +-------+----------------------+ + | 7 | Reserved | + +-------+----------------------+ + | 8:50 | Counter Address | + +-------+----------------------+ + | 51:63 | Reserved | + +-------+----------------------+ + +TRACE_IMC_SCOM bit representation +--------------------------------- + + +-------+------------+ + | 0:1 | SAMPSEL | + +-------+------------+ + | 2:33 | CPMC_LOAD | + +-------+------------+ + | 34:40 | CPMC1SEL | + +-------+------------+ + | 41:47 | CPMC2SEL | + +-------+------------+ + | 48:50 | BUFFERSIZE | + +-------+------------+ + | 51:63 | RESERVED | + +-------+------------+ + +CPMC_LOAD contains the sampling duration. SAMPSEL and CPMCxSEL determines the +event to count. BUFFERSIZE indicates the memory range. On each overflow, +hardware snapshots the program counter along with event counts and updates the +memory and reloads the CMPC_LOAD value for the next sampling duration. IMC +hardware does not support exceptions, so it quietly wraps around if memory +buffer reaches the end. + +*Currently the event monitored for trace-mode is fixed as cycle.* + +Trace IMC example usage +======================= + +.. code-block:: sh + + # perf list + [....] + trace_imc/trace_cycles/ [Kernel PMU event] + +To record an application/process with trace-imc event: + +.. code-block:: sh + + # perf record -e trace_imc/trace_cycles/ yes > /dev/null + [ perf record: Woken up 1 times to write data ] + [ perf record: Captured and wrote 0.012 MB perf.data (21 samples) ] + +The `perf.data` generated, can be read using perf report. + +Benefits of using IMC trace-mode +================================ + +PMI (Performance Monitoring Interrupts) interrupt handling is avoided, since IMC +trace mode snapshots the program counter and updates to the memory. And this +also provide a way for the operating system to do instruction sampling in real +time without PMI processing overhead. + +Performance data using `perf top` with and without trace-imc event. + +PMI interrupts count when `perf top` command is executed without trace-imc event. + +.. code-block:: sh + + # grep PMI /proc/interrupts + PMI: 0 0 0 0 Performance monitoring interrupts + # ./perf top + ... + # grep PMI /proc/interrupts + PMI: 39735 8710 17338 17801 Performance monitoring interrupts + # ./perf top -e trace_imc/trace_cycles/ + ... + # grep PMI /proc/interrupts + PMI: 39735 8710 17338 17801 Performance monitoring interrupts + + +That is, the PMI interrupt counts do not increment when using the `trace_imc` event. diff --git a/Documentation/powerpc/index.rst b/Documentation/powerpc/index.rst index ba5edb3211c0..2df04259db65 100644 --- a/Documentation/powerpc/index.rst +++ b/Documentation/powerpc/index.rst @@ -18,6 +18,7 @@ powerpc elfnote firmware-assisted-dump hvcs + imc isa-versions kaslr-booke32 mpc52xx -- cgit v1.2.3 From 1511ed0a0167f523a84b4e727372a5d2ce1b6c2f Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 6 Jan 2020 03:34:11 +0200 Subject: net: phylink: add support for polling MAC PCS Some MAC PCS blocks are unable to provide interrupts when their status changes. As we already have support in phylink for polling status, use this to provide a hook for MACs to enable polling mode. The patch idea was picked up from Russell King's suggestion on the macb phylink patch thread here [0] but the implementation was changed. Instead of introducing a new phylink_start_poll() function, which would make the implementation cumbersome for common PHYLINK implementations for multiple types of devices, like DSA, just add a boolean property to the phylink_config structure, which is just as backwards-compatible. https://lkml.org/lkml/2019/12/16/603 Suggested-by: Russell King Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- Documentation/networking/sfp-phylink.rst | 3 ++- drivers/net/phy/phylink.c | 3 ++- include/linux/phylink.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/sfp-phylink.rst b/Documentation/networking/sfp-phylink.rst index a5e00a159d21..d753a309f9d1 100644 --- a/Documentation/networking/sfp-phylink.rst +++ b/Documentation/networking/sfp-phylink.rst @@ -251,7 +251,8 @@ this documentation. phylink_mac_change(priv->phylink, link_is_up); where ``link_is_up`` is true if the link is currently up or false - otherwise. + otherwise. If a MAC is unable to provide these interrupts, then + it should set ``priv->phylink_config.pcs_poll = true;`` in step 9. 11. Verify that the driver does not call:: diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 88686e0f9ae1..af914a8842bd 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1022,7 +1022,8 @@ void phylink_start(struct phylink *pl) if (irq <= 0) mod_timer(&pl->link_poll, jiffies + HZ); } - if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->get_fixed_state) + if ((pl->cfg_link_an_mode == MLO_AN_FIXED && pl->get_fixed_state) || + pl->config->pcs_poll) mod_timer(&pl->link_poll, jiffies + HZ); if (pl->phydev) phy_start(pl->phydev); diff --git a/include/linux/phylink.h b/include/linux/phylink.h index fed5488e3c75..523209e70947 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -63,10 +63,12 @@ enum phylink_op_type { * struct phylink_config - PHYLINK configuration structure * @dev: a pointer to a struct device associated with the MAC * @type: operation type of PHYLINK instance + * @pcs_poll: MAC PCS cannot provide link change interrupt */ struct phylink_config { struct device *dev; enum phylink_op_type type; + bool pcs_poll; }; /** -- cgit v1.2.3 From 4bdc0d676a643140bdf17dbf7eafedee3d496a3c Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 6 Jan 2020 09:43:50 +0100 Subject: remove ioremap_nocache and devm_ioremap_nocache ioremap has provided non-cached semantics by default since the Linux 2.6 days, so remove the additional ioremap_nocache interface. Signed-off-by: Christoph Hellwig Acked-by: Arnd Bergmann --- Documentation/driver-api/driver-model/devres.rst | 1 - .../sound/kernel-api/writing-an-alsa-driver.rst | 2 +- Documentation/x86/pat.rst | 2 -- arch/alpha/include/asm/io.h | 10 ++-------- arch/arm/include/asm/io.h | 8 -------- arch/arm/mach-bcm/platsmp.c | 4 ++-- arch/arm/mach-davinci/devices.c | 2 +- arch/arm/mach-pxa/magician.c | 2 +- arch/arm/mach-shmobile/platsmp-apmu.c | 2 +- arch/arm/mach-shmobile/pm-rcar-gen2.c | 2 +- arch/arm/mach-shmobile/setup-r8a7740.c | 8 ++++---- arch/arm/mach-shmobile/setup-r8a7778.c | 2 +- arch/hexagon/include/asm/io.h | 1 - arch/ia64/include/asm/vga.h | 2 +- arch/ia64/kernel/cyclone.c | 8 ++++---- arch/m68k/include/asm/kmap.h | 1 - arch/mips/ar7/clock.c | 8 ++++---- arch/mips/ar7/gpio.c | 2 +- arch/mips/ar7/platform.c | 2 +- arch/mips/ath25/ar2315.c | 4 ++-- arch/mips/ath25/ar5312.c | 6 +++--- arch/mips/ath25/board.c | 2 +- arch/mips/ath79/common.c | 2 +- arch/mips/ath79/setup.c | 4 ++-- arch/mips/cavium-octeon/setup.c | 2 +- arch/mips/generic/board-ocelot.c | 2 +- arch/mips/include/asm/io.h | 1 - arch/mips/kernel/mips-cm.c | 4 ++-- arch/mips/kernel/mips-cpc.c | 2 +- arch/mips/lantiq/falcon/sysctrl.c | 6 +++--- arch/mips/lantiq/irq.c | 4 ++-- arch/mips/lantiq/xway/sysctrl.c | 6 +++--- arch/mips/loongson2ef/common/reset.c | 4 ++-- arch/mips/loongson32/common/prom.c | 8 ++++---- arch/mips/loongson32/common/reset.c | 2 +- arch/mips/loongson32/common/time.c | 2 +- arch/mips/loongson64/reset.c | 2 +- arch/mips/mti-malta/malta-dtshim.c | 2 +- arch/mips/pci/pci-alchemy.c | 2 +- arch/mips/pci/pci-ar2315.c | 2 +- arch/mips/pci/pci-bcm63xx.c | 2 +- arch/mips/pci/pci-rt2880.c | 2 +- arch/mips/pic32/pic32mzda/early_console.c | 2 +- arch/mips/pic32/pic32mzda/early_pin.c | 4 ++-- arch/mips/pmcs-msp71xx/msp_serial.c | 4 ++-- arch/mips/ralink/irq.c | 2 +- arch/mips/ralink/of.c | 2 +- arch/mips/rb532/devices.c | 2 +- arch/mips/rb532/gpio.c | 2 +- arch/mips/rb532/prom.c | 2 +- arch/mips/rb532/setup.c | 2 +- arch/mips/sni/rm200.c | 4 ++-- arch/parisc/include/asm/io.h | 5 ++--- arch/parisc/kernel/perf.c | 2 +- arch/powerpc/include/asm/io.h | 3 --- arch/sh/boards/board-sh7785lcr.c | 2 +- arch/sh/boards/mach-cayman/irq.c | 2 +- arch/sh/boards/mach-cayman/setup.c | 2 +- arch/sh/boards/mach-sdk7786/fpga.c | 2 +- arch/sh/drivers/heartbeat.c | 2 +- arch/sh/drivers/pci/pci-sh5.c | 4 ++-- arch/sh/include/asm/io.h | 1 - arch/sh/kernel/cpu/irq/intc-sh5.c | 2 +- arch/sh/kernel/cpu/sh2/smp-j2.c | 4 ++-- arch/sh/kernel/cpu/sh5/clock-sh5.c | 2 +- arch/sh/kernel/dma-coherent.c | 2 +- arch/sparc/include/asm/io_64.h | 1 - arch/unicore32/include/asm/io.h | 1 - arch/x86/kernel/apb_timer.c | 2 +- arch/x86/kernel/hpet.c | 2 +- arch/x86/kernel/quirks.c | 2 +- arch/x86/kernel/tboot.c | 2 +- arch/x86/mm/testmmiotrace.c | 4 ++-- arch/x86/pci/mmconfig_64.c | 2 +- drivers/acpi/acpi_lpit.c | 2 +- drivers/ata/pata_arasan_cf.c | 2 +- drivers/ata/pata_octeon_cf.c | 6 +++--- drivers/ata/pata_rb532_cf.c | 2 +- drivers/atm/eni.c | 8 +------- drivers/bcma/driver_chipcommon_b.c | 2 +- drivers/bcma/driver_pci_host.c | 6 +++--- drivers/bcma/host_soc.c | 2 +- drivers/bcma/scan.c | 6 +++--- drivers/block/umem.c | 2 +- drivers/bus/fsl-mc/mc-io.c | 4 ++-- drivers/char/agp/generic.c | 2 +- drivers/char/agp/intel-gtt.c | 2 +- drivers/char/applicom.c | 4 ++-- drivers/char/hw_random/intel-rng.c | 2 +- drivers/char/hw_random/octeon-rng.c | 4 ++-- drivers/clk/renesas/clk-rz.c | 4 ++-- drivers/clocksource/sh_cmt.c | 2 +- drivers/clocksource/sh_mtu2.c | 2 +- drivers/clocksource/sh_tmu.c | 2 +- drivers/cpufreq/pcc-cpufreq.c | 2 +- drivers/crypto/hifn_795x.c | 2 +- drivers/dma/altera-msgdma.c | 4 ++-- drivers/edac/i3000_edac.c | 2 +- drivers/edac/i3200_edac.c | 2 +- drivers/edac/i82975x_edac.c | 2 +- drivers/edac/ie31200_edac.c | 2 +- drivers/edac/x38_edac.c | 2 +- drivers/firewire/nosy.c | 2 +- drivers/firmware/broadcom/bcm47xx_nvram.c | 2 +- drivers/gpu/drm/gma500/gtt.c | 2 +- drivers/gpu/drm/gma500/psb_drv.c | 2 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- drivers/gpu/drm/sti/sti_dvo.c | 2 +- drivers/gpu/drm/sti/sti_hda.c | 4 ++-- drivers/gpu/drm/sti/sti_hdmi.c | 2 +- drivers/gpu/drm/sti/sti_tvout.c | 2 +- drivers/gpu/drm/sti/sti_vtg.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 2 +- drivers/gpu/drm/ttm/ttm_bo_util.c | 4 ++-- drivers/hwmon/i5k_amb.c | 2 +- drivers/i2c/busses/i2c-highlander.c | 2 +- drivers/i2c/busses/i2c-pmcmsp.c | 2 +- drivers/infiniband/hw/bnxt_re/qplib_fp.c | 2 +- drivers/infiniband/hw/bnxt_re/qplib_rcfw.c | 4 ++-- drivers/infiniband/hw/bnxt_re/qplib_res.c | 2 +- drivers/infiniband/hw/hfi1/pcie.c | 4 ++-- drivers/infiniband/hw/qib/qib_iba7322.c | 2 +- drivers/infiniband/hw/qib/qib_init.c | 4 ++-- drivers/infiniband/hw/qib/qib_pcie.c | 2 +- drivers/input/keyboard/pxa930_rotary.c | 2 +- drivers/input/keyboard/sh_keysc.c | 2 +- drivers/input/mouse/pxa930_trkball.c | 2 +- drivers/input/serio/gscps2.c | 2 +- drivers/iommu/amd_iommu_init.c | 2 +- drivers/ipack/carriers/tpci200.c | 4 ++-- drivers/ipack/devices/ipoctal.c | 6 +++--- drivers/irqchip/irq-mips-gic.c | 2 +- drivers/irqchip/irq-renesas-intc-irqpin.c | 2 +- drivers/media/common/videobuf2/videobuf2-vmalloc.c | 2 +- drivers/media/pci/cx18/cx18-driver.c | 2 +- drivers/media/pci/ivtv/ivtv-driver.c | 6 +++--- drivers/media/platform/davinci/dm355_ccdc.c | 2 +- drivers/media/platform/davinci/dm644x_ccdc.c | 2 +- drivers/media/platform/davinci/isif.c | 2 +- drivers/media/platform/tegra-cec/tegra_cec.c | 2 +- drivers/misc/cardreader/rtsx_pcr.c | 2 +- drivers/misc/mic/scif/scif_nodeqp.c | 2 +- drivers/misc/pti.c | 2 +- drivers/mmc/host/sdhci-acpi.c | 2 +- drivers/mmc/host/via-sdmmc.c | 2 +- drivers/mtd/devices/bcm47xxsflash.c | 2 +- drivers/mtd/maps/amd76xrom.c | 2 +- drivers/mtd/maps/ck804xrom.c | 2 +- drivers/mtd/maps/esb2rom.c | 2 +- drivers/mtd/maps/ichxrom.c | 2 +- drivers/mtd/maps/intel_vr_nor.c | 4 ++-- drivers/mtd/maps/l440gx.c | 2 +- drivers/mtd/maps/netsc520.c | 4 ++-- drivers/mtd/maps/nettel.c | 8 ++++---- drivers/mtd/maps/pci.c | 4 ++-- drivers/mtd/maps/sc520cdp.c | 8 ++++---- drivers/mtd/maps/scb2_flash.c | 2 +- drivers/mtd/maps/ts5500_flash.c | 4 ++-- drivers/mtd/nand/raw/au1550nd.c | 2 +- drivers/mtd/nand/raw/denali_pci.c | 6 +++--- drivers/mtd/nand/raw/fsl_upm.c | 2 +- drivers/net/can/at91_can.c | 2 +- drivers/net/can/cc770/cc770_isa.c | 2 +- drivers/net/can/sja1000/sja1000_isa.c | 2 +- drivers/net/can/sja1000/sja1000_platform.c | 2 +- drivers/net/can/softing/softing_main.c | 2 +- drivers/net/ethernet/alacritech/slicoss.c | 2 +- drivers/net/ethernet/altera/altera_tse_main.c | 4 ++-- drivers/net/ethernet/amd/au1000_eth.c | 6 +++--- drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 2 +- drivers/net/ethernet/atheros/ag71xx.c | 3 +-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- drivers/net/ethernet/broadcom/sb1250-mac.c | 2 +- drivers/net/ethernet/brocade/bna/bnad.c | 2 +- drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 2 +- drivers/net/ethernet/dec/tulip/de2104x.c | 2 +- drivers/net/ethernet/ethoc.c | 4 ++-- drivers/net/ethernet/i825xx/sni_82596.c | 6 +++--- drivers/net/ethernet/korina.c | 6 +++--- drivers/net/ethernet/lantiq_etop.c | 2 +- drivers/net/ethernet/marvell/skge.c | 2 +- drivers/net/ethernet/marvell/sky2.c | 2 +- drivers/net/ethernet/natsemi/ns83820.c | 2 +- drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c | 8 ++++---- .../ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c | 6 +++--- drivers/net/ethernet/sfc/ef10.c | 2 +- drivers/net/ethernet/sfc/efx.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- drivers/net/ethernet/smsc/smsc911x.c | 2 +- drivers/net/ethernet/ti/netcp_core.c | 2 +- drivers/net/ethernet/xilinx/ll_temac_main.c | 4 ++-- drivers/net/fddi/defxx.c | 2 +- drivers/net/fddi/defza.c | 2 +- drivers/net/fjes/fjes_hw.c | 2 +- drivers/net/wan/wanxl.c | 4 ++-- drivers/net/wireless/ath/ath10k/ahb.c | 4 ++-- drivers/net/wireless/ath/ath5k/ahb.c | 2 +- drivers/net/wireless/ath/ath9k/ahb.c | 2 +- .../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++-- drivers/net/wireless/intel/ipw2x00/ipw2100.c | 2 +- drivers/opp/ti-opp-supply.c | 2 +- drivers/parisc/ccio-dma.c | 2 +- drivers/parisc/dino.c | 2 +- drivers/parisc/eisa.c | 4 ++-- drivers/parisc/iosapic.c | 2 +- drivers/parisc/lba_pci.c | 8 ++++---- drivers/parisc/sba_iommu.c | 4 ++-- drivers/pci/controller/dwc/pci-dra7xx.c | 2 +- drivers/pci/controller/dwc/pcie-designware-ep.c | 2 +- drivers/pci/msi.c | 2 +- drivers/pci/pci.c | 2 +- drivers/pci/quirks.c | 4 ++-- drivers/pinctrl/bcm/pinctrl-ns2-mux.c | 2 +- drivers/pinctrl/bcm/pinctrl-nsp-mux.c | 2 +- drivers/pinctrl/freescale/pinctrl-imx1-core.c | 2 +- drivers/pinctrl/pinctrl-amd.c | 2 +- drivers/platform/x86/intel_scu_ipc.c | 2 +- drivers/platform/x86/intel_telemetry_pltdrv.c | 4 ++-- drivers/platform/x86/pmc_atom.c | 2 +- drivers/platform/x86/samsung-laptop.c | 4 ++-- drivers/regulator/ti-abb-regulator.c | 4 ++-- drivers/rtc/rtc-sh.c | 2 +- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 2 +- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 2 +- drivers/scsi/arcmsr/arcmsr_hba.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 6 +++--- drivers/scsi/bnx2fc/bnx2fc_hwi.c | 2 +- drivers/scsi/bnx2i/bnx2i_hwi.c | 4 ++-- drivers/scsi/csiostor/csio_init.c | 2 +- drivers/scsi/hpsa.c | 2 +- drivers/scsi/lasi700.c | 2 +- drivers/scsi/megaraid/megaraid_mbox.c | 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- drivers/scsi/myrb.c | 2 +- drivers/scsi/myrs.c | 2 +- drivers/scsi/pcmcia/nsp_cs.c | 2 +- drivers/scsi/qla2xxx/qla_mr.c | 4 ++-- drivers/scsi/smartpqi/smartpqi_init.c | 2 +- drivers/scsi/sni_53c710.c | 2 +- drivers/scsi/sun3x_esp.c | 4 ++-- drivers/scsi/zalon.c | 2 +- drivers/scsi/zorro_esp.c | 6 +++--- drivers/sh/clk/core.c | 2 +- drivers/sh/intc/core.c | 2 +- drivers/sh/intc/userimask.c | 2 +- drivers/soc/tegra/flowctrl.c | 2 +- drivers/soc/tegra/fuse/fuse-tegra.c | 2 +- drivers/soc/tegra/fuse/tegra-apbmisc.c | 4 ++-- drivers/soc/tegra/pmc.c | 4 ++-- drivers/soc/xilinx/xlnx_vcu.c | 4 ++-- drivers/spi/spi-dw-mid.c | 2 +- drivers/spi/spi-jcore.c | 2 +- drivers/spi/spi-npcm-fiu.c | 2 +- drivers/ssb/driver_extif.c | 2 +- drivers/ssb/driver_pcicore.c | 6 +++--- drivers/staging/gasket/gasket_core.c | 2 +- drivers/staging/kpc2000/kpc2000/core.c | 4 ++-- drivers/staging/kpc2000/kpc2000_i2c.c | 2 +- drivers/staging/kpc2000/kpc2000_spi.c | 2 +- drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c | 2 +- drivers/staging/media/allegro-dvt/allegro-core.c | 4 ++-- drivers/staging/qlge/qlge_main.c | 4 ++-- drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 2 +- drivers/staging/rts5208/rtsx.c | 2 +- drivers/staging/sm750fb/sm750_hw.c | 2 +- drivers/staging/uwb/whc-rc.c | 6 +++--- drivers/tc/tc.c | 2 +- drivers/tty/cyclades.c | 10 +++++----- drivers/tty/mips_ejtag_fdc.c | 2 +- drivers/tty/moxa.c | 4 ++-- drivers/tty/serial/8250/8250_gsc.c | 2 +- drivers/tty/serial/8250/8250_omap.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 6 +++--- drivers/tty/serial/8250/8250_port.c | 2 +- drivers/tty/serial/dz.c | 2 +- drivers/tty/serial/lantiq.c | 2 +- drivers/tty/serial/meson_uart.c | 2 +- drivers/tty/serial/mux.c | 2 +- drivers/tty/serial/owl-uart.c | 2 +- drivers/tty/serial/pic32_uart.c | 2 +- drivers/tty/serial/rda-uart.c | 2 +- drivers/tty/serial/sb1250-duart.c | 4 ++-- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/zs.c | 2 +- drivers/tty/synclink.c | 4 ++-- drivers/tty/synclink_gt.c | 2 +- drivers/tty/synclinkmp.c | 8 ++++---- drivers/usb/core/hcd-pci.c | 2 +- drivers/usb/early/xhci-dbc.c | 2 +- drivers/usb/gadget/udc/amd5536udc_pci.c | 2 +- drivers/usb/gadget/udc/goku_udc.c | 2 +- drivers/usb/gadget/udc/net2272.c | 6 +++--- drivers/usb/gadget/udc/net2280.c | 2 +- drivers/usb/host/ehci-pmcmsp.c | 6 +++--- drivers/usb/host/pci-quirks.c | 2 +- drivers/usb/isp1760/isp1760-if.c | 4 ++-- drivers/usb/roles/intel-xhci-usb-role-switch.c | 2 +- drivers/usb/typec/ucsi/ucsi_acpi.c | 2 +- drivers/vfio/pci/vfio_pci_rdwr.c | 2 +- drivers/vfio/platform/reset/vfio_platform_amdxgbe.c | 4 ++-- .../vfio/platform/reset/vfio_platform_bcmflexrm.c | 2 +- .../vfio/platform/reset/vfio_platform_calxedaxgmac.c | 2 +- drivers/vfio/platform/vfio_platform_common.c | 4 ++-- drivers/video/fbdev/carminefb.c | 4 ++-- drivers/video/fbdev/i810/i810_main.c | 2 +- drivers/video/fbdev/intelfb/intelfbdrv.c | 2 +- drivers/video/fbdev/kyro/fbdev.c | 2 +- drivers/video/fbdev/matrox/matroxfb_base.c | 2 +- drivers/video/fbdev/mbx/mbxfb.c | 4 ++-- drivers/video/fbdev/mmp/hw/mmp_ctrl.c | 2 +- drivers/video/fbdev/pm2fb.c | 2 +- drivers/video/fbdev/pm3fb.c | 4 ++-- drivers/video/fbdev/pmag-aa-fb.c | 4 ++-- drivers/video/fbdev/pmag-ba-fb.c | 4 ++-- drivers/video/fbdev/pmagb-b-fb.c | 4 ++-- drivers/video/fbdev/pvr2fb.c | 4 ++-- drivers/video/fbdev/pxa168fb.c | 2 +- drivers/video/fbdev/s1d13xxxfb.c | 4 ++-- drivers/video/fbdev/sh7760fb.c | 2 +- drivers/video/fbdev/sh_mobile_lcdcfb.c | 2 +- drivers/video/fbdev/sstfb.c | 4 ++-- drivers/video/fbdev/stifb.c | 4 ++-- drivers/video/fbdev/tdfxfb.c | 2 +- drivers/video/fbdev/tgafb.c | 2 +- drivers/video/fbdev/tridentfb.c | 4 ++-- drivers/video/fbdev/valkyriefb.c | 2 +- drivers/video/fbdev/vermilion/cr_pll.c | 2 +- drivers/video/fbdev/vermilion/vermilion.c | 4 ++-- drivers/video/fbdev/via/via-core.c | 2 +- drivers/video/fbdev/w100fb.c | 6 +++--- drivers/vme/boards/vme_vmivme7805.c | 2 +- drivers/vme/bridges/vme_ca91cx42.c | 4 ++-- drivers/vme/bridges/vme_tsi148.c | 4 ++-- drivers/w1/masters/matrox_w1.c | 2 +- drivers/watchdog/bcm63xx_wdt.c | 2 +- drivers/watchdog/intel_scu_watchdog.c | 2 +- drivers/watchdog/rc32434_wdt.c | 4 ++-- include/asm-generic/io.h | 4 ---- include/asm-generic/iomap.h | 4 ++-- include/linux/io.h | 6 ++---- lib/devres.c | 20 -------------------- scripts/coccinelle/free/devm_free.cocci | 4 ---- scripts/coccinelle/free/iounmap.cocci | 2 +- sound/drivers/ml403-ac97cr.c | 2 +- sound/isa/msnd/msnd_pinnacle.c | 2 +- sound/parisc/harmony.c | 2 +- sound/pci/aw2/aw2-alsa.c | 2 +- sound/pci/cs46xx/cs46xx_lib.c | 2 +- sound/pci/echoaudio/echoaudio.c | 2 +- sound/pci/nm256/nm256.c | 6 +++--- sound/pci/rme32.c | 2 +- sound/pci/rme96.c | 2 +- sound/pci/rme9652/hdsp.c | 2 +- sound/pci/rme9652/hdspm.c | 2 +- sound/pci/rme9652/rme9652.c | 2 +- sound/pci/sis7019.c | 2 +- sound/pci/ymfpci/ymfpci_main.c | 2 +- sound/soc/au1x/ac97c.c | 2 +- sound/soc/au1x/i2sc.c | 2 +- sound/soc/intel/atom/sst/sst_acpi.c | 10 +++++----- sound/soc/sh/fsi.c | 2 +- sound/x86/intel_hdmi_audio.c | 2 +- tools/testing/nvdimm/Kbuild | 3 +-- tools/testing/nvdimm/test/iomap.c | 12 +++--------- tools/testing/nvdimm/test/nfit_test.h | 2 -- 368 files changed, 508 insertions(+), 581 deletions(-) (limited to 'Documentation') diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst index 13046fcf0a5d..20e07e40be02 100644 --- a/Documentation/driver-api/driver-model/devres.rst +++ b/Documentation/driver-api/driver-model/devres.rst @@ -313,7 +313,6 @@ IOMAP devm_ioport_map() devm_ioport_unmap() devm_ioremap() - devm_ioremap_nocache() devm_ioremap_uc() devm_ioremap_wc() devm_ioremap_resource() : checks resource, requests memory region, ioremaps diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst index f169d58ca019..ddef812ddf8f 100644 --- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst +++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst @@ -1058,7 +1058,7 @@ and the allocation would be like below: return err; } chip->iobase_phys = pci_resource_start(pci, 0); - chip->iobase_virt = ioremap_nocache(chip->iobase_phys, + chip->iobase_virt = ioremap(chip->iobase_phys, pci_resource_len(pci, 0)); and the corresponding destructor would be: diff --git a/Documentation/x86/pat.rst b/Documentation/x86/pat.rst index 9a298fd97d74..5d901771016d 100644 --- a/Documentation/x86/pat.rst +++ b/Documentation/x86/pat.rst @@ -44,8 +44,6 @@ address range to avoid any aliasing. +------------------------+----------+--------------+------------------+ | ioremap_uc | -- | UC | UC | +------------------------+----------+--------------+------------------+ -| ioremap_nocache | -- | UC- | UC- | -+------------------------+----------+--------------+------------------+ | ioremap_wc | -- | -- | WC | +------------------------+----------+--------------+------------------+ | ioremap_wt | -- | -- | WT | diff --git a/arch/alpha/include/asm/io.h b/arch/alpha/include/asm/io.h index 1989b946a28d..d1ed5a8133c5 100644 --- a/arch/alpha/include/asm/io.h +++ b/arch/alpha/include/asm/io.h @@ -283,14 +283,8 @@ static inline void __iomem *ioremap(unsigned long port, unsigned long size) return IO_CONCAT(__IO_PREFIX,ioremap) (port, size); } -static inline void __iomem * ioremap_nocache(unsigned long offset, - unsigned long size) -{ - return ioremap(offset, size); -} - -#define ioremap_wc ioremap_nocache -#define ioremap_uc ioremap_nocache +#define ioremap_wc ioremap +#define ioremap_uc ioremap static inline void iounmap(volatile void __iomem *addr) { diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index aefdabdbeb84..ab2b654084fa 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -356,7 +356,6 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, * * Function Memory type Cacheability Cache hint * ioremap() Device n/a n/a - * ioremap_nocache() Device n/a n/a * ioremap_cache() Normal Writeback Read allocate * ioremap_wc() Normal Non-cacheable n/a * ioremap_wt() Normal Non-cacheable n/a @@ -368,13 +367,6 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, * - unaligned accesses are "unpredictable" * - writes may be delayed before they hit the endpoint device * - * ioremap_nocache() is the same as ioremap() as there are too many device - * drivers using this for device registers, and documentation which tells - * people to use it for such for this to be any different. This is not a - * safe fallback for memory-like mappings, or memory regions where the - * compiler may generate unaligned accesses - eg, via inlining its own - * memcpy. - * * All normal memory mappings have the following properties: * - reads can be repeated with no side effects * - repeated reads return the last value written diff --git a/arch/arm/mach-bcm/platsmp.c b/arch/arm/mach-bcm/platsmp.c index 21400b3fa5fe..c9db2a9006d9 100644 --- a/arch/arm/mach-bcm/platsmp.c +++ b/arch/arm/mach-bcm/platsmp.c @@ -105,7 +105,7 @@ static int nsp_write_lut(unsigned int cpu) if (!secondary_boot_addr) return -EINVAL; - sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, + sku_rom_lut = ioremap((phys_addr_t)secondary_boot_addr, sizeof(phys_addr_t)); if (!sku_rom_lut) { pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu); @@ -174,7 +174,7 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) if (!secondary_boot_addr) return -EINVAL; - boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr, + boot_reg = ioremap((phys_addr_t)secondary_boot_addr, sizeof(phys_addr_t)); if (!boot_reg) { pr_err("unable to map boot register for cpu %u\n", cpu_id); diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 3e447d468845..e650131ee88f 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -34,7 +34,7 @@ void __iomem *davinci_sysmod_base; void davinci_map_sysmod(void) { - davinci_sysmod_base = ioremap_nocache(DAVINCI_SYSTEM_MODULE_BASE, + davinci_sysmod_base = ioremap(DAVINCI_SYSTEM_MODULE_BASE, 0x800); /* * Throw a bug since a lot of board initialization code depends diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index e1a394ac3eea..868dc0cf4859 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -1008,7 +1008,7 @@ static void __init magician_init(void) pxa_set_udc_info(&magician_udc_info); /* Check LCD type we have */ - cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000); + cpld = ioremap(PXA_CS3_PHYS, 0x1000); if (cpld) { u8 board_id = __raw_readb(cpld + 0x14); diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c index 96330ef25641..e771ce70e132 100644 --- a/arch/arm/mach-shmobile/platsmp-apmu.c +++ b/arch/arm/mach-shmobile/platsmp-apmu.c @@ -189,7 +189,7 @@ static void apmu_init_cpu(struct resource *res, int cpu, int bit) if ((cpu >= ARRAY_SIZE(apmu_cpus)) || apmu_cpus[cpu].iomem) return; - apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res)); + apmu_cpus[cpu].iomem = ioremap(res->start, resource_size(res)); apmu_cpus[cpu].bit = bit; pr_debug("apmu ioremap %d %d %pr\n", cpu, bit, res); diff --git a/arch/arm/mach-shmobile/pm-rcar-gen2.c b/arch/arm/mach-shmobile/pm-rcar-gen2.c index e84599dd96f1..672081405a7e 100644 --- a/arch/arm/mach-shmobile/pm-rcar-gen2.c +++ b/arch/arm/mach-shmobile/pm-rcar-gen2.c @@ -103,7 +103,7 @@ map: iounmap(p); /* setup reset vectors */ - p = ioremap_nocache(RST, 0x63); + p = ioremap(RST, 0x63); bar = phys_to_sbar(res.start); if (has_a15) { writel_relaxed(bar, p + CA15BAR); diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c index 787d039b5a07..f760c27c9907 100644 --- a/arch/arm/mach-shmobile/setup-r8a7740.c +++ b/arch/arm/mach-shmobile/setup-r8a7740.c @@ -28,7 +28,7 @@ static void __init r8a7740_meram_workaround(void) { void __iomem *reg; - reg = ioremap_nocache(MEBUFCNTR, 4); + reg = ioremap(MEBUFCNTR, 4); if (reg) { iowrite32(0x01600164, reg); iounmap(reg); @@ -37,9 +37,9 @@ static void __init r8a7740_meram_workaround(void) static void __init r8a7740_init_irq_of(void) { - void __iomem *intc_prio_base = ioremap_nocache(0xe6900010, 0x10); - void __iomem *intc_msk_base = ioremap_nocache(0xe6900040, 0x10); - void __iomem *pfc_inta_ctrl = ioremap_nocache(0xe605807c, 0x4); + void __iomem *intc_prio_base = ioremap(0xe6900010, 0x10); + void __iomem *intc_msk_base = ioremap(0xe6900040, 0x10); + void __iomem *pfc_inta_ctrl = ioremap(0xe605807c, 0x4); irqchip_init(); diff --git a/arch/arm/mach-shmobile/setup-r8a7778.c b/arch/arm/mach-shmobile/setup-r8a7778.c index ce51794f64c7..2bc93f391bcf 100644 --- a/arch/arm/mach-shmobile/setup-r8a7778.c +++ b/arch/arm/mach-shmobile/setup-r8a7778.c @@ -22,7 +22,7 @@ static void __init r8a7778_init_irq_dt(void) { - void __iomem *base = ioremap_nocache(0xfe700000, 0x00100000); + void __iomem *base = ioremap(0xfe700000, 0x00100000); BUG_ON(!base); diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h index b0dbc3473172..bda2a9c2df78 100644 --- a/arch/hexagon/include/asm/io.h +++ b/arch/hexagon/include/asm/io.h @@ -172,7 +172,6 @@ static inline void writel(u32 data, volatile void __iomem *addr) #define writel_relaxed __raw_writel void __iomem *ioremap(unsigned long phys_addr, unsigned long size); -#define ioremap_nocache ioremap #define ioremap_uc(X, Y) ioremap((X), (Y)) diff --git a/arch/ia64/include/asm/vga.h b/arch/ia64/include/asm/vga.h index 30cb373f3de8..64ce0b971a0a 100644 --- a/arch/ia64/include/asm/vga.h +++ b/arch/ia64/include/asm/vga.h @@ -18,7 +18,7 @@ extern unsigned long vga_console_iobase; extern unsigned long vga_console_membase; -#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap_nocache(vga_console_membase + (x), s)) +#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap(vga_console_membase + (x), s)) #define vga_readb(x) (*(x)) #define vga_writeb(x,y) (*(y) = (x)) diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c index f80eb7fb544d..258d7b70c0f3 100644 --- a/arch/ia64/kernel/cyclone.c +++ b/arch/ia64/kernel/cyclone.c @@ -50,7 +50,7 @@ int __init init_cyclone_clock(void) /* find base address */ offset = (CYCLONE_CBAR_ADDR); - reg = ioremap_nocache(offset, sizeof(u64)); + reg = ioremap(offset, sizeof(u64)); if(!reg){ printk(KERN_ERR "Summit chipset: Could not find valid CBAR" " register.\n"); @@ -68,7 +68,7 @@ int __init init_cyclone_clock(void) /* setup PMCC */ offset = (base + CYCLONE_PMCC_OFFSET); - reg = ioremap_nocache(offset, sizeof(u64)); + reg = ioremap(offset, sizeof(u64)); if(!reg){ printk(KERN_ERR "Summit chipset: Could not find valid PMCC" " register.\n"); @@ -80,7 +80,7 @@ int __init init_cyclone_clock(void) /* setup MPCS */ offset = (base + CYCLONE_MPCS_OFFSET); - reg = ioremap_nocache(offset, sizeof(u64)); + reg = ioremap(offset, sizeof(u64)); if(!reg){ printk(KERN_ERR "Summit chipset: Could not find valid MPCS" " register.\n"); @@ -92,7 +92,7 @@ int __init init_cyclone_clock(void) /* map in cyclone_timer */ offset = (base + CYCLONE_MPMC_OFFSET); - cyclone_timer = ioremap_nocache(offset, sizeof(u32)); + cyclone_timer = ioremap(offset, sizeof(u32)); if(!cyclone_timer){ printk(KERN_ERR "Summit chipset: Could not find valid MPMC" " register.\n"); diff --git a/arch/m68k/include/asm/kmap.h b/arch/m68k/include/asm/kmap.h index 559cb91bede1..dec05743d426 100644 --- a/arch/m68k/include/asm/kmap.h +++ b/arch/m68k/include/asm/kmap.h @@ -27,7 +27,6 @@ static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size) return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); } -#define ioremap_nocache ioremap #define ioremap_uc ioremap #define ioremap_wt ioremap_wt static inline void __iomem *ioremap_wt(unsigned long physaddr, diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c index 7de162432d7f..95def949c971 100644 --- a/arch/mips/ar7/clock.c +++ b/arch/mips/ar7/clock.c @@ -236,9 +236,9 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock, static void __init tnetd7300_init_clocks(void) { - u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4); struct tnetd7300_clocks *clocks = - ioremap_nocache(UR8_REGS_CLOCKS, + ioremap(UR8_REGS_CLOCKS, sizeof(struct tnetd7300_clocks)); bus_clk.rate = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, @@ -320,9 +320,9 @@ static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr) static void __init tnetd7200_init_clocks(void) { - u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); + u32 *bootcr = (u32 *)ioremap(AR7_REGS_DCL, 4); struct tnetd7200_clocks *clocks = - ioremap_nocache(AR7_REGS_CLOCKS, + ioremap(AR7_REGS_CLOCKS, sizeof(struct tnetd7200_clocks)); int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv; int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv; diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c index 2292e55c12e2..8b006addd6ba 100644 --- a/arch/mips/ar7/gpio.c +++ b/arch/mips/ar7/gpio.c @@ -308,7 +308,7 @@ int __init ar7_gpio_init(void) size = 0x1f; } - gpch->regs = ioremap_nocache(AR7_REGS_GPIO, size); + gpch->regs = ioremap(AR7_REGS_GPIO, size); if (!gpch->regs) { printk(KERN_ERR "%s: failed to ioremap regs\n", gpch->chip.label); diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c index 1f2028266493..215149a85d83 100644 --- a/arch/mips/ar7/platform.c +++ b/arch/mips/ar7/platform.c @@ -702,7 +702,7 @@ static int __init ar7_register_devices(void) pr_warn("unable to register usb slave: %d\n", res); /* Register watchdog only if enabled in hardware */ - bootcr = ioremap_nocache(AR7_REGS_DCL, 4); + bootcr = ioremap(AR7_REGS_DCL, 4); val = readl(bootcr); iounmap(bootcr); if (val & AR7_WDT_HW_ENA) { diff --git a/arch/mips/ath25/ar2315.c b/arch/mips/ath25/ar2315.c index 8da996142d6a..24f619199ee7 100644 --- a/arch/mips/ath25/ar2315.c +++ b/arch/mips/ath25/ar2315.c @@ -262,7 +262,7 @@ void __init ar2315_plat_mem_setup(void) u32 config; /* Detect memory size */ - sdram_base = ioremap_nocache(AR2315_SDRAMCTL_BASE, + sdram_base = ioremap(AR2315_SDRAMCTL_BASE, AR2315_SDRAMCTL_SIZE); memcfg = __raw_readl(sdram_base + AR2315_MEM_CFG); memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH); @@ -272,7 +272,7 @@ void __init ar2315_plat_mem_setup(void) add_memory_region(0, memsize, BOOT_MEM_RAM); iounmap(sdram_base); - ar2315_rst_base = ioremap_nocache(AR2315_RST_BASE, AR2315_RST_SIZE); + ar2315_rst_base = ioremap(AR2315_RST_BASE, AR2315_RST_SIZE); /* Detect the hardware based on the device ID */ devid = ar2315_rst_reg_read(AR2315_SREV) & AR2315_REV_CHIP; diff --git a/arch/mips/ath25/ar5312.c b/arch/mips/ath25/ar5312.c index acd55a9cffe3..47f3e98974fc 100644 --- a/arch/mips/ath25/ar5312.c +++ b/arch/mips/ath25/ar5312.c @@ -185,7 +185,7 @@ static void __init ar5312_flash_init(void) void __iomem *flashctl_base; u32 ctl; - flashctl_base = ioremap_nocache(AR5312_FLASHCTL_BASE, + flashctl_base = ioremap(AR5312_FLASHCTL_BASE, AR5312_FLASHCTL_SIZE); ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL0); @@ -358,7 +358,7 @@ void __init ar5312_plat_mem_setup(void) u32 devid; /* Detect memory size */ - sdram_base = ioremap_nocache(AR5312_SDRAMCTL_BASE, + sdram_base = ioremap(AR5312_SDRAMCTL_BASE, AR5312_SDRAMCTL_SIZE); memcfg = __raw_readl(sdram_base + AR5312_MEM_CFG1); bank0_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0); @@ -369,7 +369,7 @@ void __init ar5312_plat_mem_setup(void) add_memory_region(0, memsize, BOOT_MEM_RAM); iounmap(sdram_base); - ar5312_rst_base = ioremap_nocache(AR5312_RST_BASE, AR5312_RST_SIZE); + ar5312_rst_base = ioremap(AR5312_RST_BASE, AR5312_RST_SIZE); devid = ar5312_rst_reg_read(AR5312_REV); devid >>= AR5312_REV_WMAC_MIN_S; diff --git a/arch/mips/ath25/board.c b/arch/mips/ath25/board.c index 989e71015ee6..cb99f9739910 100644 --- a/arch/mips/ath25/board.c +++ b/arch/mips/ath25/board.c @@ -111,7 +111,7 @@ int __init ath25_find_config(phys_addr_t base, unsigned long size) u8 *mac_addr; u32 offset; - flash_base = ioremap_nocache(base, size); + flash_base = ioremap(base, size); flash_limit = flash_base + size; ath25_board.config = NULL; diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index 63eacb8b0eb5..137abbc65c60 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -41,7 +41,7 @@ static void __iomem *ath79_ddr_pci_win_base; void ath79_ddr_ctrl_init(void) { - ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, + ath79_ddr_base = ioremap(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE); if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) { ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c; diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index ea385a865781..484ee28922a9 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -226,9 +226,9 @@ void __init plat_mem_setup(void) else if (fw_passed_dtb) __dt_setup_arch((void *)KSEG0ADDR(fw_passed_dtb)); - ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE, + ath79_reset_base = ioremap(AR71XX_RESET_BASE, AR71XX_RESET_SIZE); - ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE, + ath79_pll_base = ioremap(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ath79_detect_sys_type(); ath79_ddr_ctrl_init(); diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 1f742c32a883..4f34d92b52f9 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -357,7 +357,7 @@ static void octeon_write_lcd(const char *s) { if (octeon_bootinfo->led_display_base_addr) { void __iomem *lcd_address = - ioremap_nocache(octeon_bootinfo->led_display_base_addr, + ioremap(octeon_bootinfo->led_display_base_addr, 8); int i; for (i = 0; i < 8; i++, s++) { diff --git a/arch/mips/generic/board-ocelot.c b/arch/mips/generic/board-ocelot.c index 06d92fb37769..c238e95190ac 100644 --- a/arch/mips/generic/board-ocelot.c +++ b/arch/mips/generic/board-ocelot.c @@ -51,7 +51,7 @@ static void __init ocelot_earlyprintk_init(void) { void __iomem *uart_base; - uart_base = ioremap_nocache(UART_UART, 0x20); + uart_base = ioremap(UART_UART, 0x20); setup_8250_early_printk_port((unsigned long)uart_base, 2, 50000); } diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index d9caa811a2fa..cf1f2a4a2418 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -227,7 +227,6 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, */ #define ioremap(offset, size) \ __ioremap_mode((offset), (size), _CACHE_UNCACHED) -#define ioremap_nocache ioremap #define ioremap_uc ioremap /* diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index e5ea3db23d6b..cdb93ed91cde 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -194,7 +194,7 @@ static void mips_cm_probe_l2sync(void) write_gcr_l2_only_sync_base(addr | CM_GCR_L2_ONLY_SYNC_BASE_SYNCEN); /* Map the region */ - mips_cm_l2sync_base = ioremap_nocache(addr, MIPS_CM_L2SYNC_SIZE); + mips_cm_l2sync_base = ioremap(addr, MIPS_CM_L2SYNC_SIZE); } int mips_cm_probe(void) @@ -215,7 +215,7 @@ int mips_cm_probe(void) if (!addr) return -ENODEV; - mips_gcr_base = ioremap_nocache(addr, MIPS_CM_GCR_SIZE); + mips_gcr_base = ioremap(addr, MIPS_CM_GCR_SIZE); if (!mips_gcr_base) return -ENXIO; diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index 69e3e0b556bf..8d2535123f11 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c @@ -78,7 +78,7 @@ int mips_cpc_probe(void) if (!addr) return -ENODEV; - mips_cpc_base = ioremap_nocache(addr, 0x8000); + mips_cpc_base = ioremap(addr, 0x8000); if (!mips_cpc_base) return -ENXIO; diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c index 037b08f3257e..42222f849bd2 100644 --- a/arch/mips/lantiq/falcon/sysctrl.c +++ b/arch/mips/lantiq/falcon/sysctrl.c @@ -221,16 +221,16 @@ void __init ltq_soc_init(void) res_sys[2].name) < 0)) pr_err("Failed to request core resources"); - status_membase = ioremap_nocache(res_status.start, + status_membase = ioremap(res_status.start, resource_size(&res_status)); - ltq_ebu_membase = ioremap_nocache(res_ebu.start, + ltq_ebu_membase = ioremap(res_ebu.start, resource_size(&res_ebu)); if (!status_membase || !ltq_ebu_membase) panic("Failed to remap core resources"); for (i = 0; i < 3; i++) { - sysctl_membase[i] = ioremap_nocache(res_sys[i].start, + sysctl_membase[i] = ioremap(res_sys[i].start, resource_size(&res_sys[i])); if (!sysctl_membase[i]) panic("Failed to remap sysctrl resources"); diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 115b417dfb8e..df8eed3875f6 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -349,7 +349,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) res.name)) pr_err("Failed to request icu%i memory\n", vpe); - ltq_icu_membase[vpe] = ioremap_nocache(res.start, + ltq_icu_membase[vpe] = ioremap(res.start, resource_size(&res)); if (!ltq_icu_membase[vpe]) @@ -402,7 +402,7 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent) res.name)) pr_err("Failed to request eiu memory"); - ltq_eiu_membase = ioremap_nocache(res.start, + ltq_eiu_membase = ioremap(res.start, resource_size(&res)); if (!ltq_eiu_membase) panic("Failed to remap eiu memory"); diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c index 156a95ac5c72..aa37545ebe8f 100644 --- a/arch/mips/lantiq/xway/sysctrl.c +++ b/arch/mips/lantiq/xway/sysctrl.c @@ -431,10 +431,10 @@ void __init ltq_soc_init(void) res_ebu.name)) pr_err("Failed to request core resources"); - pmu_membase = ioremap_nocache(res_pmu.start, resource_size(&res_pmu)); - ltq_cgu_membase = ioremap_nocache(res_cgu.start, + pmu_membase = ioremap(res_pmu.start, resource_size(&res_pmu)); + ltq_cgu_membase = ioremap(res_cgu.start, resource_size(&res_cgu)); - ltq_ebu_membase = ioremap_nocache(res_ebu.start, + ltq_ebu_membase = ioremap(res_ebu.start, resource_size(&res_ebu)); if (!pmu_membase || !ltq_cgu_membase || !ltq_ebu_membase) panic("Failed to remap core resources"); diff --git a/arch/mips/loongson2ef/common/reset.c b/arch/mips/loongson2ef/common/reset.c index e7c87161ce00..e49c40646995 100644 --- a/arch/mips/loongson2ef/common/reset.c +++ b/arch/mips/loongson2ef/common/reset.c @@ -17,11 +17,11 @@ static inline void loongson_reboot(void) { #ifndef CONFIG_CPU_JUMP_WORKAROUNDS - ((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) (); + ((void (*)(void))ioremap(LOONGSON_BOOT_BASE, 4)) (); #else void (*func)(void); - func = (void *)ioremap_nocache(LOONGSON_BOOT_BASE, 4); + func = (void *)ioremap(LOONGSON_BOOT_BASE, 4); __asm__ __volatile__( " .set noat \n" diff --git a/arch/mips/loongson32/common/prom.c b/arch/mips/loongson32/common/prom.c index 73dd25142484..fd76114fa3b0 100644 --- a/arch/mips/loongson32/common/prom.c +++ b/arch/mips/loongson32/common/prom.c @@ -26,13 +26,13 @@ void __init prom_init(void) memsize = DEFAULT_MEMSIZE; if (strstr(arcs_cmdline, "console=ttyS3")) - uart_base = ioremap_nocache(LS1X_UART3_BASE, 0x0f); + uart_base = ioremap(LS1X_UART3_BASE, 0x0f); else if (strstr(arcs_cmdline, "console=ttyS2")) - uart_base = ioremap_nocache(LS1X_UART2_BASE, 0x0f); + uart_base = ioremap(LS1X_UART2_BASE, 0x0f); else if (strstr(arcs_cmdline, "console=ttyS1")) - uart_base = ioremap_nocache(LS1X_UART1_BASE, 0x0f); + uart_base = ioremap(LS1X_UART1_BASE, 0x0f); else - uart_base = ioremap_nocache(LS1X_UART0_BASE, 0x0f); + uart_base = ioremap(LS1X_UART0_BASE, 0x0f); setup_8250_early_printk_port((unsigned long)uart_base, 0, 0); } diff --git a/arch/mips/loongson32/common/reset.c b/arch/mips/loongson32/common/reset.c index 6c36a414dde7..0c7399b303fb 100644 --- a/arch/mips/loongson32/common/reset.c +++ b/arch/mips/loongson32/common/reset.c @@ -37,7 +37,7 @@ static void ls1x_power_off(void) static int __init ls1x_reboot_setup(void) { - wdt_reg_base = ioremap_nocache(LS1X_WDT_BASE, (SZ_4 + SZ_8)); + wdt_reg_base = ioremap(LS1X_WDT_BASE, (SZ_4 + SZ_8)); if (!wdt_reg_base) panic("Failed to remap watchdog registers"); diff --git a/arch/mips/loongson32/common/time.c b/arch/mips/loongson32/common/time.c index f97662045c73..4cc73f7ac0d4 100644 --- a/arch/mips/loongson32/common/time.c +++ b/arch/mips/loongson32/common/time.c @@ -49,7 +49,7 @@ static inline void ls1x_pwmtimer_restart(void) void __init ls1x_pwmtimer_init(void) { - timer_reg_base = ioremap_nocache(LS1X_TIMER_BASE, SZ_16); + timer_reg_base = ioremap(LS1X_TIMER_BASE, SZ_16); if (!timer_reg_base) panic("Failed to remap timer registers"); diff --git a/arch/mips/loongson64/reset.c b/arch/mips/loongson64/reset.c index 88b3bd5fed25..bc7671079f0c 100644 --- a/arch/mips/loongson64/reset.c +++ b/arch/mips/loongson64/reset.c @@ -17,7 +17,7 @@ static inline void loongson_reboot(void) { - ((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) (); + ((void (*)(void))ioremap(LOONGSON_BOOT_BASE, 4)) (); } static void loongson_restart(char *command) diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c index 98a063093b69..0ddf03df6268 100644 --- a/arch/mips/mti-malta/malta-dtshim.c +++ b/arch/mips/mti-malta/malta-dtshim.c @@ -240,7 +240,7 @@ static void __init remove_gic(void *fdt) * On systems using the RocIT system controller a GIC may be * present without a CM. Detect whether that is the case. */ - biu_base = ioremap_nocache(MSC01_BIU_REG_BASE, + biu_base = ioremap(MSC01_BIU_REG_BASE, MSC01_BIU_ADDRSPACE_SZ); sc_cfg = __raw_readl(biu_base + MSC01_SC_CFG_OFS); if (sc_cfg & MSC01_SC_CFG_GICPRES_MSK) { diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index 4f2411f489af..01a2af8215c8 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -409,7 +409,7 @@ static int alchemy_pci_probe(struct platform_device *pdev) goto out6; } - ctx->regs = ioremap_nocache(r->start, resource_size(r)); + ctx->regs = ioremap(r->start, resource_size(r)); if (!ctx->regs) { dev_err(&pdev->dev, "cannot map pci regs\n"); ret = -ENODEV; diff --git a/arch/mips/pci/pci-ar2315.c b/arch/mips/pci/pci-ar2315.c index 0fed6fc17fe4..490953f51528 100644 --- a/arch/mips/pci/pci-ar2315.c +++ b/arch/mips/pci/pci-ar2315.c @@ -441,7 +441,7 @@ static int ar2315_pci_probe(struct platform_device *pdev) apc->mem_res.flags = IORESOURCE_MEM; /* Remap PCI config space */ - apc->cfg_mem = devm_ioremap_nocache(dev, res->start, + apc->cfg_mem = devm_ioremap(dev, res->start, AR2315_PCI_CFG_SIZE); if (!apc->cfg_mem) { dev_err(dev, "failed to remap PCI config space\n"); diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c index 151d9b5870bb..5548365605c0 100644 --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -221,7 +221,7 @@ static int __init bcm63xx_register_pci(void) * a spinlock for each io access, so this is currently kind of * broken on SMP. */ - pci_iospace_start = ioremap_nocache(BCM_PCI_IO_BASE_PA, 4); + pci_iospace_start = ioremap(BCM_PCI_IO_BASE_PA, 4); if (!pci_iospace_start) return -ENOMEM; diff --git a/arch/mips/pci/pci-rt2880.c b/arch/mips/pci/pci-rt2880.c index c9f4d4ba058a..e1f12e398136 100644 --- a/arch/mips/pci/pci-rt2880.c +++ b/arch/mips/pci/pci-rt2880.c @@ -218,7 +218,7 @@ static int rt288x_pci_probe(struct platform_device *pdev) { void __iomem *io_map_base; - rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE); + rt2880_pci_base = ioremap(RT2880_PCI_BASE, PAGE_SIZE); io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE); rt2880_pci_controller.io_map_base = (unsigned long) io_map_base; diff --git a/arch/mips/pic32/pic32mzda/early_console.c b/arch/mips/pic32/pic32mzda/early_console.c index 8c236738b5ee..25372e62783b 100644 --- a/arch/mips/pic32/pic32mzda/early_console.c +++ b/arch/mips/pic32/pic32mzda/early_console.c @@ -135,7 +135,7 @@ void __init fw_init_early_console(char port) char *arch_cmdline = pic32_getcmdline(); int baud = -1; - uart_base = ioremap_nocache(PIC32_BASE_UART, 0xc00); + uart_base = ioremap(PIC32_BASE_UART, 0xc00); baud = get_baud_from_cmdline(arch_cmdline); if (port == -1) diff --git a/arch/mips/pic32/pic32mzda/early_pin.c b/arch/mips/pic32/pic32mzda/early_pin.c index 504e6ab399b5..f2822632b017 100644 --- a/arch/mips/pic32/pic32mzda/early_pin.c +++ b/arch/mips/pic32/pic32mzda/early_pin.c @@ -122,7 +122,7 @@ static const struct void pic32_pps_input(int function, int pin) { - void __iomem *pps_base = ioremap_nocache(PPS_BASE, 0xF4); + void __iomem *pps_base = ioremap(PPS_BASE, 0xF4); int i; for (i = 0; i < ARRAY_SIZE(input_pin_reg); i++) { @@ -252,7 +252,7 @@ static const struct void pic32_pps_output(int function, int pin) { - void __iomem *pps_base = ioremap_nocache(PPS_BASE, 0x170); + void __iomem *pps_base = ioremap(PPS_BASE, 0x170); int i; for (i = 0; i < ARRAY_SIZE(output_pin_reg); i++) { diff --git a/arch/mips/pmcs-msp71xx/msp_serial.c b/arch/mips/pmcs-msp71xx/msp_serial.c index 8e6e8db8dd5f..940c684f6921 100644 --- a/arch/mips/pmcs-msp71xx/msp_serial.c +++ b/arch/mips/pmcs-msp71xx/msp_serial.c @@ -105,7 +105,7 @@ void __init msp_serial_setup(void) /* Initialize first serial port */ up.mapbase = MSP_UART0_BASE; - up.membase = ioremap_nocache(up.mapbase, MSP_UART_REG_LEN); + up.membase = ioremap(up.mapbase, MSP_UART_REG_LEN); up.irq = MSP_INT_UART0; up.uartclk = uartclk; up.regshift = 2; @@ -143,7 +143,7 @@ void __init msp_serial_setup(void) } up.mapbase = MSP_UART1_BASE; - up.membase = ioremap_nocache(up.mapbase, MSP_UART_REG_LEN); + up.membase = ioremap(up.mapbase, MSP_UART_REG_LEN); up.irq = MSP_INT_UART1; up.line = 1; up.private_data = (void*)UART1_STATUS_REG; diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c index c945d76cfce5..220ca0cd7945 100644 --- a/arch/mips/ralink/irq.c +++ b/arch/mips/ralink/irq.c @@ -165,7 +165,7 @@ static int __init intc_of_init(struct device_node *node, res.name)) pr_err("Failed to request intc memory"); - rt_intc_membase = ioremap_nocache(res.start, + rt_intc_membase = ioremap(res.start, resource_size(&res)); if (!rt_intc_membase) panic("Failed to remap intc memory"); diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c index 59b23095bfbb..90c6d4a11c5d 100644 --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c @@ -43,7 +43,7 @@ __iomem void *plat_of_remap_node(const char *node) res.name)) panic("Failed to request resources for %s", node); - return ioremap_nocache(res.start, resource_size(&res)); + return ioremap(res.start, resource_size(&res)); } void __init device_tree_init(void) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index c9ecf17f8660..dd34f1b32b79 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -286,7 +286,7 @@ static int __init plat_setup_devices(void) nand_slot0_res[0].end = nand_slot0_res[0].start + 0x1000; /* Read and map device controller 3 */ - dev3.base = ioremap_nocache(readl(IDT434_REG_BASE + DEV3BASE), 1); + dev3.base = ioremap(readl(IDT434_REG_BASE + DEV3BASE), 1); if (!dev3.base) { printk(KERN_ERR "rb532: cannot remap device controller 3\n"); diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index fdc704abc8d4..94f02ada4082 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -192,7 +192,7 @@ int __init rb532_gpio_init(void) struct resource *r; r = rb532_gpio_reg0_res; - rb532_gpio_chip->regbase = ioremap_nocache(r->start, resource_size(r)); + rb532_gpio_chip->regbase = ioremap(r->start, resource_size(r)); if (!rb532_gpio_chip->regbase) { printk(KERN_ERR "rb532: cannot remap GPIO register 0\n"); diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index 26e957b21fbf..303cc3dc1749 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c @@ -110,7 +110,7 @@ void __init prom_init(void) phys_addr_t memsize; phys_addr_t ddrbase; - ddr = ioremap_nocache(ddr_reg[0].start, + ddr = ioremap(ddr_reg[0].start, ddr_reg[0].end - ddr_reg[0].start); if (!ddr) { diff --git a/arch/mips/rb532/setup.c b/arch/mips/rb532/setup.c index 1aa4df1385cb..51af9d374d66 100644 --- a/arch/mips/rb532/setup.c +++ b/arch/mips/rb532/setup.c @@ -49,7 +49,7 @@ void __init plat_mem_setup(void) set_io_port_base(KSEG1); - pci_reg = ioremap_nocache(pci0_res[0].start, + pci_reg = ioremap(pci0_res[0].start, pci0_res[0].end - pci0_res[0].start); if (!pci_reg) { printk(KERN_ERR "Could not remap PCI registers\n"); diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c index 160b88000b4b..f6fa9afcbfd3 100644 --- a/arch/mips/sni/rm200.c +++ b/arch/mips/sni/rm200.c @@ -399,10 +399,10 @@ void __init sni_rm200_i8259_irqs(void) { int i; - rm200_pic_master = ioremap_nocache(0x16000020, 4); + rm200_pic_master = ioremap(0x16000020, 4); if (!rm200_pic_master) return; - rm200_pic_slave = ioremap_nocache(0x160000a0, 4); + rm200_pic_slave = ioremap(0x160000a0, 4); if (!rm200_pic_slave) { iounmap(rm200_pic_master); return; diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h index 46212b52c23e..cab8f64ca4a2 100644 --- a/arch/parisc/include/asm/io.h +++ b/arch/parisc/include/asm/io.h @@ -128,9 +128,8 @@ static inline void gsc_writeq(unsigned long long val, unsigned long addr) * The standard PCI ioremap interfaces */ void __iomem *ioremap(unsigned long offset, unsigned long size); -#define ioremap_nocache(off, sz) ioremap((off), (sz)) -#define ioremap_wc ioremap_nocache -#define ioremap_uc ioremap_nocache +#define ioremap_wc ioremap +#define ioremap_uc ioremap extern void iounmap(const volatile void __iomem *addr); diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 676683641d00..e1a8fee3ad49 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -792,7 +792,7 @@ static int perf_write_image(uint64_t *memaddr) return -1; } - runway = ioremap_nocache(cpu_device->hpa.start, 4096); + runway = ioremap(cpu_device->hpa.start, 4096); if (!runway) { pr_err("perf_write_image: ioremap failed!\n"); return -ENOMEM; diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index a63ec938636d..635969b5b58e 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h @@ -691,8 +691,6 @@ static inline void iosync(void) * * ioremap_prot allows to specify the page flags as an argument and can * also be hooked by the platform via ppc_md. * - * * ioremap_nocache is identical to ioremap - * * * ioremap_wc enables write combining * * * ioremap_wt enables write through @@ -715,7 +713,6 @@ extern void __iomem *ioremap_prot(phys_addr_t address, unsigned long size, extern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size); void __iomem *ioremap_wt(phys_addr_t address, unsigned long size); void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size); -#define ioremap_nocache(addr, size) ioremap((addr), (size)) #define ioremap_uc(addr, size) ioremap((addr), (size)) #define ioremap_cache(addr, size) \ ioremap_prot((addr), (size), pgprot_val(PAGE_KERNEL)) diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index d964c4d6b139..77dad1e511b4 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c @@ -341,7 +341,7 @@ static void __init sh7785lcr_setup(char **cmdline_p) pm_power_off = sh7785lcr_power_off; /* sm501 DRAM configuration */ - sm501_reg = ioremap_nocache(SM107_REG_ADDR, SM501_DRAM_CONTROL); + sm501_reg = ioremap(SM107_REG_ADDR, SM501_DRAM_CONTROL); if (!sm501_reg) { printk(KERN_ERR "%s: ioremap error.\n", __func__); return; diff --git a/arch/sh/boards/mach-cayman/irq.c b/arch/sh/boards/mach-cayman/irq.c index 9108789fafef..3b6ea2d99013 100644 --- a/arch/sh/boards/mach-cayman/irq.c +++ b/arch/sh/boards/mach-cayman/irq.c @@ -137,7 +137,7 @@ void init_cayman_irq(void) { int i; - epld_virt = (unsigned long)ioremap_nocache(EPLD_BASE, 1024); + epld_virt = (unsigned long)ioremap(EPLD_BASE, 1024); if (!epld_virt) { printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n"); return; diff --git a/arch/sh/boards/mach-cayman/setup.c b/arch/sh/boards/mach-cayman/setup.c index 4cec14700adc..8ef76e288da0 100644 --- a/arch/sh/boards/mach-cayman/setup.c +++ b/arch/sh/boards/mach-cayman/setup.c @@ -99,7 +99,7 @@ static int __init smsc_superio_setup(void) { unsigned char devid, devrev; - smsc_superio_virt = (unsigned long)ioremap_nocache(SMSC_SUPERIO_BASE, 1024); + smsc_superio_virt = (unsigned long)ioremap(SMSC_SUPERIO_BASE, 1024); if (!smsc_superio_virt) { panic("Unable to remap SMSC SuperIO\n"); } diff --git a/arch/sh/boards/mach-sdk7786/fpga.c b/arch/sh/boards/mach-sdk7786/fpga.c index 895576ff8376..a37e1e88c6b1 100644 --- a/arch/sh/boards/mach-sdk7786/fpga.c +++ b/arch/sh/boards/mach-sdk7786/fpga.c @@ -32,7 +32,7 @@ static void __iomem *sdk7786_fpga_probe(void) * is reserved. */ for (area = PA_AREA0; area < PA_AREA7; area += SZ_64M) { - base = ioremap_nocache(area + FPGA_REGS_OFFSET, FPGA_REGS_SIZE); + base = ioremap(area + FPGA_REGS_OFFSET, FPGA_REGS_SIZE); if (!base) { /* Failed to remap this area, move along. */ continue; diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c index cf2fcccca812..24391b444b28 100644 --- a/arch/sh/drivers/heartbeat.c +++ b/arch/sh/drivers/heartbeat.c @@ -96,7 +96,7 @@ static int heartbeat_drv_probe(struct platform_device *pdev) return -ENOMEM; } - hd->base = ioremap_nocache(res->start, resource_size(res)); + hd->base = ioremap(res->start, resource_size(res)); if (unlikely(!hd->base)) { dev_err(&pdev->dev, "ioremap failed\n"); diff --git a/arch/sh/drivers/pci/pci-sh5.c b/arch/sh/drivers/pci/pci-sh5.c index 49303fab187b..03225d27770b 100644 --- a/arch/sh/drivers/pci/pci-sh5.c +++ b/arch/sh/drivers/pci/pci-sh5.c @@ -115,12 +115,12 @@ static int __init sh5pci_init(void) return -EINVAL; } - pcicr_virt = (unsigned long)ioremap_nocache(SH5PCI_ICR_BASE, 1024); + pcicr_virt = (unsigned long)ioremap(SH5PCI_ICR_BASE, 1024); if (!pcicr_virt) { panic("Unable to remap PCICR\n"); } - PCI_IO_AREA = (unsigned long)ioremap_nocache(SH5PCI_IO_BASE, 0x10000); + PCI_IO_AREA = (unsigned long)ioremap(SH5PCI_IO_BASE, 0x10000); if (!PCI_IO_AREA) { panic("Unable to remap PCIIO\n"); } diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 1495489225ac..39c9ead489e5 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -367,7 +367,6 @@ static inline void ioremap_fixed_init(void) { } static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; } #endif -#define ioremap_nocache ioremap #define ioremap_uc ioremap /* diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index 744f903b4df3..1b3050facda8 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c @@ -124,7 +124,7 @@ void __init plat_irq_setup(void) unsigned long reg; int i; - intc_virt = (unsigned long)ioremap_nocache(INTC_BASE, 1024); + intc_virt = (unsigned long)ioremap(INTC_BASE, 1024); if (!intc_virt) { panic("Unable to remap INTC\n"); } diff --git a/arch/sh/kernel/cpu/sh2/smp-j2.c b/arch/sh/kernel/cpu/sh2/smp-j2.c index ae44dc24c455..d0d5d81455ae 100644 --- a/arch/sh/kernel/cpu/sh2/smp-j2.c +++ b/arch/sh/kernel/cpu/sh2/smp-j2.c @@ -88,8 +88,8 @@ static void j2_start_cpu(unsigned int cpu, unsigned long entry_point) if (!np) return; if (of_property_read_u32_array(np, "cpu-release-addr", regs, 2)) return; - release = ioremap_nocache(regs[0], sizeof(u32)); - initpc = ioremap_nocache(regs[1], sizeof(u32)); + release = ioremap(regs[0], sizeof(u32)); + initpc = ioremap(regs[1], sizeof(u32)); __raw_writel(entry_point, initpc); __raw_writel(1, release); diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c index 43763c26a752..dee6be2c2344 100644 --- a/arch/sh/kernel/cpu/sh5/clock-sh5.c +++ b/arch/sh/kernel/cpu/sh5/clock-sh5.c @@ -68,7 +68,7 @@ static struct sh_clk_ops *sh5_clk_ops[] = { void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) { - cprc_base = (unsigned long)ioremap_nocache(CPRC_BASE, 1024); + cprc_base = (unsigned long)ioremap(CPRC_BASE, 1024); BUG_ON(!cprc_base); if (idx < ARRAY_SIZE(sh5_clk_ops)) diff --git a/arch/sh/kernel/dma-coherent.c b/arch/sh/kernel/dma-coherent.c index eeb25a4fa55f..d4811691b93c 100644 --- a/arch/sh/kernel/dma-coherent.c +++ b/arch/sh/kernel/dma-coherent.c @@ -28,7 +28,7 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, arch_sync_dma_for_device(virt_to_phys(ret), size, DMA_BIDIRECTIONAL); - ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size); + ret_nocache = (void __force *)ioremap(virt_to_phys(ret), size); if (!ret_nocache) { free_pages((unsigned long)ret, order); return NULL; diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h index f4afa301954a..9bb27e5c22f1 100644 --- a/arch/sparc/include/asm/io_64.h +++ b/arch/sparc/include/asm/io_64.h @@ -406,7 +406,6 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size) return (void __iomem *)offset; } -#define ioremap_nocache(X,Y) ioremap((X),(Y)) #define ioremap_uc(X,Y) ioremap((X),(Y)) #define ioremap_wc(X,Y) ioremap((X),(Y)) #define ioremap_wt(X,Y) ioremap((X),(Y)) diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h index 4b460e01acfa..3ca74e1cde7d 100644 --- a/arch/unicore32/include/asm/io.h +++ b/arch/unicore32/include/asm/io.h @@ -31,7 +31,6 @@ extern void __uc32_iounmap(volatile void __iomem *addr); * */ #define ioremap(cookie, size) __uc32_ioremap(cookie, size) -#define ioremap_nocache(cookie, size) __uc32_ioremap(cookie, size) #define iounmap(cookie) __uc32_iounmap(cookie) #define readb_relaxed readb diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 5da106f84e84..fe698f96617c 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c @@ -95,7 +95,7 @@ static inline void apbt_set_mapping(void) printk(KERN_WARNING "No timer base from SFI, use default\n"); apbt_address = APBT_DEFAULT_BASE; } - apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE); + apbt_virt_address = ioremap(apbt_address, APBT_MMAP_SIZE); if (!apbt_virt_address) { pr_debug("Failed mapping APBT phy address at %lu\n",\ (unsigned long)apbt_address); diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index c6f791bc481e..7a50f0b62a70 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -84,7 +84,7 @@ static inline void hpet_writel(unsigned int d, unsigned int a) static inline void hpet_set_mapping(void) { - hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE); + hpet_virt_address = ioremap(hpet_address, HPET_MMAP_SIZE); } static inline void hpet_clear_mapping(void) diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 1daf8f2aa21f..896d74cb5081 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -110,7 +110,7 @@ static void ich_force_enable_hpet(struct pci_dev *dev) } /* use bits 31:14, 16 kB aligned */ - rcba_base = ioremap_nocache(rcba, 0x4000); + rcba_base = ioremap(rcba, 0x4000); if (rcba_base == NULL) { dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; " "cannot force enable HPET\n"); diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 4c61f0713832..b89f6ac6a0c0 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -354,7 +354,7 @@ static ssize_t tboot_log_read(struct file *file, char __user *user_buf, size_t c void *kbuf; int ret = -EFAULT; - log_base = ioremap_nocache(TBOOT_SERIAL_LOG_ADDR, TBOOT_SERIAL_LOG_SIZE); + log_base = ioremap(TBOOT_SERIAL_LOG_ADDR, TBOOT_SERIAL_LOG_SIZE); if (!log_base) return ret; diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index 92153d054d6c..bda73cb7a044 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c @@ -79,7 +79,7 @@ static void do_read_far_test(void __iomem *p) static void do_test(unsigned long size) { - void __iomem *p = ioremap_nocache(mmio_address, size); + void __iomem *p = ioremap(mmio_address, size); if (!p) { pr_err("could not ioremap, aborting.\n"); return; @@ -104,7 +104,7 @@ static void do_test_bulk_ioremapping(void) int i; for (i = 0; i < 10; ++i) { - p = ioremap_nocache(mmio_address, PAGE_SIZE); + p = ioremap(mmio_address, PAGE_SIZE); if (p) iounmap(p); } diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index 887d181b769b..0c7b6e66c644 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -105,7 +105,7 @@ static void __iomem *mcfg_ioremap(struct pci_mmcfg_region *cfg) start = cfg->address + PCI_MMCFG_BUS_OFFSET(cfg->start_bus); num_buses = cfg->end_bus - cfg->start_bus + 1; size = PCI_MMCFG_BUS_OFFSET(num_buses); - addr = ioremap_nocache(start, size); + addr = ioremap(start, size); if (addr) addr -= PCI_MMCFG_BUS_OFFSET(cfg->start_bus); return addr; diff --git a/drivers/acpi/acpi_lpit.c b/drivers/acpi/acpi_lpit.c index 433376e819bb..953437a216f6 100644 --- a/drivers/acpi/acpi_lpit.c +++ b/drivers/acpi/acpi_lpit.c @@ -104,7 +104,7 @@ static void lpit_update_residency(struct lpit_residency_info *info, info->gaddr = lpit_native->residency_counter; if (info->gaddr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - info->iomem_addr = ioremap_nocache(info->gaddr.address, + info->iomem_addr = ioremap(info->gaddr.address, info->gaddr.bit_width / 8); if (!info->iomem_addr) return; diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 135173c8d138..391dff0f25a2 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -824,7 +824,7 @@ static int arasan_cf_probe(struct platform_device *pdev) quirk |= CF_BROKEN_MWDMA | CF_BROKEN_UDMA; acdev->pbase = res->start; - acdev->vbase = devm_ioremap_nocache(&pdev->dev, res->start, + acdev->vbase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!acdev->vbase) { dev_warn(&pdev->dev, "ioremap fail\n"); diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index d3d851b014a3..bd87476ab481 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -891,7 +891,7 @@ static int octeon_cf_probe(struct platform_device *pdev) of_node_put(dma_node); return -EINVAL; } - cf_port->dma_base = (u64)devm_ioremap_nocache(&pdev->dev, res_dma->start, + cf_port->dma_base = (u64)devm_ioremap(&pdev->dev, res_dma->start, resource_size(res_dma)); if (!cf_port->dma_base) { of_node_put(dma_node); @@ -909,7 +909,7 @@ static int octeon_cf_probe(struct platform_device *pdev) if (!res_cs1) return -EINVAL; - cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start, + cs1 = devm_ioremap(&pdev->dev, res_cs1->start, resource_size(res_cs1)); if (!cs1) return rv; @@ -925,7 +925,7 @@ static int octeon_cf_probe(struct platform_device *pdev) if (!res_cs0) return -EINVAL; - cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start, + cs0 = devm_ioremap(&pdev->dev, res_cs0->start, resource_size(res_cs0)); if (!cs0) return rv; diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index deae466395de..479c4b29b856 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -140,7 +140,7 @@ static int rb532_pata_driver_probe(struct platform_device *pdev) info->gpio_line = gpiod; info->irq = irq; - info->iobase = devm_ioremap_nocache(&pdev->dev, res->start, + info->iobase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!info->iobase) return -ENOMEM; diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index b23d1e4bad33..8fad56f185ba 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -31,12 +31,6 @@ #include "suni.h" #include "eni.h" -#if !defined(__i386__) && !defined(__x86_64__) -#ifndef ioremap_nocache -#define ioremap_nocache(X,Y) ioremap(X,Y) -#endif -#endif - /* * TODO: * @@ -1725,7 +1719,7 @@ static int eni_do_init(struct atm_dev *dev) } printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,", dev->number,pci_dev->revision,real_base,eni_dev->irq); - if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) { + if (!(base = ioremap(real_base,MAP_MAX_SIZE))) { printk("\n"); printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page " "mapping\n",dev->number); diff --git a/drivers/bcma/driver_chipcommon_b.c b/drivers/bcma/driver_chipcommon_b.c index 57f10b58b47c..c153c96a6145 100644 --- a/drivers/bcma/driver_chipcommon_b.c +++ b/drivers/bcma/driver_chipcommon_b.c @@ -48,7 +48,7 @@ int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb) return 0; ccb->setup_done = 1; - ccb->mii = ioremap_nocache(ccb->core->addr_s[1], BCMA_CORE_SIZE); + ccb->mii = ioremap(ccb->core->addr_s[1], BCMA_CORE_SIZE); if (!ccb->mii) return -ENOMEM; diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index c42cec7c7ecc..88a93c266c19 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c @@ -115,7 +115,7 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, if (unlikely(!addr)) goto out; err = -ENOMEM; - mmio = ioremap_nocache(addr, sizeof(val)); + mmio = ioremap(addr, sizeof(val)); if (!mmio) goto out; @@ -180,7 +180,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, if (unlikely(!addr)) goto out; err = -ENOMEM; - mmio = ioremap_nocache(addr, sizeof(val)); + mmio = ioremap(addr, sizeof(val)); if (!mmio) goto out; @@ -515,7 +515,7 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) /* Ok, ready to run, register it to the system. * The following needs change, if we want to port hostmode * to non-MIPS platform. */ - io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start, + io_map_base = (unsigned long)ioremap(pc_host->mem_resource.start, resource_size(&pc_host->mem_resource)); pc_host->pci_controller.io_map_base = io_map_base; set_io_port_base(pc_host->pci_controller.io_map_base); diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c index c8073b509a2b..90d5bdc12e03 100644 --- a/drivers/bcma/host_soc.c +++ b/drivers/bcma/host_soc.c @@ -172,7 +172,7 @@ int __init bcma_host_soc_register(struct bcma_soc *soc) /* iomap only first core. We have to read some register on this core * to scan the bus. */ - bus->mmio = ioremap_nocache(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1); + bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1); if (!bus->mmio) return -ENOMEM; diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 4a2d1b235fb5..fd546c51b076 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -425,11 +425,11 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, } } if (bus->hosttype == BCMA_HOSTTYPE_SOC) { - core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE); + core->io_addr = ioremap(core->addr, BCMA_CORE_SIZE); if (!core->io_addr) return -ENOMEM; if (core->wrap) { - core->io_wrap = ioremap_nocache(core->wrap, + core->io_wrap = ioremap(core->wrap, BCMA_CORE_SIZE); if (!core->io_wrap) { iounmap(core->io_addr); @@ -472,7 +472,7 @@ int bcma_bus_scan(struct bcma_bus *bus) erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); if (bus->hosttype == BCMA_HOSTTYPE_SOC) { - eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE); + eromptr = ioremap(erombase, BCMA_CORE_SIZE); if (!eromptr) return -ENOMEM; } else { diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 1f3f9e0f02a8..4eaf97d7a170 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -827,7 +827,7 @@ static int mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) goto failed_req_csr; } - card->csr_remap = ioremap_nocache(csr_base, csr_len); + card->csr_remap = ioremap(csr_base, csr_len); if (!card->csr_remap) { dev_printk(KERN_ERR, &card->dev->dev, "Unable to remap memory region\n"); diff --git a/drivers/bus/fsl-mc/mc-io.c b/drivers/bus/fsl-mc/mc-io.c index d9629fc13a15..6ae48ad80409 100644 --- a/drivers/bus/fsl-mc/mc-io.c +++ b/drivers/bus/fsl-mc/mc-io.c @@ -97,12 +97,12 @@ int __must_check fsl_create_mc_io(struct device *dev, return -EBUSY; } - mc_portal_virt_addr = devm_ioremap_nocache(dev, + mc_portal_virt_addr = devm_ioremap(dev, mc_portal_phys_addr, mc_portal_size); if (!mc_portal_virt_addr) { dev_err(dev, - "devm_ioremap_nocache failed for MC portal %pa\n", + "devm_ioremap failed for MC portal %pa\n", &mc_portal_phys_addr); return -ENXIO; } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index ab154a75acf0..9e84239f88d4 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -941,7 +941,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) bridge->gatt_table = (u32 __iomem *)table; #else - bridge->gatt_table = ioremap_nocache(virt_to_phys(table), + bridge->gatt_table = ioremap(virt_to_phys(table), (PAGE_SIZE * (1 << page_order))); bridge->driver->cache_flush(); #endif diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index c6271ce250b3..66a62d17a3f5 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1087,7 +1087,7 @@ static void intel_i9xx_setup_flush(void) } if (intel_private.ifp_resource.start) - intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); + intel_private.i9xx_flush_page = ioremap(intel_private.ifp_resource.start, PAGE_SIZE); if (!intel_private.i9xx_flush_page) dev_err(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing\n"); diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index eb108b3c619a..51121a4b82c7 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -204,7 +204,7 @@ static int __init applicom_init(void) if (pci_enable_device(dev)) return -EIO; - RamIO = ioremap_nocache(pci_resource_start(dev, 0), LEN_RAM_IO); + RamIO = ioremap(pci_resource_start(dev, 0), LEN_RAM_IO); if (!RamIO) { printk(KERN_INFO "ac.o: Failed to ioremap PCI memory " @@ -259,7 +259,7 @@ static int __init applicom_init(void) /* Now try the specified ISA cards */ for (i = 0; i < MAX_ISA_BOARD; i++) { - RamIO = ioremap_nocache(mem + (LEN_RAM_IO * i), LEN_RAM_IO); + RamIO = ioremap(mem + (LEN_RAM_IO * i), LEN_RAM_IO); if (!RamIO) { printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n", i + 1); diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 290c880266bf..9f205bd1acc0 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -317,7 +317,7 @@ PFX "RNG, try using the 'no_fwh_detect' option.\n"; return -EBUSY; } - intel_rng_hw->mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); + intel_rng_hw->mem = ioremap(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); if (intel_rng_hw->mem == NULL) return -EBUSY; diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c index 8c78aa090492..7be8067ac4e8 100644 --- a/drivers/char/hw_random/octeon-rng.c +++ b/drivers/char/hw_random/octeon-rng.c @@ -81,13 +81,13 @@ static int octeon_rng_probe(struct platform_device *pdev) return -ENOENT; - rng->control_status = devm_ioremap_nocache(&pdev->dev, + rng->control_status = devm_ioremap(&pdev->dev, res_ports->start, sizeof(u64)); if (!rng->control_status) return -ENOENT; - rng->result = devm_ioremap_nocache(&pdev->dev, + rng->result = devm_ioremap(&pdev->dev, res_result->start, sizeof(u64)); if (!rng->result) diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c index fbc34beafc78..7b703f14e20b 100644 --- a/drivers/clk/renesas/clk-rz.c +++ b/drivers/clk/renesas/clk-rz.c @@ -37,8 +37,8 @@ static u16 __init rz_cpg_read_mode_pins(void) void __iomem *ppr0, *pibc0; u16 modes; - ppr0 = ioremap_nocache(PPR0, 2); - pibc0 = ioremap_nocache(PIBC0, 2); + ppr0 = ioremap(PPR0, 2); + pibc0 = ioremap(PIBC0, 2); BUG_ON(!ppr0 || !pibc0); iowrite16(4, pibc0); /* enable input buffer */ modes = ioread16(ppr0); diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 9cde50cb3220..12ac75f7571f 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -905,7 +905,7 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt) return -ENXIO; } - cmt->mapbase = ioremap_nocache(mem->start, resource_size(mem)); + cmt->mapbase = ioremap(mem->start, resource_size(mem)); if (cmt->mapbase == NULL) { dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n"); return -ENXIO; diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 64526e50d471..bfccb31e94ad 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -377,7 +377,7 @@ static int sh_mtu2_map_memory(struct sh_mtu2_device *mtu) return -ENXIO; } - mtu->mapbase = ioremap_nocache(res->start, resource_size(res)); + mtu->mapbase = ioremap(res->start, resource_size(res)); if (mtu->mapbase == NULL) return -ENXIO; diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index d49690d15536..d41df9ba3725 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -486,7 +486,7 @@ static int sh_tmu_map_memory(struct sh_tmu_device *tmu) return -ENXIO; } - tmu->mapbase = ioremap_nocache(res->start, resource_size(res)); + tmu->mapbase = ioremap(res->start, resource_size(res)); if (tmu->mapbase == NULL) return -ENXIO; diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index fdc767fdbe6a..89d4fa8b65e9 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -445,7 +445,7 @@ static int __init pcc_cpufreq_probe(void) goto out_free; } - pcch_virt_addr = ioremap_nocache(mem_resource->minimum, + pcch_virt_addr = ioremap(mem_resource->minimum, mem_resource->address_length); if (pcch_virt_addr == NULL) { pr_debug("probe: could not map shared mem region\n"); diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 4e7323884ae3..354836468c5d 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -2507,7 +2507,7 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id) addr = pci_resource_start(pdev, i); size = pci_resource_len(pdev, i); - dev->bar[i] = ioremap_nocache(addr, size); + dev->bar[i] = ioremap(addr, size); if (!dev->bar[i]) { err = -ENOMEM; goto err_out_unmap_bars; diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index 832aefbe7af9..539e785039ca 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -772,10 +772,10 @@ static int request_and_map(struct platform_device *pdev, const char *name, return -EBUSY; } - *ptr = devm_ioremap_nocache(device, region->start, + *ptr = devm_ioremap(device, region->start, resource_size(region)); if (*ptr == NULL) { - dev_err(device, "ioremap_nocache of %s failed!", name); + dev_err(device, "ioremap of %s failed!", name); return -ENOMEM; } diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index f564a4a8a4ae..5c1eea96230c 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c @@ -324,7 +324,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *) & mchbar); mchbar &= I3000_MCHBAR_MASK; - window = ioremap_nocache(mchbar, I3000_MMR_WINDOW_SIZE); + window = ioremap(mchbar, I3000_MMR_WINDOW_SIZE); if (!window) { printk(KERN_ERR "i3000: cannot map mmio space at 0x%lx\n", mchbar); diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index 432b375a4075..a8988db6d423 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c @@ -280,7 +280,7 @@ static void __iomem *i3200_map_mchbar(struct pci_dev *pdev) return NULL; } - window = ioremap_nocache(u.mchbar, I3200_MMR_WINDOW_SIZE); + window = ioremap(u.mchbar, I3200_MMR_WINDOW_SIZE); if (!window) printk(KERN_ERR "i3200: cannot map mmio space at 0x%llx\n", (unsigned long long)u.mchbar); diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c index 7c6a2d4d2360..6be99e0d850d 100644 --- a/drivers/edac/i82975x_edac.c +++ b/drivers/edac/i82975x_edac.c @@ -485,7 +485,7 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */ - mch_window = ioremap_nocache(mchbar, 0x1000); + mch_window = ioremap(mchbar, 0x1000); if (!mch_window) { edac_dbg(3, "error ioremapping MCHBAR!\n"); goto fail0; diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c index 4f65073f230b..d68346a8e141 100644 --- a/drivers/edac/ie31200_edac.c +++ b/drivers/edac/ie31200_edac.c @@ -357,7 +357,7 @@ static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev) return NULL; } - window = ioremap_nocache(u.mchbar, IE31200_MMR_WINDOW_SIZE); + window = ioremap(u.mchbar, IE31200_MMR_WINDOW_SIZE); if (!window) ie31200_printk(KERN_ERR, "Cannot map mmio space at 0x%llx\n", (unsigned long long)u.mchbar); diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index cc779f3f9e2d..a65e2f78a402 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c @@ -266,7 +266,7 @@ static void __iomem *x38_map_mchbar(struct pci_dev *pdev) return NULL; } - window = ioremap_nocache(u.mchbar, X38_MMR_WINDOW_SIZE); + window = ioremap(u.mchbar, X38_MMR_WINDOW_SIZE); if (!window) printk(KERN_ERR "x38: cannot map mmio space at 0x%llx\n", (unsigned long long)u.mchbar); diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 0cc746673677..6ca2f5ab6c57 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -551,7 +551,7 @@ add_card(struct pci_dev *dev, const struct pci_device_id *unused) INIT_LIST_HEAD(&lynx->client_list); kref_init(&lynx->kref); - lynx->registers = ioremap_nocache(pci_resource_start(dev, 0), + lynx->registers = ioremap(pci_resource_start(dev, 0), PCILYNX_MAX_REGISTER); if (lynx->registers == NULL) { dev_err(&dev->dev, "Failed to map registers\n"); diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index da04fdae62a1..835ece9c00f1 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -120,7 +120,7 @@ int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) void __iomem *iobase; int err; - iobase = ioremap_nocache(base, lim); + iobase = ioremap(base, lim); if (!iobase) return -ENOMEM; diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index afaf4bea21cf..9278bcfad1bf 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -503,7 +503,7 @@ int psb_gtt_init(struct drm_device *dev, int resume) * Map the GTT and the stolen memory area */ if (!resume) - dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, + dev_priv->gtt_map = ioremap(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT); if (!dev_priv->gtt_map) { dev_err(dev->dev, "Failure to map gtt.\n"); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 7005f8f69c68..0900052fc484 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -256,7 +256,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) PSB_AUX_RESOURCE); resource_len = pci_resource_len(dev_priv->aux_pdev, PSB_AUX_RESOURCE); - dev_priv->aux_reg = ioremap_nocache(resource_start, + dev_priv->aux_reg = ioremap(resource_start, resource_len); if (!dev_priv->aux_reg) goto out_err; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index 2fd4ca91a62d..8dd5a43e5486 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -211,7 +211,7 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) ioaddr = pci_resource_start(pdev, 1); iosize = pci_resource_len(pdev, 1); - priv->mmio = devm_ioremap_nocache(dev->dev, ioaddr, iosize); + priv->mmio = devm_ioremap(dev->dev, ioaddr, iosize); if (!priv->mmio) { DRM_ERROR("Cannot map mmio region\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6239a9adbf14..f24064893b30 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2847,7 +2847,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) * readback check when writing GTT PTE entries. */ if (IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 10) - ggtt->gsm = ioremap_nocache(phys_addr, size); + ggtt->gsm = ioremap(phys_addr, size); else ggtt->gsm = ioremap_wc(phys_addr, size); if (!ggtt->gsm) { diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c84f0a8b3f2c..ac678ace09a3 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -138,7 +138,7 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, size = resource_size(res); - ptr = devm_ioremap_nocache(&pdev->dev, res->start, size); + ptr = devm_ioremap(&pdev->dev, res->start, size); if (!ptr) { DRM_DEV_ERROR(&pdev->dev, "failed to ioremap: %s\n", name); return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 098bc9f40b98..15bf8a207cb0 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -443,7 +443,7 @@ static int radeon_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_ mem->bus.size); else mem->bus.addr = - ioremap_nocache(mem->bus.base + mem->bus.offset, + ioremap(mem->bus.base + mem->bus.offset, mem->bus.size); if (!mem->bus.addr) return -ENOMEM; diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 68289b0b063a..68261c7f8c5f 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -534,7 +534,7 @@ static int sti_dvo_probe(struct platform_device *pdev) DRM_ERROR("Invalid dvo resource\n"); return -ENOMEM; } - dvo->regs = devm_ioremap_nocache(dev, res->start, + dvo->regs = devm_ioremap(dev, res->start, resource_size(res)); if (!dvo->regs) return -ENOMEM; diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c index 8f7bf33815fd..2bb32009d117 100644 --- a/drivers/gpu/drm/sti/sti_hda.c +++ b/drivers/gpu/drm/sti/sti_hda.c @@ -759,14 +759,14 @@ static int sti_hda_probe(struct platform_device *pdev) DRM_ERROR("Invalid hda resource\n"); return -ENOMEM; } - hda->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + hda->regs = devm_ioremap(dev, res->start, resource_size(res)); if (!hda->regs) return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "video-dacs-ctrl"); if (res) { - hda->video_dacs_ctrl = devm_ioremap_nocache(dev, res->start, + hda->video_dacs_ctrl = devm_ioremap(dev, res->start, resource_size(res)); if (!hda->video_dacs_ctrl) return -ENOMEM; diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 814560ead4e1..64ed102033c8 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -1393,7 +1393,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) ret = -ENOMEM; goto release_adapter; } - hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + hdmi->regs = devm_ioremap(dev, res->start, resource_size(res)); if (!hdmi->regs) { ret = -ENOMEM; goto release_adapter; diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index 5767e93dd1cd..c36a8da373cb 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -860,7 +860,7 @@ static int sti_tvout_probe(struct platform_device *pdev) DRM_ERROR("Invalid glue resource\n"); return -ENOMEM; } - tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + tvout->regs = devm_ioremap(dev, res->start, resource_size(res)); if (!tvout->regs) return -ENOMEM; diff --git a/drivers/gpu/drm/sti/sti_vtg.c b/drivers/gpu/drm/sti/sti_vtg.c index 0b17ac8a3faa..5e5f82b6a5d9 100644 --- a/drivers/gpu/drm/sti/sti_vtg.c +++ b/drivers/gpu/drm/sti/sti_vtg.c @@ -393,7 +393,7 @@ static int vtg_probe(struct platform_device *pdev) DRM_ERROR("Get memory resource failed\n"); return -ENOMEM; } - vtg->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); + vtg->regs = devm_ioremap(dev, res->start, resource_size(res)); if (!vtg->regs) { DRM_ERROR("failed to remap I/O memory\n"); return -ENOMEM; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 2a9e67597375..a3612369750f 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -256,7 +256,7 @@ static int tilcdc_init(struct drm_driver *ddrv, struct device *dev) goto init_failed; } - priv->mmio = ioremap_nocache(res->start, resource_size(res)); + priv->mmio = ioremap(res->start, resource_size(res)); if (!priv->mmio) { dev_err(dev, "failed to ioremap\n"); ret = -ENOMEM; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 6b0883a1776e..97fd1dafc3e8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -218,7 +218,7 @@ static int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *m if (mem->placement & TTM_PL_FLAG_WC) addr = ioremap_wc(mem->bus.base + mem->bus.offset, mem->bus.size); else - addr = ioremap_nocache(mem->bus.base + mem->bus.offset, mem->bus.size); + addr = ioremap(mem->bus.base + mem->bus.offset, mem->bus.size); if (!addr) { (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(bdev, mem); @@ -565,7 +565,7 @@ static int ttm_bo_ioremap(struct ttm_buffer_object *bo, map->virtual = ioremap_wc(bo->mem.bus.base + bo->mem.bus.offset + offset, size); else - map->virtual = ioremap_nocache(bo->mem.bus.base + bo->mem.bus.offset + offset, + map->virtual = ioremap(bo->mem.bus.base + bo->mem.bus.offset + offset, size); } return (!map->virtual) ? -ENOMEM : 0; diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index b09c39abd3a8..eeac4b04df27 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -528,7 +528,7 @@ static int i5k_amb_probe(struct platform_device *pdev) goto err; } - data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len); + data->amb_mmio = ioremap(data->amb_base, data->amb_len); if (!data->amb_mmio) { res = -EBUSY; goto err_map_failed; diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index ff340d7ae2e5..abfe3094c047 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -369,7 +369,7 @@ static int highlander_i2c_probe(struct platform_device *pdev) if (unlikely(!dev)) return -ENOMEM; - dev->base = ioremap_nocache(res->start, resource_size(res)); + dev->base = ioremap(res->start, resource_size(res)); if (unlikely(!dev->base)) { ret = -ENXIO; goto err; diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 0829cb696d9d..4fde74eb34a7 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -281,7 +281,7 @@ static int pmcmsptwi_probe(struct platform_device *pldev) } /* remap the memory */ - pmcmsptwi_data.iobase = ioremap_nocache(res->start, + pmcmsptwi_data.iobase = ioremap(res->start, resource_size(res)); if (!pmcmsptwi_data.iobase) { dev_err(&pldev->dev, diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index 958c1ff9c515..0441c7eea36b 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -442,7 +442,7 @@ int bnxt_qplib_enable_nq(struct pci_dev *pdev, struct bnxt_qplib_nq *nq, goto fail; } /* Unconditionally map 8 bytes to support 57500 series */ - nq->bar_reg_iomem = ioremap_nocache(nq_base + nq->bar_reg_off, 8); + nq->bar_reg_iomem = ioremap(nq_base + nq->bar_reg_off, 8); if (!nq->bar_reg_iomem) { rc = -ENOMEM; goto fail; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c index 5cdfa84faf85..1291b12287a5 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c @@ -717,7 +717,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, if (!res_base) return -ENOMEM; - rcfw->cmdq_bar_reg_iomem = ioremap_nocache(res_base + + rcfw->cmdq_bar_reg_iomem = ioremap(res_base + RCFW_COMM_BASE_OFFSET, RCFW_COMM_SIZE); if (!rcfw->cmdq_bar_reg_iomem) { @@ -739,7 +739,7 @@ int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, "CREQ BAR region %d resc start is 0!\n", rcfw->creq_bar_reg); /* Unconditionally map 8 bytes to support 57500 series */ - rcfw->creq_bar_reg_iomem = ioremap_nocache(res_base + cp_bar_reg_off, + rcfw->creq_bar_reg_iomem = ioremap(res_base + cp_bar_reg_off, 8); if (!rcfw->creq_bar_reg_iomem) { dev_err(&rcfw->pdev->dev, "CREQ BAR region %d mapping failed\n", diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index bdbde8e22420..60ea1b924b67 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -704,7 +704,7 @@ static int bnxt_qplib_alloc_dpi_tbl(struct bnxt_qplib_res *res, return -ENOMEM; } - dpit->dbr_bar_reg_iomem = ioremap_nocache(bar_reg_base + dbr_offset, + dpit->dbr_bar_reg_iomem = ioremap(bar_reg_base + dbr_offset, dbr_len); if (!dpit->dbr_bar_reg_iomem) { dev_err(&res->pdev->dev, diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c index 61362bd6d3ce..1a6268d61977 100644 --- a/drivers/infiniband/hw/hfi1/pcie.c +++ b/drivers/infiniband/hw/hfi1/pcie.c @@ -161,7 +161,7 @@ int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev) return -EINVAL; } - dd->kregbase1 = ioremap_nocache(addr, RCV_ARRAY); + dd->kregbase1 = ioremap(addr, RCV_ARRAY); if (!dd->kregbase1) { dd_dev_err(dd, "UC mapping of kregbase1 failed\n"); return -ENOMEM; @@ -179,7 +179,7 @@ int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev) dd_dev_info(dd, "RcvArray count: %u\n", rcv_array_count); dd->base2_start = RCV_ARRAY + rcv_array_count * 8; - dd->kregbase2 = ioremap_nocache( + dd->kregbase2 = ioremap( addr + dd->base2_start, TXE_PIO_SEND - dd->base2_start); if (!dd->kregbase2) { diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index dd4843379f51..91d64dd71a8a 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -6630,7 +6630,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd) /* vl15 buffers start just after the 4k buffers */ vl15off = dd->physaddr + (dd->piobufbase >> 32) + dd->piobcnt4k * dd->align4k; - dd->piovl15base = ioremap_nocache(vl15off, + dd->piovl15base = ioremap(vl15off, NUM_VL15_BUFS * dd->align4k); if (!dd->piovl15base) { ret = -ENOMEM; diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index d4fd8a6cff7b..43c8ee1f46e0 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1759,7 +1759,7 @@ int init_chip_wc_pat(struct qib_devdata *dd, u32 vl15buflen) qib_userlen = dd->ureg_align * dd->cfgctxts; /* Sanity checks passed, now create the new mappings */ - qib_kregbase = ioremap_nocache(qib_physaddr, qib_kreglen); + qib_kregbase = ioremap(qib_physaddr, qib_kreglen); if (!qib_kregbase) goto bail; @@ -1768,7 +1768,7 @@ int init_chip_wc_pat(struct qib_devdata *dd, u32 vl15buflen) goto bail_kregbase; if (qib_userlen) { - qib_userbase = ioremap_nocache(qib_physaddr + dd->uregbase, + qib_userbase = ioremap(qib_physaddr + dd->uregbase, qib_userlen); if (!qib_userbase) goto bail_piobase; diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index 864f2af171f7..3dc6ce033319 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -145,7 +145,7 @@ int qib_pcie_ddinit(struct qib_devdata *dd, struct pci_dev *pdev, addr = pci_resource_start(pdev, 0); len = pci_resource_len(pdev, 0); - dd->kregbase = ioremap_nocache(addr, len); + dd->kregbase = ioremap(addr, len); if (!dd->kregbase) return -ENOMEM; diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index f7414091d94e..2fe9dcfe0a6f 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -107,7 +107,7 @@ static int pxa930_rotary_probe(struct platform_device *pdev) if (!r) return -ENOMEM; - r->mmio_base = ioremap_nocache(res->start, resource_size(res)); + r->mmio_base = ioremap(res->start, resource_size(res)); if (r->mmio_base == NULL) { dev_err(&pdev->dev, "failed to remap IO memory\n"); err = -ENXIO; diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 27ad73f43451..c155adebf96e 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -195,7 +195,7 @@ static int sh_keysc_probe(struct platform_device *pdev) memcpy(&priv->pdata, dev_get_platdata(&pdev->dev), sizeof(priv->pdata)); pdata = &priv->pdata; - priv->iomem_base = ioremap_nocache(res->start, resource_size(res)); + priv->iomem_base = ioremap(res->start, resource_size(res)); if (priv->iomem_base == NULL) { dev_err(&pdev->dev, "failed to remap I/O memory\n"); error = -ENXIO; diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 41acde60b60f..3332b77eef2a 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -167,7 +167,7 @@ static int pxa930_trkball_probe(struct platform_device *pdev) goto failed; } - trkball->mmio_base = ioremap_nocache(res->start, resource_size(res)); + trkball->mmio_base = ioremap(res->start, resource_size(res)); if (!trkball->mmio_base) { dev_err(&pdev->dev, "failed to ioremap registers\n"); error = -ENXIO; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 96f9b5397367..2f9775de3c5b 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -349,7 +349,7 @@ static int __init gscps2_probe(struct parisc_device *dev) ps2port->port = serio; ps2port->padev = dev; - ps2port->addr = ioremap_nocache(hpa, GSC_STATUS + 4); + ps2port->addr = ioremap(hpa, GSC_STATUS + 4); spin_lock_init(&ps2port->lock); gscps2_reset(ps2port); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 568c52317757..27bde309e6f7 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -440,7 +440,7 @@ static u8 __iomem * __init iommu_map_mmio_space(u64 address, u64 end) return NULL; } - return (u8 __iomem *)ioremap_nocache(address, end); + return (u8 __iomem *)ioremap(address, end); } static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index d246d74ec3a5..23445ebfda5c 100644 --- a/drivers/ipack/carriers/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -298,7 +298,7 @@ static int tpci200_register(struct tpci200_board *tpci200) /* Map internal tpci200 driver user space */ tpci200->info->interface_regs = - ioremap_nocache(pci_resource_start(tpci200->info->pdev, + ioremap(pci_resource_start(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR), TPCI200_IFACE_SIZE); if (!tpci200->info->interface_regs) { @@ -541,7 +541,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev, ret = -EBUSY; goto out_err_pci_request; } - tpci200->info->cfg_regs = ioremap_nocache( + tpci200->info->cfg_regs = ioremap( pci_resource_start(pdev, TPCI200_CFG_MEM_BAR), pci_resource_len(pdev, TPCI200_CFG_MEM_BAR)); if (!tpci200->info->cfg_regs) { diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c index 9c2a4b5d30cf..d480a514c983 100644 --- a/drivers/ipack/devices/ipoctal.c +++ b/drivers/ipack/devices/ipoctal.c @@ -276,7 +276,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal->board_id = ipoctal->dev->id_device; region = &ipoctal->dev->region[IPACK_IO_SPACE]; - addr = devm_ioremap_nocache(&ipoctal->dev->dev, + addr = devm_ioremap(&ipoctal->dev->dev, region->start, region->size); if (!addr) { dev_err(&ipoctal->dev->dev, @@ -292,7 +292,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, region = &ipoctal->dev->region[IPACK_INT_SPACE]; ipoctal->int_space = - devm_ioremap_nocache(&ipoctal->dev->dev, + devm_ioremap(&ipoctal->dev->dev, region->start, region->size); if (!ipoctal->int_space) { dev_err(&ipoctal->dev->dev, @@ -303,7 +303,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, region = &ipoctal->dev->region[IPACK_MEM8_SPACE]; ipoctal->mem8_space = - devm_ioremap_nocache(&ipoctal->dev->dev, + devm_ioremap(&ipoctal->dev->dev, region->start, 0x8000); if (!ipoctal->mem8_space) { dev_err(&ipoctal->dev->dev, diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index f3985469c221..d70507133c1d 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -716,7 +716,7 @@ static int __init gic_of_init(struct device_node *node, __sync(); } - mips_gic_base = ioremap_nocache(gic_base, gic_len); + mips_gic_base = ioremap(gic_base, gic_len); gicconfig = read_gic_config(); gic_shared_intrs = gicconfig & GIC_CONFIG_NUMINTERRUPTS; diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index f82bc60a6793..6e5e3172796b 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c @@ -460,7 +460,7 @@ static int intc_irqpin_probe(struct platform_device *pdev) goto err0; } - i->iomem = devm_ioremap_nocache(dev, io[k]->start, + i->iomem = devm_ioremap(dev, io[k]->start, resource_size(io[k])); if (!i->iomem) { dev_err(dev, "failed to remap IOMEM\n"); diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c index 04d51ca63223..4c8c96a35282 100644 --- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c +++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c @@ -105,7 +105,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr, if (nums[i-1] + 1 != nums[i]) goto fail_map; buf->vaddr = (__force void *) - ioremap_nocache(__pfn_to_phys(nums[0]), size + offset); + ioremap(__pfn_to_phys(nums[0]), size + offset); } else { buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1, PAGE_KERNEL); diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index fd47bd07ffd8..2f1eeeb6e7c7 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -938,7 +938,7 @@ static int cx18_probe(struct pci_dev *pci_dev, /* map io memory */ CX18_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE); - cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET, + cx->enc_mem = ioremap(cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE); if (!cx->enc_mem) { CX18_ERR("ioremap failed. Can't get a window into CX23418 memory and register space\n"); diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index 3f3f40ea890b..1f79700a6307 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -1042,7 +1042,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) /* map io memory */ IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); - itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET, + itv->enc_mem = ioremap(itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); if (!itv->enc_mem) { IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n"); @@ -1056,7 +1056,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) if (itv->has_cx23415) { IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET, + itv->dec_mem = ioremap(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); if (!itv->dec_mem) { IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n"); @@ -1075,7 +1075,7 @@ static int ivtv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); itv->reg_mem = - ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); + ioremap(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); if (!itv->reg_mem) { IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n"); IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n"); diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c index f299baf7cbe0..e06d113dfe96 100644 --- a/drivers/media/platform/davinci/dm355_ccdc.c +++ b/drivers/media/platform/davinci/dm355_ccdc.c @@ -883,7 +883,7 @@ static int dm355_ccdc_probe(struct platform_device *pdev) goto fail_nores; } - ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); + ccdc_cfg.base_addr = ioremap(res->start, resource_size(res)); if (!ccdc_cfg.base_addr) { status = -ENOMEM; goto fail_nomem; diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index 2fc6c9c38f9c..c6378c4e0074 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -817,7 +817,7 @@ static int dm644x_ccdc_probe(struct platform_device *pdev) goto fail_nores; } - ccdc_cfg.base_addr = ioremap_nocache(res->start, resource_size(res)); + ccdc_cfg.base_addr = ioremap(res->start, resource_size(res)); if (!ccdc_cfg.base_addr) { status = -ENOMEM; goto fail_nomem; diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c index e2e7ab7b7f45..b49378b18e5d 100644 --- a/drivers/media/platform/davinci/isif.c +++ b/drivers/media/platform/davinci/isif.c @@ -1045,7 +1045,7 @@ static int isif_probe(struct platform_device *pdev) status = -EBUSY; goto fail_nobase_res; } - addr = ioremap_nocache(res->start, resource_size(res)); + addr = ioremap(res->start, resource_size(res)); if (!addr) { status = -ENOMEM; goto fail_base_iomap; diff --git a/drivers/media/platform/tegra-cec/tegra_cec.c b/drivers/media/platform/tegra-cec/tegra_cec.c index a99caac59f44..1ac0c70a5981 100644 --- a/drivers/media/platform/tegra-cec/tegra_cec.c +++ b/drivers/media/platform/tegra-cec/tegra_cec.c @@ -351,7 +351,7 @@ static int tegra_cec_probe(struct platform_device *pdev) if (cec->tegra_cec_irq <= 0) return -EBUSY; - cec->cec_base = devm_ioremap_nocache(&pdev->dev, res->start, + cec->cec_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!cec->cec_base) { diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c index fd7b2167103d..06038b325b02 100644 --- a/drivers/misc/cardreader/rtsx_pcr.c +++ b/drivers/misc/cardreader/rtsx_pcr.c @@ -1512,7 +1512,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, bar = 1; len = pci_resource_len(pcidev, bar); base = pci_resource_start(pcidev, bar); - pcr->remap_addr = ioremap_nocache(base, len); + pcr->remap_addr = ioremap(base, len); if (!pcr->remap_addr) { ret = -ENOMEM; goto free_handle; diff --git a/drivers/misc/mic/scif/scif_nodeqp.c b/drivers/misc/mic/scif/scif_nodeqp.c index c25fd40f3bd0..fcd999f50d14 100644 --- a/drivers/misc/mic/scif/scif_nodeqp.c +++ b/drivers/misc/mic/scif/scif_nodeqp.c @@ -788,7 +788,7 @@ scif_node_add(struct scif_dev *scifdev, struct scifmsg *msg) "failed to setup interrupts for %d\n", msg->src.node); goto interrupt_setup_error; } - newdev->mmio.va = ioremap_nocache(msg->payload[1], sdev->mmio->len); + newdev->mmio.va = ioremap(msg->payload[1], sdev->mmio->len); if (!newdev->mmio.va) { dev_err(&scifdev->sdev->dev, "failed to map mmio for %d\n", msg->src.node); diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index 359c5bab45ac..063e4419cd7e 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -834,7 +834,7 @@ static int pti_pci_probe(struct pci_dev *pdev, } drv_data->aperture_base = drv_data->pti_addr+APERTURE_14; drv_data->pti_ioaddr = - ioremap_nocache((u32)drv_data->aperture_base, + ioremap((u32)drv_data->aperture_base, APERTURE_LEN); if (!drv_data->pti_ioaddr) { retval = -ENOMEM; diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 105e73d4a3b9..674f9e084cd2 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -719,7 +719,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) goto err_free; } - host->ioaddr = devm_ioremap_nocache(dev, iomem->start, + host->ioaddr = devm_ioremap(dev, iomem->start, resource_size(iomem)); if (host->ioaddr == NULL) { err = -ENOMEM; diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index f4ac064ff471..e48bddd95ce6 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1106,7 +1106,7 @@ static int via_sd_probe(struct pci_dev *pcidev, len = pci_resource_len(pcidev, 0); base = pci_resource_start(pcidev, 0); - sdhost->mmiobase = ioremap_nocache(base, len); + sdhost->mmiobase = ioremap(base, len); if (!sdhost->mmiobase) { ret = -ENOMEM; goto free_mmc_host; diff --git a/drivers/mtd/devices/bcm47xxsflash.c b/drivers/mtd/devices/bcm47xxsflash.c index eccf2e5d905e..3af50db8b21b 100644 --- a/drivers/mtd/devices/bcm47xxsflash.c +++ b/drivers/mtd/devices/bcm47xxsflash.c @@ -320,7 +320,7 @@ static int bcm47xxsflash_bcma_probe(struct platform_device *pdev) * ChipCommon revision. */ if (b47s->bcma_cc->core->id.rev == 54) - b47s->window = ioremap_nocache(res->start, resource_size(res)); + b47s->window = ioremap(res->start, resource_size(res)); else b47s->window = ioremap_cache(res->start, resource_size(res)); if (!b47s->window) { diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 462fadb56bdb..42a95ba40f2c 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -163,7 +163,7 @@ static int amd76xrom_init_one(struct pci_dev *pdev, /* FIXME handle registers 0x80 - 0x8C the bios region locks */ /* For write accesses caches are useless */ - window->virt = ioremap_nocache(window->phys, window->size); + window->virt = ioremap(window->phys, window->size); if (!window->virt) { printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", window->phys, window->size); diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index c9b7b4d5a923..460494212f6a 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -191,7 +191,7 @@ static int __init ck804xrom_init_one(struct pci_dev *pdev, /* FIXME handle registers 0x80 - 0x8C the bios region locks */ /* For write accesses caches are useless */ - window->virt = ioremap_nocache(window->phys, window->size); + window->virt = ioremap(window->phys, window->size); if (!window->virt) { printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", window->phys, window->size); diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index 5c27c6994896..85e14150a073 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -249,7 +249,7 @@ static int __init esb2rom_init_one(struct pci_dev *pdev, } /* Map the firmware hub into my address space. */ - window->virt = ioremap_nocache(window->phys, window->size); + window->virt = ioremap(window->phys, window->size); if (!window->virt) { printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", window->phys, window->size); diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c index 6b989f391baa..fda72c5fd8f9 100644 --- a/drivers/mtd/maps/ichxrom.c +++ b/drivers/mtd/maps/ichxrom.c @@ -184,7 +184,7 @@ static int __init ichxrom_init_one(struct pci_dev *pdev, } /* Map the firmware hub into my address space. */ - window->virt = ioremap_nocache(window->phys, window->size); + window->virt = ioremap(window->phys, window->size); if (!window->virt) { printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n", window->phys, window->size); diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c index 69503aef981e..d67b845b0e89 100644 --- a/drivers/mtd/maps/intel_vr_nor.c +++ b/drivers/mtd/maps/intel_vr_nor.c @@ -133,7 +133,7 @@ static int vr_nor_init_maps(struct vr_nor_mtd *p) if (win_len < (CS0_START + CS0_SIZE)) return -ENXIO; - p->csr_base = ioremap_nocache(csr_phys, csr_len); + p->csr_base = ioremap(csr_phys, csr_len); if (!p->csr_base) return -ENOMEM; @@ -152,7 +152,7 @@ static int vr_nor_init_maps(struct vr_nor_mtd *p) p->map.bankwidth = (exp_timing_cs0 & TIMING_BYTE_EN) ? 1 : 2; p->map.phys = win_phys + CS0_START; p->map.size = CS0_SIZE; - p->map.virt = ioremap_nocache(p->map.phys, p->map.size); + p->map.virt = ioremap(p->map.phys, p->map.size); if (!p->map.virt) { err = -ENOMEM; goto release; diff --git a/drivers/mtd/maps/l440gx.c b/drivers/mtd/maps/l440gx.c index 0eeadfeb620d..832b880d1aaf 100644 --- a/drivers/mtd/maps/l440gx.c +++ b/drivers/mtd/maps/l440gx.c @@ -78,7 +78,7 @@ static int __init init_l440gx(void) return -ENODEV; } - l440gx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE); + l440gx_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!l440gx_map.virt) { printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); diff --git a/drivers/mtd/maps/netsc520.c b/drivers/mtd/maps/netsc520.c index abc52b70bb00..0bb651624f05 100644 --- a/drivers/mtd/maps/netsc520.c +++ b/drivers/mtd/maps/netsc520.c @@ -82,10 +82,10 @@ static int __init init_netsc520(void) printk(KERN_NOTICE "NetSc520 flash device: 0x%Lx at 0x%Lx\n", (unsigned long long)netsc520_map.size, (unsigned long long)netsc520_map.phys); - netsc520_map.virt = ioremap_nocache(netsc520_map.phys, netsc520_map.size); + netsc520_map.virt = ioremap(netsc520_map.phys, netsc520_map.size); if (!netsc520_map.virt) { - printk("Failed to ioremap_nocache\n"); + printk("Failed to ioremap\n"); return -EIO; } diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c index 50046d497398..7d349874ffeb 100644 --- a/drivers/mtd/maps/nettel.c +++ b/drivers/mtd/maps/nettel.c @@ -176,7 +176,7 @@ static int __init nettel_init(void) #endif int rc = 0; - nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096); + nettel_mmcrp = (void *) ioremap(0xfffef000, 4096); if (nettel_mmcrp == NULL) { printk("SNAPGEAR: failed to disable MMCR cache??\n"); return(-EIO); @@ -217,7 +217,7 @@ static int __init nettel_init(void) __asm__ ("wbinvd"); nettel_amd_map.phys = amdaddr; - nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); + nettel_amd_map.virt = ioremap(amdaddr, maxsize); if (!nettel_amd_map.virt) { printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); iounmap(nettel_mmcrp); @@ -303,7 +303,7 @@ static int __init nettel_init(void) /* Probe for the size of the first Intel flash */ nettel_intel_map.size = maxsize; nettel_intel_map.phys = intel0addr; - nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); + nettel_intel_map.virt = ioremap(intel0addr, maxsize); if (!nettel_intel_map.virt) { printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); rc = -EIO; @@ -337,7 +337,7 @@ static int __init nettel_init(void) iounmap(nettel_intel_map.virt); nettel_intel_map.size = maxsize; - nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); + nettel_intel_map.virt = ioremap(intel0addr, maxsize); if (!nettel_intel_map.virt) { printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); rc = -EIO; diff --git a/drivers/mtd/maps/pci.c b/drivers/mtd/maps/pci.c index 9a49f8a06fb8..377ef0fc4e3e 100644 --- a/drivers/mtd/maps/pci.c +++ b/drivers/mtd/maps/pci.c @@ -94,7 +94,7 @@ intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map) map->map.write = mtd_pci_write8, map->map.size = 0x00800000; - map->base = ioremap_nocache(pci_resource_start(dev, 0), + map->base = ioremap(pci_resource_start(dev, 0), pci_resource_len(dev, 0)); if (!map->base) @@ -188,7 +188,7 @@ intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map) map->map.read = mtd_pci_read32, map->map.write = mtd_pci_write32, map->map.size = len; - map->base = ioremap_nocache(base, len); + map->base = ioremap(base, len); if (!map->base) return -ENOMEM; diff --git a/drivers/mtd/maps/sc520cdp.c b/drivers/mtd/maps/sc520cdp.c index 03af2df90d47..9902b37e18b4 100644 --- a/drivers/mtd/maps/sc520cdp.c +++ b/drivers/mtd/maps/sc520cdp.c @@ -174,8 +174,8 @@ static void sc520cdp_setup_par(void) int i, j; /* map in SC520's MMCR area */ - mmcr = ioremap_nocache(SC520_MMCR_BASE, SC520_MMCR_EXTENT); - if(!mmcr) { /* ioremap_nocache failed: skip the PAR reprogramming */ + mmcr = ioremap(SC520_MMCR_BASE, SC520_MMCR_EXTENT); + if(!mmcr) { /* ioremap failed: skip the PAR reprogramming */ /* force physical address fields to BIOS defaults: */ for(i = 0; i < NUM_FLASH_BANKS; i++) sc520cdp_map[i].phys = par_table[i].default_address; @@ -225,10 +225,10 @@ static int __init init_sc520cdp(void) (unsigned long long)sc520cdp_map[i].size, (unsigned long long)sc520cdp_map[i].phys); - sc520cdp_map[i].virt = ioremap_nocache(sc520cdp_map[i].phys, sc520cdp_map[i].size); + sc520cdp_map[i].virt = ioremap(sc520cdp_map[i].phys, sc520cdp_map[i].size); if (!sc520cdp_map[i].virt) { - printk("Failed to ioremap_nocache\n"); + printk("Failed to ioremap\n"); for (j = 0; j < i; j++) { if (mymtd[j]) { map_destroy(mymtd[j]); diff --git a/drivers/mtd/maps/scb2_flash.c b/drivers/mtd/maps/scb2_flash.c index 2afb253bf456..57303f904bc1 100644 --- a/drivers/mtd/maps/scb2_flash.c +++ b/drivers/mtd/maps/scb2_flash.c @@ -152,7 +152,7 @@ static int scb2_flash_probe(struct pci_dev *dev, } /* remap the IO window (w/o caching) */ - scb2_ioaddr = ioremap_nocache(SCB2_ADDR, SCB2_WINDOW); + scb2_ioaddr = ioremap(SCB2_ADDR, SCB2_WINDOW); if (!scb2_ioaddr) { printk(KERN_ERR MODNAME ": Failed to ioremap window!\n"); if (!region_fail) diff --git a/drivers/mtd/maps/ts5500_flash.c b/drivers/mtd/maps/ts5500_flash.c index 6cfc8783c0e5..70d6e865f555 100644 --- a/drivers/mtd/maps/ts5500_flash.c +++ b/drivers/mtd/maps/ts5500_flash.c @@ -56,10 +56,10 @@ static int __init init_ts5500_map(void) { int rc = 0; - ts5500_map.virt = ioremap_nocache(ts5500_map.phys, ts5500_map.size); + ts5500_map.virt = ioremap(ts5500_map.phys, ts5500_map.size); if (!ts5500_map.virt) { - printk(KERN_ERR "Failed to ioremap_nocache\n"); + printk(KERN_ERR "Failed to ioremap\n"); rc = -EIO; goto err2; } diff --git a/drivers/mtd/nand/raw/au1550nd.c b/drivers/mtd/nand/raw/au1550nd.c index e10b76089048..75eb3e97fae3 100644 --- a/drivers/mtd/nand/raw/au1550nd.c +++ b/drivers/mtd/nand/raw/au1550nd.c @@ -404,7 +404,7 @@ static int au1550nd_probe(struct platform_device *pdev) goto out1; } - ctx->base = ioremap_nocache(r->start, 0x1000); + ctx->base = ioremap(r->start, 0x1000); if (!ctx->base) { dev_err(&pdev->dev, "cannot remap NAND memory area\n"); ret = -ENODEV; diff --git a/drivers/mtd/nand/raw/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c index d62aa5271753..2f77ee55e1bf 100644 --- a/drivers/mtd/nand/raw/denali_pci.c +++ b/drivers/mtd/nand/raw/denali_pci.c @@ -74,15 +74,15 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return ret; } - denali->reg = ioremap_nocache(csr_base, csr_len); + denali->reg = ioremap(csr_base, csr_len); if (!denali->reg) { dev_err(&dev->dev, "Spectra: Unable to remap memory region\n"); return -ENOMEM; } - denali->host = ioremap_nocache(mem_base, mem_len); + denali->host = ioremap(mem_base, mem_len); if (!denali->host) { - dev_err(&dev->dev, "Spectra: ioremap_nocache failed!"); + dev_err(&dev->dev, "Spectra: ioremap failed!"); ret = -ENOMEM; goto out_unmap_reg; } diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c index 1054cc070747..f31fae3a4c68 100644 --- a/drivers/mtd/nand/raw/fsl_upm.c +++ b/drivers/mtd/nand/raw/fsl_upm.c @@ -285,7 +285,7 @@ static int fun_probe(struct platform_device *ofdev) fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN | FSL_UPM_WAIT_WRITE_BYTE; - fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start, + fun->io_base = devm_ioremap(&ofdev->dev, io_res.start, resource_size(&io_res)); if (!fun->io_base) { ret = -ENOMEM; diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index c8e1a04ba384..9df2007b5e56 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1302,7 +1302,7 @@ static int at91_can_probe(struct platform_device *pdev) goto exit_put; } - addr = ioremap_nocache(res->start, resource_size(res)); + addr = ioremap(res->start, resource_size(res)); if (!addr) { err = -ENOMEM; goto exit_release; diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c index b9047d8110d5..194c86e0f340 100644 --- a/drivers/net/can/cc770/cc770_isa.c +++ b/drivers/net/can/cc770/cc770_isa.c @@ -175,7 +175,7 @@ static int cc770_isa_probe(struct platform_device *pdev) err = -EBUSY; goto exit; } - base = ioremap_nocache(mem[idx], iosize); + base = ioremap(mem[idx], iosize); if (!base) { err = -ENOMEM; goto exit_release; diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index 1c4d32d1a542..d513fac50718 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -130,7 +130,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) err = -EBUSY; goto exit; } - base = ioremap_nocache(mem[idx], iosize); + base = ioremap(mem[idx], iosize); if (!base) { err = -ENOMEM; goto exit_release; diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index ff5a96f34085..d7222ba46622 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -229,7 +229,7 @@ static int sp_probe(struct platform_device *pdev) resource_size(res_mem), DRV_NAME)) return -EBUSY; - addr = devm_ioremap_nocache(&pdev->dev, res_mem->start, + addr = devm_ioremap(&pdev->dev, res_mem->start, resource_size(res_mem)); if (!addr) return -ENOMEM; diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 8242fb287cbb..d1ddf763b188 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -777,7 +777,7 @@ static int softing_pdev_probe(struct platform_device *pdev) goto platform_resource_failed; card->dpram_phys = pres->start; card->dpram_size = resource_size(pres); - card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size); + card->dpram = ioremap(card->dpram_phys, card->dpram_size); if (!card->dpram) { dev_alert(&card->pdev->dev, "dpram ioremap failed\n"); goto ioremap_failed; diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c index 80ef3e15bd22..9daef4c8feef 100644 --- a/drivers/net/ethernet/alacritech/slicoss.c +++ b/drivers/net/ethernet/alacritech/slicoss.c @@ -1791,7 +1791,7 @@ static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) sdev->is_fiber = slic_is_fiber(pdev->subsystem_device); sdev->pdev = pdev; sdev->netdev = dev; - sdev->regs = ioremap_nocache(pci_resource_start(pdev, 0), + sdev->regs = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!sdev->regs) { dev_err(&pdev->dev, "failed to map registers\n"); diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index 4cd53fc338b5..1671c1f36691 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -1332,10 +1332,10 @@ static int request_and_map(struct platform_device *pdev, const char *name, return -EBUSY; } - *ptr = devm_ioremap_nocache(device, region->start, + *ptr = devm_ioremap(device, region->start, resource_size(region)); if (*ptr == NULL) { - dev_err(device, "ioremap_nocache of %s failed!", name); + dev_err(device, "ioremap of %s failed!", name); return -ENOMEM; } diff --git a/drivers/net/ethernet/amd/au1000_eth.c b/drivers/net/ethernet/amd/au1000_eth.c index 1793950f0582..307e402db8c9 100644 --- a/drivers/net/ethernet/amd/au1000_eth.c +++ b/drivers/net/ethernet/amd/au1000_eth.c @@ -1161,7 +1161,7 @@ static int au1000_probe(struct platform_device *pdev) /* aup->mac is the base address of the MAC's registers */ aup->mac = (struct mac_reg *) - ioremap_nocache(base->start, resource_size(base)); + ioremap(base->start, resource_size(base)); if (!aup->mac) { dev_err(&pdev->dev, "failed to ioremap MAC registers\n"); err = -ENXIO; @@ -1169,7 +1169,7 @@ static int au1000_probe(struct platform_device *pdev) } /* Setup some variables for quick register address access */ - aup->enable = (u32 *)ioremap_nocache(macen->start, + aup->enable = (u32 *)ioremap(macen->start, resource_size(macen)); if (!aup->enable) { dev_err(&pdev->dev, "failed to ioremap MAC enable register\n"); @@ -1178,7 +1178,7 @@ static int au1000_probe(struct platform_device *pdev) } aup->mac_id = pdev->id; - aup->macdma = ioremap_nocache(macdma->start, resource_size(macdma)); + aup->macdma = ioremap(macdma->start, resource_size(macdma)); if (!aup->macdma) { dev_err(&pdev->dev, "failed to ioremap MACDMA registers\n"); err = -ENXIO; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index 2bb329606794..6b27af0db499 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -253,7 +253,7 @@ static int aq_pci_probe(struct pci_dev *pdev, goto err_free_aq_hw; } - self->aq_hw->mmio = ioremap_nocache(mmio_pa, reg_sz); + self->aq_hw->mmio = ioremap(mmio_pa, reg_sz); if (!self->aq_hw->mmio) { err = -EIO; goto err_free_aq_hw; diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 61a334d1b5e6..60ba69db48c6 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -1687,8 +1687,7 @@ static int ag71xx_probe(struct platform_device *pdev) goto err_free; } - ag->mac_base = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); + ag->mac_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!ag->mac_base) { err = -ENOMEM; goto err_free; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index cff64e43bdd8..61fa32cdd3e3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -14053,7 +14053,7 @@ static int bnx2x_init_one(struct pci_dev *pdev, rc = -ENOMEM; goto init_one_freemem; } - bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2), + bp->doorbells = ioremap(pci_resource_start(pdev, 2), doorbell_size); } if (!bp->doorbells) { diff --git a/drivers/net/ethernet/broadcom/sb1250-mac.c b/drivers/net/ethernet/broadcom/sb1250-mac.c index 1604ad32e920..f991537818fe 100644 --- a/drivers/net/ethernet/broadcom/sb1250-mac.c +++ b/drivers/net/ethernet/broadcom/sb1250-mac.c @@ -2537,7 +2537,7 @@ static int sbmac_probe(struct platform_device *pldev) res = platform_get_resource(pldev, IORESOURCE_MEM, 0); BUG_ON(!res); - sbm_base = ioremap_nocache(res->start, resource_size(res)); + sbm_base = ioremap(res->start, resource_size(res)); if (!sbm_base) { printk(KERN_ERR "%s: unable to map device registers\n", dev_name(&pldev->dev)); diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index e338272931d1..01a50a4b2113 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -3477,7 +3477,7 @@ bnad_init(struct bnad *bnad, bnad->pcidev = pdev; bnad->mmio_start = pci_resource_start(pdev, 0); bnad->mmio_len = pci_resource_len(pdev, 0); - bnad->bar0 = ioremap_nocache(bnad->mmio_start, bnad->mmio_len); + bnad->bar0 = ioremap(bnad->mmio_start, bnad->mmio_len); if (!bnad->bar0) { dev_err(&pdev->dev, "ioremap for bar0 failed\n"); return -ENOMEM; diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 58f89f6a040f..2824b5ed4ced 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -3265,7 +3265,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_free_adapter; } - adapter->regs = ioremap_nocache(mmio_start, mmio_len); + adapter->regs = ioremap(mmio_start, mmio_len); if (!adapter->regs) { dev_err(&pdev->dev, "cannot map device registers\n"); err = -ENOMEM; diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index f1a2da15dd0a..7852a4308194 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c @@ -2039,7 +2039,7 @@ static int de_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* remap CSR registers */ - regs = ioremap_nocache(pciaddr, DE_REGS_SIZE); + regs = ioremap(pciaddr, DE_REGS_SIZE); if (!regs) { rc = -EIO; pr_err("Cannot map PCI MMIO (%llx@%lx) on pci dev %s\n", diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index ea4f17f5cce7..c6e74ae0ff0d 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1087,7 +1087,7 @@ static int ethoc_probe(struct platform_device *pdev) priv = netdev_priv(netdev); priv->netdev = netdev; - priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, + priv->iobase = devm_ioremap(&pdev->dev, netdev->base_addr, resource_size(mmio)); if (!priv->iobase) { dev_err(&pdev->dev, "cannot remap I/O memory space\n"); @@ -1096,7 +1096,7 @@ static int ethoc_probe(struct platform_device *pdev) } if (netdev->mem_end) { - priv->membase = devm_ioremap_nocache(&pdev->dev, + priv->membase = devm_ioremap(&pdev->dev, netdev->mem_start, resource_size(mem)); if (!priv->membase) { dev_err(&pdev->dev, "cannot remap memory space\n"); diff --git a/drivers/net/ethernet/i825xx/sni_82596.c b/drivers/net/ethernet/i825xx/sni_82596.c index 6436a98c5953..22f5887578b2 100644 --- a/drivers/net/ethernet/i825xx/sni_82596.c +++ b/drivers/net/ethernet/i825xx/sni_82596.c @@ -91,10 +91,10 @@ static int sni_82596_probe(struct platform_device *dev) idprom = platform_get_resource(dev, IORESOURCE_MEM, 2); if (!res || !ca || !options || !idprom) return -ENODEV; - mpu_addr = ioremap_nocache(res->start, 4); + mpu_addr = ioremap(res->start, 4); if (!mpu_addr) return -ENOMEM; - ca_addr = ioremap_nocache(ca->start, 4); + ca_addr = ioremap(ca->start, 4); if (!ca_addr) goto probe_failed_free_mpu; @@ -110,7 +110,7 @@ static int sni_82596_probe(struct platform_device *dev) netdevice->base_addr = res->start; netdevice->irq = platform_get_irq(dev, 0); - eth_addr = ioremap_nocache(idprom->start, 0x10); + eth_addr = ioremap(idprom->start, 0x10); if (!eth_addr) goto probe_failed; diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index ae195f8adff5..d3164537b694 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1043,7 +1043,7 @@ static int korina_probe(struct platform_device *pdev) r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); dev->base_addr = r->start; - lp->eth_regs = ioremap_nocache(r->start, resource_size(r)); + lp->eth_regs = ioremap(r->start, resource_size(r)); if (!lp->eth_regs) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); rc = -ENXIO; @@ -1051,7 +1051,7 @@ static int korina_probe(struct platform_device *pdev) } r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap_nocache(r->start, resource_size(r)); + lp->rx_dma_regs = ioremap(r->start, resource_size(r)); if (!lp->rx_dma_regs) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); rc = -ENXIO; @@ -1059,7 +1059,7 @@ static int korina_probe(struct platform_device *pdev) } r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap_nocache(r->start, resource_size(r)); + lp->tx_dma_regs = ioremap(r->start, resource_size(r)); if (!lp->tx_dma_regs) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); rc = -ENXIO; diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 6e73ffe6f928..41f2f5480741 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c @@ -649,7 +649,7 @@ ltq_etop_probe(struct platform_device *pdev) goto err_out; } - ltq_etop_membase = devm_ioremap_nocache(&pdev->dev, + ltq_etop_membase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!ltq_etop_membase) { dev_err(&pdev->dev, "failed to remap etop engine %d\n", diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 095f6c71b4fa..7515d079c600 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -3932,7 +3932,7 @@ static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) spin_lock_init(&hw->phy_lock); tasklet_init(&hw->phy_task, skge_extirq, (unsigned long) hw); - hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); + hw->regs = ioremap(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { dev_err(&pdev->dev, "cannot map device registers\n"); goto err_out_free_hw; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 5f56ee83e3b1..535dee35e04e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -5022,7 +5022,7 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) hw->pdev = pdev; sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev)); - hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); + hw->regs = ioremap(pci_resource_start(pdev, 0), 0x4000); if (!hw->regs) { dev_err(&pdev->dev, "cannot map device registers\n"); goto err_out_free_hw; diff --git a/drivers/net/ethernet/natsemi/ns83820.c b/drivers/net/ethernet/natsemi/ns83820.c index 6af9a7eee114..091254061052 100644 --- a/drivers/net/ethernet/natsemi/ns83820.c +++ b/drivers/net/ethernet/natsemi/ns83820.c @@ -1937,7 +1937,7 @@ static int ns83820_init_one(struct pci_dev *pci_dev, pci_set_master(pci_dev); addr = pci_resource_start(pci_dev, 1); - dev->base = ioremap_nocache(addr, PAGE_SIZE); + dev->base = ioremap(addr, PAGE_SIZE); dev->tx_descs = pci_alloc_consistent(pci_dev, 4 * DESC_SIZE * NR_TX_DESC, &dev->tx_phy_descs); dev->rx_info.descs = pci_alloc_consistent(pci_dev, diff --git a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c index e4977cdf7678..c0e2f4394aef 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_netvf_main.c @@ -106,7 +106,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, * first NFP_NET_CFG_BAR_SZ of the BAR. This keeps the code * the identical for PF and VF drivers. */ - ctrl_bar = ioremap_nocache(pci_resource_start(pdev, NFP_NET_CTRL_BAR), + ctrl_bar = ioremap(pci_resource_start(pdev, NFP_NET_CTRL_BAR), NFP_NET_CFG_BAR_SZ); if (!ctrl_bar) { dev_err(&pdev->dev, @@ -200,7 +200,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, bar_sz = (rx_bar_off + rx_bar_sz) - bar_off; map_addr = pci_resource_start(pdev, tx_bar_no) + bar_off; - vf->q_bar = ioremap_nocache(map_addr, bar_sz); + vf->q_bar = ioremap(map_addr, bar_sz); if (!vf->q_bar) { nn_err(nn, "Failed to map resource %d\n", tx_bar_no); err = -EIO; @@ -216,7 +216,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, /* TX queues */ map_addr = pci_resource_start(pdev, tx_bar_no) + tx_bar_off; - nn->tx_bar = ioremap_nocache(map_addr, tx_bar_sz); + nn->tx_bar = ioremap(map_addr, tx_bar_sz); if (!nn->tx_bar) { nn_err(nn, "Failed to map resource %d\n", tx_bar_no); err = -EIO; @@ -225,7 +225,7 @@ static int nfp_netvf_pci_probe(struct pci_dev *pdev, /* RX queues */ map_addr = pci_resource_start(pdev, rx_bar_no) + rx_bar_off; - nn->rx_bar = ioremap_nocache(map_addr, rx_bar_sz); + nn->rx_bar = ioremap(map_addr, rx_bar_sz); if (!nn->rx_bar) { nn_err(nn, "Failed to map resource %d\n", rx_bar_no); err = -EIO; diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c index 85d46f206b3c..b454db283aef 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c @@ -611,7 +611,7 @@ static int enable_bars(struct nfp6000_pcie *nfp, u16 interface) /* Configure, and lock, BAR0.0 for General Target use (MSI-X SRAM) */ bar = &nfp->bar[0]; if (nfp_bar_resource_len(bar) >= NFP_PCI_MIN_MAP_SIZE) - bar->iomem = ioremap_nocache(nfp_bar_resource_start(bar), + bar->iomem = ioremap(nfp_bar_resource_start(bar), nfp_bar_resource_len(bar)); if (bar->iomem) { int pf; @@ -677,7 +677,7 @@ static int enable_bars(struct nfp6000_pcie *nfp, u16 interface) } bar = &nfp->bar[4 + i]; - bar->iomem = ioremap_nocache(nfp_bar_resource_start(bar), + bar->iomem = ioremap(nfp_bar_resource_start(bar), nfp_bar_resource_len(bar)); if (bar->iomem) { msg += snprintf(msg, end - msg, @@ -858,7 +858,7 @@ static int nfp6000_area_acquire(struct nfp_cpp_area *area) priv->iomem = priv->bar->iomem + priv->bar_offset; else /* Must have been too big. Sub-allocate. */ - priv->iomem = ioremap_nocache(priv->phys, priv->size); + priv->iomem = ioremap(priv->phys, priv->size); if (IS_ERR_OR_NULL(priv->iomem)) { dev_err(nfp->dev, "Can't ioremap() a %d byte region of BAR %d\n", diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 4d9bbccc6f89..a6ae2cdc1986 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -1401,7 +1401,7 @@ static int efx_ef10_dimension_resources(struct efx_nic *efx) } /* Shrink the original UC mapping of the memory BAR */ - membase = ioremap_nocache(efx->membase_phys, uc_mem_map_size); + membase = ioremap(efx->membase_phys, uc_mem_map_size); if (!membase) { netif_err(efx, probe, efx->net_dev, "could not shrink memory BAR to %x\n", diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 7a38d7f282a1..6891df471538 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1338,7 +1338,7 @@ static int efx_init_io(struct efx_nic *efx) rc = -EIO; goto fail3; } - efx->membase = ioremap_nocache(efx->membase_phys, mem_map_size); + efx->membase = ioremap(efx->membase_phys, mem_map_size); if (!efx->membase) { netif_err(efx, probe, efx->net_dev, "could not map memory BAR at %llx+%x\n", diff --git a/drivers/net/ethernet/sfc/falcon/efx.c b/drivers/net/ethernet/sfc/falcon/efx.c index eecc348b1c32..53ae9faeb4c3 100644 --- a/drivers/net/ethernet/sfc/falcon/efx.c +++ b/drivers/net/ethernet/sfc/falcon/efx.c @@ -1265,7 +1265,7 @@ static int ef4_init_io(struct ef4_nic *efx) rc = -EIO; goto fail3; } - efx->membase = ioremap_nocache(efx->membase_phys, mem_map_size); + efx->membase = ioremap(efx->membase_phys, mem_map_size); if (!efx->membase) { netif_err(efx, probe, efx->net_dev, "could not map memory BAR at %llx+%x\n", diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 38068fc34141..6d90a097ce4e 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2454,7 +2454,7 @@ static int smsc911x_drv_probe(struct platform_device *pdev) pdata = netdev_priv(dev); dev->irq = irq; - pdata->ioaddr = ioremap_nocache(res->start, res_size); + pdata->ioaddr = ioremap(res->start, res_size); if (!pdata->ioaddr) { retval = -ENOMEM; goto out_ioremap_fail; diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c index 1b2702f74455..675f31de59dd 100644 --- a/drivers/net/ethernet/ti/netcp_core.c +++ b/drivers/net/ethernet/ti/netcp_core.c @@ -2019,7 +2019,7 @@ static int netcp_create_interface(struct netcp_device *netcp_device, goto quit; } - efuse = devm_ioremap_nocache(dev, res.start, size); + efuse = devm_ioremap(dev, res.start, size); if (!efuse) { dev_err(dev, "could not map resource\n"); devm_release_mem_region(dev, res.start, size); diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 21c1b4322ea7..c66aab78dcac 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1202,7 +1202,7 @@ static int temac_probe(struct platform_device *pdev) /* map device registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - lp->regs = devm_ioremap_nocache(&pdev->dev, res->start, + lp->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (IS_ERR(lp->regs)) { dev_err(&pdev->dev, "could not map TEMAC registers\n"); @@ -1296,7 +1296,7 @@ static int temac_probe(struct platform_device *pdev) } else if (pdata) { /* 2nd memory resource specifies DMA registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - lp->sdma_regs = devm_ioremap_nocache(&pdev->dev, res->start, + lp->sdma_regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (IS_ERR(lp->sdma_regs)) { dev_err(&pdev->dev, diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index 56b7791911bf..077c68498f04 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -614,7 +614,7 @@ static int dfx_register(struct device *bdev) /* Set up I/O base address. */ if (dfx_use_mmio) { - bp->base.mem = ioremap_nocache(bar_start[0], bar_len[0]); + bp->base.mem = ioremap(bar_start[0], bar_len[0]); if (!bp->base.mem) { printk(KERN_ERR "%s: Cannot map MMIO\n", print_name); err = -ENOMEM; diff --git a/drivers/net/fddi/defza.c b/drivers/net/fddi/defza.c index 060712c666bf..eaf85db53a5e 100644 --- a/drivers/net/fddi/defza.c +++ b/drivers/net/fddi/defza.c @@ -1318,7 +1318,7 @@ static int fza_probe(struct device *bdev) } /* MMIO mapping setup. */ - mmio = ioremap_nocache(start, len); + mmio = ioremap(start, len); if (!mmio) { pr_err("%s: cannot map MMIO\n", fp->name); ret = -ENOMEM; diff --git a/drivers/net/fjes/fjes_hw.c b/drivers/net/fjes/fjes_hw.c index 8a4fbfacad7e..065bb0a40b1d 100644 --- a/drivers/net/fjes/fjes_hw.c +++ b/drivers/net/fjes/fjes_hw.c @@ -40,7 +40,7 @@ static u8 *fjes_hw_iomap(struct fjes_hw *hw) return NULL; } - base = (u8 *)ioremap_nocache(hw->hw_res.start, hw->hw_res.size); + base = (u8 *)ioremap(hw->hw_res.start, hw->hw_res.size); return base; } diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 34e94ee806d6..23f93f1c815d 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -635,7 +635,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev, /* set up PLX mapping */ plx_phy = pci_resource_start(pdev, 0); - card->plx = ioremap_nocache(plx_phy, 0x70); + card->plx = ioremap(plx_phy, 0x70); if (!card->plx) { pr_err("ioremap() failed\n"); wanxl_pci_remove_one(pdev); @@ -704,7 +704,7 @@ static int wanxl_pci_init_one(struct pci_dev *pdev, PCI_DMA_FROMDEVICE); } - mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware)); + mem = ioremap(mem_phy, PDM_OFFSET + sizeof(firmware)); if (!mem) { pr_err("ioremap() failed\n"); wanxl_pci_remove_one(pdev); diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index f80854180e21..ed87bc00f2aa 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -458,7 +458,7 @@ static int ath10k_ahb_resource_init(struct ath10k *ar) ar_ahb->mem_len = resource_size(res); - ar_ahb->gcc_mem = ioremap_nocache(ATH10K_GCC_REG_BASE, + ar_ahb->gcc_mem = ioremap(ATH10K_GCC_REG_BASE, ATH10K_GCC_REG_SIZE); if (!ar_ahb->gcc_mem) { ath10k_err(ar, "gcc mem ioremap error\n"); @@ -466,7 +466,7 @@ static int ath10k_ahb_resource_init(struct ath10k *ar) goto err_mem_unmap; } - ar_ahb->tcsr_mem = ioremap_nocache(ATH10K_TCSR_REG_BASE, + ar_ahb->tcsr_mem = ioremap(ATH10K_TCSR_REG_BASE, ATH10K_TCSR_REG_SIZE); if (!ar_ahb->tcsr_mem) { ath10k_err(ar, "tcsr mem ioremap error\n"); diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index c0794f5988b3..2c9cec8b53d9 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -106,7 +106,7 @@ static int ath_ahb_probe(struct platform_device *pdev) goto err_out; } - mem = ioremap_nocache(res->start, resource_size(res)); + mem = ioremap(res->start, resource_size(res)); if (mem == NULL) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 63019c3de034..cdefb8e2daf1 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -92,7 +92,7 @@ static int ath_ahb_probe(struct platform_device *pdev) return -ENXIO; } - mem = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); + mem = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (mem == NULL) { dev_err(&pdev->dev, "ioremap failed\n"); return -ENOMEM; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index f64ce5074a55..c85840cabebe 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1643,8 +1643,8 @@ static int brcmf_pcie_get_resource(struct brcmf_pciedev_info *devinfo) return -EINVAL; } - devinfo->regs = ioremap_nocache(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE); - devinfo->tcm = ioremap_nocache(bar1_addr, bar1_size); + devinfo->regs = ioremap(bar0_addr, BRCMF_PCIE_REG_MAP_SIZE); + devinfo->tcm = ioremap(bar1_addr, bar1_size); if (!devinfo->regs || !devinfo->tcm) { brcmf_err(bus, "ioremap() failed (%p,%p)\n", devinfo->regs, diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c index c4c83ab60cbc..e85858eec8ff 100644 --- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c @@ -6167,7 +6167,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, ioaddr = pci_iomap(pci_dev, 0, 0); if (!ioaddr) { printk(KERN_WARNING DRV_NAME - "Error calling ioremap_nocache.\n"); + "Error calling ioremap.\n"); err = -EIO; goto fail; } diff --git a/drivers/opp/ti-opp-supply.c b/drivers/opp/ti-opp-supply.c index 1c69c404df11..e3357e91decb 100644 --- a/drivers/opp/ti-opp-supply.c +++ b/drivers/opp/ti-opp-supply.c @@ -90,7 +90,7 @@ static int _store_optimized_voltages(struct device *dev, goto out_map; } - base = ioremap_nocache(res->start, resource_size(res)); + base = ioremap(res->start, resource_size(res)); if (!base) { dev_err(dev, "Unable to map Efuse registers\n"); ret = -ENOMEM; diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index ad290f79983b..a5507f75b524 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1534,7 +1534,7 @@ static int __init ccio_probe(struct parisc_device *dev) *ioc_p = ioc; ioc->hw_path = dev->hw_path; - ioc->ioc_regs = ioremap_nocache(dev->hpa.start, 4096); + ioc->ioc_regs = ioremap(dev->hpa.start, 4096); if (!ioc->ioc_regs) { kfree(ioc); return -ENOMEM; diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 2f1cac89ddf5..889d7ce282eb 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -974,7 +974,7 @@ static int __init dino_probe(struct parisc_device *dev) } dino_dev->hba.dev = dev; - dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096); + dino_dev->hba.base_addr = ioremap(hpa, 4096); dino_dev->hba.lmmio_space_offset = PCI_F_EXTEND; spin_lock_init(&dino_dev->dinosaur_pen); dino_dev->hba.iommu = ccio_get_iommu(dev); diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c index 37a2c5db761d..9d00a24277aa 100644 --- a/drivers/parisc/eisa.c +++ b/drivers/parisc/eisa.c @@ -354,10 +354,10 @@ static int __init eisa_probe(struct parisc_device *dev) eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR; } } - eisa_eeprom_addr = ioremap_nocache(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH); + eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH); if (!eisa_eeprom_addr) { result = -ENOMEM; - printk(KERN_ERR "EISA: ioremap_nocache failed!\n"); + printk(KERN_ERR "EISA: ioremap failed!\n"); goto error_free_irq; } result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 32f506f00c89..8a3b0c3a1e92 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -927,7 +927,7 @@ void *iosapic_register(unsigned long hpa) return NULL; } - isi->addr = ioremap_nocache(hpa, 4096); + isi->addr = ioremap(hpa, 4096); isi->isi_hpa = hpa; isi->isi_version = iosapic_rd_version(isi); isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index a99e385c68bd..732b516c7bf8 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1134,7 +1134,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ** Postable I/O port space is per PCI host adapter. ** base of 64MB PIOP region */ - lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024); + lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024); sprintf(lba_dev->hba.io_name, "PCI%02x Ports", (int)lba_dev->hba.bus_num.start); @@ -1476,7 +1476,7 @@ lba_driver_probe(struct parisc_device *dev) u32 func_class; void *tmp_obj; char *version; - void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096); + void __iomem *addr = ioremap(dev->hpa.start, 4096); int max; /* Read HW Rev First */ @@ -1575,7 +1575,7 @@ lba_driver_probe(struct parisc_device *dev) } else { if (!astro_iop_base) { /* Sprockets PDC uses NPIOP region */ - astro_iop_base = ioremap_nocache(LBA_PORT_BASE, 64 * 1024); + astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024); pci_port = &lba_astro_port_ops; } @@ -1693,7 +1693,7 @@ void __init lba_init(void) */ void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) { - void __iomem * base_addr = ioremap_nocache(lba->hpa.start, 4096); + void __iomem * base_addr = ioremap(lba->hpa.start, 4096); imask <<= 2; /* adjust for hints - 2 more bits */ diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index de8e4e347249..7e112829d250 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1513,7 +1513,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) static void __iomem *ioc_remap(struct sba_device *sba_dev, unsigned int offset) { - return ioremap_nocache(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE); + return ioremap(sba_dev->dev->hpa.start + offset, SBA_FUNC_SIZE); } static void sba_hw_init(struct sba_device *sba_dev) @@ -1883,7 +1883,7 @@ static int __init sba_driver_callback(struct parisc_device *dev) u32 func_class; int i; char *version; - void __iomem *sba_addr = ioremap_nocache(dev->hpa.start, SBA_FUNC_SIZE); + void __iomem *sba_addr = ioremap(dev->hpa.start, SBA_FUNC_SIZE); #ifdef CONFIG_PROC_FS struct proc_dir_entry *root; #endif diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index b20651cea09f..9bf7fa99b103 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -719,7 +719,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf"); - base = devm_ioremap_nocache(dev, res->start, resource_size(res)); + base = devm_ioremap(dev, res->start, resource_size(res)); if (!base) return -ENOMEM; diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 3dd2e2697294..cfeccd7e9fff 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -434,7 +434,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, tbl_addr += (tbl_offset + ((interrupt_num - 1) * PCI_MSIX_ENTRY_SIZE)); tbl_addr &= PCI_BASE_ADDRESS_MEM_MASK; - msix_tbl = ioremap_nocache(ep->phys_base + tbl_addr, + msix_tbl = ioremap(ep->phys_base + tbl_addr, PCI_MSIX_ENTRY_SIZE); if (!msix_tbl) return -EINVAL; diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index c7709e49f0e4..6b43a5455c7a 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -688,7 +688,7 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) table_offset &= PCI_MSIX_TABLE_OFFSET; phys_addr = pci_resource_start(dev, bir) + table_offset; - return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); + return ioremap(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); } static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e87196cc1a7f..df21e3227b57 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -184,7 +184,7 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) pci_warn(pdev, "can't ioremap BAR %d: %pR\n", bar, res); return NULL; } - return ioremap_nocache(res->start, resource_size(res)); + return ioremap(res->start, resource_size(res)); } EXPORT_SYMBOL_GPL(pci_ioremap_bar); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4937a088d7d8..0d92374b0a11 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1571,7 +1571,7 @@ static void asus_hides_smbus_lpc_ich6_suspend(struct pci_dev *dev) pci_read_config_dword(dev, 0xF0, &rcba); /* use bits 31:14, 16 kB aligned */ - asus_rcba_base = ioremap_nocache(rcba & 0xFFFFC000, 0x4000); + asus_rcba_base = ioremap(rcba & 0xFFFFC000, 0x4000); if (asus_rcba_base == NULL) return; } @@ -4784,7 +4784,7 @@ static int pci_quirk_enable_intel_lpc_acs(struct pci_dev *dev) if (!(rcba & INTEL_LPC_RCBA_ENABLE)) return -EINVAL; - rcba_mem = ioremap_nocache(rcba & INTEL_LPC_RCBA_MASK, + rcba_mem = ioremap(rcba & INTEL_LPC_RCBA_MASK, PAGE_ALIGN(INTEL_UPDCR_REG)); if (!rcba_mem) return -ENOMEM; diff --git a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c index 32f268f173d1..57044ab376d3 100644 --- a/drivers/pinctrl/bcm/pinctrl-ns2-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-ns2-mux.c @@ -1049,7 +1049,7 @@ static int ns2_pinmux_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) return -EINVAL; - pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start, + pinctrl->base1 = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!pinctrl->base1) { dev_err(&pdev->dev, "unable to map I/O space\n"); diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-mux.c b/drivers/pinctrl/bcm/pinctrl-nsp-mux.c index 3756fc9d5826..f1d60a708815 100644 --- a/drivers/pinctrl/bcm/pinctrl-nsp-mux.c +++ b/drivers/pinctrl/bcm/pinctrl-nsp-mux.c @@ -578,7 +578,7 @@ static int nsp_pinmux_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) return -EINVAL; - pinctrl->base1 = devm_ioremap_nocache(&pdev->dev, res->start, + pinctrl->base1 = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!pinctrl->base1) { dev_err(&pdev->dev, "unable to map I/O space\n"); diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index 7e29e3fecdb2..c00d0022d311 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -611,7 +611,7 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev, if (!res) return -ENOENT; - ipctl->base = devm_ioremap_nocache(&pdev->dev, res->start, + ipctl->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!ipctl->base) return -ENOMEM; diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index eab078244a4c..73aff6591de2 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -866,7 +866,7 @@ static int amd_gpio_probe(struct platform_device *pdev) return -EINVAL; } - gpio_dev->base = devm_ioremap_nocache(&pdev->dev, res->start, + gpio_dev->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!gpio_dev->base) return -ENOMEM; diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index cdab916fbf92..5ea5245b8b15 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -652,7 +652,7 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id) scu->ipc_base = pcim_iomap_table(pdev)[0]; - scu->i2c_base = ioremap_nocache(pdata->i2c_base, pdata->i2c_len); + scu->i2c_base = ioremap(pdata->i2c_base, pdata->i2c_len); if (!scu->i2c_base) return -ENOMEM; diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index df8565bad595..ebfcfead23b4 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -1156,7 +1156,7 @@ static int telemetry_pltdrv_probe(struct platform_device *pdev) telm_conf->ioss_config.ssram_base_addr = res1->start; telm_conf->ioss_config.ssram_size = size; - telm_conf->pss_config.regmap = ioremap_nocache( + telm_conf->pss_config.regmap = ioremap( telm_conf->pss_config.ssram_base_addr, telm_conf->pss_config.ssram_size); if (!telm_conf->pss_config.regmap) { @@ -1164,7 +1164,7 @@ static int telemetry_pltdrv_probe(struct platform_device *pdev) goto out; } - telm_conf->ioss_config.regmap = ioremap_nocache( + telm_conf->ioss_config.regmap = ioremap( telm_conf->ioss_config.ssram_base_addr, telm_conf->ioss_config.ssram_size); if (!telm_conf->ioss_config.regmap) { diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c index 52ef1419b671..3e3c66dfec2e 100644 --- a/drivers/platform/x86/pmc_atom.c +++ b/drivers/platform/x86/pmc_atom.c @@ -489,7 +489,7 @@ static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent) pci_read_config_dword(pdev, PMC_BASE_ADDR_OFFSET, &pmc->base_addr); pmc->base_addr &= PMC_BASE_ADDR_MASK; - pmc->regmap = ioremap_nocache(pmc->base_addr, PMC_MMIO_REG_LEN); + pmc->regmap = ioremap(pmc->base_addr, PMC_MMIO_REG_LEN); if (!pmc->regmap) { dev_err(&pdev->dev, "error: ioremap failed\n"); return -ENOMEM; diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index 9b6a93ff41ff..23e40aa2176e 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -1394,7 +1394,7 @@ static int __init samsung_sabi_init(struct samsung_laptop *samsung) int ret = 0; int i; - samsung->f0000_segment = ioremap_nocache(0xf0000, 0xffff); + samsung->f0000_segment = ioremap(0xf0000, 0xffff); if (!samsung->f0000_segment) { if (debug || force) pr_err("Can't map the segment at 0xf0000\n"); @@ -1434,7 +1434,7 @@ static int __init samsung_sabi_init(struct samsung_laptop *samsung) if (debug) samsung_sabi_infos(samsung, loca, ifaceP); - samsung->sabi_iface = ioremap_nocache(ifaceP, 16); + samsung->sabi_iface = ioremap(ifaceP, 16); if (!samsung->sabi_iface) { pr_err("Can't remap %x\n", ifaceP); ret = -EINVAL; diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index 89b9314d64c9..af9abcd9c166 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -748,7 +748,7 @@ static int ti_abb_probe(struct platform_device *pdev) * We may have shared interrupt register offsets which are * write-1-to-clear between domains ensuring exclusivity. */ - abb->int_base = devm_ioremap_nocache(dev, res->start, + abb->int_base = devm_ioremap(dev, res->start, resource_size(res)); if (!abb->int_base) { dev_err(dev, "Unable to map '%s'\n", pname); @@ -768,7 +768,7 @@ static int ti_abb_probe(struct platform_device *pdev) * We may have shared efuse register offsets which are read-only * between domains */ - abb->efuse_base = devm_ioremap_nocache(dev, res->start, + abb->efuse_base = devm_ioremap(dev, res->start, resource_size(res)); if (!abb->efuse_base) { dev_err(dev, "Unable to map '%s'\n", pname); diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 579b3ff5c644..feb1f8e52c00 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -504,7 +504,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev) if (unlikely(!rtc->res)) return -EBUSY; - rtc->regbase = devm_ioremap_nocache(&pdev->dev, rtc->res->start, + rtc->regbase = devm_ioremap(&pdev->dev, rtc->res->start, rtc->regsize); if (unlikely(!rtc->regbase)) return -EINVAL; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 8466aa784ec1..8b891a05d9e7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -293,7 +293,7 @@ ahd_linux_pci_reserve_mem_region(struct ahd_softc *ahd, if (!request_mem_region(start, 0x1000, "aic79xx")) error = ENOMEM; if (!error) { - *maddr = ioremap_nocache(base_page, base_offset + 512); + *maddr = ioremap(base_page, base_offset + 512); if (*maddr == NULL) { error = ENOMEM; release_mem_region(start, 0x1000); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 717d8d1082ce..9b293b1f0b71 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -372,7 +372,7 @@ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc, if (!request_mem_region(start, 0x1000, "aic7xxx")) error = ENOMEM; if (error == 0) { - *maddr = ioremap_nocache(start, 256); + *maddr = ioremap(start, 256); if (*maddr == NULL) { error = ENOMEM; release_mem_region(start, 0x1000); diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index db687ef8a99e..40dc8eac0e3a 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -270,7 +270,7 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb) break; } case ACB_ADAPTER_TYPE_C:{ - acb->pmuC = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); + acb->pmuC = ioremap(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); if (!acb->pmuC) { printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); return false; diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 0760d0bd8a10..9b81cfbbc5c5 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -453,14 +453,14 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba, u8 __iomem *addr; int pcicfg_reg; - addr = ioremap_nocache(pci_resource_start(pcidev, 2), + addr = ioremap(pci_resource_start(pcidev, 2), pci_resource_len(pcidev, 2)); if (addr == NULL) return -ENOMEM; phba->ctrl.csr = addr; phba->csr_va = addr; - addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024); + addr = ioremap(pci_resource_start(pcidev, 4), 128 * 1024); if (addr == NULL) goto pci_map_err; phba->ctrl.db = addr; @@ -471,7 +471,7 @@ static int beiscsi_map_pci_bars(struct beiscsi_hba *phba, else pcicfg_reg = 0; - addr = ioremap_nocache(pci_resource_start(pcidev, pcicfg_reg), + addr = ioremap(pci_resource_start(pcidev, pcicfg_reg), pci_resource_len(pcidev, pcicfg_reg)); if (addr == NULL) diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index f069e09beb10..6f8335ddb1f2 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -1414,7 +1414,7 @@ int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt) reg_base = pci_resource_start(hba->pcidev, BNX2X_DOORBELL_PCI_BAR); reg_off = (1 << BNX2X_DB_SHIFT) * (context_id & 0x1FFFF); - tgt->ctx_base = ioremap_nocache(reg_base + reg_off, 4); + tgt->ctx_base = ioremap(reg_base + reg_off, 4); if (!tgt->ctx_base) return -ENOMEM; return 0; diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 12666313b937..e53ebc5eff85 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -2715,7 +2715,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) reg_base = pci_resource_start(ep->hba->pcidev, BNX2X_DOORBELL_PCI_BAR); reg_off = (1 << BNX2X_DB_SHIFT) * (cid_num & 0x1FFFF); - ep->qp.ctx_base = ioremap_nocache(reg_base + reg_off, 4); + ep->qp.ctx_base = ioremap(reg_base + reg_off, 4); if (!ep->qp.ctx_base) return -ENOMEM; goto arm_cq; @@ -2736,7 +2736,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) /* 5709 device in normal node and 5706/5708 devices */ reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num); - ep->qp.ctx_base = ioremap_nocache(ep->hba->reg_base + reg_off, + ep->qp.ctx_base = ioremap(ep->hba->reg_base + reg_off, MB_KERNEL_CTX_SIZE); if (!ep->qp.ctx_base) return -ENOMEM; diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c index 2e8a3ac575cb..8dea7d53788a 100644 --- a/drivers/scsi/csiostor/csio_init.c +++ b/drivers/scsi/csiostor/csio_init.c @@ -529,7 +529,7 @@ static struct csio_hw *csio_hw_alloc(struct pci_dev *pdev) goto err_free_hw; /* Get the start address of registers from BAR 0 */ - hw->regstart = ioremap_nocache(pci_resource_start(pdev, 0), + hw->regstart = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!hw->regstart) { csio_err(hw, "Could not map BAR 0, regstart = %p\n", diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 216e557f703e..1a4ddfacb458 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6876,7 +6876,7 @@ static void __iomem *remap_pci_mem(ulong base, ulong size) { ulong page_base = ((ulong) base) & PAGE_MASK; ulong page_offs = ((ulong) base) - page_base; - void __iomem *page_remapped = ioremap_nocache(page_base, + void __iomem *page_remapped = ioremap(page_base, page_offs + size); return page_remapped ? (page_remapped + page_offs) : NULL; diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index abac2f350aee..c48a73a0f517 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -98,7 +98,7 @@ lasi700_probe(struct parisc_device *dev) hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); - hostdata->base = ioremap_nocache(base, 0x100); + hostdata->base = ioremap(base, 0x100); hostdata->differential = 0; if (dev->id.sversion == LASI_700_SVERSION) { diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index f6ac819e6e96..8443f2f35be2 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -731,7 +731,7 @@ megaraid_init_mbox(adapter_t *adapter) goto out_free_raid_dev; } - raid_dev->baseaddr = ioremap_nocache(raid_dev->baseport, 128); + raid_dev->baseaddr = ioremap(raid_dev->baseport, 128); if (!raid_dev->baseaddr) { diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index a4bc81479284..c60cd9fc4240 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -5875,7 +5875,7 @@ static int megasas_init_fw(struct megasas_instance *instance) } base_addr = pci_resource_start(instance->pdev, instance->bar); - instance->reg_set = ioremap_nocache(base_addr, 8192); + instance->reg_set = ioremap(base_addr, 8192); if (!instance->reg_set) { dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to map IO mem\n"); diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c index 539ac8ce4fcd..d4bd31a75b9d 100644 --- a/drivers/scsi/myrb.c +++ b/drivers/scsi/myrb.c @@ -3531,7 +3531,7 @@ static struct myrb_hba *myrb_detect(struct pci_dev *pdev, spin_lock_init(&cb->queue_lock); if (mmio_size < PAGE_SIZE) mmio_size = PAGE_SIZE; - cb->mmio_base = ioremap_nocache(cb->pci_addr & PAGE_MASK, mmio_size); + cb->mmio_base = ioremap(cb->pci_addr & PAGE_MASK, mmio_size); if (cb->mmio_base == NULL) { dev_err(&pdev->dev, "Unable to map Controller Register Window\n"); diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c index eb0dd566330a..5c5666491c2e 100644 --- a/drivers/scsi/myrs.c +++ b/drivers/scsi/myrs.c @@ -2311,7 +2311,7 @@ static struct myrs_hba *myrs_detect(struct pci_dev *pdev, /* Map the Controller Register Window. */ if (mmio_size < PAGE_SIZE) mmio_size = PAGE_SIZE; - cs->mmio_base = ioremap_nocache(cs->pci_addr & PAGE_MASK, mmio_size); + cs->mmio_base = ioremap(cs->pci_addr & PAGE_MASK, mmio_size); if (cs->mmio_base == NULL) { dev_err(&pdev->dev, "Unable to map Controller Register Window\n"); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 93616f9fd6d7..d79ce97a04bd 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1560,7 +1560,7 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data) goto next_entry; data->MmioAddress = (unsigned long) - ioremap_nocache(p_dev->resource[2]->start, + ioremap(p_dev->resource[2]->start, resource_size(p_dev->resource[2])); data->MmioLength = resource_size(p_dev->resource[2]); } diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 605b59c76c90..a3a44d4ace1e 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -789,7 +789,7 @@ qlafx00_iospace_config(struct qla_hw_data *ha) } ha->cregbase = - ioremap_nocache(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00); + ioremap(pci_resource_start(ha->pdev, 0), BAR0_LEN_FX00); if (!ha->cregbase) { ql_log_pci(ql_log_fatal, ha->pdev, 0x0128, "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev)); @@ -810,7 +810,7 @@ qlafx00_iospace_config(struct qla_hw_data *ha) } ha->iobase = - ioremap_nocache(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00); + ioremap(pci_resource_start(ha->pdev, 2), BAR2_LEN_FX00); if (!ha->iobase) { ql_log_pci(ql_log_fatal, ha->pdev, 0x012b, "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev)); diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 412ac56ecd60..b7492568e02f 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -7457,7 +7457,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info) goto disable_device; } - ctrl_info->iomem_base = ioremap_nocache(pci_resource_start( + ctrl_info->iomem_base = ioremap(pci_resource_start( ctrl_info->pci_dev, 0), sizeof(struct pqi_ctrl_registers)); if (!ctrl_info->iomem_base) { diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c index a85d52b5dc32..f8397978f8ab 100644 --- a/drivers/scsi/sni_53c710.c +++ b/drivers/scsi/sni_53c710.c @@ -71,7 +71,7 @@ static int snirm710_probe(struct platform_device *dev) hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); - hostdata->base = ioremap_nocache(base, 0x100); + hostdata->base = ioremap(base, 0x100); hostdata->differential = 0; hostdata->clock = SNIRM710_CLOCK; diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index 440a73eae647..f37df79e37e1 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -190,7 +190,7 @@ static int esp_sun3x_probe(struct platform_device *dev) if (!res || !res->start) goto fail_unlink; - esp->regs = ioremap_nocache(res->start, 0x20); + esp->regs = ioremap(res->start, 0x20); if (!esp->regs) goto fail_unmap_regs; @@ -198,7 +198,7 @@ static int esp_sun3x_probe(struct platform_device *dev) if (!res || !res->start) goto fail_unmap_regs; - esp->dma_regs = ioremap_nocache(res->start, 0x10); + esp->dma_regs = ioremap(res->start, 0x10); esp->command_block = dma_alloc_coherent(esp->dev, 16, &esp->command_block_dma, diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 77bce208210e..7eac76cccc4c 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -89,7 +89,7 @@ zalon_probe(struct parisc_device *dev) struct gsc_irq gsc_irq; u32 zalon_vers; int error = -ENODEV; - void __iomem *zalon = ioremap_nocache(dev->hpa.start, 4096); + void __iomem *zalon = ioremap(dev->hpa.start, 4096); void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET; static int unit = 0; struct Scsi_Host *host; diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c index a23a8e5794f5..bdd82e497d5f 100644 --- a/drivers/scsi/zorro_esp.c +++ b/drivers/scsi/zorro_esp.c @@ -801,7 +801,7 @@ static int zorro_esp_probe(struct zorro_dev *z, /* additional setup required for Fastlane */ if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) { /* map full address space up to ESP base for DMA */ - zep->board_base = ioremap_nocache(board, + zep->board_base = ioremap(board, FASTLANE_ESP_ADDR-1); if (!zep->board_base) { pr_err("Cannot allocate board address space\n"); @@ -816,7 +816,7 @@ static int zorro_esp_probe(struct zorro_dev *z, esp->ops = zdd->esp_ops; if (ioaddr > 0xffffff) - esp->regs = ioremap_nocache(ioaddr, 0x20); + esp->regs = ioremap(ioaddr, 0x20); else /* ZorroII address space remapped nocache by early startup */ esp->regs = ZTWO_VADDR(ioaddr); @@ -842,7 +842,7 @@ static int zorro_esp_probe(struct zorro_dev *z, * Only Fastlane Z3 for now - add switch for correct struct * dma_registers size if adding any more */ - esp->dma_regs = ioremap_nocache(dmaaddr, + esp->dma_regs = ioremap(dmaaddr, sizeof(struct fastlane_dma_registers)); } else /* ZorroII address space remapped nocache by early startup */ diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 9475353f49d6..d996782a7106 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -368,7 +368,7 @@ static int clk_establish_mapping(struct clk *clk) if (!mapping->base && mapping->phys) { kref_init(&mapping->ref); - mapping->base = ioremap_nocache(mapping->phys, mapping->len); + mapping->base = ioremap(mapping->phys, mapping->len); if (unlikely(!mapping->base)) return -ENXIO; } else if (mapping->base) { diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 8485e812d9b2..f8e070d67fa3 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -213,7 +213,7 @@ int __init register_intc_controller(struct intc_desc *desc) WARN_ON(resource_type(res) != IORESOURCE_MEM); d->window[k].phys = res->start; d->window[k].size = resource_size(res); - d->window[k].virt = ioremap_nocache(res->start, + d->window[k].virt = ioremap(res->start, resource_size(res)); if (!d->window[k].virt) goto err2; diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c index 87d69e7471f9..f9f043a3d90a 100644 --- a/drivers/sh/intc/userimask.c +++ b/drivers/sh/intc/userimask.c @@ -73,7 +73,7 @@ int register_intc_userimask(unsigned long addr) if (unlikely(uimask)) return -EBUSY; - uimask = ioremap_nocache(addr, SZ_4K); + uimask = ioremap(addr, SZ_4K); if (unlikely(!uimask)) return -ENOMEM; diff --git a/drivers/soc/tegra/flowctrl.c b/drivers/soc/tegra/flowctrl.c index eb96a3086d6d..5db919d96aba 100644 --- a/drivers/soc/tegra/flowctrl.c +++ b/drivers/soc/tegra/flowctrl.c @@ -219,7 +219,7 @@ static int __init tegra_flowctrl_init(void) return 0; } - tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res)); + tegra_flowctrl_base = ioremap(res.start, resource_size(&res)); if (!tegra_flowctrl_base) return -ENXIO; diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 4d719d4b8d5a..606abbe55bba 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -408,7 +408,7 @@ static int __init tegra_init_fuse(void) } } - fuse->base = ioremap_nocache(regs.start, resource_size(®s)); + fuse->base = ioremap(regs.start, resource_size(®s)); if (!fuse->base) { pr_err("failed to map FUSE registers\n"); return -ENXIO; diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index df76778af601..a2fd6ccd48f9 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -159,11 +159,11 @@ void __init tegra_init_apbmisc(void) } } - apbmisc_base = ioremap_nocache(apbmisc.start, resource_size(&apbmisc)); + apbmisc_base = ioremap(apbmisc.start, resource_size(&apbmisc)); if (!apbmisc_base) pr_err("failed to map APBMISC registers\n"); - strapping_base = ioremap_nocache(straps.start, resource_size(&straps)); + strapping_base = ioremap(straps.start, resource_size(&straps)); if (!strapping_base) pr_err("failed to map strapping options registers\n"); diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index ea0e11a09c12..1699dda6b393 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2826,7 +2826,7 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, of_address_to_resource(np, index, ®s); - wake = ioremap_nocache(regs.start, resource_size(®s)); + wake = ioremap(regs.start, resource_size(®s)); if (!wake) { dev_err(pmc->dev, "failed to map PMC wake registers\n"); return; @@ -3097,7 +3097,7 @@ static int __init tegra_pmc_early_init(void) } } - pmc->base = ioremap_nocache(regs.start, resource_size(®s)); + pmc->base = ioremap(regs.start, resource_size(®s)); if (!pmc->base) { pr_err("failed to map PMC registers\n"); of_node_put(np); diff --git a/drivers/soc/xilinx/xlnx_vcu.c b/drivers/soc/xilinx/xlnx_vcu.c index a840c0272135..a3aa40996f13 100644 --- a/drivers/soc/xilinx/xlnx_vcu.c +++ b/drivers/soc/xilinx/xlnx_vcu.c @@ -511,7 +511,7 @@ static int xvcu_probe(struct platform_device *pdev) return -ENODEV; } - xvcu->vcu_slcr_ba = devm_ioremap_nocache(&pdev->dev, res->start, + xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!xvcu->vcu_slcr_ba) { dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); @@ -524,7 +524,7 @@ static int xvcu_probe(struct platform_device *pdev) return -ENODEV; } - xvcu->logicore_reg_ba = devm_ioremap_nocache(&pdev->dev, res->start, + xvcu->logicore_reg_ba = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!xvcu->logicore_reg_ba) { dev_err(&pdev->dev, "logicore register mapping failed.\n"); diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 2663bb12d9ce..0d86c37e0aeb 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -301,7 +301,7 @@ int dw_spi_mid_init(struct dw_spi *dws) void __iomem *clk_reg; u32 clk_cdiv; - clk_reg = ioremap_nocache(MRST_CLK_SPI_REG, 16); + clk_reg = ioremap(MRST_CLK_SPI_REG, 16); if (!clk_reg) return -ENOMEM; diff --git a/drivers/spi/spi-jcore.c b/drivers/spi/spi-jcore.c index cc49fa41fbab..bba10f030e33 100644 --- a/drivers/spi/spi-jcore.c +++ b/drivers/spi/spi-jcore.c @@ -170,7 +170,7 @@ static int jcore_spi_probe(struct platform_device *pdev) if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res), pdev->name)) goto exit_busy; - hw->base = devm_ioremap_nocache(&pdev->dev, res->start, + hw->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!hw->base) goto exit_busy; diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index cb52fd8008d0..d25ee32862e0 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -603,7 +603,7 @@ static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) if (!chip->flash_region_mapped_ptr) { chip->flash_region_mapped_ptr = - devm_ioremap_nocache(fiu->dev, (fiu->res_mem->start + + devm_ioremap(fiu->dev, (fiu->res_mem->start + (fiu->info->max_map_size * desc->mem->spi->chip_select)), (u32)desc->info.length); diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c index 06b68dd6e022..bc275968fcc6 100644 --- a/drivers/ssb/driver_extif.c +++ b/drivers/ssb/driver_extif.c @@ -63,7 +63,7 @@ int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports for (i = 0; i < 2; i++) { void __iomem *uart_regs; - uart_regs = ioremap_nocache(SSB_EUART, 16); + uart_regs = ioremap(SSB_EUART, 16); if (uart_regs) { uart_regs += (i * 8); diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 6a5622e0ded5..c1186415896b 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -122,7 +122,7 @@ static int ssb_extpci_read_config(struct ssb_pcicore *pc, if (unlikely(!addr)) goto out; err = -ENOMEM; - mmio = ioremap_nocache(addr, len); + mmio = ioremap(addr, len); if (!mmio) goto out; @@ -168,7 +168,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc, if (unlikely(!addr)) goto out; err = -ENOMEM; - mmio = ioremap_nocache(addr, len); + mmio = ioremap(addr, len); if (!mmio) goto out; @@ -382,7 +382,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc) /* Ok, ready to run, register it to the system. * The following needs change, if we want to port hostmode * to non-MIPS platform. */ - ssb_pcicore_controller.io_map_base = (unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000); + ssb_pcicore_controller.io_map_base = (unsigned long)ioremap(SSB_PCI_MEM, 0x04000000); set_io_port_base(ssb_pcicore_controller.io_map_base); /* Give some time to the PCI controller to configure itself with the new * values. Not waiting at this point causes crashes of the machine. */ diff --git a/drivers/staging/gasket/gasket_core.c b/drivers/staging/gasket/gasket_core.c index cd8be80d2076..be6b50f454b4 100644 --- a/drivers/staging/gasket/gasket_core.c +++ b/drivers/staging/gasket/gasket_core.c @@ -303,7 +303,7 @@ static int gasket_map_pci_bar(struct gasket_dev *gasket_dev, int bar_num) } gasket_dev->bar_data[bar_num].virt_base = - ioremap_nocache(gasket_dev->bar_data[bar_num].phys_base, + ioremap(gasket_dev->bar_data[bar_num].phys_base, gasket_dev->bar_data[bar_num].length_bytes); if (!gasket_dev->bar_data[bar_num].virt_base) { dev_err(gasket_dev->dev, diff --git a/drivers/staging/kpc2000/kpc2000/core.c b/drivers/staging/kpc2000/kpc2000/core.c index 0a23727d0dc3..93cf28febdf6 100644 --- a/drivers/staging/kpc2000/kpc2000/core.c +++ b/drivers/staging/kpc2000/kpc2000/core.c @@ -338,7 +338,7 @@ static int kp2000_pcie_probe(struct pci_dev *pdev, reg_bar_phys_addr = pci_resource_start(pcard->pdev, REG_BAR); reg_bar_phys_len = pci_resource_len(pcard->pdev, REG_BAR); - pcard->regs_bar_base = ioremap_nocache(reg_bar_phys_addr, PAGE_SIZE); + pcard->regs_bar_base = ioremap(reg_bar_phys_addr, PAGE_SIZE); if (!pcard->regs_bar_base) { dev_err(&pcard->pdev->dev, "probe: REG_BAR could not remap memory to virtual space\n"); @@ -367,7 +367,7 @@ static int kp2000_pcie_probe(struct pci_dev *pdev, dma_bar_phys_addr = pci_resource_start(pcard->pdev, DMA_BAR); dma_bar_phys_len = pci_resource_len(pcard->pdev, DMA_BAR); - pcard->dma_bar_base = ioremap_nocache(dma_bar_phys_addr, + pcard->dma_bar_base = ioremap(dma_bar_phys_addr, dma_bar_phys_len); if (!pcard->dma_bar_base) { dev_err(&pcard->pdev->dev, diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 5460bf973c9c..592099a1fca5 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -659,7 +659,7 @@ static int pi2c_probe(struct platform_device *pldev) if (!res) return -ENXIO; - priv->smba = (unsigned long)devm_ioremap_nocache(&pldev->dev, + priv->smba = (unsigned long)devm_ioremap(&pldev->dev, res->start, resource_size(res)); if (!priv->smba) diff --git a/drivers/staging/kpc2000/kpc2000_spi.c b/drivers/staging/kpc2000/kpc2000_spi.c index 8becf972af9c..1c360daa703d 100644 --- a/drivers/staging/kpc2000/kpc2000_spi.c +++ b/drivers/staging/kpc2000/kpc2000_spi.c @@ -464,7 +464,7 @@ kp_spi_probe(struct platform_device *pldev) goto free_master; } - kpspi->base = devm_ioremap_nocache(&pldev->dev, r->start, + kpspi->base = devm_ioremap(&pldev->dev, r->start, resource_size(r)); status = spi_register_master(master); diff --git a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c index a05ae6d40db9..ec79a8500caf 100644 --- a/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c +++ b/drivers/staging/kpc2000/kpc_dma/kpc_dma_driver.c @@ -122,7 +122,7 @@ int kpc_dma_probe(struct platform_device *pldev) rv = -ENXIO; goto err_kfree; } - ldev->eng_regs = ioremap_nocache(r->start, resource_size(r)); + ldev->eng_regs = ioremap(r->start, resource_size(r)); if (!ldev->eng_regs) { dev_err(&ldev->pldev->dev, "%s: failed to ioremap engine regs!\n", __func__); rv = -ENXIO; diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c index 6f0cd0784786..3be41698df4c 100644 --- a/drivers/staging/media/allegro-dvt/allegro-core.c +++ b/drivers/staging/media/allegro-dvt/allegro-core.c @@ -2914,7 +2914,7 @@ static int allegro_probe(struct platform_device *pdev) "regs resource missing from device tree\n"); return -EINVAL; } - regs = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); + regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (IS_ERR(regs)) { dev_err(&pdev->dev, "failed to map registers\n"); return PTR_ERR(regs); @@ -2932,7 +2932,7 @@ static int allegro_probe(struct platform_device *pdev) "sram resource missing from device tree\n"); return -EINVAL; } - sram_regs = devm_ioremap_nocache(&pdev->dev, + sram_regs = devm_ioremap(&pdev->dev, sram_res->start, resource_size(sram_res)); if (IS_ERR(sram_regs)) { diff --git a/drivers/staging/qlge/qlge_main.c b/drivers/staging/qlge/qlge_main.c index 6ad4515311f7..d890d38a1d29 100644 --- a/drivers/staging/qlge/qlge_main.c +++ b/drivers/staging/qlge/qlge_main.c @@ -4455,7 +4455,7 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, pdev->needs_freset = 1; pci_save_state(pdev); qdev->reg_base = - ioremap_nocache(pci_resource_start(pdev, 1), + ioremap(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); if (!qdev->reg_base) { dev_err(&pdev->dev, "Register mapping failed.\n"); @@ -4465,7 +4465,7 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, qdev->doorbell_area_size = pci_resource_len(pdev, 3); qdev->doorbell_area = - ioremap_nocache(pci_resource_start(pdev, 3), + ioremap(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); if (!qdev->doorbell_area) { dev_err(&pdev->dev, "Doorbell register mapping failed.\n"); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index dace81a7d1ba..e895473fcfd7 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -2463,7 +2463,7 @@ static int _rtl92e_pci_probe(struct pci_dev *pdev, } - ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len); + ioaddr = (unsigned long)ioremap(pmem_start, pmem_len); if (ioaddr == (unsigned long)NULL) { netdev_err(dev, "ioremap failed!"); goto err_rel_mem; diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c index cb95ad6fa4f9..fbb42e5258fd 100644 --- a/drivers/staging/rts5208/rtsx.c +++ b/drivers/staging/rts5208/rtsx.c @@ -858,7 +858,7 @@ static int rtsx_probe(struct pci_dev *pci, dev_info(&pci->dev, "Resource length: 0x%x\n", (unsigned int)pci_resource_len(pci, 0)); dev->addr = pci_resource_start(pci, 0); - dev->remap_addr = ioremap_nocache(dev->addr, pci_resource_len(pci, 0)); + dev->remap_addr = ioremap(dev->addr, pci_resource_len(pci, 0)); if (!dev->remap_addr) { dev_err(&pci->dev, "ioremap error\n"); err = -ENXIO; diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index ea1d3d4efbc2..b8d60701f898 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -50,7 +50,7 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } /* now map mmio and vidmem */ - sm750_dev->pvReg = ioremap_nocache(sm750_dev->vidreg_start, + sm750_dev->pvReg = ioremap(sm750_dev->vidreg_start, sm750_dev->vidreg_size); if (!sm750_dev->pvReg) { pr_err("mmio failed\n"); diff --git a/drivers/staging/uwb/whc-rc.c b/drivers/staging/uwb/whc-rc.c index 34020ed351ab..a5ab255d7d36 100644 --- a/drivers/staging/uwb/whc-rc.c +++ b/drivers/staging/uwb/whc-rc.c @@ -216,11 +216,11 @@ int whcrc_setup_rc_umc(struct whcrc *whcrc) goto error_request_region; } - whcrc->rc_base = ioremap_nocache(whcrc->area, whcrc->rc_len); + whcrc->rc_base = ioremap(whcrc->area, whcrc->rc_len); if (whcrc->rc_base == NULL) { dev_err(dev, "can't ioremap registers (%zu bytes @ 0x%lx): %d\n", whcrc->rc_len, whcrc->area, result); - goto error_ioremap_nocache; + goto error_ioremap; } result = request_irq(umc_dev->irq, whcrc_irq_cb, IRQF_SHARED, @@ -254,7 +254,7 @@ error_cmd_buffer: free_irq(umc_dev->irq, whcrc); error_request_irq: iounmap(whcrc->rc_base); -error_ioremap_nocache: +error_ioremap: release_mem_region(whcrc->area, whcrc->rc_len); error_request_region: return result; diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index cf3fad2cb871..c5b17dd8f587 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c @@ -47,7 +47,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) for (slot = 0; slot < tbus->num_tcslots; slot++) { slotaddr = tbus->slot_base + slot * slotsize; extslotaddr = tbus->ext_slot_base + slot * extslotsize; - module = ioremap_nocache(slotaddr, slotsize); + module = ioremap(slotaddr, slotsize); BUG_ON(!module); offset = TC_OLDCARD; diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index 4562c8060d09..a6aabfd6e2da 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -3256,7 +3256,7 @@ static int __init cy_detect_isa(void) return nboard; /* probe for CD1400... */ - cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin); + cy_isa_address = ioremap(isa_address, CyISA_Ywin); if (cy_isa_address == NULL) { printk(KERN_ERR "Cyclom-Y/ISA: can't remap base " "address\n"); @@ -3690,13 +3690,13 @@ static int cy_pci_probe(struct pci_dev *pdev, device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { card_name = "Cyclom-Y"; - addr0 = ioremap_nocache(pci_resource_start(pdev, 0), + addr0 = ioremap(pci_resource_start(pdev, 0), CyPCI_Yctl); if (addr0 == NULL) { dev_err(&pdev->dev, "can't remap ctl region\n"); goto err_reg; } - addr2 = ioremap_nocache(pci_resource_start(pdev, 2), + addr2 = ioremap(pci_resource_start(pdev, 2), CyPCI_Ywin); if (addr2 == NULL) { dev_err(&pdev->dev, "can't remap base region\n"); @@ -3712,7 +3712,7 @@ static int cy_pci_probe(struct pci_dev *pdev, } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { struct RUNTIME_9060 __iomem *ctl_addr; - ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), + ctl_addr = addr0 = ioremap(pci_resource_start(pdev, 0), CyPCI_Zctl); if (addr0 == NULL) { dev_err(&pdev->dev, "can't remap ctl region\n"); @@ -3727,7 +3727,7 @@ static int cy_pci_probe(struct pci_dev *pdev, mailbox = readl(&ctl_addr->mail_box_0); - addr2 = ioremap_nocache(pci_resource_start(pdev, 2), + addr2 = ioremap(pci_resource_start(pdev, 2), mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); if (addr2 == NULL) { dev_err(&pdev->dev, "can't remap base region\n"); diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index 4c1cd49ae95b..620d8488b83e 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c @@ -898,7 +898,7 @@ static int mips_ejtag_fdc_tty_probe(struct mips_cdmm_device *dev) atomic_set(&priv->xmit_total, 0); raw_spin_lock_init(&priv->lock); - priv->reg = devm_ioremap_nocache(priv->dev, dev->res.start, + priv->reg = devm_ioremap(priv->dev, dev->res.start, resource_size(&dev->res)); if (!priv->reg) { dev_err(priv->dev, "ioremap failed for resource %pR\n", diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index 3a1a5e0ee93f..9f13f7d49dd7 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -961,7 +961,7 @@ static int moxa_pci_probe(struct pci_dev *pdev, goto err; } - board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000); + board->basemem = ioremap(pci_resource_start(pdev, 2), 0x4000); if (board->basemem == NULL) { dev_err(&pdev->dev, "can't remap io space 2\n"); retval = -ENOMEM; @@ -1071,7 +1071,7 @@ static int __init moxa_init(void) brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : numports[i]; brd->busType = MOXA_BUS_TYPE_ISA; - brd->basemem = ioremap_nocache(baseaddr[i], 0x4000); + brd->basemem = ioremap(baseaddr[i], 0x4000); if (!brd->basemem) { printk(KERN_ERR "MOXA: can't remap %lx\n", baseaddr[i]); diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 0809ae2aa9b1..673cda3d011d 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -55,7 +55,7 @@ static int __init serial_init_chip(struct parisc_device *dev) uart.port.uartclk = (dev->id.sversion != 0xad) ? 7272727 : 1843200; uart.port.mapbase = address; - uart.port.membase = ioremap_nocache(address, 16); + uart.port.membase = ioremap(address, 16); if (!uart.port.membase) { dev_warn(&dev->dev, "Failed to map memory\n"); return -ENOMEM; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 836e736ae188..e603c66d6cc4 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -1147,7 +1147,7 @@ static int omap8250_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - membase = devm_ioremap_nocache(&pdev->dev, regs->start, + membase = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!membase) return -ENODEV; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 022924d5ad54..939685fed396 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -275,7 +275,7 @@ static int pci_plx9050_init(struct pci_dev *dev) /* * enable/disable interrupts */ - p = ioremap_nocache(pci_resource_start(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM; writel(irq_config, p + 0x4c); @@ -299,7 +299,7 @@ static void pci_plx9050_exit(struct pci_dev *dev) /* * disable interrupts */ - p = ioremap_nocache(pci_resource_start(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); if (p != NULL) { writel(0, p + 0x4c); @@ -475,7 +475,7 @@ static int pci_siig10x_init(struct pci_dev *dev) break; } - p = ioremap_nocache(pci_resource_start(dev, 0), 0x80); + p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 90655910b0c7..9ff5dfad590a 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2766,7 +2766,7 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) } if (port->flags & UPF_IOREMAP) { - port->membase = ioremap_nocache(port->mapbase, size); + port->membase = ioremap(port->mapbase, size); if (!port->membase) { release_mem_region(port->mapbase, size); ret = -ENOMEM; diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index 7b57e840e255..730da413d8ed 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c @@ -677,7 +677,7 @@ static void dz_release_port(struct uart_port *uport) static int dz_map_port(struct uart_port *uport) { if (!uport->membase) - uport->membase = ioremap_nocache(uport->mapbase, + uport->membase = ioremap(uport->mapbase, dec_kn_slot_size); if (!uport->membase) { printk(KERN_ERR "dz: Cannot map MMIO\n"); diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index fcbea43dc334..f67226df30d4 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -549,7 +549,7 @@ lqasc_request_port(struct uart_port *port) } if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(&pdev->dev, + port->membase = devm_ioremap(&pdev->dev, port->mapbase, size); if (port->membase == NULL) return -ENOMEM; diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index fbc5bc022a39..164b18372c02 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -411,7 +411,7 @@ static int meson_uart_request_port(struct uart_port *port) return -EBUSY; } - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, port->mapsize); if (!port->membase) return -ENOMEM; diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 00ce31e8d19a..fc58a004bef4 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c @@ -474,7 +474,7 @@ static int __init mux_probe(struct parisc_device *dev) port->iobase = 0; port->mapbase = dev->hpa.start + MUX_OFFSET + (i * MUX_LINE_OFFSET); - port->membase = ioremap_nocache(port->mapbase, MUX_LINE_OFFSET); + port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); port->iotype = UPIO_MEM; port->type = PORT_MUX; port->irq = 0; diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index d2d8b3494685..42c8cc93b603 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -427,7 +427,7 @@ static int owl_uart_request_port(struct uart_port *port) return -EBUSY; if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, resource_size(res)); if (!port->membase) return -EBUSY; diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c index 0bdf1687983f..484b7e8d5381 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -618,7 +618,7 @@ static int pic32_uart_request_port(struct uart_port *port) "pic32_uart_mem")) return -EBUSY; - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, resource_size(res_mem)); if (!port->membase) { dev_err(port->dev, "Unable to map registers\n"); diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c index ff9a27d48bca..b5ef86ae2746 100644 --- a/drivers/tty/serial/rda-uart.c +++ b/drivers/tty/serial/rda-uart.c @@ -498,7 +498,7 @@ static int rda_uart_request_port(struct uart_port *port) return -EBUSY; if (port->flags & UPF_IOREMAP) { - port->membase = devm_ioremap_nocache(port->dev, port->mapbase, + port->membase = devm_ioremap(port->dev, port->mapbase, resource_size(res)); if (!port->membase) return -EBUSY; diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 329aced26bd8..7c99340a3d66 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c @@ -668,7 +668,7 @@ static int sbd_map_port(struct uart_port *uport) struct sbd_duart *duart = sport->duart; if (!uport->membase) - uport->membase = ioremap_nocache(uport->mapbase, + uport->membase = ioremap(uport->mapbase, DUART_CHANREG_SPACING); if (!uport->membase) { printk(err); @@ -676,7 +676,7 @@ static int sbd_map_port(struct uart_port *uport) } if (!sport->memctrl) - sport->memctrl = ioremap_nocache(duart->mapctrl, + sport->memctrl = ioremap(duart->mapctrl, DUART_CHANREG_SPACING); if (!sport->memctrl) { printk(err); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 58bf9d496ba5..87ca6294de0e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2680,7 +2680,7 @@ static int sci_remap_port(struct uart_port *port) return 0; if (port->dev->of_node || (port->flags & UPF_IOREMAP)) { - port->membase = ioremap_nocache(port->mapbase, sport->reg_size); + port->membase = ioremap(port->mapbase, sport->reg_size); if (unlikely(!port->membase)) { dev_err(port->dev, "can't remap port#%d\n", port->line); return -ENXIO; diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index b03d3e458ea2..89154ac4c577 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -992,7 +992,7 @@ static void zs_release_port(struct uart_port *uport) static int zs_map_port(struct uart_port *uport) { if (!uport->membase) - uport->membase = ioremap_nocache(uport->mapbase, + uport->membase = ioremap(uport->mapbase, ZS_CHAN_IO_SIZE); if (!uport->membase) { printk(KERN_ERR "zs: Cannot map MMIO\n"); diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 84f26e43b229..0ca13f889d84 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -4054,7 +4054,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) } info->lcr_mem_requested = true; - info->memory_base = ioremap_nocache(info->phys_memory_base, + info->memory_base = ioremap(info->phys_memory_base, 0x40000); if (!info->memory_base) { printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n", @@ -4068,7 +4068,7 @@ static int mgsl_claim_resources(struct mgsl_struct *info) goto errout; } - info->lcr_base = ioremap_nocache(info->phys_lcr_base, + info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE); if (!info->lcr_base) { printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n", diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index e8a9047de451..e506fc489d48 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -3450,7 +3450,7 @@ static int claim_resources(struct slgt_info *info) else info->reg_addr_requested = true; - info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE); + info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE); if (!info->reg_addr) { DBGERR(("%s can't map device registers, addr=%08X\n", info->device_name, info->phys_reg_addr)); diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index fcb91bf7a15b..b9d974474b64 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -3559,7 +3559,7 @@ static int claim_resources(SLMP_INFO *info) else info->sca_statctrl_requested = true; - info->memory_base = ioremap_nocache(info->phys_memory_base, + info->memory_base = ioremap(info->phys_memory_base, SCA_MEM_SIZE); if (!info->memory_base) { printk( "%s(%d):%s Can't map shared memory, MemAddr=%08X\n", @@ -3568,7 +3568,7 @@ static int claim_resources(SLMP_INFO *info) goto errout; } - info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE); + info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE); if (!info->lcr_base) { printk( "%s(%d):%s Can't map LCR memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); @@ -3577,7 +3577,7 @@ static int claim_resources(SLMP_INFO *info) } info->lcr_base += info->lcr_offset; - info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE); + info->sca_base = ioremap(info->phys_sca_base, PAGE_SIZE); if (!info->sca_base) { printk( "%s(%d):%s Can't map SCA memory, MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_sca_base ); @@ -3586,7 +3586,7 @@ static int claim_resources(SLMP_INFO *info) } info->sca_base += info->sca_offset; - info->statctrl_base = ioremap_nocache(info->phys_statctrl_base, + info->statctrl_base = ioremap(info->phys_statctrl_base, PAGE_SIZE); if (!info->statctrl_base) { printk( "%s(%d):%s Can't map SCA Status/Control memory, MemAddr=%08X\n", diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 9ae2a7a93df2..f0a259937da8 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -222,7 +222,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) retval = -EBUSY; goto put_hcd; } - hcd->regs = devm_ioremap_nocache(&dev->dev, hcd->rsrc_start, + hcd->regs = devm_ioremap(&dev->dev, hcd->rsrc_start, hcd->rsrc_len); if (hcd->regs == NULL) { dev_dbg(&dev->dev, "error mapping memory\n"); diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index cac991173ac0..971c6b92484a 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -971,7 +971,7 @@ static int __init xdbc_init(void) goto free_and_quit; } - base = ioremap_nocache(xdbc.xhci_start, xdbc.xhci_length); + base = ioremap(xdbc.xhci_start, xdbc.xhci_length); if (!base) { xdbc_trace("failed to remap the io address\n"); ret = -ENOMEM; diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c index 57b6f66331cf..bfd1c9e80a1f 100644 --- a/drivers/usb/gadget/udc/amd5536udc_pci.c +++ b/drivers/usb/gadget/udc/amd5536udc_pci.c @@ -116,7 +116,7 @@ static int udc_pci_probe( goto err_memreg; } - dev->virt_addr = ioremap_nocache(resource, len); + dev->virt_addr = ioremap(resource, len); if (!dev->virt_addr) { dev_dbg(&pdev->dev, "start address cannot be mapped\n"); retval = -EFAULT; diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c index c3721225b61e..4a46f661d0e4 100644 --- a/drivers/usb/gadget/udc/goku_udc.c +++ b/drivers/usb/gadget/udc/goku_udc.c @@ -1782,7 +1782,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) } dev->got_region = 1; - base = ioremap_nocache(resource, len); + base = ioremap(resource, len); if (base == NULL) { DBG(dev, "can't map memory\n"); retval = -EFAULT; diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 247de0faaeb7..a8273b589456 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -2323,7 +2323,7 @@ net2272_rdk1_probe(struct pci_dev *pdev, struct net2272 *dev) goto err; } - mem_mapped_addr[i] = ioremap_nocache(resource, len); + mem_mapped_addr[i] = ioremap(resource, len); if (mem_mapped_addr[i] == NULL) { release_mem_region(resource, len); dev_dbg(dev->dev, "can't map memory\n"); @@ -2401,7 +2401,7 @@ net2272_rdk2_probe(struct pci_dev *pdev, struct net2272 *dev) goto err; } - mem_mapped_addr[i] = ioremap_nocache(resource, len); + mem_mapped_addr[i] = ioremap(resource, len); if (mem_mapped_addr[i] == NULL) { release_mem_region(resource, len); dev_dbg(dev->dev, "can't map memory\n"); @@ -2625,7 +2625,7 @@ net2272_plat_probe(struct platform_device *pdev) ret = -EBUSY; goto err; } - dev->base_addr = ioremap_nocache(base, len); + dev->base_addr = ioremap(base, len); if (!dev->base_addr) { dev_dbg(dev->dev, "can't map memory\n"); ret = -EFAULT; diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 51efee21915f..1fd1b9186e46 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -3659,7 +3659,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) * 8051 code into the chip, e.g. to turn on PCI PM. */ - base = ioremap_nocache(resource, len); + base = ioremap(resource, len); if (base == NULL) { ep_dbg(dev, "can't map memory\n"); retval = -EFAULT; diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index a2b610dbedfc..2d462fbbe0a6 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -107,7 +107,7 @@ static int usb_hcd_msp_map_regs(struct mspusb_device *dev) if (!request_mem_region(res->start, res_len, "mab regs")) return -EBUSY; - dev->mab_regs = ioremap_nocache(res->start, res_len); + dev->mab_regs = ioremap(res->start, res_len); if (dev->mab_regs == NULL) { retval = -ENOMEM; goto err1; @@ -124,7 +124,7 @@ static int usb_hcd_msp_map_regs(struct mspusb_device *dev) retval = -EBUSY; goto err2; } - dev->usbid_regs = ioremap_nocache(res->start, res_len); + dev->usbid_regs = ioremap(res->start, res_len); if (dev->usbid_regs == NULL) { retval = -ENOMEM; goto err3; @@ -178,7 +178,7 @@ int usb_hcd_msp_probe(const struct hc_driver *driver, retval = -EBUSY; goto err1; } - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { pr_debug("ioremap failed"); retval = -ENOMEM; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 6c7f0a876b96..beb2efa71341 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -1150,7 +1150,7 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) if (!mmio_resource_enabled(pdev, 0)) return; - base = ioremap_nocache(pci_resource_start(pdev, 0), len); + base = ioremap(pci_resource_start(pdev, 0), len); if (base == NULL) return; diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index 07cc82ff327c..ccd30f835888 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -50,7 +50,7 @@ static int isp1761_pci_init(struct pci_dev *dev) } /* map available memory */ - iobase = ioremap_nocache(mem_start, mem_length); + iobase = ioremap(mem_start, mem_length); if (!iobase) { printk(KERN_ERR "Error ioremap failed\n"); release_mem_region(mem_start, mem_length); @@ -101,7 +101,7 @@ static int isp1761_pci_init(struct pci_dev *dev) return -EBUSY; } - iobase = ioremap_nocache(mem_start, mem_length); + iobase = ioremap(mem_start, mem_length); if (!iobase) { printk(KERN_ERR "ioremap #1\n"); release_mem_region(mem_start, mem_length); diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c index 409851306e99..80d6559bbcb2 100644 --- a/drivers/usb/roles/intel-xhci-usb-role-switch.c +++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c @@ -161,7 +161,7 @@ static int intel_xhci_usb_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -EINVAL; - data->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); + data->base = devm_ioremap(dev, res->start, resource_size(res)); if (!data->base) return -ENOMEM; diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 3f1786170098..9fc4f338e870 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -127,7 +127,7 @@ static int ucsi_acpi_probe(struct platform_device *pdev) return -ENODEV; } - /* This will make sure we can use ioremap_nocache() */ + /* This will make sure we can use ioremap() */ status = acpi_release_memory(ACPI_HANDLE(&pdev->dev), res, 1); if (ACPI_FAILURE(status)) return -ENOMEM; diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 0120d8324a40..a87992892a9f 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -230,7 +230,7 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf, switch ((u32)pos) { case 0xa0000 ... 0xbffff: count = min(count, (size_t)(0xc0000 - pos)); - iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1); + iomem = ioremap(0xa0000, 0xbffff - 0xa0000 + 1); off = pos - 0xa0000; rsrc = VGA_RSRC_LEGACY_MEM; is_ioport = false; diff --git a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c index 2d2babe21b2f..40d4fb9276ba 100644 --- a/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c +++ b/drivers/vfio/platform/reset/vfio_platform_amdxgbe.c @@ -54,13 +54,13 @@ static int vfio_platform_amdxgbe_reset(struct vfio_platform_device *vdev) if (!xgmac_regs->ioaddr) { xgmac_regs->ioaddr = - ioremap_nocache(xgmac_regs->addr, xgmac_regs->size); + ioremap(xgmac_regs->addr, xgmac_regs->size); if (!xgmac_regs->ioaddr) return -ENOMEM; } if (!xpcs_regs->ioaddr) { xpcs_regs->ioaddr = - ioremap_nocache(xpcs_regs->addr, xpcs_regs->size); + ioremap(xpcs_regs->addr, xpcs_regs->size); if (!xpcs_regs->ioaddr) return -ENOMEM; } diff --git a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c index 16165a62b86d..96064ef8f629 100644 --- a/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c +++ b/drivers/vfio/platform/reset/vfio_platform_bcmflexrm.c @@ -82,7 +82,7 @@ static int vfio_platform_bcmflexrm_reset(struct vfio_platform_device *vdev) /* Map FlexRM ring registers if not mapped */ if (!reg->ioaddr) { - reg->ioaddr = ioremap_nocache(reg->addr, reg->size); + reg->ioaddr = ioremap(reg->addr, reg->size); if (!reg->ioaddr) return -ENOMEM; } diff --git a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c index f67bab547501..09a9453b75c5 100644 --- a/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c +++ b/drivers/vfio/platform/reset/vfio_platform_calxedaxgmac.c @@ -52,7 +52,7 @@ static int vfio_platform_calxedaxgmac_reset(struct vfio_platform_device *vdev) if (!reg->ioaddr) { reg->ioaddr = - ioremap_nocache(reg->addr, reg->size); + ioremap(reg->addr, reg->size); if (!reg->ioaddr) return -ENOMEM; } diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index e8f2bdbe0542..c0771a9567fb 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c @@ -409,7 +409,7 @@ static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg, if (!reg->ioaddr) { reg->ioaddr = - ioremap_nocache(reg->addr, reg->size); + ioremap(reg->addr, reg->size); if (!reg->ioaddr) return -ENOMEM; @@ -486,7 +486,7 @@ static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg, if (!reg->ioaddr) { reg->ioaddr = - ioremap_nocache(reg->addr, reg->size); + ioremap(reg->addr, reg->size); if (!reg->ioaddr) return -ENOMEM; diff --git a/drivers/video/fbdev/carminefb.c b/drivers/video/fbdev/carminefb.c index 9f3be0258623..27ba2ed4138a 100644 --- a/drivers/video/fbdev/carminefb.c +++ b/drivers/video/fbdev/carminefb.c @@ -633,7 +633,7 @@ static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent) ret = -EBUSY; goto err_free_hw; } - hw->v_regs = ioremap_nocache(carminefb_fix.mmio_start, + hw->v_regs = ioremap(carminefb_fix.mmio_start, carminefb_fix.mmio_len); if (!hw->v_regs) { printk(KERN_ERR "carminefb: Can't remap %s register.\n", @@ -664,7 +664,7 @@ static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent) goto err_unmap_vregs; } - hw->screen_mem = ioremap_nocache(carminefb_fix.smem_start, + hw->screen_mem = ioremap(carminefb_fix.smem_start, carminefb_fix.smem_len); if (!hw->screen_mem) { printk(KERN_ERR "carmine: Can't ioremap smem area.\n"); diff --git a/drivers/video/fbdev/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c index d18f7b31932c..aa7583d963ac 100644 --- a/drivers/video/fbdev/i810/i810_main.c +++ b/drivers/video/fbdev/i810/i810_main.c @@ -1883,7 +1883,7 @@ static int i810_allocate_pci_resource(struct i810fb_par *par, } par->res_flags |= MMIO_REQ; - par->mmio_start_virtual = ioremap_nocache(par->mmio_start_phys, + par->mmio_start_virtual = ioremap(par->mmio_start_phys, MMIO_SIZE); if (!par->mmio_start_virtual) { printk("i810fb_init: cannot remap mmio region\n"); diff --git a/drivers/video/fbdev/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c index a76c61512c60..a09fc2eaa40d 100644 --- a/drivers/video/fbdev/intelfb/intelfbdrv.c +++ b/drivers/video/fbdev/intelfb/intelfbdrv.c @@ -654,7 +654,7 @@ static int intelfb_pci_register(struct pci_dev *pdev, } dinfo->mmio_base = - (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys, + (u8 __iomem *)ioremap(dinfo->mmio_base_phys, INTEL_REG_SIZE); if (!dinfo->mmio_base) { ERR_MSG("Cannot remap MMIO region.\n"); diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c index a7bd9f25911b..a8660926924b 100644 --- a/drivers/video/fbdev/kyro/fbdev.c +++ b/drivers/video/fbdev/kyro/fbdev.c @@ -683,7 +683,7 @@ static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) kyro_fix.mmio_len = pci_resource_len(pdev, 1); currentpar->regbase = deviceInfo.pSTGReg = - ioremap_nocache(kyro_fix.mmio_start, kyro_fix.mmio_len); + ioremap(kyro_fix.mmio_start, kyro_fix.mmio_len); if (!currentpar->regbase) goto out_free_fb; diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c index 1a555f70923a..36cc718b96ae 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.c +++ b/drivers/video/fbdev/matrox/matroxfb_base.c @@ -1710,7 +1710,7 @@ static int initMatrox2(struct matrox_fb_info *minfo, struct board *b) memsize = mem; err = -ENOMEM; - minfo->mmio.vbase.vaddr = ioremap_nocache(ctrlptr_phys, 16384); + minfo->mmio.vbase.vaddr = ioremap(ctrlptr_phys, 16384); if (!minfo->mmio.vbase.vaddr) { printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys); goto failVideoMR; diff --git a/drivers/video/fbdev/mbx/mbxfb.c b/drivers/video/fbdev/mbx/mbxfb.c index 50935252b50b..3de4b3ed990a 100644 --- a/drivers/video/fbdev/mbx/mbxfb.c +++ b/drivers/video/fbdev/mbx/mbxfb.c @@ -938,7 +938,7 @@ static int mbxfb_probe(struct platform_device *dev) } mfbi->reg_phys_addr = mfbi->reg_res->start; - mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev, + mfbi->reg_virt_addr = devm_ioremap(&dev->dev, mfbi->reg_phys_addr, res_size(mfbi->reg_req)); if (!mfbi->reg_virt_addr) { @@ -948,7 +948,7 @@ static int mbxfb_probe(struct platform_device *dev) } virt_base_2700 = mfbi->reg_virt_addr; - mfbi->fb_virt_addr = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr, + mfbi->fb_virt_addr = devm_ioremap(&dev->dev, mfbi->fb_phys_addr, res_size(mfbi->fb_req)); if (!mfbi->fb_virt_addr) { dev_err(&dev->dev, "failed to ioremap frame buffer\n"); diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c index 17174cd7a5bb..974e4c28b08b 100644 --- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c +++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c @@ -485,7 +485,7 @@ static int mmphw_probe(struct platform_device *pdev) goto failed; } - ctrl->reg_base = devm_ioremap_nocache(ctrl->dev, + ctrl->reg_base = devm_ioremap(ctrl->dev, res->start, resource_size(res)); if (ctrl->reg_base == NULL) { dev_err(ctrl->dev, "%s: res %pR map failed\n", __func__, res); diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c index 1dcf02e12af4..7cc1216b1389 100644 --- a/drivers/video/fbdev/pm2fb.c +++ b/drivers/video/fbdev/pm2fb.c @@ -1563,7 +1563,7 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_exit_neither; } default_par->v_regs = - ioremap_nocache(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len); + ioremap(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len); if (!default_par->v_regs) { printk(KERN_WARNING "pm2fb: Can't remap %s register area.\n", pm2fb_fix.id); diff --git a/drivers/video/fbdev/pm3fb.c b/drivers/video/fbdev/pm3fb.c index 6130aa56a1e9..2fa46607e0fc 100644 --- a/drivers/video/fbdev/pm3fb.c +++ b/drivers/video/fbdev/pm3fb.c @@ -1236,7 +1236,7 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par) return 0; } screen_mem = - ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len); + ioremap(pm3fb_fix.smem_start, pm3fb_fix.smem_len); if (!screen_mem) { printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n"); release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len); @@ -1347,7 +1347,7 @@ static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent) goto err_exit_neither; } par->v_regs = - ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); + ioremap(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len); if (!par->v_regs) { printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n", pm3fb_fix.id); diff --git a/drivers/video/fbdev/pmag-aa-fb.c b/drivers/video/fbdev/pmag-aa-fb.c index d1e78ce3a9c2..d5bf185fc376 100644 --- a/drivers/video/fbdev/pmag-aa-fb.c +++ b/drivers/video/fbdev/pmag-aa-fb.c @@ -188,7 +188,7 @@ static int pmagaafb_probe(struct device *dev) /* MMIO mapping setup. */ info->fix.mmio_start = start + PMAG_AA_BT455_OFFSET; - par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + par->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; @@ -199,7 +199,7 @@ static int pmagaafb_probe(struct device *dev) /* Frame buffer mapping setup. */ info->fix.smem_start = start + PMAG_AA_ONBOARD_FBMEM_OFFSET; - info->screen_base = ioremap_nocache(info->fix.smem_start, + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); diff --git a/drivers/video/fbdev/pmag-ba-fb.c b/drivers/video/fbdev/pmag-ba-fb.c index 56b912bb28de..2ddcdf7919a2 100644 --- a/drivers/video/fbdev/pmag-ba-fb.c +++ b/drivers/video/fbdev/pmag-ba-fb.c @@ -180,7 +180,7 @@ static int pmagbafb_probe(struct device *dev) /* MMIO mapping setup. */ info->fix.mmio_start = start; - par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + par->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; @@ -190,7 +190,7 @@ static int pmagbafb_probe(struct device *dev) /* Frame buffer mapping setup. */ info->fix.smem_start = start + PMAG_BA_FBMEM; - info->screen_base = ioremap_nocache(info->fix.smem_start, + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); diff --git a/drivers/video/fbdev/pmagb-b-fb.c b/drivers/video/fbdev/pmagb-b-fb.c index 2822b2225924..90d2b04feb42 100644 --- a/drivers/video/fbdev/pmagb-b-fb.c +++ b/drivers/video/fbdev/pmagb-b-fb.c @@ -287,7 +287,7 @@ static int pmagbbfb_probe(struct device *dev) /* MMIO mapping setup. */ info->fix.mmio_start = start; - par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + par->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; @@ -298,7 +298,7 @@ static int pmagbbfb_probe(struct device *dev) /* Frame buffer mapping setup. */ info->fix.smem_start = start + PMAGB_B_FBMEM; - par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); + par->smem = ioremap(info->fix.smem_start, info->fix.smem_len); if (!par->smem) { printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); err = -ENOMEM; diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c index 0a3b2b7c7891..c680b3e651cb 100644 --- a/drivers/video/fbdev/pvr2fb.c +++ b/drivers/video/fbdev/pvr2fb.c @@ -770,7 +770,7 @@ static int __maybe_unused pvr2fb_common_init(void) struct pvr2fb_par *par = currentpar; unsigned long modememused, rev; - fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start, + fb_info->screen_base = ioremap(pvr2_fix.smem_start, pvr2_fix.smem_len); if (!fb_info->screen_base) { @@ -778,7 +778,7 @@ static int __maybe_unused pvr2fb_common_init(void) goto out_err; } - par->mmio_base = ioremap_nocache(pvr2_fix.mmio_start, + par->mmio_base = ioremap(pvr2_fix.mmio_start, pvr2_fix.mmio_len); if (!par->mmio_base) { printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n"); diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c index 1410f476e135..5615054a0cad 100644 --- a/drivers/video/fbdev/pxa168fb.c +++ b/drivers/video/fbdev/pxa168fb.c @@ -665,7 +665,7 @@ static int pxa168fb_probe(struct platform_device *pdev) /* * Map LCD controller registers. */ - fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start, + fbi->reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (fbi->reg_base == NULL) { ret = -ENOMEM; diff --git a/drivers/video/fbdev/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c index e04efb567b5c..8048499e398d 100644 --- a/drivers/video/fbdev/s1d13xxxfb.c +++ b/drivers/video/fbdev/s1d13xxxfb.c @@ -809,7 +809,7 @@ static int s1d13xxxfb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, info); default_par = info->par; - default_par->regs = ioremap_nocache(pdev->resource[1].start, + default_par->regs = ioremap(pdev->resource[1].start, pdev->resource[1].end - pdev->resource[1].start +1); if (!default_par->regs) { printk(KERN_ERR PFX "unable to map registers\n"); @@ -818,7 +818,7 @@ static int s1d13xxxfb_probe(struct platform_device *pdev) } info->pseudo_palette = default_par->pseudo_palette; - info->screen_base = ioremap_nocache(pdev->resource[0].start, + info->screen_base = ioremap(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start +1); if (!info->screen_base) { diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c index ab8fe838c776..f72b03594719 100644 --- a/drivers/video/fbdev/sh7760fb.c +++ b/drivers/video/fbdev/sh7760fb.c @@ -463,7 +463,7 @@ static int sh7760fb_probe(struct platform_device *pdev) goto out_fb; } - par->base = ioremap_nocache(res->start, resource_size(res)); + par->base = ioremap(res->start, resource_size(res)); if (!par->base) { dev_err(&pdev->dev, "cannot remap\n"); ret = -ENODEV; diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index c249763dbf0b..54ee7e02a244 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c @@ -2588,7 +2588,7 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev) if (num_channels == 2) priv->forced_fourcc = pdata->ch[0].fourcc; - priv->base = ioremap_nocache(res->start, resource_size(res)); + priv->base = ioremap(res->start, resource_size(res)); if (!priv->base) { error = -ENOMEM; goto err1; diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c index 4e22ae383c87..1f171a527174 100644 --- a/drivers/video/fbdev/sstfb.c +++ b/drivers/video/fbdev/sstfb.c @@ -1363,14 +1363,14 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto fail_fb_mem; } - par->mmio_vbase = ioremap_nocache(fix->mmio_start, + par->mmio_vbase = ioremap(fix->mmio_start, fix->mmio_len); if (!par->mmio_vbase) { printk(KERN_ERR "sstfb: cannot remap register area %#lx\n", fix->mmio_start); goto fail_mmio_remap; } - info->screen_base = ioremap_nocache(fix->smem_start, 0x400000); + info->screen_base = ioremap(fix->smem_start, 0x400000); if (!info->screen_base) { printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n", fix->smem_start); diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 9e88e3f594c2..46709443a82f 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -1198,7 +1198,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) case S9000_ID_TOMCAT: /* Dual CRX, behaves else like a CRX */ /* FIXME: TomCat supports two heads: * fb.iobase = REGION_BASE(fb_info,3); - * fb.screen_base = ioremap_nocache(REGION_BASE(fb_info,2),xxx); + * fb.screen_base = ioremap(REGION_BASE(fb_info,2),xxx); * for now we only support the left one ! */ xres = fb->ngle_rom.x_size_visible; yres = fb->ngle_rom.y_size_visible; @@ -1291,7 +1291,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) strcpy(fix->id, "stifb"); info->fbops = &stifb_ops; - info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); + info->screen_base = ioremap(REGION_BASE(fb,1), fix->smem_len); if (!info->screen_base) { printk(KERN_ERR "stifb: failed to map memory\n"); goto out_err0; diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c index fdbb1ea66e6c..0337d1a1a70b 100644 --- a/drivers/video/fbdev/tdfxfb.c +++ b/drivers/video/fbdev/tdfxfb.c @@ -1417,7 +1417,7 @@ static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) } default_par->regbase_virt = - ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); + ioremap(info->fix.mmio_start, info->fix.mmio_len); if (!default_par->regbase_virt) { printk(KERN_ERR "fb: Can't remap %s register area.\n", info->fix.id); diff --git a/drivers/video/fbdev/tgafb.c b/drivers/video/fbdev/tgafb.c index 286b2371c7dd..1966f1d70899 100644 --- a/drivers/video/fbdev/tgafb.c +++ b/drivers/video/fbdev/tgafb.c @@ -1438,7 +1438,7 @@ static int tgafb_register(struct device *dev) } /* Map the framebuffer. */ - mem_base = ioremap_nocache(bar0_start, bar0_len); + mem_base = ioremap(bar0_start, bar0_len); if (!mem_base) { printk(KERN_ERR "tgafb: Cannot map MMIO\n"); goto err1; diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c index da74bf6c5996..91b2f6ca2607 100644 --- a/drivers/video/fbdev/tridentfb.c +++ b/drivers/video/fbdev/tridentfb.c @@ -1556,7 +1556,7 @@ static int trident_pci_probe(struct pci_dev *dev, return -1; } - default_par->io_virt = ioremap_nocache(tridentfb_fix.mmio_start, + default_par->io_virt = ioremap(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); if (!default_par->io_virt) { @@ -1579,7 +1579,7 @@ static int trident_pci_probe(struct pci_dev *dev, goto out_unmap1; } - info->screen_base = ioremap_nocache(tridentfb_fix.smem_start, + info->screen_base = ioremap(tridentfb_fix.smem_start, tridentfb_fix.smem_len); if (!info->screen_base) { diff --git a/drivers/video/fbdev/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c index e04fde9c1fcd..97a59b5a4570 100644 --- a/drivers/video/fbdev/valkyriefb.c +++ b/drivers/video/fbdev/valkyriefb.c @@ -356,7 +356,7 @@ int __init valkyriefb_init(void) p->total_vram = 0x100000; p->frame_buffer_phys = frame_buffer_phys; #ifdef CONFIG_MAC - p->frame_buffer = ioremap_nocache(frame_buffer_phys, p->total_vram); + p->frame_buffer = ioremap(frame_buffer_phys, p->total_vram); #else p->frame_buffer = ioremap_wt(frame_buffer_phys, p->total_vram); #endif diff --git a/drivers/video/fbdev/vermilion/cr_pll.c b/drivers/video/fbdev/vermilion/cr_pll.c index c1e3738e6789..79d42b23d850 100644 --- a/drivers/video/fbdev/vermilion/cr_pll.c +++ b/drivers/video/fbdev/vermilion/cr_pll.c @@ -159,7 +159,7 @@ static int __init cr_pll_init(void) pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR, &mch_bar); mch_regs_base = - ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE); + ioremap(mch_bar, CRVML_MCHMAP_SIZE); if (!mch_regs_base) { printk(KERN_ERR "Carillo Ranch MCH device was not enabled.\n"); diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c index 498038a964ee..ff61605b8764 100644 --- a/drivers/video/fbdev/vermilion/vermilion.c +++ b/drivers/video/fbdev/vermilion/vermilion.c @@ -317,7 +317,7 @@ static int vmlfb_enable_mmio(struct vml_par *par) ": Could not claim display controller MMIO.\n"); return -EBUSY; } - par->vdc_mem = ioremap_nocache(par->vdc_mem_base, par->vdc_mem_size); + par->vdc_mem = ioremap(par->vdc_mem_base, par->vdc_mem_size); if (par->vdc_mem == NULL) { printk(KERN_ERR MODULE_NAME ": Could not map display controller MMIO.\n"); @@ -332,7 +332,7 @@ static int vmlfb_enable_mmio(struct vml_par *par) err = -EBUSY; goto out_err_1; } - par->gpu_mem = ioremap_nocache(par->gpu_mem_base, par->gpu_mem_size); + par->gpu_mem = ioremap(par->gpu_mem_base, par->gpu_mem_size); if (par->gpu_mem == NULL) { printk(KERN_ERR MODULE_NAME ": Could not map GPU MMIO.\n"); err = -ENOMEM; diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c index ffa2ca2d3f5e..703ddee9a244 100644 --- a/drivers/video/fbdev/via/via-core.c +++ b/drivers/video/fbdev/via/via-core.c @@ -442,7 +442,7 @@ static int via_pci_setup_mmio(struct viafb_dev *vdev) */ vdev->engine_start = pci_resource_start(vdev->pdev, 1); vdev->engine_len = pci_resource_len(vdev->pdev, 1); - vdev->engine_mmio = ioremap_nocache(vdev->engine_start, + vdev->engine_mmio = ioremap(vdev->engine_start, vdev->engine_len); if (vdev->engine_mmio == NULL) dev_err(&vdev->pdev->dev, diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c index 3be07807edcd..0796b1d90981 100644 --- a/drivers/video/fbdev/w100fb.c +++ b/drivers/video/fbdev/w100fb.c @@ -648,12 +648,12 @@ int w100fb_probe(struct platform_device *pdev) return -EINVAL; /* Remap the chip base address */ - remapped_base = ioremap_nocache(mem->start+W100_CFG_BASE, W100_CFG_LEN); + remapped_base = ioremap(mem->start+W100_CFG_BASE, W100_CFG_LEN); if (remapped_base == NULL) goto out; /* Map the register space */ - remapped_regs = ioremap_nocache(mem->start+W100_REG_BASE, W100_REG_LEN); + remapped_regs = ioremap(mem->start+W100_REG_BASE, W100_REG_LEN); if (remapped_regs == NULL) goto out; @@ -672,7 +672,7 @@ int w100fb_probe(struct platform_device *pdev) printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE); /* Remap the framebuffer */ - remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE); + remapped_fbuf = ioremap(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE); if (remapped_fbuf == NULL) goto out; diff --git a/drivers/vme/boards/vme_vmivme7805.c b/drivers/vme/boards/vme_vmivme7805.c index 1b6e42e5e8fd..51e056bae943 100644 --- a/drivers/vme/boards/vme_vmivme7805.c +++ b/drivers/vme/boards/vme_vmivme7805.c @@ -55,7 +55,7 @@ static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* Map registers in BAR 0 */ - vmic_base = ioremap_nocache(pci_resource_start(pdev, 0), 16); + vmic_base = ioremap(pci_resource_start(pdev, 0), 16); if (!vmic_base) { dev_err(&pdev->dev, "Unable to remap CRG region\n"); retval = -EIO; diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index 1edb8a5de873..ea938dc29c5e 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c @@ -554,7 +554,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image, goto err_resource; } - image->kern_base = ioremap_nocache( + image->kern_base = ioremap( image->bus_resource.start, size); if (!image->kern_base) { dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); @@ -1638,7 +1638,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* map registers in BAR 0 */ - ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0), + ca91cx42_device->base = ioremap(pci_resource_start(pdev, 0), 4096); if (!ca91cx42_device->base) { dev_err(&pdev->dev, "Unable to remap CRG region\n"); diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 7e079d39bd76..50ae26977a02 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -770,7 +770,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, goto err_resource; } - image->kern_base = ioremap_nocache( + image->kern_base = ioremap( image->bus_resource.start, size); if (!image->kern_base) { dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); @@ -2317,7 +2317,7 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* map registers in BAR 0 */ - tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0), + tsi148_device->base = ioremap(pci_resource_start(pdev, 0), 4096); if (!tsi148_device->base) { dev_err(&pdev->dev, "Unable to remap CRG region\n"); diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c index 3110791a2f1c..ee716c715710 100644 --- a/drivers/w1/masters/matrox_w1.c +++ b/drivers/w1/masters/matrox_w1.c @@ -139,7 +139,7 @@ static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent dev->phys_addr = pci_resource_start(pdev, 1); - dev->virt_addr = ioremap_nocache(dev->phys_addr, 16384); + dev->virt_addr = ioremap(dev->phys_addr, 16384); if (!dev->virt_addr) { dev_err(&pdev->dev, "%s: failed to ioremap(0x%lx, %d).\n", __func__, dev->phys_addr, 16384); diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c index 8a043b52aa2f..7cdb25363ea0 100644 --- a/drivers/watchdog/bcm63xx_wdt.c +++ b/drivers/watchdog/bcm63xx_wdt.c @@ -246,7 +246,7 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev) return -ENODEV; } - bcm63xx_wdt_device.regs = devm_ioremap_nocache(&pdev->dev, r->start, + bcm63xx_wdt_device.regs = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!bcm63xx_wdt_device.regs) { dev_err(&pdev->dev, "failed to remap I/O resources\n"); diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 6ad5bf3451ec..804e35940983 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -463,7 +463,7 @@ static int __init intel_scu_watchdog_init(void) return -ENODEV; } - tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr, + tmp_addr = ioremap(watchdog_device.timer_tbl_ptr->phys_addr, 20); if (tmp_addr == NULL) { diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 1dfede0abf18..aee3c2efd565 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -26,7 +26,7 @@ #include /* For platform_driver framework */ #include /* For spin_lock/spin_unlock/... */ #include /* For copy_to_user/put_user/... */ -#include /* For devm_ioremap_nocache */ +#include /* For devm_ioremap */ #include /* For the Watchdog registers */ @@ -267,7 +267,7 @@ static int rc32434_wdt_probe(struct platform_device *pdev) return -ENODEV; } - wdt_reg = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r)); + wdt_reg = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!wdt_reg) { pr_err("failed to remap I/O resources\n"); return -ENXIO; diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 325fc98cc9ff..d39ac997dda8 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -960,10 +960,6 @@ static inline void __iomem *ioremap(phys_addr_t addr, size_t size) } #endif /* !CONFIG_MMU || CONFIG_GENERIC_IOREMAP */ -#ifndef ioremap_nocache -#define ioremap_nocache ioremap -#endif - #ifndef ioremap_wc #define ioremap_wc ioremap #endif diff --git a/include/asm-generic/iomap.h b/include/asm-generic/iomap.h index a008f504a2d0..9d28a5e82f73 100644 --- a/include/asm-generic/iomap.h +++ b/include/asm-generic/iomap.h @@ -94,11 +94,11 @@ extern void ioport_unmap(void __iomem *); #endif #ifndef ARCH_HAS_IOREMAP_WC -#define ioremap_wc ioremap_nocache +#define ioremap_wc ioremap #endif #ifndef ARCH_HAS_IOREMAP_WT -#define ioremap_wt ioremap_nocache +#define ioremap_wt ioremap #endif #ifdef CONFIG_PCI diff --git a/include/linux/io.h b/include/linux/io.h index a59834bc0a11..b1c44bb4b2d7 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -66,8 +66,6 @@ void __iomem *devm_ioremap(struct device *dev, resource_size_t offset, resource_size_t size); void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset, resource_size_t size); -void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, - resource_size_t size); void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset, resource_size_t size); void devm_iounmap(struct device *dev, void __iomem *addr); @@ -87,7 +85,7 @@ void *__devm_memremap_pages(struct device *dev, struct resource *res); * Posting") mandate non-posted configuration transactions. There is * no ioremap API in the kernel that can guarantee non-posted write * semantics across arches so provide a default implementation for - * mapping PCI config space that defaults to ioremap_nocache(); arches + * mapping PCI config space that defaults to ioremap(); arches * should override it if they have memory mapping implementations that * guarantee non-posted writes semantics to make the memory mapping * compliant with the PCI specification. @@ -97,7 +95,7 @@ void *__devm_memremap_pages(struct device *dev, struct resource *res); static inline void __iomem *pci_remap_cfgspace(phys_addr_t offset, size_t size) { - return ioremap_nocache(offset, size); + return ioremap(offset, size); } #endif #endif diff --git a/lib/devres.c b/lib/devres.c index f56070cf970b..6ef51f159c54 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -8,7 +8,6 @@ enum devm_ioremap_type { DEVM_IOREMAP = 0, - DEVM_IOREMAP_NC, DEVM_IOREMAP_UC, DEVM_IOREMAP_WC, }; @@ -37,9 +36,6 @@ static void __iomem *__devm_ioremap(struct device *dev, resource_size_t offset, case DEVM_IOREMAP: addr = ioremap(offset, size); break; - case DEVM_IOREMAP_NC: - addr = ioremap_nocache(offset, size); - break; case DEVM_IOREMAP_UC: addr = ioremap_uc(offset, size); break; @@ -87,22 +83,6 @@ void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset, } EXPORT_SYMBOL_GPL(devm_ioremap_uc); -/** - * devm_ioremap_nocache - Managed ioremap_nocache() - * @dev: Generic device to remap IO address for - * @offset: Resource address to map - * @size: Size of map - * - * Managed ioremap_nocache(). Map is automatically unmapped on driver - * detach. - */ -void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset, - resource_size_t size) -{ - return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_NC); -} -EXPORT_SYMBOL(devm_ioremap_nocache); - /** * devm_ioremap_wc - Managed ioremap_wc() * @dev: Generic device to remap IO address for diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci index 441799b5359b..9330d4294b74 100644 --- a/scripts/coccinelle/free/devm_free.cocci +++ b/scripts/coccinelle/free/devm_free.cocci @@ -51,8 +51,6 @@ expression x; x = devm_request_irq(...) | x = devm_ioremap(...) -| - x = devm_ioremap_nocache(...) | x = devm_ioport_map(...) ) @@ -84,8 +82,6 @@ position p; x = request_irq(...) | x = ioremap(...) -| - x = ioremap_nocache(...) | x = ioport_map(...) ) diff --git a/scripts/coccinelle/free/iounmap.cocci b/scripts/coccinelle/free/iounmap.cocci index 0e60e1113a1d..63b81d0c97b6 100644 --- a/scripts/coccinelle/free/iounmap.cocci +++ b/scripts/coccinelle/free/iounmap.cocci @@ -23,7 +23,7 @@ int ret; position p1,p2,p3; @@ -e = \(ioremap@p1\|ioremap_nocache@p1\)(...) +e = \(ioremap@p1\)(...) ... when != iounmap(e) if (<+...e...+>) S ... when any diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c index 70a6d1832698..db1295f840b7 100644 --- a/sound/drivers/ml403-ac97cr.c +++ b/sound/drivers/ml403-ac97cr.c @@ -1123,7 +1123,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev, PDEBUG(INIT_INFO, "Trying to reserve resources now ...\n"); resource = platform_get_resource(pfdev, IORESOURCE_MEM, 0); /* get "port" */ - ml403_ac97cr->port = ioremap_nocache(resource->start, + ml403_ac97cr->port = ioremap(resource->start, (resource->end) - (resource->start) + 1); if (ml403_ac97cr->port == NULL) { diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index e435ebd0ced4..f15fe597582c 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -551,7 +551,7 @@ static int snd_msnd_attach(struct snd_card *card) free_irq(chip->irq, chip); return -EBUSY; } - chip->mappedbase = ioremap_nocache(chip->base, 0x8000); + chip->mappedbase = ioremap(chip->base, 0x8000); if (!chip->mappedbase) { printk(KERN_ERR LOGNAME ": unable to map memory region 0x%lx-0x%lx\n", diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 6acc59c25379..0d1eced95f33 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -907,7 +907,7 @@ snd_harmony_create(struct snd_card *card, h->card = card; h->dev = padev; h->irq = -1; - h->iobase = ioremap_nocache(padev->hpa.start, HARMONY_SIZE); + h->iobase = ioremap(padev->hpa.start, HARMONY_SIZE); if (h->iobase == NULL) { printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n", (unsigned long)padev->hpa.start); diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c index 1cbfae856a2a..459c1691bb0c 100644 --- a/sound/pci/aw2/aw2-alsa.c +++ b/sound/pci/aw2/aw2-alsa.c @@ -271,7 +271,7 @@ static int snd_aw2_create(struct snd_card *card, } chip->iobase_phys = pci_resource_start(pci, 0); chip->iobase_virt = - ioremap_nocache(chip->iobase_phys, + ioremap(chip->iobase_phys, pci_resource_len(pci, 0)); if (chip->iobase_virt == NULL) { diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 102a62965ac1..1465d7a17f7f 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -3983,7 +3983,7 @@ int snd_cs46xx_create(struct snd_card *card, snd_cs46xx_free(chip); return -EBUSY; } - region->remap_addr = ioremap_nocache(region->base, region->size); + region->remap_addr = ioremap(region->base, region->size); if (region->remap_addr == NULL) { dev_err(chip->card->dev, "%s ioremap problem\n", region->name); diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 1465813bf7c6..dfd55419d667 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -1929,7 +1929,7 @@ static int snd_echo_create(struct snd_card *card, return -EBUSY; } chip->dsp_registers = (volatile u32 __iomem *) - ioremap_nocache(chip->dsp_registers_phys, sz); + ioremap(chip->dsp_registers_phys, sz); if (!chip->dsp_registers) { dev_err(chip->card->dev, "ioremap failed\n"); snd_echo_free(chip); diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 1201c9c95660..77c683d19fbf 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -1353,7 +1353,7 @@ snd_nm256_peek_for_sig(struct nm256 *chip) unsigned long pointer_found = chip->buffer_end - 0x1400; u32 sig; - temp = ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16); + temp = ioremap(chip->buffer_addr + chip->buffer_end - 0x400, 16); if (temp == NULL) { dev_err(chip->card->dev, "Unable to scan for card signature in video RAM\n"); @@ -1518,7 +1518,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, err = -EBUSY; goto __error; } - chip->cport = ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE); + chip->cport = ioremap(chip->cport_addr, NM_PORT2_SIZE); if (chip->cport == NULL) { dev_err(card->dev, "unable to map control port %lx\n", chip->cport_addr); @@ -1589,7 +1589,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, err = -EBUSY; goto __error; } - chip->buffer = ioremap_nocache(chip->buffer_addr, chip->buffer_size); + chip->buffer = ioremap(chip->buffer_addr, chip->buffer_size); if (chip->buffer == NULL) { err = -ENOMEM; dev_err(card->dev, "unable to map ring buffer at %lx\n", diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 58a4b8df25d4..4a238de5a77e 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1344,7 +1344,7 @@ static int snd_rme32_create(struct rme32 *rme32) return err; rme32->port = pci_resource_start(rme32->pci, 0); - rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE); + rme32->iobase = ioremap(rme32->port, RME32_IO_SIZE); if (!rme32->iobase) { dev_err(rme32->card->dev, "unable to remap memory region 0x%lx-0x%lx\n", diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 64ab55772eae..db6033074ace 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -1619,7 +1619,7 @@ snd_rme96_create(struct rme96 *rme96) return err; rme96->port = pci_resource_start(rme96->pci, 0); - rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE); + rme96->iobase = ioremap(rme96->port, RME96_IO_SIZE); if (!rme96->iobase) { dev_err(rme96->card->dev, "unable to remap memory region 0x%lx-0x%lx\n", diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index cd20af465d8e..dfb06546ff25 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -5220,7 +5220,7 @@ static int snd_hdsp_create(struct snd_card *card, if ((err = pci_request_regions(pci, "hdsp")) < 0) return err; hdsp->port = pci_resource_start(pci, 0); - if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) { + if ((hdsp->iobase = ioremap(hdsp->port, HDSP_IO_EXTENT)) == NULL) { dev_err(hdsp->card->dev, "unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1); return -EBUSY; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 75c06a7cc779..e2214ba4a38d 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6594,7 +6594,7 @@ static int snd_hdspm_create(struct snd_card *card, dev_dbg(card->dev, "grabbed memory region 0x%lx-0x%lx\n", hdspm->port, hdspm->port + io_extent - 1); - hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); + hdspm->iobase = ioremap(hdspm->port, io_extent); if (!hdspm->iobase) { dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", hdspm->port, hdspm->port + io_extent - 1); diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index ef5c2f8e17c7..bb9130747fbb 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -2466,7 +2466,7 @@ static int snd_rme9652_create(struct snd_card *card, if ((err = pci_request_regions(pci, "rme9652")) < 0) return err; rme9652->port = pci_resource_start(pci, 0); - rme9652->iobase = ioremap_nocache(rme9652->port, RME9652_IO_EXTENT); + rme9652->iobase = ioremap(rme9652->port, RME9652_IO_EXTENT); if (rme9652->iobase == NULL) { dev_err(card->dev, "unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1); diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index ef7dd290ae05..ce13dcde4c36 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -1334,7 +1334,7 @@ static int sis_chip_create(struct snd_card *card, } rc = -EIO; - sis->ioaddr = ioremap_nocache(pci_resource_start(pci, 1), 0x4000); + sis->ioaddr = ioremap(pci_resource_start(pci, 1), 0x4000); if (!sis->ioaddr) { dev_err(&pci->dev, "unable to remap MMIO, aborting\n"); goto error_out_cleanup; diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 125c11ed5064..d3907811f698 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -2373,7 +2373,7 @@ int snd_ymfpci_create(struct snd_card *card, chip->device_id = pci->device; chip->rev = pci->revision; chip->reg_area_phys = pci_resource_start(pci, 0); - chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); + chip->reg_area_virt = ioremap(chip->reg_area_phys, 0x8000); pci_set_master(pci); chip->src441_used = -1; diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index 0792c40e6cc1..d28302153d74 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c @@ -248,7 +248,7 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) pdev->name)) return -EBUSY; - ctx->mmio = devm_ioremap_nocache(&pdev->dev, iores->start, + ctx->mmio = devm_ioremap(&pdev->dev, iores->start, resource_size(iores)); if (!ctx->mmio) return -EBUSY; diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c index 46f2b447ec9a..7fd08fafa490 100644 --- a/sound/soc/au1x/i2sc.c +++ b/sound/soc/au1x/i2sc.c @@ -248,7 +248,7 @@ static int au1xi2s_drvprobe(struct platform_device *pdev) pdev->name)) return -EBUSY; - ctx->mmio = devm_ioremap_nocache(&pdev->dev, iores->start, + ctx->mmio = devm_ioremap(&pdev->dev, iores->start, resource_size(iores)); if (!ctx->mmio) return -EBUSY; diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index b728fb56ea4d..f3cfe83b9ac6 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -165,7 +165,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset; ctx->iram_end = ctx->iram_base + ctx->pdata->res_info->iram_size - 1; dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base); - ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base, + ctx->iram = devm_ioremap(ctx->dev, ctx->iram_base, ctx->pdata->res_info->iram_size); if (!ctx->iram) { dev_err(ctx->dev, "unable to map IRAM\n"); @@ -175,7 +175,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset; ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1; dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base); - ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base, + ctx->dram = devm_ioremap(ctx->dev, ctx->dram_base, ctx->pdata->res_info->dram_size); if (!ctx->dram) { dev_err(ctx->dev, "unable to map DRAM\n"); @@ -184,7 +184,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset; dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add); - ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add, + ctx->shim = devm_ioremap(ctx->dev, ctx->shim_phy_add, ctx->pdata->res_info->shim_size); if (!ctx->shim) { dev_err(ctx->dev, "unable to map SHIM\n"); @@ -197,7 +197,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) /* Get mailbox addr */ ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset; dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add); - ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add, + ctx->mailbox = devm_ioremap(ctx->dev, ctx->mailbox_add, ctx->pdata->res_info->mbox_size); if (!ctx->mailbox) { dev_err(ctx->dev, "unable to map mailbox\n"); @@ -216,7 +216,7 @@ static int sst_platform_get_resources(struct intel_sst_drv *ctx) ctx->ddr_base = rsrc->start; ctx->ddr_end = rsrc->end; dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base); - ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base, + ctx->ddr = devm_ioremap(ctx->dev, ctx->ddr_base, resource_size(rsrc)); if (!ctx->ddr) { dev_err(ctx->dev, "unable to map DDR\n"); diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index e384fdc8d60e..2ead52bdb8ec 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1955,7 +1955,7 @@ static int fsi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->base = devm_ioremap_nocache(&pdev->dev, + master->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!master->base) { dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index cd389d21219a..cf258dd13050 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1755,7 +1755,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) __func__, (unsigned int)res_mmio->start, (unsigned int)res_mmio->end); - card_ctx->mmio_start = ioremap_nocache(res_mmio->start, + card_ctx->mmio_start = ioremap(res_mmio->start, (size_t)(resource_size(res_mmio))); if (!card_ctx->mmio_start) { dev_err(&pdev->dev, "Could not get ioremap\n"); diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index 6aca8d5be159..dbebf05f5931 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild @@ -1,10 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 ldflags-y += --wrap=ioremap_wc ldflags-y += --wrap=memremap -ldflags-y += --wrap=devm_ioremap_nocache +ldflags-y += --wrap=devm_ioremap ldflags-y += --wrap=devm_memremap ldflags-y += --wrap=devm_memunmap -ldflags-y += --wrap=ioremap_nocache ldflags-y += --wrap=ioremap ldflags-y += --wrap=iounmap ldflags-y += --wrap=memunmap diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index 6271ac757a4b..03e40b3b0106 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c @@ -73,7 +73,7 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, return fallback_fn(offset, size); } -void __iomem *__wrap_devm_ioremap_nocache(struct device *dev, +void __iomem *__wrap_devm_ioremap(struct device *dev, resource_size_t offset, unsigned long size) { struct nfit_test_resource *nfit_res = get_nfit_res(offset); @@ -81,9 +81,9 @@ void __iomem *__wrap_devm_ioremap_nocache(struct device *dev, if (nfit_res) return (void __iomem *) nfit_res->buf + offset - nfit_res->res.start; - return devm_ioremap_nocache(dev, offset, size); + return devm_ioremap(dev, offset, size); } -EXPORT_SYMBOL(__wrap_devm_ioremap_nocache); +EXPORT_SYMBOL(__wrap_devm_ioremap); void *__wrap_devm_memremap(struct device *dev, resource_size_t offset, size_t size, unsigned long flags) @@ -187,12 +187,6 @@ void __wrap_devm_memunmap(struct device *dev, void *addr) } EXPORT_SYMBOL(__wrap_devm_memunmap); -void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size) -{ - return __nfit_test_ioremap(offset, size, ioremap_nocache); -} -EXPORT_SYMBOL(__wrap_ioremap_nocache); - void __iomem *__wrap_ioremap(resource_size_t offset, unsigned long size) { return __nfit_test_ioremap(offset, size, ioremap); diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h index 0bf5640f1f07..db3c07beb9d1 100644 --- a/tools/testing/nvdimm/test/nfit_test.h +++ b/tools/testing/nvdimm/test/nfit_test.h @@ -207,8 +207,6 @@ typedef struct nfit_test_resource *(*nfit_test_lookup_fn)(resource_size_t); typedef union acpi_object *(*nfit_test_evaluate_dsm_fn)(acpi_handle handle, const guid_t *guid, u64 rev, u64 func, union acpi_object *argv4); -void __iomem *__wrap_ioremap_nocache(resource_size_t offset, - unsigned long size); void __wrap_iounmap(volatile void __iomem *addr); void nfit_test_setup(nfit_test_lookup_fn lookup, nfit_test_evaluate_dsm_fn evaluate); -- cgit v1.2.3 From f6e1405f7a1698234e5143a806453d60f893c651 Mon Sep 17 00:00:00 2001 From: Jim Quinlan Date: Fri, 3 Jan 2020 11:04:28 -0800 Subject: dt-bindings: reset: Document BCM7216 RESCAL reset controller BCM7216 has a special purpose RESCAL reset controller for its SATA and PCIe0/1 instances. This is a simple reset controller with #reset-cells set to 0. Signed-off-by: Jim Quinlan [florian: Convert to YAML binding] Signed-off-by: Florian Fainelli Reviewed-by: Rob Herring Signed-off-by: Philipp Zabel --- .../reset/brcm,bcm7216-pcie-sata-rescal.yaml | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Documentation/devicetree/bindings/reset/brcm,bcm7216-pcie-sata-rescal.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm7216-pcie-sata-rescal.yaml b/Documentation/devicetree/bindings/reset/brcm,bcm7216-pcie-sata-rescal.yaml new file mode 100644 index 000000000000..411bd76f1b64 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/brcm,bcm7216-pcie-sata-rescal.yaml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2020 Broadcom +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/reset/brcm,bcm7216-pcie-sata-rescal.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: BCM7216 RESCAL reset controller + +description: This document describes the BCM7216 RESCAL reset controller which is responsible for controlling the reset of the SATA and PCIe0/1 instances on BCM7216. + +maintainers: + - Florian Fainelli + - Jim Quinlan + +properties: + compatible: + const: brcm,bcm7216-pcie-sata-rescal + + reg: + maxItems: 1 + + "#reset-cells": + const: 0 + +required: + - compatible + - reg + - "#reset-cells" + +examples: + - | + reset-controller@8b2c800 { + compatible = "brcm,bcm7216-pcie-sata-rescal"; + reg = <0x8b2c800 0x10>; + #reset-cells = <0>; + }; -- cgit v1.2.3 From a44c03b5879ca0da079ccb03b378d79299e2afd5 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Mon, 9 Dec 2019 10:19:59 +0000 Subject: dt-bindings: i2c: at91: cosmetic formatting of compatible list Format the list of compatibles with one compatible per line. Suggested-by: Peter Rosin Signed-off-by: Eugen Hristev Acked-by: Ludovic Desroches Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-at91.txt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/i2c-at91.txt b/Documentation/devicetree/bindings/i2c/i2c-at91.txt index 2210f4359c45..d35cd638d054 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-at91.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-at91.txt @@ -1,10 +1,16 @@ I2C for Atmel platforms Required properties : -- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c", - "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c", - "atmel,at91sam9x5-i2c", "atmel,sama5d4-i2c", "atmel,sama5d2-i2c" or - "microchip,sam9x60-i2c" +- compatible : Must be one of: + "atmel,at91rm9200-i2c", + "atmel,at91sam9261-i2c", + "atmel,at91sam9260-i2c", + "atmel,at91sam9g20-i2c", + "atmel,at91sam9g10-i2c", + "atmel,at91sam9x5-i2c", + "atmel,sama5d4-i2c", + "atmel,sama5d2-i2c", + "microchip,sam9x60-i2c". - reg: physical base address of the controller and length of memory mapped region. - interrupts: interrupt number to the cpu. -- cgit v1.2.3 From f4b5af78cb7e87983898b4de5a7e4c2b68ac653b Mon Sep 17 00:00:00 2001 From: "周琰杰 (Zhou Yanjie)" Date: Tue, 17 Dec 2019 16:14:09 +0800 Subject: dt-bindings: I2C: Add X1000 bindings. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the I2C bindings for the X1000 Soc from Ingenic. Signed-off-by: 周琰杰 (Zhou Yanjie) Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-jz4780.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/i2c/i2c-jz4780.txt b/Documentation/devicetree/bindings/i2c/i2c-jz4780.txt index 3738cfbf863f..d229eff5ca1b 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-jz4780.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-jz4780.txt @@ -1,7 +1,9 @@ * Ingenic JZ4780 I2C Bus controller Required properties: -- compatible: should be "ingenic,jz4780-i2c" +- compatible: should be one of the following: + - "ingenic,jz4780-i2c" for the JZ4780 + - "ingenic,x1000-i2c" for the X1000 - reg: Should contain the address & size of the I2C controller registers. - interrupts: Should specify the interrupt provided by parent. - clocks: Should contain a single clock specifier for the JZ4780 I2C clock. -- cgit v1.2.3 From ab91f72e018ad55805ef056a0af92a30ea45259e Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Mon, 6 Jan 2020 00:05:45 -0800 Subject: clk: qcom: gcc-msm8996: Fix parent for CLKREF clocks The CLKREF clocks are all fed by the clock signal on the CXO2 pad on the SoC. Update the definition of these clocks to allow this to be wired up to the appropriate clock source. Retain "xo" as the global named parent to make the change a nop in the event that DT doesn't carry the necessary clocks definition. Signed-off-by: Bjorn Andersson Link: https://lkml.kernel.org/r/20200106080546.3192125-2-bjorn.andersson@linaro.org Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gcc.yaml | 10 +++++++ drivers/clk/qcom/gcc-msm8996.c | 35 +++++++++++++++++----- 2 files changed, 38 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml index f2b5cd6fe0fe..8535ed93766b 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml @@ -47,6 +47,11 @@ properties: - description: Board XO source - description: Board active XO source - description: Sleep clock source + #qcom,gcc-msm8996 + - items: + - description: XO source + - description: Second XO source + - description: Sleep clock source #qcom,gcc-msm8998 - items: - description: Board XO source @@ -65,6 +70,11 @@ properties: - const: bi_tcxo - const: bi_tcxo_ao - const: sleep_clk + #qcom,gcc-msm8996 + - items: + - const: cxo + - const: cxo2 + - const: sleep_clk #qcom,gcc-msm8998 - items: - const: xo diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index d004cdaa0e39..3c3a7ff04562 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -3046,7 +3046,10 @@ static struct clk_branch gcc_usb3_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_usb3_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, @@ -3060,7 +3063,10 @@ static struct clk_branch gcc_hdmi_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_hdmi_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, @@ -3074,7 +3080,10 @@ static struct clk_branch gcc_edp_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_edp_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, @@ -3088,7 +3097,10 @@ static struct clk_branch gcc_ufs_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_ufs_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, @@ -3102,7 +3114,10 @@ static struct clk_branch gcc_pcie_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_pcie_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, @@ -3116,7 +3131,10 @@ static struct clk_branch gcc_rx2_usb2_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_rx2_usb2_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, @@ -3130,7 +3148,10 @@ static struct clk_branch gcc_rx1_usb2_clkref_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_rx1_usb2_clkref_clk", - .parent_names = (const char *[]){ "xo" }, + .parent_data = &(const struct clk_parent_data){ + .fw_name = "cxo2", + .name = "xo", + }, .num_parents = 1, .ops = &clk_branch2_ops, }, -- cgit v1.2.3 From 8b41fc4454e36fbfdbb23f940d023d4dece2de29 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 19 Dec 2019 17:33:29 +0900 Subject: kbuild: create modules.builtin without Makefile.modbuiltin or tristate.conf Commit bc081dd6e9f6 ("kbuild: generate modules.builtin") added infrastructure to generate modules.builtin, the list of all builtin modules. Basically, it works like this: - Kconfig generates include/config/tristate.conf, the list of tristate CONFIG options with a value in a capital letter. - scripts/Makefile.modbuiltin makes Kbuild descend into directories to collect the information of builtin modules. I am not a big fan of it because Kbuild ends up with traversing the source tree twice. I am not sure how perfectly it should work, but this approach cannot avoid false positives; even if the relevant CONFIG option is tristate, some Makefiles forces obj-m to obj-y. Some examples are: arch/powerpc/platforms/powermac/Makefile: obj-$(CONFIG_NVRAM:m=y) += nvram.o net/ipv6/Makefile: obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o net/netlabel/Makefile: obj-$(subst m,y,$(CONFIG_IPV6)) += netlabel_calipso.o Nobody has complained about (or noticed) it, so it is probably fine to have false positives in modules.builtin. This commit simplifies the implementation. Let's exploit the fact that every module has MODULE_LICENSE(). (modpost shows a warning if MODULE_LICENSE is missing. If so, 0-day bot would already have blocked such a module.) I added MODULE_FILE to . When the code is being compiled as builtin, it will be filled with the file path of the module, and collected into modules.builtin.info. Then, scripts/link-vmlinux.sh extracts the list of builtin modules out of it. This new approach fixes the false-positives above, but adds another type of false-positives; non-modular code may have MODULE_LICENSE() by mistake. This is not a big deal, it is just the code is always orphan. We can clean it up if we like. You can see cleanup examples by: $ git log --grep='make.* explicitly non-modular' To sum up, this commits deletes lots of code, but still produces almost equivalent results. Please note it does not increase the vmlinux size at all. As you can see in include/asm-generic/vmlinux.lds.h, the .modinfo section is discarded in the link stage. Signed-off-by: Masahiro Yamada --- Documentation/kbuild/kconfig.rst | 5 ---- Makefile | 21 ++++----------- include/linux/module.h | 12 ++++++++- scripts/Kbuild.include | 6 ----- scripts/Makefile.modbuiltin | 57 ---------------------------------------- scripts/kconfig/confdata.c | 45 ++----------------------------- scripts/link-vmlinux.sh | 4 +++ 7 files changed, 22 insertions(+), 128 deletions(-) delete mode 100644 scripts/Makefile.modbuiltin (limited to 'Documentation') diff --git a/Documentation/kbuild/kconfig.rst b/Documentation/kbuild/kconfig.rst index a9a855f894b3..dce6801d66c9 100644 --- a/Documentation/kbuild/kconfig.rst +++ b/Documentation/kbuild/kconfig.rst @@ -154,11 +154,6 @@ KCONFIG_AUTOCONFIG This environment variable can be set to specify the path & name of the "auto.conf" file. Its default value is "include/config/auto.conf". -KCONFIG_TRISTATE ----------------- -This environment variable can be set to specify the path & name of the -"tristate.conf" file. Its default value is "include/config/tristate.conf". - KCONFIG_AUTOHEADER ------------------ This environment variable can be set to specify the path & name of the diff --git a/Makefile b/Makefile index e4c2d0327d8c..4f01de6cd43c 100644 --- a/Makefile +++ b/Makefile @@ -674,7 +674,7 @@ $(KCONFIG_CONFIG): # # This exploits the 'multi-target pattern rule' trick. # The syncconfig should be executed only once to make all the targets. -%/auto.conf %/auto.conf.cmd %/tristate.conf: $(KCONFIG_CONFIG) +%/auto.conf %/auto.conf.cmd: $(KCONFIG_CONFIG) $(Q)$(MAKE) -f $(srctree)/Makefile syncconfig else # !may-sync-config # External modules and some install targets need include/generated/autoconf.h @@ -1278,24 +1278,13 @@ all: modules # using awk while concatenating to the final file. PHONY += modules -modules: $(if $(KBUILD_BUILTIN),vmlinux) modules.order modules.builtin +modules: $(if $(KBUILD_BUILTIN),vmlinux) modules.order $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh modules.order: descend $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@ -modbuiltin-dirs := $(addprefix _modbuiltin_, $(build-dirs)) - -modules.builtin: $(modbuiltin-dirs) - $(Q)$(AWK) '!x[$$0]++' $(addsuffix /$@, $(build-dirs)) > $@ - -PHONY += $(modbuiltin-dirs) -# tristate.conf is not included from this Makefile. Add it as a prerequisite -# here to make it self-healing in case somebody accidentally removes it. -$(modbuiltin-dirs): include/config/tristate.conf - $(Q)$(MAKE) $(modbuiltin)=$(patsubst _modbuiltin_%,%,$@) - # Target to prepare building external modules PHONY += modules_prepare modules_prepare: prepare @@ -1315,7 +1304,7 @@ _modinst_: ln -s $(CURDIR) $(MODLIB)/build ; \ fi @sed 's:^:kernel/:' modules.order > $(MODLIB)/modules.order - @sed 's:^:kernel/:' modules.builtin > $(MODLIB)/modules.builtin + @cp -f modules.builtin $(MODLIB)/ @cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst @@ -1357,7 +1346,7 @@ endif # CONFIG_MODULES # Directories & files removed with 'make clean' CLEAN_DIRS += include/ksym -CLEAN_FILES += modules.builtin.modinfo modules.nsdeps +CLEAN_FILES += modules.builtin modules.builtin.modinfo modules.nsdeps # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include/generated \ @@ -1712,7 +1701,7 @@ clean: $(clean-dirs) -o -name '*.lex.c' -o -name '*.tab.[ch]' \ -o -name '*.asn1.[ch]' \ -o -name '*.symtypes' -o -name 'modules.order' \ - -o -name modules.builtin -o -name '.tmp_*.o.*' \ + -o -name '.tmp_*.o.*' \ -o -name '*.c.[012]*.*' \ -o -name '*.ll' \ -o -name '*.gcno' \) -type f -print | xargs rm -f diff --git a/include/linux/module.h b/include/linux/module.h index bd165ba68617..6877b3b191d0 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -169,6 +169,16 @@ extern void cleanup_module(void); */ #define MODULE_SOFTDEP(_softdep) MODULE_INFO(softdep, _softdep) +/* + * MODULE_FILE is used for generating modules.builtin + * So, make it no-op when this is being built as a module + */ +#ifdef MODULE +#define MODULE_FILE +#else +#define MODULE_FILE MODULE_INFO(file, KBUILD_MODFILE); +#endif + /* * The following license idents are currently accepted as indicating free * software modules @@ -213,7 +223,7 @@ extern void cleanup_module(void); * 2. So the community can ignore bug reports including proprietary modules * 3. So vendors can do likewise based on their own policies */ -#define MODULE_LICENSE(_license) MODULE_INFO(license, _license) +#define MODULE_LICENSE(_license) MODULE_FILE MODULE_INFO(license, _license) /* * Author(s), use "Name " or just "Name", for multiple diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 88c144787e57..3da8321efb74 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -163,12 +163,6 @@ ld-ifversion = $(shell [ $(ld-version) $(1) $(2) ] && echo $(3) || echo $(4)) # $(Q)$(MAKE) $(build)=dir build := -f $(srctree)/scripts/Makefile.build obj -### -# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj= -# Usage: -# $(Q)$(MAKE) $(modbuiltin)=dir -modbuiltin := -f $(srctree)/scripts/Makefile.modbuiltin obj - ### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.dtbinst obj= # Usage: diff --git a/scripts/Makefile.modbuiltin b/scripts/Makefile.modbuiltin deleted file mode 100644 index 7d4711b88656..000000000000 --- a/scripts/Makefile.modbuiltin +++ /dev/null @@ -1,57 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# ========================================================================== -# Generating modules.builtin -# ========================================================================== - -src := $(obj) - -PHONY := __modbuiltin -__modbuiltin: - -include include/config/auto.conf -# tristate.conf sets tristate variables to uppercase 'Y' or 'M' -# That way, we get the list of built-in modules in obj-Y -include include/config/tristate.conf - -include scripts/Kbuild.include - -ifdef building_out_of_srctree -# Create output directory if not already present -_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) -endif - -# The filename Kbuild has precedence over Makefile -kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) -include $(kbuild-file) - -include scripts/Makefile.lib -__subdir-Y := $(patsubst %/,%,$(filter %/, $(obj-Y))) -subdir-Y += $(__subdir-Y) -subdir-ym := $(sort $(subdir-y) $(subdir-Y) $(subdir-m)) -subdir-ym := $(addprefix $(obj)/,$(subdir-ym)) -obj-Y := $(addprefix $(obj)/,$(obj-Y)) - -modbuiltin-subdirs := $(patsubst %,%/modules.builtin, $(subdir-ym)) -modbuiltin-mods := $(filter %.ko, $(obj-Y:.o=.ko)) -modbuiltin-target := $(obj)/modules.builtin - -__modbuiltin: $(modbuiltin-target) $(subdir-ym) - @: - -$(modbuiltin-target): $(subdir-ym) FORCE - $(Q)(for m in $(modbuiltin-mods); do echo $$m; done; \ - cat /dev/null $(modbuiltin-subdirs)) > $@ - -PHONY += FORCE - -FORCE: - -# Descending -# --------------------------------------------------------------------------- - -PHONY += $(subdir-ym) -$(subdir-ym): - $(Q)$(MAKE) $(modbuiltin)=$@ - -.PHONY: $(PHONY) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 3569d2dec37c..fb675bd9a809 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -710,25 +710,6 @@ static struct conf_printer header_printer_cb = .print_comment = header_print_comment, }; -/* - * Tristate printer - * - * This printer is used when generating the `include/config/tristate.conf' file. - */ -static void -tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) -{ - - if (sym->type == S_TRISTATE && *value != 'n') - fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); -} - -static struct conf_printer tristate_printer_cb = -{ - .print_symbol = tristate_print_symbol, - .print_comment = kconfig_print_comment, -}; - static void conf_write_symbol(FILE *fp, struct symbol *sym, struct conf_printer *printer, void *printer_arg) { @@ -1062,7 +1043,7 @@ int conf_write_autoconf(int overwrite) struct symbol *sym; const char *name; const char *autoconf_name = conf_get_autoconfig_name(); - FILE *out, *tristate, *out_h; + FILE *out, *out_h; int i; if (!overwrite && is_present(autoconf_name)) @@ -1077,23 +1058,13 @@ int conf_write_autoconf(int overwrite) if (!out) return 1; - tristate = fopen(".tmpconfig_tristate", "w"); - if (!tristate) { - fclose(out); - return 1; - } - out_h = fopen(".tmpconfig.h", "w"); if (!out_h) { fclose(out); - fclose(tristate); return 1; } conf_write_heading(out, &kconfig_printer_cb, NULL); - - conf_write_heading(tristate, &tristate_printer_cb, NULL); - conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { @@ -1101,15 +1072,11 @@ int conf_write_autoconf(int overwrite) if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to auto.conf, tristate and header files */ + /* write symbols to auto.conf and autoconf.h */ conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - - conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); - conf_write_symbol(out_h, sym, &header_printer_cb, NULL); } fclose(out); - fclose(tristate); fclose(out_h); name = getenv("KCONFIG_AUTOHEADER"); @@ -1120,14 +1087,6 @@ int conf_write_autoconf(int overwrite) if (rename(".tmpconfig.h", name)) return 1; - name = getenv("KCONFIG_TRISTATE"); - if (!name) - name = "include/config/tristate.conf"; - if (make_parent_dir(name)) - return 1; - if (rename(".tmpconfig_tristate", name)) - return 1; - if (make_parent_dir(autoconf_name)) return 1; /* diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 436379940356..bf0bf9063aaf 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -250,6 +250,10 @@ ${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1 info MODINFO modules.builtin.modinfo ${OBJCOPY} -j .modinfo -O binary vmlinux.o modules.builtin.modinfo +info GEN modules.builtin +# The second line aids cases where multiple modules share the same object. +tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' | + tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin btf_vmlinux_bin_o="" if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then -- cgit v1.2.3 From f6f149604eefdcb515d80624f058b812d074dac0 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Fri, 20 Dec 2019 07:53:12 +0100 Subject: dt-bindings: phy: Add binding for marvell,mmp3-hsic-phy This is the PHY chip for USB HSIC on MMP3 platform. Link: https://lore.kernel.org/r/20191220065314.237624-4-lkundrak@v3.sk Signed-off-by: Lubomir Rintel Signed-off-by: Olof Johansson --- .../bindings/phy/marvell,mmp3-hsic-phy.yaml | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/marvell,mmp3-hsic-phy.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/phy/marvell,mmp3-hsic-phy.yaml b/Documentation/devicetree/bindings/phy/marvell,mmp3-hsic-phy.yaml new file mode 100644 index 000000000000..7917a95cda78 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/marvell,mmp3-hsic-phy.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright 2019 Lubomir Rintel +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/phy/marvell,mmp3-hsic-phy.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Marvell MMP3 HSIC PHY + +maintainers: + - Lubomir Rintel + +properties: + compatible: + const: marvell,mmp3-hsic-phy + + reg: + maxItems: 1 + description: base address of the device + + reset-gpios: + maxItems: 1 + description: GPIO connected to reset + + "#phy-cells": + const: 0 + +required: + - compatible + - reg + - reset-gpios + - "#phy-cells" + +examples: + - | + hsic-phy@f0001800 { + compatible = "marvell,mmp3-hsic-phy"; + reg = <0xf0001800 0x40>; + reset-gpios = <&gpio 63 GPIO_ACTIVE_HIGH>; + #phy-cells = <0>; + }; -- cgit v1.2.3 From bf046007641a7ef76d4ed976ac67bf24d05ac51a Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 6 Jan 2020 19:17:31 +0100 Subject: dt-bindings: fix warnings in xinpeng,xpp055c272.yaml The reg property in the example caused following warnings: xinpeng,xpp055c272.example.dts:20.17-27: Warning (reg_format): /example-0/dsi@ff450000/panel@0:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) xinpeng,xpp055c272.example.dt.yaml: Warning (pci_device_bus_num): Failed prerequisite 'reg_format' xinpeng,xpp055c272.example.dt.yaml: Warning (i2c_bus_reg): Failed prerequisite 'reg_format' xinpeng,xpp055c272.example.dt.yaml: Warning (spi_bus_reg): Failed prerequisite 'reg_format' xinpeng,xpp055c272.example.dts:18.21-24.15: Warning (avoid_default_addr_size): /example-0/dsi@ff450000/panel@0: Relying on default #address-cells value xinpeng,xpp055c272.example.dts:18.21-24.15: Warning (avoid_default_addr_size): /example-0/dsi@ff450000/panel@0: Relying on default #size-cells value Added #address-cells and #size-cells to silence the warning. Signed-off-by: Sam Ravnborg Reviewed-by: Heiko Stuebner Cc: Maxime Ripard Cc: Rob Herring Cc: devicetree@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20200106181731.GA24294@ravnborg.org --- Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml b/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml index 378cf9e2549d..186e5e1c8fa3 100644 --- a/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml +++ b/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml @@ -35,6 +35,8 @@ additionalProperties: false examples: - | dsi@ff450000 { + #address-cells = <1>; + #size-cells = <0>; panel@0 { compatible = "xinpeng,xpp055c272"; reg = <0>; -- cgit v1.2.3 From 953068058454fa6572efccf4fa550a219ed8c69e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 4 Jan 2020 16:20:48 +0100 Subject: dt-bindings: Rename Exynos to lowercase Fix up inconsistent usage of upper and lowercase letters in "Exynos" name. "EXYNOS" is not an abbreviation but a regular trademarked name. Therefore it should be written with lowercase letters starting with capital letter. The lowercase "Exynos" name is promoted by its manufacturer Samsung Electronics Co., Ltd., in advertisement materials and on website. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt | 2 +- Documentation/devicetree/bindings/media/exynos5-gsc.txt | 2 +- Documentation/devicetree/bindings/media/samsung-fimc.txt | 2 +- Documentation/devicetree/bindings/media/samsung-mipi-csis.txt | 2 +- Documentation/devicetree/bindings/phy/samsung-phy.txt | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt b/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt index 38941db23dd2..ce9a22689e53 100644 --- a/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt +++ b/Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt @@ -1,4 +1,4 @@ -Samsung S5P/EXYNOS SoC series JPEG codec +Samsung S5P/Exynos SoC series JPEG codec Required properties: diff --git a/Documentation/devicetree/bindings/media/exynos5-gsc.txt b/Documentation/devicetree/bindings/media/exynos5-gsc.txt index bc963a6d305a..1872688fa408 100644 --- a/Documentation/devicetree/bindings/media/exynos5-gsc.txt +++ b/Documentation/devicetree/bindings/media/exynos5-gsc.txt @@ -1,6 +1,6 @@ * Samsung Exynos5 G-Scaler device -G-Scaler is used for scaling and color space conversion on EXYNOS5 SoCs. +G-Scaler is used for scaling and color space conversion on Exynos5 SoCs. Required properties: - compatible: should be one of diff --git a/Documentation/devicetree/bindings/media/samsung-fimc.txt b/Documentation/devicetree/bindings/media/samsung-fimc.txt index 48c599dacbdf..f91b9dc80eb3 100644 --- a/Documentation/devicetree/bindings/media/samsung-fimc.txt +++ b/Documentation/devicetree/bindings/media/samsung-fimc.txt @@ -1,4 +1,4 @@ -Samsung S5P/EXYNOS SoC Camera Subsystem (FIMC) +Samsung S5P/Exynos SoC Camera Subsystem (FIMC) ---------------------------------------------- The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices diff --git a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt index be45f0b1a449..a4149c9434ea 100644 --- a/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt +++ b/Documentation/devicetree/bindings/media/samsung-mipi-csis.txt @@ -1,4 +1,4 @@ -Samsung S5P/EXYNOS SoC series MIPI CSI-2 receiver (MIPI CSIS) +Samsung S5P/Exynos SoC series MIPI CSI-2 receiver (MIPI CSIS) ------------------------------------------------------------- Required properties: diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt index 1c40ccd40ce4..7510830a79bd 100644 --- a/Documentation/devicetree/bindings/phy/samsung-phy.txt +++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt @@ -1,4 +1,4 @@ -Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY +Samsung S5P/Exynos SoC series MIPI CSIS/DSIM DPHY ------------------------------------------------- Required properties: @@ -27,7 +27,7 @@ the PHY specifier identifies the PHY and its meaning is as follows: supports additional fifth PHY: 4 - MIPI CSIS 2. -Samsung EXYNOS SoC series Display Port PHY +Samsung Exynos SoC series Display Port PHY ------------------------------------------------- Required properties: @@ -38,7 +38,7 @@ Required properties: control pmu registers for power isolation. - #phy-cells : from the generic PHY bindings, must be 0; -Samsung S5P/EXYNOS SoC series USB PHY +Samsung S5P/Exynos SoC series USB PHY ------------------------------------------------- Required properties: -- cgit v1.2.3 From 60d0426d7603e72329345060c52cc20154f32a4b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 6 Jan 2020 16:58:20 +0800 Subject: arm64: dts: allwinner: h5: Add Libre Computer ALL-H5-CC H5 board The Libre Computer ALL-H5-CC board is an upgraded version of the ALL-H3-CC. Changes include: - Gigabit Ethernet via external RTL8211E Ethernet PHY - 16 MiB SPI NOR flash memory - PoE tap header - Line out jack removed Only H5 variant test samples were made available, and the vendor is not certain whether other SoC variants would be made or not. Furthermore the board is a minor upgrade compared to the ALL-H3-CC. Thus the device tree simply includes the one for the ALL-H3-CC, and adds the changes on top. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- Documentation/devicetree/bindings/arm/sunxi.yaml | 5 ++ arch/arm64/boot/dts/allwinner/Makefile | 1 + .../allwinner/sun50i-h5-libretech-all-h5-cc.dts | 61 ++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h5-cc.dts (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml index a2edf5299e48..dc9aa1586143 100644 --- a/Documentation/devicetree/bindings/arm/sunxi.yaml +++ b/Documentation/devicetree/bindings/arm/sunxi.yaml @@ -347,6 +347,11 @@ properties: - const: libretech,all-h3-it-h5 - const: allwinner,sun50i-h5 + - description: Libre Computer Board ALL-H5-CC H5 + items: + - const: libretech,all-h5-cc-h5 + - const: allwinner,sun50i-h5 + - description: Lichee Pi One items: - const: licheepi,licheepi-one diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile index a7fdf04ffca2..cf4f78617c3f 100644 --- a/arch/arm64/boot/dts/allwinner/Makefile +++ b/arch/arm64/boot/dts/allwinner/Makefile @@ -16,6 +16,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus-v1.2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-emlid-neutis-n5-devboard.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-cc.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-it.dtb +dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h5-cc.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h5-cc.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h5-cc.dts new file mode 100644 index 000000000000..df1b9263ad0e --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h5-cc.dts @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2020 Chen-Yu Tsai + +#include "sun50i-h5-libretech-all-h3-cc.dts" + +/ { + model = "Libre Computer Board ALL-H5-CC H5"; + compatible = "libretech,all-h5-cc-h5", "allwinner,sun50i-h5"; + + aliases { + spi0 = &spi0; + }; + + reg_gmac_3v3: gmac-3v3 { + compatible = "regulator-fixed"; + regulator-name = "gmac-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + startup-delay-us = <5000>; + enable-active-high; + gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; + vin-supply = <®_vcc5v0>; + }; +}; + +&codec { + /* No line out; only onboard microphone */ + allwinner,audio-routing = + "MIC1", "Mic", + "Mic", "MBIAS"; +}; + +/* This board has external PHY */ +&emac { + pinctrl-names = "default"; + pinctrl-0 = <&emac_rgmii_pins>; + phy-supply = <®_gmac_3v3>; + phy-handle = <&ext_rgmii_phy>; + phy-mode = "rgmii"; + /delete-property/ allwinner,leds-active-low; + status = "okay"; +}; + +&external_mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + }; +}; -- cgit v1.2.3 From 8bc49f4489bb1a4552a10f51bc642286509a9694 Mon Sep 17 00:00:00 2001 From: "周琰杰 (Zhou Yanjie)" Date: Mon, 16 Dec 2019 00:21:03 +0800 Subject: dt-bindings: pinctrl: Add bindings for Ingenic X1830. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the pinctrl bindings for the X1830 Soc from Ingenic. Signed-off-by: 周琰杰 (Zhou Yanjie) Acked-by: Rob Herring Link: https://lore.kernel.org/r/1576426864-35348-6-git-send-email-zhouyanjie@wanyeetech.com Signed-off-by: Linus Walleij --- Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt index 0014d9899797..d9b2100c98e8 100644 --- a/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/ingenic,pinctrl.txt @@ -10,9 +10,9 @@ GPIO port configuration registers and it is typical to refer to pins using the naming scheme "PxN" where x is a character identifying the GPIO port with which the pin is associated and N is an integer from 0 to 31 identifying the pin within that GPIO port. For example PA0 is the first pin in GPIO port A, and -PB31 is the last pin in GPIO port B. The jz4740 and the x1000 contains 4 GPIO -ports, PA to PD, for a total of 128 pins. The jz4760, the jz4770 and the jz4780 -contains 6 GPIO ports, PA to PF, for a total of 192 pins. +PB31 is the last pin in GPIO port B. The jz4740, the x1000 and the x1830 +contains 4 GPIO ports, PA to PD, for a total of 128 pins. The jz4760, the +jz4770 and the jz4780 contains 6 GPIO ports, PA to PF, for a total of 192 pins. Required properties: @@ -28,6 +28,7 @@ Required properties: - "ingenic,x1000-pinctrl" - "ingenic,x1000e-pinctrl" - "ingenic,x1500-pinctrl" + - "ingenic,x1830-pinctrl" - reg: Address range of the pinctrl registers. @@ -40,6 +41,7 @@ Required properties for sub-nodes (GPIO chips): - "ingenic,jz4770-gpio" - "ingenic,jz4780-gpio" - "ingenic,x1000-gpio" + - "ingenic,x1830-gpio" - reg: The GPIO bank number. - interrupt-controller: Marks the device node as an interrupt controller. - interrupts: Interrupt specifier for the controllers interrupt. -- cgit v1.2.3 From 0434cd276e7265d6db2bc389a021b795ec16fa69 Mon Sep 17 00:00:00 2001 From: Rahul Tanwar Date: Wed, 18 Dec 2019 14:20:24 +0800 Subject: dt-bindings: pinctrl: intel: Update to use generic bindings Kernel 5.5 adds generic pin mux & cfg node schema. Update pinctrl bindings for LGM to use these newly added schemas. Also, rename filename to match the compatible string. Signed-off-by: Rahul Tanwar Link: https://lore.kernel.org/r/20191218062024.25475-1-rahul.tanwar@linux.intel.com Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/intel,lgm-io.yaml | 76 ++++++++++++++ .../bindings/pinctrl/intel,lgm-pinctrl.yaml | 116 --------------------- 2 files changed, 76 insertions(+), 116 deletions(-) create mode 100644 Documentation/devicetree/bindings/pinctrl/intel,lgm-io.yaml delete mode 100644 Documentation/devicetree/bindings/pinctrl/intel,lgm-pinctrl.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/pinctrl/intel,lgm-io.yaml b/Documentation/devicetree/bindings/pinctrl/intel,lgm-io.yaml new file mode 100644 index 000000000000..a386fb520510 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/intel,lgm-io.yaml @@ -0,0 +1,76 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/bindings/pinctrl/intel,lgm-io.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Intel Lightning Mountain SoC pinmux & GPIO controller binding + +maintainers: + - Rahul Tanwar + +description: | + Pinmux & GPIO controller controls pin multiplexing & configuration including + GPIO function selection & GPIO attributes configuration. + +allOf: + - $ref: pincfg-node.yaml# + - $ref: pinmux-node.yaml# + +properties: + compatible: + const: intel,lgm-io + + reg: + maxItems: 1 + +# Client device subnode's properties +patternProperties: + '-pins$': + type: object + description: + Pinctrl node's client devices use subnodes for desired pin configuration. + Client device subnodes use below standard properties. + + properties: + function: true + group: true + pins: true + pinmux: true + bias-pull-up: true + bias-pull-down: true + drive-strength: true + slew-rate: true + drive-open-drain: true + output-enable: true + + required: + - function + - group + + additionalProperties: false + +required: + - compatible + - reg + +additionalProperties: false + +examples: + # Pinmux controller node + - | + pinctrl: pinctrl@e2880000 { + compatible = "intel,lgm-io"; + reg = <0xe2880000 0x100000>; + + uart0-pins { + pins = <64>, /* UART_RX0 */ + <65>; /* UART_TX0 */ + function = "CONSOLE_UART0"; + pinmux = <1>, + <1>; + groups = "CONSOLE_UART0"; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/pinctrl/intel,lgm-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/intel,lgm-pinctrl.yaml deleted file mode 100644 index 240d429f773b..000000000000 --- a/Documentation/devicetree/bindings/pinctrl/intel,lgm-pinctrl.yaml +++ /dev/null @@ -1,116 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/bindings/pinctrl/intel,lgm-pinctrl.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Intel Lightning Mountain SoC pinmux & GPIO controller binding - -maintainers: - - Rahul Tanwar - -description: | - Pinmux & GPIO controller controls pin multiplexing & configuration including - GPIO function selection & GPIO attributes configuration. - - Please refer to [1] for details of the common pinctrl bindings used by the - client devices. - - [1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - -properties: - compatible: - const: intel,lgm-io - - reg: - maxItems: 1 - -# Client device subnode's properties -patternProperties: - '-pins$': - type: object - description: - Pinctrl node's client devices use subnodes for desired pin configuration. - Client device subnodes use below standard properties. - - properties: - function: - $ref: /schemas/types.yaml#/definitions/string - description: - A string containing the name of the function to mux to the group. - - groups: - $ref: /schemas/types.yaml#/definitions/string-array - description: - An array of strings identifying the list of groups. - - pins: - $ref: /schemas/types.yaml#/definitions/uint32-array - description: - List of pins to select with this function. - - pinmux: - description: The applicable mux group. - allOf: - - $ref: "/schemas/types.yaml#/definitions/uint32-array" - - bias-pull-up: - type: boolean - - bias-pull-down: - type: boolean - - drive-strength: - description: | - Selects the drive strength for the specified pins in mA. - 0: 2 mA - 1: 4 mA - 2: 8 mA - 3: 12 mA - allOf: - - $ref: /schemas/types.yaml#/definitions/uint32 - - enum: [0, 1, 2, 3] - - slew-rate: - type: boolean - description: | - Sets slew rate for specified pins. - 0: slow slew - 1: fast slew - - drive-open-drain: - type: boolean - - output-enable: - type: boolean - - required: - - function - - groups - - additionalProperties: false - -required: - - compatible - - reg - -additionalProperties: false - -examples: - # Pinmux controller node - - | - pinctrl: pinctrl@e2880000 { - compatible = "intel,lgm-pinctrl"; - reg = <0xe2880000 0x100000>; - - uart0-pins { - pins = <64>, /* UART_RX0 */ - <65>; /* UART_TX0 */ - function = "CONSOLE_UART0"; - pinmux = <1>, - <1>; - groups = "CONSOLE_UART0"; - }; - }; - -... -- cgit v1.2.3 From baac82fe06db16f36bf216dd0c8ca0eaa1e28b97 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 20 Nov 2019 17:41:13 -0600 Subject: dt-bindings: arm: Convert arm,idle-state binding to DT schema Convert the Arm idle-state binding to a DT schema. Cc: Lorenzo Pieralisi Signed-off-by: Rob Herring --- .../devicetree/bindings/arm/idle-states.txt | 706 --------------------- .../devicetree/bindings/arm/idle-states.yaml | 661 +++++++++++++++++++ 2 files changed, 661 insertions(+), 706 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/idle-states.txt create mode 100644 Documentation/devicetree/bindings/arm/idle-states.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/arm/idle-states.txt b/Documentation/devicetree/bindings/arm/idle-states.txt deleted file mode 100644 index 771f5d20ae18..000000000000 --- a/Documentation/devicetree/bindings/arm/idle-states.txt +++ /dev/null @@ -1,706 +0,0 @@ -========================================== -ARM idle states binding description -========================================== - -========================================== -1 - Introduction -========================================== - -ARM systems contain HW capable of managing power consumption dynamically, -where cores can be put in different low-power states (ranging from simple -wfi to power gating) according to OS PM policies. The CPU states representing -the range of dynamic idle states that a processor can enter at run-time, can be -specified through device tree bindings representing the parameters required -to enter/exit specific idle states on a given processor. - -According to the Server Base System Architecture document (SBSA, [3]), the -power states an ARM CPU can be put into are identified by the following list: - -- Running -- Idle_standby -- Idle_retention -- Sleep -- Off - -The power states described in the SBSA document define the basic CPU states on -top of which ARM platforms implement power management schemes that allow an OS -PM implementation to put the processor in different idle states (which include -states listed above; "off" state is not an idle state since it does not have -wake-up capabilities, hence it is not considered in this document). - -Idle state parameters (e.g. entry latency) are platform specific and need to be -characterized with bindings that provide the required information to OS PM -code so that it can build the required tables and use them at runtime. - -The device tree binding definition for ARM idle states is the subject of this -document. - -=========================================== -2 - idle-states definitions -=========================================== - -Idle states are characterized for a specific system through a set of -timing and energy related properties, that underline the HW behaviour -triggered upon idle states entry and exit. - -The following diagram depicts the CPU execution phases and related timing -properties required to enter and exit an idle state: - -..__[EXEC]__|__[PREP]__|__[ENTRY]__|__[IDLE]__|__[EXIT]__|__[EXEC]__.. - | | | | | - - |<------ entry ------->| - | latency | - |<- exit ->| - | latency | - |<-------- min-residency -------->| - |<------- wakeup-latency ------->| - - Diagram 1: CPU idle state execution phases - -EXEC: Normal CPU execution. - -PREP: Preparation phase before committing the hardware to idle mode - like cache flushing. This is abortable on pending wake-up - event conditions. The abort latency is assumed to be negligible - (i.e. less than the ENTRY + EXIT duration). If aborted, CPU - goes back to EXEC. This phase is optional. If not abortable, - this should be included in the ENTRY phase instead. - -ENTRY: The hardware is committed to idle mode. This period must run - to completion up to IDLE before anything else can happen. - -IDLE: This is the actual energy-saving idle period. This may last - between 0 and infinite time, until a wake-up event occurs. - -EXIT: Period during which the CPU is brought back to operational - mode (EXEC). - -entry-latency: Worst case latency required to enter the idle state. The -exit-latency may be guaranteed only after entry-latency has passed. - -min-residency: Minimum period, including preparation and entry, for a given -idle state to be worthwhile energywise. - -wakeup-latency: Maximum delay between the signaling of a wake-up event and the -CPU being able to execute normal code again. If not specified, this is assumed -to be entry-latency + exit-latency. - -These timing parameters can be used by an OS in different circumstances. - -An idle CPU requires the expected min-residency time to select the most -appropriate idle state based on the expected expiry time of the next IRQ -(i.e. wake-up) that causes the CPU to return to the EXEC phase. - -An operating system scheduler may need to compute the shortest wake-up delay -for CPUs in the system by detecting how long will it take to get a CPU out -of an idle state, e.g.: - -wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0) - -In other words, the scheduler can make its scheduling decision by selecting -(e.g. waking-up) the CPU with the shortest wake-up delay. -The wake-up delay must take into account the entry latency if that period -has not expired. The abortable nature of the PREP period can be ignored -if it cannot be relied upon (e.g. the PREP deadline may occur much sooner than -the worst case since it depends on the CPU operating conditions, i.e. caches -state). - -An OS has to reliably probe the wakeup-latency since some devices can enforce -latency constraint guarantees to work properly, so the OS has to detect the -worst case wake-up latency it can incur if a CPU is allowed to enter an -idle state, and possibly to prevent that to guarantee reliable device -functioning. - -The min-residency time parameter deserves further explanation since it is -expressed in time units but must factor in energy consumption coefficients. - -The energy consumption of a cpu when it enters a power state can be roughly -characterised by the following graph: - - | - | - | - e | - n | /--- - e | /------ - r | /------ - g | /----- - y | /------ - | ---- - | /| - | / | - | / | - | / | - | / | - | / | - |/ | - -----|-------+---------------------------------- - 0| 1 time(ms) - - Graph 1: Energy vs time example - -The graph is split in two parts delimited by time 1ms on the X-axis. -The graph curve with X-axis values = { x | 0 < x < 1ms } has a steep slope -and denotes the energy costs incurred while entering and leaving the idle -state. -The graph curve in the area delimited by X-axis values = {x | x > 1ms } has -shallower slope and essentially represents the energy consumption of the idle -state. - -min-residency is defined for a given idle state as the minimum expected -residency time for a state (inclusive of preparation and entry) after -which choosing that state become the most energy efficient option. A good -way to visualise this, is by taking the same graph above and comparing some -states energy consumptions plots. - -For sake of simplicity, let's consider a system with two idle states IDLE1, -and IDLE2: - - | - | - | - | /-- IDLE1 - e | /--- - n | /---- - e | /--- - r | /-----/--------- IDLE2 - g | /-------/--------- - y | ------------ /---| - | / /---- | - | / /--- | - | / /---- | - | / /--- | - | --- | - | / | - | / | - |/ | time - ---/----------------------------+------------------------ - |IDLE1-energy < IDLE2-energy | IDLE2-energy < IDLE1-energy - | - IDLE2-min-residency - - Graph 2: idle states min-residency example - -In graph 2 above, that takes into account idle states entry/exit energy -costs, it is clear that if the idle state residency time (i.e. time till next -wake-up IRQ) is less than IDLE2-min-residency, IDLE1 is the better idle state -choice energywise. - -This is mainly down to the fact that IDLE1 entry/exit energy costs are lower -than IDLE2. - -However, the lower power consumption (i.e. shallower energy curve slope) of -idle state IDLE2 implies that after a suitable time, IDLE2 becomes more energy -efficient. - -The time at which IDLE2 becomes more energy efficient than IDLE1 (and other -shallower states in a system with multiple idle states) is defined -IDLE2-min-residency and corresponds to the time when energy consumption of -IDLE1 and IDLE2 states breaks even. - -The definitions provided in this section underpin the idle states -properties specification that is the subject of the following sections. - -=========================================== -3 - idle-states node -=========================================== - -ARM processor idle states are defined within the idle-states node, which is -a direct child of the cpus node [1] and provides a container where the -processor idle states, defined as device tree nodes, are listed. - -- idle-states node - - Usage: Optional - On ARM systems, it is a container of processor idle - states nodes. If the system does not provide CPU - power management capabilities, or the processor just - supports idle_standby, an idle-states node is not - required. - - Description: idle-states node is a container node, where its - subnodes describe the CPU idle states. - - Node name must be "idle-states". - - The idle-states node's parent node must be the cpus node. - - The idle-states node's child nodes can be: - - - one or more state nodes - - Any other configuration is considered invalid. - - An idle-states node defines the following properties: - - - entry-method - Value type: - Usage and definition depend on ARM architecture version. - # On ARM v8 64-bit this property is required and must - be: - - "psci" - # On ARM 32-bit systems this property is optional - -This assumes that the "enable-method" property is set to "psci" in the cpu -node[6] that is responsible for setting up CPU idle management in the OS -implementation. - -The nodes describing the idle states (state) can only be defined -within the idle-states node, any other configuration is considered invalid -and therefore must be ignored. - -=========================================== -4 - state node -=========================================== - -A state node represents an idle state description and must be defined as -follows: - -- state node - - Description: must be child of the idle-states node - - The state node name shall follow standard device tree naming - rules ([5], 2.2.1 "Node names"), in particular state nodes which - are siblings within a single common parent must be given a unique name. - - The idle state entered by executing the wfi instruction (idle_standby - SBSA,[3][4]) is considered standard on all ARM platforms and therefore - must not be listed. - - With the definitions provided above, the following list represents - the valid properties for a state node: - - - compatible - Usage: Required - Value type: - Definition: Must be "arm,idle-state". - - - local-timer-stop - Usage: See definition - Value type: - Definition: if present the CPU local timer control logic is - lost on state entry, otherwise it is retained. - - - entry-latency-us - Usage: Required - Value type: - Definition: u32 value representing worst case latency in - microseconds required to enter the idle state. - - - exit-latency-us - Usage: Required - Value type: - Definition: u32 value representing worst case latency - in microseconds required to exit the idle state. - The exit-latency-us duration may be guaranteed - only after entry-latency-us has passed. - - - min-residency-us - Usage: Required - Value type: - Definition: u32 value representing minimum residency duration - in microseconds, inclusive of preparation and - entry, for this idle state to be considered - worthwhile energy wise (refer to section 2 of - this document for a complete description). - - - wakeup-latency-us: - Usage: Optional - Value type: - Definition: u32 value representing maximum delay between the - signaling of a wake-up event and the CPU being - able to execute normal code again. If omitted, - this is assumed to be equal to: - - entry-latency-us + exit-latency-us - - It is important to supply this value on systems - where the duration of PREP phase (see diagram 1, - section 2) is non-neglibigle. - In such systems entry-latency-us + exit-latency-us - will exceed wakeup-latency-us by this duration. - - - status: - Usage: Optional - Value type: - Definition: A standard device tree property [5] that indicates - the operational status of an idle-state. - If present, it shall be: - "okay": to indicate that the idle state is - operational. - "disabled": to indicate that the idle state has - been disabled in firmware so it is not - operational. - If the property is not present the idle-state must - be considered operational. - - - idle-state-name: - Usage: Optional - Value type: - Definition: A string used as a descriptive name for the idle - state. - - In addition to the properties listed above, a state node may require - additional properties specific to the entry-method defined in the - idle-states node. Please refer to the entry-method bindings - documentation for properties definitions. - -=========================================== -4 - Examples -=========================================== - -Example 1 (ARM 64-bit, 16-cpu system, PSCI enable-method): - -cpus { - #size-cells = <0>; - #address-cells = <2>; - - CPU0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x0>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x1>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU2: cpu@100 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x100>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU3: cpu@101 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x101>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU4: cpu@10000 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x10000>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU5: cpu@10001 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x10001>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU6: cpu@10100 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x10100>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU7: cpu@10101 { - device_type = "cpu"; - compatible = "arm,cortex-a57"; - reg = <0x0 0x10101>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 - &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; - }; - - CPU8: cpu@100000000 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x0>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU9: cpu@100000001 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x1>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU10: cpu@100000100 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x100>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU11: cpu@100000101 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x101>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU12: cpu@100010000 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x10000>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU13: cpu@100010001 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x10001>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU14: cpu@100010100 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x10100>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - CPU15: cpu@100010101 { - device_type = "cpu"; - compatible = "arm,cortex-a53"; - reg = <0x1 0x10101>; - enable-method = "psci"; - cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 - &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; - }; - - idle-states { - entry-method = "psci"; - - CPU_RETENTION_0_0: cpu-retention-0-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; - entry-latency-us = <20>; - exit-latency-us = <40>; - min-residency-us = <80>; - }; - - CLUSTER_RETENTION_0: cluster-retention-0 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x1010000>; - entry-latency-us = <50>; - exit-latency-us = <100>; - min-residency-us = <250>; - wakeup-latency-us = <130>; - }; - - CPU_SLEEP_0_0: cpu-sleep-0-0 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x0010000>; - entry-latency-us = <250>; - exit-latency-us = <500>; - min-residency-us = <950>; - }; - - CLUSTER_SLEEP_0: cluster-sleep-0 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x1010000>; - entry-latency-us = <600>; - exit-latency-us = <1100>; - min-residency-us = <2700>; - wakeup-latency-us = <1500>; - }; - - CPU_RETENTION_1_0: cpu-retention-1-0 { - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; - entry-latency-us = <20>; - exit-latency-us = <40>; - min-residency-us = <90>; - }; - - CLUSTER_RETENTION_1: cluster-retention-1 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x1010000>; - entry-latency-us = <50>; - exit-latency-us = <100>; - min-residency-us = <270>; - wakeup-latency-us = <100>; - }; - - CPU_SLEEP_1_0: cpu-sleep-1-0 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x0010000>; - entry-latency-us = <70>; - exit-latency-us = <100>; - min-residency-us = <300>; - wakeup-latency-us = <150>; - }; - - CLUSTER_SLEEP_1: cluster-sleep-1 { - compatible = "arm,idle-state"; - local-timer-stop; - arm,psci-suspend-param = <0x1010000>; - entry-latency-us = <500>; - exit-latency-us = <1200>; - min-residency-us = <3500>; - wakeup-latency-us = <1300>; - }; - }; - -}; - -Example 2 (ARM 32-bit, 8-cpu system, two clusters): - -cpus { - #size-cells = <0>; - #address-cells = <1>; - - CPU0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a15"; - reg = <0x0>; - cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>; - }; - - CPU1: cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a15"; - reg = <0x1>; - cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>; - }; - - CPU2: cpu@2 { - device_type = "cpu"; - compatible = "arm,cortex-a15"; - reg = <0x2>; - cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>; - }; - - CPU3: cpu@3 { - device_type = "cpu"; - compatible = "arm,cortex-a15"; - reg = <0x3>; - cpu-idle-states = <&CPU_SLEEP_0_0 &CLUSTER_SLEEP_0>; - }; - - CPU4: cpu@100 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x100>; - cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>; - }; - - CPU5: cpu@101 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x101>; - cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>; - }; - - CPU6: cpu@102 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x102>; - cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>; - }; - - CPU7: cpu@103 { - device_type = "cpu"; - compatible = "arm,cortex-a7"; - reg = <0x103>; - cpu-idle-states = <&CPU_SLEEP_1_0 &CLUSTER_SLEEP_1>; - }; - - idle-states { - CPU_SLEEP_0_0: cpu-sleep-0-0 { - compatible = "arm,idle-state"; - local-timer-stop; - entry-latency-us = <200>; - exit-latency-us = <100>; - min-residency-us = <400>; - wakeup-latency-us = <250>; - }; - - CLUSTER_SLEEP_0: cluster-sleep-0 { - compatible = "arm,idle-state"; - local-timer-stop; - entry-latency-us = <500>; - exit-latency-us = <1500>; - min-residency-us = <2500>; - wakeup-latency-us = <1700>; - }; - - CPU_SLEEP_1_0: cpu-sleep-1-0 { - compatible = "arm,idle-state"; - local-timer-stop; - entry-latency-us = <300>; - exit-latency-us = <500>; - min-residency-us = <900>; - wakeup-latency-us = <600>; - }; - - CLUSTER_SLEEP_1: cluster-sleep-1 { - compatible = "arm,idle-state"; - local-timer-stop; - entry-latency-us = <800>; - exit-latency-us = <2000>; - min-residency-us = <6500>; - wakeup-latency-us = <2300>; - }; - }; - -}; - -=========================================== -5 - References -=========================================== - -[1] ARM Linux Kernel documentation - CPUs bindings - Documentation/devicetree/bindings/arm/cpus.yaml - -[2] ARM Linux Kernel documentation - PSCI bindings - Documentation/devicetree/bindings/arm/psci.yaml - -[3] ARM Server Base System Architecture (SBSA) - http://infocenter.arm.com/help/index.jsp - -[4] ARM Architecture Reference Manuals - http://infocenter.arm.com/help/index.jsp - -[5] Devicetree Specification - https://www.devicetree.org/specifications/ - -[6] ARM Linux Kernel documentation - Booting AArch64 Linux - Documentation/arm64/booting.rst diff --git a/Documentation/devicetree/bindings/arm/idle-states.yaml b/Documentation/devicetree/bindings/arm/idle-states.yaml new file mode 100644 index 000000000000..ea805c1e6b20 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/idle-states.yaml @@ -0,0 +1,661 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/idle-states.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ARM idle states binding description + +maintainers: + - Lorenzo Pieralisi + +description: |+ + ========================================== + 1 - Introduction + ========================================== + + ARM systems contain HW capable of managing power consumption dynamically, + where cores can be put in different low-power states (ranging from simple wfi + to power gating) according to OS PM policies. The CPU states representing the + range of dynamic idle states that a processor can enter at run-time, can be + specified through device tree bindings representing the parameters required to + enter/exit specific idle states on a given processor. + + According to the Server Base System Architecture document (SBSA, [3]), the + power states an ARM CPU can be put into are identified by the following list: + + - Running + - Idle_standby + - Idle_retention + - Sleep + - Off + + The power states described in the SBSA document define the basic CPU states on + top of which ARM platforms implement power management schemes that allow an OS + PM implementation to put the processor in different idle states (which include + states listed above; "off" state is not an idle state since it does not have + wake-up capabilities, hence it is not considered in this document). + + Idle state parameters (e.g. entry latency) are platform specific and need to + be characterized with bindings that provide the required information to OS PM + code so that it can build the required tables and use them at runtime. + + The device tree binding definition for ARM idle states is the subject of this + document. + + =========================================== + 2 - idle-states definitions + =========================================== + + Idle states are characterized for a specific system through a set of + timing and energy related properties, that underline the HW behaviour + triggered upon idle states entry and exit. + + The following diagram depicts the CPU execution phases and related timing + properties required to enter and exit an idle state: + + ..__[EXEC]__|__[PREP]__|__[ENTRY]__|__[IDLE]__|__[EXIT]__|__[EXEC]__.. + | | | | | + + |<------ entry ------->| + | latency | + |<- exit ->| + | latency | + |<-------- min-residency -------->| + |<------- wakeup-latency ------->| + + Diagram 1: CPU idle state execution phases + + EXEC: Normal CPU execution. + + PREP: Preparation phase before committing the hardware to idle mode + like cache flushing. This is abortable on pending wake-up + event conditions. The abort latency is assumed to be negligible + (i.e. less than the ENTRY + EXIT duration). If aborted, CPU + goes back to EXEC. This phase is optional. If not abortable, + this should be included in the ENTRY phase instead. + + ENTRY: The hardware is committed to idle mode. This period must run + to completion up to IDLE before anything else can happen. + + IDLE: This is the actual energy-saving idle period. This may last + between 0 and infinite time, until a wake-up event occurs. + + EXIT: Period during which the CPU is brought back to operational + mode (EXEC). + + entry-latency: Worst case latency required to enter the idle state. The + exit-latency may be guaranteed only after entry-latency has passed. + + min-residency: Minimum period, including preparation and entry, for a given + idle state to be worthwhile energywise. + + wakeup-latency: Maximum delay between the signaling of a wake-up event and the + CPU being able to execute normal code again. If not specified, this is assumed + to be entry-latency + exit-latency. + + These timing parameters can be used by an OS in different circumstances. + + An idle CPU requires the expected min-residency time to select the most + appropriate idle state based on the expected expiry time of the next IRQ + (i.e. wake-up) that causes the CPU to return to the EXEC phase. + + An operating system scheduler may need to compute the shortest wake-up delay + for CPUs in the system by detecting how long will it take to get a CPU out + of an idle state, e.g.: + + wakeup-delay = exit-latency + max(entry-latency - (now - entry-timestamp), 0) + + In other words, the scheduler can make its scheduling decision by selecting + (e.g. waking-up) the CPU with the shortest wake-up delay. + The wake-up delay must take into account the entry latency if that period + has not expired. The abortable nature of the PREP period can be ignored + if it cannot be relied upon (e.g. the PREP deadline may occur much sooner than + the worst case since it depends on the CPU operating conditions, i.e. caches + state). + + An OS has to reliably probe the wakeup-latency since some devices can enforce + latency constraint guarantees to work properly, so the OS has to detect the + worst case wake-up latency it can incur if a CPU is allowed to enter an + idle state, and possibly to prevent that to guarantee reliable device + functioning. + + The min-residency time parameter deserves further explanation since it is + expressed in time units but must factor in energy consumption coefficients. + + The energy consumption of a cpu when it enters a power state can be roughly + characterised by the following graph: + + | + | + | + e | + n | /--- + e | /------ + r | /------ + g | /----- + y | /------ + | ---- + | /| + | / | + | / | + | / | + | / | + | / | + |/ | + -----|-------+---------------------------------- + 0| 1 time(ms) + + Graph 1: Energy vs time example + + The graph is split in two parts delimited by time 1ms on the X-axis. + The graph curve with X-axis values = { x | 0 < x < 1ms } has a steep slope + and denotes the energy costs incurred while entering and leaving the idle + state. + The graph curve in the area delimited by X-axis values = {x | x > 1ms } has + shallower slope and essentially represents the energy consumption of the idle + state. + + min-residency is defined for a given idle state as the minimum expected + residency time for a state (inclusive of preparation and entry) after + which choosing that state become the most energy efficient option. A good + way to visualise this, is by taking the same graph above and comparing some + states energy consumptions plots. + + For sake of simplicity, let's consider a system with two idle states IDLE1, + and IDLE2: + + | + | + | + | /-- IDLE1 + e | /--- + n | /---- + e | /--- + r | /-----/--------- IDLE2 + g | /-------/--------- + y | ------------ /---| + | / /---- | + | / /--- | + | / /---- | + | / /--- | + | --- | + | / | + | / | + |/ | time + ---/----------------------------+------------------------ + |IDLE1-energy < IDLE2-energy | IDLE2-energy < IDLE1-energy + | + IDLE2-min-residency + + Graph 2: idle states min-residency example + + In graph 2 above, that takes into account idle states entry/exit energy + costs, it is clear that if the idle state residency time (i.e. time till next + wake-up IRQ) is less than IDLE2-min-residency, IDLE1 is the better idle state + choice energywise. + + This is mainly down to the fact that IDLE1 entry/exit energy costs are lower + than IDLE2. + + However, the lower power consumption (i.e. shallower energy curve slope) of + idle state IDLE2 implies that after a suitable time, IDLE2 becomes more energy + efficient. + + The time at which IDLE2 becomes more energy efficient than IDLE1 (and other + shallower states in a system with multiple idle states) is defined + IDLE2-min-residency and corresponds to the time when energy consumption of + IDLE1 and IDLE2 states breaks even. + + The definitions provided in this section underpin the idle states + properties specification that is the subject of the following sections. + + =========================================== + 3 - idle-states node + =========================================== + + ARM processor idle states are defined within the idle-states node, which is + a direct child of the cpus node [1] and provides a container where the + processor idle states, defined as device tree nodes, are listed. + + On ARM systems, it is a container of processor idle states nodes. If the + system does not provide CPU power management capabilities, or the processor + just supports idle_standby, an idle-states node is not required. + + =========================================== + 4 - References + =========================================== + + [1] ARM Linux Kernel documentation - CPUs bindings + Documentation/devicetree/bindings/arm/cpus.yaml + + [2] ARM Linux Kernel documentation - PSCI bindings + Documentation/devicetree/bindings/arm/psci.yaml + + [3] ARM Server Base System Architecture (SBSA) + http://infocenter.arm.com/help/index.jsp + + [4] ARM Architecture Reference Manuals + http://infocenter.arm.com/help/index.jsp + + [6] ARM Linux Kernel documentation - Booting AArch64 Linux + Documentation/arm64/booting.rst + +properties: + $nodename: + const: idle-states + + entry-method: + description: | + Usage and definition depend on ARM architecture version. + + On ARM v8 64-bit this property is required. + On ARM 32-bit systems this property is optional + + This assumes that the "enable-method" property is set to "psci" in the cpu + node[6] that is responsible for setting up CPU idle management in the OS + implementation. + const: psci + +patternProperties: + "^(cpu|cluster)-": + type: object + description: | + Each state node represents an idle state description and must be defined + as follows. + + The idle state entered by executing the wfi instruction (idle_standby + SBSA,[3][4]) is considered standard on all ARM platforms and therefore + must not be listed. + + In addition to the properties listed above, a state node may require + additional properties specific to the entry-method defined in the + idle-states node. Please refer to the entry-method bindings + documentation for properties definitions. + + properties: + compatible: + const: arm,idle-state + + local-timer-stop: + description: + If present the CPU local timer control logic is + lost on state entry, otherwise it is retained. + type: boolean + + entry-latency-us: + description: + Worst case latency in microseconds required to enter the idle state. + + exit-latency-us: + description: + Worst case latency in microseconds required to exit the idle state. + The exit-latency-us duration may be guaranteed only after + entry-latency-us has passed. + + min-residency-us: + description: + Minimum residency duration in microseconds, inclusive of preparation + and entry, for this idle state to be considered worthwhile energy wise + (refer to section 2 of this document for a complete description). + + wakeup-latency-us: + description: | + Maximum delay between the signaling of a wake-up event and the CPU + being able to execute normal code again. If omitted, this is assumed + to be equal to: + + entry-latency-us + exit-latency-us + + It is important to supply this value on systems where the duration of + PREP phase (see diagram 1, section 2) is non-neglibigle. In such + systems entry-latency-us + exit-latency-us will exceed + wakeup-latency-us by this duration. + + idle-state-name: + $ref: /schemas/types.yaml#definitions/string + description: + A string used as a descriptive name for the idle state. + + required: + - compatible + - entry-latency-us + - exit-latency-us + - min-residency-us + +additionalProperties: false + +examples: + - | + + cpus { + #size-cells = <0>; + #address-cells = <2>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x100>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x101>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@10000 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x10000>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@10001 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x10001>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@10100 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x10100>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@10101 { + device_type = "cpu"; + compatible = "arm,cortex-a57"; + reg = <0x0 0x10101>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_0_0 &CPU_SLEEP_0_0 + &CLUSTER_RETENTION_0 &CLUSTER_SLEEP_0>; + }; + + cpu@100000000 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x0>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100000001 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x1>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100000100 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x100>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100000101 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x101>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100010000 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x10000>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100010001 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x10001>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100010100 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x10100>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + cpu@100010101 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1 0x10101>; + enable-method = "psci"; + cpu-idle-states = <&CPU_RETENTION_1_0 &CPU_SLEEP_1_0 + &CLUSTER_RETENTION_1 &CLUSTER_SLEEP_1>; + }; + + idle-states { + entry-method = "psci"; + + CPU_RETENTION_0_0: cpu-retention-0-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <20>; + exit-latency-us = <40>; + min-residency-us = <80>; + }; + + CLUSTER_RETENTION_0: cluster-retention-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <50>; + exit-latency-us = <100>; + min-residency-us = <250>; + wakeup-latency-us = <130>; + }; + + CPU_SLEEP_0_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <250>; + exit-latency-us = <500>; + min-residency-us = <950>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <600>; + exit-latency-us = <1100>; + min-residency-us = <2700>; + wakeup-latency-us = <1500>; + }; + + CPU_RETENTION_1_0: cpu-retention-1-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <20>; + exit-latency-us = <40>; + min-residency-us = <90>; + }; + + CLUSTER_RETENTION_1: cluster-retention-1 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <50>; + exit-latency-us = <100>; + min-residency-us = <270>; + wakeup-latency-us = <100>; + }; + + CPU_SLEEP_1_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <70>; + exit-latency-us = <100>; + min-residency-us = <300>; + wakeup-latency-us = <150>; + }; + + CLUSTER_SLEEP_1: cluster-sleep-1 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1200>; + min-residency-us = <3500>; + wakeup-latency-us = <1300>; + }; + }; + }; + + - | + // Example 2 (ARM 32-bit, 8-cpu system, two clusters): + + cpus { + #size-cells = <0>; + #address-cells = <1>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0x0>; + cpu-idle-states = <&cpu_sleep_0_0 &cluster_sleep_0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0x1>; + cpu-idle-states = <&cpu_sleep_0_0 &cluster_sleep_0>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0x2>; + cpu-idle-states = <&cpu_sleep_0_0 &cluster_sleep_0>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a15"; + reg = <0x3>; + cpu-idle-states = <&cpu_sleep_0_0 &cluster_sleep_0>; + }; + + cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x100>; + cpu-idle-states = <&cpu_sleep_1_0 &cluster_sleep_1>; + }; + + cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x101>; + cpu-idle-states = <&cpu_sleep_1_0 &cluster_sleep_1>; + }; + + cpu@102 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x102>; + cpu-idle-states = <&cpu_sleep_1_0 &cluster_sleep_1>; + }; + + cpu@103 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0x103>; + cpu-idle-states = <&cpu_sleep_1_0 &cluster_sleep_1>; + }; + + idle-states { + cpu_sleep_0_0: cpu-sleep-0-0 { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <200>; + exit-latency-us = <100>; + min-residency-us = <400>; + wakeup-latency-us = <250>; + }; + + cluster_sleep_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <500>; + exit-latency-us = <1500>; + min-residency-us = <2500>; + wakeup-latency-us = <1700>; + }; + + cpu_sleep_1_0: cpu-sleep-1-0 { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <300>; + exit-latency-us = <500>; + min-residency-us = <900>; + wakeup-latency-us = <600>; + }; + + cluster_sleep_1: cluster-sleep-1 { + compatible = "arm,idle-state"; + local-timer-stop; + entry-latency-us = <800>; + exit-latency-us = <2000>; + min-residency-us = <6500>; + wakeup-latency-us = <2300>; + }; + }; + }; + +... -- cgit v1.2.3 From ebb37bd06460fff8d6f54f7731f593b7b52143ca Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 15 Aug 2019 13:06:12 +0300 Subject: dt-bindings: interconnect: Add Qualcomm MSM8916 DT bindings The Qualcomm MSM8916 platform has several bus fabrics that could be controlled and tuned dynamically according to the bandwidth demand. Reviewed-by: Rob Herring Signed-off-by: Georgi Djakov --- .../bindings/interconnect/qcom,msm8916.yaml | 77 ++++++++++++++++ include/dt-bindings/interconnect/qcom,msm8916.h | 100 +++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 Documentation/devicetree/bindings/interconnect/qcom,msm8916.yaml create mode 100644 include/dt-bindings/interconnect/qcom,msm8916.h (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8916.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8916.yaml new file mode 100644 index 000000000000..4107e60cab12 --- /dev/null +++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8916.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interconnect/qcom,msm8916.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm MSM8916 Network-On-Chip interconnect + +maintainers: + - Georgi Djakov + +description: | + The Qualcomm MSM8916 interconnect providers support adjusting the + bandwidth requirements between the various NoC fabrics. + +properties: + compatible: + enum: + - qcom,msm8916-bimc + - qcom,msm8916-pcnoc + - qcom,msm8916-snoc + + reg: + maxItems: 1 + + '#interconnect-cells': + const: 1 + + clock-names: + items: + - const: bus + - const: bus_a + + clocks: + items: + - description: Bus Clock + - description: Bus A Clock + +required: + - compatible + - reg + - '#interconnect-cells' + - clock-names + - clocks + +additionalProperties: false + +examples: + - | + #include + + bimc: interconnect@400000 { + compatible = "qcom,msm8916-bimc"; + reg = <0x00400000 0x62000>; + #interconnect-cells = <1>; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_BIMC_CLK>, + <&rpmcc RPM_SMD_BIMC_A_CLK>; + }; + + pcnoc: interconnect@500000 { + compatible = "qcom,msm8916-pcnoc"; + reg = <0x00500000 0x11000>; + #interconnect-cells = <1>; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_PCNOC_CLK>, + <&rpmcc RPM_SMD_PCNOC_A_CLK>; + }; + + snoc: interconnect@580000 { + compatible = "qcom,msm8916-snoc"; + reg = <0x00580000 0x14000>; + #interconnect-cells = <1>; + clock-names = "bus", "bus_a"; + clocks = <&rpmcc RPM_SMD_SNOC_CLK>, + <&rpmcc RPM_SMD_SNOC_A_CLK>; + }; diff --git a/include/dt-bindings/interconnect/qcom,msm8916.h b/include/dt-bindings/interconnect/qcom,msm8916.h new file mode 100644 index 000000000000..359a75feb198 --- /dev/null +++ b/include/dt-bindings/interconnect/qcom,msm8916.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Qualcomm interconnect IDs + * + * Copyright (c) 2019, Linaro Ltd. + * Author: Georgi Djakov + */ + +#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_MSM8916_H +#define __DT_BINDINGS_INTERCONNECT_QCOM_MSM8916_H + +#define BIMC_SNOC_SLV 0 +#define MASTER_JPEG 1 +#define MASTER_MDP_PORT0 2 +#define MASTER_QDSS_BAM 3 +#define MASTER_QDSS_ETR 4 +#define MASTER_SNOC_CFG 5 +#define MASTER_VFE 6 +#define MASTER_VIDEO_P0 7 +#define SNOC_MM_INT_0 8 +#define SNOC_MM_INT_1 9 +#define SNOC_MM_INT_2 10 +#define SNOC_MM_INT_BIMC 11 +#define PCNOC_SNOC_SLV 12 +#define SLAVE_APSS 13 +#define SLAVE_CATS_128 14 +#define SLAVE_OCMEM_64 15 +#define SLAVE_IMEM 16 +#define SLAVE_QDSS_STM 17 +#define SLAVE_SRVC_SNOC 18 +#define SNOC_BIMC_0_MAS 19 +#define SNOC_BIMC_1_MAS 20 +#define SNOC_INT_0 21 +#define SNOC_INT_1 22 +#define SNOC_INT_BIMC 23 +#define SNOC_PCNOC_MAS 24 +#define SNOC_QDSS_INT 25 + +#define BIMC_SNOC_MAS 0 +#define MASTER_AMPSS_M0 1 +#define MASTER_GRAPHICS_3D 2 +#define MASTER_TCU0 3 +#define MASTER_TCU1 4 +#define SLAVE_AMPSS_L2 5 +#define SLAVE_EBI_CH0 6 +#define SNOC_BIMC_0_SLV 7 +#define SNOC_BIMC_1_SLV 8 + +#define MASTER_BLSP_1 0 +#define MASTER_DEHR 1 +#define MASTER_LPASS 2 +#define MASTER_CRYPTO_CORE0 3 +#define MASTER_SDCC_1 4 +#define MASTER_SDCC_2 5 +#define MASTER_SPDM 6 +#define MASTER_USB_HS 7 +#define PCNOC_INT_0 8 +#define PCNOC_INT_1 9 +#define PCNOC_MAS_0 10 +#define PCNOC_MAS_1 11 +#define PCNOC_SLV_0 12 +#define PCNOC_SLV_1 13 +#define PCNOC_SLV_2 14 +#define PCNOC_SLV_3 15 +#define PCNOC_SLV_4 16 +#define PCNOC_SLV_8 17 +#define PCNOC_SLV_9 18 +#define PCNOC_SNOC_MAS 19 +#define SLAVE_BIMC_CFG 20 +#define SLAVE_BLSP_1 21 +#define SLAVE_BOOT_ROM 22 +#define SLAVE_CAMERA_CFG 23 +#define SLAVE_CLK_CTL 24 +#define SLAVE_CRYPTO_0_CFG 25 +#define SLAVE_DEHR_CFG 26 +#define SLAVE_DISPLAY_CFG 27 +#define SLAVE_GRAPHICS_3D_CFG 28 +#define SLAVE_IMEM_CFG 29 +#define SLAVE_LPASS 30 +#define SLAVE_MPM 31 +#define SLAVE_MSG_RAM 32 +#define SLAVE_MSS 33 +#define SLAVE_PDM 34 +#define SLAVE_PMIC_ARB 35 +#define SLAVE_PCNOC_CFG 36 +#define SLAVE_PRNG 37 +#define SLAVE_QDSS_CFG 38 +#define SLAVE_RBCPR_CFG 39 +#define SLAVE_SDCC_1 40 +#define SLAVE_SDCC_2 41 +#define SLAVE_SECURITY 42 +#define SLAVE_SNOC_CFG 43 +#define SLAVE_SPDM 44 +#define SLAVE_TCSR 45 +#define SLAVE_TLMM 46 +#define SLAVE_USB_HS 47 +#define SLAVE_VENUS_CFG 48 +#define SNOC_PCNOC_SLV 49 + +#endif -- cgit v1.2.3 From 89b223bfb8a89731bea4c84982b5d2ad7ba460e3 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 18 Dec 2019 21:45:08 -0500 Subject: selinux: deprecate disabling SELinux and runtime Deprecate the CONFIG_SECURITY_SELINUX_DISABLE functionality. The code was originally developed to make it easier for Linux distributions to support architectures where adding parameters to the kernel command line was difficult. Unfortunately, supporting runtime disable meant we had to make some security trade-offs when it came to the LSM hooks, as documented in the Kconfig help text: NOTE: selecting this option will disable the '__ro_after_init' kernel hardening feature for security hooks. Please consider using the selinux=0 boot parameter instead of enabling this option. Fortunately it looks as if that the original motivation for the runtime disable functionality is gone, and Fedora/RHEL appears to be the only major distribution enabling this capability at build time so we are now taking steps to remove it entirely from the kernel. The first step is to mark the functionality as deprecated and print an error when it is used (what this patch is doing). As Fedora/RHEL makes progress in transitioning the distribution away from runtime disable, we will introduce follow-up patches over several kernel releases which will block for increasing periods of time when the runtime disable is used. Finally we will remove the option entirely once we believe all users have moved to the kernel cmdline approach. Acked-by: Casey Schaufler Acked-by: Ondrej Mosnacek Acked-by: Stephen Smalley Signed-off-by: Paul Moore --- Documentation/ABI/obsolete/sysfs-selinux-disable | 26 ++++++++++++++++++++++++ MAINTAINERS | 1 + security/selinux/Kconfig | 3 +++ security/selinux/selinuxfs.c | 7 +++++++ 4 files changed, 37 insertions(+) create mode 100644 Documentation/ABI/obsolete/sysfs-selinux-disable (limited to 'Documentation') diff --git a/Documentation/ABI/obsolete/sysfs-selinux-disable b/Documentation/ABI/obsolete/sysfs-selinux-disable new file mode 100644 index 000000000000..c340278e3cf8 --- /dev/null +++ b/Documentation/ABI/obsolete/sysfs-selinux-disable @@ -0,0 +1,26 @@ +What: /sys/fs/selinux/disable +Date: April 2005 (predates git) +KernelVersion: 2.6.12-rc2 (predates git) +Contact: selinux@vger.kernel.org +Description: + + The selinuxfs "disable" node allows SELinux to be disabled at runtime + prior to a policy being loaded into the kernel. If disabled via this + mechanism, SELinux will remain disabled until the system is rebooted. + + The preferred method of disabling SELinux is via the "selinux=0" boot + parameter, but the selinuxfs "disable" node was created to make it + easier for systems with primitive bootloaders that did not allow for + easy modification of the kernel command line. Unfortunately, allowing + for SELinux to be disabled at runtime makes it difficult to secure the + kernel's LSM hooks using the "__ro_after_init" feature. + + Thankfully, the need for the SELinux runtime disable appears to be + gone, the default Kconfig configuration disables this selinuxfs node, + and only one of the major distributions, Fedora, supports disabling + SELinux at runtime. Fedora is in the process of removing the + selinuxfs "disable" node and once that is complete we will start the + slow process of removing this code from the kernel. + + More information on /sys/fs/selinux/disable can be found under the + CONFIG_SECURITY_SELINUX_DISABLE Kconfig option. diff --git a/MAINTAINERS b/MAINTAINERS index bd5847e802de..9dc5767861b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14806,6 +14806,7 @@ F: include/uapi/linux/selinux_netlink.h F: security/selinux/ F: scripts/selinux/ F: Documentation/admin-guide/LSM/SELinux.rst +F: Documentation/ABI/obsolete/sysfs-selinux-disable SENSABLE PHANTOM M: Jiri Slaby diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 996d35d950f7..580ac24c7aa1 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -42,6 +42,9 @@ config SECURITY_SELINUX_DISABLE using the selinux=0 boot parameter instead of enabling this option. + WARNING: this option is deprecated and will be removed in a future + kernel release. + If you are unsure how to answer this question, answer N. config SECURITY_SELINUX_DEVELOP diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index d903574f1f0d..79c710911a3c 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -281,6 +281,13 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, int new_value; int enforcing; + /* NOTE: we are now officially considering runtime disable as + * deprecated, and using it will become increasingly painful + * (e.g. sleeping/blocking) as we progress through future + * kernel releases until eventually it is removed + */ + pr_err("SELinux: Runtime disable is deprecated, use selinux=0 on the kernel cmdline.\n"); + if (count >= PAGE_SIZE) return -ENOMEM; -- cgit v1.2.3 From 43f3952a51f8198d365acb7f51fe42d578fe5d0a Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Thu, 19 Dec 2019 17:58:46 +0100 Subject: dm raid: table line rebuild status fixes raid_status() wasn't emitting rebuild flags on the table line properly because the rdev number was not yet set properly; index raid component devices array directly to solve. Also fix wrong argument count on emitted table line caused by 1 too many rebuild/write_mostly argument and consider any journal_(dev|mode) pairs. Link: https://bugzilla.redhat.com/1782045 Signed-off-by: Heinz Mauelshagen Signed-off-by: Mike Snitzer --- .../admin-guide/device-mapper/dm-raid.rst | 2 + drivers/md/dm-raid.c | 43 +++++++++++----------- 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'Documentation') diff --git a/Documentation/admin-guide/device-mapper/dm-raid.rst b/Documentation/admin-guide/device-mapper/dm-raid.rst index f6344675e395..695a2ea1d1ae 100644 --- a/Documentation/admin-guide/device-mapper/dm-raid.rst +++ b/Documentation/admin-guide/device-mapper/dm-raid.rst @@ -419,3 +419,5 @@ Version History rebuild errors. 1.15.0 Fix size extensions not being synchronized in case of new MD bitmap pages allocated; also fix those not occuring after previous reductions + 1.15.1 Fix argument count and arguments for rebuild/write_mostly/journal_(dev|mode) + on the status line. diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index c412eaa975fc..9a18bef0a5ff 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -129,7 +129,9 @@ struct raid_dev { CTR_FLAG_RAID10_COPIES | \ CTR_FLAG_RAID10_FORMAT | \ CTR_FLAG_DELTA_DISKS | \ - CTR_FLAG_DATA_OFFSET) + CTR_FLAG_DATA_OFFSET | \ + CTR_FLAG_JOURNAL_DEV | \ + CTR_FLAG_JOURNAL_MODE) /* Valid options definitions per raid level... */ @@ -3001,7 +3003,6 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv) { 1, 254, "Cannot understand number of raid devices parameters" } }; - /* Must have */ arg = dm_shift_arg(&as); if (!arg) { ti->error = "No arguments"; @@ -3508,8 +3509,7 @@ static void raid_status(struct dm_target *ti, status_type_t type, unsigned long recovery; unsigned int raid_param_cnt = 1; /* at least 1 for chunksize */ unsigned int sz = 0; - unsigned int rebuild_disks; - unsigned int write_mostly_params = 0; + unsigned int rebuild_writemostly_count = 0; sector_t progress, resync_max_sectors, resync_mismatches; enum sync_state state; struct raid_type *rt; @@ -3593,18 +3593,20 @@ static void raid_status(struct dm_target *ti, status_type_t type, case STATUSTYPE_TABLE: /* Report the table line string you would use to construct this raid set */ - /* Calculate raid parameter count */ - for (i = 0; i < rs->raid_disks; i++) - if (test_bit(WriteMostly, &rs->dev[i].rdev.flags)) - write_mostly_params += 2; - rebuild_disks = memweight(rs->rebuild_disks, DISKS_ARRAY_ELEMS * sizeof(*rs->rebuild_disks)); - raid_param_cnt += rebuild_disks * 2 + - write_mostly_params + + /* + * Count any rebuild or writemostly argument pairs and subtract the + * hweight count being added below of any rebuild and writemostly ctr flags. + */ + for (i = 0; i < rs->raid_disks; i++) { + rebuild_writemostly_count += (test_bit(i, (void *) rs->rebuild_disks) ? 2 : 0) + + (test_bit(WriteMostly, &rs->dev[i].rdev.flags) ? 2 : 0); + } + rebuild_writemostly_count -= (test_bit(__CTR_FLAG_REBUILD, &rs->ctr_flags) ? 2 : 0) + + (test_bit(__CTR_FLAG_WRITE_MOSTLY, &rs->ctr_flags) ? 2 : 0); + /* Calculate raid parameter count based on ^ rebuild/writemostly argument counts and ctr flags set. */ + raid_param_cnt += rebuild_writemostly_count + hweight32(rs->ctr_flags & CTR_FLAG_OPTIONS_NO_ARGS) + - hweight32(rs->ctr_flags & CTR_FLAG_OPTIONS_ONE_ARG) * 2 + - (test_bit(__CTR_FLAG_JOURNAL_DEV, &rs->ctr_flags) ? 2 : 0) + - (test_bit(__CTR_FLAG_JOURNAL_MODE, &rs->ctr_flags) ? 2 : 0); - + hweight32(rs->ctr_flags & CTR_FLAG_OPTIONS_ONE_ARG) * 2; /* Emit table line */ /* This has to be in the documented order for userspace! */ DMEMIT("%s %u %u", rs->raid_type->name, raid_param_cnt, mddev->new_chunk_sectors); @@ -3612,11 +3614,10 @@ static void raid_status(struct dm_target *ti, status_type_t type, DMEMIT(" %s", dm_raid_arg_name_by_flag(CTR_FLAG_SYNC)); if (test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags)) DMEMIT(" %s", dm_raid_arg_name_by_flag(CTR_FLAG_NOSYNC)); - if (rebuild_disks) + if (test_bit(__CTR_FLAG_REBUILD, &rs->ctr_flags)) for (i = 0; i < rs->raid_disks; i++) - if (test_bit(rs->dev[i].rdev.raid_disk, (void *) rs->rebuild_disks)) - DMEMIT(" %s %u", dm_raid_arg_name_by_flag(CTR_FLAG_REBUILD), - rs->dev[i].rdev.raid_disk); + if (test_bit(i, (void *) rs->rebuild_disks)) + DMEMIT(" %s %u", dm_raid_arg_name_by_flag(CTR_FLAG_REBUILD), i); if (test_bit(__CTR_FLAG_DAEMON_SLEEP, &rs->ctr_flags)) DMEMIT(" %s %lu", dm_raid_arg_name_by_flag(CTR_FLAG_DAEMON_SLEEP), mddev->bitmap_info.daemon_sleep); @@ -3626,7 +3627,7 @@ static void raid_status(struct dm_target *ti, status_type_t type, if (test_bit(__CTR_FLAG_MAX_RECOVERY_RATE, &rs->ctr_flags)) DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_MAX_RECOVERY_RATE), mddev->sync_speed_max); - if (write_mostly_params) + if (test_bit(__CTR_FLAG_WRITE_MOSTLY, &rs->ctr_flags)) for (i = 0; i < rs->raid_disks; i++) if (test_bit(WriteMostly, &rs->dev[i].rdev.flags)) DMEMIT(" %s %d", dm_raid_arg_name_by_flag(CTR_FLAG_WRITE_MOSTLY), @@ -4029,7 +4030,7 @@ static void raid_resume(struct dm_target *ti) static struct target_type raid_target = { .name = "raid", - .version = {1, 15, 0}, + .version = {1, 15, 1}, .module = THIS_MODULE, .ctr = raid_ctr, .dtr = raid_dtr, -- cgit v1.2.3 From d41415eb5edae2a750940aa24924993b81947040 Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Tue, 7 Jan 2020 11:35:04 -0500 Subject: Documentation,selinux: fix references to old selinuxfs mount point selinuxfs was originally mounted on /selinux, and various docs and kconfig help texts referred to nodes under it. In Linux 3.0, /sys/fs/selinux was introduced as the preferred mount point for selinuxfs. Fix all the old references to /selinux/ to /sys/fs/selinux/. While we are there, update the description of the selinux boot parameter to reflect the fact that the default value is always 1 since commit be6ec88f41ba94 ("selinux: Remove SECURITY_SELINUX_BOOTPARAM_VALUE") and drop discussion of runtime disable since it is deprecated. Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- Documentation/admin-guide/kernel-parameters.txt | 9 ++++----- security/selinux/Kconfig | 7 ++++--- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index ade4e6ec23e0..eed51293d6cf 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -511,7 +511,7 @@ 1 -- check protection requested by application. Default value is set via a kernel config option. Value can be changed at runtime via - /selinux/checkreqprot. + /sys/fs/selinux/checkreqprot. cio_ignore= [S390] See Documentation/s390/common_io.rst for details. @@ -1245,7 +1245,8 @@ 0 -- permissive (log only, no denials). 1 -- enforcing (deny and log). Default value is 0. - Value can be changed at runtime via /selinux/enforce. + Value can be changed at runtime via + /sys/fs/selinux/enforce. erst_disable [ACPI] Disable Error Record Serialization Table (ERST) @@ -4348,9 +4349,7 @@ See security/selinux/Kconfig help text. 0 -- disable. 1 -- enable. - Default value is set via kernel config option. - If enabled at boot time, /selinux/disable can be used - later to disable prior to initial policy load. + Default value is 1. apparmor= [APPARMOR] Disable or enable AppArmor at boot time Format: { "0" | "1" } diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 580ac24c7aa1..1014cb0ee956 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -58,7 +58,8 @@ config SECURITY_SELINUX_DEVELOP kernel will start in permissive mode (log everything, deny nothing) unless you specify enforcing=1 on the kernel command line. You can interactively toggle the kernel between enforcing mode and - permissive mode (if permitted by the policy) via /selinux/enforce. + permissive mode (if permitted by the policy) via + /sys/fs/selinux/enforce. config SECURITY_SELINUX_AVC_STATS bool "NSA SELinux AVC Statistics" @@ -66,7 +67,7 @@ config SECURITY_SELINUX_AVC_STATS default y help This option collects access vector cache statistics to - /selinux/avc/cache_stats, which may be monitored via + /sys/fs/selinux/avc/cache_stats, which may be monitored via tools such as avcstat. config SECURITY_SELINUX_CHECKREQPROT_VALUE @@ -85,7 +86,7 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE default to checking the protection requested by the application. The checkreqprot flag may be changed from the default via the 'checkreqprot=' boot parameter. It may also be changed at runtime - via /selinux/checkreqprot if authorized by policy. + via /sys/fs/selinux/checkreqprot if authorized by policy. If you are unsure how to answer this question, answer 0. -- cgit v1.2.3 From 2ffebffbe7dc8fc966174eedee8fa76cb6143820 Mon Sep 17 00:00:00 2001 From: Jose Abreu Date: Tue, 7 Jan 2020 11:37:19 +0100 Subject: Documentation: networking: Convert stmmac documentation to RST format Convert the documentation of the driver to RST format and delete the old txt and old information that no longer applies. Also, add some new information. Signed-off-by: Jose Abreu Signed-off-by: David S. Miller --- .../networking/device_drivers/stmicro/stmmac.rst | 697 +++++++++++++++++++++ .../networking/device_drivers/stmicro/stmmac.txt | 401 ------------ 2 files changed, 697 insertions(+), 401 deletions(-) create mode 100644 Documentation/networking/device_drivers/stmicro/stmmac.rst delete mode 100644 Documentation/networking/device_drivers/stmicro/stmmac.txt (limited to 'Documentation') diff --git a/Documentation/networking/device_drivers/stmicro/stmmac.rst b/Documentation/networking/device_drivers/stmicro/stmmac.rst new file mode 100644 index 000000000000..c34bab3d2df0 --- /dev/null +++ b/Documentation/networking/device_drivers/stmicro/stmmac.rst @@ -0,0 +1,697 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +============================================================== +Linux Driver for the Synopsys(R) Ethernet Controllers "stmmac" +============================================================== + +Authors: Giuseppe Cavallaro , +Alexandre Torgue , Jose Abreu + +Contents +======== + +- In This Release +- Feature List +- Kernel Configuration +- Command Line Parameters +- Driver Information and Notes +- Debug Information +- Support + +In This Release +=============== + +This file describes the stmmac Linux Driver for all the Synopsys(R) Ethernet +Controllers. + +Currently, this network device driver is for all STi embedded MAC/GMAC +(i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XILINX XC2V3000 +FF1152AMT0221 D1215994A VIRTEX FPGA board. The Synopsys Ethernet QoS 5.0 IPK +is also supported. + +DesignWare(R) Cores Ethernet MAC 10/100/1000 Universal version 3.70a +(and older) and DesignWare(R) Cores Ethernet Quality-of-Service version 4.0 +(and upper) have been used for developing this driver as well as +DesignWare(R) Cores XGMAC - 10G Ethernet MAC. + +This driver supports both the platform bus and PCI. + +This driver includes support for the following Synopsys(R) DesignWare(R) +Cores Ethernet Controllers and corresponding minimum and maximum versions: + ++-------------------------------+--------------+--------------+--------------+ +| Controller Name | Min. Version | Max. Version | Abbrev. Name | ++===============================+==============+==============+==============+ +| Ethernet MAC Universal | N/A | 3.73a | GMAC | ++-------------------------------+--------------+--------------+--------------+ +| Ethernet Quality-of-Service | 4.00a | N/A | GMAC4+ | ++-------------------------------+--------------+--------------+--------------+ +| XGMAC - 10G Ethernet MAC | 2.10a | N/A | XGMAC2+ | ++-------------------------------+--------------+--------------+--------------+ + +For questions related to hardware requirements, refer to the documentation +supplied with your Ethernet adapter. All hardware requirements listed apply +to use with Linux. + +Feature List +============ + +The following features are available in this driver: + - GMII/MII/RGMII/SGMII/RMII/XGMII Interface + - Half-Duplex / Full-Duplex Operation + - Energy Efficient Ethernet (EEE) + - IEEE 802.3x PAUSE Packets (Flow Control) + - RMON/MIB Counters + - IEEE 1588 Timestamping (PTP) + - Pulse-Per-Second Output (PPS) + - MDIO Clause 22 / Clause 45 Interface + - MAC Loopback + - ARP Offloading + - Automatic CRC / PAD Insertion and Checking + - Checksum Offload for Received and Transmitted Packets + - Standard or Jumbo Ethernet Packets + - Source Address Insertion / Replacement + - VLAN TAG Insertion / Replacement / Deletion / Filtering (HASH and PERFECT) + - Programmable TX and RX Watchdog and Coalesce Settings + - Destination Address Filtering (PERFECT) + - HASH Filtering (Multicast) + - Layer 3 / Layer 4 Filtering + - Remote Wake-Up Detection + - Receive Side Scaling (RSS) + - Frame Preemption for TX and RX + - Programmable Burst Length, Threshold, Queue Size + - Multiple Queues (up to 8) + - Multiple Scheduling Algorithms (TX: WRR, DWRR, WFQ, SP, CBS, EST, TBS; + RX: WRR, SP) + - Flexible RX Parser + - TCP / UDP Segmentation Offload (TSO, USO) + - Split Header (SPH) + - Safety Features (ECC Protection, Data Parity Protection) + - Selftests using Ethtool + +Kernel Configuration +==================== + +The kernel configuration option is ``CONFIG_STMMAC_ETH``: + - ``CONFIG_STMMAC_PLATFORM``: is to enable the platform driver. + - ``CONFIG_STMMAC_PCI``: is to enable the pci driver. + +Command Line Parameters +======================= + +If the driver is built as a module the following optional parameters are used +by entering them on the command line with the modprobe command using this +syntax (e.g. for PCI module):: + + modprobe stmmac_pci [