diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 12:10:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 12:10:59 -0500 |
commit | 2bf16b7a73caf3435f782e4170cfe563675e10f9 (patch) | |
tree | 7f4c5b28a02f08c4d6fd69dd43db5872b07c20c4 | |
parent | b9743042b3d31fed271ae19aee79dd86817904f0 (diff) | |
parent | f13d1a8a801dae552ef495c84a223280586a9f67 (diff) |
Merge tag 'char-misc-4.15-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc updates from Greg KH:
"Here is the big set of char/misc and other driver subsystem patches
for 4.15-rc1.
There are small changes all over here, hyperv driver updates, pcmcia
driver updates, w1 driver updats, vme driver updates, nvmem driver
updates, and lots of other little one-off driver updates as well. The
shortlog has the full details.
All of these have been in linux-next for quite a while with no
reported issues"
* tag 'char-misc-4.15-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (90 commits)
VME: Return -EBUSY when DMA list in use
w1: keep balance of mutex locks and refcnts
MAINTAINERS: Update VME subsystem tree.
nvmem: sunxi-sid: add support for A64/H5's SID controller
nvmem: imx-ocotp: Update module description
nvmem: imx-ocotp: Enable i.MX7D OTP write support
nvmem: imx-ocotp: Add i.MX7D timing write clock setup support
nvmem: imx-ocotp: Move i.MX6 write clock setup to dedicated function
nvmem: imx-ocotp: Add support for banked OTP addressing
nvmem: imx-ocotp: Pass parameters via a struct
nvmem: imx-ocotp: Restrict OTP write to IMX6 processors
nvmem: uniphier: add UniPhier eFuse driver
dt-bindings: nvmem: add description for UniPhier eFuse
nvmem: set nvmem->owner to nvmem->dev->driver->owner if unset
nvmem: qfprom: fix different address space warnings of sparse
nvmem: mtk-efuse: fix different address space warnings of sparse
nvmem: mtk-efuse: use stack for nvmem_config instead of malloc'ing it
nvmem: imx-iim: use stack for nvmem_config instead of malloc'ing it
thunderbolt: tb: fix use after free in tb_activate_pcie_devices
MAINTAINERS: Add git tree for Thunderbolt development
...
79 files changed, 2770 insertions, 517 deletions
diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus index 5d0125f7bcaf..d4077cc60d55 100644 --- a/Documentation/ABI/stable/sysfs-bus-vmbus +++ b/Documentation/ABI/stable/sysfs-bus-vmbus | |||
@@ -41,3 +41,73 @@ KernelVersion: 4.5 | |||
41 | Contact: K. Y. Srinivasan <kys@microsoft.com> | 41 | Contact: K. Y. Srinivasan <kys@microsoft.com> |
42 | Description: The 16 bit vendor ID of the device | 42 | Description: The 16 bit vendor ID of the device |
43 | Users: tools/hv/lsvmbus and user level RDMA libraries | 43 | Users: tools/hv/lsvmbus and user level RDMA libraries |
44 | |||
45 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/cpu | ||
46 | Date: September. 2017 | ||
47 | KernelVersion: 4.14 | ||
48 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
49 | Description: VCPU (sub)channel is affinitized to | ||
50 | Users: tools/hv/lsvmbus and other debuggig tools | ||
51 | |||
52 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/cpu | ||
53 | Date: September. 2017 | ||
54 | KernelVersion: 4.14 | ||
55 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
56 | Description: VCPU (sub)channel is affinitized to | ||
57 | Users: tools/hv/lsvmbus and other debuggig tools | ||
58 | |||
59 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/in_mask | ||
60 | Date: September. 2017 | ||
61 | KernelVersion: 4.14 | ||
62 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
63 | Description: Inbound channel signaling state | ||
64 | Users: Debugging tools | ||
65 | |||
66 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/latency | ||
67 | Date: September. 2017 | ||
68 | KernelVersion: 4.14 | ||
69 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
70 | Description: Channel signaling latency | ||
71 | Users: Debugging tools | ||
72 | |||
73 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/out_mask | ||
74 | Date: September. 2017 | ||
75 | KernelVersion: 4.14 | ||
76 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
77 | Description: Outbound channel signaling state | ||
78 | Users: Debugging tools | ||
79 | |||
80 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/pending | ||
81 | Date: September. 2017 | ||
82 | KernelVersion: 4.14 | ||
83 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
84 | Description: Channel interrupt pending state | ||
85 | Users: Debugging tools | ||
86 | |||
87 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/read_avail | ||
88 | Date: September. 2017 | ||
89 | KernelVersion: 4.14 | ||
90 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
91 | Description: Bytes availabble to read | ||
92 | Users: Debugging tools | ||
93 | |||
94 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/write_avail | ||
95 | Date: September. 2017 | ||
96 | KernelVersion: 4.14 | ||
97 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
98 | Description: Bytes availabble to write | ||
99 | Users: Debugging tools | ||
100 | |||
101 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/events | ||
102 | Date: September. 2017 | ||
103 | KernelVersion: 4.14 | ||
104 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
105 | Description: Number of times we have signaled the host | ||
106 | Users: Debugging tools | ||
107 | |||
108 | What: /sys/bus/vmbus/devices/vmbus_*/channels/relid/interrupts | ||
109 | Date: September. 2017 | ||
110 | KernelVersion: 4.14 | ||
111 | Contact: Stephen Hemminger <sthemmin@microsoft.com> | ||
112 | Description: Number of times we have taken an interrupt (incoming) | ||
113 | Users: Debugging tools | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-w1_ds28e17 b/Documentation/ABI/testing/sysfs-driver-w1_ds28e17 new file mode 100644 index 000000000000..d301e7017afe --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-w1_ds28e17 | |||
@@ -0,0 +1,21 @@ | |||
1 | What: /sys/bus/w1/devices/19-<id>/speed | ||
2 | Date: Sep 2017 | ||
3 | KernelVersion: 4.14 | ||
4 | Contact: Jan Kandziora <jjj@gmx.de> | ||
5 | Description: When written, this file sets the I2C speed on the connected | ||
6 | DS28E17 chip. When read, it reads the current setting from | ||
7 | the DS28E17 chip. | ||
8 | Valid values: 100, 400, 900 [kBaud]. | ||
9 | Default 100, can be set by w1_ds28e17.speed= module parameter. | ||
10 | Users: w1_ds28e17 driver | ||
11 | |||
12 | What: /sys/bus/w1/devices/19-<id>/stretch | ||
13 | Date: Sep 2017 | ||
14 | KernelVersion: 4.14 | ||
15 | Contact: Jan Kandziora <jjj@gmx.de> | ||
16 | Description: When written, this file sets the multiplier used to calculate | ||
17 | the busy timeout for I2C operations on the connected DS28E17 | ||
18 | chip. When read, returns the current setting. | ||
19 | Valid values: 1 to 9. | ||
20 | Default 1, can be set by w1_ds28e17.stretch= module parameter. | ||
21 | Users: w1_ds28e17 driver | ||
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt index 081c49c0dac0..d69543701d5d 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt | |||
@@ -5,6 +5,7 @@ Required properties: | |||
5 | "allwinner,sun4i-a10-sid" | 5 | "allwinner,sun4i-a10-sid" |
6 | "allwinner,sun7i-a20-sid" | 6 | "allwinner,sun7i-a20-sid" |
7 | "allwinner,sun8i-h3-sid" | 7 | "allwinner,sun8i-h3-sid" |
8 | "allwinner,sun50i-a64-sid" | ||
8 | 9 | ||
9 | - reg: Should contain registers location and length | 10 | - reg: Should contain registers location and length |
10 | 11 | ||
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt index fafd85bd67a6..e3298e18de26 100644 --- a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt +++ b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | = Amlogic eFuse device tree bindings = | 1 | = Amlogic Meson GX eFuse device tree bindings = |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: should be "amlogic,meson-gxbb-efuse" | 4 | - compatible: should be "amlogic,meson-gxbb-efuse" |
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt b/Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt new file mode 100644 index 000000000000..a3c63954a1a4 --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt | |||
@@ -0,0 +1,22 @@ | |||
1 | Amlogic Meson6/Meson8/Meson8b efuse | ||
2 | |||
3 | Required Properties: | ||
4 | - compatible: depending on the SoC this should be one of: | ||
5 | - "amlogic,meson6-efuse" | ||
6 | - "amlogic,meson8-efuse" | ||
7 | - "amlogic,meson8b-efuse" | ||
8 | - reg: base address and size of the efuse registers | ||
9 | - clocks: a reference to the efuse core gate clock | ||
10 | - clock-names: must be "core" | ||
11 | |||
12 | All properties and sub-nodes as well as the consumer bindings | ||
13 | defined in nvmem.txt in this directory are also supported. | ||
14 | |||
15 | |||
16 | Example: | ||
17 | efuse: nvmem@0 { | ||
18 | compatible = "amlogic,meson8-efuse"; | ||
19 | reg = <0x0 0x2000>; | ||
20 | clocks = <&clkc CLKID_EFUSE>; | ||
21 | clock-names = "core"; | ||
22 | }; | ||
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt index 1ff02afdc55a..60bec4782806 100644 --- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt +++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.txt | |||
@@ -6,6 +6,7 @@ Required properties: | |||
6 | - "rockchip,rk3188-efuse" - for RK3188 SoCs. | 6 | - "rockchip,rk3188-efuse" - for RK3188 SoCs. |
7 | - "rockchip,rk3228-efuse" - for RK3228 SoCs. | 7 | - "rockchip,rk3228-efuse" - for RK3228 SoCs. |
8 | - "rockchip,rk3288-efuse" - for RK3288 SoCs. | 8 | - "rockchip,rk3288-efuse" - for RK3288 SoCs. |
9 | - "rockchip,rk3368-efuse" - for RK3368 SoCs. | ||
9 | - "rockchip,rk3399-efuse" - for RK3399 SoCs. | 10 | - "rockchip,rk3399-efuse" - for RK3399 SoCs. |
10 | - reg: Should contain the registers location and exact eFuse size | 11 | - reg: Should contain the registers location and exact eFuse size |
11 | - clocks: Should be the clock id of eFuse | 12 | - clocks: Should be the clock id of eFuse |
diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt new file mode 100644 index 000000000000..20bc49b49799 --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.txt | |||
@@ -0,0 +1,20 @@ | |||
1 | Device tree bindings for Low Power General Purpose Register found in i.MX6Q/D | ||
2 | Secure Non-Volatile Storage. | ||
3 | |||
4 | This DT node should be represented as a sub-node of a "syscon", | ||
5 | "simple-mfd" node. | ||
6 | |||
7 | Required properties: | ||
8 | - compatible: should be one of the fallowing variants: | ||
9 | "fsl,imx6q-snvs-lpgpr" for Freescale i.MX6Q/D/DL/S | ||
10 | "fsl,imx6ul-snvs-lpgpr" for Freescale i.MX6UL | ||
11 | |||
12 | Example: | ||
13 | snvs: snvs@020cc000 { | ||
14 | compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd"; | ||
15 | reg = <0x020cc000 0x4000>; | ||
16 | |||
17 | snvs_lpgpr: snvs-lpgpr { | ||
18 | compatible = "fsl,imx6q-snvs-lpgpr"; | ||
19 | }; | ||
20 | }; | ||
diff --git a/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt new file mode 100644 index 000000000000..eccf490d5a6d --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt | |||
@@ -0,0 +1,49 @@ | |||
1 | = UniPhier eFuse device tree bindings = | ||
2 | |||
3 | This UniPhier eFuse must be under soc-glue. | ||
4 | |||
5 | Required properties: | ||
6 | - compatible: should be "socionext,uniphier-efuse" | ||
7 | - reg: should contain the register location and length | ||
8 | |||
9 | = Data cells = | ||
10 | Are child nodes of efuse, bindings of which as described in | ||
11 | bindings/nvmem/nvmem.txt | ||
12 | |||
13 | Example: | ||
14 | |||
15 | soc-glue@5f900000 { | ||
16 | compatible = "socionext,uniphier-ld20-soc-glue-debug", | ||
17 | "simple-mfd"; | ||
18 | #address-cells = <1>; | ||
19 | #size-cells = <1>; | ||
20 | ranges = <0x0 0x5f900000 0x2000>; | ||
21 | |||
22 | efuse@100 { | ||
23 | compatible = "socionext,uniphier-efuse"; | ||
24 | reg = <0x100 0x28>; | ||
25 | }; | ||
26 | |||
27 | efuse@200 { | ||
28 | compatible = "socionext,uniphier-efuse"; | ||
29 | reg = <0x200 0x68>; | ||
30 | #address-cells = <1>; | ||
31 | #size-cells = <1>; | ||
32 | |||
33 | /* Data cells */ | ||
34 | usb_mon: usb-mon@54 { | ||
35 | reg = <0x54 0xc>; | ||
36 | }; | ||
37 | }; | ||
38 | }; | ||
39 | |||
40 | = Data consumers = | ||
41 | Are device nodes which consume nvmem data cells. | ||
42 | |||
43 | Example: | ||
44 | |||
45 | usb { | ||
46 | ... | ||
47 | nvmem-cells = <&usb_mon>; | ||
48 | nvmem-cell-names = "usb_mon"; | ||
49 | } | ||
diff --git a/Documentation/trace/coresight-cpu-debug.txt b/Documentation/trace/coresight-cpu-debug.txt index b3da1f90b861..2b9b51cd501e 100644 --- a/Documentation/trace/coresight-cpu-debug.txt +++ b/Documentation/trace/coresight-cpu-debug.txt | |||
@@ -149,11 +149,23 @@ If you want to limit idle states at boot time, you can use "nohlt" or | |||
149 | 149 | ||
150 | At the runtime you can disable idle states with below methods: | 150 | At the runtime you can disable idle states with below methods: |
151 | 151 | ||
152 | Set latency request to /dev/cpu_dma_latency to disable all CPUs specific idle | 152 | It is possible to disable CPU idle states by way of the PM QoS |
153 | states (if latency = 0uS then disable all idle states): | 153 | subsystem, more specifically by using the "/dev/cpu_dma_latency" |
154 | # echo "what_ever_latency_you_need_in_uS" > /dev/cpu_dma_latency | 154 | interface (see Documentation/power/pm_qos_interface.txt for more |
155 | 155 | details). As specified in the PM QoS documentation the requested | |
156 | Disable specific CPU's specific idle state: | 156 | parameter will stay in effect until the file descriptor is released. |
157 | For example: | ||
158 | |||
159 | # exec 3<> /dev/cpu_dma_latency; echo 0 >&3 | ||
160 | ... | ||
161 | Do some work... | ||
162 | ... | ||
163 | # exec 3<>- | ||
164 | |||
165 | The same can also be done from an application program. | ||
166 | |||
167 | Disable specific CPU's specific idle state from cpuidle sysfs (see | ||
168 | Documentation/cpuidle/sysfs.txt): | ||
157 | # echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable | 169 | # echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable |
158 | 170 | ||
159 | 171 | ||
diff --git a/Documentation/w1/slaves/00-INDEX b/Documentation/w1/slaves/00-INDEX index 8d76718e1ea2..68946f83e579 100644 --- a/Documentation/w1/slaves/00-INDEX +++ b/Documentation/w1/slaves/00-INDEX | |||
@@ -10,3 +10,5 @@ w1_ds2438 | |||
10 | - The Maxim/Dallas Semiconductor ds2438 smart battery monitor. | 10 | - The Maxim/Dallas Semiconductor ds2438 smart battery monitor. |
11 | w1_ds28e04 | 11 | w1_ds28e04 |
12 | - The Maxim/Dallas Semiconductor ds28e04 eeprom. | 12 | - The Maxim/Dallas Semiconductor ds28e04 eeprom. |
13 | w1_ds28e17 | ||
14 | - The Maxim/Dallas Semiconductor ds28e17 1-Wire-to-I2C Master Bridge. | ||
diff --git a/Documentation/w1/slaves/w1_ds28e17 b/Documentation/w1/slaves/w1_ds28e17 new file mode 100644 index 000000000000..7fcfad5b4a37 --- /dev/null +++ b/Documentation/w1/slaves/w1_ds28e17 | |||
@@ -0,0 +1,68 @@ | |||
1 | Kernel driver w1_ds28e17 | ||
2 | ======================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Maxim DS28E17 1-Wire-to-I2C Master Bridge | ||
6 | |||
7 | supported family codes: | ||
8 | W1_FAMILY_DS28E17 0x19 | ||
9 | |||
10 | Author: Jan Kandziora <jjj@gmx.de> | ||
11 | |||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | The DS28E17 is a Onewire slave device which acts as an I2C bus master. | ||
16 | |||
17 | This driver creates a new I2C bus for any DS28E17 device detected. I2C buses | ||
18 | come and go as the DS28E17 devices come and go. I2C slave devices connected to | ||
19 | a DS28E17 can be accessed by the kernel or userspace tools as if they were | ||
20 | connected to a "native" I2C bus master. | ||
21 | |||
22 | |||
23 | An udev rule like the following | ||
24 | ------------------------------------------------------------------------------- | ||
25 | SUBSYSTEM=="i2c-dev", KERNEL=="i2c-[0-9]*", ATTRS{name}=="w1-19-*", \ | ||
26 | SYMLINK+="i2c-$attr{name}" | ||
27 | ------------------------------------------------------------------------------- | ||
28 | may be used to create stable /dev/i2c- entries based on the unique id of the | ||
29 | DS28E17 chip. | ||
30 | |||
31 | |||
32 | Driver parameters are: | ||
33 | |||
34 | speed: | ||
35 | This sets up the default I2C speed a DS28E17 get configured for as soon | ||
36 | it is connected. The power-on default of the DS28E17 is 400kBaud, but | ||
37 | chips may come and go on the Onewire bus without being de-powered and | ||
38 | as soon the "w1_ds28e17" driver notices a freshly connected, or | ||
39 | reconnected DS28E17 device on the Onewire bus, it will re-apply this | ||
40 | setting. | ||
41 | |||
42 | Valid values are 100, 400, 900 [kBaud]. Any other value means to leave | ||
43 | alone the current DS28E17 setting on detect. The default value is 100. | ||
44 | |||
45 | stretch: | ||
46 | This sets up the default stretch value used for freshly connected | ||
47 | DS28E17 devices. It is a multiplier used on the calculation of the busy | ||
48 | wait time for an I2C transfer. This is to account for I2C slave devices | ||
49 | which make heavy use of the I2C clock stretching feature and thus, the | ||
50 | needed timeout cannot be pre-calculated correctly. As the w1_ds28e17 | ||
51 | driver checks the DS28E17's busy flag in a loop after the precalculated | ||
52 | wait time, it should be hardly needed to tweak this setting. | ||
53 | |||
54 | Leave it at 1 unless you get ETIMEDOUT errors and a "w1_slave_driver | ||
55 | 19-00000002dbd8: busy timeout" in the kernel log. | ||
56 | |||
57 | Valid values are 1 to 9. The default is 1. | ||
58 | |||
59 | |||
60 | The driver creates sysfs files /sys/bus/w1/devices/19-<id>/speed and | ||
61 | /sys/bus/w1/devices/19-<id>/stretch for each device, preloaded with the default | ||
62 | settings from the driver parameters. They may be changed anytime. In addition a | ||
63 | directory /sys/bus/w1/devices/19-<id>/i2c-<nnn> for the I2C bus master sysfs | ||
64 | structure is created. | ||
65 | |||
66 | |||
67 | See https://github.com/ianka/w1_ds28e17 for even more information. | ||
68 | |||
diff --git a/MAINTAINERS b/MAINTAINERS index d32726746a88..7f9c4f3fc941 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5474,7 +5474,7 @@ K: fmc_d.*register | |||
5474 | 5474 | ||
5475 | FPGA MANAGER FRAMEWORK | 5475 | FPGA MANAGER FRAMEWORK |
5476 | M: Alan Tull <atull@kernel.org> | 5476 | M: Alan Tull <atull@kernel.org> |
5477 | R: Moritz Fischer <mdf@kernel.org> | 5477 | M: Moritz Fischer <mdf@kernel.org> |
5478 | L: linux-fpga@vger.kernel.org | 5478 | L: linux-fpga@vger.kernel.org |
5479 | S: Maintained | 5479 | S: Maintained |
5480 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git | 5480 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/atull/linux-fpga.git |
@@ -13390,6 +13390,7 @@ M: Andreas Noever <andreas.noever@gmail.com> | |||
13390 | M: Michael Jamet <michael.jamet@intel.com> | 13390 | M: Michael Jamet <michael.jamet@intel.com> |
13391 | M: Mika Westerberg <mika.westerberg@linux.intel.com> | 13391 | M: Mika Westerberg <mika.westerberg@linux.intel.com> |
13392 | M: Yehezkel Bernat <yehezkel.bernat@intel.com> | 13392 | M: Yehezkel Bernat <yehezkel.bernat@intel.com> |
13393 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git | ||
13393 | S: Maintained | 13394 | S: Maintained |
13394 | F: drivers/thunderbolt/ | 13395 | F: drivers/thunderbolt/ |
13395 | F: include/linux/thunderbolt.h | 13396 | F: include/linux/thunderbolt.h |
@@ -14485,7 +14486,7 @@ M: Manohar Vanga <manohar.vanga@gmail.com> | |||
14485 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 14486 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
14486 | L: devel@driverdev.osuosl.org | 14487 | L: devel@driverdev.osuosl.org |
14487 | S: Maintained | 14488 | S: Maintained |
14488 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git | 14489 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git |
14489 | F: Documentation/driver-api/vme.rst | 14490 | F: Documentation/driver-api/vme.rst |
14490 | F: drivers/staging/vme/ | 14491 | F: drivers/staging/vme/ |
14491 | F: drivers/vme/ | 14492 | F: drivers/vme/ |
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index a0b86cf486e0..189a398290db 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c | |||
@@ -210,9 +210,10 @@ void hyperv_cleanup(void) | |||
210 | } | 210 | } |
211 | EXPORT_SYMBOL_GPL(hyperv_cleanup); | 211 | EXPORT_SYMBOL_GPL(hyperv_cleanup); |
212 | 212 | ||
213 | void hyperv_report_panic(struct pt_regs *regs) | 213 | void hyperv_report_panic(struct pt_regs *regs, long err) |
214 | { | 214 | { |
215 | static bool panic_reported; | 215 | static bool panic_reported; |
216 | u64 guest_id; | ||
216 | 217 | ||
217 | /* | 218 | /* |
218 | * We prefer to report panic on 'die' chain as we have proper | 219 | * We prefer to report panic on 'die' chain as we have proper |
@@ -223,11 +224,13 @@ void hyperv_report_panic(struct pt_regs *regs) | |||
223 | return; | 224 | return; |
224 | panic_reported = true; | 225 | panic_reported = true; |
225 | 226 | ||
226 | wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip); | 227 | rdmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id); |
227 | wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax); | 228 | |
228 | wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx); | 229 | wrmsrl(HV_X64_MSR_CRASH_P0, err); |
229 | wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx); | 230 | wrmsrl(HV_X64_MSR_CRASH_P1, guest_id); |
230 | wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx); | 231 | wrmsrl(HV_X64_MSR_CRASH_P2, regs->ip); |
232 | wrmsrl(HV_X64_MSR_CRASH_P3, regs->ax); | ||
233 | wrmsrl(HV_X64_MSR_CRASH_P4, regs->sp); | ||
231 | 234 | ||
232 | /* | 235 | /* |
233 | * Let Hyper-V know there is crash data available | 236 | * Let Hyper-V know there is crash data available |
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 581bb54dd464..5400add2885b 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h | |||
@@ -311,7 +311,7 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number) | |||
311 | void hyperv_init(void); | 311 | void hyperv_init(void); |
312 | void hyperv_setup_mmu_ops(void); | 312 | void hyperv_setup_mmu_ops(void); |
313 | void hyper_alloc_mmu(void); | 313 | void hyper_alloc_mmu(void); |
314 | void hyperv_report_panic(struct pt_regs *regs); | 314 | void hyperv_report_panic(struct pt_regs *regs, long err); |
315 | bool hv_is_hypercall_page_setup(void); | 315 | bool hv_is_hypercall_page_setup(void); |
316 | void hyperv_cleanup(void); | 316 | void hyperv_cleanup(void); |
317 | #else /* CONFIG_HYPERV */ | 317 | #else /* CONFIG_HYPERV */ |
diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 7255f94ded30..a73596a4f804 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c | |||
@@ -2192,7 +2192,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, | |||
2192 | off_start, | 2192 | off_start, |
2193 | offp - off_start); | 2193 | offp - off_start); |
2194 | if (!parent) { | 2194 | if (!parent) { |
2195 | pr_err("transaction release %d bad parent offset", | 2195 | pr_err("transaction release %d bad parent offset\n", |
2196 | debug_id); | 2196 | debug_id); |
2197 | continue; | 2197 | continue; |
2198 | } | 2198 | } |
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index c2819a3d58a6..6f6f745605af 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c | |||
@@ -186,12 +186,12 @@ struct binder_buffer *binder_alloc_prepare_to_free(struct binder_alloc *alloc, | |||
186 | } | 186 | } |
187 | 187 | ||
188 | static int binder_update_page_range(struct binder_alloc *alloc, int allocate, | 188 | static int binder_update_page_range(struct binder_alloc *alloc, int allocate, |
189 | void *start, void *end, | 189 | void *start, void *end) |
190 | struct vm_area_struct *vma) | ||
191 | { | 190 | { |
192 | void *page_addr; | 191 | void *page_addr; |
193 | unsigned long user_page_addr; | 192 | unsigned long user_page_addr; |
194 | struct binder_lru_page *page; | 193 | struct binder_lru_page *page; |
194 | struct vm_area_struct *vma = NULL; | ||
195 | struct mm_struct *mm = NULL; | 195 | struct mm_struct *mm = NULL; |
196 | bool need_mm = false; | 196 | bool need_mm = false; |
197 | 197 | ||
@@ -215,7 +215,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, | |||
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | if (!vma && need_mm && mmget_not_zero(alloc->vma_vm_mm)) | 218 | if (need_mm && mmget_not_zero(alloc->vma_vm_mm)) |
219 | mm = alloc->vma_vm_mm; | 219 | mm = alloc->vma_vm_mm; |
220 | 220 | ||
221 | if (mm) { | 221 | if (mm) { |
@@ -437,7 +437,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, | |||
437 | if (end_page_addr > has_page_addr) | 437 | if (end_page_addr > has_page_addr) |
438 | end_page_addr = has_page_addr; | 438 | end_page_addr = has_page_addr; |
439 | ret = binder_update_page_range(alloc, 1, | 439 | ret = binder_update_page_range(alloc, 1, |
440 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr, NULL); | 440 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), end_page_addr); |
441 | if (ret) | 441 | if (ret) |
442 | return ERR_PTR(ret); | 442 | return ERR_PTR(ret); |
443 | 443 | ||
@@ -478,7 +478,7 @@ struct binder_buffer *binder_alloc_new_buf_locked(struct binder_alloc *alloc, | |||
478 | err_alloc_buf_struct_failed: | 478 | err_alloc_buf_struct_failed: |
479 | binder_update_page_range(alloc, 0, | 479 | binder_update_page_range(alloc, 0, |
480 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), | 480 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), |
481 | end_page_addr, NULL); | 481 | end_page_addr); |
482 | return ERR_PTR(-ENOMEM); | 482 | return ERR_PTR(-ENOMEM); |
483 | } | 483 | } |
484 | 484 | ||
@@ -562,8 +562,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, | |||
562 | alloc->pid, buffer->data, | 562 | alloc->pid, buffer->data, |
563 | prev->data, next ? next->data : NULL); | 563 | prev->data, next ? next->data : NULL); |
564 | binder_update_page_range(alloc, 0, buffer_start_page(buffer), | 564 | binder_update_page_range(alloc, 0, buffer_start_page(buffer), |
565 | buffer_start_page(buffer) + PAGE_SIZE, | 565 | buffer_start_page(buffer) + PAGE_SIZE); |
566 | NULL); | ||
567 | } | 566 | } |
568 | list_del(&buffer->entry); | 567 | list_del(&buffer->entry); |
569 | kfree(buffer); | 568 | kfree(buffer); |
@@ -600,8 +599,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc, | |||
600 | 599 | ||
601 | binder_update_page_range(alloc, 0, | 600 | binder_update_page_range(alloc, 0, |
602 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), | 601 | (void *)PAGE_ALIGN((uintptr_t)buffer->data), |
603 | (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK), | 602 | (void *)(((uintptr_t)buffer->data + buffer_size) & PAGE_MASK)); |
604 | NULL); | ||
605 | 603 | ||
606 | rb_erase(&buffer->rb_node, &alloc->allocated_buffers); | 604 | rb_erase(&buffer->rb_node, &alloc->allocated_buffers); |
607 | buffer->free = 1; | 605 | buffer->free = 1; |
@@ -984,7 +982,7 @@ binder_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) | |||
984 | return ret; | 982 | return ret; |
985 | } | 983 | } |
986 | 984 | ||
987 | struct shrinker binder_shrinker = { | 985 | static struct shrinker binder_shrinker = { |
988 | .count_objects = binder_shrink_count, | 986 | .count_objects = binder_shrink_count, |
989 | .scan_objects = binder_shrink_scan, | 987 | .scan_objects = binder_shrink_scan, |
990 | .seeks = DEFAULT_SEEKS, | 988 | .seeks = DEFAULT_SEEKS, |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index cd53771b9ae7..370e0a64ead1 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -659,9 +659,9 @@ static void terminate_monitor(struct cm4000_dev *dev) | |||
659 | * is already doing that for you. | 659 | * is already doing that for you. |
660 | */ | 660 | */ |
661 | 661 | ||
662 | static void monitor_card(unsigned long p) | 662 | static void monitor_card(struct timer_list *t) |
663 | { | 663 | { |
664 | struct cm4000_dev *dev = (struct cm4000_dev *) p; | 664 | struct cm4000_dev *dev = from_timer(dev, t, timer); |
665 | unsigned int iobase = dev->p_dev->resource[0]->start; | 665 | unsigned int iobase = dev->p_dev->resource[0]->start; |
666 | unsigned short s; | 666 | unsigned short s; |
667 | struct ptsreq ptsreq; | 667 | struct ptsreq ptsreq; |
@@ -1374,7 +1374,7 @@ static void start_monitor(struct cm4000_dev *dev) | |||
1374 | DEBUGP(3, dev, "-> start_monitor\n"); | 1374 | DEBUGP(3, dev, "-> start_monitor\n"); |
1375 | if (!dev->monitor_running) { | 1375 | if (!dev->monitor_running) { |
1376 | DEBUGP(5, dev, "create, init and add timer\n"); | 1376 | DEBUGP(5, dev, "create, init and add timer\n"); |
1377 | setup_timer(&dev->timer, monitor_card, (unsigned long)dev); | 1377 | timer_setup(&dev->timer, monitor_card, 0); |
1378 | dev->monitor_running = 1; | 1378 | dev->monitor_running = 1; |
1379 | mod_timer(&dev->timer, jiffies); | 1379 | mod_timer(&dev->timer, jiffies); |
1380 | } else | 1380 | } else |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 382c864814d9..9a1aaf538758 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -104,9 +104,9 @@ static inline unsigned char xinb(unsigned short port) | |||
104 | 104 | ||
105 | /* poll the device fifo status register. not to be confused with | 105 | /* poll the device fifo status register. not to be confused with |
106 | * the poll syscall. */ | 106 | * the poll syscall. */ |
107 | static void cm4040_do_poll(unsigned long dummy) | 107 | static void cm4040_do_poll(struct timer_list *t) |
108 | { | 108 | { |
109 | struct reader_dev *dev = (struct reader_dev *) dummy; | 109 | struct reader_dev *dev = from_timer(dev, t, poll_timer); |
110 | unsigned int obs = xinb(dev->p_dev->resource[0]->start | 110 | unsigned int obs = xinb(dev->p_dev->resource[0]->start |
111 | + REG_OFFSET_BUFFER_STATUS); | 111 | + REG_OFFSET_BUFFER_STATUS); |
112 | 112 | ||
@@ -465,7 +465,6 @@ static int cm4040_open(struct inode *inode, struct file *filp) | |||
465 | 465 | ||
466 | link->open = 1; | 466 | link->open = 1; |
467 | 467 | ||
468 | dev->poll_timer.data = (unsigned long) dev; | ||
469 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); | 468 | mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); |
470 | 469 | ||
471 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); | 470 | DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); |
@@ -585,7 +584,7 @@ static int reader_probe(struct pcmcia_device *link) | |||
585 | init_waitqueue_head(&dev->poll_wait); | 584 | init_waitqueue_head(&dev->poll_wait); |
586 | init_waitqueue_head(&dev->read_wait); | 585 | init_waitqueue_head(&dev->read_wait); |
587 | init_waitqueue_head(&dev->write_wait); | 586 | init_waitqueue_head(&dev->write_wait); |
588 | setup_timer(&dev->poll_timer, cm4040_do_poll, 0); | 587 | timer_setup(&dev->poll_timer, cm4040_do_poll, 0); |
589 | 588 | ||
590 | ret = reader_config(link, i); | 589 | ret = reader_config(link, i); |
591 | if (ret) { | 590 | if (ret) { |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 62be953e5fb0..aa502e9fb7fa 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -375,7 +375,7 @@ static void reset_device(MGSLPC_INFO *info); | |||
375 | static void hdlc_mode(MGSLPC_INFO *info); | 375 | static void hdlc_mode(MGSLPC_INFO *info); |
376 | static void async_mode(MGSLPC_INFO *info); | 376 | static void async_mode(MGSLPC_INFO *info); |
377 | 377 | ||
378 | static void tx_timeout(unsigned long context); | 378 | static void tx_timeout(struct timer_list *t); |
379 | 379 | ||
380 | static int carrier_raised(struct tty_port *port); | 380 | static int carrier_raised(struct tty_port *port); |
381 | static void dtr_rts(struct tty_port *port, int onoff); | 381 | static void dtr_rts(struct tty_port *port, int onoff); |
@@ -1289,7 +1289,7 @@ static int startup(MGSLPC_INFO * info, struct tty_struct *tty) | |||
1289 | 1289 | ||
1290 | memset(&info->icount, 0, sizeof(info->icount)); | 1290 | memset(&info->icount, 0, sizeof(info->icount)); |
1291 | 1291 | ||
1292 | setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info); | 1292 | timer_setup(&info->tx_timer, tx_timeout, 0); |
1293 | 1293 | ||
1294 | /* Allocate and claim adapter resources */ | 1294 | /* Allocate and claim adapter resources */ |
1295 | retval = claim_resources(info); | 1295 | retval = claim_resources(info); |
@@ -3846,9 +3846,9 @@ static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit) | |||
3846 | /* HDLC frame time out | 3846 | /* HDLC frame time out |
3847 | * update stats and do tx completion processing | 3847 | * update stats and do tx completion processing |
3848 | */ | 3848 | */ |
3849 | static void tx_timeout(unsigned long context) | 3849 | static void tx_timeout(struct timer_list *t) |
3850 | { | 3850 | { |
3851 | MGSLPC_INFO *info = (MGSLPC_INFO*)context; | 3851 | MGSLPC_INFO *info = from_timer(info, t, tx_timer); |
3852 | unsigned long flags; | 3852 | unsigned long flags; |
3853 | 3853 | ||
3854 | if (debug_level >= DEBUG_LEVEL_INFO) | 3854 | if (debug_level >= DEBUG_LEVEL_INFO) |
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c index e359930bebc8..0d7743089414 100644 --- a/drivers/fpga/xilinx-pr-decoupler.c +++ b/drivers/fpga/xilinx-pr-decoupler.c | |||
@@ -79,7 +79,7 @@ static int xlnx_pr_decoupler_enable_show(struct fpga_bridge *bridge) | |||
79 | return !status; | 79 | return !status; |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = { | 82 | static const struct fpga_bridge_ops xlnx_pr_decoupler_br_ops = { |
83 | .enable_set = xlnx_pr_decoupler_enable_set, | 83 | .enable_set = xlnx_pr_decoupler_enable_set, |
84 | .enable_show = xlnx_pr_decoupler_enable_show, | 84 | .enable_show = xlnx_pr_decoupler_enable_show, |
85 | }; | 85 | }; |
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 4ea63d9bd131..e318bf8c623c 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c | |||
@@ -185,7 +185,7 @@ static int fsi_slave_calc_addr(struct fsi_slave *slave, uint32_t *addrp, | |||
185 | return 0; | 185 | return 0; |
186 | } | 186 | } |
187 | 187 | ||
188 | int fsi_slave_report_and_clear_errors(struct fsi_slave *slave) | 188 | static int fsi_slave_report_and_clear_errors(struct fsi_slave *slave) |
189 | { | 189 | { |
190 | struct fsi_master *master = slave->master; | 190 | struct fsi_master *master = slave->master; |
191 | uint32_t irq, stat; | 191 | uint32_t irq, stat; |
@@ -215,8 +215,8 @@ int fsi_slave_report_and_clear_errors(struct fsi_slave *slave) | |||
215 | 215 | ||
216 | static int fsi_slave_set_smode(struct fsi_master *master, int link, int id); | 216 | static int fsi_slave_set_smode(struct fsi_master *master, int link, int id); |
217 | 217 | ||
218 | int fsi_slave_handle_error(struct fsi_slave *slave, bool write, uint32_t addr, | 218 | static int fsi_slave_handle_error(struct fsi_slave *slave, bool write, |
219 | size_t size) | 219 | uint32_t addr, size_t size) |
220 | { | 220 | { |
221 | struct fsi_master *master = slave->master; | 221 | struct fsi_master *master = slave->master; |
222 | int rc, link; | 222 | int rc, link; |
diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index e7b1d796ba2e..14c22786b519 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile | |||
@@ -3,7 +3,9 @@ obj-$(CONFIG_HYPERV) += hv_vmbus.o | |||
3 | obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o | 3 | obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o |
4 | obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o | 4 | obj-$(CONFIG_HYPERV_BALLOON) += hv_balloon.o |
5 | 5 | ||
6 | CFLAGS_hv_trace.o = -I$(src) | ||
7 | |||
6 | hv_vmbus-y := vmbus_drv.o \ | 8 | hv_vmbus-y := vmbus_drv.o \ |
7 | hv.o connection.o channel.o \ | 9 | hv.o connection.o channel.o \ |
8 | channel_mgmt.o ring_buffer.o | 10 | channel_mgmt.o ring_buffer.o hv_trace.o |
9 | hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_fcopy.o hv_utils_transport.o | 11 | hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_fcopy.o hv_utils_transport.o |
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 894b67ac2cae..19f0cf37e0ed 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c | |||
@@ -43,6 +43,8 @@ void vmbus_setevent(struct vmbus_channel *channel) | |||
43 | { | 43 | { |
44 | struct hv_monitor_page *monitorpage; | 44 | struct hv_monitor_page *monitorpage; |
45 | 45 | ||
46 | trace_vmbus_setevent(channel); | ||
47 | |||
46 | /* | 48 | /* |
47 | * For channels marked as in "low latency" mode | 49 | * For channels marked as in "low latency" mode |
48 | * bypass the monitor page mechanism. | 50 | * bypass the monitor page mechanism. |
@@ -185,6 +187,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, | |||
185 | ret = vmbus_post_msg(open_msg, | 187 | ret = vmbus_post_msg(open_msg, |
186 | sizeof(struct vmbus_channel_open_channel), true); | 188 | sizeof(struct vmbus_channel_open_channel), true); |
187 | 189 | ||
190 | trace_vmbus_open(open_msg, ret); | ||
191 | |||
188 | if (ret != 0) { | 192 | if (ret != 0) { |
189 | err = ret; | 193 | err = ret; |
190 | goto error_clean_msglist; | 194 | goto error_clean_msglist; |
@@ -234,13 +238,18 @@ int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id, | |||
234 | const uuid_le *shv_host_servie_id) | 238 | const uuid_le *shv_host_servie_id) |
235 | { | 239 | { |
236 | struct vmbus_channel_tl_connect_request conn_msg; | 240 | struct vmbus_channel_tl_connect_request conn_msg; |
241 | int ret; | ||
237 | 242 | ||
238 | memset(&conn_msg, 0, sizeof(conn_msg)); | 243 | memset(&conn_msg, 0, sizeof(conn_msg)); |
239 | conn_msg.header.msgtype = CHANNELMSG_TL_CONNECT_REQUEST; | 244 | conn_msg.header.msgtype = CHANNELMSG_TL_CONNECT_REQUEST; |
240 | conn_msg.guest_endpoint_id = *shv_guest_servie_id; | 245 | conn_msg.guest_endpoint_id = *shv_guest_servie_id; |
241 | conn_msg.host_service_id = *shv_host_servie_id; | 246 | conn_msg.host_service_id = *shv_host_servie_id; |
242 | 247 | ||
243 | return vmbus_post_msg(&conn_msg, sizeof(conn_msg), true); | 248 | ret = vmbus_post_msg(&conn_msg, sizeof(conn_msg), true); |
249 | |||
250 | trace_vmbus_send_tl_connect_request(&conn_msg, ret); | ||
251 | |||
252 | return ret; | ||
244 | } | 253 | } |
245 | EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request); | 254 | EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request); |
246 | 255 | ||
@@ -433,6 +442,9 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, | |||
433 | 442 | ||
434 | ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize - | 443 | ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize - |
435 | sizeof(*msginfo), true); | 444 | sizeof(*msginfo), true); |
445 | |||
446 | trace_vmbus_establish_gpadl_header(gpadlmsg, ret); | ||
447 | |||
436 | if (ret != 0) | 448 | if (ret != 0) |
437 | goto cleanup; | 449 | goto cleanup; |
438 | 450 | ||
@@ -448,6 +460,9 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, | |||
448 | ret = vmbus_post_msg(gpadl_body, | 460 | ret = vmbus_post_msg(gpadl_body, |
449 | submsginfo->msgsize - sizeof(*submsginfo), | 461 | submsginfo->msgsize - sizeof(*submsginfo), |
450 | true); | 462 | true); |
463 | |||
464 | trace_vmbus_establish_gpadl_body(gpadl_body, ret); | ||
465 | |||
451 | if (ret != 0) | 466 | if (ret != 0) |
452 | goto cleanup; | 467 | goto cleanup; |
453 | 468 | ||
@@ -511,6 +526,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) | |||
511 | ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown), | 526 | ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown), |
512 | true); | 527 | true); |
513 | 528 | ||
529 | trace_vmbus_teardown_gpadl(msg, ret); | ||
530 | |||
514 | if (ret) | 531 | if (ret) |
515 | goto post_msg_err; | 532 | goto post_msg_err; |
516 | 533 | ||
@@ -589,6 +606,8 @@ static int vmbus_close_internal(struct vmbus_channel *channel) | |||
589 | ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel), | 606 | ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel), |
590 | true); | 607 | true); |
591 | 608 | ||
609 | trace_vmbus_close_internal(msg, ret); | ||
610 | |||
592 | if (ret) { | 611 | if (ret) { |
593 | pr_err("Close failed: close post msg return is %d\n", ret); | 612 | pr_err("Close failed: close post msg return is %d\n", ret); |
594 | /* | 613 | /* |
@@ -745,6 +764,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, | |||
745 | desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */ | 764 | desc.dataoffset8 = descsize >> 3; /* in 8-bytes granularity */ |
746 | desc.length8 = (u16)(packetlen_aligned >> 3); | 765 | desc.length8 = (u16)(packetlen_aligned >> 3); |
747 | desc.transactionid = requestid; | 766 | desc.transactionid = requestid; |
767 | desc.reserved = 0; | ||
748 | desc.rangecount = pagecount; | 768 | desc.rangecount = pagecount; |
749 | 769 | ||
750 | for (i = 0; i < pagecount; i++) { | 770 | for (i = 0; i < pagecount; i++) { |
@@ -788,6 +808,7 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel, | |||
788 | desc->dataoffset8 = desc_size >> 3; /* in 8-bytes granularity */ | 808 | desc->dataoffset8 = desc_size >> 3; /* in 8-bytes granularity */ |
789 | desc->length8 = (u16)(packetlen_aligned >> 3); | 809 | desc->length8 = (u16)(packetlen_aligned >> 3); |
790 | desc->transactionid = requestid; | 810 | desc->transactionid = requestid; |
811 | desc->reserved = 0; | ||
791 | desc->rangecount = 1; | 812 | desc->rangecount = 1; |
792 | 813 | ||
793 | bufferlist[0].iov_base = desc; | 814 | bufferlist[0].iov_base = desc; |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 379b0df123be..ec5454f3f4a6 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -350,7 +350,7 @@ static void free_channel(struct vmbus_channel *channel) | |||
350 | { | 350 | { |
351 | tasklet_kill(&channel->callback_event); | 351 | tasklet_kill(&channel->callback_event); |
352 | 352 | ||
353 | kfree_rcu(channel, rcu); | 353 | kobject_put(&channel->kobj); |
354 | } | 354 | } |
355 | 355 | ||
356 | static void percpu_channel_enq(void *arg) | 356 | static void percpu_channel_enq(void *arg) |
@@ -373,12 +373,15 @@ static void percpu_channel_deq(void *arg) | |||
373 | static void vmbus_release_relid(u32 relid) | 373 | static void vmbus_release_relid(u32 relid) |
374 | { | 374 | { |
375 | struct vmbus_channel_relid_released msg; | 375 | struct vmbus_channel_relid_released msg; |
376 | int ret; | ||
376 | 377 | ||
377 | memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); | 378 | memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); |
378 | msg.child_relid = relid; | 379 | msg.child_relid = relid; |
379 | msg.header.msgtype = CHANNELMSG_RELID_RELEASED; | 380 | msg.header.msgtype = CHANNELMSG_RELID_RELEASED; |
380 | vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released), | 381 | ret = vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released), |
381 | true); | 382 | true); |
383 | |||
384 | trace_vmbus_release_relid(&msg, ret); | ||
382 | } | 385 | } |
383 | 386 | ||
384 | void hv_process_channel_removal(u32 relid) | 387 | void hv_process_channel_removal(u32 relid) |
@@ -520,6 +523,14 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) | |||
520 | newchannel->state = CHANNEL_OPEN_STATE; | 523 | newchannel->state = CHANNEL_OPEN_STATE; |
521 | 524 | ||
522 | if (!fnew) { | 525 | if (!fnew) { |
526 | struct hv_device *dev | ||
527 | = newchannel->primary_channel->device_obj; | ||
528 | |||
529 | if (vmbus_add_channel_kobj(dev, newchannel)) { | ||
530 | atomic_dec(&vmbus_connection.offer_in_progress); | ||
531 | goto err_free_chan; | ||
532 | } | ||
533 | |||
523 | if (channel->sc_creation_callback != NULL) | 534 | if (channel->sc_creation_callback != NULL) |
524 | channel->sc_creation_callback(newchannel); | 535 | channel->sc_creation_callback(newchannel); |
525 | newchannel->probe_done = true; | 536 | newchannel->probe_done = true; |
@@ -805,6 +816,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) | |||
805 | 816 | ||
806 | offer = (struct vmbus_channel_offer_channel *)hdr; | 817 | offer = (struct vmbus_channel_offer_channel *)hdr; |
807 | 818 | ||
819 | trace_vmbus_onoffer(offer); | ||
820 | |||
808 | /* Allocate the channel object and save this offer. */ | 821 | /* Allocate the channel object and save this offer. */ |
809 | newchannel = alloc_channel(); | 822 | newchannel = alloc_channel(); |
810 | if (!newchannel) { | 823 | if (!newchannel) { |
@@ -846,6 +859,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) | |||
846 | 859 | ||
847 | rescind = (struct vmbus_channel_rescind_offer *)hdr; | 860 | rescind = (struct vmbus_channel_rescind_offer *)hdr; |
848 | 861 | ||
862 | trace_vmbus_onoffer_rescind(rescind); | ||
863 | |||
849 | /* | 864 | /* |
850 | * The offer msg and the corresponding rescind msg | 865 | * The offer msg and the corresponding rescind msg |
851 | * from the host are guranteed to be ordered - | 866 | * from the host are guranteed to be ordered - |
@@ -974,6 +989,8 @@ static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr) | |||
974 | 989 | ||
975 | result = (struct vmbus_channel_open_result *)hdr; | 990 | result = (struct vmbus_channel_open_result *)hdr; |
976 | 991 | ||
992 | trace_vmbus_onopen_result(result); | ||
993 | |||
977 | /* | 994 | /* |
978 | * Find the open msg, copy the result and signal/unblock the wait event | 995 | * Find the open msg, copy the result and signal/unblock the wait event |
979 | */ | 996 | */ |
@@ -1018,6 +1035,8 @@ static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr) | |||
1018 | 1035 | ||
1019 | gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr; | 1036 | gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr; |
1020 | 1037 | ||
1038 | trace_vmbus_ongpadl_created(gpadlcreated); | ||
1039 | |||
1021 | /* | 1040 | /* |
1022 | * Find the establish msg, copy the result and signal/unblock the wait | 1041 | * Find the establish msg, copy the result and signal/unblock the wait |
1023 | * event | 1042 | * event |
@@ -1066,6 +1085,8 @@ static void vmbus_ongpadl_torndown( | |||
1066 | 1085 | ||
1067 | gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr; | 1086 | gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr; |
1068 | 1087 | ||
1088 | trace_vmbus_ongpadl_torndown(gpadl_torndown); | ||
1089 | |||
1069 | /* | 1090 | /* |
1070 | * Find the open msg, copy the result and signal/unblock the wait event | 1091 | * Find the open msg, copy the result and signal/unblock the wait event |
1071 | */ | 1092 | */ |
@@ -1109,6 +1130,9 @@ static void vmbus_onversion_response( | |||
1109 | unsigned long flags; | 1130 | unsigned long flags; |
1110 | 1131 | ||
1111 | version_response = (struct vmbus_channel_version_response *)hdr; | 1132 | version_response = (struct vmbus_channel_version_response *)hdr; |
1133 | |||
1134 | trace_vmbus_onversion_response(version_response); | ||
1135 | |||
1112 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 1136 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
1113 | 1137 | ||
1114 | list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, | 1138 | list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, |
@@ -1168,6 +1192,8 @@ void vmbus_onmessage(void *context) | |||
1168 | hdr = (struct vmbus_channel_message_header *)msg->u.payload; | 1192 | hdr = (struct vmbus_channel_message_header *)msg->u.payload; |
1169 | size = msg->header.payload_size; | 1193 | size = msg->header.payload_size; |
1170 | 1194 | ||
1195 | trace_vmbus_on_message(hdr); | ||
1196 | |||
1171 | if (hdr->msgtype >= CHANNELMSG_COUNT) { | 1197 | if (hdr->msgtype >= CHANNELMSG_COUNT) { |
1172 | pr_err("Received invalid channel message type %d size %d\n", | 1198 | pr_err("Received invalid channel message type %d size %d\n", |
1173 | hdr->msgtype, size); | 1199 | hdr->msgtype, size); |
@@ -1201,9 +1227,11 @@ int vmbus_request_offers(void) | |||
1201 | 1227 | ||
1202 | msg->msgtype = CHANNELMSG_REQUESTOFFERS; | 1228 | msg->msgtype = CHANNELMSG_REQUESTOFFERS; |
1203 | 1229 | ||
1204 | |||
1205 | ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header), | 1230 | ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_message_header), |
1206 | true); | 1231 | true); |
1232 | |||
1233 | trace_vmbus_request_offers(ret); | ||
1234 | |||
1207 | if (ret != 0) { | 1235 | if (ret != 0) { |
1208 | pr_err("Unable to request offers - %d\n", ret); | 1236 | pr_err("Unable to request offers - %d\n", ret); |
1209 | 1237 | ||
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index f41901f80b64..447371f4de56 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c | |||
@@ -117,6 +117,9 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, | |||
117 | ret = vmbus_post_msg(msg, | 117 | ret = vmbus_post_msg(msg, |
118 | sizeof(struct vmbus_channel_initiate_contact), | 118 | sizeof(struct vmbus_channel_initiate_contact), |
119 | true); | 119 | true); |
120 | |||
121 | trace_vmbus_negotiate_version(msg, ret); | ||
122 | |||
120 | if (ret != 0) { | 123 | if (ret != 0) { |
121 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 124 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
122 | list_del(&msginfo->msglistentry); | 125 | list_del(&msginfo->msglistentry); |
@@ -319,6 +322,8 @@ void vmbus_on_event(unsigned long data) | |||
319 | struct vmbus_channel *channel = (void *) data; | 322 | struct vmbus_channel *channel = (void *) data; |
320 | unsigned long time_limit = jiffies + 2; | 323 | unsigned long time_limit = jiffies + 2; |
321 | 324 | ||
325 | trace_vmbus_on_event(channel); | ||
326 | |||
322 | do { | 327 | do { |
323 | void (*callback_fn)(void *); | 328 | void (*callback_fn)(void *); |
324 | 329 | ||
@@ -409,6 +414,8 @@ void vmbus_set_event(struct vmbus_channel *channel) | |||
409 | if (!channel->is_dedicated_interrupt) | 414 | if (!channel->is_dedicated_interrupt) |
410 | vmbus_send_interrupt(child_relid); | 415 | vmbus_send_interrupt(child_relid); |
411 | 416 | ||
417 | ++channel->sig_events; | ||
418 | |||
412 | hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); | 419 | hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); |
413 | } | 420 | } |
414 | EXPORT_SYMBOL_GPL(vmbus_set_event); | 421 | EXPORT_SYMBOL_GPL(vmbus_set_event); |
diff --git a/drivers/hv/hv_trace.c b/drivers/hv/hv_trace.c new file mode 100644 index 000000000000..df47acd01a81 --- /dev/null +++ b/drivers/hv/hv_trace.c | |||
@@ -0,0 +1,4 @@ | |||
1 | #include "hyperv_vmbus.h" | ||
2 | |||
3 | #define CREATE_TRACE_POINTS | ||
4 | #include "hv_trace.h" | ||
diff --git a/drivers/hv/hv_trace.h b/drivers/hv/hv_trace.h new file mode 100644 index 000000000000..d635ee95b20d --- /dev/null +++ b/drivers/hv/hv_trace.h | |||
@@ -0,0 +1,327 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM hyperv | ||
3 | |||
4 | #if !defined(_HV_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _HV_TRACE_H | ||
6 | |||
7 | #include <linux/tracepoint.h> | ||
8 | |||
9 | DECLARE_EVENT_CLASS(vmbus_hdr_msg, | ||
10 | TP_PROTO(const struct vmbus_channel_message_header *hdr), | ||
11 | TP_ARGS(hdr), | ||
12 | TP_STRUCT__entry(__field(unsigned int, msgtype)), | ||
13 | TP_fast_assign(__entry->msgtype = hdr->msgtype;), | ||
14 | TP_printk("msgtype=%u", __entry->msgtype) | ||
15 | ); | ||
16 | |||
17 | DEFINE_EVENT(vmbus_hdr_msg, vmbus_on_msg_dpc, | ||
18 | TP_PROTO(const struct vmbus_channel_message_header *hdr), | ||
19 | TP_ARGS(hdr) | ||
20 | ); | ||
21 | |||
22 | DEFINE_EVENT(vmbus_hdr_msg, vmbus_on_message, | ||
23 | TP_PROTO(const struct vmbus_channel_message_header *hdr), | ||
24 | TP_ARGS(hdr) | ||
25 | ); | ||
26 | |||
27 | TRACE_EVENT(vmbus_onoffer, | ||
28 | TP_PROTO(const struct vmbus_channel_offer_channel *offer), | ||
29 | TP_ARGS(offer), | ||
30 | TP_STRUCT__entry( | ||
31 | __field(u32, child_relid) | ||
32 | __field(u8, monitorid) | ||
33 | __field(u16, is_ddc_int) | ||
34 | __field(u32, connection_id) | ||
35 | __array(char, if_type, 16) | ||
36 | __array(char, if_instance, 16) | ||
37 | __field(u16, chn_flags) | ||
38 | __field(u16, mmio_mb) | ||
39 | __field(u16, sub_idx) | ||
40 | ), | ||
41 | TP_fast_assign(__entry->child_relid = offer->child_relid; | ||
42 | __entry->monitorid = offer->monitorid; | ||
43 | __entry->is_ddc_int = offer->is_dedicated_interrupt; | ||
44 | __entry->connection_id = offer->connection_id; | ||
45 | memcpy(__entry->if_type, | ||
46 | &offer->offer.if_type.b, 16); | ||
47 | memcpy(__entry->if_instance, | ||
48 | &offer->offer.if_instance.b, 16); | ||
49 | __entry->chn_flags = offer->offer.chn_flags; | ||
50 | __entry->mmio_mb = offer->offer.mmio_megabytes; | ||
51 | __entry->sub_idx = offer->offer.sub_channel_index; | ||
52 | ), | ||
53 | TP_printk("child_relid 0x%x, monitorid 0x%x, is_dedicated %d, " | ||
54 | "connection_id 0x%x, if_type %pUl, if_instance %pUl, " | ||
55 | "chn_flags 0x%x, mmio_megabytes %d, sub_channel_index %d", | ||
56 | __entry->child_relid, __entry->monitorid, | ||
57 | __entry->is_ddc_int, __entry->connection_id, | ||
58 | __entry->if_type, __entry->if_instance, | ||
59 | __entry->chn_flags, __entry->mmio_mb, | ||
60 | __entry->sub_idx | ||
61 | ) | ||
62 | ); | ||
63 | |||
64 | TRACE_EVENT(vmbus_onoffer_rescind, | ||
65 | TP_PROTO(const struct vmbus_channel_rescind_offer *offer), | ||
66 | TP_ARGS(offer), | ||
67 | TP_STRUCT__entry(__field(u32, child_relid)), | ||
68 | TP_fast_assign(__entry->child_relid = offer->child_relid), | ||
69 | TP_printk("child_relid 0x%x", __entry->child_relid) | ||
70 | ); | ||
71 | |||
72 | TRACE_EVENT(vmbus_onopen_result, | ||
73 | TP_PROTO(const struct vmbus_channel_open_result *result), | ||
74 | TP_ARGS(result), | ||
75 | TP_STRUCT__entry( | ||
76 | __field(u32, child_relid) | ||
77 | __field(u32, openid) | ||
78 | __field(u32, status) | ||
79 | ), | ||
80 | TP_fast_assign(__entry->child_relid = result->child_relid; | ||
81 | __entry->openid = result->openid; | ||
82 | __entry->status = result->status; | ||
83 | ), | ||
84 | TP_printk("child_relid 0x%x, openid %d, status %d", | ||
85 | __entry->child_relid, __entry->openid, __entry->status | ||
86 | ) | ||
87 | ); | ||
88 | |||
89 | TRACE_EVENT(vmbus_ongpadl_created, | ||
90 | TP_PROTO(const struct vmbus_channel_gpadl_created *gpadlcreated), | ||
91 | TP_ARGS(gpadlcreated), | ||
92 | TP_STRUCT__entry( | ||
93 | __field(u32, child_relid) | ||
94 | __field(u32, gpadl) | ||
95 | __field(u32, status) | ||
96 | ), | ||
97 | TP_fast_assign(__entry->child_relid = gpadlcreated->child_relid; | ||
98 | __entry->gpadl = gpadlcreated->gpadl; | ||
99 | __entry->status = gpadlcreated->creation_status; | ||
100 | ), | ||
101 | TP_printk("child_relid 0x%x, gpadl 0x%x, creation_status %d", | ||
102 | __entry->child_relid, __entry->gpadl, __entry->status | ||
103 | ) | ||
104 | ); | ||
105 | |||
106 | TRACE_EVENT(vmbus_ongpadl_torndown, | ||
107 | TP_PROTO(const struct vmbus_channel_gpadl_torndown *gpadltorndown), | ||
108 | TP_ARGS(gpadltorndown), | ||
109 | TP_STRUCT__entry(__field(u32, gpadl)), | ||
110 | TP_fast_assign(__entry->gpadl = gpadltorndown->gpadl), | ||
111 | TP_printk("gpadl 0x%x", __entry->gpadl) | ||
112 | ); | ||
113 | |||
114 | TRACE_EVENT(vmbus_onversion_response, | ||
115 | TP_PROTO(const struct vmbus_channel_version_response *response), | ||
116 | TP_ARGS(response), | ||
117 | TP_STRUCT__entry( | ||
118 | __field(u8, ver) | ||
119 | ), | ||
120 | TP_fast_assign(__entry->ver = response->version_supported; | ||
121 | ), | ||
122 | TP_printk("version_supported %d", __entry->ver) | ||
123 | ); | ||
124 | |||
125 | TRACE_EVENT(vmbus_request_offers, | ||
126 | TP_PROTO(int ret), | ||
127 | TP_ARGS(ret), | ||
128 | TP_STRUCT__entry(__field(int, ret)), | ||
129 | TP_fast_assign(__entry->ret = ret), | ||
130 | TP_printk("sending ret %d", __entry->ret) | ||
131 | ); | ||
132 | |||
133 | TRACE_EVENT(vmbus_open, | ||
134 | TP_PROTO(const struct vmbus_channel_open_channel *msg, int ret), | ||
135 | TP_ARGS(msg, ret), | ||
136 | TP_STRUCT__entry( | ||
137 | __field(u32, child_relid) | ||
138 | __field(u32, openid) | ||
139 | __field(u32, gpadlhandle) | ||
140 | __field(u32, target_vp) | ||
141 | __field(u32, offset) | ||
142 | __field(int, ret) | ||
143 | ), | ||
144 | TP_fast_assign( | ||
145 | __entry->child_relid = msg->child_relid; | ||
146 | __entry->openid = msg->openid; | ||
147 | __entry->gpadlhandle = msg->ringbuffer_gpadlhandle; | ||
148 | __entry->target_vp = msg->target_vp; | ||
149 | __entry->offset = msg->downstream_ringbuffer_pageoffset; | ||
150 | __entry->ret = ret; | ||
151 | ), | ||
152 | TP_printk("sending child_relid 0x%x, openid %d, " | ||
153 | "gpadlhandle 0x%x, target_vp 0x%x, offset 0x%x, ret %d", | ||
154 | __entry->child_relid, __entry->openid, | ||
155 | __entry->gpadlhandle, __entry->target_vp, | ||
156 | __entry->offset, __entry->ret | ||
157 | ) | ||
158 | ); | ||
159 | |||
160 | TRACE_EVENT(vmbus_close_internal, | ||
161 | TP_PROTO(const struct vmbus_channel_close_channel *msg, int ret), | ||
162 | TP_ARGS(msg, ret), | ||
163 | TP_STRUCT__entry( | ||
164 | __field(u32, child_relid) | ||
165 | __field(int, ret) | ||
166 | ), | ||
167 | TP_fast_assign( | ||
168 | __entry->child_relid = msg->child_relid; | ||
169 | __entry->ret = ret; | ||
170 | ), | ||
171 | TP_printk("sending child_relid 0x%x, ret %d", __entry->child_relid, | ||
172 | __entry->ret) | ||
173 | ); | ||
174 | |||
175 | TRACE_EVENT(vmbus_establish_gpadl_header, | ||
176 | TP_PROTO(const struct vmbus_channel_gpadl_header *msg, int ret), | ||
177 | TP_ARGS(msg, ret), | ||
178 | TP_STRUCT__entry( | ||
179 | __field(u32, child_relid) | ||
180 | __field(u32, gpadl) | ||
181 | __field(u16, range_buflen) | ||
182 | __field(u16, rangecount) | ||
183 | __field(int, ret) | ||
184 | ), | ||
185 | TP_fast_assign( | ||
186 | __entry->child_relid = msg->child_relid; | ||
187 | __entry->gpadl = msg->gpadl; | ||
188 | __entry->range_buflen = msg->range_buflen; | ||
189 | __entry->rangecount = msg->rangecount; | ||
190 | __entry->ret = ret; | ||
191 | ), | ||
192 | TP_printk("sending child_relid 0x%x, gpadl 0x%x, range_buflen %d " | ||
193 | "rangecount %d, ret %d", | ||
194 | __entry->child_relid, __entry->gpadl, | ||
195 | __entry->range_buflen, __entry->rangecount, __entry->ret | ||
196 | ) | ||
197 | ); | ||
198 | |||
199 | TRACE_EVENT(vmbus_establish_gpadl_body, | ||
200 | TP_PROTO(const struct vmbus_channel_gpadl_body *msg, int ret), | ||
201 | TP_ARGS(msg, ret), | ||
202 | TP_STRUCT__entry( | ||
203 | __field(u32, msgnumber) | ||
204 | __field(u32, gpadl) | ||
205 | __field(int, ret) | ||
206 | ), | ||
207 | TP_fast_assign( | ||
208 | __entry->msgnumber = msg->msgnumber; | ||
209 | __entry->gpadl = msg->gpadl; | ||
210 | __entry->ret = ret; | ||
211 | ), | ||
212 | TP_printk("sending msgnumber %d, gpadl 0x%x, ret %d", | ||
213 | __entry->msgnumber, __entry->gpadl, __entry->ret | ||
214 | ) | ||
215 | ); | ||
216 | |||
217 | TRACE_EVENT(vmbus_teardown_gpadl, | ||
218 | TP_PROTO(const struct vmbus_channel_gpadl_teardown *msg, int ret), | ||
219 | TP_ARGS(msg, ret), | ||
220 | TP_STRUCT__entry( | ||
221 | __field(u32, child_relid) | ||
222 | __field(u32, gpadl) | ||
223 | __field(int, ret) | ||
224 | ), | ||
225 | TP_fast_assign( | ||
226 | __entry->child_relid = msg->child_relid; | ||
227 | __entry->gpadl = msg->gpadl; | ||
228 | __entry->ret = ret; | ||
229 | ), | ||
230 | TP_printk("sending child_relid 0x%x, gpadl 0x%x, ret %d", | ||
231 | __entry->child_relid, __entry->gpadl, __entry->ret | ||
232 | ) | ||
233 | ); | ||
234 | |||
235 | TRACE_EVENT(vmbus_negotiate_version, | ||
236 | TP_PROTO(const struct vmbus_channel_initiate_contact *msg, int ret), | ||
237 | TP_ARGS(msg, ret), | ||
238 | TP_STRUCT__entry( | ||
239 | __field(u32, ver) | ||
240 | __field(u32, target_vcpu) | ||
241 | __field(int, ret) | ||
242 | __field(u64, int_page) | ||
243 | __field(u64, mon_page1) | ||
244 | __field(u64, mon_page2) | ||
245 | ), | ||
246 | TP_fast_assign( | ||
247 | __entry->ver = msg->vmbus_version_requested; | ||
248 | __entry->target_vcpu = msg->target_vcpu; | ||
249 | __entry->int_page = msg->interrupt_page; | ||
250 | __entry->mon_page1 = msg->monitor_page1; | ||
251 | __entry->mon_page2 = msg->monitor_page2; | ||
252 | __entry->ret = ret; | ||
253 | ), | ||
254 | TP_printk("sending vmbus_version_requested %d, target_vcpu 0x%x, " | ||
255 | "pages %llx:%llx:%llx, ret %d", | ||
256 | __entry->ver, __entry->target_vcpu, __entry->int_page, | ||
257 | __entry->mon_page1, __entry->mon_page2, __entry->ret | ||
258 | ) | ||
259 | ); | ||
260 | |||
261 | TRACE_EVENT(vmbus_release_relid, | ||
262 | TP_PROTO(const struct vmbus_channel_relid_released *msg, int ret), | ||
263 | TP_ARGS(msg, ret), | ||
264 | TP_STRUCT__entry( | ||
265 | __field(u32, child_relid) | ||
266 | __field(int, ret) | ||
267 | ), | ||
268 | TP_fast_assign( | ||
269 | __entry->child_relid = msg->child_relid; | ||
270 | __entry->ret = ret; | ||
271 | ), | ||
272 | TP_printk("sending child_relid 0x%x, ret %d", | ||
273 | __entry->child_relid, __entry->ret | ||
274 | ) | ||
275 | ); | ||
276 | |||
277 | TRACE_EVENT(vmbus_send_tl_connect_request, | ||
278 | TP_PROTO(const struct vmbus_channel_tl_connect_request *msg, | ||
279 | int ret), | ||
280 | TP_ARGS(msg, ret), | ||
281 | TP_STRUCT__entry( | ||
282 | __array(char, guest_id, 16) | ||
283 | __array(char, host_id, 16) | ||
284 | __field(int, ret) | ||
285 | ), | ||
286 | TP_fast_assign( | ||
287 | memcpy(__entry->guest_id, &msg->guest_endpoint_id.b, 16); | ||
288 | memcpy(__entry->host_id, &msg->host_service_id.b, 16); | ||
289 | __entry->ret = ret; | ||
290 | ), | ||
291 | TP_printk("sending guest_endpoint_id %pUl, host_service_id %pUl, " | ||
292 | "ret %d", | ||
293 | __entry->guest_id, __entry->host_id, __entry->ret | ||
294 | ) | ||
295 | ); | ||
296 | |||
297 | DECLARE_EVENT_CLASS(vmbus_channel, | ||
298 | TP_PROTO(const struct vmbus_channel *channel), | ||
299 | TP_ARGS(channel), | ||
300 | TP_STRUCT__entry(__field(u32, relid)), | ||
301 | TP_fast_assign(__entry->relid = channel->offermsg.child_relid), | ||
302 | TP_printk("relid 0x%x", __entry->relid) | ||
303 | ); | ||
304 | |||
305 | DEFINE_EVENT(vmbus_channel, vmbus_chan_sched, | ||
306 | TP_PROTO(const struct vmbus_channel *channel), | ||
307 | TP_ARGS(channel) | ||
308 | ); | ||
309 | |||
310 | DEFINE_EVENT(vmbus_channel, vmbus_setevent, | ||
311 | TP_PROTO(const struct vmbus_channel *channel), | ||
312 | TP_ARGS(channel) | ||
313 | ); | ||
314 | |||
315 | DEFINE_EVENT(vmbus_channel, vmbus_on_event, | ||
316 | TP_PROTO(const struct vmbus_channel *channel), | ||
317 | TP_ARGS(channel) | ||
318 | ); | ||
319 | |||
320 | #undef TRACE_INCLUDE_PATH | ||
321 | #define TRACE_INCLUDE_PATH . | ||
322 | #undef TRACE_INCLUDE_FILE | ||
323 | #define TRACE_INCLUDE_FILE hv_trace | ||
324 | #endif /* _HV_TRACE_H */ | ||
325 | |||
326 | /* This part must be outside protection */ | ||
327 | #include <trace/define_trace.h> | ||
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 49569f8fe038..22300ec7b556 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/hyperv.h> | 31 | #include <linux/hyperv.h> |
32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
33 | 33 | ||
34 | #include "hv_trace.h" | ||
35 | |||
34 | /* | 36 | /* |
35 | * Timeout for services such as KVP and fcopy. | 37 | * Timeout for services such as KVP and fcopy. |
36 | */ | 38 | */ |
@@ -373,6 +375,8 @@ struct hv_device *vmbus_device_create(const uuid_le *type, | |||
373 | 375 | ||
374 | int vmbus_device_register(struct hv_device *child_device_obj); | 376 | int vmbus_device_register(struct hv_device *child_device_obj); |
375 | void vmbus_device_unregister(struct hv_device *device_obj); | 377 | void vmbus_device_unregister(struct hv_device *device_obj); |
378 | int vmbus_add_channel_kobj(struct hv_device *device_obj, | ||
379 | struct vmbus_channel *channel); | ||
376 | 380 | ||
377 | struct vmbus_channel *relid2channel(u32 relid); | 381 | struct vmbus_channel *relid2channel(u32 relid); |
378 | 382 | ||
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 2cd134dd94d2..76ed9a216f10 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c | |||
@@ -65,7 +65,7 @@ static int hyperv_panic_event(struct notifier_block *nb, unsigned long val, | |||
65 | 65 | ||
66 | regs = current_pt_regs(); | 66 | regs = current_pt_regs(); |
67 | 67 | ||
68 | hyperv_report_panic(regs); | 68 | hyperv_report_panic(regs, val); |
69 | return NOTIFY_DONE; | 69 | return NOTIFY_DONE; |
70 | } | 70 | } |
71 | 71 | ||
@@ -75,7 +75,7 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val, | |||
75 | struct die_args *die = (struct die_args *)args; | 75 | struct die_args *die = (struct die_args *)args; |
76 | struct pt_regs *regs = die->regs; | 76 | struct pt_regs *regs = die->regs; |
77 | 77 | ||
78 | hyperv_report_panic(regs); | 78 | hyperv_report_panic(regs, val); |
79 | return NOTIFY_DONE; | 79 | return NOTIFY_DONE; |
80 | } | 80 | } |
81 | 81 | ||
@@ -107,28 +107,30 @@ static void print_alias_name(struct hv_device *hv_dev, char *alias_name) | |||
107 | sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]); | 107 | sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]); |
108 | } | 108 | } |
109 | 109 | ||
110 | static u8 channel_monitor_group(struct vmbus_channel *channel) | 110 | static u8 channel_monitor_group(const struct vmbus_channel *channel) |
111 | { | 111 | { |
112 | return (u8)channel->offermsg.monitorid / 32; | 112 | return (u8)channel->offermsg.monitorid / 32; |
113 | } | 113 | } |
114 | 114 | ||
115 | static u8 channel_monitor_offset(struct vmbus_channel *channel) | 115 | static u8 channel_monitor_offset(const struct vmbus_channel *channel) |
116 | { | 116 | { |
117 | return (u8)channel->offermsg.monitorid % 32; | 117 | return (u8)channel->offermsg.monitorid % 32; |
118 | } | 118 | } |
119 | 119 | ||
120 | static u32 channel_pending(struct vmbus_channel *channel, | 120 | static u32 channel_pending(const struct vmbus_channel *channel, |
121 | struct hv_monitor_page *monitor_page) | 121 | const struct hv_monitor_page *monitor_page) |
122 | { | 122 | { |
123 | u8 monitor_group = channel_monitor_group(channel); | 123 | u8 monitor_group = channel_monitor_group(channel); |
124 | |||
124 | return monitor_page->trigger_group[monitor_group].pending; | 125 | return monitor_page->trigger_group[monitor_group].pending; |
125 | } | 126 | } |
126 | 127 | ||
127 | static u32 channel_latency(struct vmbus_channel *channel, | 128 | static u32 channel_latency(const struct vmbus_channel *channel, |
128 | struct hv_monitor_page *monitor_page) | 129 | const struct hv_monitor_page *monitor_page) |
129 | { | 130 | { |
130 | u8 monitor_group = channel_monitor_group(channel); | 131 | u8 monitor_group = channel_monitor_group(channel); |
131 | u8 monitor_offset = channel_monitor_offset(channel); | 132 | u8 monitor_offset = channel_monitor_offset(channel); |
133 | |||
132 | return monitor_page->latency[monitor_group][monitor_offset]; | 134 | return monitor_page->latency[monitor_group][monitor_offset]; |
133 | } | 135 | } |
134 | 136 | ||
@@ -833,6 +835,8 @@ void vmbus_on_msg_dpc(unsigned long data) | |||
833 | 835 | ||
834 | hdr = (struct vmbus_channel_message_header *)msg->u.payload; | 836 | hdr = (struct vmbus_channel_message_header *)msg->u.payload; |
835 | 837 | ||
838 | trace_vmbus_on_msg_dpc(hdr); | ||
839 | |||
836 | if (hdr->msgtype >= CHANNELMSG_COUNT) { | 840 | if (hdr->msgtype >= CHANNELMSG_COUNT) { |
837 | WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); | 841 | WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); |
838 | goto msg_handled; | 842 | goto msg_handled; |
@@ -942,6 +946,10 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) | |||
942 | if (channel->rescind) | 946 | if (channel->rescind) |
943 | continue; | 947 | continue; |
944 | 948 | ||
949 | trace_vmbus_chan_sched(channel); | ||
950 | |||
951 | ++channel->interrupts; | ||
952 | |||
945 | switch (channel->callback_mode) { | 953 | switch (channel->callback_mode) { |
946 | case HV_CALL_ISR: | 954 | case HV_CALL_ISR: |
947 | vmbus_channel_isr(channel); | 955 | vmbus_channel_isr(channel); |
@@ -1133,6 +1141,159 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) | |||
1133 | } | 1141 | } |
1134 | EXPORT_SYMBOL_GPL(vmbus_driver_unregister); | 1142 | EXPORT_SYMBOL_GPL(vmbus_driver_unregister); |
1135 | 1143 | ||
1144 | |||
1145 | /* | ||
1146 | * Called when last reference to channel is gone. | ||
1147 | */ | ||
1148 | static void vmbus_chan_release(struct kobject *kobj) | ||
1149 | { | ||
1150 | struct vmbus_channel *channel | ||
1151 | = container_of(kobj, struct vmbus_channel, kobj); | ||
1152 | |||
1153 | kfree_rcu(channel, rcu); | ||
1154 | } | ||
1155 | |||
1156 | struct vmbus_chan_attribute { | ||
1157 | struct attribute attr; | ||
1158 | ssize_t (*show)(const struct vmbus_channel *chan, char *buf); | ||
1159 | ssize_t (*store)(struct vmbus_channel *chan, | ||
1160 | const char *buf, size_t count); | ||
1161 | }; | ||
1162 | #define VMBUS_CHAN_ATTR(_name, _mode, _show, _store) \ | ||
1163 | struct vmbus_chan_attribute chan_attr_##_name \ | ||
1164 | = __ATTR(_name, _mode, _show, _store) | ||
1165 | #define VMBUS_CHAN_ATTR_RW(_name) \ | ||
1166 | struct vmbus_chan_attribute chan_attr_##_name = __ATTR_RW(_name) | ||
1167 | #define VMBUS_CHAN_ATTR_RO(_name) \ | ||
1168 | struct vmbus_chan_attribute chan_attr_##_name = __ATTR_RO(_name) | ||
1169 | #define VMBUS_CHAN_ATTR_WO(_name) \ | ||
1170 | struct vmbus_chan_attribute chan_attr_##_name = __ATTR_WO(_name) | ||
1171 | |||
1172 | static ssize_t vmbus_chan_attr_show(struct kobject *kobj, | ||
1173 | struct attribute *attr, char *buf) | ||
1174 | { | ||
1175 | const struct vmbus_chan_attribute *attribute | ||
1176 | = container_of(attr, struct vmbus_chan_attribute, attr); | ||
1177 | const struct vmbus_channel *chan | ||
1178 | = container_of(kobj, struct vmbus_channel, kobj); | ||
1179 | |||
1180 | if (!attribute->show) | ||
1181 | return -EIO; | ||
1182 | |||
1183 | return attribute->show(chan, buf); | ||
1184 | } | ||
1185 | |||
1186 | static const struct sysfs_ops vmbus_chan_sysfs_ops = { | ||
1187 | .show = vmbus_chan_attr_show, | ||
1188 | }; | ||
1189 | |||
1190 | static ssize_t out_mask_show(const struct vmbus_channel *channel, char *buf) | ||
1191 | { | ||
1192 | const struct hv_ring_buffer_info *rbi = &channel->outbound; | ||
1193 | |||
1194 | return sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask); | ||
1195 | } | ||
1196 | VMBUS_CHAN_ATTR_RO(out_mask); | ||
1197 | |||
1198 | static ssize_t in_mask_show(const struct vmbus_channel *channel, char *buf) | ||
1199 | { | ||
1200 | const struct hv_ring_buffer_info *rbi = &channel->inbound; | ||
1201 | |||
1202 | return sprintf(buf, "%u\n", rbi->ring_buffer->interrupt_mask); | ||
1203 | } | ||
1204 | VMBUS_CHAN_ATTR_RO(in_mask); | ||
1205 | |||
1206 | static ssize_t read_avail_show(const struct vmbus_channel *channel, char *buf) | ||
1207 | { | ||
1208 | const struct hv_ring_buffer_info *rbi = &channel->inbound; | ||
1209 | |||
1210 | return sprintf(buf, "%u\n", hv_get_bytes_to_read(rbi)); | ||
1211 | } | ||
1212 | VMBUS_CHAN_ATTR_RO(read_avail); | ||
1213 | |||
1214 | static ssize_t write_avail_show(const struct vmbus_channel *channel, char *buf) | ||
1215 | { | ||
1216 | const struct hv_ring_buffer_info *rbi = &channel->outbound; | ||
1217 | |||
1218 | return sprintf(buf, "%u\n", hv_get_bytes_to_write(rbi)); | ||
1219 | } | ||
1220 | VMBUS_CHAN_ATTR_RO(write_avail); | ||
1221 | |||
1222 | static ssize_t show_target_cpu(const struct vmbus_channel *channel, char *buf) | ||
1223 | { | ||
1224 | return sprintf(buf, "%u\n", channel->target_cpu); | ||
1225 | } | ||
1226 | VMBUS_CHAN_ATTR(cpu, S_IRUGO, show_target_cpu, NULL); | ||
1227 | |||
1228 | static ssize_t channel_pending_show(const struct vmbus_channel *channel, | ||
1229 | char *buf) | ||
1230 | { | ||
1231 | return sprintf(buf, "%d\n", | ||
1232 | channel_pending(channel, | ||
1233 | vmbus_connection.monitor_pages[1])); | ||
1234 | } | ||
1235 | VMBUS_CHAN_ATTR(pending, S_IRUGO, channel_pending_show, NULL); | ||
1236 | |||
1237 | static ssize_t channel_latency_show(const struct vmbus_channel *channel, | ||
1238 | char *buf) | ||
1239 | { | ||
1240 | return sprintf(buf, "%d\n", | ||
1241 | channel_latency(channel, | ||
1242 | vmbus_connection.monitor_pages[1])); | ||
1243 | } | ||
1244 | VMBUS_CHAN_ATTR(latency, S_IRUGO, channel_latency_show, NULL); | ||
1245 | |||
1246 | static ssize_t channel_interrupts_show(const struct vmbus_channel *channel, char *buf) | ||
1247 | { | ||
1248 | return sprintf(buf, "%llu\n", channel->interrupts); | ||
1249 | } | ||
1250 | VMBUS_CHAN_ATTR(interrupts, S_IRUGO, channel_interrupts_show, NULL); | ||
1251 | |||
1252 | static ssize_t channel_events_show(const struct vmbus_channel *channel, char *buf) | ||
1253 | { | ||
1254 | return sprintf(buf, "%llu\n", channel->sig_events); | ||
1255 | } | ||
1256 | VMBUS_CHAN_ATTR(events, S_IRUGO, channel_events_show, NULL); | ||
1257 | |||
1258 | static struct attribute *vmbus_chan_attrs[] = { | ||
1259 | &chan_attr_out_mask.attr, | ||
1260 | &chan_attr_in_mask.attr, | ||
1261 | &chan_attr_read_avail.attr, | ||
1262 | &chan_attr_write_avail.attr, | ||
1263 | &chan_attr_cpu.attr, | ||
1264 | &chan_attr_pending.attr, | ||
1265 | &chan_attr_latency.attr, | ||
1266 | &chan_attr_interrupts.attr, | ||
1267 | &chan_attr_events.attr, | ||
1268 | NULL | ||
1269 | }; | ||
1270 | |||
1271 | static struct kobj_type vmbus_chan_ktype = { | ||
1272 | .sysfs_ops = &vmbus_chan_sysfs_ops, | ||
1273 | .release = vmbus_chan_release, | ||
1274 | .default_attrs = vmbus_chan_attrs, | ||
1275 | }; | ||
1276 | |||
1277 | /* | ||
1278 | * vmbus_add_channel_kobj - setup a sub-directory under device/channels | ||
1279 | */ | ||
1280 | int vmbus_add_channel_kobj(struct hv_device *dev, struct vmbus_channel *channel) | ||
1281 | { | ||
1282 | struct kobject *kobj = &channel->kobj; | ||
1283 | u32 relid = channel->offermsg.child_relid; | ||
1284 | int ret; | ||
1285 | |||
1286 | kobj->kset = dev->channels_kset; | ||
1287 | ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL, | ||
1288 | "%u", relid); | ||
1289 | if (ret) | ||
1290 | return ret; | ||
1291 | |||
1292 | kobject_uevent(kobj, KOBJ_ADD); | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1136 | /* | 1297 | /* |
1137 | * vmbus_device_create - Creates and registers a new child device | 1298 | * vmbus_device_create - Creates and registers a new child device |
1138 | * on the vmbus. | 1299 | * on the vmbus. |
@@ -1164,7 +1325,8 @@ struct hv_device *vmbus_device_create(const uuid_le *type, | |||
1164 | */ | 1325 | */ |
1165 | int vmbus_device_register(struct hv_device *child_device_obj) | 1326 | int vmbus_device_register(struct hv_device *child_device_obj) |
1166 | { | 1327 | { |
1167 | int ret = 0; | 1328 | struct kobject *kobj = &child_device_obj->device.kobj; |
1329 | int ret; | ||
1168 | 1330 | ||
1169 | dev_set_name(&child_device_obj->device, "%pUl", | 1331 | dev_set_name(&child_device_obj->device, "%pUl", |
1170 | child_device_obj->channel->offermsg.offer.if_instance.b); | 1332 | child_device_obj->channel->offermsg.offer.if_instance.b); |
@@ -1178,13 +1340,32 @@ int vmbus_device_register(struct hv_device *child_device_obj) | |||
1178 | * binding...which will eventually call vmbus_match() and vmbus_probe() | 1340 | * binding...which will eventually call vmbus_match() and vmbus_probe() |
1179 | */ | 1341 | */ |
1180 | ret = device_register(&child_device_obj->device); | 1342 | ret = device_register(&child_device_obj->device); |
1181 | 1343 | if (ret) { | |
1182 | if (ret) | ||
1183 | pr_err("Unable to register child device\n"); | 1344 | pr_err("Unable to register child device\n"); |
1184 | else | 1345 | return ret; |
1185 | pr_debug("child device %s registered\n", | 1346 | } |
1186 | dev_name(&child_device_obj->device)); | 1347 | |
1348 | child_device_obj->channels_kset = kset_create_and_add("channels", | ||
1349 | NULL, kobj); | ||
1350 | if (!child_device_obj->channels_kset) { | ||
1351 | ret = -ENOMEM; | ||
1352 | goto err_dev_unregister; | ||
1353 | } | ||
1354 | |||
1355 | ret = vmbus_add_channel_kobj(child_device_obj, | ||
1356 | child_device_obj->channel); | ||
1357 | if (ret) { | ||
1358 | pr_err("Unable to register primary channeln"); | ||
1359 | goto err_kset_unregister; | ||
1360 | } | ||
1361 | |||
1362 | return 0; | ||
1363 | |||
1364 | err_kset_unregister: | ||
1365 | kset_unregister(child_device_obj->channels_kset); | ||
1187 | 1366 | ||
1367 | err_dev_unregister: | ||
1368 | device_unregister(&child_device_obj->device); | ||
1188 | return ret; | 1369 | return ret; |
1189 | } | 1370 | } |
1190 | 1371 | ||
diff --git a/drivers/hwtracing/coresight/coresight-dynamic-replicator.c b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c index accc2056f7c6..8f4357e2626c 100644 --- a/drivers/hwtracing/coresight/coresight-dynamic-replicator.c +++ b/drivers/hwtracing/coresight/coresight-dynamic-replicator.c | |||
@@ -199,8 +199,8 @@ static const struct dev_pm_ops replicator_dev_pm_ops = { | |||
199 | 199 | ||
200 | static const struct amba_id replicator_ids[] = { | 200 | static const struct amba_id replicator_ids[] = { |
201 | { | 201 | { |
202 | .id = 0x0003b909, | 202 | .id = 0x000bb909, |
203 | .mask = 0x0003ffff, | 203 | .mask = 0x000fffff, |
204 | }, | 204 | }, |
205 | { | 205 | { |
206 | /* Coresight SoC-600 */ | 206 | /* Coresight SoC-600 */ |
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 56ecd7aff5eb..e03e58933141 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c | |||
@@ -748,8 +748,8 @@ static const struct dev_pm_ops etb_dev_pm_ops = { | |||
748 | 748 | ||
749 | static const struct amba_id etb_ids[] = { | 749 | static const struct amba_id etb_ids[] = { |
750 | { | 750 | { |
751 | .id = 0x0003b907, | 751 | .id = 0x000bb907, |
752 | .mask = 0x0003ffff, | 752 | .mask = 0x000fffff, |
753 | }, | 753 | }, |
754 | { 0, 0}, | 754 | { 0, 0}, |
755 | }; | 755 | }; |
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index e5b1ec57dbde..39f42fdd503d 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c | |||
@@ -901,33 +901,33 @@ static const struct dev_pm_ops etm_dev_pm_ops = { | |||
901 | 901 | ||
902 | static const struct amba_id etm_ids[] = { | 902 | static const struct amba_id etm_ids[] = { |
903 | { /* ETM 3.3 */ | 903 | { /* ETM 3.3 */ |
904 | .id = 0x0003b921, | 904 | .id = 0x000bb921, |
905 | .mask = 0x0003ffff, | 905 | .mask = 0x000fffff, |
906 | .data = "ETM 3.3", | 906 | .data = "ETM 3.3", |
907 | }, | 907 | }, |
908 | { /* ETM 3.5 - Cortex-A5 */ | 908 | { /* ETM 3.5 - Cortex-A5 */ |
909 | .id = 0x0003b955, | 909 | .id = 0x000bb955, |
910 | .mask = 0x0003ffff, | 910 | .mask = 0x000fffff, |
911 | .data = "ETM 3.5", | 911 | .data = "ETM 3.5", |
912 | }, | 912 | }, |
913 | { /* ETM 3.5 */ | 913 | { /* ETM 3.5 */ |
914 | .id = 0x0003b956, | 914 | .id = 0x000bb956, |
915 | .mask = 0x0003ffff, | 915 | .mask = 0x000fffff, |
916 | .data = "ETM 3.5", | 916 | .data = "ETM 3.5", |
917 | }, | 917 | }, |
918 | { /* PTM 1.0 */ | 918 | { /* PTM 1.0 */ |
919 | .id = 0x0003b950, | 919 | .id = 0x000bb950, |
920 | .mask = 0x0003ffff, | 920 | .mask = 0x000fffff, |
921 | .data = "PTM 1.0", | 921 | .data = "PTM 1.0", |
922 | }, | 922 | }, |
923 | { /* PTM 1.1 */ | 923 | { /* PTM 1.1 */ |
924 | .id = 0x0003b95f, | 924 | .id = 0x000bb95f, |
925 | .mask = 0x0003ffff, | 925 | .mask = 0x000fffff, |
926 | .data = "PTM 1.1", | 926 | .data = "PTM 1.1", |
927 | }, | 927 | }, |
928 | { /* PTM 1.1 Qualcomm */ | 928 | { /* PTM 1.1 Qualcomm */ |
929 | .id = 0x0003006f, | 929 | .id = 0x000b006f, |
930 | .mask = 0x0003ffff, | 930 | .mask = 0x000fffff, |
931 | .data = "PTM 1.1", | 931 | .data = "PTM 1.1", |
932 | }, | 932 | }, |
933 | { 0, 0}, | 933 | { 0, 0}, |
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 77642e0e955b..fd3c396717f6 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c | |||
@@ -248,8 +248,8 @@ static const struct dev_pm_ops funnel_dev_pm_ops = { | |||
248 | 248 | ||
249 | static const struct amba_id funnel_ids[] = { | 249 | static const struct amba_id funnel_ids[] = { |
250 | { | 250 | { |
251 | .id = 0x0003b908, | 251 | .id = 0x000bb908, |
252 | .mask = 0x0003ffff, | 252 | .mask = 0x000fffff, |
253 | }, | 253 | }, |
254 | { | 254 | { |
255 | /* Coresight SoC-600 */ | 255 | /* Coresight SoC-600 */ |
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 92a780a6df1d..15e7ef3891f5 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c | |||
@@ -917,13 +917,13 @@ static const struct dev_pm_ops stm_dev_pm_ops = { | |||
917 | 917 | ||
918 | static const struct amba_id stm_ids[] = { | 918 | static const struct amba_id stm_ids[] = { |
919 | { | 919 | { |
920 | .id = 0x0003b962, | 920 | .id = 0x000bb962, |
921 | .mask = 0x0003ffff, | 921 | .mask = 0x000fffff, |
922 | .data = "STM32", | 922 | .data = "STM32", |
923 | }, | 923 | }, |
924 | { | 924 | { |
925 | .id = 0x0003b963, | 925 | .id = 0x000bb963, |
926 | .mask = 0x0003ffff, | 926 | .mask = 0x000fffff, |
927 | .data = "STM500", | 927 | .data = "STM500", |
928 | }, | 928 | }, |
929 | { 0, 0}, | 929 | { 0, 0}, |
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 2ff4a66a3caa..0ea04f588de0 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c | |||
@@ -439,8 +439,8 @@ out: | |||
439 | 439 | ||
440 | static const struct amba_id tmc_ids[] = { | 440 | static const struct amba_id tmc_ids[] = { |
441 | { | 441 | { |
442 | .id = 0x0003b961, | 442 | .id = 0x000bb961, |
443 | .mask = 0x0003ffff, | 443 | .mask = 0x000fffff, |
444 | }, | 444 | }, |
445 | { | 445 | { |
446 | /* Coresight SoC 600 TMC-ETR/ETS */ | 446 | /* Coresight SoC 600 TMC-ETR/ETS */ |
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index d7a3e453016d..bef49a3a5ca7 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c | |||
@@ -194,8 +194,8 @@ static const struct dev_pm_ops tpiu_dev_pm_ops = { | |||
194 | 194 | ||
195 | static const struct amba_id tpiu_ids[] = { | 195 | static const struct amba_id tpiu_ids[] = { |
196 | { | 196 | { |
197 | .id = 0x0003b912, | 197 | .id = 0x000bb912, |
198 | .mask = 0x0003ffff, | 198 | .mask = 0x000fffff, |
199 | }, | 199 | }, |
200 | { | 200 | { |
201 | .id = 0x0004b912, | 201 | .id = 0x0004b912, |
diff --git a/drivers/misc/altera-stapl/Kconfig b/drivers/misc/altera-stapl/Kconfig index 7f01d8e93992..8a828fe41fad 100644 --- a/drivers/misc/altera-stapl/Kconfig +++ b/drivers/misc/altera-stapl/Kconfig | |||
@@ -1,4 +1,5 @@ | |||
1 | comment "Altera FPGA firmware download module" | 1 | comment "Altera FPGA firmware download module (requires I2C)" |
2 | depends on !I2C | ||
2 | 3 | ||
3 | config ALTERA_STAPL | 4 | config ALTERA_STAPL |
4 | tristate "Altera FPGA firmware download module" | 5 | tristate "Altera FPGA firmware download module" |
diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h index 5813b5f25006..3743c87f8ab9 100644 --- a/drivers/misc/genwqe/card_base.h +++ b/drivers/misc/genwqe/card_base.h | |||
@@ -182,6 +182,7 @@ struct dma_mapping { | |||
182 | 182 | ||
183 | struct list_head card_list; /* list of usr_maps for card */ | 183 | struct list_head card_list; /* list of usr_maps for card */ |
184 | struct list_head pin_list; /* list of pinned memory for dev */ | 184 | struct list_head pin_list; /* list of pinned memory for dev */ |
185 | int write; /* writable map? useful in unmapping */ | ||
185 | }; | 186 | }; |
186 | 187 | ||
187 | static inline void genwqe_mapping_init(struct dma_mapping *m, | 188 | static inline void genwqe_mapping_init(struct dma_mapping *m, |
@@ -189,6 +190,7 @@ static inline void genwqe_mapping_init(struct dma_mapping *m, | |||
189 | { | 190 | { |
190 | memset(m, 0, sizeof(*m)); | 191 | memset(m, 0, sizeof(*m)); |
191 | m->type = type; | 192 | m->type = type; |
193 | m->write = 1; /* Assume the maps we create are R/W */ | ||
192 | } | 194 | } |
193 | 195 | ||
194 | /** | 196 | /** |
@@ -347,6 +349,7 @@ enum genwqe_requ_state { | |||
347 | * @user_size: size of user-space memory area | 349 | * @user_size: size of user-space memory area |
348 | * @page: buffer for partial pages if needed | 350 | * @page: buffer for partial pages if needed |
349 | * @page_dma_addr: dma address partial pages | 351 | * @page_dma_addr: dma address partial pages |
352 | * @write: should we write it back to userspace? | ||
350 | */ | 353 | */ |
351 | struct genwqe_sgl { | 354 | struct genwqe_sgl { |
352 | dma_addr_t sgl_dma_addr; | 355 | dma_addr_t sgl_dma_addr; |
@@ -356,6 +359,8 @@ struct genwqe_sgl { | |||
356 | void __user *user_addr; /* user-space base-address */ | 359 | void __user *user_addr; /* user-space base-address */ |
357 | size_t user_size; /* size of memory area */ | 360 | size_t user_size; /* size of memory area */ |
358 | 361 | ||
362 | int write; | ||
363 | |||
359 | unsigned long nr_pages; | 364 | unsigned long nr_pages; |
360 | unsigned long fpage_offs; | 365 | unsigned long fpage_offs; |
361 | size_t fpage_size; | 366 | size_t fpage_size; |
@@ -369,7 +374,7 @@ struct genwqe_sgl { | |||
369 | }; | 374 | }; |
370 | 375 | ||
371 | int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, | 376 | int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, |
372 | void __user *user_addr, size_t user_size); | 377 | void __user *user_addr, size_t user_size, int write); |
373 | 378 | ||
374 | int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, | 379 | int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, |
375 | dma_addr_t *dma_list); | 380 | dma_addr_t *dma_list); |
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index dd4617764f14..3ecfa35457e0 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c | |||
@@ -942,6 +942,10 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req) | |||
942 | 942 | ||
943 | genwqe_mapping_init(m, | 943 | genwqe_mapping_init(m, |
944 | GENWQE_MAPPING_SGL_TEMP); | 944 | GENWQE_MAPPING_SGL_TEMP); |
945 | |||
946 | if (ats_flags == ATS_TYPE_SGL_RD) | ||
947 | m->write = 0; | ||
948 | |||
945 | rc = genwqe_user_vmap(cd, m, (void *)u_addr, | 949 | rc = genwqe_user_vmap(cd, m, (void *)u_addr, |
946 | u_size, req); | 950 | u_size, req); |
947 | if (rc != 0) | 951 | if (rc != 0) |
@@ -954,7 +958,7 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req) | |||
954 | /* create genwqe style scatter gather list */ | 958 | /* create genwqe style scatter gather list */ |
955 | rc = genwqe_alloc_sync_sgl(cd, &req->sgls[i], | 959 | rc = genwqe_alloc_sync_sgl(cd, &req->sgls[i], |
956 | (void __user *)u_addr, | 960 | (void __user *)u_addr, |
957 | u_size); | 961 | u_size, m->write); |
958 | if (rc != 0) | 962 | if (rc != 0) |
959 | goto err_out; | 963 | goto err_out; |
960 | 964 | ||
diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 147b83011b58..5c0d917636f7 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c | |||
@@ -296,7 +296,7 @@ static int genwqe_sgl_size(int num_pages) | |||
296 | * from user-space into the cached pages. | 296 | * from user-space into the cached pages. |
297 | */ | 297 | */ |
298 | int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, | 298 | int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, |
299 | void __user *user_addr, size_t user_size) | 299 | void __user *user_addr, size_t user_size, int write) |
300 | { | 300 | { |
301 | int rc; | 301 | int rc; |
302 | struct pci_dev *pci_dev = cd->pci_dev; | 302 | struct pci_dev *pci_dev = cd->pci_dev; |
@@ -312,6 +312,7 @@ int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, | |||
312 | 312 | ||
313 | sgl->user_addr = user_addr; | 313 | sgl->user_addr = user_addr; |
314 | sgl->user_size = user_size; | 314 | sgl->user_size = user_size; |
315 | sgl->write = write; | ||
315 | sgl->sgl_size = genwqe_sgl_size(sgl->nr_pages); | 316 | sgl->sgl_size = genwqe_sgl_size(sgl->nr_pages); |
316 | 317 | ||
317 | if (get_order(sgl->sgl_size) > MAX_ORDER) { | 318 | if (get_order(sgl->sgl_size) > MAX_ORDER) { |
@@ -476,14 +477,20 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, | |||
476 | int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl) | 477 | int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl) |
477 | { | 478 | { |
478 | int rc = 0; | 479 | int rc = 0; |
480 | size_t offset; | ||
481 | unsigned long res; | ||
479 | struct pci_dev *pci_dev = cd->pci_dev; | 482 | struct pci_dev *pci_dev = cd->pci_dev; |
480 | 483 | ||
481 | if (sgl->fpage) { | 484 | if (sgl->fpage) { |
482 | if (copy_to_user(sgl->user_addr, sgl->fpage + sgl->fpage_offs, | 485 | if (sgl->write) { |
483 | sgl->fpage_size)) { | 486 | res = copy_to_user(sgl->user_addr, |
484 | dev_err(&pci_dev->dev, "[%s] err: copying fpage!\n", | 487 | sgl->fpage + sgl->fpage_offs, sgl->fpage_size); |
485 | __func__); | 488 | if (res) { |
486 | rc = -EFAULT; | 489 | dev_err(&pci_dev->dev, |
490 | "[%s] err: copying fpage! (res=%lu)\n", | ||
491 | __func__, res); | ||
492 | rc = -EFAULT; | ||
493 | } | ||
487 | } | 494 | } |
488 | __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, | 495 | __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, |
489 | sgl->fpage_dma_addr); | 496 | sgl->fpage_dma_addr); |
@@ -491,12 +498,16 @@ int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl) | |||
491 | sgl->fpage_dma_addr = 0; | 498 | sgl->fpage_dma_addr = 0; |
492 | } | 499 | } |
493 | if (sgl->lpage) { | 500 | if (sgl->lpage) { |
494 | if (copy_to_user(sgl->user_addr + sgl->user_size - | 501 | if (sgl->write) { |
495 | sgl->lpage_size, sgl->lpage, | 502 | offset = sgl->user_size - sgl->lpage_size; |
496 | sgl->lpage_size)) { | 503 | res = copy_to_user(sgl->user_addr + offset, sgl->lpage, |
497 | dev_err(&pci_dev->dev, "[%s] err: copying lpage!\n", | 504 | sgl->lpage_size); |
498 | __func__); | 505 | if (res) { |
499 | rc = -EFAULT; | 506 | dev_err(&pci_dev->dev, |
507 | "[%s] err: copying lpage! (res=%lu)\n", | ||
508 | __func__, res); | ||
509 | rc = -EFAULT; | ||
510 | } | ||
500 | } | 511 | } |
501 | __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage, | 512 | __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage, |
502 | sgl->lpage_dma_addr); | 513 | sgl->lpage_dma_addr); |
@@ -599,14 +610,14 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr, | |||
599 | /* pin user pages in memory */ | 610 | /* pin user pages in memory */ |
600 | rc = get_user_pages_fast(data & PAGE_MASK, /* page aligned addr */ | 611 | rc = get_user_pages_fast(data & PAGE_MASK, /* page aligned addr */ |
601 | m->nr_pages, | 612 | m->nr_pages, |
602 | 1, /* write by caller */ | 613 | m->write, /* readable/writable */ |
603 | m->page_list); /* ptrs to pages */ | 614 | m->page_list); /* ptrs to pages */ |
604 | if (rc < 0) | 615 | if (rc < 0) |
605 | goto fail_get_user_pages; | 616 | goto fail_get_user_pages; |
606 | 617 | ||
607 | /* assumption: get_user_pages can be killed by signals. */ | 618 | /* assumption: get_user_pages can be killed by signals. */ |
608 | if (rc < m->nr_pages) { | 619 | if (rc < m->nr_pages) { |
609 | free_user_pages(m->page_list, rc, 0); | 620 | free_user_pages(m->page_list, rc, m->write); |
610 | rc = -EFAULT; | 621 | rc = -EFAULT; |
611 | goto fail_get_user_pages; | 622 | goto fail_get_user_pages; |
612 | } | 623 | } |
@@ -618,7 +629,7 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr, | |||
618 | return 0; | 629 | return 0; |
619 | 630 | ||
620 | fail_free_user_pages: | 631 | fail_free_user_pages: |
621 | free_user_pages(m->page_list, m->nr_pages, 0); | 632 | free_user_pages(m->page_list, m->nr_pages, m->write); |
622 | 633 | ||
623 | fail_get_user_pages: | 634 | fail_get_user_pages: |
624 | kfree(m->page_list); | 635 | kfree(m->page_list); |
@@ -651,7 +662,7 @@ int genwqe_user_vunmap(struct genwqe_dev *cd, struct dma_mapping *m, | |||
651 | genwqe_unmap_pages(cd, m->dma_list, m->nr_pages); | 662 | genwqe_unmap_pages(cd, m->dma_list, m->nr_pages); |
652 | 663 | ||
653 | if (m->page_list) { | 664 | if (m->page_list) { |
654 | free_user_pages(m->page_list, m->nr_pages, 1); | 665 | free_user_pages(m->page_list, m->nr_pages, m->write); |
655 | 666 | ||
656 | kfree(m->page_list); | 667 | kfree(m->page_list); |
657 | m->page_list = NULL; | 668 | m->page_list = NULL; |
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c index ed7f0c61c59a..ba92291508dc 100644 --- a/drivers/misc/lkdtm_core.c +++ b/drivers/misc/lkdtm_core.c | |||
@@ -122,7 +122,7 @@ struct crashtype { | |||
122 | } | 122 | } |
123 | 123 | ||
124 | /* Define the possible types of crashes that can be triggered. */ | 124 | /* Define the possible types of crashes that can be triggered. */ |
125 | struct crashtype crashtypes[] = { | 125 | static const struct crashtype crashtypes[] = { |
126 | CRASHTYPE(PANIC), | 126 | CRASHTYPE(PANIC), |
127 | CRASHTYPE(BUG), | 127 | CRASHTYPE(BUG), |
128 | CRASHTYPE(WARNING), | 128 | CRASHTYPE(WARNING), |
@@ -188,8 +188,8 @@ struct crashtype crashtypes[] = { | |||
188 | 188 | ||
189 | /* Global kprobe entry and crashtype. */ | 189 | /* Global kprobe entry and crashtype. */ |
190 | static struct kprobe *lkdtm_kprobe; | 190 | static struct kprobe *lkdtm_kprobe; |
191 | struct crashpoint *lkdtm_crashpoint; | 191 | static struct crashpoint *lkdtm_crashpoint; |
192 | struct crashtype *lkdtm_crashtype; | 192 | static const struct crashtype *lkdtm_crashtype; |
193 | 193 | ||
194 | /* Module parameters */ | 194 | /* Module parameters */ |
195 | static int recur_count = -1; | 195 | static int recur_count = -1; |
@@ -212,7 +212,7 @@ MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ | |||
212 | 212 | ||
213 | 213 | ||
214 | /* Return the crashtype number or NULL if the name is invalid */ | 214 | /* Return the crashtype number or NULL if the name is invalid */ |
215 | static struct crashtype *find_crashtype(const char *name) | 215 | static const struct crashtype *find_crashtype(const char *name) |
216 | { | 216 | { |
217 | int i; | 217 | int i; |
218 | 218 | ||
@@ -228,7 +228,7 @@ static struct crashtype *find_crashtype(const char *name) | |||
228 | * This is forced noinline just so it distinctly shows up in the stackdump | 228 | * This is forced noinline just so it distinctly shows up in the stackdump |
229 | * which makes validation of expected lkdtm crashes easier. | 229 | * which makes validation of expected lkdtm crashes easier. |
230 | */ | 230 | */ |
231 | static noinline void lkdtm_do_action(struct crashtype *crashtype) | 231 | static noinline void lkdtm_do_action(const struct crashtype *crashtype) |
232 | { | 232 | { |
233 | if (WARN_ON(!crashtype || !crashtype->func)) | 233 | if (WARN_ON(!crashtype || !crashtype->func)) |
234 | return; | 234 | return; |
@@ -236,7 +236,7 @@ static noinline void lkdtm_do_action(struct crashtype *crashtype) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | static int lkdtm_register_cpoint(struct crashpoint *crashpoint, | 238 | static int lkdtm_register_cpoint(struct crashpoint *crashpoint, |
239 | struct crashtype *crashtype) | 239 | const struct crashtype *crashtype) |
240 | { | 240 | { |
241 | int ret; | 241 | int ret; |
242 | 242 | ||
@@ -300,7 +300,7 @@ static ssize_t lkdtm_debugfs_entry(struct file *f, | |||
300 | size_t count, loff_t *off) | 300 | size_t count, loff_t *off) |
301 | { | 301 | { |
302 | struct crashpoint *crashpoint = file_inode(f)->i_private; | 302 | struct crashpoint *crashpoint = file_inode(f)->i_private; |
303 | struct crashtype *crashtype = NULL; | 303 | const struct crashtype *crashtype = NULL; |
304 | char *buf; | 304 | char *buf; |
305 | int err; | 305 | int err; |
306 | 306 | ||
@@ -368,7 +368,7 @@ static int lkdtm_debugfs_open(struct inode *inode, struct file *file) | |||
368 | static ssize_t direct_entry(struct file *f, const char __user *user_buf, | 368 | static ssize_t direct_entry(struct file *f, const char __user *user_buf, |
369 | size_t count, loff_t *off) | 369 | size_t count, loff_t *off) |
370 | { | 370 | { |
371 | struct crashtype *crashtype; | 371 | const struct crashtype *crashtype; |
372 | char *buf; | 372 | char *buf; |
373 | 373 | ||
374 | if (count >= PAGE_SIZE) | 374 | if (count >= PAGE_SIZE) |
@@ -404,7 +404,7 @@ static struct dentry *lkdtm_debugfs_root; | |||
404 | static int __init lkdtm_module_init(void) | 404 | static int __init lkdtm_module_init(void) |
405 | { | 405 | { |
406 | struct crashpoint *crashpoint = NULL; | 406 | struct crashpoint *crashpoint = NULL; |
407 | struct crashtype *crashtype = NULL; | 407 | const struct crashtype *crashtype = NULL; |
408 | int ret = -EINVAL; | 408 | int ret = -EINVAL; |
409 | int i; | 409 | int i; |
410 | 410 | ||
diff --git a/drivers/misc/mei/mei-trace.c b/drivers/misc/mei/mei-trace.c index e19e6acb191b..374edde72a14 100644 --- a/drivers/misc/mei/mei-trace.c +++ b/drivers/misc/mei/mei-trace.c | |||
@@ -23,5 +23,4 @@ | |||
23 | EXPORT_TRACEPOINT_SYMBOL(mei_reg_read); | 23 | EXPORT_TRACEPOINT_SYMBOL(mei_reg_read); |
24 | EXPORT_TRACEPOINT_SYMBOL(mei_reg_write); | 24 | EXPORT_TRACEPOINT_SYMBOL(mei_reg_write); |
25 | EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_read); | 25 | EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_read); |
26 | EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_write); | ||
27 | #endif /* __CHECKER__ */ | 26 | #endif /* __CHECKER__ */ |
diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h index 7d2d5d4a1624..b52e9b97a7c0 100644 --- a/drivers/misc/mei/mei-trace.h +++ b/drivers/misc/mei/mei-trace.h | |||
@@ -83,25 +83,6 @@ TRACE_EVENT(mei_pci_cfg_read, | |||
83 | __get_str(dev), __entry->reg, __entry->offs, __entry->val) | 83 | __get_str(dev), __entry->reg, __entry->offs, __entry->val) |
84 | ); | 84 | ); |
85 | 85 | ||
86 | TRACE_EVENT(mei_pci_cfg_write, | ||
87 | TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val), | ||
88 | TP_ARGS(dev, reg, offs, val), | ||
89 | TP_STRUCT__entry( | ||
90 | __string(dev, dev_name(dev)) | ||
91 | __field(const char *, reg) | ||
92 | __field(u32, offs) | ||
93 | __field(u32, val) | ||
94 | ), | ||
95 | TP_fast_assign( | ||
96 | __assign_str(dev, dev_name(dev)) | ||
97 | __entry->reg = reg; | ||
98 | __entry->offs = offs; | ||
99 | __entry->val = val; | ||
100 | ), | ||
101 | TP_printk("[%s] pci cfg write %s[%#x] = %#x", | ||
102 | __get_str(dev), __entry->reg, __entry->offs, __entry->val) | ||
103 | ); | ||
104 | |||
105 | #endif /* _MEI_TRACE_H_ */ | 86 | #endif /* _MEI_TRACE_H_ */ |
106 | 87 | ||
107 | /* This part must be outside protection */ | 88 | /* This part must be outside protection */ |
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig index 6fd9d367dea7..227cc7443671 100644 --- a/drivers/misc/mic/Kconfig +++ b/drivers/misc/mic/Kconfig | |||
@@ -1,3 +1,5 @@ | |||
1 | menu "Intel MIC & related support" | ||
2 | |||
1 | comment "Intel MIC Bus Driver" | 3 | comment "Intel MIC Bus Driver" |
2 | 4 | ||
3 | config INTEL_MIC_BUS | 5 | config INTEL_MIC_BUS |
@@ -150,3 +152,5 @@ config VOP | |||
150 | if VOP | 152 | if VOP |
151 | source "drivers/vhost/Kconfig.vringh" | 153 | source "drivers/vhost/Kconfig.vringh" |
152 | endif | 154 | endif |
155 | |||
156 | endmenu | ||
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 101ced4c84be..ff505af064ba 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig | |||
@@ -123,6 +123,17 @@ config NVMEM_SUNXI_SID | |||
123 | This driver can also be built as a module. If so, the module | 123 | This driver can also be built as a module. If so, the module |
124 | will be called nvmem_sunxi_sid. | 124 | will be called nvmem_sunxi_sid. |
125 | 125 | ||
126 | config UNIPHIER_EFUSE | ||
127 | tristate "UniPhier SoCs eFuse support" | ||
128 | depends on ARCH_UNIPHIER || COMPILE_TEST | ||
129 | depends on HAS_IOMEM | ||
130 | help | ||
131 | This is a simple driver to dump specified values of UniPhier SoC | ||
132 | from eFuse. | ||
133 | |||
134 | This driver can also be built as a module. If so, the module | ||
135 | will be called nvmem-uniphier-efuse. | ||
136 | |||
126 | config NVMEM_VF610_OCOTP | 137 | config NVMEM_VF610_OCOTP |
127 | tristate "VF610 SoC OCOTP support" | 138 | tristate "VF610 SoC OCOTP support" |
128 | depends on SOC_VF610 || COMPILE_TEST | 139 | depends on SOC_VF610 || COMPILE_TEST |
@@ -135,13 +146,33 @@ config NVMEM_VF610_OCOTP | |||
135 | be called nvmem-vf610-ocotp. | 146 | be called nvmem-vf610-ocotp. |
136 | 147 | ||
137 | config MESON_EFUSE | 148 | config MESON_EFUSE |
138 | tristate "Amlogic eFuse Support" | 149 | tristate "Amlogic Meson GX eFuse Support" |
139 | depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM | 150 | depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM |
140 | help | 151 | help |
141 | This is a driver to retrieve specific values from the eFuse found on | 152 | This is a driver to retrieve specific values from the eFuse found on |
142 | the Amlogic Meson SoCs. | 153 | the Amlogic Meson GX SoCs. |
143 | 154 | ||
144 | This driver can also be built as a module. If so, the module | 155 | This driver can also be built as a module. If so, the module |
145 | will be called nvmem_meson_efuse. | 156 | will be called nvmem_meson_efuse. |
146 | 157 | ||
158 | config MESON_MX_EFUSE | ||
159 | tristate "Amlogic Meson6/Meson8/Meson8b eFuse Support" | ||
160 | depends on ARCH_MESON || COMPILE_TEST | ||
161 | help | ||
162 | This is a driver to retrieve specific values from the eFuse found on | ||
163 | the Amlogic Meson6, Meson8 and Meson8b SoCs. | ||
164 | |||
165 | This driver can also be built as a module. If so, the module | ||
166 | will be called nvmem_meson_mx_efuse. | ||
167 | |||
168 | config NVMEM_SNVS_LPGPR | ||
169 | tristate "Support for Low Power General Purpose Register" | ||
170 | depends on SOC_IMX6 || COMPILE_TEST | ||
171 | help | ||
172 | This is a driver for Low Power General Purpose Register (LPGPR) available on | ||
173 | i.MX6 SoCs in Secure Non-Volatile Storage (SNVS) of this chip. | ||
174 | |||
175 | This driver can also be built as a module. If so, the module | ||
176 | will be called nvmem-snvs-lpgpr. | ||
177 | |||
147 | endif | 178 | endif |
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 6f7a77fb3ee7..e54dcfa6565a 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile | |||
@@ -27,7 +27,13 @@ obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o | |||
27 | nvmem_rockchip_efuse-y := rockchip-efuse.o | 27 | nvmem_rockchip_efuse-y := rockchip-efuse.o |
28 | obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o | 28 | obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o |
29 | nvmem_sunxi_sid-y := sunxi_sid.o | 29 | nvmem_sunxi_sid-y := sunxi_sid.o |
30 | obj-$(CONFIG_UNIPHIER_EFUSE) += nvmem-uniphier-efuse.o | ||
31 | nvmem-uniphier-efuse-y := uniphier-efuse.o | ||
30 | obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o | 32 | obj-$(CONFIG_NVMEM_VF610_OCOTP) += nvmem-vf610-ocotp.o |
31 | nvmem-vf610-ocotp-y := vf610-ocotp.o | 33 | nvmem-vf610-ocotp-y := vf610-ocotp.o |
32 | obj-$(CONFIG_MESON_EFUSE) += nvmem_meson_efuse.o | 34 | obj-$(CONFIG_MESON_EFUSE) += nvmem_meson_efuse.o |
33 | nvmem_meson_efuse-y := meson-efuse.o | 35 | nvmem_meson_efuse-y := meson-efuse.o |
36 | obj-$(CONFIG_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o | ||
37 | nvmem_meson_mx_efuse-y := meson-mx-efuse.o | ||
38 | obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o | ||
39 | nvmem_snvs_lpgpr-y := snvs_lpgpr.o | ||
diff --git a/drivers/nvmem/bcm-ocotp.c b/drivers/nvmem/bcm-ocotp.c index 3c56e3b2bd65..5e9e324427f9 100644 --- a/drivers/nvmem/bcm-ocotp.c +++ b/drivers/nvmem/bcm-ocotp.c | |||
@@ -232,7 +232,6 @@ static struct nvmem_config bcm_otpc_nvmem_config = { | |||
232 | .read_only = false, | 232 | .read_only = false, |
233 | .word_size = 4, | 233 | .word_size = 4, |
234 | .stride = 4, | 234 | .stride = 4, |
235 | .owner = THIS_MODULE, | ||
236 | .reg_read = bcm_otpc_read, | 235 | .reg_read = bcm_otpc_read, |
237 | .reg_write = bcm_otpc_write, | 236 | .reg_write = bcm_otpc_write, |
238 | }; | 237 | }; |
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index d12e5de78e70..5a5cefd12153 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c | |||
@@ -462,6 +462,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) | |||
462 | 462 | ||
463 | nvmem->id = rval; | 463 | nvmem->id = rval; |
464 | nvmem->owner = config->owner; | 464 | nvmem->owner = config->owner; |
465 | if (!nvmem->owner && config->dev->driver) | ||
466 | nvmem->owner = config->dev->driver->owner; | ||
465 | nvmem->stride = config->stride; | 467 | nvmem->stride = config->stride; |
466 | nvmem->word_size = config->word_size; | 468 | nvmem->word_size = config->word_size; |
467 | nvmem->size = config->size; | 469 | nvmem->size = config->size; |
@@ -615,7 +617,7 @@ static struct nvmem_device *nvmem_find(const char *name) | |||
615 | return to_nvmem_device(d); | 617 | return to_nvmem_device(d); |
616 | } | 618 | } |
617 | 619 | ||
618 | #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) | 620 | #if IS_ENABLED(CONFIG_OF) |
619 | /** | 621 | /** |
620 | * of_nvmem_device_get() - Get nvmem device from a given id | 622 | * of_nvmem_device_get() - Get nvmem device from a given id |
621 | * | 623 | * |
@@ -753,7 +755,7 @@ static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id) | |||
753 | return cell; | 755 | return cell; |
754 | } | 756 | } |
755 | 757 | ||
756 | #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) | 758 | #if IS_ENABLED(CONFIG_OF) |
757 | /** | 759 | /** |
758 | * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id | 760 | * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id |
759 | * | 761 | * |
@@ -946,8 +948,7 @@ void nvmem_cell_put(struct nvmem_cell *cell) | |||
946 | } | 948 | } |
947 | EXPORT_SYMBOL_GPL(nvmem_cell_put); | 949 | EXPORT_SYMBOL_GPL(nvmem_cell_put); |
948 | 950 | ||
949 | static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, | 951 | static void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf) |
950 | void *buf) | ||
951 | { | 952 | { |
952 | u8 *p, *b; | 953 | u8 *p, *b; |
953 | int i, bit_offset = cell->bit_offset; | 954 | int i, bit_offset = cell->bit_offset; |
@@ -1028,8 +1029,8 @@ void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len) | |||
1028 | } | 1029 | } |
1029 | EXPORT_SYMBOL_GPL(nvmem_cell_read); | 1030 | EXPORT_SYMBOL_GPL(nvmem_cell_read); |
1030 | 1031 | ||
1031 | static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell, | 1032 | static void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell, |
1032 | u8 *_buf, int len) | 1033 | u8 *_buf, int len) |
1033 | { | 1034 | { |
1034 | struct nvmem_device *nvmem = cell->nvmem; | 1035 | struct nvmem_device *nvmem = cell->nvmem; |
1035 | int i, rc, nbits, bit_offset = cell->bit_offset; | 1036 | int i, rc, nbits, bit_offset = cell->bit_offset; |
diff --git a/drivers/nvmem/imx-iim.c b/drivers/nvmem/imx-iim.c index 52ff65e0673f..52cfe91d9762 100644 --- a/drivers/nvmem/imx-iim.c +++ b/drivers/nvmem/imx-iim.c | |||
@@ -34,7 +34,6 @@ struct imx_iim_drvdata { | |||
34 | struct iim_priv { | 34 | struct iim_priv { |
35 | void __iomem *base; | 35 | void __iomem *base; |
36 | struct clk *clk; | 36 | struct clk *clk; |
37 | struct nvmem_config nvmem; | ||
38 | }; | 37 | }; |
39 | 38 | ||
40 | static int imx_iim_read(void *context, unsigned int offset, | 39 | static int imx_iim_read(void *context, unsigned int offset, |
@@ -108,7 +107,7 @@ static int imx_iim_probe(struct platform_device *pdev) | |||
108 | struct resource *res; | 107 | struct resource *res; |
109 | struct iim_priv *iim; | 108 | struct iim_priv *iim; |
110 | struct nvmem_device *nvmem; | 109 | struct nvmem_device *nvmem; |
111 | struct nvmem_config *cfg; | 110 | struct nvmem_config cfg = {}; |
112 | const struct imx_iim_drvdata *drvdata = NULL; | 111 | const struct imx_iim_drvdata *drvdata = NULL; |
113 | 112 | ||
114 | iim = devm_kzalloc(dev, sizeof(*iim), GFP_KERNEL); | 113 | iim = devm_kzalloc(dev, sizeof(*iim), GFP_KERNEL); |
@@ -130,19 +129,16 @@ static int imx_iim_probe(struct platform_device *pdev) | |||
130 | if (IS_ERR(iim->clk)) | 129 | if (IS_ERR(iim->clk)) |
131 | return PTR_ERR(iim->clk); | 130 | return PTR_ERR(iim->clk); |
132 | 131 | ||
133 | cfg = &iim->nvmem; | 132 | cfg.name = "imx-iim", |
133 | cfg.read_only = true, | ||
134 | cfg.word_size = 1, | ||
135 | cfg.stride = 1, | ||
136 | cfg.reg_read = imx_iim_read, | ||
137 | cfg.dev = dev; | ||
138 | cfg.size = drvdata->nregs; | ||
139 | cfg.priv = iim; | ||
134 | 140 | ||
135 | cfg->name = "imx-iim", | 141 | nvmem = nvmem_register(&cfg); |
136 | cfg->read_only = true, | ||
137 | cfg->word_size = 1, | ||
138 | cfg->stride = 1, | ||
139 | cfg->owner = THIS_MODULE, | ||
140 | cfg->reg_read = imx_iim_read, | ||
141 | cfg->dev = dev; | ||
142 | cfg->size = drvdata->nregs; | ||
143 | cfg->priv = iim; | ||
144 | |||
145 | nvmem = nvmem_register(cfg); | ||
146 | if (IS_ERR(nvmem)) | 142 | if (IS_ERR(nvmem)) |
147 | return PTR_ERR(nvmem); | 143 | return PTR_ERR(nvmem); |
148 | 144 | ||
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index 193ca8fd350a..d7ba351a70c9 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c | |||
@@ -40,14 +40,19 @@ | |||
40 | #define IMX_OCOTP_ADDR_CTRL_SET 0x0004 | 40 | #define IMX_OCOTP_ADDR_CTRL_SET 0x0004 |
41 | #define IMX_OCOTP_ADDR_CTRL_CLR 0x0008 | 41 | #define IMX_OCOTP_ADDR_CTRL_CLR 0x0008 |
42 | #define IMX_OCOTP_ADDR_TIMING 0x0010 | 42 | #define IMX_OCOTP_ADDR_TIMING 0x0010 |
43 | #define IMX_OCOTP_ADDR_DATA 0x0020 | 43 | #define IMX_OCOTP_ADDR_DATA0 0x0020 |
44 | #define IMX_OCOTP_ADDR_DATA1 0x0030 | ||
45 | #define IMX_OCOTP_ADDR_DATA2 0x0040 | ||
46 | #define IMX_OCOTP_ADDR_DATA3 0x0050 | ||
44 | 47 | ||
45 | #define IMX_OCOTP_BM_CTRL_ADDR 0x0000007F | 48 | #define IMX_OCOTP_BM_CTRL_ADDR 0x0000007F |
46 | #define IMX_OCOTP_BM_CTRL_BUSY 0x00000100 | 49 | #define IMX_OCOTP_BM_CTRL_BUSY 0x00000100 |
47 | #define IMX_OCOTP_BM_CTRL_ERROR 0x00000200 | 50 | #define IMX_OCOTP_BM_CTRL_ERROR 0x00000200 |
48 | #define IMX_OCOTP_BM_CTRL_REL_SHADOWS 0x00000400 | 51 | #define IMX_OCOTP_BM_CTRL_REL_SHADOWS 0x00000400 |
49 | 52 | ||
50 | #define DEF_RELAX 20 /* > 16.5ns */ | 53 | #define DEF_RELAX 20 /* > 16.5ns */ |
54 | #define DEF_FSOURCE 1001 /* > 1000 ns */ | ||
55 | #define DEF_STROBE_PROG 10000 /* IPG clocks */ | ||
51 | #define IMX_OCOTP_WR_UNLOCK 0x3E770000 | 56 | #define IMX_OCOTP_WR_UNLOCK 0x3E770000 |
52 | #define IMX_OCOTP_READ_LOCKED_VAL 0xBADABADA | 57 | #define IMX_OCOTP_READ_LOCKED_VAL 0xBADABADA |
53 | 58 | ||
@@ -57,10 +62,16 @@ struct ocotp_priv { | |||
57 | struct device *dev; | 62 | struct device *dev; |
58 | struct clk *clk; | 63 | struct clk *clk; |
59 | void __iomem *base; | 64 | void __iomem *base; |
60 | unsigned int nregs; | 65 | const struct ocotp_params *params; |
61 | struct nvmem_config *config; | 66 | struct nvmem_config *config; |
62 | }; | 67 | }; |
63 | 68 | ||
69 | struct ocotp_params { | ||
70 | unsigned int nregs; | ||
71 | unsigned int bank_address_words; | ||
72 | void (*set_timing)(struct ocotp_priv *priv); | ||
73 | }; | ||
74 | |||
64 | static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags) | 75 | static int imx_ocotp_wait_for_busy(void __iomem *base, u32 flags) |
65 | { | 76 | { |
66 | int count; | 77 | int count; |
@@ -121,8 +132,8 @@ static int imx_ocotp_read(void *context, unsigned int offset, | |||
121 | index = offset >> 2; | 132 | index = offset >> 2; |
122 | count = bytes >> 2; | 133 | count = bytes >> 2; |
123 | 134 | ||
124 | if (count > (priv->nregs - index)) | 135 | if (count > (priv->params->nregs - index)) |
125 | count = priv->nregs - index; | 136 | count = priv->params->nregs - index; |
126 | 137 | ||
127 | mutex_lock(&ocotp_mutex); | 138 | mutex_lock(&ocotp_mutex); |
128 | 139 | ||
@@ -160,6 +171,52 @@ read_end: | |||
160 | return ret; | 171 | return ret; |
161 | } | 172 | } |
162 | 173 | ||
174 | static void imx_ocotp_set_imx6_timing(struct ocotp_priv *priv) | ||
175 | { | ||
176 | unsigned long clk_rate = 0; | ||
177 | unsigned long strobe_read, relax, strobe_prog; | ||
178 | u32 timing = 0; | ||
179 | |||
180 | /* 47.3.1.3.1 | ||
181 | * Program HW_OCOTP_TIMING[STROBE_PROG] and HW_OCOTP_TIMING[RELAX] | ||
182 | * fields with timing values to match the current frequency of the | ||
183 | * ipg_clk. OTP writes will work at maximum bus frequencies as long | ||
184 | * as the HW_OCOTP_TIMING parameters are set correctly. | ||
185 | */ | ||
186 | clk_rate = clk_get_rate(priv->clk); | ||
187 | |||
188 | relax = clk_rate / (1000000000 / DEF_RELAX) - 1; | ||
189 | strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; | ||
190 | strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; | ||
191 | |||
192 | timing = strobe_prog & 0x00000FFF; | ||
193 | timing |= (relax << 12) & 0x0000F000; | ||
194 | timing |= (strobe_read << 16) & 0x003F0000; | ||
195 | |||
196 | writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); | ||
197 | } | ||
198 | |||
199 | static void imx_ocotp_set_imx7_timing(struct ocotp_priv *priv) | ||
200 | { | ||
201 | unsigned long clk_rate = 0; | ||
202 | u64 fsource, strobe_prog; | ||
203 | u32 timing = 0; | ||
204 | |||
205 | /* i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1 | ||
206 | * 6.4.3.3 | ||
207 | */ | ||
208 | clk_rate = clk_get_rate(priv->clk); | ||
209 | fsource = DIV_ROUND_UP_ULL((u64)clk_rate * DEF_FSOURCE, | ||
210 | NSEC_PER_SEC) + 1; | ||
211 | strobe_prog = DIV_ROUND_CLOSEST_ULL((u64)clk_rate * DEF_STROBE_PROG, | ||
212 | NSEC_PER_SEC) + 1; | ||
213 | |||
214 | timing = strobe_prog & 0x00000FFF; | ||
215 | timing |= (fsource << 12) & 0x000FF000; | ||
216 | |||
217 | writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); | ||
218 | } | ||
219 | |||
163 | static int imx_ocotp_write(void *context, unsigned int offset, void *val, | 220 | static int imx_ocotp_write(void *context, unsigned int offset, void *val, |
164 | size_t bytes) | 221 | size_t bytes) |
165 | { | 222 | { |
@@ -167,11 +224,9 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, | |||
167 | u32 *buf = val; | 224 | u32 *buf = val; |
168 | int ret; | 225 | int ret; |
169 | 226 | ||
170 | unsigned long clk_rate = 0; | ||
171 | unsigned long strobe_read, relax, strobe_prog; | ||
172 | u32 timing = 0; | ||
173 | u32 ctrl; | 227 | u32 ctrl; |
174 | u8 waddr; | 228 | u8 waddr; |
229 | u8 word = 0; | ||
175 | 230 | ||
176 | /* allow only writing one complete OTP word at a time */ | 231 | /* allow only writing one complete OTP word at a time */ |
177 | if ((bytes != priv->config->word_size) || | 232 | if ((bytes != priv->config->word_size) || |
@@ -187,23 +242,8 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, | |||
187 | return ret; | 242 | return ret; |
188 | } | 243 | } |
189 | 244 | ||
190 | /* 47.3.1.3.1 | 245 | /* Setup the write timing values */ |
191 | * Program HW_OCOTP_TIMING[STROBE_PROG] and HW_OCOTP_TIMING[RELAX] | 246 | priv->params->set_timing(priv); |
192 | * fields with timing values to match the current frequency of the | ||
193 | * ipg_clk. OTP writes will work at maximum bus frequencies as long | ||
194 | * as the HW_OCOTP_TIMING parameters are set correctly. | ||
195 | */ | ||
196 | clk_rate = clk_get_rate(priv->clk); | ||
197 | |||
198 | relax = clk_rate / (1000000000 / DEF_RELAX) - 1; | ||
199 | strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; | ||
200 | strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; | ||
201 | |||
202 | timing = strobe_prog & 0x00000FFF; | ||
203 | timing |= (relax << 12) & 0x0000F000; | ||
204 | timing |= (strobe_read << 16) & 0x003F0000; | ||
205 | |||
206 | writel(timing, priv->base + IMX_OCOTP_ADDR_TIMING); | ||
207 | 247 | ||
208 | /* 47.3.1.3.2 | 248 | /* 47.3.1.3.2 |
209 | * Check that HW_OCOTP_CTRL[BUSY] and HW_OCOTP_CTRL[ERROR] are clear. | 249 | * Check that HW_OCOTP_CTRL[BUSY] and HW_OCOTP_CTRL[ERROR] are clear. |
@@ -224,8 +264,23 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, | |||
224 | * description. Both the unlock code and address can be written in the | 264 | * description. Both the unlock code and address can be written in the |
225 | * same operation. | 265 | * same operation. |
226 | */ | 266 | */ |
227 | /* OTP write/read address specifies one of 128 word address locations */ | 267 | if (priv->params->bank_address_words != 0) { |
228 | waddr = offset / 4; | 268 | /* |
269 | * In banked/i.MX7 mode the OTP register bank goes into waddr | ||
270 | * see i.MX 7Solo Applications Processor Reference Manual, Rev. | ||
271 | * 0.1 section 6.4.3.1 | ||
272 | */ | ||
273 | offset = offset / priv->config->word_size; | ||
274 | waddr = offset / priv->params->bank_address_words; | ||
275 | word = offset & (priv->params->bank_address_words - 1); | ||
276 | } else { | ||
277 | /* | ||
278 | * Non-banked i.MX6 mode. | ||
279 | * OTP write/read address specifies one of 128 word address | ||
280 | * locations | ||
281 | */ | ||
282 | waddr = offset / 4; | ||
283 | } | ||
229 | 284 | ||
230 | ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL); | 285 | ctrl = readl(priv->base + IMX_OCOTP_ADDR_CTRL); |
231 | ctrl &= ~IMX_OCOTP_BM_CTRL_ADDR; | 286 | ctrl &= ~IMX_OCOTP_BM_CTRL_ADDR; |
@@ -251,8 +306,43 @@ static int imx_ocotp_write(void *context, unsigned int offset, void *val, | |||
251 | * shift right (with zero fill). This shifting is required to program | 306 | * shift right (with zero fill). This shifting is required to program |
252 | * the OTP serially. During the write operation, HW_OCOTP_DATA cannot be | 307 | * the OTP serially. During the write operation, HW_OCOTP_DATA cannot be |
253 | * modified. | 308 | * modified. |
309 | * Note: on i.MX7 there are four data fields to write for banked write | ||
310 | * with the fuse blowing operation only taking place after data0 | ||
311 | * has been written. This is why data0 must always be the last | ||
312 | * register written. | ||
254 | */ | 313 | */ |
255 | writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA); | 314 | if (priv->params->bank_address_words != 0) { |
315 | /* Banked/i.MX7 mode */ | ||
316 | switch (word) { | ||
317 | case 0: | ||
318 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); | ||
319 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); | ||
320 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); | ||
321 | writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0); | ||
322 | break; | ||
323 | case 1: | ||
324 | writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA1); | ||
325 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); | ||
326 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); | ||
327 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); | ||
328 | break; | ||
329 | case 2: | ||
330 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); | ||
331 | writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA2); | ||
332 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA3); | ||
333 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); | ||
334 | break; | ||
335 | case 3: | ||
336 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA1); | ||
337 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA2); | ||
338 | writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA3); | ||
339 | writel(0, priv->base + IMX_OCOTP_ADDR_DATA0); | ||
340 | break; | ||
341 | } | ||
342 | } else { | ||
343 | /* Non-banked i.MX6 mode */ | ||
344 | writel(*buf, priv->base + IMX_OCOTP_ADDR_DATA0); | ||
345 | } | ||
256 | 346 | ||
257 | /* 47.4.1.4.5 | 347 | /* 47.4.1.4.5 |
258 | * Once complete, the controller will clear BUSY. A write request to a | 348 | * Once complete, the controller will clear BUSY. A write request to a |
@@ -303,17 +393,46 @@ static struct nvmem_config imx_ocotp_nvmem_config = { | |||
303 | .read_only = false, | 393 | .read_only = false, |
304 | .word_size = 4, | 394 | .word_size = 4, |
305 | .stride = 4, | 395 | .stride = 4, |
306 | .owner = THIS_MODULE, | ||
307 | .reg_read = imx_ocotp_read, | 396 | .reg_read = imx_ocotp_read, |
308 | .reg_write = imx_ocotp_write, | 397 | .reg_write = imx_ocotp_write, |
309 | }; | 398 | }; |
310 | 399 | ||
400 | static const struct ocotp_params imx6q_params = { | ||
401 | .nregs = 128, | ||
402 | .bank_address_words = 0, | ||
403 | .set_timing = imx_ocotp_set_imx6_timing, | ||
404 | }; | ||
405 | |||
406 | static const struct ocotp_params imx6sl_params = { | ||
407 | .nregs = 64, | ||
408 | .bank_address_words = 0, | ||
409 | .set_timing = imx_ocotp_set_imx6_timing, | ||
410 | }; | ||
411 | |||
412 | static const struct ocotp_params imx6sx_params = { | ||
413 | .nregs = 128, | ||
414 | .bank_address_words = 0, | ||
415 | .set_timing = imx_ocotp_set_imx6_timing, | ||
416 | }; | ||
417 | |||
418 | static const struct ocotp_params imx6ul_params = { | ||
419 | .nregs = 128, | ||
420 | .bank_address_words = 0, | ||
421 | .set_timing = imx_ocotp_set_imx6_timing, | ||
422 | }; | ||
423 | |||
424 | static const struct ocotp_params imx7d_params = { | ||
425 | .nregs = 64, | ||
426 | .bank_address_words = 4, | ||
427 | .set_timing = imx_ocotp_set_imx7_timing, | ||
428 | }; | ||
429 | |||
311 | static const struct of_device_id imx_ocotp_dt_ids[] = { | 430 | static const struct of_device_id imx_ocotp_dt_ids[] = { |
312 | { .compatible = "fsl,imx6q-ocotp", (void *)128 }, | 431 | { .compatible = "fsl,imx6q-ocotp", .data = &imx6q_params }, |
313 | { .compatible = "fsl,imx6sl-ocotp", (void *)64 }, | 432 | { .compatible = "fsl,imx6sl-ocotp", .data = &imx6sl_params }, |
314 | { .compatible = "fsl,imx6sx-ocotp", (void *)128 }, | 433 | { .compatible = "fsl,imx6sx-ocotp", .data = &imx6sx_params }, |
315 | { .compatible = "fsl,imx6ul-ocotp", (void *)128 }, | 434 | { .compatible = "fsl,imx6ul-ocotp", .data = &imx6ul_params }, |
316 | { .compatible = "fsl,imx7d-ocotp", (void *)64 }, | 435 | { .compatible = "fsl,imx7d-ocotp", .data = &imx7d_params }, |
317 | { }, | 436 | { }, |
318 | }; | 437 | }; |
319 | MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); | 438 | MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids); |
@@ -342,8 +461,8 @@ static int imx_ocotp_probe(struct platform_device *pdev) | |||
342 | return PTR_ERR(priv->clk); | 461 | return PTR_ERR(priv->clk); |
343 | 462 | ||
344 | of_id = of_match_device(imx_ocotp_dt_ids, dev); | 463 | of_id = of_match_device(imx_ocotp_dt_ids, dev); |
345 | priv->nregs = (unsigned long)of_id->data; | 464 | priv->params = of_device_get_match_data(&pdev->dev); |
346 | imx_ocotp_nvmem_config.size = 4 * priv->nregs; | 465 | imx_ocotp_nvmem_config.size = 4 * priv->params->nregs; |
347 | imx_ocotp_nvmem_config.dev = dev; | 466 | imx_ocotp_nvmem_config.dev = dev; |
348 | imx_ocotp_nvmem_config.priv = priv; | 467 | imx_ocotp_nvmem_config.priv = priv; |
349 | priv->config = &imx_ocotp_nvmem_config; | 468 | priv->config = &imx_ocotp_nvmem_config; |
@@ -375,5 +494,5 @@ static struct platform_driver imx_ocotp_driver = { | |||
375 | module_platform_driver(imx_ocotp_driver); | 494 | module_platform_driver(imx_ocotp_driver); |
376 | 495 | ||
377 | MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>"); | 496 | MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>"); |
378 | MODULE_DESCRIPTION("i.MX6 OCOTP fuse box driver"); | 497 | MODULE_DESCRIPTION("i.MX6/i.MX7 OCOTP fuse box driver"); |
379 | MODULE_LICENSE("GPL v2"); | 498 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c index 6c7e2c424a4e..b1af966206a6 100644 --- a/drivers/nvmem/lpc18xx_eeprom.c +++ b/drivers/nvmem/lpc18xx_eeprom.c | |||
@@ -159,7 +159,6 @@ static struct nvmem_config lpc18xx_nvmem_config = { | |||
159 | .word_size = 4, | 159 | .word_size = 4, |
160 | .reg_read = lpc18xx_eeprom_read, | 160 | .reg_read = lpc18xx_eeprom_read, |
161 | .reg_write = lpc18xx_eeprom_gather_write, | 161 | .reg_write = lpc18xx_eeprom_gather_write, |
162 | .owner = THIS_MODULE, | ||
163 | }; | 162 | }; |
164 | 163 | ||
165 | static int lpc18xx_eeprom_probe(struct platform_device *pdev) | 164 | static int lpc18xx_eeprom_probe(struct platform_device *pdev) |
diff --git a/drivers/nvmem/lpc18xx_otp.c b/drivers/nvmem/lpc18xx_otp.c index be8d07403ffc..95268db155e9 100644 --- a/drivers/nvmem/lpc18xx_otp.c +++ b/drivers/nvmem/lpc18xx_otp.c | |||
@@ -64,7 +64,6 @@ static struct nvmem_config lpc18xx_otp_nvmem_config = { | |||
64 | .read_only = true, | 64 | .read_only = true, |
65 | .word_size = LPC18XX_OTP_WORD_SIZE, | 65 | .word_size = LPC18XX_OTP_WORD_SIZE, |
66 | .stride = LPC18XX_OTP_WORD_SIZE, | 66 | .stride = LPC18XX_OTP_WORD_SIZE, |
67 | .owner = THIS_MODULE, | ||
68 | .reg_read = lpc18xx_otp_read, | 67 | .reg_read = lpc18xx_otp_read, |
69 | }; | 68 | }; |
70 | 69 | ||
diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c index 70bfc9839bb2..a43c68f90937 100644 --- a/drivers/nvmem/meson-efuse.c +++ b/drivers/nvmem/meson-efuse.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Amlogic eFuse Driver | 2 | * Amlogic Meson GX eFuse Driver |
3 | * | 3 | * |
4 | * Copyright (c) 2016 Endless Computers, Inc. | 4 | * Copyright (c) 2016 Endless Computers, Inc. |
5 | * Author: Carlo Caione <carlo@endlessm.com> | 5 | * Author: Carlo Caione <carlo@endlessm.com> |
@@ -37,7 +37,6 @@ static int meson_efuse_read(void *context, unsigned int offset, | |||
37 | 37 | ||
38 | static struct nvmem_config econfig = { | 38 | static struct nvmem_config econfig = { |
39 | .name = "meson-efuse", | 39 | .name = "meson-efuse", |
40 | .owner = THIS_MODULE, | ||
41 | .stride = 1, | 40 | .stride = 1, |
42 | .word_size = 1, | 41 | .word_size = 1, |
43 | .read_only = true, | 42 | .read_only = true, |
@@ -89,5 +88,5 @@ static struct platform_driver meson_efuse_driver = { | |||
89 | module_platform_driver(meson_efuse_driver); | 88 | module_platform_driver(meson_efuse_driver); |
90 | 89 | ||
91 | MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>"); | 90 | MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>"); |
92 | MODULE_DESCRIPTION("Amlogic Meson NVMEM driver"); | 91 | MODULE_DESCRIPTION("Amlogic Meson GX NVMEM driver"); |
93 | MODULE_LICENSE("GPL v2"); | 92 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/nvmem/meson-mx-efuse.c b/drivers/nvmem/meson-mx-efuse.c new file mode 100644 index 000000000000..a346b4923550 --- /dev/null +++ b/drivers/nvmem/meson-mx-efuse.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * Amlogic Meson6, Meson8 and Meson8b eFuse Driver | ||
3 | * | ||
4 | * Copyright (c) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of version 2 of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/bitfield.h> | ||
17 | #include <linux/bitops.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/iopoll.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/nvmem-provider.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/of_device.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/sizes.h> | ||
28 | #include <linux/slab.h> | ||
29 | |||
30 | #define MESON_MX_EFUSE_CNTL1 0x04 | ||
31 | #define MESON_MX_EFUSE_CNTL1_PD_ENABLE BIT(27) | ||
32 | #define MESON_MX_EFUSE_CNTL1_AUTO_RD_BUSY BIT(26) | ||
33 | #define MESON_MX_EFUSE_CNTL1_AUTO_RD_START BIT(25) | ||
34 | #define MESON_MX_EFUSE_CNTL1_AUTO_RD_ENABLE BIT(24) | ||
35 | #define MESON_MX_EFUSE_CNTL1_BYTE_WR_DATA GENMASK(23, 16) | ||
36 | #define MESON_MX_EFUSE_CNTL1_AUTO_WR_BUSY BIT(14) | ||
37 | #define MESON_MX_EFUSE_CNTL1_AUTO_WR_START BIT(13) | ||
38 | #define MESON_MX_EFUSE_CNTL1_AUTO_WR_ENABLE BIT(12) | ||
39 | #define MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET BIT(11) | ||
40 | #define MESON_MX_EFUSE_CNTL1_BYTE_ADDR_MASK GENMASK(10, 0) | ||
41 | |||
42 | #define MESON_MX_EFUSE_CNTL2 0x08 | ||
43 | |||
44 | #define MESON_MX_EFUSE_CNTL4 0x10 | ||
45 | #define MESON_MX_EFUSE_CNTL4_ENCRYPT_ENABLE BIT(10) | ||
46 | |||
47 | struct meson_mx_efuse_platform_data { | ||
48 | const char *name; | ||
49 | unsigned int word_size; | ||
50 | }; | ||
51 | |||
52 | struct meson_mx_efuse { | ||
53 | void __iomem *base; | ||
54 | struct clk *core_clk; | ||
55 | struct nvmem_device *nvmem; | ||
56 | struct nvmem_config config; | ||
57 | }; | ||
58 | |||
59 | static void meson_mx_efuse_mask_bits(struct meson_mx_efuse *efuse, u32 reg, | ||
60 | u32 mask, u32 set) | ||
61 | { | ||
62 | u32 data; | ||
63 | |||
64 | data = readl(efuse->base + reg); | ||
65 | data &= ~mask; | ||
66 | data |= (set & mask); | ||
67 | |||
68 | writel(data, efuse->base + reg); | ||
69 | } | ||
70 | |||
71 | static int meson_mx_efuse_hw_enable(struct meson_mx_efuse *efuse) | ||
72 | { | ||
73 | int err; | ||
74 | |||
75 | err = clk_prepare_enable(efuse->core_clk); | ||
76 | if (err) | ||
77 | return err; | ||
78 | |||
79 | /* power up the efuse */ | ||
80 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
81 | MESON_MX_EFUSE_CNTL1_PD_ENABLE, 0); | ||
82 | |||
83 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL4, | ||
84 | MESON_MX_EFUSE_CNTL4_ENCRYPT_ENABLE, 0); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static void meson_mx_efuse_hw_disable(struct meson_mx_efuse *efuse) | ||
90 | { | ||
91 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
92 | MESON_MX_EFUSE_CNTL1_PD_ENABLE, | ||
93 | MESON_MX_EFUSE_CNTL1_PD_ENABLE); | ||
94 | |||
95 | clk_disable_unprepare(efuse->core_clk); | ||
96 | } | ||
97 | |||
98 | static int meson_mx_efuse_read_addr(struct meson_mx_efuse *efuse, | ||
99 | unsigned int addr, u32 *value) | ||
100 | { | ||
101 | int err; | ||
102 | u32 regval; | ||
103 | |||
104 | /* write the address to read */ | ||
105 | regval = FIELD_PREP(MESON_MX_EFUSE_CNTL1_BYTE_ADDR_MASK, addr); | ||
106 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
107 | MESON_MX_EFUSE_CNTL1_BYTE_ADDR_MASK, regval); | ||
108 | |||
109 | /* inform the hardware that we changed the address */ | ||
110 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
111 | MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET, | ||
112 | MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET); | ||
113 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
114 | MESON_MX_EFUSE_CNTL1_BYTE_ADDR_SET, 0); | ||
115 | |||
116 | /* start the read process */ | ||
117 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
118 | MESON_MX_EFUSE_CNTL1_AUTO_RD_START, | ||
119 | MESON_MX_EFUSE_CNTL1_AUTO_RD_START); | ||
120 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
121 | MESON_MX_EFUSE_CNTL1_AUTO_RD_START, 0); | ||
122 | |||
123 | /* | ||
124 | * perform a dummy read to ensure that the HW has the RD_BUSY bit set | ||
125 | * when polling for the status below. | ||
126 | */ | ||
127 | readl(efuse->base + MESON_MX_EFUSE_CNTL1); | ||
128 | |||
129 | err = readl_poll_timeout_atomic(efuse->base + MESON_MX_EFUSE_CNTL1, | ||
130 | regval, | ||
131 | (!(regval & MESON_MX_EFUSE_CNTL1_AUTO_RD_BUSY)), | ||
132 | 1, 1000); | ||
133 | if (err) { | ||
134 | dev_err(efuse->config.dev, | ||
135 | "Timeout while reading efuse address %u\n", addr); | ||
136 | return err; | ||
137 | } | ||
138 | |||
139 | *value = readl(efuse->base + MESON_MX_EFUSE_CNTL2); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int meson_mx_efuse_read(void *context, unsigned int offset, | ||
145 | void *buf, size_t bytes) | ||
146 | { | ||
147 | struct meson_mx_efuse *efuse = context; | ||
148 | u32 tmp; | ||
149 | int err, i, addr; | ||
150 | |||
151 | err = meson_mx_efuse_hw_enable(efuse); | ||
152 | if (err) | ||
153 | return err; | ||
154 | |||
155 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
156 | MESON_MX_EFUSE_CNTL1_AUTO_RD_ENABLE, | ||
157 | MESON_MX_EFUSE_CNTL1_AUTO_RD_ENABLE); | ||
158 | |||
159 | for (i = offset; i < offset + bytes; i += efuse->config.word_size) { | ||
160 | addr = i / efuse->config.word_size; | ||
161 | |||
162 | err = meson_mx_efuse_read_addr(efuse, addr, &tmp); | ||
163 | if (err) | ||
164 | break; | ||
165 | |||
166 | memcpy(buf + i, &tmp, efuse->config.word_size); | ||
167 | } | ||
168 | |||
169 | meson_mx_efuse_mask_bits(efuse, MESON_MX_EFUSE_CNTL1, | ||
170 | MESON_MX_EFUSE_CNTL1_AUTO_RD_ENABLE, 0); | ||
171 | |||
172 | meson_mx_efuse_hw_disable(efuse); | ||
173 | |||
174 | return err; | ||
175 | } | ||
176 | |||
177 | static const struct meson_mx_efuse_platform_data meson6_efuse_data = { | ||
178 | .name = "meson6-efuse", | ||
179 | .word_size = 1, | ||
180 | }; | ||
181 | |||
182 | static const struct meson_mx_efuse_platform_data meson8_efuse_data = { | ||
183 | .name = "meson8-efuse", | ||
184 | .word_size = 4, | ||
185 | }; | ||
186 | |||
187 | static const struct meson_mx_efuse_platform_data meson8b_efuse_data = { | ||
188 | .name = "meson8b-efuse", | ||
189 | .word_size = 4, | ||
190 | }; | ||
191 | |||
192 | static const struct of_device_id meson_mx_efuse_match[] = { | ||
193 | { .compatible = "amlogic,meson6-efuse", .data = &meson6_efuse_data }, | ||
194 | { .compatible = "amlogic,meson8-efuse", .data = &meson8_efuse_data }, | ||
195 | { .compatible = "amlogic,meson8b-efuse", .data = &meson8b_efuse_data }, | ||
196 | { /* sentinel */ }, | ||
197 | }; | ||
198 | MODULE_DEVICE_TABLE(of, meson_mx_efuse_match); | ||
199 | |||
200 | static int meson_mx_efuse_probe(struct platform_device *pdev) | ||
201 | { | ||
202 | const struct meson_mx_efuse_platform_data *drvdata; | ||
203 | struct meson_mx_efuse *efuse; | ||
204 | struct resource *res; | ||
205 | |||
206 | drvdata = of_device_get_match_data(&pdev->dev); | ||
207 | if (!drvdata) | ||
208 | return -EINVAL; | ||
209 | |||
210 | efuse = devm_kzalloc(&pdev->dev, sizeof(*efuse), GFP_KERNEL); | ||
211 | if (!efuse) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
215 | efuse->base = devm_ioremap_resource(&pdev->dev, res); | ||
216 | if (IS_ERR(efuse->base)) | ||
217 | return PTR_ERR(efuse->base); | ||
218 | |||
219 | efuse->config.name = devm_kstrdup(&pdev->dev, drvdata->name, | ||
220 | GFP_KERNEL); | ||
221 | efuse->config.owner = THIS_MODULE; | ||
222 | efuse->config.dev = &pdev->dev; | ||
223 | efuse->config.priv = efuse; | ||
224 | efuse->config.stride = drvdata->word_size; | ||
225 | efuse->config.word_size = drvdata->word_size; | ||
226 | efuse->config.size = SZ_512; | ||
227 | efuse->config.read_only = true; | ||
228 | efuse->config.reg_read = meson_mx_efuse_read; | ||
229 | |||
230 | efuse->core_clk = devm_clk_get(&pdev->dev, "core"); | ||
231 | if (IS_ERR(efuse->core_clk)) { | ||
232 | dev_err(&pdev->dev, "Failed to get core clock\n"); | ||
233 | return PTR_ERR(efuse->core_clk); | ||
234 | } | ||
235 | |||
236 | efuse->nvmem = nvmem_register(&efuse->config); | ||
237 | if (IS_ERR(efuse->nvmem)) | ||
238 | return PTR_ERR(efuse->nvmem); | ||
239 | |||
240 | platform_set_drvdata(pdev, efuse); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int meson_mx_efuse_remove(struct platform_device *pdev) | ||
246 | { | ||
247 | struct meson_mx_efuse *efuse = platform_get_drvdata(pdev); | ||
248 | |||
249 | return nvmem_unregister(efuse->nvmem); | ||
250 | } | ||
251 | |||
252 | static struct platform_driver meson_mx_efuse_driver = { | ||
253 | .probe = meson_mx_efuse_probe, | ||
254 | .remove = meson_mx_efuse_remove, | ||
255 | .driver = { | ||
256 | .name = "meson-mx-efuse", | ||
257 | .of_match_table = meson_mx_efuse_match, | ||
258 | }, | ||
259 | }; | ||
260 | |||
261 | module_platform_driver(meson_mx_efuse_driver); | ||
262 | |||
263 | MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); | ||
264 | MODULE_DESCRIPTION("Amlogic Meson MX eFuse NVMEM driver"); | ||
265 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c index 32fd572e18c5..9ee3479cfc7b 100644 --- a/drivers/nvmem/mtk-efuse.c +++ b/drivers/nvmem/mtk-efuse.c | |||
@@ -18,15 +18,19 @@ | |||
18 | #include <linux/nvmem-provider.h> | 18 | #include <linux/nvmem-provider.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | 20 | ||
21 | struct mtk_efuse_priv { | ||
22 | void __iomem *base; | ||
23 | }; | ||
24 | |||
21 | static int mtk_reg_read(void *context, | 25 | static int mtk_reg_read(void *context, |
22 | unsigned int reg, void *_val, size_t bytes) | 26 | unsigned int reg, void *_val, size_t bytes) |
23 | { | 27 | { |
24 | void __iomem *base = context; | 28 | struct mtk_efuse_priv *priv = context; |
25 | u32 *val = _val; | 29 | u32 *val = _val; |
26 | int i = 0, words = bytes / 4; | 30 | int i = 0, words = bytes / 4; |
27 | 31 | ||
28 | while (words--) | 32 | while (words--) |
29 | *val++ = readl(base + reg + (i++ * 4)); | 33 | *val++ = readl(priv->base + reg + (i++ * 4)); |
30 | 34 | ||
31 | return 0; | 35 | return 0; |
32 | } | 36 | } |
@@ -34,12 +38,12 @@ static int mtk_reg_read(void *context, | |||
34 | static int mtk_reg_write(void *context, | 38 | static int mtk_reg_write(void *context, |
35 | unsigned int reg, void *_val, size_t bytes) | 39 | unsigned int reg, void *_val, size_t bytes) |
36 | { | 40 | { |
37 | void __iomem *base = context; | 41 | struct mtk_efuse_priv *priv = context; |
38 | u32 *val = _val; | 42 | u32 *val = _val; |
39 | int i = 0, words = bytes / 4; | 43 | int i = 0, words = bytes / 4; |
40 | 44 | ||
41 | while (words--) | 45 | while (words--) |
42 | writel(*val++, base + reg + (i++ * 4)); | 46 | writel(*val++, priv->base + reg + (i++ * 4)); |
43 | 47 | ||
44 | return 0; | 48 | return 0; |
45 | } | 49 | } |
@@ -49,27 +53,26 @@ static int mtk_efuse_probe(struct platform_device *pdev) | |||
49 | struct device *dev = &pdev->dev; | 53 | struct device *dev = &pdev->dev; |
50 | struct resource *res; | 54 | struct resource *res; |
51 | struct nvmem_device *nvmem; | 55 | struct nvmem_device *nvmem; |
52 | struct nvmem_config *econfig; | 56 | struct nvmem_config econfig = {}; |
53 | void __iomem *base; | 57 | struct mtk_efuse_priv *priv; |
54 | 58 | ||
55 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 59 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
56 | base = devm_ioremap_resource(dev, res); | 60 | if (!priv) |
57 | if (IS_ERR(base)) | ||
58 | return PTR_ERR(base); | ||
59 | |||
60 | econfig = devm_kzalloc(dev, sizeof(*econfig), GFP_KERNEL); | ||
61 | if (!econfig) | ||
62 | return -ENOMEM; | 61 | return -ENOMEM; |
63 | 62 | ||
64 | econfig->stride = 4; | 63 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
65 | econfig->word_size = 4; | 64 | priv->base = devm_ioremap_resource(dev, res); |
66 | econfig->reg_read = mtk_reg_read; | 65 | if (IS_ERR(priv->base)) |
67 | econfig->reg_write = mtk_reg_write; | 66 | return PTR_ERR(priv->base); |
68 | econfig->size = resource_size(res); | 67 | |
69 | econfig->priv = base; | 68 | econfig.stride = 4; |
70 | econfig->dev = dev; | 69 | econfig.word_size = 4; |
71 | econfig->owner = THIS_MODULE; | 70 | econfig.reg_read = mtk_reg_read; |
72 | nvmem = nvmem_register(econfig); | 71 | econfig.reg_write = mtk_reg_write; |
72 | econfig.size = resource_size(res); | ||
73 | econfig.priv = priv; | ||
74 | econfig.dev = dev; | ||
75 | nvmem = nvmem_register(&econfig); | ||
73 | if (IS_ERR(nvmem)) | 76 | if (IS_ERR(nvmem)) |
74 | return PTR_ERR(nvmem); | 77 | return PTR_ERR(nvmem); |
75 | 78 | ||
diff --git a/drivers/nvmem/mxs-ocotp.c b/drivers/nvmem/mxs-ocotp.c index d26dd03cec80..7018e2ef5714 100644 --- a/drivers/nvmem/mxs-ocotp.c +++ b/drivers/nvmem/mxs-ocotp.c | |||
@@ -118,7 +118,6 @@ static struct nvmem_config ocotp_config = { | |||
118 | .name = "mxs-ocotp", | 118 | .name = "mxs-ocotp", |
119 | .stride = 16, | 119 | .stride = 16, |
120 | .word_size = 4, | 120 | .word_size = 4, |
121 | .owner = THIS_MODULE, | ||
122 | .reg_read = mxs_ocotp_read, | 121 | .reg_read = mxs_ocotp_read, |
123 | }; | 122 | }; |
124 | 123 | ||
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c index 2bdb6c389328..cb3b48b47d64 100644 --- a/drivers/nvmem/qfprom.c +++ b/drivers/nvmem/qfprom.c | |||
@@ -17,15 +17,19 @@ | |||
17 | #include <linux/nvmem-provider.h> | 17 | #include <linux/nvmem-provider.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | 19 | ||
20 | struct qfprom_priv { | ||
21 | void __iomem *base; | ||
22 | }; | ||
23 | |||
20 | static int qfprom_reg_read(void *context, | 24 | static int qfprom_reg_read(void *context, |
21 | unsigned int reg, void *_val, size_t bytes) | 25 | unsigned int reg, void *_val, size_t bytes) |
22 | { | 26 | { |
23 | void __iomem *base = context; | 27 | struct qfprom_priv *priv = context; |
24 | u8 *val = _val; | 28 | u8 *val = _val; |
25 | int i = 0, words = bytes; | 29 | int i = 0, words = bytes; |
26 | 30 | ||
27 | while (words--) | 31 | while (words--) |
28 | *val++ = readb(base + reg + i++); | 32 | *val++ = readb(priv->base + reg + i++); |
29 | 33 | ||
30 | return 0; | 34 | return 0; |
31 | } | 35 | } |
@@ -33,12 +37,12 @@ static int qfprom_reg_read(void *context, | |||
33 | static int qfprom_reg_write(void *context, | 37 | static int qfprom_reg_write(void *context, |
34 | unsigned int reg, void *_val, size_t bytes) | 38 | unsigned int reg, void *_val, size_t bytes) |
35 | { | 39 | { |
36 | void __iomem *base = context; | 40 | struct qfprom_priv *priv = context; |
37 | u8 *val = _val; | 41 | u8 *val = _val; |
38 | int i = 0, words = bytes; | 42 | int i = 0, words = bytes; |
39 | 43 | ||
40 | while (words--) | 44 | while (words--) |
41 | writeb(*val++, base + reg + i++); | 45 | writeb(*val++, priv->base + reg + i++); |
42 | 46 | ||
43 | return 0; | 47 | return 0; |
44 | } | 48 | } |
@@ -52,7 +56,6 @@ static int qfprom_remove(struct platform_device *pdev) | |||
52 | 56 | ||
53 | static struct nvmem_config econfig = { | 57 | static struct nvmem_config econfig = { |
54 | .name = "qfprom", | 58 | .name = "qfprom", |
55 | .owner = THIS_MODULE, | ||
56 | .stride = 1, | 59 | .stride = 1, |
57 | .word_size = 1, | 60 | .word_size = 1, |
58 | .reg_read = qfprom_reg_read, | 61 | .reg_read = qfprom_reg_read, |
@@ -64,16 +67,20 @@ static int qfprom_probe(struct platform_device *pdev) | |||
64 | struct device *dev = &pdev->dev; | 67 | struct device *dev = &pdev->dev; |
65 | struct resource *res; | 68 | struct resource *res; |
66 | struct nvmem_device *nvmem; | 69 | struct nvmem_device *nvmem; |
67 | void __iomem *base; | 70 | struct qfprom_priv *priv; |
71 | |||
72 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
73 | if (!priv) | ||
74 | return -ENOMEM; | ||
68 | 75 | ||
69 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 76 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
70 | base = devm_ioremap_resource(dev, res); | 77 | priv->base = devm_ioremap_resource(dev, res); |
71 | if (IS_ERR(base)) | 78 | if (IS_ERR(priv->base)) |
72 | return PTR_ERR(base); | 79 | return PTR_ERR(priv->base); |
73 | 80 | ||
74 | econfig.size = resource_size(res); | 81 | econfig.size = resource_size(res); |
75 | econfig.dev = dev; | 82 | econfig.dev = dev; |
76 | econfig.priv = base; | 83 | econfig.priv = priv; |
77 | 84 | ||
78 | nvmem = nvmem_register(&econfig); | 85 | nvmem = nvmem_register(&econfig); |
79 | if (IS_ERR(nvmem)) | 86 | if (IS_ERR(nvmem)) |
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c index 63e3eb55f3ac..123de77ca5d6 100644 --- a/drivers/nvmem/rockchip-efuse.c +++ b/drivers/nvmem/rockchip-efuse.c | |||
@@ -149,7 +149,6 @@ static int rockchip_rk3399_efuse_read(void *context, unsigned int offset, | |||
149 | 149 | ||
150 | static struct nvmem_config econfig = { | 150 | static struct nvmem_config econfig = { |
151 | .name = "rockchip-efuse", | 151 | .name = "rockchip-efuse", |
152 | .owner = THIS_MODULE, | ||
153 | .stride = 1, | 152 | .stride = 1, |
154 | .word_size = 1, | 153 | .word_size = 1, |
155 | .read_only = true, | 154 | .read_only = true, |
@@ -178,6 +177,10 @@ static const struct of_device_id rockchip_efuse_match[] = { | |||
178 | .data = (void *)&rockchip_rk3288_efuse_read, | 177 | .data = (void *)&rockchip_rk3288_efuse_read, |
179 | }, | 178 | }, |
180 | { | 179 | { |
180 | .compatible = "rockchip,rk3368-efuse", | ||
181 | .data = (void *)&rockchip_rk3288_efuse_read, | ||
182 | }, | ||
183 | { | ||
181 | .compatible = "rockchip,rk3399-efuse", | 184 | .compatible = "rockchip,rk3399-efuse", |
182 | .data = (void *)&rockchip_rk3399_efuse_read, | 185 | .data = (void *)&rockchip_rk3399_efuse_read, |
183 | }, | 186 | }, |
diff --git a/drivers/nvmem/snvs_lpgpr.c b/drivers/nvmem/snvs_lpgpr.c new file mode 100644 index 000000000000..e5c2a4a17f03 --- /dev/null +++ b/drivers/nvmem/snvs_lpgpr.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de> | ||
3 | * Copyright (c) 2017 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/mfd/syscon.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/nvmem-provider.h> | ||
13 | #include <linux/of_device.h> | ||
14 | #include <linux/regmap.h> | ||
15 | |||
16 | #define IMX6Q_SNVS_HPLR 0x00 | ||
17 | #define IMX6Q_GPR_SL BIT(5) | ||
18 | #define IMX6Q_SNVS_LPLR 0x34 | ||
19 | #define IMX6Q_GPR_HL BIT(5) | ||
20 | #define IMX6Q_SNVS_LPGPR 0x68 | ||
21 | |||
22 | struct snvs_lpgpr_cfg { | ||
23 | int offset; | ||
24 | int offset_hplr; | ||
25 | int offset_lplr; | ||
26 | }; | ||
27 | |||
28 | struct snvs_lpgpr_priv { | ||
29 | struct device_d *dev; | ||
30 | struct regmap *regmap; | ||
31 | struct nvmem_config cfg; | ||
32 | const struct snvs_lpgpr_cfg *dcfg; | ||
33 | }; | ||
34 | |||
35 | static const struct snvs_lpgpr_cfg snvs_lpgpr_cfg_imx6q = { | ||
36 | .offset = IMX6Q_SNVS_LPGPR, | ||
37 | .offset_hplr = IMX6Q_SNVS_HPLR, | ||
38 | .offset_lplr = IMX6Q_SNVS_LPLR, | ||
39 | }; | ||
40 | |||
41 | static int snvs_lpgpr_write(void *context, unsigned int offset, void *val, | ||
42 | size_t bytes) | ||
43 | { | ||
44 | struct snvs_lpgpr_priv *priv = context; | ||
45 | const struct snvs_lpgpr_cfg *dcfg = priv->dcfg; | ||
46 | unsigned int lock_reg; | ||
47 | int ret; | ||
48 | |||
49 | ret = regmap_read(priv->regmap, dcfg->offset_hplr, &lock_reg); | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | |||
53 | if (lock_reg & IMX6Q_GPR_SL) | ||
54 | return -EPERM; | ||
55 | |||
56 | ret = regmap_read(priv->regmap, dcfg->offset_lplr, &lock_reg); | ||
57 | if (ret < 0) | ||
58 | return ret; | ||
59 | |||
60 | if (lock_reg & IMX6Q_GPR_HL) | ||
61 | return -EPERM; | ||
62 | |||
63 | return regmap_bulk_write(priv->regmap, dcfg->offset + offset, val, | ||
64 | bytes / 4); | ||
65 | } | ||
66 | |||
67 | static int snvs_lpgpr_read(void *context, unsigned int offset, void *val, | ||
68 | size_t bytes) | ||
69 | { | ||
70 | struct snvs_lpgpr_priv *priv = context; | ||
71 | const struct snvs_lpgpr_cfg *dcfg = priv->dcfg; | ||
72 | |||
73 | return regmap_bulk_read(priv->regmap, dcfg->offset + offset, | ||
74 | val, bytes / 4); | ||
75 | } | ||
76 | |||
77 | static int snvs_lpgpr_probe(struct platform_device *pdev) | ||
78 | { | ||
79 | struct device *dev = &pdev->dev; | ||
80 | struct device_node *node = dev->of_node; | ||
81 | struct device_node *syscon_node; | ||
82 | struct snvs_lpgpr_priv *priv; | ||
83 | struct nvmem_config *cfg; | ||
84 | struct nvmem_device *nvmem; | ||
85 | const struct snvs_lpgpr_cfg *dcfg; | ||
86 | |||
87 | if (!node) | ||
88 | return -ENOENT; | ||
89 | |||
90 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
91 | if (!priv) | ||
92 | return -ENOMEM; | ||
93 | |||
94 | dcfg = of_device_get_match_data(dev); | ||
95 | if (!dcfg) | ||
96 | return -EINVAL; | ||
97 | |||
98 | syscon_node = of_get_parent(node); | ||
99 | if (!syscon_node) | ||
100 | return -ENODEV; | ||
101 | |||
102 | priv->regmap = syscon_node_to_regmap(syscon_node); | ||
103 | of_node_put(syscon_node); | ||
104 | if (IS_ERR(priv->regmap)) | ||
105 | return PTR_ERR(priv->regmap); | ||
106 | |||
107 | priv->dcfg = dcfg; | ||
108 | |||
109 | cfg = &priv->cfg; | ||
110 | cfg->priv = priv; | ||
111 | cfg->name = dev_name(dev); | ||
112 | cfg->dev = dev; | ||
113 | cfg->stride = 4, | ||
114 | cfg->word_size = 4, | ||
115 | cfg->size = 4, | ||
116 | cfg->owner = THIS_MODULE, | ||
117 | cfg->reg_read = snvs_lpgpr_read, | ||
118 | cfg->reg_write = snvs_lpgpr_write, | ||
119 | |||
120 | nvmem = nvmem_register(cfg); | ||
121 | if (IS_ERR(nvmem)) | ||
122 | return PTR_ERR(nvmem); | ||
123 | |||
124 | platform_set_drvdata(pdev, nvmem); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int snvs_lpgpr_remove(struct platform_device *pdev) | ||
130 | { | ||
131 | struct nvmem_device *nvmem = platform_get_drvdata(pdev); | ||
132 | |||
133 | return nvmem_unregister(nvmem); | ||
134 | } | ||
135 | |||
136 | static const struct of_device_id snvs_lpgpr_dt_ids[] = { | ||
137 | { .compatible = "fsl,imx6q-snvs-lpgpr", .data = &snvs_lpgpr_cfg_imx6q }, | ||
138 | { .compatible = "fsl,imx6ul-snvs-lpgpr", | ||
139 | .data = &snvs_lpgpr_cfg_imx6q }, | ||
140 | { }, | ||
141 | }; | ||
142 | MODULE_DEVICE_TABLE(of, snvs_lpgpr_dt_ids); | ||
143 | |||
144 | static struct platform_driver snvs_lpgpr_driver = { | ||
145 | .probe = snvs_lpgpr_probe, | ||
146 | .remove = snvs_lpgpr_remove, | ||
147 | .driver = { | ||
148 | .name = "snvs_lpgpr", | ||
149 | .of_match_table = snvs_lpgpr_dt_ids, | ||
150 | }, | ||
151 | }; | ||
152 | module_platform_driver(snvs_lpgpr_driver); | ||
153 | |||
154 | MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>"); | ||
155 | MODULE_DESCRIPTION("Low Power General Purpose Register in i.MX6 Secure Non-Volatile Storage"); | ||
156 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 0d6648be93b8..99bd54d85fcb 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c | |||
@@ -40,7 +40,6 @@ static struct nvmem_config econfig = { | |||
40 | .read_only = true, | 40 | .read_only = true, |
41 | .stride = 4, | 41 | .stride = 4, |
42 | .word_size = 1, | 42 | .word_size = 1, |
43 | .owner = THIS_MODULE, | ||
44 | }; | 43 | }; |
45 | 44 | ||
46 | struct sunxi_sid_cfg { | 45 | struct sunxi_sid_cfg { |
@@ -199,10 +198,16 @@ static const struct sunxi_sid_cfg sun8i_h3_cfg = { | |||
199 | .need_register_readout = true, | 198 | .need_register_readout = true, |
200 | }; | 199 | }; |
201 | 200 | ||
201 | static const struct sunxi_sid_cfg sun50i_a64_cfg = { | ||
202 | .value_offset = 0x200, | ||
203 | .size = 0x100, | ||
204 | }; | ||
205 | |||
202 | static const struct of_device_id sunxi_sid_of_match[] = { | 206 | static const struct of_device_id sunxi_sid_of_match[] = { |
203 | { .compatible = "allwinner,sun4i-a10-sid", .data = &sun4i_a10_cfg }, | 207 | { .compatible = "allwinner,sun4i-a10-sid", .data = &sun4i_a10_cfg }, |
204 | { .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg }, | 208 | { .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg }, |
205 | { .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg }, | 209 | { .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg }, |
210 | { .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg }, | ||
206 | {/* sentinel */}, | 211 | {/* sentinel */}, |
207 | }; | 212 | }; |
208 | MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); | 213 | MODULE_DEVICE_TABLE(of, sunxi_sid_of_match); |
diff --git a/drivers/nvmem/uniphier-efuse.c b/drivers/nvmem/uniphier-efuse.c new file mode 100644 index 000000000000..9d278b4e1dc7 --- /dev/null +++ b/drivers/nvmem/uniphier-efuse.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * UniPhier eFuse driver | ||
3 | * | ||
4 | * Copyright (C) 2017 Socionext Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/device.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/nvmem-provider.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | |||
22 | struct uniphier_efuse_priv { | ||
23 | void __iomem *base; | ||
24 | }; | ||
25 | |||
26 | static int uniphier_reg_read(void *context, | ||
27 | unsigned int reg, void *_val, size_t bytes) | ||
28 | { | ||
29 | struct uniphier_efuse_priv *priv = context; | ||
30 | u32 *val = _val; | ||
31 | int offs; | ||
32 | |||
33 | for (offs = 0; offs < bytes; offs += sizeof(u32)) | ||
34 | *val++ = readl(priv->base + reg + offs); | ||
35 | |||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | static int uniphier_efuse_probe(struct platform_device *pdev) | ||
40 | { | ||
41 | struct device *dev = &pdev->dev; | ||
42 | struct resource *res; | ||
43 | struct nvmem_device *nvmem; | ||
44 | struct nvmem_config econfig = {}; | ||
45 | struct uniphier_efuse_priv *priv; | ||
46 | |||
47 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||
48 | if (!priv) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
52 | priv->base = devm_ioremap_resource(dev, res); | ||
53 | if (IS_ERR(priv->base)) | ||
54 | return PTR_ERR(priv->base); | ||
55 | |||
56 | econfig.stride = 4; | ||
57 | econfig.word_size = 4; | ||
58 | econfig.read_only = true; | ||
59 | econfig.reg_read = uniphier_reg_read; | ||
60 | econfig.size = resource_size(res); | ||
61 | econfig.priv = priv; | ||
62 | econfig.dev = dev; | ||
63 | nvmem = nvmem_register(&econfig); | ||
64 | if (IS_ERR(nvmem)) | ||
65 | return PTR_ERR(nvmem); | ||
66 | |||
67 | platform_set_drvdata(pdev, nvmem); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int uniphier_efuse_remove(struct platform_device *pdev) | ||
73 | { | ||
74 | struct nvmem_device *nvmem = platform_get_drvdata(pdev); | ||
75 | |||
76 | return nvmem_unregister(nvmem); | ||
77 | } | ||
78 | |||
79 | static const struct of_device_id uniphier_efuse_of_match[] = { | ||
80 | { .compatible = "socionext,uniphier-efuse",}, | ||
81 | {/* sentinel */}, | ||
82 | }; | ||
83 | MODULE_DEVICE_TABLE(of, uniphier_efuse_of_match); | ||
84 | |||
85 | static struct platform_driver uniphier_efuse_driver = { | ||
86 | .probe = uniphier_efuse_probe, | ||
87 | .remove = uniphier_efuse_remove, | ||
88 | .driver = { | ||
89 | .name = "uniphier-efuse", | ||
90 | .of_match_table = uniphier_efuse_of_match, | ||
91 | }, | ||
92 | }; | ||
93 | module_platform_driver(uniphier_efuse_driver); | ||
94 | |||
95 | MODULE_AUTHOR("Keiji Hayashibara <hayashibara.keiji@socionext.com>"); | ||
96 | MODULE_DESCRIPTION("UniPhier eFuse driver"); | ||
97 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/nvmem/vf610-ocotp.c b/drivers/nvmem/vf610-ocotp.c index 72e4faabce29..5ae9e002f195 100644 --- a/drivers/nvmem/vf610-ocotp.c +++ b/drivers/nvmem/vf610-ocotp.c | |||
@@ -206,7 +206,6 @@ static int vf610_ocotp_read(void *context, unsigned int offset, | |||
206 | 206 | ||
207 | static struct nvmem_config ocotp_config = { | 207 | static struct nvmem_config ocotp_config = { |
208 | .name = "ocotp", | 208 | .name = "ocotp", |
209 | .owner = THIS_MODULE, | ||
210 | .stride = 4, | 209 | .stride = 4, |
211 | .word_size = 4, | 210 | .word_size = 4, |
212 | .reg_read = vf610_ocotp_read, | 211 | .reg_read = vf610_ocotp_read, |
diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c index 0186db7680d4..62873070f988 100644 --- a/drivers/parport/parport_ip32.c +++ b/drivers/parport/parport_ip32.c | |||
@@ -1769,7 +1769,7 @@ stop: | |||
1769 | 1769 | ||
1770 | /*--- Default parport operations ---------------------------------------*/ | 1770 | /*--- Default parport operations ---------------------------------------*/ |
1771 | 1771 | ||
1772 | static __initdata struct parport_operations parport_ip32_ops = { | 1772 | static const struct parport_operations parport_ip32_ops __initconst = { |
1773 | .write_data = parport_ip32_write_data, | 1773 | .write_data = parport_ip32_write_data, |
1774 | .read_data = parport_ip32_read_data, | 1774 | .read_data = parport_ip32_read_data, |
1775 | 1775 | ||
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 55ef7d1fd8da..102646fedb56 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -1599,7 +1599,7 @@ static ssize_t pccard_store_cis(struct file *filp, struct kobject *kobj, | |||
1599 | } | 1599 | } |
1600 | 1600 | ||
1601 | 1601 | ||
1602 | struct bin_attribute pccard_cis_attr = { | 1602 | const struct bin_attribute pccard_cis_attr = { |
1603 | .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, | 1603 | .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR }, |
1604 | .size = 0x200, | 1604 | .size = 0x200, |
1605 | .read = pccard_show_cis, | 1605 | .read = pccard_show_cis, |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index e86cd6b31773..6765beadea95 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -152,7 +152,7 @@ void pcmcia_cleanup_irq(struct pcmcia_socket *s); | |||
152 | int pcmcia_setup_irq(struct pcmcia_device *p_dev); | 152 | int pcmcia_setup_irq(struct pcmcia_device *p_dev); |
153 | 153 | ||
154 | /* cistpl.c */ | 154 | /* cistpl.c */ |
155 | extern struct bin_attribute pccard_cis_attr; | 155 | extern const struct bin_attribute pccard_cis_attr; |
156 | 156 | ||
157 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, | 157 | int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, |
158 | u_int addr, u_int len, void *ptr); | 158 | u_int addr, u_int len, void *ptr); |
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 70b089430fcc..9a4940e56e2f 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c | |||
@@ -380,11 +380,10 @@ static irqreturn_t pcc_interrupt(int irq, void *dev) | |||
380 | return IRQ_RETVAL(handled); | 380 | return IRQ_RETVAL(handled); |
381 | } /* pcc_interrupt */ | 381 | } /* pcc_interrupt */ |
382 | 382 | ||
383 | static void pcc_interrupt_wrapper(u_long data) | 383 | static void pcc_interrupt_wrapper(struct timer_list *unused) |
384 | { | 384 | { |
385 | pr_debug("m32r_cfc: pcc_interrupt_wrapper:\n"); | 385 | pr_debug("m32r_cfc: pcc_interrupt_wrapper:\n"); |
386 | pcc_interrupt(0, NULL); | 386 | pcc_interrupt(0, NULL); |
387 | init_timer(&poll_timer); | ||
388 | poll_timer.expires = jiffies + poll_interval; | 387 | poll_timer.expires = jiffies + poll_interval; |
389 | add_timer(&poll_timer); | 388 | add_timer(&poll_timer); |
390 | } | 389 | } |
@@ -758,9 +757,7 @@ static int __init init_m32r_pcc(void) | |||
758 | 757 | ||
759 | /* Finally, schedule a polling interrupt */ | 758 | /* Finally, schedule a polling interrupt */ |
760 | if (poll_interval != 0) { | 759 | if (poll_interval != 0) { |
761 | poll_timer.function = pcc_interrupt_wrapper; | 760 | timer_setup(&poll_timer, pcc_interrupt_wrapper, 0); |
762 | poll_timer.data = 0; | ||
763 | init_timer(&poll_timer); | ||
764 | poll_timer.expires = jiffies + poll_interval; | 761 | poll_timer.expires = jiffies + poll_interval; |
765 | add_timer(&poll_timer); | 762 | add_timer(&poll_timer); |
766 | } | 763 | } |
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index e50bbf826188..c2239a7e383a 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c | |||
@@ -386,10 +386,9 @@ static irqreturn_t pcc_interrupt(int irq, void *dev) | |||
386 | return IRQ_RETVAL(handled); | 386 | return IRQ_RETVAL(handled); |
387 | } /* pcc_interrupt */ | 387 | } /* pcc_interrupt */ |
388 | 388 | ||
389 | static void pcc_interrupt_wrapper(u_long data) | 389 | static void pcc_interrupt_wrapper(struct timer_list *unused) |
390 | { | 390 | { |
391 | pcc_interrupt(0, NULL); | 391 | pcc_interrupt(0, NULL); |
392 | init_timer(&poll_timer); | ||
393 | poll_timer.expires = jiffies + poll_interval; | 392 | poll_timer.expires = jiffies + poll_interval; |
394 | add_timer(&poll_timer); | 393 | add_timer(&poll_timer); |
395 | } | 394 | } |
@@ -729,9 +728,7 @@ static int __init init_m32r_pcc(void) | |||
729 | 728 | ||
730 | /* Finally, schedule a polling interrupt */ | 729 | /* Finally, schedule a polling interrupt */ |
731 | if (poll_interval != 0) { | 730 | if (poll_interval != 0) { |
732 | poll_timer.function = pcc_interrupt_wrapper; | 731 | timer_setup(&poll_timer, pcc_interrupt_wrapper, 0); |
733 | poll_timer.data = 0; | ||
734 | init_timer(&poll_timer); | ||
735 | poll_timer.expires = jiffies + poll_interval; | 732 | poll_timer.expires = jiffies + poll_interval; |
736 | add_timer(&poll_timer); | 733 | add_timer(&poll_timer); |
737 | } | 734 | } |
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index d674e06767a5..1424581fd9af 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c | |||
@@ -225,6 +225,7 @@ static void tb_activate_pcie_devices(struct tb *tb) | |||
225 | tb_port_info(up_port, | 225 | tb_port_info(up_port, |
226 | "PCIe tunnel activation failed, aborting\n"); | 226 | "PCIe tunnel activation failed, aborting\n"); |
227 | tb_pci_free(tunnel); | 227 | tb_pci_free(tunnel); |
228 | continue; | ||
228 | } | 229 | } |
229 | 230 | ||
230 | list_add(&tunnel->list, &tcm->tunnel_list); | 231 | list_add(&tunnel->list, &tcm->tunnel_list); |
diff --git a/drivers/vme/bridges/vme_ca91cx42.c b/drivers/vme/bridges/vme_ca91cx42.c index 7cc51223db1c..5dd284008630 100644 --- a/drivers/vme/bridges/vme_ca91cx42.c +++ b/drivers/vme/bridges/vme_ca91cx42.c | |||
@@ -511,7 +511,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image, | |||
511 | ca91cx42_bridge = image->parent; | 511 | ca91cx42_bridge = image->parent; |
512 | 512 | ||
513 | /* Find pci_dev container of dev */ | 513 | /* Find pci_dev container of dev */ |
514 | if (ca91cx42_bridge->parent == NULL) { | 514 | if (!ca91cx42_bridge->parent) { |
515 | dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); | 515 | dev_err(ca91cx42_bridge->parent, "Dev entry NULL\n"); |
516 | return -EINVAL; | 516 | return -EINVAL; |
517 | } | 517 | } |
@@ -529,14 +529,12 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image, | |||
529 | image->kern_base = NULL; | 529 | image->kern_base = NULL; |
530 | kfree(image->bus_resource.name); | 530 | kfree(image->bus_resource.name); |
531 | release_resource(&image->bus_resource); | 531 | release_resource(&image->bus_resource); |
532 | memset(&image->bus_resource, 0, sizeof(struct resource)); | 532 | memset(&image->bus_resource, 0, sizeof(image->bus_resource)); |
533 | } | 533 | } |
534 | 534 | ||
535 | if (image->bus_resource.name == NULL) { | 535 | if (!image->bus_resource.name) { |
536 | image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); | 536 | image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); |
537 | if (image->bus_resource.name == NULL) { | 537 | if (!image->bus_resource.name) { |
538 | dev_err(ca91cx42_bridge->parent, "Unable to allocate " | ||
539 | "memory for resource name\n"); | ||
540 | retval = -ENOMEM; | 538 | retval = -ENOMEM; |
541 | goto err_name; | 539 | goto err_name; |
542 | } | 540 | } |
@@ -562,7 +560,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image, | |||
562 | 560 | ||
563 | image->kern_base = ioremap_nocache( | 561 | image->kern_base = ioremap_nocache( |
564 | image->bus_resource.start, size); | 562 | image->bus_resource.start, size); |
565 | if (image->kern_base == NULL) { | 563 | if (!image->kern_base) { |
566 | dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); | 564 | dev_err(ca91cx42_bridge->parent, "Failed to remap resource\n"); |
567 | retval = -ENOMEM; | 565 | retval = -ENOMEM; |
568 | goto err_remap; | 566 | goto err_remap; |
@@ -574,7 +572,7 @@ err_remap: | |||
574 | release_resource(&image->bus_resource); | 572 | release_resource(&image->bus_resource); |
575 | err_resource: | 573 | err_resource: |
576 | kfree(image->bus_resource.name); | 574 | kfree(image->bus_resource.name); |
577 | memset(&image->bus_resource, 0, sizeof(struct resource)); | 575 | memset(&image->bus_resource, 0, sizeof(image->bus_resource)); |
578 | err_name: | 576 | err_name: |
579 | return retval; | 577 | return retval; |
580 | } | 578 | } |
@@ -588,7 +586,7 @@ static void ca91cx42_free_resource(struct vme_master_resource *image) | |||
588 | image->kern_base = NULL; | 586 | image->kern_base = NULL; |
589 | release_resource(&image->bus_resource); | 587 | release_resource(&image->bus_resource); |
590 | kfree(image->bus_resource.name); | 588 | kfree(image->bus_resource.name); |
591 | memset(&image->bus_resource, 0, sizeof(struct resource)); | 589 | memset(&image->bus_resource, 0, sizeof(image->bus_resource)); |
592 | } | 590 | } |
593 | 591 | ||
594 | 592 | ||
@@ -1036,10 +1034,8 @@ static int ca91cx42_dma_list_add(struct vme_dma_list *list, | |||
1036 | dev = list->parent->parent->parent; | 1034 | dev = list->parent->parent->parent; |
1037 | 1035 | ||
1038 | /* XXX descriptor must be aligned on 64-bit boundaries */ | 1036 | /* XXX descriptor must be aligned on 64-bit boundaries */ |
1039 | entry = kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL); | 1037 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
1040 | if (entry == NULL) { | 1038 | if (!entry) { |
1041 | dev_err(dev, "Failed to allocate memory for dma resource " | ||
1042 | "structure\n"); | ||
1043 | retval = -ENOMEM; | 1039 | retval = -ENOMEM; |
1044 | goto err_mem; | 1040 | goto err_mem; |
1045 | } | 1041 | } |
@@ -1052,7 +1048,7 @@ static int ca91cx42_dma_list_add(struct vme_dma_list *list, | |||
1052 | goto err_align; | 1048 | goto err_align; |
1053 | } | 1049 | } |
1054 | 1050 | ||
1055 | memset(&entry->descriptor, 0, sizeof(struct ca91cx42_dma_descriptor)); | 1051 | memset(&entry->descriptor, 0, sizeof(entry->descriptor)); |
1056 | 1052 | ||
1057 | if (dest->type == VME_DMA_VME) { | 1053 | if (dest->type == VME_DMA_VME) { |
1058 | entry->descriptor.dctl |= CA91CX42_DCTL_L2V; | 1054 | entry->descriptor.dctl |= CA91CX42_DCTL_L2V; |
@@ -1323,7 +1319,7 @@ static int ca91cx42_lm_set(struct vme_lm_resource *lm, | |||
1323 | 1319 | ||
1324 | /* If we already have a callback attached, we can't move it! */ | 1320 | /* If we already have a callback attached, we can't move it! */ |
1325 | for (i = 0; i < lm->monitors; i++) { | 1321 | for (i = 0; i < lm->monitors; i++) { |
1326 | if (bridge->lm_callback[i] != NULL) { | 1322 | if (bridge->lm_callback[i]) { |
1327 | mutex_unlock(&lm->mtx); | 1323 | mutex_unlock(&lm->mtx); |
1328 | dev_err(dev, "Location monitor callback attached, " | 1324 | dev_err(dev, "Location monitor callback attached, " |
1329 | "can't reset\n"); | 1325 | "can't reset\n"); |
@@ -1432,7 +1428,7 @@ static int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor, | |||
1432 | } | 1428 | } |
1433 | 1429 | ||
1434 | /* Check that a callback isn't already attached */ | 1430 | /* Check that a callback isn't already attached */ |
1435 | if (bridge->lm_callback[monitor] != NULL) { | 1431 | if (bridge->lm_callback[monitor]) { |
1436 | mutex_unlock(&lm->mtx); | 1432 | mutex_unlock(&lm->mtx); |
1437 | dev_err(dev, "Existing callback attached\n"); | 1433 | dev_err(dev, "Existing callback attached\n"); |
1438 | return -EBUSY; | 1434 | return -EBUSY; |
@@ -1567,7 +1563,7 @@ static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge, | |||
1567 | /* Allocate mem for CR/CSR image */ | 1563 | /* Allocate mem for CR/CSR image */ |
1568 | bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE, | 1564 | bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE, |
1569 | &bridge->crcsr_bus); | 1565 | &bridge->crcsr_bus); |
1570 | if (bridge->crcsr_kernel == NULL) { | 1566 | if (!bridge->crcsr_kernel) { |
1571 | dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " | 1567 | dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " |
1572 | "image\n"); | 1568 | "image\n"); |
1573 | return -ENOMEM; | 1569 | return -ENOMEM; |
@@ -1618,21 +1614,15 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1618 | /* We want to support more than one of each bridge so we need to | 1614 | /* We want to support more than one of each bridge so we need to |
1619 | * dynamically allocate the bridge structure | 1615 | * dynamically allocate the bridge structure |
1620 | */ | 1616 | */ |
1621 | ca91cx42_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); | 1617 | ca91cx42_bridge = kzalloc(sizeof(*ca91cx42_bridge), GFP_KERNEL); |
1622 | 1618 | if (!ca91cx42_bridge) { | |
1623 | if (ca91cx42_bridge == NULL) { | ||
1624 | dev_err(&pdev->dev, "Failed to allocate memory for device " | ||
1625 | "structure\n"); | ||
1626 | retval = -ENOMEM; | 1619 | retval = -ENOMEM; |
1627 | goto err_struct; | 1620 | goto err_struct; |
1628 | } | 1621 | } |
1629 | vme_init_bridge(ca91cx42_bridge); | 1622 | vme_init_bridge(ca91cx42_bridge); |
1630 | 1623 | ||
1631 | ca91cx42_device = kzalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL); | 1624 | ca91cx42_device = kzalloc(sizeof(*ca91cx42_device), GFP_KERNEL); |
1632 | 1625 | if (!ca91cx42_device) { | |
1633 | if (ca91cx42_device == NULL) { | ||
1634 | dev_err(&pdev->dev, "Failed to allocate memory for device " | ||
1635 | "structure\n"); | ||
1636 | retval = -ENOMEM; | 1626 | retval = -ENOMEM; |
1637 | goto err_driver; | 1627 | goto err_driver; |
1638 | } | 1628 | } |
@@ -1688,11 +1678,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1688 | 1678 | ||
1689 | /* Add master windows to list */ | 1679 | /* Add master windows to list */ |
1690 | for (i = 0; i < CA91C142_MAX_MASTER; i++) { | 1680 | for (i = 0; i < CA91C142_MAX_MASTER; i++) { |
1691 | master_image = kmalloc(sizeof(struct vme_master_resource), | 1681 | master_image = kmalloc(sizeof(*master_image), GFP_KERNEL); |
1692 | GFP_KERNEL); | 1682 | if (!master_image) { |
1693 | if (master_image == NULL) { | ||
1694 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1695 | "master resource structure\n"); | ||
1696 | retval = -ENOMEM; | 1683 | retval = -ENOMEM; |
1697 | goto err_master; | 1684 | goto err_master; |
1698 | } | 1685 | } |
@@ -1706,7 +1693,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1706 | VME_SUPER | VME_USER | VME_PROG | VME_DATA; | 1693 | VME_SUPER | VME_USER | VME_PROG | VME_DATA; |
1707 | master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; | 1694 | master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; |
1708 | memset(&master_image->bus_resource, 0, | 1695 | memset(&master_image->bus_resource, 0, |
1709 | sizeof(struct resource)); | 1696 | sizeof(master_image->bus_resource)); |
1710 | master_image->kern_base = NULL; | 1697 | master_image->kern_base = NULL; |
1711 | list_add_tail(&master_image->list, | 1698 | list_add_tail(&master_image->list, |
1712 | &ca91cx42_bridge->master_resources); | 1699 | &ca91cx42_bridge->master_resources); |
@@ -1714,11 +1701,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1714 | 1701 | ||
1715 | /* Add slave windows to list */ | 1702 | /* Add slave windows to list */ |
1716 | for (i = 0; i < CA91C142_MAX_SLAVE; i++) { | 1703 | for (i = 0; i < CA91C142_MAX_SLAVE; i++) { |
1717 | slave_image = kmalloc(sizeof(struct vme_slave_resource), | 1704 | slave_image = kmalloc(sizeof(*slave_image), GFP_KERNEL); |
1718 | GFP_KERNEL); | 1705 | if (!slave_image) { |
1719 | if (slave_image == NULL) { | ||
1720 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1721 | "slave resource structure\n"); | ||
1722 | retval = -ENOMEM; | 1706 | retval = -ENOMEM; |
1723 | goto err_slave; | 1707 | goto err_slave; |
1724 | } | 1708 | } |
@@ -1741,11 +1725,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1741 | 1725 | ||
1742 | /* Add dma engines to list */ | 1726 | /* Add dma engines to list */ |
1743 | for (i = 0; i < CA91C142_MAX_DMA; i++) { | 1727 | for (i = 0; i < CA91C142_MAX_DMA; i++) { |
1744 | dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), | 1728 | dma_ctrlr = kmalloc(sizeof(*dma_ctrlr), GFP_KERNEL); |
1745 | GFP_KERNEL); | 1729 | if (!dma_ctrlr) { |
1746 | if (dma_ctrlr == NULL) { | ||
1747 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1748 | "dma resource structure\n"); | ||
1749 | retval = -ENOMEM; | 1730 | retval = -ENOMEM; |
1750 | goto err_dma; | 1731 | goto err_dma; |
1751 | } | 1732 | } |
@@ -1762,10 +1743,8 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1762 | } | 1743 | } |
1763 | 1744 | ||
1764 | /* Add location monitor to list */ | 1745 | /* Add location monitor to list */ |
1765 | lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); | 1746 | lm = kmalloc(sizeof(*lm), GFP_KERNEL); |
1766 | if (lm == NULL) { | 1747 | if (!lm) { |
1767 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1768 | "location monitor resource structure\n"); | ||
1769 | retval = -ENOMEM; | 1748 | retval = -ENOMEM; |
1770 | goto err_lm; | 1749 | goto err_lm; |
1771 | } | 1750 | } |
diff --git a/drivers/vme/bridges/vme_fake.c b/drivers/vme/bridges/vme_fake.c index 30b3acc93833..7d83691047f4 100644 --- a/drivers/vme/bridges/vme_fake.c +++ b/drivers/vme/bridges/vme_fake.c | |||
@@ -409,7 +409,7 @@ static void fake_lm_check(struct fake_driver *bridge, unsigned long long addr, | |||
409 | /* Each location monitor covers 8 bytes */ | 409 | /* Each location monitor covers 8 bytes */ |
410 | if (((lm_base + (8 * i)) <= addr) && | 410 | if (((lm_base + (8 * i)) <= addr) && |
411 | ((lm_base + (8 * i) + 8) > addr)) { | 411 | ((lm_base + (8 * i) + 8) > addr)) { |
412 | if (bridge->lm_callback[i] != NULL) | 412 | if (bridge->lm_callback[i]) |
413 | bridge->lm_callback[i]( | 413 | bridge->lm_callback[i]( |
414 | bridge->lm_data[i]); | 414 | bridge->lm_data[i]); |
415 | } | 415 | } |
@@ -866,7 +866,7 @@ static int fake_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, | |||
866 | 866 | ||
867 | /* If we already have a callback attached, we can't move it! */ | 867 | /* If we already have a callback attached, we can't move it! */ |
868 | for (i = 0; i < lm->monitors; i++) { | 868 | for (i = 0; i < lm->monitors; i++) { |
869 | if (bridge->lm_callback[i] != NULL) { | 869 | if (bridge->lm_callback[i]) { |
870 | mutex_unlock(&lm->mtx); | 870 | mutex_unlock(&lm->mtx); |
871 | pr_err("Location monitor callback attached, can't reset\n"); | 871 | pr_err("Location monitor callback attached, can't reset\n"); |
872 | return -EBUSY; | 872 | return -EBUSY; |
@@ -940,7 +940,7 @@ static int fake_lm_attach(struct vme_lm_resource *lm, int monitor, | |||
940 | } | 940 | } |
941 | 941 | ||
942 | /* Check that a callback isn't already attached */ | 942 | /* Check that a callback isn't already attached */ |
943 | if (bridge->lm_callback[monitor] != NULL) { | 943 | if (bridge->lm_callback[monitor]) { |
944 | mutex_unlock(&lm->mtx); | 944 | mutex_unlock(&lm->mtx); |
945 | pr_err("Existing callback attached\n"); | 945 | pr_err("Existing callback attached\n"); |
946 | return -EBUSY; | 946 | return -EBUSY; |
@@ -978,7 +978,7 @@ static int fake_lm_detach(struct vme_lm_resource *lm, int monitor) | |||
978 | /* If all location monitors disabled, disable global Location Monitor */ | 978 | /* If all location monitors disabled, disable global Location Monitor */ |
979 | tmp = 0; | 979 | tmp = 0; |
980 | for (i = 0; i < lm->monitors; i++) { | 980 | for (i = 0; i < lm->monitors; i++) { |
981 | if (bridge->lm_callback[i] != NULL) | 981 | if (bridge->lm_callback[i]) |
982 | tmp = 1; | 982 | tmp = 1; |
983 | } | 983 | } |
984 | 984 | ||
@@ -1003,7 +1003,7 @@ static void *fake_alloc_consistent(struct device *parent, size_t size, | |||
1003 | { | 1003 | { |
1004 | void *alloc = kmalloc(size, GFP_KERNEL); | 1004 | void *alloc = kmalloc(size, GFP_KERNEL); |
1005 | 1005 | ||
1006 | if (alloc != NULL) | 1006 | if (alloc) |
1007 | *dma = fake_ptr_to_pci(alloc); | 1007 | *dma = fake_ptr_to_pci(alloc); |
1008 | 1008 | ||
1009 | return alloc; | 1009 | return alloc; |
@@ -1039,7 +1039,7 @@ static int fake_crcsr_init(struct vme_bridge *fake_bridge) | |||
1039 | /* Allocate mem for CR/CSR image */ | 1039 | /* Allocate mem for CR/CSR image */ |
1040 | bridge->crcsr_kernel = kzalloc(VME_CRCSR_BUF_SIZE, GFP_KERNEL); | 1040 | bridge->crcsr_kernel = kzalloc(VME_CRCSR_BUF_SIZE, GFP_KERNEL); |
1041 | bridge->crcsr_bus = fake_ptr_to_pci(bridge->crcsr_kernel); | 1041 | bridge->crcsr_bus = fake_ptr_to_pci(bridge->crcsr_kernel); |
1042 | if (bridge->crcsr_kernel == NULL) | 1042 | if (!bridge->crcsr_kernel) |
1043 | return -ENOMEM; | 1043 | return -ENOMEM; |
1044 | 1044 | ||
1045 | vstat = fake_slot_get(fake_bridge); | 1045 | vstat = fake_slot_get(fake_bridge); |
@@ -1075,14 +1075,14 @@ static int __init fake_init(void) | |||
1075 | /* If we want to support more than one bridge at some point, we need to | 1075 | /* If we want to support more than one bridge at some point, we need to |
1076 | * dynamically allocate this so we get one per device. | 1076 | * dynamically allocate this so we get one per device. |
1077 | */ | 1077 | */ |
1078 | fake_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); | 1078 | fake_bridge = kzalloc(sizeof(*fake_bridge), GFP_KERNEL); |
1079 | if (fake_bridge == NULL) { | 1079 | if (!fake_bridge) { |
1080 | retval = -ENOMEM; | 1080 | retval = -ENOMEM; |
1081 | goto err_struct; | 1081 | goto err_struct; |
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | fake_device = kzalloc(sizeof(struct fake_driver), GFP_KERNEL); | 1084 | fake_device = kzalloc(sizeof(*fake_device), GFP_KERNEL); |
1085 | if (fake_device == NULL) { | 1085 | if (!fake_device) { |
1086 | retval = -ENOMEM; | 1086 | retval = -ENOMEM; |
1087 | goto err_driver; | 1087 | goto err_driver; |
1088 | } | 1088 | } |
@@ -1104,9 +1104,8 @@ static int __init fake_init(void) | |||
1104 | /* Add master windows to list */ | 1104 | /* Add master windows to list */ |
1105 | INIT_LIST_HEAD(&fake_bridge->master_resources); | 1105 | INIT_LIST_HEAD(&fake_bridge->master_resources); |
1106 | for (i = 0; i < FAKE_MAX_MASTER; i++) { | 1106 | for (i = 0; i < FAKE_MAX_MASTER; i++) { |
1107 | master_image = kmalloc(sizeof(struct vme_master_resource), | 1107 | master_image = kmalloc(sizeof(*master_image), GFP_KERNEL); |
1108 | GFP_KERNEL); | 1108 | if (!master_image) { |
1109 | if (master_image == NULL) { | ||
1110 | retval = -ENOMEM; | 1109 | retval = -ENOMEM; |
1111 | goto err_master; | 1110 | goto err_master; |
1112 | } | 1111 | } |
@@ -1131,9 +1130,8 @@ static int __init fake_init(void) | |||
1131 | /* Add slave windows to list */ | 1130 | /* Add slave windows to list */ |
1132 | INIT_LIST_HEAD(&fake_bridge->slave_resources); | 1131 | INIT_LIST_HEAD(&fake_bridge->slave_resources); |
1133 | for (i = 0; i < FAKE_MAX_SLAVE; i++) { | 1132 | for (i = 0; i < FAKE_MAX_SLAVE; i++) { |
1134 | slave_image = kmalloc(sizeof(struct vme_slave_resource), | 1133 | slave_image = kmalloc(sizeof(*slave_image), GFP_KERNEL); |
1135 | GFP_KERNEL); | 1134 | if (!slave_image) { |
1136 | if (slave_image == NULL) { | ||
1137 | retval = -ENOMEM; | 1135 | retval = -ENOMEM; |
1138 | goto err_slave; | 1136 | goto err_slave; |
1139 | } | 1137 | } |
@@ -1154,9 +1152,8 @@ static int __init fake_init(void) | |||
1154 | 1152 | ||
1155 | /* Add location monitor to list */ | 1153 | /* Add location monitor to list */ |
1156 | INIT_LIST_HEAD(&fake_bridge->lm_resources); | 1154 | INIT_LIST_HEAD(&fake_bridge->lm_resources); |
1157 | lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); | 1155 | lm = kmalloc(sizeof(*lm), GFP_KERNEL); |
1158 | if (lm == NULL) { | 1156 | if (!lm) { |
1159 | pr_err("Failed to allocate memory for location monitor resource structure\n"); | ||
1160 | retval = -ENOMEM; | 1157 | retval = -ENOMEM; |
1161 | goto err_lm; | 1158 | goto err_lm; |
1162 | } | 1159 | } |
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index fc1b634b969a..647d231d4422 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c | |||
@@ -741,18 +741,16 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, | |||
741 | image->kern_base = NULL; | 741 | image->kern_base = NULL; |
742 | kfree(image->bus_resource.name); | 742 | kfree(image->bus_resource.name); |
743 | release_resource(&image->bus_resource); | 743 | release_resource(&image->bus_resource); |
744 | memset(&image->bus_resource, 0, sizeof(struct resource)); | 744 | memset(&image->bus_resource, 0, sizeof(image->bus_resource)); |
745 | } | 745 | } |
746 | 746 | ||
747 | /* Exit here if size is zero */ | 747 | /* Exit here if size is zero */ |
748 | if (size == 0) | 748 | if (size == 0) |
749 | return 0; | 749 | return 0; |
750 | 750 | ||
751 | if (image->bus_resource.name == NULL) { | 751 | if (!image->bus_resource.name) { |
752 | image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); | 752 | image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_ATOMIC); |
753 | if (image->bus_resource.name == NULL) { | 753 | if (!image->bus_resource.name) { |
754 | dev_err(tsi148_bridge->parent, "Unable to allocate " | ||
755 | "memory for resource name\n"); | ||
756 | retval = -ENOMEM; | 754 | retval = -ENOMEM; |
757 | goto err_name; | 755 | goto err_name; |
758 | } | 756 | } |
@@ -778,7 +776,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, | |||
778 | 776 | ||
779 | image->kern_base = ioremap_nocache( | 777 | image->kern_base = ioremap_nocache( |
780 | image->bus_resource.start, size); | 778 | image->bus_resource.start, size); |
781 | if (image->kern_base == NULL) { | 779 | if (!image->kern_base) { |
782 | dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); | 780 | dev_err(tsi148_bridge->parent, "Failed to remap resource\n"); |
783 | retval = -ENOMEM; | 781 | retval = -ENOMEM; |
784 | goto err_remap; | 782 | goto err_remap; |
@@ -790,7 +788,7 @@ err_remap: | |||
790 | release_resource(&image->bus_resource); | 788 | release_resource(&image->bus_resource); |
791 | err_resource: | 789 | err_resource: |
792 | kfree(image->bus_resource.name); | 790 | kfree(image->bus_resource.name); |
793 | memset(&image->bus_resource, 0, sizeof(struct resource)); | 791 | memset(&image->bus_resource, 0, sizeof(image->bus_resource)); |
794 | err_name: | 792 | err_name: |
795 | return retval; | 793 | return retval; |
796 | } | 794 | } |
@@ -804,7 +802,7 @@ static void tsi148_free_resource(struct vme_master_resource *image) | |||
804 | image->kern_base = NULL; | 802 | image->kern_base = NULL; |
805 | release_resource(&image->bus_resource); | 803 | release_resource(&image->bus_resource); |
806 | kfree(image->bus_resource.name); | 804 | kfree(image->bus_resource.name); |
807 | memset(&image->bus_resource, 0, sizeof(struct resource)); | 805 | memset(&image->bus_resource, 0, sizeof(image->bus_resource)); |
808 | } | 806 | } |
809 | 807 | ||
810 | /* | 808 | /* |
@@ -1641,10 +1639,8 @@ static int tsi148_dma_list_add(struct vme_dma_list *list, | |||
1641 | tsi148_bridge = list->parent->parent; | 1639 | tsi148_bridge = list->parent->parent; |
1642 | 1640 | ||
1643 | /* Descriptor must be aligned on 64-bit boundaries */ | 1641 | /* Descriptor must be aligned on 64-bit boundaries */ |
1644 | entry = kmalloc(sizeof(struct tsi148_dma_entry), GFP_KERNEL); | 1642 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
1645 | if (entry == NULL) { | 1643 | if (!entry) { |
1646 | dev_err(tsi148_bridge->parent, "Failed to allocate memory for " | ||
1647 | "dma resource structure\n"); | ||
1648 | retval = -ENOMEM; | 1644 | retval = -ENOMEM; |
1649 | goto err_mem; | 1645 | goto err_mem; |
1650 | } | 1646 | } |
@@ -1661,7 +1657,7 @@ static int tsi148_dma_list_add(struct vme_dma_list *list, | |||
1661 | /* Given we are going to fill out the structure, we probably don't | 1657 | /* Given we are going to fill out the structure, we probably don't |
1662 | * need to zero it, but better safe than sorry for now. | 1658 | * need to zero it, but better safe than sorry for now. |
1663 | */ | 1659 | */ |
1664 | memset(&entry->descriptor, 0, sizeof(struct tsi148_dma_descriptor)); | 1660 | memset(&entry->descriptor, 0, sizeof(entry->descriptor)); |
1665 | 1661 | ||
1666 | /* Fill out source part */ | 1662 | /* Fill out source part */ |
1667 | switch (src->type) { | 1663 | switch (src->type) { |
@@ -1756,8 +1752,9 @@ static int tsi148_dma_list_add(struct vme_dma_list *list, | |||
1756 | list_add_tail(&entry->list, &list->entries); | 1752 | list_add_tail(&entry->list, &list->entries); |
1757 | 1753 | ||
1758 | entry->dma_handle = dma_map_single(tsi148_bridge->parent, | 1754 | entry->dma_handle = dma_map_single(tsi148_bridge->parent, |
1759 | &entry->descriptor, | 1755 | &entry->descriptor, |
1760 | sizeof(struct tsi148_dma_descriptor), DMA_TO_DEVICE); | 1756 | sizeof(entry->descriptor), |
1757 | DMA_TO_DEVICE); | ||
1761 | if (dma_mapping_error(tsi148_bridge->parent, entry->dma_handle)) { | 1758 | if (dma_mapping_error(tsi148_bridge->parent, entry->dma_handle)) { |
1762 | dev_err(tsi148_bridge->parent, "DMA mapping error\n"); | 1759 | dev_err(tsi148_bridge->parent, "DMA mapping error\n"); |
1763 | retval = -EINVAL; | 1760 | retval = -EINVAL; |
@@ -1946,7 +1943,7 @@ static int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base, | |||
1946 | 1943 | ||
1947 | /* If we already have a callback attached, we can't move it! */ | 1944 | /* If we already have a callback attached, we can't move it! */ |
1948 | for (i = 0; i < lm->monitors; i++) { | 1945 | for (i = 0; i < lm->monitors; i++) { |
1949 | if (bridge->lm_callback[i] != NULL) { | 1946 | if (bridge->lm_callback[i]) { |
1950 | mutex_unlock(&lm->mtx); | 1947 | mutex_unlock(&lm->mtx); |
1951 | dev_err(tsi148_bridge->parent, "Location monitor " | 1948 | dev_err(tsi148_bridge->parent, "Location monitor " |
1952 | "callback attached, can't reset\n"); | 1949 | "callback attached, can't reset\n"); |
@@ -2071,7 +2068,7 @@ static int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor, | |||
2071 | } | 2068 | } |
2072 | 2069 | ||
2073 | /* Check that a callback isn't already attached */ | 2070 | /* Check that a callback isn't already attached */ |
2074 | if (bridge->lm_callback[monitor] != NULL) { | 2071 | if (bridge->lm_callback[monitor]) { |
2075 | mutex_unlock(&lm->mtx); | 2072 | mutex_unlock(&lm->mtx); |
2076 | dev_err(tsi148_bridge->parent, "Existing callback attached\n"); | 2073 | dev_err(tsi148_bridge->parent, "Existing callback attached\n"); |
2077 | return -EBUSY; | 2074 | return -EBUSY; |
@@ -2208,7 +2205,7 @@ static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge, | |||
2208 | /* Allocate mem for CR/CSR image */ | 2205 | /* Allocate mem for CR/CSR image */ |
2209 | bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE, | 2206 | bridge->crcsr_kernel = pci_zalloc_consistent(pdev, VME_CRCSR_BUF_SIZE, |
2210 | &bridge->crcsr_bus); | 2207 | &bridge->crcsr_bus); |
2211 | if (bridge->crcsr_kernel == NULL) { | 2208 | if (!bridge->crcsr_kernel) { |
2212 | dev_err(tsi148_bridge->parent, "Failed to allocate memory for " | 2209 | dev_err(tsi148_bridge->parent, "Failed to allocate memory for " |
2213 | "CR/CSR image\n"); | 2210 | "CR/CSR image\n"); |
2214 | return -ENOMEM; | 2211 | return -ENOMEM; |
@@ -2294,19 +2291,15 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2294 | /* If we want to support more than one of each bridge, we need to | 2291 | /* If we want to support more than one of each bridge, we need to |
2295 | * dynamically generate this so we get one per device | 2292 | * dynamically generate this so we get one per device |
2296 | */ | 2293 | */ |
2297 | tsi148_bridge = kzalloc(sizeof(struct vme_bridge), GFP_KERNEL); | 2294 | tsi148_bridge = kzalloc(sizeof(*tsi148_bridge), GFP_KERNEL); |
2298 | if (tsi148_bridge == NULL) { | 2295 | if (!tsi148_bridge) { |
2299 | dev_err(&pdev->dev, "Failed to allocate memory for device " | ||
2300 | "structure\n"); | ||
2301 | retval = -ENOMEM; | 2296 | retval = -ENOMEM; |
2302 | goto err_struct; | 2297 | goto err_struct; |
2303 | } | 2298 | } |
2304 | vme_init_bridge(tsi148_bridge); | 2299 | vme_init_bridge(tsi148_bridge); |
2305 | 2300 | ||
2306 | tsi148_device = kzalloc(sizeof(struct tsi148_driver), GFP_KERNEL); | 2301 | tsi148_device = kzalloc(sizeof(*tsi148_device), GFP_KERNEL); |
2307 | if (tsi148_device == NULL) { | 2302 | if (!tsi148_device) { |
2308 | dev_err(&pdev->dev, "Failed to allocate memory for device " | ||
2309 | "structure\n"); | ||
2310 | retval = -ENOMEM; | 2303 | retval = -ENOMEM; |
2311 | goto err_driver; | 2304 | goto err_driver; |
2312 | } | 2305 | } |
@@ -2371,10 +2364,9 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2371 | master_num--; | 2364 | master_num--; |
2372 | 2365 | ||
2373 | tsi148_device->flush_image = | 2366 | tsi148_device->flush_image = |
2374 | kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL); | 2367 | kmalloc(sizeof(*tsi148_device->flush_image), |
2375 | if (tsi148_device->flush_image == NULL) { | 2368 | GFP_KERNEL); |
2376 | dev_err(&pdev->dev, "Failed to allocate memory for " | 2369 | if (!tsi148_device->flush_image) { |
2377 | "flush resource structure\n"); | ||
2378 | retval = -ENOMEM; | 2370 | retval = -ENOMEM; |
2379 | goto err_master; | 2371 | goto err_master; |
2380 | } | 2372 | } |
@@ -2383,17 +2375,14 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2383 | tsi148_device->flush_image->locked = 1; | 2375 | tsi148_device->flush_image->locked = 1; |
2384 | tsi148_device->flush_image->number = master_num; | 2376 | tsi148_device->flush_image->number = master_num; |
2385 | memset(&tsi148_device->flush_image->bus_resource, 0, | 2377 | memset(&tsi148_device->flush_image->bus_resource, 0, |
2386 | sizeof(struct resource)); | 2378 | sizeof(tsi148_device->flush_image->bus_resource)); |
2387 | tsi148_device->flush_image->kern_base = NULL; | 2379 | tsi148_device->flush_image->kern_base = NULL; |
2388 | } | 2380 | } |
2389 | 2381 | ||
2390 | /* Add master windows to list */ | 2382 | /* Add master windows to list */ |
2391 | for (i = 0; i < master_num; i++) { | 2383 | for (i = 0; i < master_num; i++) { |
2392 | master_image = kmalloc(sizeof(struct vme_master_resource), | 2384 | master_image = kmalloc(sizeof(*master_image), GFP_KERNEL); |
2393 | GFP_KERNEL); | 2385 | if (!master_image) { |
2394 | if (master_image == NULL) { | ||
2395 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
2396 | "master resource structure\n"); | ||
2397 | retval = -ENOMEM; | 2386 | retval = -ENOMEM; |
2398 | goto err_master; | 2387 | goto err_master; |
2399 | } | 2388 | } |
@@ -2410,7 +2399,7 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2410 | VME_PROG | VME_DATA; | 2399 | VME_PROG | VME_DATA; |
2411 | master_image->width_attr = VME_D16 | VME_D32; | 2400 | master_image->width_attr = VME_D16 | VME_D32; |
2412 | memset(&master_image->bus_resource, 0, | 2401 | memset(&master_image->bus_resource, 0, |
2413 | sizeof(struct resource)); | 2402 | sizeof(master_image->bus_resource)); |
2414 | master_image->kern_base = NULL; | 2403 | master_image->kern_base = NULL; |
2415 | list_add_tail(&master_image->list, | 2404 | list_add_tail(&master_image->list, |
2416 | &tsi148_bridge->master_resources); | 2405 | &tsi148_bridge->master_resources); |
@@ -2418,11 +2407,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2418 | 2407 | ||
2419 | /* Add slave windows to list */ | 2408 | /* Add slave windows to list */ |
2420 | for (i = 0; i < TSI148_MAX_SLAVE; i++) { | 2409 | for (i = 0; i < TSI148_MAX_SLAVE; i++) { |
2421 | slave_image = kmalloc(sizeof(struct vme_slave_resource), | 2410 | slave_image = kmalloc(sizeof(*slave_image), GFP_KERNEL); |
2422 | GFP_KERNEL); | 2411 | if (!slave_image) { |
2423 | if (slave_image == NULL) { | ||
2424 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
2425 | "slave resource structure\n"); | ||
2426 | retval = -ENOMEM; | 2412 | retval = -ENOMEM; |
2427 | goto err_slave; | 2413 | goto err_slave; |
2428 | } | 2414 | } |
@@ -2442,11 +2428,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2442 | 2428 | ||
2443 | /* Add dma engines to list */ | 2429 | /* Add dma engines to list */ |
2444 | for (i = 0; i < TSI148_MAX_DMA; i++) { | 2430 | for (i = 0; i < TSI148_MAX_DMA; i++) { |
2445 | dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), | 2431 | dma_ctrlr = kmalloc(sizeof(*dma_ctrlr), GFP_KERNEL); |
2446 | GFP_KERNEL); | 2432 | if (!dma_ctrlr) { |
2447 | if (dma_ctrlr == NULL) { | ||
2448 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
2449 | "dma resource structure\n"); | ||
2450 | retval = -ENOMEM; | 2433 | retval = -ENOMEM; |
2451 | goto err_dma; | 2434 | goto err_dma; |
2452 | } | 2435 | } |
@@ -2465,10 +2448,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2465 | } | 2448 | } |
2466 | 2449 | ||
2467 | /* Add location monitor to list */ | 2450 | /* Add location monitor to list */ |
2468 | lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); | 2451 | lm = kmalloc(sizeof(*lm), GFP_KERNEL); |
2469 | if (lm == NULL) { | 2452 | if (!lm) { |
2470 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
2471 | "location monitor resource structure\n"); | ||
2472 | retval = -ENOMEM; | 2453 | retval = -ENOMEM; |
2473 | goto err_lm; | 2454 | goto err_lm; |
2474 | } | 2455 | } |
diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c index 6a3ead42aba8..81246221a13b 100644 --- a/drivers/vme/vme.c +++ b/drivers/vme/vme.c | |||
@@ -92,23 +92,23 @@ void *vme_alloc_consistent(struct vme_resource *resource, size_t size, | |||
92 | { | 92 | { |
93 | struct vme_bridge *bridge; | 93 | struct vme_bridge *bridge; |
94 | 94 | ||
95 | if (resource == NULL) { | 95 | if (!resource) { |
96 | printk(KERN_ERR "No resource\n"); | 96 | printk(KERN_ERR "No resource\n"); |
97 | return NULL; | 97 | return NULL; |
98 | } | 98 | } |
99 | 99 | ||
100 | bridge = find_bridge(resource); | 100 | bridge = find_bridge(resource); |
101 | if (bridge == NULL) { | 101 | if (!bridge) { |
102 | printk(KERN_ERR "Can't find bridge\n"); | 102 | printk(KERN_ERR "Can't find bridge\n"); |
103 | return NULL; | 103 | return NULL; |
104 | } | 104 | } |
105 | 105 | ||
106 | if (bridge->parent == NULL) { | 106 | if (!bridge->parent) { |
107 | printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); | 107 | printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); |
108 | return NULL; | 108 | return NULL; |
109 | } | 109 | } |
110 | 110 | ||
111 | if (bridge->alloc_consistent == NULL) { | 111 | if (!bridge->alloc_consistent) { |
112 | printk(KERN_ERR "alloc_consistent not supported by bridge %s\n", | 112 | printk(KERN_ERR "alloc_consistent not supported by bridge %s\n", |
113 | bridge->name); | 113 | bridge->name); |
114 | return NULL; | 114 | return NULL; |
@@ -132,23 +132,23 @@ void vme_free_consistent(struct vme_resource *resource, size_t size, | |||
132 | { | 132 | { |
133 | struct vme_bridge *bridge; | 133 | struct vme_bridge *bridge; |
134 | 134 | ||
135 | if (resource == NULL) { | 135 | if (!resource) { |
136 | printk(KERN_ERR "No resource\n"); | 136 | printk(KERN_ERR "No resource\n"); |
137 | return; | 137 | return; |
138 | } | 138 | } |
139 | 139 | ||
140 | bridge = find_bridge(resource); | 140 | bridge = find_bridge(resource); |
141 | if (bridge == NULL) { | 141 | if (!bridge) { |
142 | printk(KERN_ERR "Can't find bridge\n"); | 142 | printk(KERN_ERR "Can't find bridge\n"); |
143 | return; | 143 | return; |
144 | } | 144 | } |
145 | 145 | ||
146 | if (bridge->parent == NULL) { | 146 | if (!bridge->parent) { |
147 | printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); | 147 | printk(KERN_ERR "Dev entry NULL for bridge %s\n", bridge->name); |
148 | return; | 148 | return; |
149 | } | 149 | } |
150 | 150 | ||
151 | if (bridge->free_consistent == NULL) { | 151 | if (!bridge->free_consistent) { |
152 | printk(KERN_ERR "free_consistent not supported by bridge %s\n", | 152 | printk(KERN_ERR "free_consistent not supported by bridge %s\n", |
153 | bridge->name); | 153 | bridge->name); |
154 | return; | 154 | return; |
@@ -208,29 +208,27 @@ int vme_check_window(u32 aspace, unsigned long long vme_base, | |||
208 | { | 208 | { |
209 | int retval = 0; | 209 | int retval = 0; |
210 | 210 | ||
211 | if (vme_base + size < size) | ||
212 | return -EINVAL; | ||
213 | |||
211 | switch (aspace) { | 214 | switch (aspace) { |
212 | case VME_A16: | 215 | case VME_A16: |
213 | if (((vme_base + size) > VME_A16_MAX) || | 216 | if (vme_base + size > VME_A16_MAX) |
214 | (vme_base > VME_A16_MAX)) | ||
215 | retval = -EFAULT; | 217 | retval = -EFAULT; |
216 | break; | 218 | break; |
217 | case VME_A24: | 219 | case VME_A24: |
218 | if (((vme_base + size) > VME_A24_MAX) || | 220 | if (vme_base + size > VME_A24_MAX) |
219 | (vme_base > VME_A24_MAX)) | ||
220 | retval = -EFAULT; | 221 | retval = -EFAULT; |
221 | break; | 222 | break; |
222 | case VME_A32: | 223 | case VME_A32: |
223 | if (((vme_base + size) > VME_A32_MAX) || | 224 | if (vme_base + size > VME_A32_MAX) |
224 | (vme_base > VME_A32_MAX)) | ||
225 | retval = -EFAULT; | 225 | retval = -EFAULT; |
226 | break; | 226 | break; |
227 | case VME_A64: | 227 | case VME_A64: |
228 | if ((size != 0) && (vme_base > U64_MAX + 1 - size)) | 228 | /* The VME_A64_MAX limit is actually U64_MAX + 1 */ |
229 | retval = -EFAULT; | ||
230 | break; | 229 | break; |
231 | case VME_CRCSR: | 230 | case VME_CRCSR: |
232 | if (((vme_base + size) > VME_CRCSR_MAX) || | 231 | if (vme_base + size > VME_CRCSR_MAX) |
233 | (vme_base > VME_CRCSR_MAX)) | ||
234 | retval = -EFAULT; | 232 | retval = -EFAULT; |
235 | break; | 233 | break; |
236 | case VME_USER1: | 234 | case VME_USER1: |
@@ -303,7 +301,7 @@ struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, | |||
303 | struct vme_resource *resource = NULL; | 301 | struct vme_resource *resource = NULL; |
304 | 302 | ||
305 | bridge = vdev->bridge; | 303 | bridge = vdev->bridge; |
306 | if (bridge == NULL) { | 304 | if (!bridge) { |
307 | printk(KERN_ERR "Can't find VME bus\n"); | 305 | printk(KERN_ERR "Can't find VME bus\n"); |
308 | goto err_bus; | 306 | goto err_bus; |
309 | } | 307 | } |
@@ -313,7 +311,7 @@ struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, | |||
313 | slave_image = list_entry(slave_pos, | 311 | slave_image = list_entry(slave_pos, |
314 | struct vme_slave_resource, list); | 312 | struct vme_slave_resource, list); |
315 | 313 | ||
316 | if (slave_image == NULL) { | 314 | if (!slave_image) { |
317 | printk(KERN_ERR "Registered NULL Slave resource\n"); | 315 | printk(KERN_ERR "Registered NULL Slave resource\n"); |
318 | continue; | 316 | continue; |
319 | } | 317 | } |
@@ -333,14 +331,13 @@ struct vme_resource *vme_slave_request(struct vme_dev *vdev, u32 address, | |||
333 | } | 331 | } |
334 | 332 | ||
335 | /* No free image */ | 333 | /* No free image */ |
336 | if (allocated_image == NULL) | 334 | if (!allocated_image) |
337 | goto err_image; | 335 | goto err_image; |
338 | 336 | ||
339 | resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); | 337 | resource = kmalloc(sizeof(*resource), GFP_KERNEL); |
340 | if (resource == NULL) { | 338 | if (!resource) |
341 | printk(KERN_WARNING "Unable to allocate resource structure\n"); | ||
342 | goto err_alloc; | 339 | goto err_alloc; |
343 | } | 340 | |
344 | resource->type = VME_SLAVE; | 341 | resource->type = VME_SLAVE; |
345 | resource->entry = &allocated_image->list; | 342 | resource->entry = &allocated_image->list; |
346 | 343 | ||
@@ -389,7 +386,7 @@ int vme_slave_set(struct vme_resource *resource, int enabled, | |||
389 | 386 | ||
390 | image = list_entry(resource->entry, struct vme_slave_resource, list); | 387 | image = list_entry(resource->entry, struct vme_slave_resource, list); |
391 | 388 | ||
392 | if (bridge->slave_set == NULL) { | 389 | if (!bridge->slave_set) { |
393 | printk(KERN_ERR "Function not supported\n"); | 390 | printk(KERN_ERR "Function not supported\n"); |
394 | return -ENOSYS; | 391 | return -ENOSYS; |
395 | } | 392 | } |
@@ -438,7 +435,7 @@ int vme_slave_get(struct vme_resource *resource, int *enabled, | |||
438 | 435 | ||
439 | image = list_entry(resource->entry, struct vme_slave_resource, list); | 436 | image = list_entry(resource->entry, struct vme_slave_resource, list); |
440 | 437 | ||
441 | if (bridge->slave_get == NULL) { | 438 | if (!bridge->slave_get) { |
442 | printk(KERN_ERR "vme_slave_get not supported\n"); | 439 | printk(KERN_ERR "vme_slave_get not supported\n"); |
443 | return -EINVAL; | 440 | return -EINVAL; |
444 | } | 441 | } |
@@ -465,7 +462,7 @@ void vme_slave_free(struct vme_resource *resource) | |||
465 | 462 | ||
466 | slave_image = list_entry(resource->entry, struct vme_slave_resource, | 463 | slave_image = list_entry(resource->entry, struct vme_slave_resource, |
467 | list); | 464 | list); |
468 | if (slave_image == NULL) { | 465 | if (!slave_image) { |
469 | printk(KERN_ERR "Can't find slave resource\n"); | 466 | printk(KERN_ERR "Can't find slave resource\n"); |
470 | return; | 467 | return; |
471 | } | 468 | } |
@@ -505,7 +502,7 @@ struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, | |||
505 | struct vme_resource *resource = NULL; | 502 | struct vme_resource *resource = NULL; |
506 | 503 | ||
507 | bridge = vdev->bridge; | 504 | bridge = vdev->bridge; |
508 | if (bridge == NULL) { | 505 | if (!bridge) { |
509 | printk(KERN_ERR "Can't find VME bus\n"); | 506 | printk(KERN_ERR "Can't find VME bus\n"); |
510 | goto err_bus; | 507 | goto err_bus; |
511 | } | 508 | } |
@@ -515,7 +512,7 @@ struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, | |||
515 | master_image = list_entry(master_pos, | 512 | master_image = list_entry(master_pos, |
516 | struct vme_master_resource, list); | 513 | struct vme_master_resource, list); |
517 | 514 | ||
518 | if (master_image == NULL) { | 515 | if (!master_image) { |
519 | printk(KERN_WARNING "Registered NULL master resource\n"); | 516 | printk(KERN_WARNING "Registered NULL master resource\n"); |
520 | continue; | 517 | continue; |
521 | } | 518 | } |
@@ -536,16 +533,15 @@ struct vme_resource *vme_master_request(struct vme_dev *vdev, u32 address, | |||
536 | } | 533 | } |
537 | 534 | ||
538 | /* Check to see if we found a resource */ | 535 | /* Check to see if we found a resource */ |
539 | if (allocated_image == NULL) { | 536 | if (!allocated_image) { |
540 | printk(KERN_ERR "Can't find a suitable resource\n"); | 537 | printk(KERN_ERR "Can't find a suitable resource\n"); |
541 | goto err_image; | 538 | goto err_image; |
542 | } | 539 | } |
543 | 540 | ||
544 | resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); | 541 | resource = kmalloc(sizeof(*resource), GFP_KERNEL); |
545 | if (resource == NULL) { | 542 | if (!resource) |
546 | printk(KERN_ERR "Unable to allocate resource structure\n"); | ||
547 | goto err_alloc; | 543 | goto err_alloc; |
548 | } | 544 | |
549 | resource->type = VME_MASTER; | 545 | resource->type = VME_MASTER; |
550 | resource->entry = &allocated_image->list; | 546 | resource->entry = &allocated_image->list; |
551 | 547 | ||
@@ -594,7 +590,7 @@ int vme_master_set(struct vme_resource *resource, int enabled, | |||
594 | 590 | ||
595 | image = list_entry(resource->entry, struct vme_master_resource, list); | 591 | image = list_entry(resource->entry, struct vme_master_resource, list); |
596 | 592 | ||
597 | if (bridge->master_set == NULL) { | 593 | if (!bridge->master_set) { |
598 | printk(KERN_WARNING "vme_master_set not supported\n"); | 594 | printk(KERN_WARNING "vme_master_set not supported\n"); |
599 | return -EINVAL; | 595 | return -EINVAL; |
600 | } | 596 | } |
@@ -644,7 +640,7 @@ int vme_master_get(struct vme_resource *resource, int *enabled, | |||
644 | 640 | ||
645 | image = list_entry(resource->entry, struct vme_master_resource, list); | 641 | image = list_entry(resource->entry, struct vme_master_resource, list); |
646 | 642 | ||
647 | if (bridge->master_get == NULL) { | 643 | if (!bridge->master_get) { |
648 | printk(KERN_WARNING "%s not supported\n", __func__); | 644 | printk(KERN_WARNING "%s not supported\n", __func__); |
649 | return -EINVAL; | 645 | return -EINVAL; |
650 | } | 646 | } |
@@ -676,7 +672,7 @@ ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count, | |||
676 | struct vme_master_resource *image; | 672 | struct vme_master_resource *image; |
677 | size_t length; | 673 | size_t length; |
678 | 674 | ||
679 | if (bridge->master_read == NULL) { | 675 | if (!bridge->master_read) { |
680 | printk(KERN_WARNING "Reading from resource not supported\n"); | 676 | printk(KERN_WARNING "Reading from resource not supported\n"); |
681 | return -EINVAL; | 677 | return -EINVAL; |
682 | } | 678 | } |
@@ -725,7 +721,7 @@ ssize_t vme_master_write(struct vme_resource *resource, void *buf, | |||
725 | struct vme_master_resource *image; | 721 | struct vme_master_resource *image; |
726 | size_t length; | 722 | size_t length; |
727 | 723 | ||
728 | if (bridge->master_write == NULL) { | 724 | if (!bridge->master_write) { |
729 | printk(KERN_WARNING "Writing to resource not supported\n"); | 725 | printk(KERN_WARNING "Writing to resource not supported\n"); |
730 | return -EINVAL; | 726 | return -EINVAL; |
731 | } | 727 | } |
@@ -776,7 +772,7 @@ unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask, | |||
776 | struct vme_bridge *bridge = find_bridge(resource); | 772 | struct vme_bridge *bridge = find_bridge(resource); |
777 | struct vme_master_resource *image; | 773 | struct vme_master_resource *image; |
778 | 774 | ||
779 | if (bridge->master_rmw == NULL) { | 775 | if (!bridge->master_rmw) { |
780 | printk(KERN_WARNING "Writing to resource not supported\n"); | 776 | printk(KERN_WARNING "Writing to resource not supported\n"); |
781 | return -EINVAL; | 777 | return -EINVAL; |
782 | } | 778 | } |
@@ -846,7 +842,7 @@ void vme_master_free(struct vme_resource *resource) | |||
846 | 842 | ||
847 | master_image = list_entry(resource->entry, struct vme_master_resource, | 843 | master_image = list_entry(resource->entry, struct vme_master_resource, |
848 | list); | 844 | list); |
849 | if (master_image == NULL) { | 845 | if (!master_image) { |
850 | printk(KERN_ERR "Can't find master resource\n"); | 846 | printk(KERN_ERR "Can't find master resource\n"); |
851 | return; | 847 | return; |
852 | } | 848 | } |
@@ -886,7 +882,7 @@ struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) | |||
886 | printk(KERN_ERR "No VME resource Attribute tests done\n"); | 882 | printk(KERN_ERR "No VME resource Attribute tests done\n"); |
887 | 883 | ||
888 | bridge = vdev->bridge; | 884 | bridge = vdev->bridge; |
889 | if (bridge == NULL) { | 885 | if (!bridge) { |
890 | printk(KERN_ERR "Can't find VME bus\n"); | 886 | printk(KERN_ERR "Can't find VME bus\n"); |
891 | goto err_bus; | 887 | goto err_bus; |
892 | } | 888 | } |
@@ -895,8 +891,7 @@ struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) | |||
895 | list_for_each(dma_pos, &bridge->dma_resources) { | 891 | list_for_each(dma_pos, &bridge->dma_resources) { |
896 | dma_ctrlr = list_entry(dma_pos, | 892 | dma_ctrlr = list_entry(dma_pos, |
897 | struct vme_dma_resource, list); | 893 | struct vme_dma_resource, list); |
898 | 894 | if (!dma_ctrlr) { | |
899 | if (dma_ctrlr == NULL) { | ||
900 | printk(KERN_ERR "Registered NULL DMA resource\n"); | 895 | printk(KERN_ERR "Registered NULL DMA resource\n"); |
901 | continue; | 896 | continue; |
902 | } | 897 | } |
@@ -915,14 +910,13 @@ struct vme_resource *vme_dma_request(struct vme_dev *vdev, u32 route) | |||
915 | } | 910 | } |
916 | 911 | ||
917 | /* Check to see if we found a resource */ | 912 | /* Check to see if we found a resource */ |
918 | if (allocated_ctrlr == NULL) | 913 | if (!allocated_ctrlr) |
919 | goto err_ctrlr; | 914 | goto err_ctrlr; |
920 | 915 | ||
921 | resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); | 916 | resource = kmalloc(sizeof(*resource), GFP_KERNEL); |
922 | if (resource == NULL) { | 917 | if (!resource) |
923 | printk(KERN_WARNING "Unable to allocate resource structure\n"); | ||
924 | goto err_alloc; | 918 | goto err_alloc; |
925 | } | 919 | |
926 | resource->type = VME_DMA; | 920 | resource->type = VME_DMA; |
927 | resource->entry = &allocated_ctrlr->list; | 921 | resource->entry = &allocated_ctrlr->list; |
928 | 922 | ||
@@ -951,7 +945,6 @@ EXPORT_SYMBOL(vme_dma_request); | |||
951 | */ | 945 | */ |
952 | struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) | 946 | struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) |
953 | { | 947 | { |
954 | struct vme_dma_resource *ctrlr; | ||
955 | struct vme_dma_list *dma_list; | 948 | struct vme_dma_list *dma_list; |
956 | 949 | ||
957 | if (resource->type != VME_DMA) { | 950 | if (resource->type != VME_DMA) { |
@@ -959,15 +952,14 @@ struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource) | |||
959 | return NULL; | 952 | return NULL; |
960 | } | 953 | } |
961 | 954 | ||
962 | ctrlr = list_entry(resource->entry, struct vme_dma_resource, list); | 955 | dma_list = kmalloc(sizeof(*dma_list), GFP_KERNEL); |
963 | 956 | if (!dma_list) | |
964 | dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL); | ||
965 | if (dma_list == NULL) { | ||
966 | printk(KERN_ERR "Unable to allocate memory for new DMA list\n"); | ||
967 | return NULL; | 957 | return NULL; |
968 | } | 958 | |
969 | INIT_LIST_HEAD(&dma_list->entries); | 959 | INIT_LIST_HEAD(&dma_list->entries); |
970 | dma_list->parent = ctrlr; | 960 | dma_list->parent = list_entry(resource->entry, |
961 | struct vme_dma_resource, | ||
962 | list); | ||
971 | mutex_init(&dma_list->mtx); | 963 | mutex_init(&dma_list->mtx); |
972 | 964 | ||
973 | return dma_list; | 965 | return dma_list; |
@@ -990,17 +982,13 @@ struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type) | |||
990 | struct vme_dma_attr *attributes; | 982 | struct vme_dma_attr *attributes; |
991 | struct vme_dma_pattern *pattern_attr; | 983 | struct vme_dma_pattern *pattern_attr; |
992 | 984 | ||
993 | attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); | 985 | attributes = kmalloc(sizeof(*attributes), GFP_KERNEL); |
994 | if (attributes == NULL) { | 986 | if (!attributes) |
995 | printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); | ||
996 | goto err_attr; | 987 | goto err_attr; |
997 | } | ||
998 | 988 | ||
999 | pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL); | 989 | pattern_attr = kmalloc(sizeof(*pattern_attr), GFP_KERNEL); |
1000 | if (pattern_attr == NULL) { | 990 | if (!pattern_attr) |
1001 | printk(KERN_ERR "Unable to allocate memory for pattern attributes\n"); | ||
1002 | goto err_pat; | 991 | goto err_pat; |
1003 | } | ||
1004 | 992 | ||
1005 | attributes->type = VME_DMA_PATTERN; | 993 | attributes->type = VME_DMA_PATTERN; |
1006 | attributes->private = (void *)pattern_attr; | 994 | attributes->private = (void *)pattern_attr; |
@@ -1034,19 +1022,13 @@ struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address) | |||
1034 | 1022 | ||
1035 | /* XXX Run some sanity checks here */ | 1023 | /* XXX Run some sanity checks here */ |
1036 | 1024 | ||
1037 | attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL); | 1025 | attributes = kmalloc(sizeof(*attributes), GFP_KERNEL); |
1038 | if (attributes == NULL) { | 1026 | if (!attributes) |
1039 | printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); | ||
1040 | goto err_attr; | 1027 | goto err_attr; |
1041 | } | ||
1042 | 1028 | ||
1043 | pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL); | 1029 | pci_attr = kmalloc(sizeof(*pci_attr), GFP_KERNEL); |
1044 | if (pci_attr == NULL) { | 1030 | if (!pci_attr) |
1045 | printk(KERN_ERR "Unable to allocate memory for PCI attributes\n"); | ||
1046 | goto err_pci; | 1031 | goto err_pci; |
1047 | } | ||
1048 | |||
1049 | |||
1050 | 1032 | ||
1051 | attributes->type = VME_DMA_PCI; | 1033 | attributes->type = VME_DMA_PCI; |
1052 | attributes->private = (void *)pci_attr; | 1034 | attributes->private = (void *)pci_attr; |
@@ -1081,18 +1063,13 @@ struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address, | |||
1081 | struct vme_dma_attr *attributes; | 1063 | struct vme_dma_attr *attributes; |
1082 | struct vme_dma_vme *vme_attr; | 1064 | struct vme_dma_vme *vme_attr; |
1083 | 1065 | ||
1084 | attributes = kmalloc( | 1066 | attributes = kmalloc(sizeof(*attributes), GFP_KERNEL); |
1085 | sizeof(struct vme_dma_attr), GFP_KERNEL); | 1067 | if (!attributes) |
1086 | if (attributes == NULL) { | ||
1087 | printk(KERN_ERR "Unable to allocate memory for attributes structure\n"); | ||
1088 | goto err_attr; | 1068 | goto err_attr; |
1089 | } | ||
1090 | 1069 | ||
1091 | vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL); | 1070 | vme_attr = kmalloc(sizeof(*vme_attr), GFP_KERNEL); |
1092 | if (vme_attr == NULL) { | 1071 | if (!vme_attr) |
1093 | printk(KERN_ERR "Unable to allocate memory for VME attributes\n"); | ||
1094 | goto err_vme; | 1072 | goto err_vme; |
1095 | } | ||
1096 | 1073 | ||
1097 | attributes->type = VME_DMA_VME; | 1074 | attributes->type = VME_DMA_VME; |
1098 | attributes->private = (void *)vme_attr; | 1075 | attributes->private = (void *)vme_attr; |
@@ -1148,7 +1125,7 @@ int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, | |||
1148 | struct vme_bridge *bridge = list->parent->parent; | 1125 | struct vme_bridge *bridge = list->parent->parent; |
1149 | int retval; | 1126 | int retval; |
1150 | 1127 | ||
1151 | if (bridge->dma_list_add == NULL) { | 1128 | if (!bridge->dma_list_add) { |
1152 | printk(KERN_WARNING "Link List DMA generation not supported\n"); | 1129 | printk(KERN_WARNING "Link List DMA generation not supported\n"); |
1153 | return -EINVAL; | 1130 | return -EINVAL; |
1154 | } | 1131 | } |
@@ -1181,7 +1158,7 @@ int vme_dma_list_exec(struct vme_dma_list *list) | |||
1181 | struct vme_bridge *bridge = list->parent->parent; | 1158 | struct vme_bridge *bridge = list->parent->parent; |
1182 | int retval; | 1159 | int retval; |
1183 | 1160 | ||
1184 | if (bridge->dma_list_exec == NULL) { | 1161 | if (!bridge->dma_list_exec) { |
1185 | printk(KERN_ERR "Link List DMA execution not supported\n"); | 1162 | printk(KERN_ERR "Link List DMA execution not supported\n"); |
1186 | return -EINVAL; | 1163 | return -EINVAL; |
1187 | } | 1164 | } |
@@ -1210,14 +1187,14 @@ int vme_dma_list_free(struct vme_dma_list *list) | |||
1210 | struct vme_bridge *bridge = list->parent->parent; | 1187 | struct vme_bridge *bridge = list->parent->parent; |
1211 | int retval; | 1188 | int retval; |
1212 | 1189 | ||
1213 | if (bridge->dma_list_empty == NULL) { | 1190 | if (!bridge->dma_list_empty) { |
1214 | printk(KERN_WARNING "Emptying of Link Lists not supported\n"); | 1191 | printk(KERN_WARNING "Emptying of Link Lists not supported\n"); |
1215 | return -EINVAL; | 1192 | return -EINVAL; |
1216 | } | 1193 | } |
1217 | 1194 | ||
1218 | if (!mutex_trylock(&list->mtx)) { | 1195 | if (!mutex_trylock(&list->mtx)) { |
1219 | printk(KERN_ERR "Link List in use\n"); | 1196 | printk(KERN_ERR "Link List in use\n"); |
1220 | return -EINVAL; | 1197 | return -EBUSY; |
1221 | } | 1198 | } |
1222 | 1199 | ||
1223 | /* | 1200 | /* |
@@ -1342,8 +1319,7 @@ void vme_irq_handler(struct vme_bridge *bridge, int level, int statid) | |||
1342 | 1319 | ||
1343 | call = bridge->irq[level - 1].callback[statid].func; | 1320 | call = bridge->irq[level - 1].callback[statid].func; |
1344 | priv_data = bridge->irq[level - 1].callback[statid].priv_data; | 1321 | priv_data = bridge->irq[level - 1].callback[statid].priv_data; |
1345 | 1322 | if (call) | |
1346 | if (call != NULL) | ||
1347 | call(level, statid, priv_data); | 1323 | call(level, statid, priv_data); |
1348 | else | 1324 | else |
1349 | printk(KERN_WARNING "Spurious VME interrupt, level:%x, vector:%x\n", | 1325 | printk(KERN_WARNING "Spurious VME interrupt, level:%x, vector:%x\n", |
@@ -1374,7 +1350,7 @@ int vme_irq_request(struct vme_dev *vdev, int level, int statid, | |||
1374 | struct vme_bridge *bridge; | 1350 | struct vme_bridge *bridge; |
1375 | 1351 | ||
1376 | bridge = vdev->bridge; | 1352 | bridge = vdev->bridge; |
1377 | if (bridge == NULL) { | 1353 | if (!bridge) { |
1378 | printk(KERN_ERR "Can't find VME bus\n"); | 1354 | printk(KERN_ERR "Can't find VME bus\n"); |
1379 | return -EINVAL; | 1355 | return -EINVAL; |
1380 | } | 1356 | } |
@@ -1384,7 +1360,7 @@ int vme_irq_request(struct vme_dev *vdev, int level, int statid, | |||
1384 | return -EINVAL; | 1360 | return -EINVAL; |
1385 | } | 1361 | } |
1386 | 1362 | ||
1387 | if (bridge->irq_set == NULL) { | 1363 | if (!bridge->irq_set) { |
1388 | printk(KERN_ERR "Configuring interrupts not supported\n"); | 1364 | printk(KERN_ERR "Configuring interrupts not supported\n"); |
1389 | return -EINVAL; | 1365 | return -EINVAL; |
1390 | } | 1366 | } |
@@ -1423,7 +1399,7 @@ void vme_irq_free(struct vme_dev *vdev, int level, int statid) | |||
1423 | struct vme_bridge *bridge; | 1399 | struct vme_bridge *bridge; |
1424 | 1400 | ||
1425 | bridge = vdev->bridge; | 1401 | bridge = vdev->bridge; |
1426 | if (bridge == NULL) { | 1402 | if (!bridge) { |
1427 | printk(KERN_ERR "Can't find VME bus\n"); | 1403 | printk(KERN_ERR "Can't find VME bus\n"); |
1428 | return; | 1404 | return; |
1429 | } | 1405 | } |
@@ -1433,7 +1409,7 @@ void vme_irq_free(struct vme_dev *vdev, int level, int statid) | |||
1433 | return; | 1409 | return; |
1434 | } | 1410 | } |
1435 | 1411 | ||
1436 | if (bridge->irq_set == NULL) { | 1412 | if (!bridge->irq_set) { |
1437 | printk(KERN_ERR "Configuring interrupts not supported\n"); | 1413 | printk(KERN_ERR "Configuring interrupts not supported\n"); |
1438 | return; | 1414 | return; |
1439 | } | 1415 | } |
@@ -1470,7 +1446,7 @@ int vme_irq_generate(struct vme_dev *vdev, int level, int statid) | |||
1470 | struct vme_bridge *bridge; | 1446 | struct vme_bridge *bridge; |
1471 | 1447 | ||
1472 | bridge = vdev->bridge; | 1448 | bridge = vdev->bridge; |
1473 | if (bridge == NULL) { | 1449 | if (!bridge) { |
1474 | printk(KERN_ERR "Can't find VME bus\n"); | 1450 | printk(KERN_ERR "Can't find VME bus\n"); |
1475 | return -EINVAL; | 1451 | return -EINVAL; |
1476 | } | 1452 | } |
@@ -1480,7 +1456,7 @@ int vme_irq_generate(struct vme_dev *vdev, int level, int statid) | |||
1480 | return -EINVAL; | 1456 | return -EINVAL; |
1481 | } | 1457 | } |
1482 | 1458 | ||
1483 | if (bridge->irq_generate == NULL) { | 1459 | if (!bridge->irq_generate) { |
1484 | printk(KERN_WARNING "Interrupt generation not supported\n"); | 1460 | printk(KERN_WARNING "Interrupt generation not supported\n"); |
1485 | return -EINVAL; | 1461 | return -EINVAL; |
1486 | } | 1462 | } |
@@ -1508,7 +1484,7 @@ struct vme_resource *vme_lm_request(struct vme_dev *vdev) | |||
1508 | struct vme_resource *resource = NULL; | 1484 | struct vme_resource *resource = NULL; |
1509 | 1485 | ||
1510 | bridge = vdev->bridge; | 1486 | bridge = vdev->bridge; |
1511 | if (bridge == NULL) { | 1487 | if (!bridge) { |
1512 | printk(KERN_ERR "Can't find VME bus\n"); | 1488 | printk(KERN_ERR "Can't find VME bus\n"); |
1513 | goto err_bus; | 1489 | goto err_bus; |
1514 | } | 1490 | } |
@@ -1517,8 +1493,7 @@ struct vme_resource *vme_lm_request(struct vme_dev *vdev) | |||
1517 | list_for_each(lm_pos, &bridge->lm_resources) { | 1493 | list_for_each(lm_pos, &bridge->lm_resources) { |
1518 | lm = list_entry(lm_pos, | 1494 | lm = list_entry(lm_pos, |
1519 | struct vme_lm_resource, list); | 1495 | struct vme_lm_resource, list); |
1520 | 1496 | if (!lm) { | |
1521 | if (lm == NULL) { | ||
1522 | printk(KERN_ERR "Registered NULL Location Monitor resource\n"); | 1497 | printk(KERN_ERR "Registered NULL Location Monitor resource\n"); |
1523 | continue; | 1498 | continue; |
1524 | } | 1499 | } |
@@ -1535,14 +1510,13 @@ struct vme_resource *vme_lm_request(struct vme_dev *vdev) | |||
1535 | } | 1510 | } |
1536 | 1511 | ||
1537 | /* Check to see if we found a resource */ | 1512 | /* Check to see if we found a resource */ |
1538 | if (allocated_lm == NULL) | 1513 | if (!allocated_lm) |
1539 | goto err_lm; | 1514 | goto err_lm; |
1540 | 1515 | ||
1541 | resource = kmalloc(sizeof(struct vme_resource), GFP_KERNEL); | 1516 | resource = kmalloc(sizeof(*resource), GFP_KERNEL); |
1542 | if (resource == NULL) { | 1517 | if (!resource) |
1543 | printk(KERN_ERR "Unable to allocate resource structure\n"); | ||
1544 | goto err_alloc; | 1518 | goto err_alloc; |
1545 | } | 1519 | |
1546 | resource->type = VME_LM; | 1520 | resource->type = VME_LM; |
1547 | resource->entry = &allocated_lm->list; | 1521 | resource->entry = &allocated_lm->list; |
1548 | 1522 | ||
@@ -1612,7 +1586,7 @@ int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base, | |||
1612 | 1586 | ||
1613 | lm = list_entry(resource->entry, struct vme_lm_resource, list); | 1587 | lm = list_entry(resource->entry, struct vme_lm_resource, list); |
1614 | 1588 | ||
1615 | if (bridge->lm_set == NULL) { | 1589 | if (!bridge->lm_set) { |
1616 | printk(KERN_ERR "vme_lm_set not supported\n"); | 1590 | printk(KERN_ERR "vme_lm_set not supported\n"); |
1617 | return -EINVAL; | 1591 | return -EINVAL; |
1618 | } | 1592 | } |
@@ -1648,7 +1622,7 @@ int vme_lm_get(struct vme_resource *resource, unsigned long long *lm_base, | |||
1648 | 1622 | ||
1649 | lm = list_entry(resource->entry, struct vme_lm_resource, list); | 1623 | lm = list_entry(resource->entry, struct vme_lm_resource, list); |
1650 | 1624 | ||
1651 | if (bridge->lm_get == NULL) { | 1625 | if (!bridge->lm_get) { |
1652 | printk(KERN_ERR "vme_lm_get not supported\n"); | 1626 | printk(KERN_ERR "vme_lm_get not supported\n"); |
1653 | return -EINVAL; | 1627 | return -EINVAL; |
1654 | } | 1628 | } |
@@ -1685,7 +1659,7 @@ int vme_lm_attach(struct vme_resource *resource, int monitor, | |||
1685 | 1659 | ||
1686 | lm = list_entry(resource->entry, struct vme_lm_resource, list); | 1660 | lm = list_entry(resource->entry, struct vme_lm_resource, list); |
1687 | 1661 | ||
1688 | if (bridge->lm_attach == NULL) { | 1662 | if (!bridge->lm_attach) { |
1689 | printk(KERN_ERR "vme_lm_attach not supported\n"); | 1663 | printk(KERN_ERR "vme_lm_attach not supported\n"); |
1690 | return -EINVAL; | 1664 | return -EINVAL; |
1691 | } | 1665 | } |
@@ -1718,7 +1692,7 @@ int vme_lm_detach(struct vme_resource *resource, int monitor) | |||
1718 | 1692 | ||
1719 | lm = list_entry(resource->entry, struct vme_lm_resource, list); | 1693 | lm = list_entry(resource->entry, struct vme_lm_resource, list); |
1720 | 1694 | ||
1721 | if (bridge->lm_detach == NULL) { | 1695 | if (!bridge->lm_detach) { |
1722 | printk(KERN_ERR "vme_lm_detach not supported\n"); | 1696 | printk(KERN_ERR "vme_lm_detach not supported\n"); |
1723 | return -EINVAL; | 1697 | return -EINVAL; |
1724 | } | 1698 | } |
@@ -1780,12 +1754,12 @@ int vme_slot_num(struct vme_dev *vdev) | |||
1780 | struct vme_bridge *bridge; | 1754 | struct vme_bridge *bridge; |
1781 | 1755 | ||
1782 | bridge = vdev->bridge; | 1756 | bridge = vdev->bridge; |
1783 | if (bridge == NULL) { | 1757 | if (!bridge) { |
1784 | printk(KERN_ERR "Can't find VME bus\n"); | 1758 | printk(KERN_ERR "Can't find VME bus\n"); |
1785 | return -EINVAL; | 1759 | return -EINVAL; |
1786 | } | 1760 | } |
1787 | 1761 | ||
1788 | if (bridge->slot_get == NULL) { | 1762 | if (!bridge->slot_get) { |
1789 | printk(KERN_WARNING "vme_slot_num not supported\n"); | 1763 | printk(KERN_WARNING "vme_slot_num not supported\n"); |
1790 | return -EINVAL; | 1764 | return -EINVAL; |
1791 | } | 1765 | } |
@@ -1808,7 +1782,7 @@ int vme_bus_num(struct vme_dev *vdev) | |||
1808 | struct vme_bridge *bridge; | 1782 | struct vme_bridge *bridge; |
1809 | 1783 | ||
1810 | bridge = vdev->bridge; | 1784 | bridge = vdev->bridge; |
1811 | if (bridge == NULL) { | 1785 | if (!bridge) { |
1812 | pr_err("Can't find VME bus\n"); | 1786 | pr_err("Can't find VME bus\n"); |
1813 | return -EINVAL; | 1787 | return -EINVAL; |
1814 | } | 1788 | } |
@@ -1888,7 +1862,7 @@ static int __vme_register_driver_bus(struct vme_driver *drv, | |||
1888 | struct vme_dev *tmp; | 1862 | struct vme_dev *tmp; |
1889 | 1863 | ||
1890 | for (i = 0; i < ndevs; i++) { | 1864 | for (i = 0; i < ndevs; i++) { |
1891 | vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL); | 1865 | vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); |
1892 | if (!vdev) { | 1866 | if (!vdev) { |
1893 | err = -ENOMEM; | 1867 | err = -ENOMEM; |
1894 | goto err_devalloc; | 1868 | goto err_devalloc; |
@@ -2020,30 +1994,26 @@ static int vme_bus_match(struct device *dev, struct device_driver *drv) | |||
2020 | 1994 | ||
2021 | static int vme_bus_probe(struct device *dev) | 1995 | static int vme_bus_probe(struct device *dev) |
2022 | { | 1996 | { |
2023 | int retval = -ENODEV; | ||
2024 | struct vme_driver *driver; | 1997 | struct vme_driver *driver; |
2025 | struct vme_dev *vdev = dev_to_vme_dev(dev); | 1998 | struct vme_dev *vdev = dev_to_vme_dev(dev); |
2026 | 1999 | ||
2027 | driver = dev->platform_data; | 2000 | driver = dev->platform_data; |
2001 | if (driver->probe) | ||
2002 | return driver->probe(vdev); | ||
2028 | 2003 | ||
2029 | if (driver->probe != NULL) | 2004 | return -ENODEV; |
2030 | retval = driver->probe(vdev); | ||
2031 | |||
2032 | return retval; | ||
2033 | } | 2005 | } |
2034 | 2006 | ||
2035 | static int vme_bus_remove(struct device *dev) | 2007 | static int vme_bus_remove(struct device *dev) |
2036 | { | 2008 | { |
2037 | int retval = -ENODEV; | ||
2038 | struct vme_driver *driver; | 2009 | struct vme_driver *driver; |
2039 | struct vme_dev *vdev = dev_to_vme_dev(dev); | 2010 | struct vme_dev *vdev = dev_to_vme_dev(dev); |
2040 | 2011 | ||
2041 | driver = dev->platform_data; | 2012 | driver = dev->platform_data; |
2013 | if (driver->remove) | ||
2014 | return driver->remove(vdev); | ||
2042 | 2015 | ||
2043 | if (driver->remove != NULL) | 2016 | return -ENODEV; |
2044 | retval = driver->remove(vdev); | ||
2045 | |||
2046 | return retval; | ||
2047 | } | 2017 | } |
2048 | 2018 | ||
2049 | struct bus_type vme_bus_type = { | 2019 | struct bus_type vme_bus_type = { |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 3c945f9f5f0f..7931231d8e80 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
@@ -148,4 +148,19 @@ config W1_SLAVE_DS28E04 | |||
148 | 148 | ||
149 | If you are unsure, say N. | 149 | If you are unsure, say N. |
150 | 150 | ||
151 | config W1_SLAVE_DS28E17 | ||
152 | tristate "1-wire-to-I2C master bridge (DS28E17)" | ||
153 | select CRC16 | ||
154 | depends on I2C | ||
155 | help | ||
156 | Say Y here if you want to use the DS28E17 1-wire-to-I2C master bridge. | ||
157 | For each DS28E17 detected, a new I2C adapter is created within the | ||
158 | kernel. I2C devices on that bus can be configured to be used by the | ||
159 | kernel and userspace tools as on any other "native" I2C bus. | ||
160 | |||
161 | This driver is also available as a module. If so, the module | ||
162 | will be called w1_ds28e17. | ||
163 | |||
164 | If you are unsure, say N. | ||
165 | |||
151 | endmenu | 166 | endmenu |
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index 79c611ce5f18..d5f4f4d5b9e5 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile | |||
@@ -18,3 +18,4 @@ obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o | |||
18 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o | 18 | obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o |
19 | obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o | 19 | obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o |
20 | obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o | 20 | obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o |
21 | obj-$(CONFIG_W1_SLAVE_DS28E17) += w1_ds28e17.o | ||
diff --git a/drivers/w1/slaves/w1_ds28e17.c b/drivers/w1/slaves/w1_ds28e17.c new file mode 100644 index 000000000000..e78b63ea4daf --- /dev/null +++ b/drivers/w1/slaves/w1_ds28e17.c | |||
@@ -0,0 +1,771 @@ | |||
1 | /* | ||
2 | * w1_ds28e17.c - w1 family 19 (DS28E17) driver | ||
3 | * | ||
4 | * Copyright (c) 2016 Jan Kandziora <jjj@gmx.de> | ||
5 | * | ||
6 | * This source code is licensed under the GNU General Public License, | ||
7 | * Version 2. See the file COPYING for more details. | ||
8 | */ | ||
9 | |||
10 | #include <linux/crc16.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/uaccess.h> | ||
20 | |||
21 | #define CRC16_INIT 0 | ||
22 | |||
23 | #include <linux/w1.h> | ||
24 | |||
25 | #define W1_FAMILY_DS28E17 0x19 | ||
26 | |||
27 | /* Module setup. */ | ||
28 | MODULE_LICENSE("GPL v2"); | ||
29 | MODULE_AUTHOR("Jan Kandziora <jjj@gmx.de>"); | ||
30 | MODULE_DESCRIPTION("w1 family 19 driver for DS28E17, 1-wire to I2C master bridge"); | ||
31 | MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E17)); | ||
32 | |||
33 | |||
34 | /* Default I2C speed to be set when a DS28E17 is detected. */ | ||
35 | static int i2c_speed = 100; | ||
36 | module_param_named(speed, i2c_speed, int, (S_IRUSR | S_IWUSR)); | ||
37 | MODULE_PARM_DESC(speed, "Default I2C speed to be set when a DS28E17 is detected"); | ||
38 | |||
39 | /* Default I2C stretch value to be set when a DS28E17 is detected. */ | ||
40 | static char i2c_stretch = 1; | ||
41 | module_param_named(stretch, i2c_stretch, byte, (S_IRUSR | S_IWUSR)); | ||
42 | MODULE_PARM_DESC(stretch, "Default I2C stretch value to be set when a DS28E17 is detected"); | ||
43 | |||
44 | /* DS28E17 device command codes. */ | ||
45 | #define W1_F19_WRITE_DATA_WITH_STOP 0x4B | ||
46 | #define W1_F19_WRITE_DATA_NO_STOP 0x5A | ||
47 | #define W1_F19_WRITE_DATA_ONLY 0x69 | ||
48 | #define W1_F19_WRITE_DATA_ONLY_WITH_STOP 0x78 | ||
49 | #define W1_F19_READ_DATA_WITH_STOP 0x87 | ||
50 | #define W1_F19_WRITE_READ_DATA_WITH_STOP 0x2D | ||
51 | #define W1_F19_WRITE_CONFIGURATION 0xD2 | ||
52 | #define W1_F19_READ_CONFIGURATION 0xE1 | ||
53 | #define W1_F19_ENABLE_SLEEP_MODE 0x1E | ||
54 | #define W1_F19_READ_DEVICE_REVISION 0xC4 | ||
55 | |||
56 | /* DS28E17 status bits */ | ||
57 | #define W1_F19_STATUS_CRC 0x01 | ||
58 | #define W1_F19_STATUS_ADDRESS 0x02 | ||
59 | #define W1_F19_STATUS_START 0x08 | ||
60 | |||
61 | /* | ||
62 | * Maximum number of I2C bytes to transfer within one CRC16 protected onewire | ||
63 | * command. | ||
64 | * */ | ||
65 | #define W1_F19_WRITE_DATA_LIMIT 255 | ||
66 | |||
67 | /* Maximum number of I2C bytes to read with one onewire command. */ | ||
68 | #define W1_F19_READ_DATA_LIMIT 255 | ||
69 | |||
70 | /* Constants for calculating the busy sleep. */ | ||
71 | #define W1_F19_BUSY_TIMEBASES { 90, 23, 10 } | ||
72 | #define W1_F19_BUSY_GRATUITY 1000 | ||
73 | |||
74 | /* Number of checks for the busy flag before timeout. */ | ||
75 | #define W1_F19_BUSY_CHECKS 1000 | ||
76 | |||
77 | |||
78 | /* Slave specific data. */ | ||
79 | struct w1_f19_data { | ||
80 | u8 speed; | ||
81 | u8 stretch; | ||
82 | struct i2c_adapter adapter; | ||
83 | }; | ||
84 | |||
85 | |||
86 | /* Wait a while until the busy flag clears. */ | ||
87 | static int w1_f19_i2c_busy_wait(struct w1_slave *sl, size_t count) | ||
88 | { | ||
89 | const unsigned long timebases[3] = W1_F19_BUSY_TIMEBASES; | ||
90 | struct w1_f19_data *data = sl->family_data; | ||
91 | unsigned int checks; | ||
92 | |||
93 | /* Check the busy flag first in any case.*/ | ||
94 | if (w1_touch_bit(sl->master, 1) == 0) | ||
95 | return 0; | ||
96 | |||
97 | /* | ||
98 | * Do a generously long sleep in the beginning, | ||
99 | * as we have to wait at least this time for all | ||
100 | * the I2C bytes at the given speed to be transferred. | ||
101 | */ | ||
102 | usleep_range(timebases[data->speed] * (data->stretch) * count, | ||
103 | timebases[data->speed] * (data->stretch) * count | ||
104 | + W1_F19_BUSY_GRATUITY); | ||
105 | |||
106 | /* Now continusly check the busy flag sent by the DS28E17. */ | ||
107 | checks = W1_F19_BUSY_CHECKS; | ||
108 | while ((checks--) > 0) { | ||
109 | /* Return success if the busy flag is cleared. */ | ||
110 | if (w1_touch_bit(sl->master, 1) == 0) | ||
111 | return 0; | ||
112 | |||
113 | /* Wait one non-streched byte timeslot. */ | ||
114 | udelay(timebases[data->speed]); | ||
115 | } | ||
116 | |||
117 | /* Timeout. */ | ||
118 | dev_warn(&sl->dev, "busy timeout\n"); | ||
119 | return -ETIMEDOUT; | ||
120 | } | ||
121 | |||
122 | |||
123 | /* Utility function: result. */ | ||
124 | static size_t w1_f19_error(struct w1_slave *sl, u8 w1_buf[]) | ||
125 | { | ||
126 | /* Warnings. */ | ||
127 | if (w1_buf[0] & W1_F19_STATUS_CRC) | ||
128 | dev_warn(&sl->dev, "crc16 mismatch\n"); | ||
129 | if (w1_buf[0] & W1_F19_STATUS_ADDRESS) | ||
130 | dev_warn(&sl->dev, "i2c device not responding\n"); | ||
131 | if ((w1_buf[0] & (W1_F19_STATUS_CRC | W1_F19_STATUS_ADDRESS)) == 0 | ||
132 | && w1_buf[1] != 0) { | ||
133 | dev_warn(&sl->dev, "i2c short write, %d bytes not acknowledged\n", | ||
134 | w1_buf[1]); | ||
135 | } | ||
136 | |||
137 | /* Check error conditions. */ | ||
138 | if (w1_buf[0] & W1_F19_STATUS_ADDRESS) | ||
139 | return -ENXIO; | ||
140 | if (w1_buf[0] & W1_F19_STATUS_START) | ||
141 | return -EAGAIN; | ||
142 | if (w1_buf[0] != 0 || w1_buf[1] != 0) | ||
143 | return -EIO; | ||
144 | |||
145 | /* All ok. */ | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | |||
150 | /* Utility function: write data to I2C slave, single chunk. */ | ||
151 | static int __w1_f19_i2c_write(struct w1_slave *sl, | ||
152 | const u8 *command, size_t command_count, | ||
153 | const u8 *buffer, size_t count) | ||
154 | { | ||
155 | u16 crc; | ||
156 | int error; | ||
157 | u8 w1_buf[2]; | ||
158 | |||
159 | /* Send command and I2C data to DS28E17. */ | ||
160 | crc = crc16(CRC16_INIT, command, command_count); | ||
161 | w1_write_block(sl->master, command, command_count); | ||
162 | |||
163 | w1_buf[0] = count; | ||
164 | crc = crc16(crc, w1_buf, 1); | ||
165 | w1_write_8(sl->master, w1_buf[0]); | ||
166 | |||
167 | crc = crc16(crc, buffer, count); | ||
168 | w1_write_block(sl->master, buffer, count); | ||
169 | |||
170 | w1_buf[0] = ~(crc & 0xFF); | ||
171 | w1_buf[1] = ~((crc >> 8) & 0xFF); | ||
172 | w1_write_block(sl->master, w1_buf, 2); | ||
173 | |||
174 | /* Wait until busy flag clears (or timeout). */ | ||
175 | if (w1_f19_i2c_busy_wait(sl, count + 1) < 0) | ||
176 | return -ETIMEDOUT; | ||
177 | |||
178 | /* Read status from DS28E17. */ | ||
179 | w1_read_block(sl->master, w1_buf, 2); | ||
180 | |||
181 | /* Check error conditions. */ | ||
182 | error = w1_f19_error(sl, w1_buf); | ||
183 | if (error < 0) | ||
184 | return error; | ||
185 | |||
186 | /* Return number of bytes written. */ | ||
187 | return count; | ||
188 | } | ||
189 | |||
190 | |||
191 | /* Write data to I2C slave. */ | ||
192 | static int w1_f19_i2c_write(struct w1_slave *sl, u16 i2c_address, | ||
193 | const u8 *buffer, size_t count, bool stop) | ||
194 | { | ||
195 | int result; | ||
196 | int remaining = count; | ||
197 | const u8 *p; | ||
198 | u8 command[2]; | ||
199 | |||
200 | /* Check input. */ | ||
201 | if (count == 0) | ||
202 | return -EOPNOTSUPP; | ||
203 | |||
204 | /* Check whether we need multiple commands. */ | ||
205 | if (count <= W1_F19_WRITE_DATA_LIMIT) { | ||
206 | /* | ||
207 | * Small data amount. Data can be sent with | ||
208 | * a single onewire command. | ||
209 | */ | ||
210 | |||
211 | /* Send all data to DS28E17. */ | ||
212 | command[0] = (stop ? W1_F19_WRITE_DATA_WITH_STOP | ||
213 | : W1_F19_WRITE_DATA_NO_STOP); | ||
214 | command[1] = i2c_address << 1; | ||
215 | result = __w1_f19_i2c_write(sl, command, 2, buffer, count); | ||
216 | } else { | ||
217 | /* Large data amount. Data has to be sent in multiple chunks. */ | ||
218 | |||
219 | /* Send first chunk to DS28E17. */ | ||
220 | p = buffer; | ||
221 | command[0] = W1_F19_WRITE_DATA_NO_STOP; | ||
222 | command[1] = i2c_address << 1; | ||
223 | result = __w1_f19_i2c_write(sl, command, 2, p, | ||
224 | W1_F19_WRITE_DATA_LIMIT); | ||
225 | if (result < 0) | ||
226 | return result; | ||
227 | |||
228 | /* Resume to same DS28E17. */ | ||
229 | if (w1_reset_resume_command(sl->master)) | ||
230 | return -EIO; | ||
231 | |||
232 | /* Next data chunk. */ | ||
233 | p += W1_F19_WRITE_DATA_LIMIT; | ||
234 | remaining -= W1_F19_WRITE_DATA_LIMIT; | ||
235 | |||
236 | while (remaining > W1_F19_WRITE_DATA_LIMIT) { | ||
237 | /* Send intermediate chunk to DS28E17. */ | ||
238 | command[0] = W1_F19_WRITE_DATA_ONLY; | ||
239 | result = __w1_f19_i2c_write(sl, command, 1, p, | ||
240 | W1_F19_WRITE_DATA_LIMIT); | ||
241 | if (result < 0) | ||
242 | return result; | ||
243 | |||
244 | /* Resume to same DS28E17. */ | ||
245 | if (w1_reset_resume_command(sl->master)) | ||
246 | return -EIO; | ||
247 | |||
248 | /* Next data chunk. */ | ||
249 | p += W1_F19_WRITE_DATA_LIMIT; | ||
250 | remaining -= W1_F19_WRITE_DATA_LIMIT; | ||
251 | } | ||
252 | |||
253 | /* Send final chunk to DS28E17. */ | ||
254 | command[0] = (stop ? W1_F19_WRITE_DATA_ONLY_WITH_STOP | ||
255 | : W1_F19_WRITE_DATA_ONLY); | ||
256 | result = __w1_f19_i2c_write(sl, command, 1, p, remaining); | ||
257 | } | ||
258 | |||
259 | return result; | ||
260 | } | ||
261 | |||
262 | |||
263 | /* Read data from I2C slave. */ | ||
264 | static int w1_f19_i2c_read(struct w1_slave *sl, u16 i2c_address, | ||
265 | u8 *buffer, size_t count) | ||
266 | { | ||
267 | u16 crc; | ||
268 | int error; | ||
269 | u8 w1_buf[5]; | ||
270 | |||
271 | /* Check input. */ | ||
272 | if (count == 0) | ||
273 | return -EOPNOTSUPP; | ||
274 | |||
275 | /* Send command to DS28E17. */ | ||
276 | w1_buf[0] = W1_F19_READ_DATA_WITH_STOP; | ||
277 | w1_buf[1] = i2c_address << 1 | 0x01; | ||
278 | w1_buf[2] = count; | ||
279 | crc = crc16(CRC16_INIT, w1_buf, 3); | ||
280 | w1_buf[3] = ~(crc & 0xFF); | ||
281 | w1_buf[4] = ~((crc >> 8) & 0xFF); | ||
282 | w1_write_block(sl->master, w1_buf, 5); | ||
283 | |||
284 | /* Wait until busy flag clears (or timeout). */ | ||
285 | if (w1_f19_i2c_busy_wait(sl, count + 1) < 0) | ||
286 | return -ETIMEDOUT; | ||
287 | |||
288 | /* Read status from DS28E17. */ | ||
289 | w1_buf[0] = w1_read_8(sl->master); | ||
290 | w1_buf[1] = 0; | ||
291 | |||
292 | /* Check error conditions. */ | ||
293 | error = w1_f19_error(sl, w1_buf); | ||
294 | if (error < 0) | ||
295 | return error; | ||
296 | |||
297 | /* Read received I2C data from DS28E17. */ | ||
298 | return w1_read_block(sl->master, buffer, count); | ||
299 | } | ||
300 | |||
301 | |||
302 | /* Write to, then read data from I2C slave. */ | ||
303 | static int w1_f19_i2c_write_read(struct w1_slave *sl, u16 i2c_address, | ||
304 | const u8 *wbuffer, size_t wcount, u8 *rbuffer, size_t rcount) | ||
305 | { | ||
306 | u16 crc; | ||
307 | int error; | ||
308 | u8 w1_buf[3]; | ||
309 | |||
310 | /* Check input. */ | ||
311 | if (wcount == 0 || rcount == 0) | ||
312 | return -EOPNOTSUPP; | ||
313 | |||
314 | /* Send command and I2C data to DS28E17. */ | ||
315 | w1_buf[0] = W1_F19_WRITE_READ_DATA_WITH_STOP; | ||
316 | w1_buf[1] = i2c_address << 1; | ||
317 | w1_buf[2] = wcount; | ||
318 | crc = crc16(CRC16_INIT, w1_buf, 3); | ||
319 | w1_write_block(sl->master, w1_buf, 3); | ||
320 | |||
321 | crc = crc16(crc, wbuffer, wcount); | ||
322 | w1_write_block(sl->master, wbuffer, wcount); | ||
323 | |||
324 | w1_buf[0] = rcount; | ||
325 | crc = crc16(crc, w1_buf, 1); | ||
326 | w1_buf[1] = ~(crc & 0xFF); | ||
327 | w1_buf[2] = ~((crc >> 8) & 0xFF); | ||
328 | w1_write_block(sl->master, w1_buf, 3); | ||
329 | |||
330 | /* Wait until busy flag clears (or timeout). */ | ||
331 | if (w1_f19_i2c_busy_wait(sl, wcount + rcount + 2) < 0) | ||
332 | return -ETIMEDOUT; | ||
333 | |||
334 | /* Read status from DS28E17. */ | ||
335 | w1_read_block(sl->master, w1_buf, 2); | ||
336 | |||
337 | /* Check error conditions. */ | ||
338 | error = w1_f19_error(sl, w1_buf); | ||
339 | if (error < 0) | ||
340 | return error; | ||
341 | |||
342 | /* Read received I2C data from DS28E17. */ | ||
343 | return w1_read_block(sl->master, rbuffer, rcount); | ||
344 | } | ||
345 | |||
346 | |||
347 | /* Do an I2C master transfer. */ | ||
348 | static int w1_f19_i2c_master_transfer(struct i2c_adapter *adapter, | ||
349 | struct i2c_msg *msgs, int num) | ||
350 | { | ||
351 | struct w1_slave *sl = (struct w1_slave *) adapter->algo_data; | ||
352 | int i = 0; | ||
353 | int result = 0; | ||
354 | |||
355 | /* Start onewire transaction. */ | ||
356 | mutex_lock(&sl->master->bus_mutex); | ||
357 | |||
358 | /* Select DS28E17. */ | ||
359 | if (w1_reset_select_slave(sl)) { | ||
360 | i = -EIO; | ||
361 | goto error; | ||
362 | } | ||
363 | |||
364 | /* Loop while there are still messages to transfer. */ | ||
365 | while (i < num) { | ||
366 | /* | ||
367 | * Check for special case: Small write followed | ||
368 | * by read to same I2C device. | ||
369 | */ | ||
370 | if (i < (num-1) | ||
371 | && msgs[i].addr == msgs[i+1].addr | ||
372 | && !(msgs[i].flags & I2C_M_RD) | ||
373 | && (msgs[i+1].flags & I2C_M_RD) | ||
374 | && (msgs[i].len <= W1_F19_WRITE_DATA_LIMIT)) { | ||
375 | /* | ||
376 | * The DS28E17 has a combined transfer | ||
377 | * for small write+read. | ||
378 | */ | ||
379 | result = w1_f19_i2c_write_read(sl, msgs[i].addr, | ||
380 | msgs[i].buf, msgs[i].len, | ||
381 | msgs[i+1].buf, msgs[i+1].len); | ||
382 | if (result < 0) { | ||
383 | i = result; | ||
384 | goto error; | ||
385 | } | ||
386 | |||
387 | /* | ||
388 | * Check if we should interpret the read data | ||
389 | * as a length byte. The DS28E17 unfortunately | ||
390 | * has no read without stop, so we can just do | ||
391 | * another simple read in that case. | ||
392 | */ | ||
393 | if (msgs[i+1].flags & I2C_M_RECV_LEN) { | ||
394 | result = w1_f19_i2c_read(sl, msgs[i+1].addr, | ||
395 | &(msgs[i+1].buf[1]), msgs[i+1].buf[0]); | ||
396 | if (result < 0) { | ||
397 | i = result; | ||
398 | goto error; | ||
399 | } | ||
400 | } | ||
401 | |||
402 | /* Eat up read message, too. */ | ||
403 | i++; | ||
404 | } else if (msgs[i].flags & I2C_M_RD) { | ||
405 | /* Read transfer. */ | ||
406 | result = w1_f19_i2c_read(sl, msgs[i].addr, | ||
407 | msgs[i].buf, msgs[i].len); | ||
408 | if (result < 0) { | ||
409 | i = result; | ||
410 | goto error; | ||
411 | } | ||
412 | |||
413 | /* | ||
414 | * Check if we should interpret the read data | ||
415 | * as a length byte. The DS28E17 unfortunately | ||
416 | * has no read without stop, so we can just do | ||
417 | * another simple read in that case. | ||
418 | */ | ||
419 | if (msgs[i].flags & I2C_M_RECV_LEN) { | ||
420 | result = w1_f19_i2c_read(sl, | ||
421 | msgs[i].addr, | ||
422 | &(msgs[i].buf[1]), | ||
423 | msgs[i].buf[0]); | ||
424 | if (result < 0) { | ||
425 | i = result; | ||
426 | goto error; | ||
427 | } | ||
428 | } | ||
429 | } else { | ||
430 | /* | ||
431 | * Write transfer. | ||
432 | * Stop condition only for last | ||
433 | * transfer. | ||
434 | */ | ||
435 | result = w1_f19_i2c_write(sl, | ||
436 | msgs[i].addr, | ||
437 | msgs[i].buf, | ||
438 | msgs[i].len, | ||
439 | i == (num-1)); | ||
440 | if (result < 0) { | ||
441 | i = result; | ||
442 | goto error; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /* Next message. */ | ||
447 | i++; | ||
448 | |||
449 | /* Are there still messages to send/receive? */ | ||
450 | if (i < num) { | ||
451 | /* Yes. Resume to same DS28E17. */ | ||
452 | if (w1_reset_resume_command(sl->master)) { | ||
453 | i = -EIO; | ||
454 | goto error; | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | |||
459 | error: | ||
460 | /* End onewire transaction. */ | ||
461 | mutex_unlock(&sl->master->bus_mutex); | ||
462 | |||
463 | /* Return number of messages processed or error. */ | ||
464 | return i; | ||
465 | } | ||
466 | |||
467 | |||
468 | /* Get I2C adapter functionality. */ | ||
469 | static u32 w1_f19_i2c_functionality(struct i2c_adapter *adapter) | ||
470 | { | ||
471 | /* | ||
472 | * Plain I2C functions only. | ||
473 | * SMBus is emulated by the kernel's I2C layer. | ||
474 | * No "I2C_FUNC_SMBUS_QUICK" | ||
475 | * No "I2C_FUNC_SMBUS_READ_BLOCK_DATA" | ||
476 | * No "I2C_FUNC_SMBUS_BLOCK_PROC_CALL" | ||
477 | */ | ||
478 | return I2C_FUNC_I2C | | ||
479 | I2C_FUNC_SMBUS_BYTE | | ||
480 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
481 | I2C_FUNC_SMBUS_WORD_DATA | | ||
482 | I2C_FUNC_SMBUS_PROC_CALL | | ||
483 | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | | ||
484 | I2C_FUNC_SMBUS_I2C_BLOCK | | ||
485 | I2C_FUNC_SMBUS_PEC; | ||
486 | } | ||
487 | |||
488 | |||
489 | /* I2C adapter quirks. */ | ||
490 | static const struct i2c_adapter_quirks w1_f19_i2c_adapter_quirks = { | ||
491 | .max_read_len = W1_F19_READ_DATA_LIMIT, | ||
492 | }; | ||
493 | |||
494 | /* I2C algorithm. */ | ||
495 | static const struct i2c_algorithm w1_f19_i2c_algorithm = { | ||
496 | .master_xfer = w1_f19_i2c_master_transfer, | ||
497 | .functionality = w1_f19_i2c_functionality, | ||
498 | }; | ||
499 | |||
500 | |||
501 | /* Read I2C speed from DS28E17. */ | ||
502 | static int w1_f19_get_i2c_speed(struct w1_slave *sl) | ||
503 | { | ||
504 | struct w1_f19_data *data = sl->family_data; | ||
505 | int result = -EIO; | ||
506 | |||
507 | /* Start onewire transaction. */ | ||
508 | mutex_lock(&sl->master->bus_mutex); | ||
509 | |||
510 | /* Select slave. */ | ||
511 | if (w1_reset_select_slave(sl)) | ||
512 | goto error; | ||
513 | |||
514 | /* Read slave configuration byte. */ | ||
515 | w1_write_8(sl->master, W1_F19_READ_CONFIGURATION); | ||
516 | result = w1_read_8(sl->master); | ||
517 | if (result < 0 || result > 2) { | ||
518 | result = -EIO; | ||
519 | goto error; | ||
520 | } | ||
521 | |||
522 | /* Update speed in slave specific data. */ | ||
523 | data->speed = result; | ||
524 | |||
525 | error: | ||
526 | /* End onewire transaction. */ | ||
527 | mutex_unlock(&sl->master->bus_mutex); | ||
528 | |||
529 | return result; | ||
530 | } | ||
531 | |||
532 | |||
533 | /* Set I2C speed on DS28E17. */ | ||
534 | static int __w1_f19_set_i2c_speed(struct w1_slave *sl, u8 speed) | ||
535 | { | ||
536 | struct w1_f19_data *data = sl->family_data; | ||
537 | const int i2c_speeds[3] = { 100, 400, 900 }; | ||
538 | u8 w1_buf[2]; | ||
539 | |||
540 | /* Select slave. */ | ||
541 | if (w1_reset_select_slave(sl)) | ||
542 | return -EIO; | ||
543 | |||
544 | w1_buf[0] = W1_F19_WRITE_CONFIGURATION; | ||
545 | w1_buf[1] = speed; | ||
546 | w1_write_block(sl->master, w1_buf, 2); | ||
547 | |||
548 | /* Update speed in slave specific data. */ | ||
549 | data->speed = speed; | ||
550 | |||
551 | dev_info(&sl->dev, "i2c speed set to %d kBaud\n", i2c_speeds[speed]); | ||
552 | |||
553 | return 0; | ||
554 | } | ||
555 | |||
556 | static int w1_f19_set_i2c_speed(struct w1_slave *sl, u8 speed) | ||
557 | { | ||
558 | int result; | ||
559 | |||
560 | /* Start onewire transaction. */ | ||
561 | mutex_lock(&sl->master->bus_mutex); | ||
562 | |||
563 | /* Set I2C speed on DS28E17. */ | ||
564 | result = __w1_f19_set_i2c_speed(sl, speed); | ||
565 | |||
566 | /* End onewire transaction. */ | ||
567 | mutex_unlock(&sl->master->bus_mutex); | ||
568 | |||
569 | return result; | ||
570 | } | ||
571 | |||
572 | |||
573 | /* Sysfs attributes. */ | ||
574 | |||
575 | /* I2C speed attribute for a single chip. */ | ||
576 | static ssize_t speed_show(struct device *dev, struct device_attribute *attr, | ||
577 | char *buf) | ||
578 | { | ||
579 | struct w1_slave *sl = dev_to_w1_slave(dev); | ||
580 | int result; | ||
581 | |||
582 | /* Read current speed from slave. Updates data->speed. */ | ||
583 | result = w1_f19_get_i2c_speed(sl); | ||
584 | if (result < 0) | ||
585 | return result; | ||
586 | |||
587 | /* Return current speed value. */ | ||
588 | return sprintf(buf, "%d\n", result); | ||
589 | } | ||
590 | |||
591 | static ssize_t speed_store(struct device *dev, struct device_attribute *attr, | ||
592 | const char *buf, size_t count) | ||
593 | { | ||
594 | struct w1_slave *sl = dev_to_w1_slave(dev); | ||
595 | int error; | ||
596 | |||
597 | /* Valid values are: "100", "400", "900" */ | ||
598 | if (count < 3 || count > 4 || !buf) | ||
599 | return -EINVAL; | ||
600 | if (count == 4 && buf[3] != '\n') | ||
601 | return -EINVAL; | ||
602 | if (buf[1] != '0' || buf[2] != '0') | ||
603 | return -EINVAL; | ||
604 | |||
605 | /* Set speed on slave. */ | ||
606 | switch (buf[0]) { | ||
607 | case '1': | ||
608 | error = w1_f19_set_i2c_speed(sl, 0); | ||
609 | break; | ||
610 | case '4': | ||
611 | error = w1_f19_set_i2c_speed(sl, 1); | ||
612 | break; | ||
613 | case '9': | ||
614 | error = w1_f19_set_i2c_speed(sl, 2); | ||
615 | break; | ||
616 | default: | ||
617 | return -EINVAL; | ||
618 | } | ||
619 | |||
620 | if (error < 0) | ||
621 | return error; | ||
622 | |||
623 | /* Return bytes written. */ | ||
624 | return count; | ||
625 | } | ||
626 | |||
627 | static DEVICE_ATTR_RW(speed); | ||
628 | |||
629 | |||
630 | /* Busy stretch attribute for a single chip. */ | ||
631 | static ssize_t stretch_show(struct device *dev, struct device_attribute *attr, | ||
632 | char *buf) | ||
633 | { | ||
634 | struct w1_slave *sl = dev_to_w1_slave(dev); | ||
635 | struct w1_f19_data *data = sl->family_data; | ||
636 | |||
637 | /* Return current stretch value. */ | ||
638 | return sprintf(buf, "%d\n", data->stretch); | ||
639 | } | ||
640 | |||
641 | static ssize_t stretch_store(struct device *dev, struct device_attribute *attr, | ||
642 | const char *buf, size_t count) | ||
643 | { | ||
644 | struct w1_slave *sl = dev_to_w1_slave(dev); | ||
645 | struct w1_f19_data *data = sl->family_data; | ||
646 | |||
647 | /* Valid values are '1' to '9' */ | ||
648 | if (count < 1 || count > 2 || !buf) | ||
649 | return -EINVAL; | ||
650 | if (count == 2 && buf[1] != '\n') | ||
651 | return -EINVAL; | ||
652 | if (buf[0] < '1' || buf[0] > '9') | ||
653 | return -EINVAL; | ||
654 | |||
655 | /* Set busy stretch value. */ | ||
656 | data->stretch = buf[0] & 0x0F; | ||
657 | |||
658 | /* Return bytes written. */ | ||
659 | return count; | ||
660 | } | ||
661 | |||
662 | static DEVICE_ATTR_RW(stretch); | ||
663 | |||
664 | |||
665 | /* All attributes. */ | ||
666 | static struct attribute *w1_f19_attrs[] = { | ||
667 | &dev_attr_speed.attr, | ||
668 | &dev_attr_stretch.attr, | ||
669 | NULL, | ||
670 | }; | ||
671 | |||
672 | static const struct attribute_group w1_f19_group = { | ||
673 | .attrs = w1_f19_attrs, | ||
674 | }; | ||
675 | |||
676 | static const struct attribute_group *w1_f19_groups[] = { | ||
677 | &w1_f19_group, | ||
678 | NULL, | ||
679 | }; | ||
680 | |||
681 | |||
682 | /* Slave add and remove functions. */ | ||
683 | static int w1_f19_add_slave(struct w1_slave *sl) | ||
684 | { | ||
685 | struct w1_f19_data *data = NULL; | ||
686 | |||
687 | /* Allocate memory for slave specific data. */ | ||
688 | data = devm_kzalloc(&sl->dev, sizeof(*data), GFP_KERNEL); | ||
689 | if (!data) | ||
690 | return -ENOMEM; | ||
691 | sl->family_data = data; | ||
692 | |||
693 | /* Setup default I2C speed on slave. */ | ||
694 | switch (i2c_speed) { | ||
695 | case 100: | ||
696 | __w1_f19_set_i2c_speed(sl, 0); | ||
697 | break; | ||
698 | case 400: | ||
699 | __w1_f19_set_i2c_speed(sl, 1); | ||
700 | break; | ||
701 | case 900: | ||
702 | __w1_f19_set_i2c_speed(sl, 2); | ||
703 | break; | ||
704 | default: | ||
705 | /* | ||
706 | * A i2c_speed module parameter of anything else | ||
707 | * than 100, 400, 900 means not to touch the | ||
708 | * speed of the DS28E17. | ||
709 | * We assume 400kBaud, the power-on value. | ||
710 | */ | ||
711 | data->speed = 1; | ||
712 | } | ||
713 | |||
714 | /* | ||
715 | * Setup default busy stretch | ||
716 | * configuration for the DS28E17. | ||
717 | */ | ||
718 | data->stretch = i2c_stretch; | ||
719 | |||
720 | /* Setup I2C adapter. */ | ||
721 | data->adapter.owner = THIS_MODULE; | ||
722 | data->adapter.algo = &w1_f19_i2c_algorithm; | ||
723 | data->adapter.algo_data = sl; | ||
724 | strcpy(data->adapter.name, "w1-"); | ||
725 | strcat(data->adapter.name, sl->name); | ||
726 | data->adapter.dev.parent = &sl->dev; | ||
727 | data->adapter.quirks = &w1_f19_i2c_adapter_quirks; | ||
728 | |||
729 | return i2c_add_adapter(&data->adapter); | ||
730 | } | ||
731 | |||
732 | static void w1_f19_remove_slave(struct w1_slave *sl) | ||
733 | { | ||
734 | struct w1_f19_data *family_data = sl->family_data; | ||
735 | |||
736 | /* Delete I2C adapter. */ | ||
737 | i2c_del_adapter(&family_data->adapter); | ||
738 | |||
739 | /* Free slave specific data. */ | ||
740 | devm_kfree(&sl->dev, family_data); | ||
741 | sl->family_data = NULL; | ||
742 | } | ||
743 | |||
744 | |||
745 | /* Declarations within the w1 subsystem. */ | ||
746 | static struct w1_family_ops w1_f19_fops = { | ||
747 | .add_slave = w1_f19_add_slave, | ||
748 | .remove_slave = w1_f19_remove_slave, | ||
749 | .groups = w1_f19_groups, | ||
750 | }; | ||
751 | |||
752 | static struct w1_family w1_family_19 = { | ||
753 | .fid = W1_FAMILY_DS28E17, | ||
754 | .fops = &w1_f19_fops, | ||
755 | }; | ||
756 | |||
757 | |||
758 | /* Module init and remove functions. */ | ||
759 | static int __init w1_f19_init(void) | ||
760 | { | ||
761 | return w1_register_family(&w1_family_19); | ||
762 | } | ||
763 | |||
764 | static void __exit w1_f19_fini(void) | ||
765 | { | ||
766 | w1_unregister_family(&w1_family_19); | ||
767 | } | ||
768 | |||
769 | module_init(w1_f19_init); | ||
770 | module_exit(w1_f19_fini); | ||
771 | |||
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 259525c3382a..3c350dfbcd0b 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
@@ -268,17 +268,18 @@ static inline int w1_therm_eeprom(struct device *device) | |||
268 | int ret, max_trying = 10; | 268 | int ret, max_trying = 10; |
269 | u8 *family_data = sl->family_data; | 269 | u8 *family_data = sl->family_data; |
270 | 270 | ||
271 | ret = mutex_lock_interruptible(&dev->bus_mutex); | ||
272 | if (ret != 0) | ||
273 | goto post_unlock; | ||
274 | |||
275 | if (!sl->family_data) { | 271 | if (!sl->family_data) { |
276 | ret = -ENODEV; | 272 | ret = -ENODEV; |
277 | goto pre_unlock; | 273 | goto error; |
278 | } | 274 | } |
279 | 275 | ||
280 | /* prevent the slave from going away in sleep */ | 276 | /* prevent the slave from going away in sleep */ |
281 | atomic_inc(THERM_REFCNT(family_data)); | 277 | atomic_inc(THERM_REFCNT(family_data)); |
278 | |||
279 | ret = mutex_lock_interruptible(&dev->bus_mutex); | ||
280 | if (ret != 0) | ||
281 | goto dec_refcnt; | ||
282 | |||
282 | memset(rom, 0, sizeof(rom)); | 283 | memset(rom, 0, sizeof(rom)); |
283 | 284 | ||
284 | while (max_trying--) { | 285 | while (max_trying--) { |
@@ -306,17 +307,17 @@ static inline int w1_therm_eeprom(struct device *device) | |||
306 | sleep_rem = msleep_interruptible(tm); | 307 | sleep_rem = msleep_interruptible(tm); |
307 | if (sleep_rem != 0) { | 308 | if (sleep_rem != 0) { |
308 | ret = -EINTR; | 309 | ret = -EINTR; |
309 | goto post_unlock; | 310 | goto dec_refcnt; |
310 | } | 311 | } |
311 | 312 | ||
312 | ret = mutex_lock_interruptible(&dev->bus_mutex); | 313 | ret = mutex_lock_interruptible(&dev->bus_mutex); |
313 | if (ret != 0) | 314 | if (ret != 0) |
314 | goto post_unlock; | 315 | goto dec_refcnt; |
315 | } else if (!w1_strong_pullup) { | 316 | } else if (!w1_strong_pullup) { |
316 | sleep_rem = msleep_interruptible(tm); | 317 | sleep_rem = msleep_interruptible(tm); |
317 | if (sleep_rem != 0) { | 318 | if (sleep_rem != 0) { |
318 | ret = -EINTR; | 319 | ret = -EINTR; |
319 | goto pre_unlock; | 320 | goto mt_unlock; |
320 | } | 321 | } |
321 | } | 322 | } |
322 | 323 | ||
@@ -324,11 +325,11 @@ static inline int w1_therm_eeprom(struct device *device) | |||
324 | } | 325 | } |
325 | } | 326 | } |
326 | 327 | ||
327 | pre_unlock: | 328 | mt_unlock: |
328 | mutex_unlock(&dev->bus_mutex); | 329 | mutex_unlock(&dev->bus_mutex); |
329 | 330 | dec_refcnt: | |
330 | post_unlock: | ||
331 | atomic_dec(THERM_REFCNT(family_data)); | 331 | atomic_dec(THERM_REFCNT(family_data)); |
332 | error: | ||
332 | return ret; | 333 | return ret; |
333 | } | 334 | } |
334 | 335 | ||
@@ -350,20 +351,22 @@ static inline int w1_DS18B20_precision(struct device *device, int val) | |||
350 | 351 | ||
351 | if (val > 12 || val < 9) { | 352 | if (val > 12 || val < 9) { |
352 | pr_warn("Unsupported precision\n"); | 353 | pr_warn("Unsupported precision\n"); |
353 | return -1; | 354 | ret = -EINVAL; |
355 | goto error; | ||
354 | } | 356 | } |
355 | 357 | ||
356 | ret = mutex_lock_interruptible(&dev->bus_mutex); | ||
357 | if (ret != 0) | ||
358 | goto post_unlock; | ||
359 | |||
360 | if (!sl->family_data) { | 358 | if (!sl->family_data) { |
361 | ret = -ENODEV; | 359 | ret = -ENODEV; |
362 | goto pre_unlock; | 360 | goto error; |
363 | } | 361 | } |
364 | 362 | ||
365 | /* prevent the slave from going away in sleep */ | 363 | /* prevent the slave from going away in sleep */ |
366 | atomic_inc(THERM_REFCNT(family_data)); | 364 | atomic_inc(THERM_REFCNT(family_data)); |
365 | |||
366 | ret = mutex_lock_interruptible(&dev->bus_mutex); | ||
367 | if (ret != 0) | ||
368 | goto dec_refcnt; | ||
369 | |||
367 | memset(rom, 0, sizeof(rom)); | 370 | memset(rom, 0, sizeof(rom)); |
368 | 371 | ||
369 | /* translate precision to bitmask (see datasheet page 9) */ | 372 | /* translate precision to bitmask (see datasheet page 9) */ |
@@ -411,11 +414,10 @@ static inline int w1_DS18B20_precision(struct device *device, int val) | |||
411 | } | 414 | } |
412 | } | 415 | } |
413 | 416 | ||
414 | pre_unlock: | ||
415 | mutex_unlock(&dev->bus_mutex); | 417 | mutex_unlock(&dev->bus_mutex); |
416 | 418 | dec_refcnt: | |
417 | post_unlock: | ||
418 | atomic_dec(THERM_REFCNT(family_data)); | 419 | atomic_dec(THERM_REFCNT(family_data)); |
420 | error: | ||
419 | return ret; | 421 | return ret; |
420 | } | 422 | } |
421 | 423 | ||
@@ -490,17 +492,18 @@ static ssize_t read_therm(struct device *device, | |||
490 | int ret, max_trying = 10; | 492 | int ret, max_trying = 10; |
491 | u8 *family_data = sl->family_data; | 493 | u8 *family_data = sl->family_data; |
492 | 494 | ||
493 | ret = mutex_lock_interruptible(&dev->bus_mutex); | ||
494 | if (ret != 0) | ||
495 | goto error; | ||
496 | |||
497 | if (!family_data) { | 495 | if (!family_data) { |
498 | ret = -ENODEV; | 496 | ret = -ENODEV; |
499 | goto mt_unlock; | 497 | goto error; |
500 | } | 498 | } |
501 | 499 | ||
502 | /* prevent the slave from going away in sleep */ | 500 | /* prevent the slave from going away in sleep */ |
503 | atomic_inc(THERM_REFCNT(family_data)); | 501 | atomic_inc(THERM_REFCNT(family_data)); |
502 | |||
503 | ret = mutex_lock_interruptible(&dev->bus_mutex); | ||
504 | if (ret != 0) | ||
505 | goto dec_refcnt; | ||
506 | |||
504 | memset(info->rom, 0, sizeof(info->rom)); | 507 | memset(info->rom, 0, sizeof(info->rom)); |
505 | 508 | ||
506 | while (max_trying--) { | 509 | while (max_trying--) { |
@@ -542,7 +545,7 @@ static ssize_t read_therm(struct device *device, | |||
542 | sleep_rem = msleep_interruptible(tm); | 545 | sleep_rem = msleep_interruptible(tm); |
543 | if (sleep_rem != 0) { | 546 | if (sleep_rem != 0) { |
544 | ret = -EINTR; | 547 | ret = -EINTR; |
545 | goto dec_refcnt; | 548 | goto mt_unlock; |
546 | } | 549 | } |
547 | } | 550 | } |
548 | 551 | ||
@@ -567,10 +570,10 @@ static ssize_t read_therm(struct device *device, | |||
567 | break; | 570 | break; |
568 | } | 571 | } |
569 | 572 | ||
570 | dec_refcnt: | ||
571 | atomic_dec(THERM_REFCNT(family_data)); | ||
572 | mt_unlock: | 573 | mt_unlock: |
573 | mutex_unlock(&dev->bus_mutex); | 574 | mutex_unlock(&dev->bus_mutex); |
575 | dec_refcnt: | ||
576 | atomic_dec(THERM_REFCNT(family_data)); | ||
574 | error: | 577 | error: |
575 | return ret; | 578 | return ret; |
576 | } | 579 | } |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index d191e1f80579..075d120e7b88 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -58,7 +58,7 @@ static u8 w1_read_bit(struct w1_master *dev); | |||
58 | * @dev: the master device | 58 | * @dev: the master device |
59 | * @bit: 0 - write a 0, 1 - write a 0 read the level | 59 | * @bit: 0 - write a 0, 1 - write a 0 read the level |
60 | */ | 60 | */ |
61 | static u8 w1_touch_bit(struct w1_master *dev, int bit) | 61 | u8 w1_touch_bit(struct w1_master *dev, int bit) |
62 | { | 62 | { |
63 | if (dev->bus_master->touch_bit) | 63 | if (dev->bus_master->touch_bit) |
64 | return dev->bus_master->touch_bit(dev->bus_master->data, bit); | 64 | return dev->bus_master->touch_bit(dev->bus_master->data, bit); |
@@ -69,6 +69,7 @@ static u8 w1_touch_bit(struct w1_master *dev, int bit) | |||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | EXPORT_SYMBOL_GPL(w1_touch_bit); | ||
72 | 73 | ||
73 | /** | 74 | /** |
74 | * w1_write_bit() - Generates a write-0 or write-1 cycle. | 75 | * w1_write_bit() - Generates a write-0 or write-1 cycle. |
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 6431087816ba..f3e97c5f94c9 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -719,6 +719,10 @@ struct vmbus_channel { | |||
719 | 719 | ||
720 | struct vmbus_close_msg close_msg; | 720 | struct vmbus_close_msg close_msg; |
721 | 721 | ||
722 | /* Statistics */ | ||
723 | u64 interrupts; /* Host to Guest interrupts */ | ||
724 | u64 sig_events; /* Guest to Host events */ | ||
725 | |||
722 | /* Channel callback's invoked in softirq context */ | 726 | /* Channel callback's invoked in softirq context */ |
723 | struct tasklet_struct callback_event; | 727 | struct tasklet_struct callback_event; |
724 | void (*onchannel_callback)(void *context); | 728 | void (*onchannel_callback)(void *context); |
@@ -829,6 +833,11 @@ struct vmbus_channel { | |||
829 | struct rcu_head rcu; | 833 | struct rcu_head rcu; |
830 | 834 | ||
831 | /* | 835 | /* |
836 | * For sysfs per-channel properties. | ||
837 | */ | ||
838 | struct kobject kobj; | ||
839 | |||
840 | /* | ||
832 | * For performance critical channels (storage, networking | 841 | * For performance critical channels (storage, networking |
833 | * etc,), Hyper-V has a mechanism to enhance the throughput | 842 | * etc,), Hyper-V has a mechanism to enhance the throughput |
834 | * at the expense of latency: | 843 | * at the expense of latency: |
@@ -1089,6 +1098,7 @@ struct hv_device { | |||
1089 | struct device device; | 1098 | struct device device; |
1090 | 1099 | ||
1091 | struct vmbus_channel *channel; | 1100 | struct vmbus_channel *channel; |
1101 | struct kset *channels_kset; | ||
1092 | }; | 1102 | }; |
1093 | 1103 | ||
1094 | 1104 | ||
diff --git a/include/linux/w1.h b/include/linux/w1.h index 5b2972946dda..694101f744c7 100644 --- a/include/linux/w1.h +++ b/include/linux/w1.h | |||
@@ -293,6 +293,7 @@ void w1_unregister_family(struct w1_family *family); | |||
293 | w1_unregister_family) | 293 | w1_unregister_family) |
294 | 294 | ||
295 | u8 w1_triplet(struct w1_master *dev, int bdir); | 295 | u8 w1_triplet(struct w1_master *dev, int bdir); |
296 | u8 w1_touch_bit(struct w1_master *dev, int bit); | ||
296 | void w1_write_8(struct w1_master *, u8); | 297 | void w1_write_8(struct w1_master *, u8); |
297 | u8 w1_read_8(struct w1_master *); | 298 | u8 w1_read_8(struct w1_master *); |
298 | int w1_reset_bus(struct w1_master *); | 299 | int w1_reset_bus(struct w1_master *); |