Linux 6.8-rc4 Pulling this for a bugfix upstream with which the gpio/for-next branch conflicts.
Unified · Split
| @@ -289,6 +289,7 @@ Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com> · 288 unmodified lines | ||
| 289 | 289 | John Crispin <john@phrozen.org> <blogic@openwrt.org> |
| 290 | 290 | John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com> |
| 291 | 291 | John Keeping <john@keeping.me.uk> <john@metanate.com> |
| 292 | +John Moon <john@jmoon.dev> <quic_johmoo@quicinc.com> | |
| 292 | 293 | John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> |
| 293 | 294 | John Stultz <johnstul@us.ibm.com> |
| 294 | 295 | <jon.toppins+linux@gmail.com> <jtoppins@cumulusnetworks.com> |
| @@ -344,6 +345,7 @@ Leonid I Ananiev <leonid.i.ananiev@intel.com> · 49 unmodified lines | ||
| 344 | 345 | Leon Romanovsky <leon@kernel.org> <leon@leon.nu> |
| 345 | 346 | Leon Romanovsky <leon@kernel.org> <leonro@mellanox.com> |
| 346 | 347 | Leon Romanovsky <leon@kernel.org> <leonro@nvidia.com> |
| 348 | +Leo Yan <leo.yan@linux.dev> <leo.yan@linaro.org> | |
| 347 | 349 | Liam Mark <quic_lmark@quicinc.com> <lmark@codeaurora.org> |
| 348 | 350 | Linas Vepstas <linas@austin.ibm.com> |
| 349 | 351 | Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch> |
| @@ -2161,6 +2161,19 @@ N: Mike Kravetz · 2160 unmodified lines | ||
| 2161 | 2161 | E: mike.kravetz@oracle.com |
| 2162 | 2162 | D: Maintenance and development of the hugetlb subsystem |
| 2163 | 2163 | |
| 2164 | +N: Seth Jennings | |
| 2165 | +E: sjenning@redhat.com | |
| 2166 | +D: Creation and maintenance of zswap | |
| 2167 | + | |
| 2168 | +N: Dan Streetman | |
| 2169 | +E: ddstreet@ieee.org | |
| 2170 | +D: Maintenance and development of zswap | |
| 2171 | +D: Creation and maintenance of the zpool API | |
| 2172 | + | |
| 2173 | +N: Vitaly Wool | |
| 2174 | +E: vitaly.wool@konsulko.com | |
| 2175 | +D: Maintenance and development of zswap | |
| 2176 | + | |
| 2164 | 2177 | N: Andreas S. Krebs |
| 2165 | 2178 | E: akrebs@altavista.net |
| 2166 | 2179 | D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards |
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/class/<iface>/queues/rx-<queue>/rps_cpus | |
| 1 | +What: /sys/class/net/<iface>/queues/rx-<queue>/rps_cpus | |
| 2 | 2 | Date: March 2010 |
| 3 | 3 | KernelVersion: 2.6.35 |
| 4 | 4 | Contact: netdev@vger.kernel.org |
| @@ -8,7 +8,7 @@ Description: · 3 unmodified lines | ||
| 8 | 8 | network device queue. Possible values depend on the number |
| 9 | 9 | of available CPU(s) in the system. |
| 10 | 10 | |
| 11 | −What: /sys/class/<iface>/queues/rx-<queue>/rps_flow_cnt | |
| 11 | +What: /sys/class/net/<iface>/queues/rx-<queue>/rps_flow_cnt | |
| 12 | 12 | Date: April 2010 |
| 13 | 13 | KernelVersion: 2.6.35 |
| 14 | 14 | Contact: netdev@vger.kernel.org |
| @@ -16,7 +16,7 @@ Description: · 1 unmodified line | ||
| 16 | 16 | Number of Receive Packet Steering flows being currently |
| 17 | 17 | processed by this particular network device receive queue. |
| 18 | 18 | |
| 19 | −What: /sys/class/<iface>/queues/tx-<queue>/tx_timeout | |
| 19 | +What: /sys/class/net/<iface>/queues/tx-<queue>/tx_timeout | |
| 20 | 20 | Date: November 2011 |
| 21 | 21 | KernelVersion: 3.3 |
| 22 | 22 | Contact: netdev@vger.kernel.org |
| @@ -24,7 +24,7 @@ Description: · 1 unmodified line | ||
| 24 | 24 | Indicates the number of transmit timeout events seen by this |
| 25 | 25 | network interface transmit queue. |
| 26 | 26 | |
| 27 | −What: /sys/class/<iface>/queues/tx-<queue>/tx_maxrate | |
| 27 | +What: /sys/class/net/<iface>/queues/tx-<queue>/tx_maxrate | |
| 28 | 28 | Date: March 2015 |
| 29 | 29 | KernelVersion: 4.1 |
| 30 | 30 | Contact: netdev@vger.kernel.org |
| @@ -32,7 +32,7 @@ Description: · 1 unmodified line | ||
| 32 | 32 | A Mbps max-rate set for the queue, a value of zero means disabled, |
| 33 | 33 | default is disabled. |
| 34 | 34 | |
| 35 | −What: /sys/class/<iface>/queues/tx-<queue>/xps_cpus | |
| 35 | +What: /sys/class/net/<iface>/queues/tx-<queue>/xps_cpus | |
| 36 | 36 | Date: November 2010 |
| 37 | 37 | KernelVersion: 2.6.38 |
| 38 | 38 | Contact: netdev@vger.kernel.org |
| @@ -42,7 +42,7 @@ Description: · 3 unmodified lines | ||
| 42 | 42 | network device transmit queue. Possible values depend on the |
| 43 | 43 | number of available CPU(s) in the system. |
| 44 | 44 | |
| 45 | −What: /sys/class/<iface>/queues/tx-<queue>/xps_rxqs | |
| 45 | +What: /sys/class/net/<iface>/queues/tx-<queue>/xps_rxqs | |
| 46 | 46 | Date: June 2018 |
| 47 | 47 | KernelVersion: 4.18.0 |
| 48 | 48 | Contact: netdev@vger.kernel.org |
| @@ -53,7 +53,7 @@ Description: · 4 unmodified lines | ||
| 53 | 53 | number of available receive queue(s) in the network device. |
| 54 | 54 | Default is disabled. |
| 55 | 55 | |
| 56 | −What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time | |
| 56 | +What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time | |
| 57 | 57 | Date: November 2011 |
| 58 | 58 | KernelVersion: 3.3 |
| 59 | 59 | Contact: netdev@vger.kernel.org |
| @@ -62,7 +62,7 @@ Description: · 2 unmodified lines | ||
| 62 | 62 | of this particular network device transmit queue. |
| 63 | 63 | Default value is 1000. |
| 64 | 64 | |
| 65 | −What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/inflight | |
| 65 | +What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/inflight | |
| 66 | 66 | Date: November 2011 |
| 67 | 67 | KernelVersion: 3.3 |
| 68 | 68 | Contact: netdev@vger.kernel.org |
| @@ -70,7 +70,7 @@ Description: · 1 unmodified line | ||
| 70 | 70 | Indicates the number of bytes (objects) in flight on this |
| 71 | 71 | network device transmit queue. |
| 72 | 72 | |
| 73 | −What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit | |
| 73 | +What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit | |
| 74 | 74 | Date: November 2011 |
| 75 | 75 | KernelVersion: 3.3 |
| 76 | 76 | Contact: netdev@vger.kernel.org |
| @@ -79,7 +79,7 @@ Description: · 2 unmodified lines | ||
| 79 | 79 | on this network device transmit queue. This value is clamped |
| 80 | 80 | to be within the bounds defined by limit_max and limit_min. |
| 81 | 81 | |
| 82 | −What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max | |
| 82 | +What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max | |
| 83 | 83 | Date: November 2011 |
| 84 | 84 | KernelVersion: 3.3 |
| 85 | 85 | Contact: netdev@vger.kernel.org |
| @@ -88,7 +88,7 @@ Description: · 2 unmodified lines | ||
| 88 | 88 | queued on this network device transmit queue. See |
| 89 | 89 | include/linux/dynamic_queue_limits.h for the default value. |
| 90 | 90 | |
| 91 | −What: /sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min | |
| 91 | +What: /sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min | |
| 92 | 92 | Date: November 2011 |
| 93 | 93 | KernelVersion: 3.3 |
| 94 | 94 | Contact: netdev@vger.kernel.org |
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/devices/.../hwmon/hwmon<i>/in0_input | |
| 1 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/in0_input | |
| 2 | 2 | Date: February 2023 |
| 3 | 3 | KernelVersion: 6.2 |
| 4 | 4 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -6,7 +6,7 @@ Description: RO. Current Voltage in millivolt. · 1 unmodified line | ||
| 6 | 6 | |
| 7 | 7 | Only supported for particular Intel i915 graphics platforms. |
| 8 | 8 | |
| 9 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max | |
| 9 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_max | |
| 10 | 10 | Date: February 2023 |
| 11 | 11 | KernelVersion: 6.2 |
| 12 | 12 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -20,7 +20,7 @@ Description: RW. Card reactive sustained (PL1/Tau) power limit in microwatts. · 7 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | Only supported for particular Intel i915 graphics platforms. |
| 22 | 22 | |
| 23 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_rated_max | |
| 23 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_rated_max | |
| 24 | 24 | Date: February 2023 |
| 25 | 25 | KernelVersion: 6.2 |
| 26 | 26 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -28,7 +28,7 @@ Description: RO. Card default power limit (default TDP setting). · 1 unmodified line | ||
| 28 | 28 | |
| 29 | 29 | Only supported for particular Intel i915 graphics platforms. |
| 30 | 30 | |
| 31 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max_interval | |
| 31 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_max_interval | |
| 32 | 32 | Date: February 2023 |
| 33 | 33 | KernelVersion: 6.2 |
| 34 | 34 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -37,7 +37,7 @@ Description: RW. Sustained power limit interval (Tau in PL1/Tau) in · 2 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | Only supported for particular Intel i915 graphics platforms. |
| 39 | 39 | |
| 40 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_crit | |
| 40 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/power1_crit | |
| 41 | 41 | Date: February 2023 |
| 42 | 42 | KernelVersion: 6.2 |
| 43 | 43 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -50,7 +50,7 @@ Description: RW. Card reactive critical (I1) power limit in microwatts. · 6 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | Only supported for particular Intel i915 graphics platforms. |
| 52 | 52 | |
| 53 | −What: /sys/devices/.../hwmon/hwmon<i>/curr1_crit | |
| 53 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/curr1_crit | |
| 54 | 54 | Date: February 2023 |
| 55 | 55 | KernelVersion: 6.2 |
| 56 | 56 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -63,7 +63,7 @@ Description: RW. Card reactive critical (I1) power limit in milliamperes. · 6 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | Only supported for particular Intel i915 graphics platforms. |
| 65 | 65 | |
| 66 | −What: /sys/devices/.../hwmon/hwmon<i>/energy1_input | |
| 66 | +What: /sys/bus/pci/drivers/i915/.../hwmon/hwmon<i>/energy1_input | |
| 67 | 67 | Date: February 2023 |
| 68 | 68 | KernelVersion: 6.2 |
| 69 | 69 | Contact: intel-gfx@lists.freedesktop.org |
| @@ -1,4 +1,4 @@ | ||
| 1 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max | |
| 1 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_max | |
| 2 | 2 | Date: September 2023 |
| 3 | 3 | KernelVersion: 6.5 |
| 4 | 4 | Contact: intel-xe@lists.freedesktop.org |
| @@ -12,7 +12,7 @@ Description: RW. Card reactive sustained (PL1) power limit in microwatts. · 7 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | Only supported for particular Intel xe graphics platforms. |
| 14 | 14 | |
| 15 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_rated_max | |
| 15 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_rated_max | |
| 16 | 16 | Date: September 2023 |
| 17 | 17 | KernelVersion: 6.5 |
| 18 | 18 | Contact: intel-xe@lists.freedesktop.org |
| @@ -20,7 +20,7 @@ Description: RO. Card default power limit (default TDP setting). · 1 unmodified line | ||
| 20 | 20 | |
| 21 | 21 | Only supported for particular Intel xe graphics platforms. |
| 22 | 22 | |
| 23 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_crit | |
| 23 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_crit | |
| 24 | 24 | Date: September 2023 |
| 25 | 25 | KernelVersion: 6.5 |
| 26 | 26 | Contact: intel-xe@lists.freedesktop.org |
| @@ -33,7 +33,7 @@ Description: RW. Card reactive critical (I1) power limit in microwatts. · 6 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | Only supported for particular Intel xe graphics platforms. |
| 35 | 35 | |
| 36 | −What: /sys/devices/.../hwmon/hwmon<i>/curr1_crit | |
| 36 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/curr1_crit | |
| 37 | 37 | Date: September 2023 |
| 38 | 38 | KernelVersion: 6.5 |
| 39 | 39 | Contact: intel-xe@lists.freedesktop.org |
| @@ -44,7 +44,7 @@ Description: RW. Card reactive critical (I1) power limit in milliamperes. · 4 unmodified lines | ||
| 44 | 44 | the operating frequency if the power averaged over a window |
| 45 | 45 | exceeds this limit. |
| 46 | 46 | |
| 47 | −What: /sys/devices/.../hwmon/hwmon<i>/in0_input | |
| 47 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/in0_input | |
| 48 | 48 | Date: September 2023 |
| 49 | 49 | KernelVersion: 6.5 |
| 50 | 50 | Contact: intel-xe@lists.freedesktop.org |
| @@ -52,7 +52,7 @@ Description: RO. Current Voltage in millivolt. · 1 unmodified line | ||
| 52 | 52 | |
| 53 | 53 | Only supported for particular Intel xe graphics platforms. |
| 54 | 54 | |
| 55 | −What: /sys/devices/.../hwmon/hwmon<i>/energy1_input | |
| 55 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/energy1_input | |
| 56 | 56 | Date: September 2023 |
| 57 | 57 | KernelVersion: 6.5 |
| 58 | 58 | Contact: intel-xe@lists.freedesktop.org |
| @@ -60,7 +60,7 @@ Description: RO. Energy input of device in microjoules. · 1 unmodified line | ||
| 60 | 60 | |
| 61 | 61 | Only supported for particular Intel xe graphics platforms. |
| 62 | 62 | |
| 63 | −What: /sys/devices/.../hwmon/hwmon<i>/power1_max_interval | |
| 63 | +What: /sys/bus/pci/drivers/xe/.../hwmon/hwmon<i>/power1_max_interval | |
| 64 | 64 | Date: October 2023 |
| 65 | 65 | KernelVersion: 6.6 |
| 66 | 66 | Contact: intel-xe@lists.freedesktop.org |
| @@ -10,6 +10,7 @@ What: /sys/devices/platform/silicom-platform/power_cycle · 9 unmodified lines | ||
| 10 | 10 | Date: November 2023 |
| 11 | 11 | KernelVersion: 6.7 |
| 12 | 12 | Contact: Henry Shi <henrys@silicom-usa.com> |
| 13 | +Description: | |
| 13 | 14 | This file allow user to power cycle the platform. |
| 14 | 15 | Default value is 0; when set to 1, it powers down |
| 15 | 16 | the platform, waits 5 seconds, then powers on the |
| @@ -101,8 +101,8 @@ External References · 100 unmodified lines | ||
| 101 | 101 | email threads |
| 102 | 102 | ------------- |
| 103 | 103 | |
| 104 | −* `Initial discussion on the New subsystem for acceleration devices <https://lkml.org/lkml/2022/7/31/83>`_ - Oded Gabbay (2022) | |
| 105 | −* `patch-set to add the new subsystem <https://lkml.org/lkml/2022/10/22/544>`_ - Oded Gabbay (2022) | |
| 104 | +* `Initial discussion on the New subsystem for acceleration devices <https://lore.kernel.org/lkml/CAFCwf11=9qpNAepL7NL+YAV_QO=Wv6pnWPhKHKAepK3fNn+2Dg@mail.gmail.com/>`_ - Oded Gabbay (2022) | |
| 105 | +* `patch-set to add the new subsystem <https://lore.kernel.org/lkml/20221022214622.18042-1-ogabbay@kernel.org/>`_ - Oded Gabbay (2022) | |
| 106 | 106 | |
| 107 | 107 | Conference talks |
| 108 | 108 | ---------------- |
| @@ -218,8 +218,3 @@ bytes respectively. Such letter suffixes can also be entirely omitted: · 217 unmodified lines | ||
| 218 | 218 | |
| 219 | 219 | .. include:: kernel-parameters.txt |
| 220 | 220 | :literal: |
| 221 | − | |
| 222 | −Todo | |
| 223 | −---- | |
| 224 | − | |
| 225 | − Add more DRM drivers. | |
| @@ -243,13 +243,9 @@ To reduce its OS jitter, do any of the following: · 242 unmodified lines | ||
| 243 | 243 | 3. Do any of the following needed to avoid jitter that your |
| 244 | 244 | application cannot tolerate: |
| 245 | 245 | |
| 246 | − a. Build your kernel with CONFIG_SLUB=y rather than | |
| 247 | − CONFIG_SLAB=y, thus avoiding the slab allocator's periodic | |
| 248 | − use of each CPU's workqueues to run its cache_reap() | |
| 249 | − function. | |
| 250 | − b. Avoid using oprofile, thus avoiding OS jitter from | |
| 246 | + a. Avoid using oprofile, thus avoiding OS jitter from | |
| 251 | 247 | wq_sync_buffer(). |
| 252 | − c. Limit your CPU frequency so that a CPU-frequency | |
| 248 | + b. Limit your CPU frequency so that a CPU-frequency | |
| 253 | 249 | governor is not required, possibly enlisting the aid of |
| 254 | 250 | special heatsinks or other cooling technologies. If done |
| 255 | 251 | correctly, and if you CPU architecture permits, you should |
| @@ -259,7 +255,7 @@ To reduce its OS jitter, do any of the following: · 3 unmodified lines | ||
| 259 | 255 | |
| 260 | 256 | WARNING: Please check your CPU specifications to |
| 261 | 257 | make sure that this is safe on your particular system. |
| 262 | − d. As of v3.18, Christoph Lameter's on-demand vmstat workers | |
| 258 | + c. As of v3.18, Christoph Lameter's on-demand vmstat workers | |
| 263 | 259 | commit prevents OS jitter due to vmstat_update() on |
| 264 | 260 | CONFIG_SMP=y systems. Before v3.18, is not possible |
| 265 | 261 | to entirely get rid of the OS jitter, but you can |
| @@ -274,7 +270,7 @@ To reduce its OS jitter, do any of the following: · 8 unmodified lines | ||
| 274 | 270 | (based on an earlier one from Gilad Ben-Yossef) that |
| 275 | 271 | reduces or even eliminates vmstat overhead for some |
| 276 | 272 | workloads at https://lore.kernel.org/r/00000140e9dfd6bd-40db3d4f-c1be-434f-8132-7820f81bb586-000000@email.amazonses.com. |
| 277 | − e. If running on high-end powerpc servers, build with | |
| 273 | + d. If running on high-end powerpc servers, build with | |
| 278 | 274 | CONFIG_PPC_RTAS_DAEMON=n. This prevents the RTAS |
| 279 | 275 | daemon from running on each CPU every second or so. |
| 280 | 276 | (This will require editing Kconfig files and will defeat |
| @@ -282,12 +278,12 @@ To reduce its OS jitter, do any of the following: · 1 unmodified line | ||
| 282 | 278 | due to the rtas_event_scan() function. |
| 283 | 279 | WARNING: Please check your CPU specifications to |
| 284 | 280 | make sure that this is safe on your particular system. |
| 285 | − f. If running on Cell Processor, build your kernel with | |
| 281 | + e. If running on Cell Processor, build your kernel with | |
| 286 | 282 | CBE_CPUFREQ_SPU_GOVERNOR=n to avoid OS jitter from |
| 287 | 283 | spu_gov_work(). |
| 288 | 284 | WARNING: Please check your CPU specifications to |
| 289 | 285 | make sure that this is safe on your particular system. |
| 290 | − g. If running on PowerMAC, build your kernel with | |
| 286 | + f. If running on PowerMAC, build your kernel with | |
| 291 | 287 | CONFIG_PMAC_RACKMETER=n to disable the CPU-meter, |
| 292 | 288 | avoiding OS jitter from rackmeter_do_timer(). |
| 293 | 289 | |
| @@ -671,8 +671,23 @@ Testing Static Functions · 670 unmodified lines | ||
| 671 | 671 | ------------------------ |
| 672 | 672 | |
| 673 | 673 | If we do not want to expose functions or variables for testing, one option is to |
| 674 | −conditionally ``#include`` the test file at the end of your .c file. For | |
| 675 | −example: | |
| 674 | +conditionally export the used symbol. For example: | |
| 675 | + | |
| 676 | +.. code-block:: c | |
| 677 | + | |
| 678 | + /* In my_file.c */ | |
| 679 | + | |
| 680 | + VISIBLE_IF_KUNIT int do_interesting_thing(); | |
| 681 | + EXPORT_SYMBOL_IF_KUNIT(do_interesting_thing); | |
| 682 | + | |
| 683 | + /* In my_file.h */ | |
| 684 | + | |
| 685 | + #if IS_ENABLED(CONFIG_KUNIT) | |
| 686 | + int do_interesting_thing(void); | |
| 687 | + #endif | |
| 688 | + | |
| 689 | +Alternatively, you could conditionally ``#include`` the test file at the end of | |
| 690 | +your .c file. For example: | |
| 676 | 691 | |
| 677 | 692 | .. code-block:: c |
| 678 | 693 | |
| @@ -85,7 +85,7 @@ allOf: · 84 unmodified lines | ||
| 85 | 85 | clocks: |
| 86 | 86 | minItems: 6 |
| 87 | 87 | maxItems: 6 |
| 88 | − regs: | |
| 88 | + reg: | |
| 89 | 89 | minItems: 2 |
| 90 | 90 | maxItems: 2 |
| 91 | 91 | |
| @@ -99,7 +99,7 @@ allOf: · 7 unmodified lines | ||
| 99 | 99 | clocks: |
| 100 | 100 | minItems: 4 |
| 101 | 101 | maxItems: 4 |
| 102 | − regs: | |
| 102 | + reg: | |
| 103 | 103 | minItems: 2 |
| 104 | 104 | maxItems: 2 |
| 105 | 105 | |
| @@ -116,7 +116,7 @@ allOf: · 10 unmodified lines | ||
| 116 | 116 | clocks: |
| 117 | 117 | minItems: 3 |
| 118 | 118 | maxItems: 3 |
| 119 | − regs: | |
| 119 | + reg: | |
| 120 | 120 | minItems: 1 |
| 121 | 121 | maxItems: 1 |
| 122 | 122 | |
| @@ -17,7 +17,7 @@ properties: · 16 unmodified lines | ||
| 17 | 17 | compatible: |
| 18 | 18 | items: |
| 19 | 19 | - enum: |
| 20 | − - ti,k3-j721s2-wave521c | |
| 20 | + - ti,j721s2-wave521c | |
| 21 | 21 | - const: cnm,wave521c |
| 22 | 22 | |
| 23 | 23 | reg: |
| @@ -53,7 +53,7 @@ additionalProperties: false · 29 unmodified lines | ||
| 53 | 53 | examples: |
| 54 | 54 | - | |
| 55 | 55 | vpu: video-codec@12345678 { |
| 56 | − compatible = "ti,k3-j721s2-wave521c", "cnm,wave521c"; | |
| 56 | + compatible = "ti,j721s2-wave521c", "cnm,wave521c"; | |
| 57 | 57 | reg = <0x12345678 0x1000>; |
| 58 | 58 | clocks = <&clks 42>; |
| 59 | 59 | interrupts = <42>; |
| @@ -22,6 +22,7 @@ properties: · 21 unmodified lines | ||
| 22 | 22 | - const: allwinner,sun6i-a31-spdif |
| 23 | 23 | - const: allwinner,sun8i-h3-spdif |
| 24 | 24 | - const: allwinner,sun50i-h6-spdif |
| 25 | + - const: allwinner,sun50i-h616-spdif | |
| 25 | 26 | - items: |
| 26 | 27 | - const: allwinner,sun8i-a83t-spdif |
| 27 | 28 | - const: allwinner,sun8i-h3-spdif |
| @@ -62,6 +63,8 @@ allOf: · 34 unmodified lines | ||
| 62 | 63 | enum: |
| 63 | 64 | - allwinner,sun6i-a31-spdif |
| 64 | 65 | - allwinner,sun8i-h3-spdif |
| 66 | + - allwinner,sun50i-h6-spdif | |
| 67 | + - allwinner,sun50i-h616-spdif | |
| 65 | 68 | |
| 66 | 69 | then: |
| 67 | 70 | required: |
| @@ -73,7 +76,7 @@ allOf: · 5 unmodified lines | ||
| 73 | 76 | contains: |
| 74 | 77 | enum: |
| 75 | 78 | - allwinner,sun8i-h3-spdif |
| 76 | − - allwinner,sun50i-h6-spdif | |
| 79 | + - allwinner,sun50i-h616-spdif | |
| 77 | 80 | |
| 78 | 81 | then: |
| 79 | 82 | properties: |
| @@ -145,7 +145,9 @@ filesystem, an overlay filesystem needs to record in the upper filesystem · 144 unmodified lines | ||
| 145 | 145 | that files have been removed. This is done using whiteouts and opaque |
| 146 | 146 | directories (non-directories are always opaque). |
| 147 | 147 | |
| 148 | −A whiteout is created as a character device with 0/0 device number. | |
| 148 | +A whiteout is created as a character device with 0/0 device number or | |
| 149 | +as a zero-size regular file with the xattr "trusted.overlay.whiteout". | |
| 150 | + | |
| 149 | 151 | When a whiteout is found in the upper level of a merged directory, any |
| 150 | 152 | matching name in the lower level is ignored, and the whiteout itself |
| 151 | 153 | is also hidden. |
| @@ -154,6 +156,13 @@ A directory is made opaque by setting the xattr "trusted.overlay.opaque" · 2 unmodified lines | ||
| 154 | 156 | to "y". Where the upper filesystem contains an opaque directory, any |
| 155 | 157 | directory in the lower filesystem with the same name is ignored. |
| 156 | 158 | |
| 159 | +An opaque directory should not conntain any whiteouts, because they do not | |
| 160 | +serve any purpose. A merge directory containing regular files with the xattr | |
| 161 | +"trusted.overlay.whiteout", should be additionally marked by setting the xattr | |
| 162 | +"trusted.overlay.opaque" to "x" on the merge directory itself. | |
| 163 | +This is needed to avoid the overhead of checking the "trusted.overlay.whiteout" | |
| 164 | +on all entries during readdir in the common case. | |
| 165 | + | |
| 157 | 166 | readdir |
| 158 | 167 | ------- |
| 159 | 168 | |
| @@ -534,8 +543,9 @@ A lower dir with a regular whiteout will always be handled by the overlayfs · 374 unmodified lines | ||
| 534 | 543 | mount, so to support storing an effective whiteout file in an overlayfs mount an |
| 535 | 544 | alternative form of whiteout is supported. This form is a regular, zero-size |
| 536 | 545 | file with the "overlay.whiteout" xattr set, inside a directory with the |
| 537 | −"overlay.whiteouts" xattr set. Such whiteouts are never created by overlayfs, | |
| 538 | −but can be used by userspace tools (like containers) that generate lower layers. | |
| 546 | +"overlay.opaque" xattr set to "x" (see `whiteouts and opaque directories`_). | |
| 547 | +These alternative whiteouts are never created by overlayfs, but can be used by | |
| 548 | +userspace tools (like containers) that generate lower layers. | |
| 539 | 549 | These alternative whiteouts can be escaped using the standard xattr escape |
| 540 | 550 | mechanism in order to properly nest to any depth. |
| 541 | 551 | |
| @@ -942,6 +942,10 @@ attribute-sets: · 941 unmodified lines | ||
| 942 | 942 | - |
| 943 | 943 | name: gro-ipv4-max-size |
| 944 | 944 | type: u32 |
| 945 | + - | |
| 946 | + name: dpll-pin | |
| 947 | + type: nest | |
| 948 | + nested-attributes: link-dpll-pin-attrs | |
| 945 | 949 | - |
| 946 | 950 | name: af-spec-attrs |
| 947 | 951 | attributes: |
| @@ -1627,6 +1631,12 @@ attribute-sets: · 679 unmodified lines | ||
| 1627 | 1631 | - |
| 1628 | 1632 | name: used |
| 1629 | 1633 | type: u8 |
| 1634 | + - | |
| 1635 | + name: link-dpll-pin-attrs | |
| 1636 | + attributes: | |
| 1637 | + - | |
| 1638 | + name: id | |
| 1639 | + type: u32 | |
| 1630 | 1640 | |
| 1631 | 1641 | sub-messages: |
| 1632 | 1642 | - |
| @@ -12,5 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | <script type="text/javascript"> <!-- |
| 13 | 13 | var sbar = document.getElementsByClassName("sphinxsidebar")[0]; |
| 14 | 14 | let currents = document.getElementsByClassName("current") |
| 15 | − sbar.scrollTop = currents[currents.length - 1].offsetTop; | |
| 15 | + if (currents.length) { | |
| 16 | + sbar.scrollTop = currents[currents.length - 1].offsetTop; | |
| 17 | + } | |
| 16 | 18 | --> </script> |
| @@ -448,17 +448,17 @@ Function-specific configfs interface · 447 unmodified lines | ||
| 448 | 448 | The function name to use when creating the function directory is "ncm". |
| 449 | 449 | The NCM function provides these attributes in its function directory: |
| 450 | 450 | |
| 451 | − =============== ================================================== | |
| 452 | − ifname network device interface name associated with this | |
| 453 | − function instance | |
| 454 | − qmult queue length multiplier for high and super speed | |
| 455 | − host_addr MAC address of host's end of this | |
| 456 | − Ethernet over USB link | |
| 457 | − dev_addr MAC address of device's end of this | |
| 458 | − Ethernet over USB link | |
| 459 | − max_segment_size Segment size required for P2P connections. This | |
| 460 | − will set MTU to (max_segment_size - 14 bytes) | |
| 461 | − =============== ================================================== | |
| 451 | + ======================= ================================================== | |
| 452 | + ifname network device interface name associated with this | |
| 453 | + function instance | |
| 454 | + qmult queue length multiplier for high and super speed | |
| 455 | + host_addr MAC address of host's end of this | |
| 456 | + Ethernet over USB link | |
| 457 | + dev_addr MAC address of device's end of this | |
| 458 | + Ethernet over USB link | |
| 459 | + max_segment_size Segment size required for P2P connections. This | |
| 460 | + will set MTU to 14 bytes | |
| 461 | + ======================= ================================================== | |
| 462 | 462 | |
| 463 | 463 | and after creating the functions/ncm.<instance name> they contain default |
| 464 | 464 | values: qmult is 5, dev_addr and host_addr are randomly selected. |
| @@ -3168,10 +3168,10 @@ F: drivers/hwmon/asus-ec-sensors.c · 3167 unmodified lines | ||
| 3168 | 3168 | |
| 3169 | 3169 | ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS |
| 3170 | 3170 | M: Corentin Chary <corentin.chary@gmail.com> |
| 3171 | −L: acpi4asus-user@lists.sourceforge.net | |
| 3171 | +M: Luke D. Jones <luke@ljones.dev> | |
| 3172 | 3172 | L: platform-driver-x86@vger.kernel.org |
| 3173 | 3173 | S: Maintained |
| 3174 | −W: http://acpi4asus.sf.net | |
| 3174 | +W: https://asus-linux.org/ | |
| 3175 | 3175 | F: drivers/platform/x86/asus*.c |
| 3176 | 3176 | F: drivers/platform/x86/eeepc*.c |
| 3177 | 3177 | |
| @@ -4169,14 +4169,14 @@ F: drivers/firmware/broadcom/tee_bnxt_fw.c · 991 unmodified lines | ||
| 4169 | 4169 | F: drivers/net/ethernet/broadcom/bnxt/ |
| 4170 | 4170 | F: include/linux/firmware/broadcom/tee_bnxt_fw.h |
| 4171 | 4171 | |
| 4172 | −BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER | |
| 4173 | −M: Arend van Spriel <aspriel@gmail.com> | |
| 4174 | −M: Franky Lin <franky.lin@broadcom.com> | |
| 4175 | −M: Hante Meuleman <hante.meuleman@broadcom.com> | |
| 4172 | +BROADCOM BRCM80211 IEEE802.11 WIRELESS DRIVERS | |
| 4173 | +M: Arend van Spriel <arend.vanspriel@broadcom.com> | |
| 4176 | 4174 | L: linux-wireless@vger.kernel.org |
| 4175 | +L: brcm80211@lists.linux.dev | |
| 4177 | 4176 | L: brcm80211-dev-list.pdl@broadcom.com |
| 4178 | 4177 | S: Supported |
| 4179 | 4178 | F: drivers/net/wireless/broadcom/brcm80211/ |
| 4179 | +F: include/linux/platform_data/brcmfmac.h | |
| 4180 | 4180 | |
| 4181 | 4181 | BROADCOM BRCMSTB GPIO DRIVER |
| 4182 | 4182 | M: Doug Berger <opendmb@gmail.com> |
| @@ -4547,7 +4547,7 @@ F: drivers/net/ieee802154/ca8210.c · 364 unmodified lines | ||
| 4547 | 4547 | |
| 4548 | 4548 | CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS |
| 4549 | 4549 | M: David Howells <dhowells@redhat.com> |
| 4550 | −L: linux-cachefs@redhat.com (moderated for non-subscribers) | |
| 4550 | +L: netfs@lists.linux.dev | |
| 4551 | 4551 | S: Supported |
| 4552 | 4552 | F: Documentation/filesystems/caching/cachefiles.rst |
| 4553 | 4553 | F: fs/cachefiles/ |
| @@ -5958,7 +5958,6 @@ S: Maintained · 1404 unmodified lines | ||
| 5958 | 5958 | F: drivers/platform/x86/dell/dell-wmi-descriptor.c |
| 5959 | 5959 | |
| 5960 | 5960 | DELL WMI HARDWARE PRIVACY SUPPORT |
| 5961 | −M: Perry Yuan <Perry.Yuan@dell.com> | |
| 5962 | 5961 | L: Dell.Client.Kernel@dell.com |
| 5963 | 5962 | L: platform-driver-x86@vger.kernel.org |
| 5964 | 5963 | S: Maintained |
| @@ -7955,12 +7954,13 @@ L: rust-for-linux@vger.kernel.org · 1990 unmodified lines | ||
| 7955 | 7954 | S: Maintained |
| 7956 | 7955 | F: rust/kernel/net/phy.rs |
| 7957 | 7956 | |
| 7958 | −EXEC & BINFMT API | |
| 7957 | +EXEC & BINFMT API, ELF | |
| 7959 | 7958 | R: Eric Biederman <ebiederm@xmission.com> |
| 7960 | 7959 | R: Kees Cook <keescook@chromium.org> |
| 7961 | 7960 | L: linux-mm@kvack.org |
| 7962 | 7961 | S: Supported |
| 7963 | 7962 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/execve |
| 7963 | +F: Documentation/userspace-api/ELF.rst | |
| 7964 | 7964 | F: fs/*binfmt_*.c |
| 7965 | 7965 | F: fs/exec.c |
| 7966 | 7966 | F: include/linux/binfmts.h |
| @@ -8223,7 +8223,8 @@ F: include/linux/iomap.h · 256 unmodified lines | ||
| 8223 | 8223 | |
| 8224 | 8224 | FILESYSTEMS [NETFS LIBRARY] |
| 8225 | 8225 | M: David Howells <dhowells@redhat.com> |
| 8226 | −L: linux-cachefs@redhat.com (moderated for non-subscribers) | |
| 8226 | +R: Jeff Layton <jlayton@kernel.org> | |
| 8227 | +L: netfs@lists.linux.dev | |
| 8227 | 8228 | L: linux-fsdevel@vger.kernel.org |
| 8228 | 8229 | S: Supported |
| 8229 | 8230 | F: Documentation/filesystems/caching/ |
| @@ -10091,7 +10092,7 @@ L: linux-i2c@vger.kernel.org · 1861 unmodified lines | ||
| 10091 | 10092 | S: Maintained |
| 10092 | 10093 | W: https://i2c.wiki.kernel.org/ |
| 10093 | 10094 | Q: https://patchwork.ozlabs.org/project/linux-i2c/list/ |
| 10094 | −T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git | |
| 10095 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git | |
| 10095 | 10096 | F: Documentation/devicetree/bindings/i2c/ |
| 10096 | 10097 | F: drivers/i2c/algos/ |
| 10097 | 10098 | F: drivers/i2c/busses/ |
| @@ -10283,7 +10284,7 @@ F: drivers/scsi/ibmvscsi/ibmvscsi* · 185 unmodified lines | ||
| 10283 | 10284 | F: include/scsi/viosrp.h |
| 10284 | 10285 | |
| 10285 | 10286 | IBM Power Virtual SCSI Device Target Driver |
| 10286 | −M: Michael Cyr <mikecyr@linux.ibm.com> | |
| 10287 | +M: Tyrel Datwyler <tyreld@linux.ibm.com> | |
| 10287 | 10288 | L: linux-scsi@vger.kernel.org |
| 10288 | 10289 | L: target-devel@vger.kernel.org |
| 10289 | 10290 | S: Supported |
| @@ -10801,11 +10802,11 @@ F: drivers/gpio/gpio-tangier.h · 511 unmodified lines | ||
| 10801 | 10802 | |
| 10802 | 10803 | INTEL GVT-g DRIVERS (Intel GPU Virtualization) |
| 10803 | 10804 | M: Zhenyu Wang <zhenyuw@linux.intel.com> |
| 10804 | −M: Zhi Wang <zhi.a.wang@intel.com> | |
| 10805 | +M: Zhi Wang <zhi.wang.linux@gmail.com> | |
| 10805 | 10806 | L: intel-gvt-dev@lists.freedesktop.org |
| 10806 | 10807 | L: intel-gfx@lists.freedesktop.org |
| 10807 | 10808 | S: Supported |
| 10808 | −W: https://01.org/igvt-g | |
| 10809 | +W: https://github.com/intel/gvt-linux/wiki | |
| 10809 | 10810 | T: git https://github.com/intel/gvt-linux.git |
| 10810 | 10811 | F: drivers/gpu/drm/i915/gvt/ |
| 10811 | 10812 | |
| @@ -11127,7 +11128,6 @@ S: Supported · 315 unmodified lines | ||
| 11127 | 11128 | F: drivers/net/wireless/intel/iwlegacy/ |
| 11128 | 11129 | |
| 11129 | 11130 | INTEL WIRELESS WIFI LINK (iwlwifi) |
| 11130 | −M: Gregory Greenman <gregory.greenman@intel.com> | |
| 11131 | 11131 | M: Miri Korenblit <miriam.rachel.korenblit@intel.com> |
| 11132 | 11132 | L: linux-wireless@vger.kernel.org |
| 11133 | 11133 | S: Supported |
| @@ -11725,6 +11725,7 @@ F: fs/smb/server/ · 591 unmodified lines | ||
| 11725 | 11725 | KERNEL UNIT TESTING FRAMEWORK (KUnit) |
| 11726 | 11726 | M: Brendan Higgins <brendanhiggins@google.com> |
| 11727 | 11727 | M: David Gow <davidgow@google.com> |
| 11728 | +R: Rae Moar <rmoar@google.com> | |
| 11728 | 11729 | L: linux-kselftest@vger.kernel.org |
| 11729 | 11730 | L: kunit-dev@googlegroups.com |
| 11730 | 11731 | S: Maintained |
| @@ -12903,6 +12904,8 @@ M: Alejandro Colomar <alx@kernel.org> · 1172 unmodified lines | ||
| 12903 | 12904 | L: linux-man@vger.kernel.org |
| 12904 | 12905 | S: Maintained |
| 12905 | 12906 | W: http://www.kernel.org/doc/man-pages |
| 12907 | +T: git git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git | |
| 12908 | +T: git git://www.alejandro-colomar.es/src/alx/linux/man-pages/man-pages.git | |
| 12906 | 12909 | |
| 12907 | 12910 | MANAGEMENT COMPONENT TRANSPORT PROTOCOL (MCTP) |
| 12908 | 12911 | M: Jeremy Kerr <jk@codeconstruct.com.au> |
| @@ -15178,6 +15181,7 @@ F: Documentation/networking/net_cachelines/net_device.rst · 2269 unmodified lines | ||
| 15178 | 15181 | F: drivers/connector/ |
| 15179 | 15182 | F: drivers/net/ |
| 15180 | 15183 | F: include/dt-bindings/net/ |
| 15184 | +F: include/linux/cn_proc.h | |
| 15181 | 15185 | F: include/linux/etherdevice.h |
| 15182 | 15186 | F: include/linux/fcdevice.h |
| 15183 | 15187 | F: include/linux/fddidevice.h |
| @@ -15185,6 +15189,7 @@ F: include/linux/hippidevice.h · 1 unmodified line | ||
| 15185 | 15189 | F: include/linux/if_* |
| 15186 | 15190 | F: include/linux/inetdevice.h |
| 15187 | 15191 | F: include/linux/netdevice.h |
| 15192 | +F: include/uapi/linux/cn_proc.h | |
| 15188 | 15193 | F: include/uapi/linux/if_* |
| 15189 | 15194 | F: include/uapi/linux/netdevice.h |
| 15190 | 15195 | X: drivers/net/wireless/ |
| @@ -16857,9 +16862,8 @@ F: Documentation/devicetree/bindings/pci/xilinx-versal-cpm.yaml · 1666 unmodified lines | ||
| 16857 | 16862 | F: drivers/pci/controller/pcie-xilinx-cpm.c |
| 16858 | 16863 | |
| 16859 | 16864 | PCI ENDPOINT SUBSYSTEM |
| 16860 | −M: Lorenzo Pieralisi <lpieralisi@kernel.org> | |
| 16865 | +M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | |
| 16861 | 16866 | M: Krzysztof Wilczyński <kw@linux.com> |
| 16862 | −R: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> | |
| 16863 | 16867 | R: Kishon Vijay Abraham I <kishon@kernel.org> |
| 16864 | 16868 | L: linux-pci@vger.kernel.org |
| 16865 | 16869 | S: Supported |
| @@ -17179,7 +17183,7 @@ R: John Garry <john.g.garry@oracle.com> · 313 unmodified lines | ||
| 17179 | 17183 | R: Will Deacon <will@kernel.org> |
| 17180 | 17184 | R: James Clark <james.clark@arm.com> |
| 17181 | 17185 | R: Mike Leach <mike.leach@linaro.org> |
| 17182 | −R: Leo Yan <leo.yan@linaro.org> | |
| 17186 | +R: Leo Yan <leo.yan@linux.dev> | |
| 17183 | 17187 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 17184 | 17188 | S: Supported |
| 17185 | 17189 | F: tools/build/feature/test-libopencsd.c |
| @@ -18082,7 +18086,6 @@ F: drivers/net/ethernet/qualcomm/emac/ · 896 unmodified lines | ||
| 18082 | 18086 | |
| 18083 | 18087 | QUALCOMM ETHQOS ETHERNET DRIVER |
| 18084 | 18088 | M: Vinod Koul <vkoul@kernel.org> |
| 18085 | −R: Bhupesh Sharma <bhupesh.sharma@linaro.org> | |
| 18086 | 18089 | L: netdev@vger.kernel.org |
| 18087 | 18090 | L: linux-arm-msm@vger.kernel.org |
| 18088 | 18091 | S: Maintained |
| @@ -18429,7 +18432,7 @@ S: Supported · 340 unmodified lines | ||
| 18429 | 18432 | F: drivers/infiniband/sw/rdmavt |
| 18430 | 18433 | |
| 18431 | 18434 | RDS - RELIABLE DATAGRAM SOCKETS |
| 18432 | −M: Santosh Shilimkar <santosh.shilimkar@oracle.com> | |
| 18435 | +M: Allison Henderson <allison.henderson@oracle.com> | |
| 18433 | 18436 | L: netdev@vger.kernel.org |
| 18434 | 18437 | L: linux-rdma@vger.kernel.org |
| 18435 | 18438 | L: rds-devel@oss.oracle.com (moderated for non-subscribers) |
| @@ -20550,6 +20553,7 @@ F: Documentation/translations/sp_SP/ · 2114 unmodified lines | ||
| 20550 | 20553 | |
| 20551 | 20554 | SPARC + UltraSPARC (sparc/sparc64) |
| 20552 | 20555 | M: "David S. Miller" <davem@davemloft.net> |
| 20556 | +M: Andreas Larsson <andreas@gaisler.com> | |
| 20553 | 20557 | L: sparclinux@vger.kernel.org |
| 20554 | 20558 | S: Maintained |
| 20555 | 20559 | Q: http://patchwork.ozlabs.org/project/sparclinux/list/ |
| @@ -24340,13 +24344,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/zonefs.git · 3784 unmodified lines | ||
| 24340 | 24344 | F: Documentation/filesystems/zonefs.rst |
| 24341 | 24345 | F: fs/zonefs/ |
| 24342 | 24346 | |
| 24343 | −ZPOOL COMPRESSED PAGE STORAGE API | |
| 24344 | −M: Dan Streetman <ddstreet@ieee.org> | |
| 24345 | −L: linux-mm@kvack.org | |
| 24346 | −S: Maintained | |
| 24347 | −F: include/linux/zpool.h | |
| 24348 | −F: mm/zpool.c | |
| 24349 | − | |
| 24350 | 24347 | ZR36067 VIDEO FOR LINUX DRIVER |
| 24351 | 24348 | M: Corentin Labbe <clabbe@baylibre.com> |
| 24352 | 24349 | L: mjpeg-users@lists.sourceforge.net |
| @@ -24398,7 +24395,9 @@ M: Nhat Pham <nphamcs@gmail.com> · 45 unmodified lines | ||
| 24398 | 24395 | L: linux-mm@kvack.org |
| 24399 | 24396 | S: Maintained |
| 24400 | 24397 | F: Documentation/admin-guide/mm/zswap.rst |
| 24398 | +F: include/linux/zpool.h | |
| 24401 | 24399 | F: include/linux/zswap.h |
| 24400 | +F: mm/zpool.c | |
| 24402 | 24401 | F: mm/zswap.c |
| 24403 | 24402 | |
| 24404 | 24403 | THE REST |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 8 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc1 | |
| 5 | +EXTRAVERSION = -rc4 | |
| 6 | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -294,15 +294,15 @@ may-sync-config := 1 · 285 unmodified lines | ||
| 294 | 294 | single-build := |
| 295 | 295 | |
| 296 | 296 | ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) |
| 297 | − ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) | |
| 297 | + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) | |
| 298 | 298 | need-config := |
| 299 | − endif | |
| 299 | + endif | |
| 300 | 300 | endif |
| 301 | 301 | |
| 302 | 302 | ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),) |
| 303 | − ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),) | |
| 303 | + ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),) | |
| 304 | 304 | may-sync-config := |
| 305 | − endif | |
| 305 | + endif | |
| 306 | 306 | endif |
| 307 | 307 | |
| 308 | 308 | need-compiler := $(may-sync-config) |
| @@ -323,9 +323,9 @@ endif · 14 unmodified lines | ||
| 323 | 323 | # We cannot build single targets and the others at the same time |
| 324 | 324 | ifneq ($(filter $(single-targets), $(MAKECMDGOALS)),) |
| 325 | 325 | single-build := 1 |
| 326 | − ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),) | |
| 326 | + ifneq ($(filter-out $(single-targets), $(MAKECMDGOALS)),) | |
| 327 | 327 | mixed-build := 1 |
| 328 | − endif | |
| 328 | + endif | |
| 329 | 329 | endif |
| 330 | 330 | |
| 331 | 331 | # For "make -j clean all", "make -j mrproper defconfig all", etc. |
| @@ -986,6 +986,10 @@ NOSTDINC_FLAGS += -nostdinc · 654 unmodified lines | ||
| 986 | 986 | # perform bounds checking. |
| 987 | 987 | KBUILD_CFLAGS += $(call cc-option, -fstrict-flex-arrays=3) |
| 988 | 988 | |
| 989 | +#Currently, disable -Wstringop-overflow for GCC 11, globally. | |
| 990 | +KBUILD_CFLAGS-$(CONFIG_CC_NO_STRINGOP_OVERFLOW) += $(call cc-option, -Wno-stringop-overflow) | |
| 991 | +KBUILD_CFLAGS-$(CONFIG_CC_STRINGOP_OVERFLOW) += $(call cc-option, -Wstringop-overflow) | |
| 992 | + | |
| 989 | 993 | # disable invalid "can't wrap" optimizations for signed / pointers |
| 990 | 994 | KBUILD_CFLAGS += -fno-strict-overflow |
| 991 | 995 | |
| @@ -1662,7 +1666,7 @@ help: · 670 unmodified lines | ||
| 1662 | 1666 | @echo ' (sparse by default)' |
| 1663 | 1667 | @echo ' make C=2 [targets] Force check of all c source with $$CHECK' |
| 1664 | 1668 | @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' |
| 1665 | − @echo ' make W=n [targets] Enable extra build checks, n=1,2,3 where' | |
| 1669 | + @echo ' make W=n [targets] Enable extra build checks, n=1,2,3,c,e where' | |
| 1666 | 1670 | @echo ' 1: warnings which may be relevant and do not occur too often' |
| 1667 | 1671 | @echo ' 2: warnings which occur quite often but may still be relevant' |
| 1668 | 1672 | @echo ' 3: more obscure warnings, can most likely be ignored' |
| @@ -673,6 +673,7 @@ config SHADOW_CALL_STACK · 672 unmodified lines | ||
| 673 | 673 | bool "Shadow Call Stack" |
| 674 | 674 | depends on ARCH_SUPPORTS_SHADOW_CALL_STACK |
| 675 | 675 | depends on DYNAMIC_FTRACE_WITH_ARGS || DYNAMIC_FTRACE_WITH_REGS || !FUNCTION_GRAPH_TRACER |
| 676 | + depends on MMU | |
| 676 | 677 | help |
| 677 | 678 | This option enables the compiler's Shadow Call Stack, which |
| 678 | 679 | uses a shadow stack to protect function return addresses from |
| @@ -31,7 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | static __always_inline bool arch_static_branch(struct static_key *key, |
| 32 | 32 | bool branch) |
| 33 | 33 | { |
| 34 | − asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n" | |
| 34 | + asm goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n" | |
| 35 | 35 | "1: \n" |
| 36 | 36 | "nop \n" |
| 37 | 37 | ".pushsection __jump_table, \"aw\" \n" |
| @@ -47,7 +47,7 @@ l_yes: · 9 unmodified lines | ||
| 47 | 47 | static __always_inline bool arch_static_branch_jump(struct static_key *key, |
| 48 | 48 | bool branch) |
| 49 | 49 | { |
| 50 | − asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n" | |
| 50 | + asm goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)" \n" | |
| 51 | 51 | "1: \n" |
| 52 | 52 | "b %l[l_yes] \n" |
| 53 | 53 | ".pushsection __jump_table, \"aw\" \n" |
| @@ -45,8 +45,8 @@ · 44 unmodified lines | ||
| 45 | 45 | num-chipselects = <1>; |
| 46 | 46 | cs-gpios = <&gpio0 ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>; |
| 47 | 47 | |
| 48 | − tpmdev@0 { | |
| 49 | − compatible = "tcg,tpm_tis-spi"; | |
| 48 | + tpm@0 { | |
| 49 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 50 | 50 | spi-max-frequency = <33000000>; |
| 51 | 51 | reg = <0>; |
| 52 | 52 | }; |
| @@ -80,8 +80,8 @@ · 79 unmodified lines | ||
| 80 | 80 | gpio-miso = <&gpio ASPEED_GPIO(R, 5) GPIO_ACTIVE_HIGH>; |
| 81 | 81 | num-chipselects = <1>; |
| 82 | 82 | |
| 83 | − tpmdev@0 { | |
| 84 | − compatible = "tcg,tpm_tis-spi"; | |
| 83 | + tpm@0 { | |
| 84 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 85 | 85 | spi-max-frequency = <33000000>; |
| 86 | 86 | reg = <0>; |
| 87 | 87 | }; |
| @@ -456,7 +456,7 @@ · 455 unmodified lines | ||
| 456 | 456 | status = "okay"; |
| 457 | 457 | |
| 458 | 458 | tpm: tpm@2e { |
| 459 | − compatible = "tcg,tpm-tis-i2c"; | |
| 459 | + compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c"; | |
| 460 | 460 | reg = <0x2e>; |
| 461 | 461 | }; |
| 462 | 462 | }; |
| @@ -35,8 +35,8 @@ · 34 unmodified lines | ||
| 35 | 35 | gpio-mosi = <&gpio0 ASPEED_GPIO(X, 4) GPIO_ACTIVE_HIGH>; |
| 36 | 36 | gpio-miso = <&gpio0 ASPEED_GPIO(X, 5) GPIO_ACTIVE_HIGH>; |
| 37 | 37 | |
| 38 | − tpmdev@0 { | |
| 39 | − compatible = "tcg,tpm_tis-spi"; | |
| 38 | + tpm@0 { | |
| 39 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 40 | 40 | spi-max-frequency = <33000000>; |
| 41 | 41 | reg = <0>; |
| 42 | 42 | }; |
| @@ -116,7 +116,7 @@ · 115 unmodified lines | ||
| 116 | 116 | tpm_tis: tpm@1 { |
| 117 | 117 | pinctrl-names = "default"; |
| 118 | 118 | pinctrl-0 = <&pinctrl_tpm>; |
| 119 | − compatible = "tcg,tpm_tis-spi"; | |
| 119 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 120 | 120 | reg = <1>; |
| 121 | 121 | spi-max-frequency = <20000000>; |
| 122 | 122 | interrupt-parent = <&gpio5>; |
| @@ -130,7 +130,7 @@ · 129 unmodified lines | ||
| 130 | 130 | * TCG specification - Section 6.4.1 Clocking: |
| 131 | 131 | * TPM shall support a SPI clock frequency range of 10-24 MHz. |
| 132 | 132 | */ |
| 133 | − st33htph: tpm-tis@0 { | |
| 133 | + st33htph: tpm@0 { | |
| 134 | 134 | compatible = "st,st33htpm-spi", "tcg,tpm_tis-spi"; |
| 135 | 135 | reg = <0>; |
| 136 | 136 | spi-max-frequency = <24000000>; |
| @@ -434,6 +434,7 @@ · 433 unmodified lines | ||
| 434 | 434 | }; |
| 435 | 435 | |
| 436 | 436 | &fimd { |
| 437 | + samsung,invert-vclk; | |
| 437 | 438 | status = "okay"; |
| 438 | 439 | }; |
| 439 | 440 | |
| @@ -217,7 +217,7 @@ · 216 unmodified lines | ||
| 217 | 217 | pinctrl-names = "default"; |
| 218 | 218 | pinctrl-0 = <&spi1_pins>; |
| 219 | 219 | |
| 220 | − tpm_spi_tis@0 { | |
| 220 | + tpm@0 { | |
| 221 | 221 | compatible = "tcg,tpm_tis-spi"; |
| 222 | 222 | reg = <0>; |
| 223 | 223 | spi-max-frequency = <500000>; |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 13 | 13 | { |
| 14 | − asm_volatile_goto("1:\n\t" | |
| 14 | + asm goto("1:\n\t" | |
| 15 | 15 | WASM(nop) "\n\t" |
| 16 | 16 | ".pushsection __jump_table, \"aw\"\n\t" |
| 17 | 17 | ".word 1b, %l[l_yes], %c0\n\t" |
| @@ -25,7 +25,7 @@ l_yes: · 7 unmodified lines | ||
| 25 | 25 | |
| 26 | 26 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 27 | 27 | { |
| 28 | − asm_volatile_goto("1:\n\t" | |
| 28 | + asm goto("1:\n\t" | |
| 29 | 29 | WASM(b) " %l[l_yes]\n\t" |
| 30 | 30 | ".pushsection __jump_table, \"aw\"\n\t" |
| 31 | 31 | ".word 1b, %l[l_yes], %c0\n\t" |
| @@ -298,6 +298,8 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) · 297 unmodified lines | ||
| 298 | 298 | goto done; |
| 299 | 299 | } |
| 300 | 300 | count_vm_vma_lock_event(VMA_LOCK_RETRY); |
| 301 | + if (fault & VM_FAULT_MAJOR) | |
| 302 | + flags |= FAULT_FLAG_TRIED; | |
| 301 | 303 | |
| 302 | 304 | /* Quick path to respond to signals */ |
| 303 | 305 | if (fault_signal_pending(fault, regs)) { |
| @@ -195,7 +195,7 @@ vdso_prepare: prepare0 · 194 unmodified lines | ||
| 195 | 195 | include/generated/vdso-offsets.h arch/arm64/kernel/vdso/vdso.so |
| 196 | 196 | ifdef CONFIG_COMPAT_VDSO |
| 197 | 197 | $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 \ |
| 198 | − include/generated/vdso32-offsets.h arch/arm64/kernel/vdso32/vdso.so | |
| 198 | + arch/arm64/kernel/vdso32/vdso.so | |
| 199 | 199 | endif |
| 200 | 200 | endif |
| 201 | 201 | |
| @@ -289,7 +289,7 @@ · 288 unmodified lines | ||
| 289 | 289 | #clock-cells = <1>; |
| 290 | 290 | clocks = <&cmu_top CLK_DOUT_CMU_MISC_BUS>, |
| 291 | 291 | <&cmu_top CLK_DOUT_CMU_MISC_SSS>; |
| 292 | − clock-names = "dout_cmu_misc_bus", "dout_cmu_misc_sss"; | |
| 292 | + clock-names = "bus", "sss"; | |
| 293 | 293 | }; |
| 294 | 294 | |
| 295 | 295 | watchdog_cl0: watchdog@10060000 { |
| @@ -120,7 +120,7 @@ · 119 unmodified lines | ||
| 120 | 120 | }; |
| 121 | 121 | |
| 122 | 122 | tpm: tpm@1 { |
| 123 | − compatible = "tcg,tpm_tis-spi"; | |
| 123 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 124 | 124 | interrupts = <11 IRQ_TYPE_LEVEL_LOW>; |
| 125 | 125 | interrupt-parent = <&gpio2>; |
| 126 | 126 | pinctrl-names = "default"; |
| @@ -89,7 +89,7 @@ · 88 unmodified lines | ||
| 89 | 89 | status = "okay"; |
| 90 | 90 | |
| 91 | 91 | tpm@1 { |
| 92 | − compatible = "tcg,tpm_tis-spi"; | |
| 92 | + compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; | |
| 93 | 93 | reg = <0x1>; |
| 94 | 94 | spi-max-frequency = <36000000>; |
| 95 | 95 | }; |
| @@ -109,7 +109,7 @@ · 108 unmodified lines | ||
| 109 | 109 | status = "okay"; |
| 110 | 110 | |
| 111 | 111 | tpm@1 { |
| 112 | − compatible = "tcg,tpm_tis-spi"; | |
| 112 | + compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; | |
| 113 | 113 | reg = <0x1>; |
| 114 | 114 | spi-max-frequency = <36000000>; |
| 115 | 115 | }; |
| @@ -234,7 +234,7 @@ · 233 unmodified lines | ||
| 234 | 234 | status = "okay"; |
| 235 | 235 | |
| 236 | 236 | tpm: tpm@0 { |
| 237 | − compatible = "infineon,slb9670"; | |
| 237 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 238 | 238 | reg = <0>; |
| 239 | 239 | pinctrl-names = "default"; |
| 240 | 240 | pinctrl-0 = <&pinctrl_tpm>; |
| @@ -103,7 +103,7 @@ · 102 unmodified lines | ||
| 103 | 103 | status = "okay"; |
| 104 | 104 | |
| 105 | 105 | tpm@1 { |
| 106 | − compatible = "tcg,tpm_tis-spi"; | |
| 106 | + compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; | |
| 107 | 107 | reg = <0x1>; |
| 108 | 108 | spi-max-frequency = <36000000>; |
| 109 | 109 | }; |
| @@ -115,7 +115,7 @@ · 114 unmodified lines | ||
| 115 | 115 | status = "okay"; |
| 116 | 116 | |
| 117 | 117 | tpm@1 { |
| 118 | − compatible = "tcg,tpm_tis-spi"; | |
| 118 | + compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; | |
| 119 | 119 | reg = <0x1>; |
| 120 | 120 | spi-max-frequency = <36000000>; |
| 121 | 121 | }; |
| @@ -196,7 +196,7 @@ · 195 unmodified lines | ||
| 196 | 196 | status = "okay"; |
| 197 | 197 | |
| 198 | 198 | tpm@0 { |
| 199 | − compatible = "tcg,tpm_tis-spi"; | |
| 199 | + compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; | |
| 200 | 200 | reg = <0x0>; |
| 201 | 201 | spi-max-frequency = <36000000>; |
| 202 | 202 | }; |
| @@ -65,7 +65,7 @@ · 64 unmodified lines | ||
| 65 | 65 | status = "okay"; |
| 66 | 66 | |
| 67 | 67 | tpm@0 { |
| 68 | − compatible = "infineon,slb9670"; | |
| 68 | + compatible = "infineon,slb9670", "tcg,tpm_tis-spi"; | |
| 69 | 69 | reg = <0>; |
| 70 | 70 | spi-max-frequency = <43000000>; |
| 71 | 71 | }; |
| @@ -888,7 +888,7 @@ · 887 unmodified lines | ||
| 888 | 888 | status = "okay"; |
| 889 | 889 | cs-gpios = <&pio 86 GPIO_ACTIVE_LOW>; |
| 890 | 890 | |
| 891 | − cr50@0 { | |
| 891 | + tpm@0 { | |
| 892 | 892 | compatible = "google,cr50"; |
| 893 | 893 | reg = <0>; |
| 894 | 894 | spi-max-frequency = <1000000>; |
| @@ -1402,7 +1402,7 @@ · 1401 unmodified lines | ||
| 1402 | 1402 | pinctrl-names = "default"; |
| 1403 | 1403 | pinctrl-0 = <&spi5_pins>; |
| 1404 | 1404 | |
| 1405 | − cr50@0 { | |
| 1405 | + tpm@0 { | |
| 1406 | 1406 | compatible = "google,cr50"; |
| 1407 | 1407 | reg = <0>; |
| 1408 | 1408 | interrupts-extended = <&pio 171 IRQ_TYPE_EDGE_RISING>; |
| @@ -70,7 +70,7 @@ · 69 unmodified lines | ||
| 70 | 70 | &spi0 { |
| 71 | 71 | status = "okay"; |
| 72 | 72 | |
| 73 | − cr50@0 { | |
| 73 | + tpm@0 { | |
| 74 | 74 | compatible = "google,cr50"; |
| 75 | 75 | reg = <0>; |
| 76 | 76 | interrupt-parent = <&gpio0>; |
| @@ -706,7 +706,7 @@ camera: &i2c7 { · 705 unmodified lines | ||
| 706 | 706 | &spi2 { |
| 707 | 707 | status = "okay"; |
| 708 | 708 | |
| 709 | − cr50@0 { | |
| 709 | + tpm@0 { | |
| 710 | 710 | compatible = "google,cr50"; |
| 711 | 711 | reg = <0>; |
| 712 | 712 | interrupt-parent = <&gpio1>; |
| @@ -229,7 +229,7 @@ alternative_has_cap_likely(const unsigned long cpucap) · 228 unmodified lines | ||
| 229 | 229 | if (!cpucap_is_possible(cpucap)) |
| 230 | 230 | return false; |
| 231 | 231 | |
| 232 | − asm_volatile_goto( | |
| 232 | + asm goto( | |
| 233 | 233 | ALTERNATIVE_CB("b %l[l_no]", %[cpucap], alt_cb_patch_nops) |
| 234 | 234 | : |
| 235 | 235 | : [cpucap] "i" (cpucap) |
| @@ -247,7 +247,7 @@ alternative_has_cap_unlikely(const unsigned long cpucap) · 11 unmodified lines | ||
| 247 | 247 | if (!cpucap_is_possible(cpucap)) |
| 248 | 248 | return false; |
| 249 | 249 | |
| 250 | − asm_volatile_goto( | |
| 250 | + asm goto( | |
| 251 | 251 | ALTERNATIVE("nop", "b %l[l_yes]", %[cpucap]) |
| 252 | 252 | : |
| 253 | 253 | : [cpucap] "i" (cpucap) |
| @@ -18,7 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | static __always_inline bool arch_static_branch(struct static_key * const key, |
| 19 | 19 | const bool branch) |
| 20 | 20 | { |
| 21 | − asm_volatile_goto( | |
| 21 | + asm goto( | |
| 22 | 22 | "1: nop \n\t" |
| 23 | 23 | " .pushsection __jump_table, \"aw\" \n\t" |
| 24 | 24 | " .align 3 \n\t" |
| @@ -35,7 +35,7 @@ l_yes: · 10 unmodified lines | ||
| 35 | 35 | static __always_inline bool arch_static_branch_jump(struct static_key * const key, |
| 36 | 36 | const bool branch) |
| 37 | 37 | { |
| 38 | − asm_volatile_goto( | |
| 38 | + asm goto( | |
| 39 | 39 | "1: b %l[l_yes] \n\t" |
| 40 | 40 | " .pushsection __jump_table, \"aw\" \n\t" |
| 41 | 41 | " .align 3 \n\t" |
| @@ -17,9 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #ifndef __ASSEMBLY__ |
| 18 | 18 | |
| 19 | 19 | #include <generated/vdso-offsets.h> |
| 20 | −#ifdef CONFIG_COMPAT_VDSO | |
| 21 | −#include <generated/vdso32-offsets.h> | |
| 22 | −#endif | |
| 23 | 20 | |
| 24 | 21 | #define VDSO_SYMBOL(base, name) \ |
| 25 | 22 | ({ \ |
| @@ -77,9 +77,9 @@ obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.o · 76 unmodified lines | ||
| 77 | 77 | # We need to prevent the SCS patching code from patching itself. Using |
| 78 | 78 | # -mbranch-protection=none here to avoid the patchable PAC opcodes from being |
| 79 | 79 | # generated triggers an issue with full LTO on Clang, which stops emitting PAC |
| 80 | −# instructions altogether. So instead, omit the unwind tables used by the | |
| 81 | −# patching code, so it will not be able to locate its own PAC instructions. | |
| 82 | −CFLAGS_patch-scs.o += -fno-asynchronous-unwind-tables -fno-unwind-tables | |
| 80 | +# instructions altogether. So disable LTO as well for the compilation unit. | |
| 81 | +CFLAGS_patch-scs.o += -mbranch-protection=none | |
| 82 | +CFLAGS_REMOVE_patch-scs.o += $(CC_FLAGS_LTO) | |
| 83 | 83 | |
| 84 | 84 | # Force dependency (vdso*-wrap.S includes vdso.so through incbin) |
| 85 | 85 | $(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so |
| @@ -127,9 +127,6 @@ obj-vdso := $(c-obj-vdso) $(c-obj-vdso-gettimeofday) $(asm-obj-vdso) · 126 unmodified lines | ||
| 127 | 127 | targets += vdso.lds |
| 128 | 128 | CPPFLAGS_vdso.lds += -P -C -U$(ARCH) |
| 129 | 129 | |
| 130 | −include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE | |
| 131 | − $(call if_changed,vdsosym) | |
| 132 | − | |
| 133 | 130 | # Strip rule for vdso.so |
| 134 | 131 | $(obj)/vdso.so: OBJCOPYFLAGS := -S |
| 135 | 132 | $(obj)/vdso.so: $(obj)/vdso32.so.dbg FORCE |
| @@ -166,9 +163,3 @@ quiet_cmd_vdsoas = AS32 $@ · 30 unmodified lines | ||
| 166 | 163 | |
| 167 | 164 | quiet_cmd_vdsomunge = MUNGE $@ |
| 168 | 165 | cmd_vdsomunge = $(obj)/$(munge) $< $@ |
| 169 | − | |
| 170 | −# Generate vDSO offsets using helper script (borrowed from the 64-bit vDSO) | |
| 171 | −gen-vdsosym := $(srctree)/$(src)/../vdso/gen_vdso_offsets.sh | |
| 172 | −quiet_cmd_vdsosym = VDSOSYM $@ | |
| 173 | −# The AArch64 nm should be able to read an AArch32 binary | |
| 174 | − cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ | |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | static __always_inline bool arch_static_branch(struct static_key *key, |
| 13 | 13 | bool branch) |
| 14 | 14 | { |
| 15 | − asm_volatile_goto( | |
| 15 | + asm goto( | |
| 16 | 16 | "1: nop32 \n" |
| 17 | 17 | " .pushsection __jump_table, \"aw\" \n" |
| 18 | 18 | " .align 2 \n" |
| @@ -29,7 +29,7 @@ label: · 10 unmodified lines | ||
| 29 | 29 | static __always_inline bool arch_static_branch_jump(struct static_key *key, |
| 30 | 30 | bool branch) |
| 31 | 31 | { |
| 32 | − asm_volatile_goto( | |
| 32 | + asm goto( | |
| 33 | 33 | "1: bsr32 %l[label] \n" |
| 34 | 34 | " .pushsection __jump_table, \"aw\" \n" |
| 35 | 35 | " .align 2 \n" |
| @@ -12,6 +12,7 @@ config LOONGARCH · 11 unmodified lines | ||
| 12 | 12 | select ARCH_DISABLE_KASAN_INLINE |
| 13 | 13 | select ARCH_ENABLE_MEMORY_HOTPLUG |
| 14 | 14 | select ARCH_ENABLE_MEMORY_HOTREMOVE |
| 15 | + select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE | |
| 15 | 16 | select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI |
| 16 | 17 | select ARCH_HAS_CPU_FINALIZE_INIT |
| 17 | 18 | select ARCH_HAS_FORTIFY_SOURCE |
| @@ -99,6 +100,7 @@ config LOONGARCH · 81 unmodified lines | ||
| 99 | 100 | select HAVE_ARCH_KFENCE |
| 100 | 101 | select HAVE_ARCH_KGDB if PERF_EVENTS |
| 101 | 102 | select HAVE_ARCH_MMAP_RND_BITS if MMU |
| 103 | + select HAVE_ARCH_SECCOMP | |
| 102 | 104 | select HAVE_ARCH_SECCOMP_FILTER |
| 103 | 105 | select HAVE_ARCH_TRACEHOOK |
| 104 | 106 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE |
| @@ -632,23 +634,6 @@ config RANDOMIZE_BASE_MAX_OFFSET · 527 unmodified lines | ||
| 632 | 634 | |
| 633 | 635 | This is limited by the size of the lower address memory, 256MB. |
| 634 | 636 | |
| 635 | −config SECCOMP | |
| 636 | − bool "Enable seccomp to safely compute untrusted bytecode" | |
| 637 | − depends on PROC_FS | |
| 638 | − default y | |
| 639 | − help | |
| 640 | − This kernel feature is useful for number crunching applications | |
| 641 | − that may need to compute untrusted bytecode during their | |
| 642 | − execution. By using pipes or other transports made available to | |
| 643 | − the process as file descriptors supporting the read/write | |
| 644 | − syscalls, it's possible to isolate those applications in | |
| 645 | − their own address space using seccomp. Once seccomp is | |
| 646 | − enabled via /proc/<pid>/seccomp, it cannot be disabled | |
| 647 | − and the task is only allowed to execute a few safe syscalls | |
| 648 | − defined by each seccomp mode. | |
| 649 | − | |
| 650 | − If unsure, say Y. Only embedded should say N here. | |
| 651 | − | |
| 652 | 637 | endmenu |
| 653 | 638 | |
| 654 | 639 | config ARCH_SELECT_MEMORY_MODEL |
| @@ -667,10 +652,6 @@ config ARCH_SPARSEMEM_ENABLE · 12 unmodified lines | ||
| 667 | 652 | or have huge holes in the physical address space for other reasons. |
| 668 | 653 | See <file:Documentation/mm/numa.rst> for more. |
| 669 | 654 | |
| 670 | −config ARCH_ENABLE_THP_MIGRATION | |
| 671 | − def_bool y | |
| 672 | − depends on TRANSPARENT_HUGEPAGE | |
| 673 | − | |
| 674 | 655 | config ARCH_MEMORY_PROBE |
| 675 | 656 | def_bool y |
| 676 | 657 | depends on MEMORY_HOTPLUG |
| @@ -32,8 +32,10 @@ static inline bool acpi_has_cpu_in_madt(void) · 31 unmodified lines | ||
| 32 | 32 | return true; |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | +#define MAX_CORE_PIC 256 | |
| 36 | + | |
| 35 | 37 | extern struct list_head acpi_wakeup_device_list; |
| 36 | −extern struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; | |
| 38 | +extern struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC]; | |
| 37 | 39 | |
| 38 | 40 | extern int __init parse_acpi_topology(void); |
| 39 | 41 | |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) |
| 24 | 24 | { |
| 25 | − asm_volatile_goto( | |
| 25 | + asm goto( | |
| 26 | 26 | "1: nop \n\t" |
| 27 | 27 | JUMP_TABLE_ENTRY |
| 28 | 28 | : : "i"(&((char *)key)[branch]) : : l_yes); |
| @@ -35,7 +35,7 @@ l_yes: · 6 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch) |
| 37 | 37 | { |
| 38 | − asm_volatile_goto( | |
| 38 | + asm goto( | |
| 39 | 39 | "1: b %l[l_yes] \n\t" |
| 40 | 40 | JUMP_TABLE_ENTRY |
| 41 | 41 | : : "i"(&((char *)key)[branch]) : : l_yes); |
| @@ -60,7 +60,7 @@ int kvm_own_lsx(struct kvm_vcpu *vcpu); · 59 unmodified lines | ||
| 60 | 60 | void kvm_save_lsx(struct loongarch_fpu *fpu); |
| 61 | 61 | void kvm_restore_lsx(struct loongarch_fpu *fpu); |
| 62 | 62 | #else |
| 63 | −static inline int kvm_own_lsx(struct kvm_vcpu *vcpu) { } | |
| 63 | +static inline int kvm_own_lsx(struct kvm_vcpu *vcpu) { return -EINVAL; } | |
| 64 | 64 | static inline void kvm_save_lsx(struct loongarch_fpu *fpu) { } |
| 65 | 65 | static inline void kvm_restore_lsx(struct loongarch_fpu *fpu) { } |
| 66 | 66 | #endif |
| @@ -70,7 +70,7 @@ int kvm_own_lasx(struct kvm_vcpu *vcpu); · 3 unmodified lines | ||
| 70 | 70 | void kvm_save_lasx(struct loongarch_fpu *fpu); |
| 71 | 71 | void kvm_restore_lasx(struct loongarch_fpu *fpu); |
| 72 | 72 | #else |
| 73 | −static inline int kvm_own_lasx(struct kvm_vcpu *vcpu) { } | |
| 73 | +static inline int kvm_own_lasx(struct kvm_vcpu *vcpu) { return -EINVAL; } | |
| 74 | 74 | static inline void kvm_save_lasx(struct loongarch_fpu *fpu) { } |
| 75 | 75 | static inline void kvm_restore_lasx(struct loongarch_fpu *fpu) { } |
| 76 | 76 | #endif |
| @@ -29,11 +29,9 @@ int disabled_cpus; · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | u64 acpi_saved_sp; |
| 31 | 31 | |
| 32 | −#define MAX_CORE_PIC 256 | |
| 33 | − | |
| 34 | 32 | #define PREFIX "ACPI: " |
| 35 | 33 | |
| 36 | −struct acpi_madt_core_pic acpi_core_pic[NR_CPUS]; | |
| 34 | +struct acpi_madt_core_pic acpi_core_pic[MAX_CORE_PIC]; | |
| 37 | 35 | |
| 38 | 36 | void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) |
| 39 | 37 | { |
| @@ -509,7 +509,6 @@ asmlinkage void start_secondary(void) · 508 unmodified lines | ||
| 509 | 509 | sync_counter(); |
| 510 | 510 | cpu = raw_smp_processor_id(); |
| 511 | 511 | set_my_cpu_offset(per_cpu_offset(cpu)); |
| 512 | − rcutree_report_cpu_starting(cpu); | |
| 513 | 512 | |
| 514 | 513 | cpu_probe(); |
| 515 | 514 | constant_clockevent_init(); |
| @@ -675,7 +675,7 @@ static bool fault_supports_huge_mapping(struct kvm_memory_slot *memslot, · 674 unmodified lines | ||
| 675 | 675 | * |
| 676 | 676 | * There are several ways to safely use this helper: |
| 677 | 677 | * |
| 678 | − * - Check mmu_invalidate_retry_hva() after grabbing the mapping level, before | |
| 678 | + * - Check mmu_invalidate_retry_gfn() after grabbing the mapping level, before | |
| 679 | 679 | * consuming it. In this case, mmu_lock doesn't need to be held during the |
| 680 | 680 | * lookup, but it does need to be held while checking the MMU notifier. |
| 681 | 681 | * |
| @@ -855,7 +855,7 @@ retry: · 173 unmodified lines | ||
| 855 | 855 | |
| 856 | 856 | /* Check if an invalidation has taken place since we got pfn */ |
| 857 | 857 | spin_lock(&kvm->mmu_lock); |
| 858 | − if (mmu_invalidate_retry_hva(kvm, mmu_seq, hva)) { | |
| 858 | + if (mmu_invalidate_retry_gfn(kvm, mmu_seq, gfn)) { | |
| 859 | 859 | /* |
| 860 | 860 | * This can happen when mappings are changed asynchronously, but |
| 861 | 861 | * also synchronously if a COW is triggered by |
| @@ -44,6 +44,9 @@ void *kasan_mem_to_shadow(const void *addr) · 43 unmodified lines | ||
| 44 | 44 | unsigned long xrange = (maddr >> XRANGE_SHIFT) & 0xffff; |
| 45 | 45 | unsigned long offset = 0; |
| 46 | 46 | |
| 47 | + if (maddr >= FIXADDR_START) | |
| 48 | + return (void *)(kasan_early_shadow_page); | |
| 49 | + | |
| 47 | 50 | maddr &= XRANGE_SHADOW_MASK; |
| 48 | 51 | switch (xrange) { |
| 49 | 52 | case XKPRANGE_CC_SEG: |
| @@ -284,12 +284,16 @@ static void setup_tlb_handler(int cpu) · 283 unmodified lines | ||
| 284 | 284 | set_handler(EXCCODE_TLBNR * VECSIZE, handle_tlb_protect, VECSIZE); |
| 285 | 285 | set_handler(EXCCODE_TLBNX * VECSIZE, handle_tlb_protect, VECSIZE); |
| 286 | 286 | set_handler(EXCCODE_TLBPE * VECSIZE, handle_tlb_protect, VECSIZE); |
| 287 | − } | |
| 287 | + } else { | |
| 288 | + int vec_sz __maybe_unused; | |
| 289 | + void *addr __maybe_unused; | |
| 290 | + struct page *page __maybe_unused; | |
| 291 | + | |
| 292 | + /* Avoid lockdep warning */ | |
| 293 | + rcutree_report_cpu_starting(cpu); | |
| 294 | + | |
| 288 | 295 | #ifdef CONFIG_NUMA |
| 289 | − else { | |
| 290 | − void *addr; | |
| 291 | − struct page *page; | |
| 292 | − const int vec_sz = sizeof(exception_handlers); | |
| 296 | + vec_sz = sizeof(exception_handlers); | |
| 293 | 297 | |
| 294 | 298 | if (pcpu_handlers[cpu]) |
| 295 | 299 | return; |
| @@ -305,8 +309,8 @@ static void setup_tlb_handler(int cpu) · 9 unmodified lines | ||
| 305 | 309 | csr_write64(pcpu_handlers[cpu], LOONGARCH_CSR_EENTRY); |
| 306 | 310 | csr_write64(pcpu_handlers[cpu], LOONGARCH_CSR_MERRENTRY); |
| 307 | 311 | csr_write64(pcpu_handlers[cpu] + 80*VECSIZE, LOONGARCH_CSR_TLBRENTRY); |
| 308 | − } | |
| 309 | 312 | #endif |
| 313 | + } | |
| 310 | 314 | } |
| 311 | 315 | |
| 312 | 316 | void tlb_init(int cpu) |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | # Objects to go into the VDSO. |
| 3 | 3 | |
| 4 | 4 | KASAN_SANITIZE := n |
| 5 | +UBSAN_SANITIZE := n | |
| 5 | 6 | KCOV_INSTRUMENT := n |
| 6 | 7 | |
| 7 | 8 | # Include the generic Makefile to check the built vdso. |
| @@ -15,10 +15,10 @@ · 14 unmodified lines | ||
| 15 | 15 | KBUILD_DEFCONFIG := multi_defconfig |
| 16 | 16 | |
| 17 | 17 | ifdef cross_compiling |
| 18 | − ifeq ($(CROSS_COMPILE),) | |
| 18 | + ifeq ($(CROSS_COMPILE),) | |
| 19 | 19 | CROSS_COMPILE := $(call cc-cross-prefix, \ |
| 20 | 20 | m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-) |
| 21 | − endif | |
| 21 | + endif | |
| 22 | 22 | endif |
| 23 | 23 | |
| 24 | 24 | # |
| @@ -40,6 +40,7 @@ · 39 unmodified lines | ||
| 40 | 40 | #include <linux/string.h> |
| 41 | 41 | |
| 42 | 42 | #include <asm/bootinfo.h> |
| 43 | +#include <prom.h> | |
| 43 | 44 | |
| 44 | 45 | int prom_argc; |
| 45 | 46 | char **prom_argv; |
| @@ -30,13 +30,11 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/mm.h> |
| 31 | 31 | #include <linux/dma-map-ops.h> /* for dma_default_coherent */ |
| 32 | 32 | |
| 33 | +#include <asm/bootinfo.h> | |
| 33 | 34 | #include <asm/mipsregs.h> |
| 34 | 35 | |
| 35 | 36 | #include <au1000.h> |
| 36 | 37 | |
| 37 | −extern void __init board_setup(void); | |
| 38 | −extern void __init alchemy_set_lpj(void); | |
| 39 | − | |
| 40 | 38 | static bool alchemy_dma_coherent(void) |
| 41 | 39 | { |
| 42 | 40 | switch (alchemy_get_cputype()) { |
| @@ -702,7 +702,7 @@ static struct ssb_sprom bcm63xx_sprom = { · 701 unmodified lines | ||
| 702 | 702 | .boardflags_hi = 0x0000, |
| 703 | 703 | }; |
| 704 | 704 | |
| 705 | −int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) | |
| 705 | +static int bcm63xx_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) | |
| 706 | 706 | { |
| 707 | 707 | if (bus->bustype == SSB_BUSTYPE_PCI) { |
| 708 | 708 | memcpy(out, &bcm63xx_sprom, sizeof(struct ssb_sprom)); |
| @@ -26,7 +26,7 @@ static struct platform_device bcm63xx_rng_device = { · 25 unmodified lines | ||
| 26 | 26 | .resource = rng_resources, |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | −int __init bcm63xx_rng_register(void) | |
| 29 | +static int __init bcm63xx_rng_register(void) | |
| 30 | 30 | { |
| 31 | 31 | if (!BCMCPU_IS_6368()) |
| 32 | 32 | return -ENODEV; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/kernel.h> |
| 11 | 11 | #include <linux/platform_device.h> |
| 12 | 12 | #include <bcm63xx_cpu.h> |
| 13 | +#include <bcm63xx_dev_uart.h> | |
| 13 | 14 | |
| 14 | 15 | static struct resource uart0_resources[] = { |
| 15 | 16 | { |
| @@ -34,7 +34,7 @@ static struct platform_device bcm63xx_wdt_device = { · 33 unmodified lines | ||
| 34 | 34 | }, |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | −int __init bcm63xx_wdt_register(void) | |
| 37 | +static int __init bcm63xx_wdt_register(void) | |
| 38 | 38 | { |
| 39 | 39 | wdt_resources[0].start = bcm63xx_regset_address(RSET_WDT); |
| 40 | 40 | wdt_resources[0].end = wdt_resources[0].start; |
| @@ -72,7 +72,7 @@ static inline int enable_irq_for_cpu(int cpu, struct irq_data *d, · 71 unmodified lines | ||
| 72 | 72 | */ |
| 73 | 73 | |
| 74 | 74 | #define BUILD_IPIC_INTERNAL(width) \ |
| 75 | −void __dispatch_internal_##width(int cpu) \ | |
| 75 | +static void __dispatch_internal_##width(int cpu) \ | |
| 76 | 76 | { \ |
| 77 | 77 | u32 pending[width / 32]; \ |
| 78 | 78 | unsigned int src, tgt; \ |
| @@ -159,7 +159,7 @@ void __init plat_mem_setup(void) · 158 unmodified lines | ||
| 159 | 159 | board_setup(); |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | −int __init bcm63xx_register_devices(void) | |
| 162 | +static int __init bcm63xx_register_devices(void) | |
| 163 | 163 | { |
| 164 | 164 | /* register gpiochip */ |
| 165 | 165 | bcm63xx_gpio_init(); |
| @@ -178,7 +178,7 @@ int bcm63xx_timer_set(int id, int monotonic, unsigned int countdown_us) · 177 unmodified lines | ||
| 178 | 178 | |
| 179 | 179 | EXPORT_SYMBOL(bcm63xx_timer_set); |
| 180 | 180 | |
| 181 | −int bcm63xx_timer_init(void) | |
| 181 | +static int bcm63xx_timer_init(void) | |
| 182 | 182 | { |
| 183 | 183 | int ret, irq; |
| 184 | 184 | u32 reg; |
| @@ -23,9 +23,6 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | #include <cobalt.h> |
| 25 | 25 | |
| 26 | −extern void cobalt_machine_restart(char *command); | |
| 27 | −extern void cobalt_machine_halt(void); | |
| 28 | − | |
| 29 | 26 | const char *get_system_type(void) |
| 30 | 27 | { |
| 31 | 28 | switch (cobalt_board_id) { |
| @@ -37,7 +37,7 @@ static unsigned int nr_prom_mem __initdata; · 36 unmodified lines | ||
| 37 | 37 | */ |
| 38 | 38 | #define ARC_PAGE_SHIFT 12 |
| 39 | 39 | |
| 40 | −struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) | |
| 40 | +static struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) | |
| 41 | 41 | { |
| 42 | 42 | return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current); |
| 43 | 43 | } |
| @@ -39,7 +39,7 @@ extern void jump_label_apply_nops(struct module *mod); · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 41 | 41 | { |
| 42 | − asm_volatile_goto("1:\t" B_INSN " 2f\n\t" | |
| 42 | + asm goto("1:\t" B_INSN " 2f\n\t" | |
| 43 | 43 | "2:\t.insn\n\t" |
| 44 | 44 | ".pushsection __jump_table, \"aw\"\n\t" |
| 45 | 45 | WORD_INSN " 1b, %l[l_yes], %0\n\t" |
| @@ -53,7 +53,7 @@ l_yes: · 7 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 55 | 55 | { |
| 56 | − asm_volatile_goto("1:\t" J_INSN " %l[l_yes]\n\t" | |
| 56 | + asm goto("1:\t" J_INSN " %l[l_yes]\n\t" | |
| 57 | 57 | ".pushsection __jump_table, \"aw\"\n\t" |
| 58 | 58 | WORD_INSN " 1b, %l[l_yes], %0\n\t" |
| 59 | 59 | ".popsection\n\t" |
| @@ -597,6 +597,9 @@ · 596 unmodified lines | ||
| 597 | 597 | |
| 598 | 598 | #include <asm/cpu.h> |
| 599 | 599 | |
| 600 | +void alchemy_set_lpj(void); | |
| 601 | +void board_setup(void); | |
| 602 | + | |
| 600 | 603 | /* helpers to access the SYS_* registers */ |
| 601 | 604 | static inline unsigned long alchemy_rdsys(int regofs) |
| 602 | 605 | { |
| @@ -19,4 +19,7 @@ extern int cobalt_board_id; · 18 unmodified lines | ||
| 19 | 19 | #define COBALT_BRD_ID_QUBE2 0x5 |
| 20 | 20 | #define COBALT_BRD_ID_RAQ2 0x6 |
| 21 | 21 | |
| 22 | +void cobalt_machine_halt(void); | |
| 23 | +void cobalt_machine_restart(char *command); | |
| 24 | + | |
| 22 | 25 | #endif /* __ASM_COBALT_H */ |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | #include <asm/cpu-features.h> |
| 13 | 13 | #include <asm/cpu-info.h> |
| 14 | +#include <asm/fpu.h> | |
| 14 | 15 | |
| 15 | 16 | #ifdef CONFIG_MIPS_FP_SUPPORT |
| 16 | 17 | |
| @@ -309,6 +310,11 @@ void mips_set_personality_nan(struct arch_elf_state *state) · 292 unmodified lines | ||
| 309 | 310 | struct cpuinfo_mips *c = &boot_cpu_data; |
| 310 | 311 | struct task_struct *t = current; |
| 311 | 312 | |
| 313 | + /* Do this early so t->thread.fpu.fcr31 won't be clobbered in case | |
| 314 | + * we are preempted before the lose_fpu(0) in start_thread. | |
| 315 | + */ | |
| 316 | + lose_fpu(0); | |
| 317 | + | |
| 312 | 318 | t->thread.fpu.fcr31 = c->fpu_csr31; |
| 313 | 319 | switch (state->nan_2008) { |
| 314 | 320 | case 0: |
| @@ -2007,7 +2007,13 @@ unsigned long vi_handlers[64]; · 2006 unmodified lines | ||
| 2007 | 2007 | |
| 2008 | 2008 | void reserve_exception_space(phys_addr_t addr, unsigned long size) |
| 2009 | 2009 | { |
| 2010 | − memblock_reserve(addr, size); | |
| 2010 | + /* | |
| 2011 | + * reserve exception space on CPUs other than CPU0 | |
| 2012 | + * is too late, since memblock is unavailable when APs | |
| 2013 | + * up | |
| 2014 | + */ | |
| 2015 | + if (smp_processor_id() == 0) | |
| 2016 | + memblock_reserve(addr, size); | |
| 2011 | 2017 | } |
| 2012 | 2018 | |
| 2013 | 2019 | void __init *set_except_vector(int n, void *addr) |
| @@ -108,10 +108,9 @@ void __init prom_init(void) · 107 unmodified lines | ||
| 108 | 108 | prom_init_cmdline(); |
| 109 | 109 | |
| 110 | 110 | #if defined(CONFIG_MIPS_MT_SMP) |
| 111 | − if (cpu_has_mipsmt) { | |
| 112 | − lantiq_smp_ops = vsmp_smp_ops; | |
| 111 | + lantiq_smp_ops = vsmp_smp_ops; | |
| 112 | + if (cpu_has_mipsmt) | |
| 113 | 113 | lantiq_smp_ops.init_secondary = lantiq_init_secondary; |
| 114 | − register_smp_ops(&lantiq_smp_ops); | |
| 115 | − } | |
| 114 | + register_smp_ops(&lantiq_smp_ops); | |
| 116 | 115 | #endif |
| 117 | 116 | } |
| @@ -103,6 +103,9 @@ void __init szmem(unsigned int node) · 102 unmodified lines | ||
| 103 | 103 | if (loongson_sysconf.vgabios_addr) |
| 104 | 104 | memblock_reserve(virt_to_phys((void *)loongson_sysconf.vgabios_addr), |
| 105 | 105 | SZ_256K); |
| 106 | + /* set nid for reserved memory */ | |
| 107 | + memblock_set_node((u64)node << 44, (u64)(node + 1) << 44, | |
| 108 | + &memblock.reserved, node); | |
| 106 | 109 | } |
| 107 | 110 | |
| 108 | 111 | #ifndef CONFIG_NUMA |
| @@ -132,6 +132,8 @@ static void __init node_mem_init(unsigned int node) · 131 unmodified lines | ||
| 132 | 132 | |
| 133 | 133 | /* Reserve pfn range 0~node[0]->node_start_pfn */ |
| 134 | 134 | memblock_reserve(0, PAGE_SIZE * start_pfn); |
| 135 | + /* set nid for reserved memory on node 0 */ | |
| 136 | + memblock_set_node(0, 1ULL << 44, &memblock.reserved, 0); | |
| 135 | 137 | } |
| 136 | 138 | } |
| 137 | 139 | |
| @@ -5,7 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o \ |
| 7 | 7 | ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o \ |
| 8 | − ip27-hubio.o ip27-xtalk.o | |
| 8 | + ip27-xtalk.o | |
| 9 | 9 | |
| 10 | 10 | obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o |
| 11 | 11 | obj-$(CONFIG_SMP) += ip27-smp.o |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | #include <asm/traps.h> |
| 23 | 23 | #include <linux/uaccess.h> |
| 24 | 24 | |
| 25 | +#include "ip27-common.h" | |
| 26 | + | |
| 25 | 27 | static void dump_hub_information(unsigned long errst0, unsigned long errst1) |
| 26 | 28 | { |
| 27 | 29 | static char *err_type[2][8] = { |
| @@ -57,7 +59,7 @@ static void dump_hub_information(unsigned long errst0, unsigned long errst1) · 29 unmodified lines | ||
| 57 | 59 | [st0.pi_stat0_fmt.s0_err_type] ? : "invalid"); |
| 58 | 60 | } |
| 59 | 61 | |
| 60 | −int ip27_be_handler(struct pt_regs *regs, int is_fixup) | |
| 62 | +static int ip27_be_handler(struct pt_regs *regs, int is_fixup) | |
| 61 | 63 | { |
| 62 | 64 | unsigned long errst0, errst1; |
| 63 | 65 | int data = regs->cp0_cause & 4; |
| @@ -10,6 +10,7 @@ extern void hub_rt_clock_event_init(void); · 9 unmodified lines | ||
| 10 | 10 | extern void hub_rtc_init(nasid_t nasid); |
| 11 | 11 | extern void install_cpu_nmi_handler(int slice); |
| 12 | 12 | extern void install_ipi(void); |
| 13 | +extern void ip27_be_init(void); | |
| 13 | 14 | extern void ip27_reboot_setup(void); |
| 14 | 15 | extern const struct plat_smp_ops ip27_smp_ops; |
| 15 | 16 | extern unsigned long node_getfirstfree(nasid_t nasid); |
| @@ -17,4 +18,5 @@ extern void per_cpu_init(void); · 1 unmodified line | ||
| 17 | 18 | extern void replicate_kernel_text(void); |
| 18 | 19 | extern void setup_replication_mask(void); |
| 19 | 20 | |
| 21 | + | |
| 20 | 22 | #endif /* __IP27_COMMON_H */ |
| @@ -1,185 +0,0 @@ | ||
| 1 | −// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | −/* | |
| 3 | − * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. | |
| 4 | − * Copyright (C) 2004 Christoph Hellwig. | |
| 5 | − * | |
| 6 | − * Support functions for the HUB ASIC - mostly PIO mapping related. | |
| 7 | − */ | |
| 8 | − | |
| 9 | −#include <linux/bitops.h> | |
| 10 | −#include <linux/string.h> | |
| 11 | −#include <linux/mmzone.h> | |
| 12 | −#include <asm/sn/addrs.h> | |
| 13 | −#include <asm/sn/arch.h> | |
| 14 | −#include <asm/sn/agent.h> | |
| 15 | −#include <asm/sn/io.h> | |
| 16 | −#include <asm/xtalk/xtalk.h> | |
| 17 | − | |
| 18 | − | |
| 19 | −static int force_fire_and_forget = 1; | |
| 20 | − | |
| 21 | −/** | |
| 22 | − * hub_pio_map - establish a HUB PIO mapping | |
| 23 | − * | |
| 24 | − * @nasid: nasid to perform PIO mapping on | |
| 25 | − * @widget: widget ID to perform PIO mapping for | |
| 26 | − * @xtalk_addr: xtalk_address that needs to be mapped | |
| 27 | − * @size: size of the PIO mapping | |
| 28 | − * | |
| 29 | − **/ | |
| 30 | −unsigned long hub_pio_map(nasid_t nasid, xwidgetnum_t widget, | |
| 31 | − unsigned long xtalk_addr, size_t size) | |
| 32 | −{ | |
| 33 | − unsigned i; | |
| 34 | − | |
| 35 | − /* use small-window mapping if possible */ | |
| 36 | − if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE) | |
| 37 | − return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE); | |
| 38 | − | |
| 39 | − if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) { | |
| 40 | − printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx" | |
| 41 | − " too big (%ld)\n", | |
| 42 | − nasid, widget, xtalk_addr, size); | |
| 43 | − return 0; | |
| 44 | − } | |
| 45 | − | |
| 46 | − xtalk_addr &= ~(BWIN_SIZE-1); | |
| 47 | − for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) { | |
| 48 | − if (test_and_set_bit(i, hub_data(nasid)->h_bigwin_used)) | |
| 49 | − continue; | |
| 50 | − | |
| 51 | − /* | |
| 52 | − * The code below does a PIO write to setup an ITTE entry. | |
| 53 | − * | |
| 54 | − * We need to prevent other CPUs from seeing our updated | |
| 55 | − * memory shadow of the ITTE (in the piomap) until the ITTE | |
| 56 | − * entry is actually set up; otherwise, another CPU might | |
| 57 | − * attempt a PIO prematurely. | |
| 58 | − * | |
| 59 | − * Also, the only way we can know that an entry has been | |
| 60 | − * received by the hub and can be used by future PIO reads/ | |
| 61 | − * writes is by reading back the ITTE entry after writing it. | |
| 62 | − * | |
| 63 | − * For these two reasons, we PIO read back the ITTE entry | |
| 64 | − * after we write it. | |
| 65 | − */ | |
| 66 | − IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr); | |
| 67 | − __raw_readq(IIO_ITTE_GET(nasid, i)); | |
| 68 | − | |
| 69 | − return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE); | |
| 70 | − } | |
| 71 | − | |
| 72 | − printk(KERN_WARNING "unable to establish PIO mapping for at" | |
| 73 | − " hub %d widget %d addr 0x%lx\n", | |
| 74 | − nasid, widget, xtalk_addr); | |
| 75 | − return 0; | |
| 76 | −} | |
| 77 | − | |
| 78 | − | |
| 79 | −/* | |
| 80 | − * hub_setup_prb(nasid, prbnum, credits, conveyor) | |
| 81 | − * | |
| 82 | − * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, | |
| 83 | − * put it into conveyor belt mode with the specified number of credits. | |
| 84 | − */ | |
| 85 | −static void hub_setup_prb(nasid_t nasid, int prbnum, int credits) | |
| 86 | −{ | |
| 87 | − union iprb_u prb; | |
| 88 | − int prb_offset; | |
| 89 | − | |
| 90 | − /* | |
| 91 | − * Get the current register value. | |
| 92 | − */ | |
| 93 | − prb_offset = IIO_IOPRB(prbnum); | |
| 94 | − prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset); | |
| 95 | − | |
| 96 | − /* | |
| 97 | − * Clear out some fields. | |
| 98 | − */ | |
| 99 | − prb.iprb_ovflow = 1; | |
| 100 | − prb.iprb_bnakctr = 0; | |
| 101 | − prb.iprb_anakctr = 0; | |
| 102 | − | |
| 103 | − /* | |
| 104 | − * Enable or disable fire-and-forget mode. | |
| 105 | − */ | |
| 106 | − prb.iprb_ff = force_fire_and_forget ? 1 : 0; | |
| 107 | − | |
| 108 | − /* | |
| 109 | − * Set the appropriate number of PIO credits for the widget. | |
| 110 | − */ | |
| 111 | − prb.iprb_xtalkctr = credits; | |
| 112 | − | |
| 113 | − /* | |
| 114 | − * Store the new value to the register. | |
| 115 | − */ | |
| 116 | − REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval); | |
| 117 | −} | |
| 118 | − | |
| 119 | −/** | |
| 120 | − * hub_set_piomode - set pio mode for a given hub | |
| 121 | − * | |
| 122 | − * @nasid: physical node ID for the hub in question | |
| 123 | − * | |
| 124 | − * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" mode. | |
| 125 | − * To do this, we have to make absolutely sure that no PIOs are in progress | |
| 126 | − * so we turn off access to all widgets for the duration of the function. | |
| 127 | − * | |
| 128 | − * XXX - This code should really check what kind of widget we're talking | |
| 129 | − * to. Bridges can only handle three requests, but XG will do more. | |
| 130 | − * How many can crossbow handle to widget 0? We're assuming 1. | |
| 131 | − * | |
| 132 | − * XXX - There is a bug in the crossbow that link reset PIOs do not | |
| 133 | − * return write responses. The easiest solution to this problem is to | |
| 134 | − * leave widget 0 (xbow) in fire-and-forget mode at all times. This | |
| 135 | − * only affects pio's to xbow registers, which should be rare. | |
| 136 | − **/ | |
| 137 | −static void hub_set_piomode(nasid_t nasid) | |
| 138 | −{ | |
| 139 | − u64 ii_iowa; | |
| 140 | − union hubii_wcr_u ii_wcr; | |
| 141 | − unsigned i; | |
| 142 | − | |
| 143 | − ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS); | |
| 144 | − REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0); | |
| 145 | − | |
| 146 | − ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR); | |
| 147 | − | |
| 148 | − if (ii_wcr.iwcr_dir_con) { | |
| 149 | − /* | |
| 150 | − * Assume a bridge here. | |
| 151 | − */ | |
| 152 | − hub_setup_prb(nasid, 0, 3); | |
| 153 | − } else { | |
| 154 | − /* | |
| 155 | − * Assume a crossbow here. | |
| 156 | − */ | |
| 157 | − hub_setup_prb(nasid, 0, 1); | |
| 158 | − } | |
| 159 | − | |
| 160 | − /* | |
| 161 | − * XXX - Here's where we should take the widget type into | |
| 162 | − * when account assigning credits. | |
| 163 | − */ | |
| 164 | − for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) | |
| 165 | − hub_setup_prb(nasid, i, 3); | |
| 166 | − | |
| 167 | − REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa); | |
| 168 | −} | |
| 169 | − | |
| 170 | −/* | |
| 171 | − * hub_pio_init - PIO-related hub initialization | |
| 172 | − * | |
| 173 | − * @hub: hubinfo structure for our hub | |
| 174 | − */ | |
| 175 | −void hub_pio_init(nasid_t nasid) | |
| 176 | −{ | |
| 177 | − unsigned i; | |
| 178 | − | |
| 179 | − /* initialize big window piomaps for this hub */ | |
| 180 | − bitmap_zero(hub_data(nasid)->h_bigwin_used, HUB_NUM_BIG_WINDOW); | |
| 181 | − for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) | |
| 182 | − IIO_ITTE_DISABLE(nasid, i); | |
| 183 | − | |
| 184 | − hub_set_piomode(nasid); | |
| 185 | −} | |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <asm/sn/intr.h> |
| 24 | 24 | #include <asm/sn/irq_alloc.h> |
| 25 | 25 | |
| 26 | +#include "ip27-common.h" | |
| 27 | + | |
| 26 | 28 | struct hub_irq_data { |
| 27 | 29 | u64 *irq_mask[2]; |
| 28 | 30 | cpuid_t cpu; |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <asm/page.h> |
| 24 | 24 | #include <asm/pgalloc.h> |
| 25 | 25 | #include <asm/sections.h> |
| 26 | +#include <asm/sgialib.h> | |
| 26 | 27 | |
| 27 | 28 | #include <asm/sn/arch.h> |
| 28 | 29 | #include <asm/sn/agent.h> |
| @@ -11,6 +11,8 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <asm/sn/arch.h> |
| 12 | 12 | #include <asm/sn/agent.h> |
| 13 | 13 | |
| 14 | +#include "ip27-common.h" | |
| 15 | + | |
| 14 | 16 | #if 0 |
| 15 | 17 | #define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n) |
| 16 | 18 | #else |
| @@ -23,16 +25,7 @@ · 6 unmodified lines | ||
| 23 | 25 | typedef unsigned long machreg_t; |
| 24 | 26 | |
| 25 | 27 | static arch_spinlock_t nmi_lock = __ARCH_SPIN_LOCK_UNLOCKED; |
| 26 | − | |
| 27 | −/* | |
| 28 | − * Let's see what else we need to do here. Set up sp, gp? | |
| 29 | − */ | |
| 30 | −void nmi_dump(void) | |
| 31 | −{ | |
| 32 | − void cont_nmi_dump(void); | |
| 33 | − | |
| 34 | − cont_nmi_dump(); | |
| 35 | −} | |
| 28 | +static void nmi_dump(void); | |
| 36 | 29 | |
| 37 | 30 | void install_cpu_nmi_handler(int slice) |
| 38 | 31 | { |
| @@ -53,7 +46,7 @@ void install_cpu_nmi_handler(int slice) · 14 unmodified lines | ||
| 53 | 46 | * into the eframe format for the node under consideration. |
| 54 | 47 | */ |
| 55 | 48 | |
| 56 | −void nmi_cpu_eframe_save(nasid_t nasid, int slice) | |
| 49 | +static void nmi_cpu_eframe_save(nasid_t nasid, int slice) | |
| 57 | 50 | { |
| 58 | 51 | struct reg_struct *nr; |
| 59 | 52 | int i; |
| @@ -129,7 +122,7 @@ void nmi_cpu_eframe_save(nasid_t nasid, int slice) · 69 unmodified lines | ||
| 129 | 122 | pr_emerg("\n"); |
| 130 | 123 | } |
| 131 | 124 | |
| 132 | −void nmi_dump_hub_irq(nasid_t nasid, int slice) | |
| 125 | +static void nmi_dump_hub_irq(nasid_t nasid, int slice) | |
| 133 | 126 | { |
| 134 | 127 | u64 mask0, mask1, pend0, pend1; |
| 135 | 128 | |
| @@ -153,7 +146,7 @@ void nmi_dump_hub_irq(nasid_t nasid, int slice) · 17 unmodified lines | ||
| 153 | 146 | * Copy the cpu registers which have been saved in the IP27prom format |
| 154 | 147 | * into the eframe format for the node under consideration. |
| 155 | 148 | */ |
| 156 | −void nmi_node_eframe_save(nasid_t nasid) | |
| 149 | +static void nmi_node_eframe_save(nasid_t nasid) | |
| 157 | 150 | { |
| 158 | 151 | int slice; |
| 159 | 152 | |
| @@ -170,8 +163,7 @@ void nmi_node_eframe_save(nasid_t nasid) · 10 unmodified lines | ||
| 170 | 163 | /* |
| 171 | 164 | * Save the nmi cpu registers for all cpus in the system. |
| 172 | 165 | */ |
| 173 | −void | |
| 174 | −nmi_eframes_save(void) | |
| 166 | +static void nmi_eframes_save(void) | |
| 175 | 167 | { |
| 176 | 168 | nasid_t nasid; |
| 177 | 169 | |
| @@ -179,8 +171,7 @@ nmi_eframes_save(void) · 1 unmodified line | ||
| 179 | 171 | nmi_node_eframe_save(nasid); |
| 180 | 172 | } |
| 181 | 173 | |
| 182 | −void | |
| 183 | −cont_nmi_dump(void) | |
| 174 | +static void nmi_dump(void) | |
| 184 | 175 | { |
| 185 | 176 | #ifndef REAL_NMI_SIGNAL |
| 186 | 177 | static atomic_t nmied_cpus = ATOMIC_INIT(0); |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | #include <linux/io.h> |
| 4 | 4 | |
| 5 | 5 | #include <asm/sn/ioc3.h> |
| 6 | +#include <asm/setup.h> | |
| 6 | 7 | |
| 7 | 8 | static inline struct ioc3_uartregs *console_uart(void) |
| 8 | 9 | { |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/percpu.h> |
| 15 | 15 | #include <linux/memblock.h> |
| 16 | 16 | |
| 17 | +#include <asm/bootinfo.h> | |
| 17 | 18 | #include <asm/smp-ops.h> |
| 18 | 19 | #include <asm/sgialib.h> |
| 19 | 20 | #include <asm/time.h> |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <asm/ip32/crime.h> |
| 19 | 19 | #include <asm/ip32/mace.h> |
| 20 | 20 | |
| 21 | +#include "ip32-common.h" | |
| 22 | + | |
| 21 | 23 | struct sgi_crime __iomem *crime; |
| 22 | 24 | struct sgi_mace __iomem *mace; |
| 23 | 25 | |
| @@ -39,7 +41,7 @@ void __init crime_init(void) · 15 unmodified lines | ||
| 39 | 41 | id, rev, field, (unsigned long) CRIME_BASE); |
| 40 | 42 | } |
| 41 | 43 | |
| 42 | −irqreturn_t crime_memerr_intr(unsigned int irq, void *dev_id) | |
| 44 | +irqreturn_t crime_memerr_intr(int irq, void *dev_id) | |
| 43 | 45 | { |
| 44 | 46 | unsigned long stat, addr; |
| 45 | 47 | int fatal = 0; |
| @@ -90,7 +92,7 @@ irqreturn_t crime_memerr_intr(unsigned int irq, void *dev_id) · 44 unmodified lines | ||
| 90 | 92 | return IRQ_HANDLED; |
| 91 | 93 | } |
| 92 | 94 | |
| 93 | −irqreturn_t crime_cpuerr_intr(unsigned int irq, void *dev_id) | |
| 95 | +irqreturn_t crime_cpuerr_intr(int irq, void *dev_id) | |
| 94 | 96 | { |
| 95 | 97 | unsigned long stat = crime->cpu_error_stat & CRIME_CPU_ERROR_MASK; |
| 96 | 98 | unsigned long addr = crime->cpu_error_addr & CRIME_CPU_ERROR_ADDR_MASK; |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <asm/ptrace.h> |
| 19 | 19 | #include <asm/tlbdebug.h> |
| 20 | 20 | |
| 21 | +#include "ip32-common.h" | |
| 22 | + | |
| 21 | 23 | static int ip32_be_handler(struct pt_regs *regs, int is_fixup) |
| 22 | 24 | { |
| 23 | 25 | int data = regs->cp0_cause & 4; |
| @@ -0,0 +1,15 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | + | |
| 3 | +#ifndef __IP32_COMMON_H | |
| 4 | +#define __IP32_COMMON_H | |
| 5 | + | |
| 6 | +#include <linux/init.h> | |
| 7 | +#include <linux/interrupt.h> | |
| 8 | + | |
| 9 | +void __init crime_init(void); | |
| 10 | +irqreturn_t crime_memerr_intr(int irq, void *dev_id); | |
| 11 | +irqreturn_t crime_cpuerr_intr(int irq, void *dev_id); | |
| 12 | +void __init ip32_be_init(void); | |
| 13 | +void ip32_prepare_poweroff(void); | |
| 14 | + | |
| 15 | +#endif /* __IP32_COMMON_H */ | |
| @@ -28,6 +28,8 @@ · 27 unmodified lines | ||
| 28 | 28 | #include <asm/ip32/mace.h> |
| 29 | 29 | #include <asm/ip32/ip32_ints.h> |
| 30 | 30 | |
| 31 | +#include "ip32-common.h" | |
| 32 | + | |
| 31 | 33 | /* issue a PIO read to make sure no PIO writes are pending */ |
| 32 | 34 | static inline void flush_crime_bus(void) |
| 33 | 35 | { |
| @@ -107,10 +109,6 @@ static inline void flush_mace_bus(void) · 73 unmodified lines | ||
| 107 | 109 | * is quite different anyway. |
| 108 | 110 | */ |
| 109 | 111 | |
| 110 | −/* Some initial interrupts to set up */ | |
| 111 | −extern irqreturn_t crime_memerr_intr(int irq, void *dev_id); | |
| 112 | −extern irqreturn_t crime_cpuerr_intr(int irq, void *dev_id); | |
| 113 | − | |
| 114 | 112 | /* |
| 115 | 113 | * This is for pure CRIME interrupts - ie not MACE. The advantage? |
| 116 | 114 | * We get to split the register in half and do faster lookups. |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <asm/ip32/crime.h> |
| 16 | 16 | #include <asm/bootinfo.h> |
| 17 | 17 | #include <asm/page.h> |
| 18 | +#include <asm/sgialib.h> | |
| 18 | 19 | |
| 19 | 20 | extern void crime_init(void); |
| 20 | 21 | |
| @@ -29,6 +29,8 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <asm/ip32/crime.h> |
| 30 | 30 | #include <asm/ip32/ip32_ints.h> |
| 31 | 31 | |
| 32 | +#include "ip32-common.h" | |
| 33 | + | |
| 32 | 34 | #define POWERDOWN_TIMEOUT 120 |
| 33 | 35 | /* |
| 34 | 36 | * Blink frequency during reboot grace period and when panicked. |
| @@ -26,8 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <asm/ip32/mace.h> |
| 27 | 27 | #include <asm/ip32/ip32_ints.h> |
| 28 | 28 | |
| 29 | −extern void ip32_be_init(void); | |
| 30 | −extern void crime_init(void); | |
| 29 | +#include "ip32-common.h" | |
| 31 | 30 | |
| 32 | 31 | #ifdef CONFIG_SGI_O2MACE_ETH |
| 33 | 32 | /* |
| @@ -25,7 +25,6 @@ config PARISC · 24 unmodified lines | ||
| 25 | 25 | select RTC_DRV_GENERIC |
| 26 | 26 | select INIT_ALL_POSSIBLE |
| 27 | 27 | select BUG |
| 28 | − select BUILDTIME_TABLE_SORT | |
| 29 | 28 | select HAVE_KERNEL_UNCOMPRESSED |
| 30 | 29 | select HAVE_PCI |
| 31 | 30 | select HAVE_PERF_EVENTS |
| @@ -50,12 +50,12 @@ export CROSS32CC · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | # Set default cross compiler for kernel build |
| 52 | 52 | ifdef cross_compiling |
| 53 | − ifeq ($(CROSS_COMPILE),) | |
| 53 | + ifeq ($(CROSS_COMPILE),) | |
| 54 | 54 | CC_SUFFIXES = linux linux-gnu unknown-linux-gnu suse-linux |
| 55 | 55 | CROSS_COMPILE := $(call cc-cross-prefix, \ |
| 56 | 56 | $(foreach a,$(CC_ARCHES), \ |
| 57 | 57 | $(foreach s,$(CC_SUFFIXES),$(a)-$(s)-))) |
| 58 | − endif | |
| 58 | + endif | |
| 59 | 59 | endif |
| 60 | 60 | |
| 61 | 61 | ifdef CONFIG_DYNAMIC_FTRACE |
| @@ -576,6 +576,7 @@ · 575 unmodified lines | ||
| 576 | 576 | .section __ex_table,"aw" ! \ |
| 577 | 577 | .align 4 ! \ |
| 578 | 578 | .word (fault_addr - .), (except_addr - .) ! \ |
| 579 | + or %r0,%r0,%r0 ! \ | |
| 579 | 580 | .previous |
| 580 | 581 | |
| 581 | 582 | |
| @@ -0,0 +1,64 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +#ifndef __PARISC_EXTABLE_H | |
| 3 | +#define __PARISC_EXTABLE_H | |
| 4 | + | |
| 5 | +#include <asm/ptrace.h> | |
| 6 | +#include <linux/compiler.h> | |
| 7 | + | |
| 8 | +/* | |
| 9 | + * The exception table consists of three addresses: | |
| 10 | + * | |
| 11 | + * - A relative address to the instruction that is allowed to fault. | |
| 12 | + * - A relative address at which the program should continue (fixup routine) | |
| 13 | + * - An asm statement which specifies which CPU register will | |
| 14 | + * receive -EFAULT when an exception happens if the lowest bit in | |
| 15 | + * the fixup address is set. | |
| 16 | + * | |
| 17 | + * Note: The register specified in the err_opcode instruction will be | |
| 18 | + * modified at runtime if a fault happens. Register %r0 will be ignored. | |
| 19 | + * | |
| 20 | + * Since relative addresses are used, 32bit values are sufficient even on | |
| 21 | + * 64bit kernel. | |
| 22 | + */ | |
| 23 | + | |
| 24 | +struct pt_regs; | |
| 25 | +int fixup_exception(struct pt_regs *regs); | |
| 26 | + | |
| 27 | +#define ARCH_HAS_RELATIVE_EXTABLE | |
| 28 | +struct exception_table_entry { | |
| 29 | + int insn; /* relative address of insn that is allowed to fault. */ | |
| 30 | + int fixup; /* relative address of fixup routine */ | |
| 31 | + int err_opcode; /* sample opcode with register which holds error code */ | |
| 32 | +}; | |
| 33 | + | |
| 34 | +#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr, opcode )\ | |
| 35 | + ".section __ex_table,\"aw\"\n" \ | |
| 36 | + ".align 4\n" \ | |
| 37 | + ".word (" #fault_addr " - .), (" #except_addr " - .)\n" \ | |
| 38 | + opcode "\n" \ | |
| 39 | + ".previous\n" | |
| 40 | + | |
| 41 | +/* | |
| 42 | + * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry | |
| 43 | + * (with lowest bit set) for which the fault handler in fixup_exception() will | |
| 44 | + * load -EFAULT on fault into the register specified by the err_opcode instruction, | |
| 45 | + * and zeroes the target register in case of a read fault in get_user(). | |
| 46 | + */ | |
| 47 | +#define ASM_EXCEPTIONTABLE_VAR(__err_var) \ | |
| 48 | + int __err_var = 0 | |
| 49 | +#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr, register )\ | |
| 50 | + ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1, "or %%r0,%%r0," register) | |
| 51 | + | |
| 52 | +static inline void swap_ex_entry_fixup(struct exception_table_entry *a, | |
| 53 | + struct exception_table_entry *b, | |
| 54 | + struct exception_table_entry tmp, | |
| 55 | + int delta) | |
| 56 | +{ | |
| 57 | + a->fixup = b->fixup + delta; | |
| 58 | + b->fixup = tmp.fixup - delta; | |
| 59 | + a->err_opcode = b->err_opcode; | |
| 60 | + b->err_opcode = tmp.err_opcode; | |
| 61 | +} | |
| 62 | +#define swap_ex_entry_fixup swap_ex_entry_fixup | |
| 63 | + | |
| 64 | +#endif | |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 14 | 14 | { |
| 15 | − asm_volatile_goto("1:\n\t" | |
| 15 | + asm goto("1:\n\t" | |
| 16 | 16 | "nop\n\t" |
| 17 | 17 | ".pushsection __jump_table, \"aw\"\n\t" |
| 18 | 18 | ".align %1\n\t" |
| @@ -29,7 +29,7 @@ l_yes: · 10 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 31 | 31 | { |
| 32 | − asm_volatile_goto("1:\n\t" | |
| 32 | + asm goto("1:\n\t" | |
| 33 | 33 | "b,n %l[l_yes]\n\t" |
| 34 | 34 | ".pushsection __jump_table, \"aw\"\n\t" |
| 35 | 35 | ".align %1\n\t" |
| @@ -8,7 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | "copy %%r0,%0\n" \ |
| 9 | 9 | "8:\tlpa %%r0(%1),%0\n" \ |
| 10 | 10 | "9:\n" \ |
| 11 | − ASM_EXCEPTIONTABLE_ENTRY(8b, 9b) \ | |
| 11 | + ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \ | |
| 12 | + "or %%r0,%%r0,%%r0") \ | |
| 12 | 13 | : "=&r" (pa) \ |
| 13 | 14 | : "r" (va) \ |
| 14 | 15 | : "memory" \ |
| @@ -22,7 +23,8 @@ · 7 unmodified lines | ||
| 22 | 23 | "copy %%r0,%0\n" \ |
| 23 | 24 | "8:\tlpa %%r0(%%sr3,%1),%0\n" \ |
| 24 | 25 | "9:\n" \ |
| 25 | − ASM_EXCEPTIONTABLE_ENTRY(8b, 9b) \ | |
| 26 | + ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \ | |
| 27 | + "or %%r0,%%r0,%%r0") \ | |
| 26 | 28 | : "=&r" (pa) \ |
| 27 | 29 | : "r" (va) \ |
| 28 | 30 | : "memory" \ |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | */ |
| 8 | 8 | #include <asm/page.h> |
| 9 | 9 | #include <asm/cache.h> |
| 10 | +#include <asm/extable.h> | |
| 10 | 11 | |
| 11 | 12 | #include <linux/bug.h> |
| 12 | 13 | #include <linux/string.h> |
| @@ -26,37 +27,6 @@ · 13 unmodified lines | ||
| 26 | 27 | #define STD_USER(sr, x, ptr) __put_user_asm(sr, "std", x, ptr) |
| 27 | 28 | #endif |
| 28 | 29 | |
| 29 | −/* | |
| 30 | − * The exception table contains two values: the first is the relative offset to | |
| 31 | − * the address of the instruction that is allowed to fault, and the second is | |
| 32 | − * the relative offset to the address of the fixup routine. Since relative | |
| 33 | − * addresses are used, 32bit values are sufficient even on 64bit kernel. | |
| 34 | − */ | |
| 35 | − | |
| 36 | −#define ARCH_HAS_RELATIVE_EXTABLE | |
| 37 | −struct exception_table_entry { | |
| 38 | − int insn; /* relative address of insn that is allowed to fault. */ | |
| 39 | − int fixup; /* relative address of fixup routine */ | |
| 40 | −}; | |
| 41 | − | |
| 42 | −#define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\ | |
| 43 | − ".section __ex_table,\"aw\"\n" \ | |
| 44 | − ".align 4\n" \ | |
| 45 | − ".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \ | |
| 46 | − ".previous\n" | |
| 47 | − | |
| 48 | −/* | |
| 49 | − * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() creates a special exception table entry | |
| 50 | − * (with lowest bit set) for which the fault handler in fixup_exception() will | |
| 51 | − * load -EFAULT into %r29 for a read or write fault, and zeroes the target | |
| 52 | − * register in case of a read fault in get_user(). | |
| 53 | − */ | |
| 54 | −#define ASM_EXCEPTIONTABLE_REG 29 | |
| 55 | −#define ASM_EXCEPTIONTABLE_VAR(__variable) \ | |
| 56 | − register long __variable __asm__ ("r29") = 0 | |
| 57 | −#define ASM_EXCEPTIONTABLE_ENTRY_EFAULT( fault_addr, except_addr )\ | |
| 58 | − ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr + 1) | |
| 59 | − | |
| 60 | 30 | #define __get_user_internal(sr, val, ptr) \ |
| 61 | 31 | ({ \ |
| 62 | 32 | ASM_EXCEPTIONTABLE_VAR(__gu_err); \ |
| @@ -83,7 +53,7 @@ struct exception_table_entry { · 20 unmodified lines | ||
| 83 | 53 | \ |
| 84 | 54 | __asm__("1: " ldx " 0(%%sr%2,%3),%0\n" \ |
| 85 | 55 | "9:\n" \ |
| 86 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ | |
| 56 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%1") \ | |
| 87 | 57 | : "=r"(__gu_val), "+r"(__gu_err) \ |
| 88 | 58 | : "i"(sr), "r"(ptr)); \ |
| 89 | 59 | \ |
| @@ -115,8 +85,8 @@ struct exception_table_entry { · 25 unmodified lines | ||
| 115 | 85 | "1: ldw 0(%%sr%2,%3),%0\n" \ |
| 116 | 86 | "2: ldw 4(%%sr%2,%3),%R0\n" \ |
| 117 | 87 | "9:\n" \ |
| 118 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ | |
| 119 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \ | |
| 88 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%1") \ | |
| 89 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b, "%1") \ | |
| 120 | 90 | : "=&r"(__gu_tmp.l), "+r"(__gu_err) \ |
| 121 | 91 | : "i"(sr), "r"(ptr)); \ |
| 122 | 92 | \ |
| @@ -174,7 +144,7 @@ struct exception_table_entry { · 51 unmodified lines | ||
| 174 | 144 | __asm__ __volatile__ ( \ |
| 175 | 145 | "1: " stx " %1,0(%%sr%2,%3)\n" \ |
| 176 | 146 | "9:\n" \ |
| 177 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ | |
| 147 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%0") \ | |
| 178 | 148 | : "+r"(__pu_err) \ |
| 179 | 149 | : "r"(x), "i"(sr), "r"(ptr)) |
| 180 | 150 | |
| @@ -186,15 +156,14 @@ struct exception_table_entry { · 5 unmodified lines | ||
| 186 | 156 | "1: stw %1,0(%%sr%2,%3)\n" \ |
| 187 | 157 | "2: stw %R1,4(%%sr%2,%3)\n" \ |
| 188 | 158 | "9:\n" \ |
| 189 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b) \ | |
| 190 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b) \ | |
| 159 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 9b, "%0") \ | |
| 160 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 9b, "%0") \ | |
| 191 | 161 | : "+r"(__pu_err) \ |
| 192 | 162 | : "r"(__val), "i"(sr), "r"(ptr)); \ |
| 193 | 163 | } while (0) |
| 194 | 164 | |
| 195 | 165 | #endif /* !defined(CONFIG_64BIT) */ |
| 196 | 166 | |
| 197 | − | |
| 198 | 167 | /* |
| 199 | 168 | * Complex access routines -- external declarations |
| 200 | 169 | */ |
| @@ -216,7 +185,4 @@ unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src, · 15 unmodified lines | ||
| 216 | 185 | #define INLINE_COPY_TO_USER |
| 217 | 186 | #define INLINE_COPY_FROM_USER |
| 218 | 187 | |
| 219 | −struct pt_regs; | |
| 220 | −int fixup_exception(struct pt_regs *regs); | |
| 221 | − | |
| 222 | 188 | #endif /* __PARISC_UACCESS_H */ |
| @@ -58,7 +58,7 @@ int pa_serialize_tlb_flushes __ro_after_init; · 57 unmodified lines | ||
| 58 | 58 | |
| 59 | 59 | struct pdc_cache_info cache_info __ro_after_init; |
| 60 | 60 | #ifndef CONFIG_PA20 |
| 61 | −struct pdc_btlb_info btlb_info __ro_after_init; | |
| 61 | +struct pdc_btlb_info btlb_info; | |
| 62 | 62 | #endif |
| 63 | 63 | |
| 64 | 64 | DEFINE_STATIC_KEY_TRUE(parisc_has_cache); |
| @@ -264,6 +264,10 @@ parisc_cache_init(void) · 199 unmodified lines | ||
| 264 | 264 | icache_stride = CAFL_STRIDE(cache_info.ic_conf); |
| 265 | 265 | #undef CAFL_STRIDE |
| 266 | 266 | |
| 267 | + /* stride needs to be non-zero, otherwise cache flushes will not work */ | |
| 268 | + WARN_ON(cache_info.dc_size && dcache_stride == 0); | |
| 269 | + WARN_ON(cache_info.ic_size && icache_stride == 0); | |
| 270 | + | |
| 267 | 271 | if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == |
| 268 | 272 | PDC_MODEL_NVA_UNSUPPORTED) { |
| 269 | 273 | printk(KERN_WARNING "parisc_cache_init: Only equivalent aliasing supported!\n"); |
| @@ -850,7 +854,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, · 580 unmodified lines | ||
| 850 | 854 | #endif |
| 851 | 855 | " fic,m %3(%4,%0)\n" |
| 852 | 856 | "2: sync\n" |
| 853 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b) | |
| 857 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") | |
| 854 | 858 | : "+r" (start), "+r" (error) |
| 855 | 859 | : "r" (end), "r" (dcache_stride), "i" (SR_USER)); |
| 856 | 860 | } |
| @@ -865,7 +869,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, · 8 unmodified lines | ||
| 865 | 869 | #endif |
| 866 | 870 | " fdc,m %3(%4,%0)\n" |
| 867 | 871 | "2: sync\n" |
| 868 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b) | |
| 872 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") | |
| 869 | 873 | : "+r" (start), "+r" (error) |
| 870 | 874 | : "r" (end), "r" (icache_stride), "i" (SR_USER)); |
| 871 | 875 | } |
| @@ -742,7 +742,7 @@ parse_tree_node(struct device *parent, int index, struct hardware_path *modpath) · 741 unmodified lines | ||
| 742 | 742 | }; |
| 743 | 743 | |
| 744 | 744 | if (device_for_each_child(parent, &recurse_data, descend_children)) |
| 745 | − { /* nothing */ }; | |
| 745 | + { /* nothing */ } | |
| 746 | 746 | |
| 747 | 747 | return d.dev; |
| 748 | 748 | } |
| @@ -1004,6 +1004,9 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data) · 255 unmodified lines | ||
| 1004 | 1004 | |
| 1005 | 1005 | pr_info("\n"); |
| 1006 | 1006 | |
| 1007 | + /* Prevent hung task messages when printing on serial console */ | |
| 1008 | + cond_resched(); | |
| 1009 | + | |
| 1007 | 1010 | pr_info("#define HPA_%08lx_DESCRIPTION \"%s\"\n", |
| 1008 | 1011 | hpa, parisc_hardware_description(&dev->id)); |
| 1009 | 1012 | |
| @@ -120,8 +120,8 @@ static int emulate_ldh(struct pt_regs *regs, int toreg) · 119 unmodified lines | ||
| 120 | 120 | "2: ldbs 1(%%sr1,%3), %0\n" |
| 121 | 121 | " depw %2, 23, 24, %0\n" |
| 122 | 122 | "3: \n" |
| 123 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b) | |
| 124 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b) | |
| 123 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1") | |
| 124 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1") | |
| 125 | 125 | : "+r" (val), "+r" (ret), "=&r" (temp1) |
| 126 | 126 | : "r" (saddr), "r" (regs->isr) ); |
| 127 | 127 | |
| @@ -152,8 +152,8 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop) · 24 unmodified lines | ||
| 152 | 152 | " mtctl %2,11\n" |
| 153 | 153 | " vshd %0,%3,%0\n" |
| 154 | 154 | "3: \n" |
| 155 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b) | |
| 156 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b) | |
| 155 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1") | |
| 156 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1") | |
| 157 | 157 | : "+r" (val), "+r" (ret), "=&r" (temp1), "=&r" (temp2) |
| 158 | 158 | : "r" (saddr), "r" (regs->isr) ); |
| 159 | 159 | |
| @@ -189,8 +189,8 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) · 29 unmodified lines | ||
| 189 | 189 | " mtsar %%r19\n" |
| 190 | 190 | " shrpd %0,%%r20,%%sar,%0\n" |
| 191 | 191 | "3: \n" |
| 192 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b) | |
| 193 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b) | |
| 192 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1") | |
| 193 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1") | |
| 194 | 194 | : "=r" (val), "+r" (ret) |
| 195 | 195 | : "0" (val), "r" (saddr), "r" (regs->isr) |
| 196 | 196 | : "r19", "r20" ); |
| @@ -209,9 +209,9 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) · 12 unmodified lines | ||
| 209 | 209 | " vshd %0,%R0,%0\n" |
| 210 | 210 | " vshd %R0,%4,%R0\n" |
| 211 | 211 | "4: \n" |
| 212 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 4b) | |
| 213 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 4b) | |
| 214 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 4b) | |
| 212 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 4b, "%1") | |
| 213 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 4b, "%1") | |
| 214 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 4b, "%1") | |
| 215 | 215 | : "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1) |
| 216 | 216 | : "r" (regs->isr) ); |
| 217 | 217 | } |
| @@ -244,8 +244,8 @@ static int emulate_sth(struct pt_regs *regs, int frreg) · 26 unmodified lines | ||
| 244 | 244 | "1: stb %1, 0(%%sr1, %3)\n" |
| 245 | 245 | "2: stb %2, 1(%%sr1, %3)\n" |
| 246 | 246 | "3: \n" |
| 247 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b) | |
| 248 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b) | |
| 247 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%0") | |
| 248 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%0") | |
| 249 | 249 | : "+r" (ret), "=&r" (temp1) |
| 250 | 250 | : "r" (val), "r" (regs->ior), "r" (regs->isr) ); |
| 251 | 251 | |
| @@ -285,8 +285,8 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop) · 33 unmodified lines | ||
| 285 | 285 | " stw %%r20,0(%%sr1,%2)\n" |
| 286 | 286 | " stw %%r21,4(%%sr1,%2)\n" |
| 287 | 287 | "3: \n" |
| 288 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b) | |
| 289 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b) | |
| 288 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%0") | |
| 289 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%0") | |
| 290 | 290 | : "+r" (ret) |
| 291 | 291 | : "r" (val), "r" (regs->ior), "r" (regs->isr) |
| 292 | 292 | : "r19", "r20", "r21", "r22", "r1" ); |
| @@ -329,10 +329,10 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) · 36 unmodified lines | ||
| 329 | 329 | "3: std %%r20,0(%%sr1,%2)\n" |
| 330 | 330 | "4: std %%r21,8(%%sr1,%2)\n" |
| 331 | 331 | "5: \n" |
| 332 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 5b) | |
| 333 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 5b) | |
| 334 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 5b) | |
| 335 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 5b) | |
| 332 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 5b, "%0") | |
| 333 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 5b, "%0") | |
| 334 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 5b, "%0") | |
| 335 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 5b, "%0") | |
| 336 | 336 | : "+r" (ret) |
| 337 | 337 | : "r" (val), "r" (regs->ior), "r" (regs->isr) |
| 338 | 338 | : "r19", "r20", "r21", "r22", "r1" ); |
| @@ -357,11 +357,11 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) · 18 unmodified lines | ||
| 357 | 357 | "4: stw %%r1,4(%%sr1,%2)\n" |
| 358 | 358 | "5: stw %R1,8(%%sr1,%2)\n" |
| 359 | 359 | "6: \n" |
| 360 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 6b) | |
| 361 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 6b) | |
| 362 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 6b) | |
| 363 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 6b) | |
| 364 | − ASM_EXCEPTIONTABLE_ENTRY_EFAULT(5b, 6b) | |
| 360 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 6b, "%0") | |
| 361 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 6b, "%0") | |
| 362 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 6b, "%0") | |
| 363 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 6b, "%0") | |
| 364 | + ASM_EXCEPTIONTABLE_ENTRY_EFAULT(5b, 6b, "%0") | |
| 365 | 365 | : "+r" (ret) |
| 366 | 366 | : "r" (val), "r" (regs->ior), "r" (regs->isr) |
| 367 | 367 | : "r19", "r20", "r21", "r1" ); |
| @@ -127,7 +127,7 @@ SECTIONS · 126 unmodified lines | ||
| 127 | 127 | } |
| 128 | 128 | #endif |
| 129 | 129 | |
| 130 | − RO_DATA(8) | |
| 130 | + RO_DATA(PAGE_SIZE) | |
| 131 | 131 | |
| 132 | 132 | /* unwind info */ |
| 133 | 133 | . = ALIGN(4); |
| @@ -150,11 +150,16 @@ int fixup_exception(struct pt_regs *regs) · 149 unmodified lines | ||
| 150 | 150 | * Fix up get_user() and put_user(). |
| 151 | 151 | * ASM_EXCEPTIONTABLE_ENTRY_EFAULT() sets the least-significant |
| 152 | 152 | * bit in the relative address of the fixup routine to indicate |
| 153 | − * that gr[ASM_EXCEPTIONTABLE_REG] should be loaded with | |
| 154 | − * -EFAULT to report a userspace access error. | |
| 153 | + * that the register encoded in the "or %r0,%r0,register" | |
| 154 | + * opcode should be loaded with -EFAULT to report a userspace | |
| 155 | + * access error. | |
| 155 | 156 | */ |
| 156 | 157 | if (fix->fixup & 1) { |
| 157 | − regs->gr[ASM_EXCEPTIONTABLE_REG] = -EFAULT; | |
| 158 | + int fault_error_reg = fix->err_opcode & 0x1f; | |
| 159 | + if (!WARN_ON(!fault_error_reg)) | |
| 160 | + regs->gr[fault_error_reg] = -EFAULT; | |
| 161 | + pr_debug("Unalignment fixup of register %d at %pS\n", | |
| 162 | + fault_error_reg, (void*)regs->iaoq[0]); | |
| 158 | 163 | |
| 159 | 164 | /* zero target register for get_user() */ |
| 160 | 165 | if (parisc_acctyp(0, regs->iir) == VM_READ) { |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 19 | 19 | { |
| 20 | − asm_volatile_goto("1:\n\t" | |
| 20 | + asm goto("1:\n\t" | |
| 21 | 21 | "nop # arch_static_branch\n\t" |
| 22 | 22 | ".pushsection __jump_table, \"aw\"\n\t" |
| 23 | 23 | ".long 1b - ., %l[l_yes] - .\n\t" |
| @@ -32,7 +32,7 @@ l_yes: · 8 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 34 | 34 | { |
| 35 | − asm_volatile_goto("1:\n\t" | |
| 35 | + asm goto("1:\n\t" | |
| 36 | 36 | "b %l[l_yes] # arch_static_branch_jump\n\t" |
| 37 | 37 | ".pushsection __jump_table, \"aw\"\n\t" |
| 38 | 38 | ".long 1b - ., %l[l_yes] - .\n\t" |
| @@ -74,7 +74,7 @@ __pu_failed: \ · 73 unmodified lines | ||
| 74 | 74 | /* -mprefixed can generate offsets beyond range, fall back hack */ |
| 75 | 75 | #ifdef CONFIG_PPC_KERNEL_PREFIXED |
| 76 | 76 | #define __put_user_asm_goto(x, addr, label, op) \ |
| 77 | − asm_volatile_goto( \ | |
| 77 | + asm goto( \ | |
| 78 | 78 | "1: " op " %0,0(%1) # put_user\n" \ |
| 79 | 79 | EX_TABLE(1b, %l2) \ |
| 80 | 80 | : \ |
| @@ -83,7 +83,7 @@ __pu_failed: \ · 2 unmodified lines | ||
| 83 | 83 | : label) |
| 84 | 84 | #else |
| 85 | 85 | #define __put_user_asm_goto(x, addr, label, op) \ |
| 86 | − asm_volatile_goto( \ | |
| 86 | + asm goto( \ | |
| 87 | 87 | "1: " op "%U1%X1 %0,%1 # put_user\n" \ |
| 88 | 88 | EX_TABLE(1b, %l2) \ |
| 89 | 89 | : \ |
| @@ -97,7 +97,7 @@ __pu_failed: \ · 7 unmodified lines | ||
| 97 | 97 | __put_user_asm_goto(x, ptr, label, "std") |
| 98 | 98 | #else /* __powerpc64__ */ |
| 99 | 99 | #define __put_user_asm2_goto(x, addr, label) \ |
| 100 | − asm_volatile_goto( \ | |
| 100 | + asm goto( \ | |
| 101 | 101 | "1: stw%X1 %0, %1\n" \ |
| 102 | 102 | "2: stw%X1 %L0, %L1\n" \ |
| 103 | 103 | EX_TABLE(1b, %l2) \ |
| @@ -146,7 +146,7 @@ do { \ · 42 unmodified lines | ||
| 146 | 146 | /* -mprefixed can generate offsets beyond range, fall back hack */ |
| 147 | 147 | #ifdef CONFIG_PPC_KERNEL_PREFIXED |
| 148 | 148 | #define __get_user_asm_goto(x, addr, label, op) \ |
| 149 | − asm_volatile_goto( \ | |
| 149 | + asm_goto_output( \ | |
| 150 | 150 | "1: "op" %0,0(%1) # get_user\n" \ |
| 151 | 151 | EX_TABLE(1b, %l2) \ |
| 152 | 152 | : "=r" (x) \ |
| @@ -155,7 +155,7 @@ do { \ · 2 unmodified lines | ||
| 155 | 155 | : label) |
| 156 | 156 | #else |
| 157 | 157 | #define __get_user_asm_goto(x, addr, label, op) \ |
| 158 | − asm_volatile_goto( \ | |
| 158 | + asm_goto_output( \ | |
| 159 | 159 | "1: "op"%U1%X1 %0, %1 # get_user\n" \ |
| 160 | 160 | EX_TABLE(1b, %l2) \ |
| 161 | 161 | : "=r" (x) \ |
| @@ -169,7 +169,7 @@ do { \ · 7 unmodified lines | ||
| 169 | 169 | __get_user_asm_goto(x, addr, label, "ld") |
| 170 | 170 | #else /* __powerpc64__ */ |
| 171 | 171 | #define __get_user_asm2_goto(x, addr, label) \ |
| 172 | − asm_volatile_goto( \ | |
| 172 | + asm_goto_output( \ | |
| 173 | 173 | "1: lwz%X1 %0, %1\n" \ |
| 174 | 174 | "2: lwz%X1 %L0, %L1\n" \ |
| 175 | 175 | EX_TABLE(1b, %l2) \ |
| @@ -1287,20 +1287,20 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain, · 1286 unmodified lines | ||
| 1287 | 1287 | struct iommu_domain *domain = iommu_get_domain_for_dev(dev); |
| 1288 | 1288 | struct iommu_group *grp = iommu_group_get(dev); |
| 1289 | 1289 | struct iommu_table_group *table_group; |
| 1290 | − int ret = -EINVAL; | |
| 1291 | 1290 | |
| 1292 | 1291 | /* At first attach the ownership is already set */ |
| 1293 | 1292 | if (!domain) |
| 1294 | 1293 | return 0; |
| 1295 | 1294 | |
| 1296 | − if (!grp) | |
| 1297 | − return -ENODEV; | |
| 1298 | − | |
| 1299 | 1295 | table_group = iommu_group_get_iommudata(grp); |
| 1300 | − ret = table_group->ops->take_ownership(table_group); | |
| 1296 | + /* | |
| 1297 | + * The domain being set to PLATFORM from earlier | |
| 1298 | + * BLOCKED. The table_group ownership has to be released. | |
| 1299 | + */ | |
| 1300 | + table_group->ops->release_ownership(table_group); | |
| 1301 | 1301 | iommu_group_put(grp); |
| 1302 | 1302 | |
| 1303 | − return ret; | |
| 1303 | + return 0; | |
| 1304 | 1304 | } |
| 1305 | 1305 | |
| 1306 | 1306 | static const struct iommu_domain_ops spapr_tce_platform_domain_ops = { |
| @@ -1312,13 +1312,32 @@ static struct iommu_domain spapr_tce_platform_domain = { · 5 unmodified lines | ||
| 1312 | 1312 | .ops = &spapr_tce_platform_domain_ops, |
| 1313 | 1313 | }; |
| 1314 | 1314 | |
| 1315 | −static struct iommu_domain spapr_tce_blocked_domain = { | |
| 1316 | − .type = IOMMU_DOMAIN_BLOCKED, | |
| 1315 | +static int | |
| 1316 | +spapr_tce_blocked_iommu_attach_dev(struct iommu_domain *platform_domain, | |
| 1317 | + struct device *dev) | |
| 1318 | +{ | |
| 1319 | + struct iommu_group *grp = iommu_group_get(dev); | |
| 1320 | + struct iommu_table_group *table_group; | |
| 1321 | + int ret = -EINVAL; | |
| 1322 | + | |
| 1317 | 1323 | /* |
| 1318 | 1324 | * FIXME: SPAPR mixes blocked and platform behaviors, the blocked domain |
| 1319 | 1325 | * also sets the dma_api ops |
| 1320 | 1326 | */ |
| 1321 | − .ops = &spapr_tce_platform_domain_ops, | |
| 1327 | + table_group = iommu_group_get_iommudata(grp); | |
| 1328 | + ret = table_group->ops->take_ownership(table_group); | |
| 1329 | + iommu_group_put(grp); | |
| 1330 | + | |
| 1331 | + return ret; | |
| 1332 | +} | |
| 1333 | + | |
| 1334 | +static const struct iommu_domain_ops spapr_tce_blocked_domain_ops = { | |
| 1335 | + .attach_dev = spapr_tce_blocked_iommu_attach_dev, | |
| 1336 | +}; | |
| 1337 | + | |
| 1338 | +static struct iommu_domain spapr_tce_blocked_domain = { | |
| 1339 | + .type = IOMMU_DOMAIN_BLOCKED, | |
| 1340 | + .ops = &spapr_tce_blocked_domain_ops, | |
| 1322 | 1341 | }; |
| 1323 | 1342 | |
| 1324 | 1343 | static bool spapr_tce_iommu_capable(struct device *dev, enum iommu_cap cap) |
| @@ -230,7 +230,7 @@ again: · 229 unmodified lines | ||
| 230 | 230 | * This allows interrupts to be unmasked without hard disabling, and |
| 231 | 231 | * also without new hard interrupts coming in ahead of pending ones. |
| 232 | 232 | */ |
| 233 | − asm_volatile_goto( | |
| 233 | + asm goto( | |
| 234 | 234 | "1: \n" |
| 235 | 235 | " lbz 9,%0(13) \n" |
| 236 | 236 | " cmpwi 9,0 \n" |
| @@ -93,144 +93,160 @@ · 92 unmodified lines | ||
| 93 | 93 | <&cpu63_intc 3>; |
| 94 | 94 | }; |
| 95 | 95 | |
| 96 | − clint_mtimer0: timer@70ac000000 { | |
| 96 | + clint_mtimer0: timer@70ac004000 { | |
| 97 | 97 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 98 | − reg = <0x00000070 0xac000000 0x00000000 0x00007ff8>; | |
| 98 | + reg = <0x00000070 0xac004000 0x00000000 0x0000c000>; | |
| 99 | + reg-names = "mtimecmp"; | |
| 99 | 100 | interrupts-extended = <&cpu0_intc 7>, |
| 100 | 101 | <&cpu1_intc 7>, |
| 101 | 102 | <&cpu2_intc 7>, |
| 102 | 103 | <&cpu3_intc 7>; |
| 103 | 104 | }; |
| 104 | 105 | |
| 105 | − clint_mtimer1: timer@70ac010000 { | |
| 106 | + clint_mtimer1: timer@70ac014000 { | |
| 106 | 107 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 107 | − reg = <0x00000070 0xac010000 0x00000000 0x00007ff8>; | |
| 108 | + reg = <0x00000070 0xac014000 0x00000000 0x0000c000>; | |
| 109 | + reg-names = "mtimecmp"; | |
| 108 | 110 | interrupts-extended = <&cpu4_intc 7>, |
| 109 | 111 | <&cpu5_intc 7>, |
| 110 | 112 | <&cpu6_intc 7>, |
| 111 | 113 | <&cpu7_intc 7>; |
| 112 | 114 | }; |
| 113 | 115 | |
| 114 | − clint_mtimer2: timer@70ac020000 { | |
| 116 | + clint_mtimer2: timer@70ac024000 { | |
| 115 | 117 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 116 | − reg = <0x00000070 0xac020000 0x00000000 0x00007ff8>; | |
| 118 | + reg = <0x00000070 0xac024000 0x00000000 0x0000c000>; | |
| 119 | + reg-names = "mtimecmp"; | |
| 117 | 120 | interrupts-extended = <&cpu8_intc 7>, |
| 118 | 121 | <&cpu9_intc 7>, |
| 119 | 122 | <&cpu10_intc 7>, |
| 120 | 123 | <&cpu11_intc 7>; |
| 121 | 124 | }; |
| 122 | 125 | |
| 123 | − clint_mtimer3: timer@70ac030000 { | |
| 126 | + clint_mtimer3: timer@70ac034000 { | |
| 124 | 127 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 125 | − reg = <0x00000070 0xac030000 0x00000000 0x00007ff8>; | |
| 128 | + reg = <0x00000070 0xac034000 0x00000000 0x0000c000>; | |
| 129 | + reg-names = "mtimecmp"; | |
| 126 | 130 | interrupts-extended = <&cpu12_intc 7>, |
| 127 | 131 | <&cpu13_intc 7>, |
| 128 | 132 | <&cpu14_intc 7>, |
| 129 | 133 | <&cpu15_intc 7>; |
| 130 | 134 | }; |
| 131 | 135 | |
| 132 | − clint_mtimer4: timer@70ac040000 { | |
| 136 | + clint_mtimer4: timer@70ac044000 { | |
| 133 | 137 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 134 | − reg = <0x00000070 0xac040000 0x00000000 0x00007ff8>; | |
| 138 | + reg = <0x00000070 0xac044000 0x00000000 0x0000c000>; | |
| 139 | + reg-names = "mtimecmp"; | |
| 135 | 140 | interrupts-extended = <&cpu16_intc 7>, |
| 136 | 141 | <&cpu17_intc 7>, |
| 137 | 142 | <&cpu18_intc 7>, |
| 138 | 143 | <&cpu19_intc 7>; |
| 139 | 144 | }; |
| 140 | 145 | |
| 141 | − clint_mtimer5: timer@70ac050000 { | |
| 146 | + clint_mtimer5: timer@70ac054000 { | |
| 142 | 147 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 143 | − reg = <0x00000070 0xac050000 0x00000000 0x00007ff8>; | |
| 148 | + reg = <0x00000070 0xac054000 0x00000000 0x0000c000>; | |
| 149 | + reg-names = "mtimecmp"; | |
| 144 | 150 | interrupts-extended = <&cpu20_intc 7>, |
| 145 | 151 | <&cpu21_intc 7>, |
| 146 | 152 | <&cpu22_intc 7>, |
| 147 | 153 | <&cpu23_intc 7>; |
| 148 | 154 | }; |
| 149 | 155 | |
| 150 | − clint_mtimer6: timer@70ac060000 { | |
| 156 | + clint_mtimer6: timer@70ac064000 { | |
| 151 | 157 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 152 | − reg = <0x00000070 0xac060000 0x00000000 0x00007ff8>; | |
| 158 | + reg = <0x00000070 0xac064000 0x00000000 0x0000c000>; | |
| 159 | + reg-names = "mtimecmp"; | |
| 153 | 160 | interrupts-extended = <&cpu24_intc 7>, |
| 154 | 161 | <&cpu25_intc 7>, |
| 155 | 162 | <&cpu26_intc 7>, |
| 156 | 163 | <&cpu27_intc 7>; |
| 157 | 164 | }; |
| 158 | 165 | |
| 159 | − clint_mtimer7: timer@70ac070000 { | |
| 166 | + clint_mtimer7: timer@70ac074000 { | |
| 160 | 167 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 161 | − reg = <0x00000070 0xac070000 0x00000000 0x00007ff8>; | |
| 168 | + reg = <0x00000070 0xac074000 0x00000000 0x0000c000>; | |
| 169 | + reg-names = "mtimecmp"; | |
| 162 | 170 | interrupts-extended = <&cpu28_intc 7>, |
| 163 | 171 | <&cpu29_intc 7>, |
| 164 | 172 | <&cpu30_intc 7>, |
| 165 | 173 | <&cpu31_intc 7>; |
| 166 | 174 | }; |
| 167 | 175 | |
| 168 | − clint_mtimer8: timer@70ac080000 { | |
| 176 | + clint_mtimer8: timer@70ac084000 { | |
| 169 | 177 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 170 | − reg = <0x00000070 0xac080000 0x00000000 0x00007ff8>; | |
| 178 | + reg = <0x00000070 0xac084000 0x00000000 0x0000c000>; | |
| 179 | + reg-names = "mtimecmp"; | |
| 171 | 180 | interrupts-extended = <&cpu32_intc 7>, |
| 172 | 181 | <&cpu33_intc 7>, |
| 173 | 182 | <&cpu34_intc 7>, |
| 174 | 183 | <&cpu35_intc 7>; |
| 175 | 184 | }; |
| 176 | 185 | |
| 177 | − clint_mtimer9: timer@70ac090000 { | |
| 186 | + clint_mtimer9: timer@70ac094000 { | |
| 178 | 187 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 179 | − reg = <0x00000070 0xac090000 0x00000000 0x00007ff8>; | |
| 188 | + reg = <0x00000070 0xac094000 0x00000000 0x0000c000>; | |
| 189 | + reg-names = "mtimecmp"; | |
| 180 | 190 | interrupts-extended = <&cpu36_intc 7>, |
| 181 | 191 | <&cpu37_intc 7>, |
| 182 | 192 | <&cpu38_intc 7>, |
| 183 | 193 | <&cpu39_intc 7>; |
| 184 | 194 | }; |
| 185 | 195 | |
| 186 | − clint_mtimer10: timer@70ac0a0000 { | |
| 196 | + clint_mtimer10: timer@70ac0a4000 { | |
| 187 | 197 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 188 | − reg = <0x00000070 0xac0a0000 0x00000000 0x00007ff8>; | |
| 198 | + reg = <0x00000070 0xac0a4000 0x00000000 0x0000c000>; | |
| 199 | + reg-names = "mtimecmp"; | |
| 189 | 200 | interrupts-extended = <&cpu40_intc 7>, |
| 190 | 201 | <&cpu41_intc 7>, |
| 191 | 202 | <&cpu42_intc 7>, |
| 192 | 203 | <&cpu43_intc 7>; |
| 193 | 204 | }; |
| 194 | 205 | |
| 195 | − clint_mtimer11: timer@70ac0b0000 { | |
| 206 | + clint_mtimer11: timer@70ac0b4000 { | |
| 196 | 207 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 197 | − reg = <0x00000070 0xac0b0000 0x00000000 0x00007ff8>; | |
| 208 | + reg = <0x00000070 0xac0b4000 0x00000000 0x0000c000>; | |
| 209 | + reg-names = "mtimecmp"; | |
| 198 | 210 | interrupts-extended = <&cpu44_intc 7>, |
| 199 | 211 | <&cpu45_intc 7>, |
| 200 | 212 | <&cpu46_intc 7>, |
| 201 | 213 | <&cpu47_intc 7>; |
| 202 | 214 | }; |
| 203 | 215 | |
| 204 | − clint_mtimer12: timer@70ac0c0000 { | |
| 216 | + clint_mtimer12: timer@70ac0c4000 { | |
| 205 | 217 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 206 | − reg = <0x00000070 0xac0c0000 0x00000000 0x00007ff8>; | |
| 218 | + reg = <0x00000070 0xac0c4000 0x00000000 0x0000c000>; | |
| 219 | + reg-names = "mtimecmp"; | |
| 207 | 220 | interrupts-extended = <&cpu48_intc 7>, |
| 208 | 221 | <&cpu49_intc 7>, |
| 209 | 222 | <&cpu50_intc 7>, |
| 210 | 223 | <&cpu51_intc 7>; |
| 211 | 224 | }; |
| 212 | 225 | |
| 213 | − clint_mtimer13: timer@70ac0d0000 { | |
| 226 | + clint_mtimer13: timer@70ac0d4000 { | |
| 214 | 227 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 215 | − reg = <0x00000070 0xac0d0000 0x00000000 0x00007ff8>; | |
| 228 | + reg = <0x00000070 0xac0d4000 0x00000000 0x0000c000>; | |
| 229 | + reg-names = "mtimecmp"; | |
| 216 | 230 | interrupts-extended = <&cpu52_intc 7>, |
| 217 | 231 | <&cpu53_intc 7>, |
| 218 | 232 | <&cpu54_intc 7>, |
| 219 | 233 | <&cpu55_intc 7>; |
| 220 | 234 | }; |
| 221 | 235 | |
| 222 | − clint_mtimer14: timer@70ac0e0000 { | |
| 236 | + clint_mtimer14: timer@70ac0e4000 { | |
| 223 | 237 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 224 | − reg = <0x00000070 0xac0e0000 0x00000000 0x00007ff8>; | |
| 238 | + reg = <0x00000070 0xac0e4000 0x00000000 0x0000c000>; | |
| 239 | + reg-names = "mtimecmp"; | |
| 225 | 240 | interrupts-extended = <&cpu56_intc 7>, |
| 226 | 241 | <&cpu57_intc 7>, |
| 227 | 242 | <&cpu58_intc 7>, |
| 228 | 243 | <&cpu59_intc 7>; |
| 229 | 244 | }; |
| 230 | 245 | |
| 231 | − clint_mtimer15: timer@70ac0f0000 { | |
| 246 | + clint_mtimer15: timer@70ac0f4000 { | |
| 232 | 247 | compatible = "sophgo,sg2042-aclint-mtimer", "thead,c900-aclint-mtimer"; |
| 233 | − reg = <0x00000070 0xac0f0000 0x00000000 0x00007ff8>; | |
| 248 | + reg = <0x00000070 0xac0f4000 0x00000000 0x0000c000>; | |
| 249 | + reg-names = "mtimecmp"; | |
| 234 | 250 | interrupts-extended = <&cpu60_intc 7>, |
| 235 | 251 | <&cpu61_intc 7>, |
| 236 | 252 | <&cpu62_intc 7>, |
| @@ -20,7 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | static __always_inline unsigned int __arch_hweight32(unsigned int w) |
| 21 | 21 | { |
| 22 | 22 | #ifdef CONFIG_RISCV_ISA_ZBB |
| 23 | − asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 23 | + asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 24 | 24 | RISCV_ISA_EXT_ZBB, 1) |
| 25 | 25 | : : : : legacy); |
| 26 | 26 | |
| @@ -51,7 +51,7 @@ static inline unsigned int __arch_hweight8(unsigned int w) · 24 unmodified lines | ||
| 51 | 51 | static __always_inline unsigned long __arch_hweight64(__u64 w) |
| 52 | 52 | { |
| 53 | 53 | # ifdef CONFIG_RISCV_ISA_ZBB |
| 54 | − asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 54 | + asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 55 | 55 | RISCV_ISA_EXT_ZBB, 1) |
| 56 | 56 | : : : : legacy); |
| 57 | 57 | |
| @@ -39,7 +39,7 @@ static __always_inline unsigned long variable__ffs(unsigned long word) · 38 unmodified lines | ||
| 39 | 39 | { |
| 40 | 40 | int num; |
| 41 | 41 | |
| 42 | − asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 42 | + asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 43 | 43 | RISCV_ISA_EXT_ZBB, 1) |
| 44 | 44 | : : : : legacy); |
| 45 | 45 | |
| @@ -95,7 +95,7 @@ static __always_inline unsigned long variable__fls(unsigned long word) · 49 unmodified lines | ||
| 95 | 95 | { |
| 96 | 96 | int num; |
| 97 | 97 | |
| 98 | − asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 98 | + asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 99 | 99 | RISCV_ISA_EXT_ZBB, 1) |
| 100 | 100 | : : : : legacy); |
| 101 | 101 | |
| @@ -154,7 +154,7 @@ static __always_inline int variable_ffs(int x) · 52 unmodified lines | ||
| 154 | 154 | if (!x) |
| 155 | 155 | return 0; |
| 156 | 156 | |
| 157 | − asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 157 | + asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 158 | 158 | RISCV_ISA_EXT_ZBB, 1) |
| 159 | 159 | : : : : legacy); |
| 160 | 160 | |
| @@ -209,7 +209,7 @@ static __always_inline int variable_fls(unsigned int x) · 48 unmodified lines | ||
| 209 | 209 | if (!x) |
| 210 | 210 | return 0; |
| 211 | 211 | |
| 212 | − asm_volatile_goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 212 | + asm goto(ALTERNATIVE("j %l[legacy]", "nop", 0, | |
| 213 | 213 | RISCV_ISA_EXT_ZBB, 1) |
| 214 | 214 | : : : : legacy); |
| 215 | 215 | |
| @@ -53,7 +53,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) · 52 unmodified lines | ||
| 53 | 53 | IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { |
| 54 | 54 | unsigned long fold_temp; |
| 55 | 55 | |
| 56 | − asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 56 | + asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 57 | 57 | RISCV_ISA_EXT_ZBB, 1) |
| 58 | 58 | : |
| 59 | 59 | : |
| @@ -80,7 +80,7 @@ riscv_has_extension_likely(const unsigned long ext) · 79 unmodified lines | ||
| 80 | 80 | "ext must be < RISCV_ISA_EXT_MAX"); |
| 81 | 81 | |
| 82 | 82 | if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { |
| 83 | − asm_volatile_goto( | |
| 83 | + asm goto( | |
| 84 | 84 | ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1) |
| 85 | 85 | : |
| 86 | 86 | : [ext] "i" (ext) |
| @@ -103,7 +103,7 @@ riscv_has_extension_unlikely(const unsigned long ext) · 16 unmodified lines | ||
| 103 | 103 | "ext must be < RISCV_ISA_EXT_MAX"); |
| 104 | 104 | |
| 105 | 105 | if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) { |
| 106 | − asm_volatile_goto( | |
| 106 | + asm goto( | |
| 107 | 107 | ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1) |
| 108 | 108 | : |
| 109 | 109 | : [ext] "i" (ext) |
| @@ -11,6 +11,9 @@ static inline void arch_clear_hugepage_flags(struct page *page) · 10 unmodified lines | ||
| 11 | 11 | } |
| 12 | 12 | #define arch_clear_hugepage_flags arch_clear_hugepage_flags |
| 13 | 13 | |
| 14 | +bool arch_hugetlb_migration_supported(struct hstate *h); | |
| 15 | +#define arch_hugetlb_migration_supported arch_hugetlb_migration_supported | |
| 16 | + | |
| 14 | 17 | #ifdef CONFIG_RISCV_ISA_SVNAPOT |
| 15 | 18 | #define __HAVE_ARCH_HUGE_PTE_CLEAR |
| 16 | 19 | void huge_pte_clear(struct mm_struct *mm, unsigned long addr, |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | static __always_inline bool arch_static_branch(struct static_key * const key, |
| 18 | 18 | const bool branch) |
| 19 | 19 | { |
| 20 | − asm_volatile_goto( | |
| 20 | + asm goto( | |
| 21 | 21 | " .align 2 \n\t" |
| 22 | 22 | " .option push \n\t" |
| 23 | 23 | " .option norelax \n\t" |
| @@ -39,7 +39,7 @@ label: · 15 unmodified lines | ||
| 39 | 39 | static __always_inline bool arch_static_branch_jump(struct static_key * const key, |
| 40 | 40 | const bool branch) |
| 41 | 41 | { |
| 42 | − asm_volatile_goto( | |
| 42 | + asm goto( | |
| 43 | 43 | " .align 2 \n\t" |
| 44 | 44 | " .option push \n\t" |
| 45 | 45 | " .option norelax \n\t" |
| @@ -21,4 +21,9 @@ static inline bool on_thread_stack(void) · 20 unmodified lines | ||
| 21 | 21 | return !(((unsigned long)(current->stack) ^ current_stack_pointer) & ~(THREAD_SIZE - 1)); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | + | |
| 25 | +#ifdef CONFIG_VMAP_STACK | |
| 26 | +DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack); | |
| 27 | +#endif /* CONFIG_VMAP_STACK */ | |
| 28 | + | |
| 24 | 29 | #endif /* _ASM_RISCV_STACKTRACE_H */ |
| @@ -16,7 +16,7 @@ static void tlb_flush(struct mmu_gather *tlb); · 15 unmodified lines | ||
| 16 | 16 | static inline void tlb_flush(struct mmu_gather *tlb) |
| 17 | 17 | { |
| 18 | 18 | #ifdef CONFIG_MMU |
| 19 | − if (tlb->fullmm || tlb->need_flush_all) | |
| 19 | + if (tlb->fullmm || tlb->need_flush_all || tlb->freed_tables) | |
| 20 | 20 | flush_tlb_mm(tlb->mm); |
| 21 | 21 | else |
| 22 | 22 | flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, |
| @@ -75,6 +75,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, · 74 unmodified lines | ||
| 75 | 75 | |
| 76 | 76 | #define flush_tlb_mm(mm) flush_tlb_all() |
| 77 | 77 | #define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all() |
| 78 | +#define local_flush_tlb_kernel_range(start, end) flush_tlb_all() | |
| 78 | 79 | #endif /* !CONFIG_SMP || !CONFIG_MMU */ |
| 79 | 80 | |
| 80 | 81 | #endif /* _ASM_RISCV_TLBFLUSH_H */ |
| @@ -139,6 +139,33 @@ enum KVM_RISCV_ISA_EXT_ID { · 138 unmodified lines | ||
| 139 | 139 | KVM_RISCV_ISA_EXT_ZIHPM, |
| 140 | 140 | KVM_RISCV_ISA_EXT_SMSTATEEN, |
| 141 | 141 | KVM_RISCV_ISA_EXT_ZICOND, |
| 142 | + KVM_RISCV_ISA_EXT_ZBC, | |
| 143 | + KVM_RISCV_ISA_EXT_ZBKB, | |
| 144 | + KVM_RISCV_ISA_EXT_ZBKC, | |
| 145 | + KVM_RISCV_ISA_EXT_ZBKX, | |
| 146 | + KVM_RISCV_ISA_EXT_ZKND, | |
| 147 | + KVM_RISCV_ISA_EXT_ZKNE, | |
| 148 | + KVM_RISCV_ISA_EXT_ZKNH, | |
| 149 | + KVM_RISCV_ISA_EXT_ZKR, | |
| 150 | + KVM_RISCV_ISA_EXT_ZKSED, | |
| 151 | + KVM_RISCV_ISA_EXT_ZKSH, | |
| 152 | + KVM_RISCV_ISA_EXT_ZKT, | |
| 153 | + KVM_RISCV_ISA_EXT_ZVBB, | |
| 154 | + KVM_RISCV_ISA_EXT_ZVBC, | |
| 155 | + KVM_RISCV_ISA_EXT_ZVKB, | |
| 156 | + KVM_RISCV_ISA_EXT_ZVKG, | |
| 157 | + KVM_RISCV_ISA_EXT_ZVKNED, | |
| 158 | + KVM_RISCV_ISA_EXT_ZVKNHA, | |
| 159 | + KVM_RISCV_ISA_EXT_ZVKNHB, | |
| 160 | + KVM_RISCV_ISA_EXT_ZVKSED, | |
| 161 | + KVM_RISCV_ISA_EXT_ZVKSH, | |
| 162 | + KVM_RISCV_ISA_EXT_ZVKT, | |
| 163 | + KVM_RISCV_ISA_EXT_ZFH, | |
| 164 | + KVM_RISCV_ISA_EXT_ZFHMIN, | |
| 165 | + KVM_RISCV_ISA_EXT_ZIHINTNTL, | |
| 166 | + KVM_RISCV_ISA_EXT_ZVFH, | |
| 167 | + KVM_RISCV_ISA_EXT_ZVFHMIN, | |
| 168 | + KVM_RISCV_ISA_EXT_ZFA, | |
| 142 | 169 | KVM_RISCV_ISA_EXT_MAX, |
| 143 | 170 | }; |
| 144 | 171 | |
| @@ -42,15 +42,42 @@ static const unsigned long kvm_isa_ext_arr[] = { · 41 unmodified lines | ||
| 42 | 42 | KVM_ISA_EXT_ARR(SVPBMT), |
| 43 | 43 | KVM_ISA_EXT_ARR(ZBA), |
| 44 | 44 | KVM_ISA_EXT_ARR(ZBB), |
| 45 | + KVM_ISA_EXT_ARR(ZBC), | |
| 46 | + KVM_ISA_EXT_ARR(ZBKB), | |
| 47 | + KVM_ISA_EXT_ARR(ZBKC), | |
| 48 | + KVM_ISA_EXT_ARR(ZBKX), | |
| 45 | 49 | KVM_ISA_EXT_ARR(ZBS), |
| 50 | + KVM_ISA_EXT_ARR(ZFA), | |
| 51 | + KVM_ISA_EXT_ARR(ZFH), | |
| 52 | + KVM_ISA_EXT_ARR(ZFHMIN), | |
| 46 | 53 | KVM_ISA_EXT_ARR(ZICBOM), |
| 47 | 54 | KVM_ISA_EXT_ARR(ZICBOZ), |
| 48 | 55 | KVM_ISA_EXT_ARR(ZICNTR), |
| 49 | 56 | KVM_ISA_EXT_ARR(ZICOND), |
| 50 | 57 | KVM_ISA_EXT_ARR(ZICSR), |
| 51 | 58 | KVM_ISA_EXT_ARR(ZIFENCEI), |
| 59 | + KVM_ISA_EXT_ARR(ZIHINTNTL), | |
| 52 | 60 | KVM_ISA_EXT_ARR(ZIHINTPAUSE), |
| 53 | 61 | KVM_ISA_EXT_ARR(ZIHPM), |
| 62 | + KVM_ISA_EXT_ARR(ZKND), | |
| 63 | + KVM_ISA_EXT_ARR(ZKNE), | |
| 64 | + KVM_ISA_EXT_ARR(ZKNH), | |
| 65 | + KVM_ISA_EXT_ARR(ZKR), | |
| 66 | + KVM_ISA_EXT_ARR(ZKSED), | |
| 67 | + KVM_ISA_EXT_ARR(ZKSH), | |
| 68 | + KVM_ISA_EXT_ARR(ZKT), | |
| 69 | + KVM_ISA_EXT_ARR(ZVBB), | |
| 70 | + KVM_ISA_EXT_ARR(ZVBC), | |
| 71 | + KVM_ISA_EXT_ARR(ZVFH), | |
| 72 | + KVM_ISA_EXT_ARR(ZVFHMIN), | |
| 73 | + KVM_ISA_EXT_ARR(ZVKB), | |
| 74 | + KVM_ISA_EXT_ARR(ZVKG), | |
| 75 | + KVM_ISA_EXT_ARR(ZVKNED), | |
| 76 | + KVM_ISA_EXT_ARR(ZVKNHA), | |
| 77 | + KVM_ISA_EXT_ARR(ZVKNHB), | |
| 78 | + KVM_ISA_EXT_ARR(ZVKSED), | |
| 79 | + KVM_ISA_EXT_ARR(ZVKSH), | |
| 80 | + KVM_ISA_EXT_ARR(ZVKT), | |
| 54 | 81 | }; |
| 55 | 82 | |
| 56 | 83 | static unsigned long kvm_riscv_vcpu_base2isa_ext(unsigned long base_ext) |
| @@ -92,13 +119,40 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext) · 35 unmodified lines | ||
| 92 | 119 | case KVM_RISCV_ISA_EXT_SVNAPOT: |
| 93 | 120 | case KVM_RISCV_ISA_EXT_ZBA: |
| 94 | 121 | case KVM_RISCV_ISA_EXT_ZBB: |
| 122 | + case KVM_RISCV_ISA_EXT_ZBC: | |
| 123 | + case KVM_RISCV_ISA_EXT_ZBKB: | |
| 124 | + case KVM_RISCV_ISA_EXT_ZBKC: | |
| 125 | + case KVM_RISCV_ISA_EXT_ZBKX: | |
| 95 | 126 | case KVM_RISCV_ISA_EXT_ZBS: |
| 127 | + case KVM_RISCV_ISA_EXT_ZFA: | |
| 128 | + case KVM_RISCV_ISA_EXT_ZFH: | |
| 129 | + case KVM_RISCV_ISA_EXT_ZFHMIN: | |
| 96 | 130 | case KVM_RISCV_ISA_EXT_ZICNTR: |
| 97 | 131 | case KVM_RISCV_ISA_EXT_ZICOND: |
| 98 | 132 | case KVM_RISCV_ISA_EXT_ZICSR: |
| 99 | 133 | case KVM_RISCV_ISA_EXT_ZIFENCEI: |
| 134 | + case KVM_RISCV_ISA_EXT_ZIHINTNTL: | |
| 100 | 135 | case KVM_RISCV_ISA_EXT_ZIHINTPAUSE: |
| 101 | 136 | case KVM_RISCV_ISA_EXT_ZIHPM: |
| 137 | + case KVM_RISCV_ISA_EXT_ZKND: | |
| 138 | + case KVM_RISCV_ISA_EXT_ZKNE: | |
| 139 | + case KVM_RISCV_ISA_EXT_ZKNH: | |
| 140 | + case KVM_RISCV_ISA_EXT_ZKR: | |
| 141 | + case KVM_RISCV_ISA_EXT_ZKSED: | |
| 142 | + case KVM_RISCV_ISA_EXT_ZKSH: | |
| 143 | + case KVM_RISCV_ISA_EXT_ZKT: | |
| 144 | + case KVM_RISCV_ISA_EXT_ZVBB: | |
| 145 | + case KVM_RISCV_ISA_EXT_ZVBC: | |
| 146 | + case KVM_RISCV_ISA_EXT_ZVFH: | |
| 147 | + case KVM_RISCV_ISA_EXT_ZVFHMIN: | |
| 148 | + case KVM_RISCV_ISA_EXT_ZVKB: | |
| 149 | + case KVM_RISCV_ISA_EXT_ZVKG: | |
| 150 | + case KVM_RISCV_ISA_EXT_ZVKNED: | |
| 151 | + case KVM_RISCV_ISA_EXT_ZVKNHA: | |
| 152 | + case KVM_RISCV_ISA_EXT_ZVKNHB: | |
| 153 | + case KVM_RISCV_ISA_EXT_ZVKSED: | |
| 154 | + case KVM_RISCV_ISA_EXT_ZVKSH: | |
| 155 | + case KVM_RISCV_ISA_EXT_ZVKT: | |
| 102 | 156 | return false; |
| 103 | 157 | /* Extensions which can be disabled using Smstateen */ |
| 104 | 158 | case KVM_RISCV_ISA_EXT_SSAIA: |
| @@ -53,7 +53,7 @@ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, · 52 unmodified lines | ||
| 53 | 53 | * support, so nop when Zbb is available and jump when Zbb is |
| 54 | 54 | * not available. |
| 55 | 55 | */ |
| 56 | − asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 56 | + asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 57 | 57 | RISCV_ISA_EXT_ZBB, 1) |
| 58 | 58 | : |
| 59 | 59 | : |
| @@ -170,7 +170,7 @@ do_csum_with_alignment(const unsigned char *buff, int len) · 110 unmodified lines | ||
| 170 | 170 | * support, so nop when Zbb is available and jump when Zbb is |
| 171 | 171 | * not available. |
| 172 | 172 | */ |
| 173 | − asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 173 | + asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 174 | 174 | RISCV_ISA_EXT_ZBB, 1) |
| 175 | 175 | : |
| 176 | 176 | : |
| @@ -178,7 +178,7 @@ do_csum_with_alignment(const unsigned char *buff, int len) · 1 unmodified line | ||
| 178 | 178 | : no_zbb); |
| 179 | 179 | |
| 180 | 180 | #ifdef CONFIG_32BIT |
| 181 | − asm_volatile_goto(".option push \n\ | |
| 181 | + asm_goto_output(".option push \n\ | |
| 182 | 182 | .option arch,+zbb \n\ |
| 183 | 183 | rori %[fold_temp], %[csum], 16 \n\ |
| 184 | 184 | andi %[offset], %[offset], 1 \n\ |
| @@ -193,7 +193,7 @@ do_csum_with_alignment(const unsigned char *buff, int len) · 8 unmodified lines | ||
| 193 | 193 | |
| 194 | 194 | return (unsigned short)csum; |
| 195 | 195 | #else /* !CONFIG_32BIT */ |
| 196 | − asm_volatile_goto(".option push \n\ | |
| 196 | + asm_goto_output(".option push \n\ | |
| 197 | 197 | .option arch,+zbb \n\ |
| 198 | 198 | rori %[fold_temp], %[csum], 32 \n\ |
| 199 | 199 | add %[csum], %[fold_temp], %[csum] \n\ |
| @@ -257,7 +257,7 @@ do_csum_no_alignment(const unsigned char *buff, int len) · 57 unmodified lines | ||
| 257 | 257 | * support, so nop when Zbb is available and jump when Zbb is |
| 258 | 258 | * not available. |
| 259 | 259 | */ |
| 260 | − asm_volatile_goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 260 | + asm goto(ALTERNATIVE("j %l[no_zbb]", "nop", 0, | |
| 261 | 261 | RISCV_ISA_EXT_ZBB, 1) |
| 262 | 262 | : |
| 263 | 263 | : |
| @@ -125,6 +125,26 @@ pte_t *huge_pte_offset(struct mm_struct *mm, · 124 unmodified lines | ||
| 125 | 125 | return pte; |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | +unsigned long hugetlb_mask_last_page(struct hstate *h) | |
| 129 | +{ | |
| 130 | + unsigned long hp_size = huge_page_size(h); | |
| 131 | + | |
| 132 | + switch (hp_size) { | |
| 133 | +#ifndef __PAGETABLE_PMD_FOLDED | |
| 134 | + case PUD_SIZE: | |
| 135 | + return P4D_SIZE - PUD_SIZE; | |
| 136 | +#endif | |
| 137 | + case PMD_SIZE: | |
| 138 | + return PUD_SIZE - PMD_SIZE; | |
| 139 | + case napot_cont_size(NAPOT_CONT64KB_ORDER): | |
| 140 | + return PMD_SIZE - napot_cont_size(NAPOT_CONT64KB_ORDER); | |
| 141 | + default: | |
| 142 | + break; | |
| 143 | + } | |
| 144 | + | |
| 145 | + return 0UL; | |
| 146 | +} | |
| 147 | + | |
| 128 | 148 | static pte_t get_clear_contig(struct mm_struct *mm, |
| 129 | 149 | unsigned long addr, |
| 130 | 150 | pte_t *ptep, |
| @@ -177,13 +197,36 @@ pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags) · 46 unmodified lines | ||
| 177 | 197 | return entry; |
| 178 | 198 | } |
| 179 | 199 | |
| 200 | +static void clear_flush(struct mm_struct *mm, | |
| 201 | + unsigned long addr, | |
| 202 | + pte_t *ptep, | |
| 203 | + unsigned long pgsize, | |
| 204 | + unsigned long ncontig) | |
| 205 | +{ | |
| 206 | + struct vm_area_struct vma = TLB_FLUSH_VMA(mm, 0); | |
| 207 | + unsigned long i, saddr = addr; | |
| 208 | + | |
| 209 | + for (i = 0; i < ncontig; i++, addr += pgsize, ptep++) | |
| 210 | + ptep_get_and_clear(mm, addr, ptep); | |
| 211 | + | |
| 212 | + flush_tlb_range(&vma, saddr, addr); | |
| 213 | +} | |
| 214 | + | |
| 215 | +/* | |
| 216 | + * When dealing with NAPOT mappings, the privileged specification indicates that | |
| 217 | + * "if an update needs to be made, the OS generally should first mark all of the | |
| 218 | + * PTEs invalid, then issue SFENCE.VMA instruction(s) covering all 4 KiB regions | |
| 219 | + * within the range, [...] then update the PTE(s), as described in Section | |
| 220 | + * 4.2.1.". That's the equivalent of the Break-Before-Make approach used by | |
| 221 | + * arm64. | |
| 222 | + */ | |
| 180 | 223 | void set_huge_pte_at(struct mm_struct *mm, |
| 181 | 224 | unsigned long addr, |
| 182 | 225 | pte_t *ptep, |
| 183 | 226 | pte_t pte, |
| 184 | 227 | unsigned long sz) |
| 185 | 228 | { |
| 186 | − unsigned long hugepage_shift; | |
| 229 | + unsigned long hugepage_shift, pgsize; | |
| 187 | 230 | int i, pte_num; |
| 188 | 231 | |
| 189 | 232 | if (sz >= PGDIR_SIZE) |
| @@ -198,7 +241,22 @@ void set_huge_pte_at(struct mm_struct *mm, · 8 unmodified lines | ||
| 198 | 241 | hugepage_shift = PAGE_SHIFT; |
| 199 | 242 | |
| 200 | 243 | pte_num = sz >> hugepage_shift; |
| 201 | − for (i = 0; i < pte_num; i++, ptep++, addr += (1 << hugepage_shift)) | |
| 244 | + pgsize = 1 << hugepage_shift; | |
| 245 | + | |
| 246 | + if (!pte_present(pte)) { | |
| 247 | + for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) | |
| 248 | + set_ptes(mm, addr, ptep, pte, 1); | |
| 249 | + return; | |
| 250 | + } | |
| 251 | + | |
| 252 | + if (!pte_napot(pte)) { | |
| 253 | + set_ptes(mm, addr, ptep, pte, 1); | |
| 254 | + return; | |
| 255 | + } | |
| 256 | + | |
| 257 | + clear_flush(mm, addr, ptep, pgsize, pte_num); | |
| 258 | + | |
| 259 | + for (i = 0; i < pte_num; i++, ptep++, addr += pgsize) | |
| 202 | 260 | set_pte_at(mm, addr, ptep, pte); |
| 203 | 261 | } |
| 204 | 262 | |
| @@ -306,7 +364,7 @@ void huge_pte_clear(struct mm_struct *mm, · 101 unmodified lines | ||
| 306 | 364 | pte_clear(mm, addr, ptep); |
| 307 | 365 | } |
| 308 | 366 | |
| 309 | −static __init bool is_napot_size(unsigned long size) | |
| 367 | +static bool is_napot_size(unsigned long size) | |
| 310 | 368 | { |
| 311 | 369 | unsigned long order; |
| 312 | 370 | |
| @@ -334,7 +392,7 @@ arch_initcall(napot_hugetlbpages_init); · 21 unmodified lines | ||
| 334 | 392 | |
| 335 | 393 | #else |
| 336 | 394 | |
| 337 | −static __init bool is_napot_size(unsigned long size) | |
| 395 | +static bool is_napot_size(unsigned long size) | |
| 338 | 396 | { |
| 339 | 397 | return false; |
| 340 | 398 | } |
| @@ -351,7 +409,7 @@ int pmd_huge(pmd_t pmd) · 10 unmodified lines | ||
| 351 | 409 | return pmd_leaf(pmd); |
| 352 | 410 | } |
| 353 | 411 | |
| 354 | −bool __init arch_hugetlb_valid_size(unsigned long size) | |
| 412 | +static bool __hugetlb_valid_size(unsigned long size) | |
| 355 | 413 | { |
| 356 | 414 | if (size == HPAGE_SIZE) |
| 357 | 415 | return true; |
| @@ -363,6 +421,16 @@ bool __init arch_hugetlb_valid_size(unsigned long size) · 5 unmodified lines | ||
| 363 | 421 | return false; |
| 364 | 422 | } |
| 365 | 423 | |
| 424 | +bool __init arch_hugetlb_valid_size(unsigned long size) | |
| 425 | +{ | |
| 426 | + return __hugetlb_valid_size(size); | |
| 427 | +} | |
| 428 | + | |
| 429 | +bool arch_hugetlb_migration_supported(struct hstate *h) | |
| 430 | +{ | |
| 431 | + return __hugetlb_valid_size(huge_page_size(h)); | |
| 432 | +} | |
| 433 | + | |
| 366 | 434 | #ifdef CONFIG_CONTIG_ALLOC |
| 367 | 435 | static __init int gigantic_pages_init(void) |
| 368 | 436 | { |
| @@ -1385,6 +1385,10 @@ void __init misc_mem_init(void) · 1384 unmodified lines | ||
| 1385 | 1385 | early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); |
| 1386 | 1386 | arch_numa_init(); |
| 1387 | 1387 | sparse_init(); |
| 1388 | +#ifdef CONFIG_SPARSEMEM_VMEMMAP | |
| 1389 | + /* The entire VMEMMAP region has been populated. Flush TLB for this region */ | |
| 1390 | + local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END); | |
| 1391 | +#endif | |
| 1388 | 1392 | zone_sizes_init(); |
| 1389 | 1393 | arch_reserve_crashkernel(); |
| 1390 | 1394 | memblock_dump_all(); |
| @@ -66,9 +66,10 @@ static inline void local_flush_tlb_range_asid(unsigned long start, · 65 unmodified lines | ||
| 66 | 66 | local_flush_tlb_range_threshold_asid(start, size, stride, asid); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | +/* Flush a range of kernel pages without broadcasting */ | |
| 69 | 70 | void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) |
| 70 | 71 | { |
| 71 | − local_flush_tlb_range_asid(start, end, PAGE_SIZE, FLUSH_TLB_NO_ASID); | |
| 72 | + local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID); | |
| 72 | 73 | } |
| 73 | 74 | |
| 74 | 75 | static void __ipi_flush_tlb_all(void *info) |
| @@ -233,4 +234,5 @@ void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) · 158 unmodified lines | ||
| 233 | 234 | { |
| 234 | 235 | __flush_tlb_range(&batch->cpumask, FLUSH_TLB_NO_ASID, 0, |
| 235 | 236 | FLUSH_TLB_MAX_SIZE, PAGE_SIZE); |
| 237 | + cpumask_clear(&batch->cpumask); | |
| 236 | 238 | } |
| @@ -795,6 +795,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 794 unmodified lines | ||
| 795 | 795 | struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY]; |
| 796 | 796 | struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT]; |
| 797 | 797 | struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN]; |
| 798 | + bool is_struct_ops = flags & BPF_TRAMP_F_INDIRECT; | |
| 798 | 799 | void *orig_call = func_addr; |
| 799 | 800 | bool save_ret; |
| 800 | 801 | u32 insn; |
| @@ -878,7 +879,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 77 unmodified lines | ||
| 878 | 879 | |
| 879 | 880 | stack_size = round_up(stack_size, 16); |
| 880 | 881 | |
| 881 | − if (func_addr) { | |
| 882 | + if (!is_struct_ops) { | |
| 882 | 883 | /* For the trampoline called from function entry, |
| 883 | 884 | * the frame of traced function and the frame of |
| 884 | 885 | * trampoline need to be considered. |
| @@ -998,7 +999,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 113 unmodified lines | ||
| 998 | 999 | |
| 999 | 1000 | emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx); |
| 1000 | 1001 | |
| 1001 | − if (func_addr) { | |
| 1002 | + if (!is_struct_ops) { | |
| 1002 | 1003 | /* trampoline called from function entry */ |
| 1003 | 1004 | emit_ld(RV_REG_T0, stack_size - 8, RV_REG_SP, ctx); |
| 1004 | 1005 | emit_ld(RV_REG_FP, stack_size - 16, RV_REG_SP, ctx); |
| @@ -25,7 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | */ |
| 26 | 26 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 27 | 27 | { |
| 28 | − asm_volatile_goto("0: brcl 0,%l[label]\n" | |
| 28 | + asm goto("0: brcl 0,%l[label]\n" | |
| 29 | 29 | ".pushsection __jump_table,\"aw\"\n" |
| 30 | 30 | ".balign 8\n" |
| 31 | 31 | ".long 0b-.,%l[label]-.\n" |
| @@ -39,7 +39,7 @@ label: · 7 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 41 | 41 | { |
| 42 | − asm_volatile_goto("0: brcl 15,%l[label]\n" | |
| 42 | + asm goto("0: brcl 15,%l[label]\n" | |
| 43 | 43 | ".pushsection __jump_table,\"aw\"\n" |
| 44 | 44 | ".balign 8\n" |
| 45 | 45 | ".long 0b-.,%l[label]-.\n" |
| @@ -676,8 +676,12 @@ static int handle_pqap(struct kvm_vcpu *vcpu) · 675 unmodified lines | ||
| 676 | 676 | if (vcpu->kvm->arch.crypto.pqap_hook) { |
| 677 | 677 | pqap_hook = *vcpu->kvm->arch.crypto.pqap_hook; |
| 678 | 678 | ret = pqap_hook(vcpu); |
| 679 | − if (!ret && vcpu->run->s.regs.gprs[1] & 0x00ff0000) | |
| 680 | − kvm_s390_set_psw_cc(vcpu, 3); | |
| 679 | + if (!ret) { | |
| 680 | + if (vcpu->run->s.regs.gprs[1] & 0x00ff0000) | |
| 681 | + kvm_s390_set_psw_cc(vcpu, 3); | |
| 682 | + else | |
| 683 | + kvm_s390_set_psw_cc(vcpu, 0); | |
| 684 | + } | |
| 681 | 685 | up_read(&vcpu->kvm->arch.crypto.pqap_hook_rwsem); |
| 682 | 686 | return ret; |
| 683 | 687 | } |
| @@ -1235,7 +1235,6 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu, · 1234 unmodified lines | ||
| 1235 | 1235 | gmap = gmap_shadow(vcpu->arch.gmap, asce, edat); |
| 1236 | 1236 | if (IS_ERR(gmap)) |
| 1237 | 1237 | return PTR_ERR(gmap); |
| 1238 | − gmap->private = vcpu->kvm; | |
| 1239 | 1238 | vcpu->kvm->stat.gmap_shadow_create++; |
| 1240 | 1239 | WRITE_ONCE(vsie_page->gmap, gmap); |
| 1241 | 1240 | return 0; |
| @@ -1691,6 +1691,7 @@ struct gmap *gmap_shadow(struct gmap *parent, unsigned long asce, · 1690 unmodified lines | ||
| 1691 | 1691 | return ERR_PTR(-ENOMEM); |
| 1692 | 1692 | new->mm = parent->mm; |
| 1693 | 1693 | new->parent = gmap_get(parent); |
| 1694 | + new->private = parent->private; | |
| 1694 | 1695 | new->orig_asce = asce; |
| 1695 | 1696 | new->edat_level = edat_level; |
| 1696 | 1697 | new->initialized = false; |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 12 | 12 | { |
| 13 | − asm_volatile_goto("1:\n\t" | |
| 13 | + asm goto("1:\n\t" | |
| 14 | 14 | "nop\n\t" |
| 15 | 15 | "nop\n\t" |
| 16 | 16 | ".pushsection __jump_table, \"aw\"\n\t" |
| @@ -26,7 +26,7 @@ l_yes: · 9 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 28 | 28 | { |
| 29 | − asm_volatile_goto("1:\n\t" | |
| 29 | + asm goto("1:\n\t" | |
| 30 | 30 | "b %l[l_yes]\n\t" |
| 31 | 31 | "nop\n\t" |
| 32 | 32 | ".pushsection __jump_table, \"aw\"\n\t" |
| @@ -115,7 +115,9 @@ archprepare: · 114 unmodified lines | ||
| 115 | 115 | $(Q)$(MAKE) $(build)=$(HOST_DIR)/um include/generated/user_constants.h |
| 116 | 116 | |
| 117 | 117 | LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static |
| 118 | −LINK-$(CONFIG_LD_SCRIPT_DYN) += $(call cc-option, -no-pie) | |
| 118 | +ifdef CONFIG_LD_SCRIPT_DYN | |
| 119 | +LINK-$(call gcc-min-version, 60100)$(CONFIG_CC_IS_CLANG) += -no-pie | |
| 120 | +endif | |
| 119 | 121 | LINK-$(CONFIG_LD_SCRIPT_DYN_RPATH) += -Wl,-rpath,/lib |
| 120 | 122 | |
| 121 | 123 | CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \ |
| @@ -75,7 +75,7 @@ extern void setup_clear_cpu_cap(unsigned int bit); · 74 unmodified lines | ||
| 75 | 75 | */ |
| 76 | 76 | static __always_inline bool _static_cpu_has(u16 bit) |
| 77 | 77 | { |
| 78 | − asm_volatile_goto("1: jmp 6f\n" | |
| 78 | + asm goto("1: jmp 6f\n" | |
| 79 | 79 | "2:\n" |
| 80 | 80 | ".skip -(((5f-4f) - (2b-1b)) > 0) * " |
| 81 | 81 | "((5f-4f) - (2b-1b)),0x90\n" |
| @@ -379,7 +379,7 @@ config X86_CMOV · 378 unmodified lines | ||
| 379 | 379 | config X86_MINIMUM_CPU_FAMILY |
| 380 | 380 | int |
| 381 | 381 | default "64" if X86_64 |
| 382 | − default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCRUSOE || MCORE2 || MK7 || MK8) | |
| 382 | + default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCORE2 || MK7 || MK8) | |
| 383 | 383 | default "5" if X86_32 && X86_CMPXCHG64 |
| 384 | 384 | default "4" |
| 385 | 385 | |
| @@ -112,13 +112,13 @@ ifeq ($(CONFIG_X86_32),y) · 111 unmodified lines | ||
| 112 | 112 | # temporary until string.h is fixed |
| 113 | 113 | KBUILD_CFLAGS += -ffreestanding |
| 114 | 114 | |
| 115 | − ifeq ($(CONFIG_STACKPROTECTOR),y) | |
| 116 | − ifeq ($(CONFIG_SMP),y) | |
| 115 | + ifeq ($(CONFIG_STACKPROTECTOR),y) | |
| 116 | + ifeq ($(CONFIG_SMP),y) | |
| 117 | 117 | KBUILD_CFLAGS += -mstack-protector-guard-reg=fs -mstack-protector-guard-symbol=__stack_chk_guard |
| 118 | − else | |
| 118 | + else | |
| 119 | 119 | KBUILD_CFLAGS += -mstack-protector-guard=global |
| 120 | − endif | |
| 121 | − endif | |
| 120 | + endif | |
| 121 | + endif | |
| 122 | 122 | else |
| 123 | 123 | BITS := 64 |
| 124 | 124 | UTS_MACHINE := x86_64 |
| @@ -106,8 +106,7 @@ extra_header_fields: · 105 unmodified lines | ||
| 106 | 106 | .word 0 # MinorSubsystemVersion |
| 107 | 107 | .long 0 # Win32VersionValue |
| 108 | 108 | |
| 109 | − .long setup_size + ZO__end + pecompat_vsize | |
| 110 | − # SizeOfImage | |
| 109 | + .long setup_size + ZO__end # SizeOfImage | |
| 111 | 110 | |
| 112 | 111 | .long salign # SizeOfHeaders |
| 113 | 112 | .long 0 # CheckSum |
| @@ -143,7 +142,7 @@ section_table: · 29 unmodified lines | ||
| 143 | 142 | .ascii ".setup" |
| 144 | 143 | .byte 0 |
| 145 | 144 | .byte 0 |
| 146 | − .long setup_size - salign # VirtualSize | |
| 145 | + .long pecompat_fstart - salign # VirtualSize | |
| 147 | 146 | .long salign # VirtualAddress |
| 148 | 147 | .long pecompat_fstart - salign # SizeOfRawData |
| 149 | 148 | .long salign # PointerToRawData |
| @@ -156,8 +155,8 @@ section_table: · 6 unmodified lines | ||
| 156 | 155 | #ifdef CONFIG_EFI_MIXED |
| 157 | 156 | .asciz ".compat" |
| 158 | 157 | |
| 159 | − .long 8 # VirtualSize | |
| 160 | − .long setup_size + ZO__end # VirtualAddress | |
| 158 | + .long pecompat_fsize # VirtualSize | |
| 159 | + .long pecompat_fstart # VirtualAddress | |
| 161 | 160 | .long pecompat_fsize # SizeOfRawData |
| 162 | 161 | .long pecompat_fstart # PointerToRawData |
| 163 | 162 | |
| @@ -172,17 +171,16 @@ section_table: · 8 unmodified lines | ||
| 172 | 171 | * modes this image supports. |
| 173 | 172 | */ |
| 174 | 173 | .pushsection ".pecompat", "a", @progbits |
| 175 | − .balign falign | |
| 176 | − .set pecompat_vsize, salign | |
| 174 | + .balign salign | |
| 177 | 175 | .globl pecompat_fstart |
| 178 | 176 | pecompat_fstart: |
| 179 | 177 | .byte 0x1 # Version |
| 180 | 178 | .byte 8 # Size |
| 181 | 179 | .word IMAGE_FILE_MACHINE_I386 # PE machine type |
| 182 | 180 | .long setup_size + ZO_efi32_pe_entry # Entrypoint |
| 181 | + .byte 0x0 # Sentinel | |
| 183 | 182 | .popsection |
| 184 | 183 | #else |
| 185 | − .set pecompat_vsize, 0 | |
| 186 | 184 | .set pecompat_fstart, setup_size |
| 187 | 185 | #endif |
| 188 | 186 | .ascii ".text" |
| @@ -24,6 +24,9 @@ SECTIONS · 23 unmodified lines | ||
| 24 | 24 | .text : { *(.text .text.*) } |
| 25 | 25 | .text32 : { *(.text32) } |
| 26 | 26 | |
| 27 | + .pecompat : { *(.pecompat) } | |
| 28 | + PROVIDE(pecompat_fsize = setup_size - pecompat_fstart); | |
| 29 | + | |
| 27 | 30 | . = ALIGN(16); |
| 28 | 31 | .rodata : { *(.rodata*) } |
| 29 | 32 | |
| @@ -36,9 +39,6 @@ SECTIONS · 6 unmodified lines | ||
| 36 | 39 | . = ALIGN(16); |
| 37 | 40 | .data : { *(.data*) } |
| 38 | 41 | |
| 39 | − .pecompat : { *(.pecompat) } | |
| 40 | − PROVIDE(pecompat_fsize = setup_size - pecompat_fstart); | |
| 41 | − | |
| 42 | 42 | .signature : { |
| 43 | 43 | setup_sig = .; |
| 44 | 44 | LONG(0x5a5aaa55) |
| @@ -10,13 +10,14 @@ enum cc_vendor { · 9 unmodified lines | ||
| 10 | 10 | CC_VENDOR_INTEL, |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | −extern enum cc_vendor cc_vendor; | |
| 14 | − | |
| 15 | 13 | #ifdef CONFIG_ARCH_HAS_CC_PLATFORM |
| 14 | +extern enum cc_vendor cc_vendor; | |
| 16 | 15 | void cc_set_mask(u64 mask); |
| 17 | 16 | u64 cc_mkenc(u64 val); |
| 18 | 17 | u64 cc_mkdec(u64 val); |
| 19 | 18 | #else |
| 19 | +#define cc_vendor (CC_VENDOR_NONE) | |
| 20 | + | |
| 20 | 21 | static inline u64 cc_mkenc(u64 val) |
| 21 | 22 | { |
| 22 | 23 | return val; |
| @@ -168,7 +168,7 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); · 167 unmodified lines | ||
| 168 | 168 | */ |
| 169 | 169 | static __always_inline bool _static_cpu_has(u16 bit) |
| 170 | 170 | { |
| 171 | − asm_volatile_goto( | |
| 171 | + asm goto( | |
| 172 | 172 | ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]") |
| 173 | 173 | ".pushsection .altinstr_aux,\"ax\"\n" |
| 174 | 174 | "6:\n" |
| @@ -81,10 +81,8 @@ · 80 unmodified lines | ||
| 81 | 81 | #define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ |
| 82 | 82 | #define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ |
| 83 | 83 | #define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ |
| 84 | − | |
| 85 | −/* CPU types for specific tunings: */ | |
| 86 | 84 | #define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ |
| 87 | −/* FREE, was #define X86_FEATURE_K7 ( 3*32+ 5) "" Athlon */ | |
| 85 | +#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* "" CPU based on Zen5 microarchitecture */ | |
| 88 | 86 | #define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ |
| 89 | 87 | #define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ |
| 90 | 88 | #define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ |
| @@ -162,6 +162,8 @@ · 161 unmodified lines | ||
| 162 | 162 | #define INTEL_FAM6_ATOM_CRESTMONT_X 0xAF /* Sierra Forest */ |
| 163 | 163 | #define INTEL_FAM6_ATOM_CRESTMONT 0xB6 /* Grand Ridge */ |
| 164 | 164 | |
| 165 | +#define INTEL_FAM6_ATOM_DARKMONT_X 0xDD /* Clearwater Forest */ | |
| 166 | + | |
| 165 | 167 | /* Xeon Phi */ |
| 166 | 168 | |
| 167 | 169 | #define INTEL_FAM6_XEON_PHI_KNL 0x57 /* Knights Landing */ |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
| 26 | 26 | { |
| 27 | − asm_volatile_goto("1:" | |
| 27 | + asm goto("1:" | |
| 28 | 28 | "jmp %l[l_yes] # objtool NOPs this \n\t" |
| 29 | 29 | JUMP_TABLE_ENTRY |
| 30 | 30 | : : "i" (key), "i" (2 | branch) : : l_yes); |
| @@ -38,7 +38,7 @@ l_yes: · 7 unmodified lines | ||
| 38 | 38 | |
| 39 | 39 | static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch) |
| 40 | 40 | { |
| 41 | − asm_volatile_goto("1:" | |
| 41 | + asm goto("1:" | |
| 42 | 42 | ".byte " __stringify(BYTES_NOP5) "\n\t" |
| 43 | 43 | JUMP_TABLE_ENTRY |
| 44 | 44 | : : "i" (key), "i" (branch) : : l_yes); |
| @@ -52,7 +52,7 @@ l_yes: · 7 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch) |
| 54 | 54 | { |
| 55 | − asm_volatile_goto("1:" | |
| 55 | + asm goto("1:" | |
| 56 | 56 | "jmp %l[l_yes]\n\t" |
| 57 | 57 | JUMP_TABLE_ENTRY |
| 58 | 58 | : : "i" (key), "i" (branch) : : l_yes); |
| @@ -64,6 +64,7 @@ static inline bool kmsan_virt_addr_valid(void *addr) · 63 unmodified lines | ||
| 64 | 64 | { |
| 65 | 65 | unsigned long x = (unsigned long)addr; |
| 66 | 66 | unsigned long y = x - __START_KERNEL_map; |
| 67 | + bool ret; | |
| 67 | 68 | |
| 68 | 69 | /* use the carry flag to determine if x was < __START_KERNEL_map */ |
| 69 | 70 | if (unlikely(x > y)) { |
| @@ -79,7 +80,21 @@ static inline bool kmsan_virt_addr_valid(void *addr) · 9 unmodified lines | ||
| 79 | 80 | return false; |
| 80 | 81 | } |
| 81 | 82 | |
| 82 | − return pfn_valid(x >> PAGE_SHIFT); | |
| 83 | + /* | |
| 84 | + * pfn_valid() relies on RCU, and may call into the scheduler on exiting | |
| 85 | + * the critical section. However, this would result in recursion with | |
| 86 | + * KMSAN. Therefore, disable preemption here, and re-enable preemption | |
| 87 | + * below while suppressing reschedules to avoid recursion. | |
| 88 | + * | |
| 89 | + * Note, this sacrifices occasionally breaking scheduling guarantees. | |
| 90 | + * Although, a kernel compiled with KMSAN has already given up on any | |
| 91 | + * performance guarantees due to being heavily instrumented. | |
| 92 | + */ | |
| 93 | + preempt_disable(); | |
| 94 | + ret = pfn_valid(x >> PAGE_SHIFT); | |
| 95 | + preempt_enable_no_resched(); | |
| 96 | + | |
| 97 | + return ret; | |
| 83 | 98 | } |
| 84 | 99 | |
| 85 | 100 | #endif /* !MODULE */ |
| @@ -1145,6 +1145,8 @@ struct kvm_hv { · 1144 unmodified lines | ||
| 1145 | 1145 | unsigned int synic_auto_eoi_used; |
| 1146 | 1146 | |
| 1147 | 1147 | struct kvm_hv_syndbg hv_syndbg; |
| 1148 | + | |
| 1149 | + bool xsaves_xsavec_checked; | |
| 1148 | 1150 | }; |
| 1149 | 1151 | #endif |
| 1150 | 1152 | |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #define __GEN_RMWcc(fullop, _var, cc, clobbers, ...) \ |
| 14 | 14 | ({ \ |
| 15 | 15 | bool c = false; \ |
| 16 | − asm_volatile_goto (fullop "; j" #cc " %l[cc_label]" \ | |
| 16 | + asm goto (fullop "; j" #cc " %l[cc_label]" \ | |
| 17 | 17 | : : [var] "m" (_var), ## __VA_ARGS__ \ |
| 18 | 18 | : clobbers : cc_label); \ |
| 19 | 19 | if (0) { \ |
| @@ -205,7 +205,7 @@ static inline void clwb(volatile void *__p) · 204 unmodified lines | ||
| 205 | 205 | #ifdef CONFIG_X86_USER_SHADOW_STACK |
| 206 | 206 | static inline int write_user_shstk_64(u64 __user *addr, u64 val) |
| 207 | 207 | { |
| 208 | − asm_volatile_goto("1: wrussq %[val], (%[addr])\n" | |
| 208 | + asm goto("1: wrussq %[val], (%[addr])\n" | |
| 209 | 209 | _ASM_EXTABLE(1b, %l[fail]) |
| 210 | 210 | :: [addr] "r" (addr), [val] "r" (val) |
| 211 | 211 | :: fail); |
| @@ -58,12 +58,29 @@ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs); · 57 unmodified lines | ||
| 58 | 58 | ,,regs->di,,regs->si,,regs->dx \ |
| 59 | 59 | ,,regs->r10,,regs->r8,,regs->r9) \ |
| 60 | 60 | |
| 61 | + | |
| 62 | +/* SYSCALL_PT_ARGS is Adapted from s390x */ | |
| 63 | +#define SYSCALL_PT_ARG6(m, t1, t2, t3, t4, t5, t6) \ | |
| 64 | + SYSCALL_PT_ARG5(m, t1, t2, t3, t4, t5), m(t6, (regs->bp)) | |
| 65 | +#define SYSCALL_PT_ARG5(m, t1, t2, t3, t4, t5) \ | |
| 66 | + SYSCALL_PT_ARG4(m, t1, t2, t3, t4), m(t5, (regs->di)) | |
| 67 | +#define SYSCALL_PT_ARG4(m, t1, t2, t3, t4) \ | |
| 68 | + SYSCALL_PT_ARG3(m, t1, t2, t3), m(t4, (regs->si)) | |
| 69 | +#define SYSCALL_PT_ARG3(m, t1, t2, t3) \ | |
| 70 | + SYSCALL_PT_ARG2(m, t1, t2), m(t3, (regs->dx)) | |
| 71 | +#define SYSCALL_PT_ARG2(m, t1, t2) \ | |
| 72 | + SYSCALL_PT_ARG1(m, t1), m(t2, (regs->cx)) | |
| 73 | +#define SYSCALL_PT_ARG1(m, t1) m(t1, (regs->bx)) | |
| 74 | +#define SYSCALL_PT_ARGS(x, ...) SYSCALL_PT_ARG##x(__VA_ARGS__) | |
| 75 | + | |
| 76 | +#define __SC_COMPAT_CAST(t, a) \ | |
| 77 | + (__typeof(__builtin_choose_expr(__TYPE_IS_L(t), 0, 0U))) \ | |
| 78 | + (unsigned int)a | |
| 79 | + | |
| 61 | 80 | /* Mapping of registers to parameters for syscalls on i386 */ |
| 62 | 81 | #define SC_IA32_REGS_TO_ARGS(x, ...) \ |
| 63 | − __MAP(x,__SC_ARGS \ | |
| 64 | − ,,(unsigned int)regs->bx,,(unsigned int)regs->cx \ | |
| 65 | − ,,(unsigned int)regs->dx,,(unsigned int)regs->si \ | |
| 66 | − ,,(unsigned int)regs->di,,(unsigned int)regs->bp) | |
| 82 | + SYSCALL_PT_ARGS(x, __SC_COMPAT_CAST, \ | |
| 83 | + __MAP(x, __SC_TYPE, __VA_ARGS__)) \ | |
| 67 | 84 | |
| 68 | 85 | #define __SYS_STUB0(abi, name) \ |
| 69 | 86 | long __##abi##_##name(const struct pt_regs *regs); \ |
| @@ -133,7 +133,7 @@ extern int __get_user_bad(void); · 132 unmodified lines | ||
| 133 | 133 | |
| 134 | 134 | #ifdef CONFIG_X86_32 |
| 135 | 135 | #define __put_user_goto_u64(x, addr, label) \ |
| 136 | − asm_volatile_goto("\n" \ | |
| 136 | + asm goto("\n" \ | |
| 137 | 137 | "1: movl %%eax,0(%1)\n" \ |
| 138 | 138 | "2: movl %%edx,4(%1)\n" \ |
| 139 | 139 | _ASM_EXTABLE_UA(1b, %l2) \ |
| @@ -295,7 +295,7 @@ do { \ · 155 unmodified lines | ||
| 295 | 295 | } while (0) |
| 296 | 296 | |
| 297 | 297 | #define __get_user_asm(x, addr, itype, ltype, label) \ |
| 298 | − asm_volatile_goto("\n" \ | |
| 298 | + asm_goto_output("\n" \ | |
| 299 | 299 | "1: mov"itype" %[umem],%[output]\n" \ |
| 300 | 300 | _ASM_EXTABLE_UA(1b, %l2) \ |
| 301 | 301 | : [output] ltype(x) \ |
| @@ -375,7 +375,7 @@ do { \ · 73 unmodified lines | ||
| 375 | 375 | __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ |
| 376 | 376 | __typeof__(*(_ptr)) __old = *_old; \ |
| 377 | 377 | __typeof__(*(_ptr)) __new = (_new); \ |
| 378 | − asm_volatile_goto("\n" \ | |
| 378 | + asm_goto_output("\n" \ | |
| 379 | 379 | "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\ |
| 380 | 380 | _ASM_EXTABLE_UA(1b, %l[label]) \ |
| 381 | 381 | : CC_OUT(z) (success), \ |
| @@ -394,7 +394,7 @@ do { \ · 12 unmodified lines | ||
| 394 | 394 | __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold); \ |
| 395 | 395 | __typeof__(*(_ptr)) __old = *_old; \ |
| 396 | 396 | __typeof__(*(_ptr)) __new = (_new); \ |
| 397 | − asm_volatile_goto("\n" \ | |
| 397 | + asm_goto_output("\n" \ | |
| 398 | 398 | "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n" \ |
| 399 | 399 | _ASM_EXTABLE_UA(1b, %l[label]) \ |
| 400 | 400 | : CC_OUT(z) (success), \ |
| @@ -477,7 +477,7 @@ struct __large_struct { unsigned long buf[100]; }; · 76 unmodified lines | ||
| 477 | 477 | * aliasing issues. |
| 478 | 478 | */ |
| 479 | 479 | #define __put_user_goto(x, addr, itype, ltype, label) \ |
| 480 | − asm_volatile_goto("\n" \ | |
| 480 | + asm goto("\n" \ | |
| 481 | 481 | "1: mov"itype" %0,%1\n" \ |
| 482 | 482 | _ASM_EXTABLE_UA(1b, %l2) \ |
| 483 | 483 | : : ltype(x), "m" (__m(addr)) \ |
| @@ -403,7 +403,7 @@ noinstr void BUG_func(void) · 402 unmodified lines | ||
| 403 | 403 | { |
| 404 | 404 | BUG(); |
| 405 | 405 | } |
| 406 | −EXPORT_SYMBOL_GPL(BUG_func); | |
| 406 | +EXPORT_SYMBOL(BUG_func); | |
| 407 | 407 | |
| 408 | 408 | #define CALL_RIP_REL_OPCODE 0xff |
| 409 | 409 | #define CALL_RIP_REL_MODRM 0x15 |
| @@ -538,7 +538,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) · 537 unmodified lines | ||
| 538 | 538 | |
| 539 | 539 | /* Figure out Zen generations: */ |
| 540 | 540 | switch (c->x86) { |
| 541 | − case 0x17: { | |
| 541 | + case 0x17: | |
| 542 | 542 | switch (c->x86_model) { |
| 543 | 543 | case 0x00 ... 0x2f: |
| 544 | 544 | case 0x50 ... 0x5f: |
| @@ -554,8 +554,8 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) · 9 unmodified lines | ||
| 554 | 554 | goto warn; |
| 555 | 555 | } |
| 556 | 556 | break; |
| 557 | − } | |
| 558 | − case 0x19: { | |
| 557 | + | |
| 558 | + case 0x19: | |
| 559 | 559 | switch (c->x86_model) { |
| 560 | 560 | case 0x00 ... 0x0f: |
| 561 | 561 | case 0x20 ... 0x5f: |
| @@ -569,7 +569,20 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) · 7 unmodified lines | ||
| 569 | 569 | goto warn; |
| 570 | 570 | } |
| 571 | 571 | break; |
| 572 | − } | |
| 572 | + | |
| 573 | + case 0x1a: | |
| 574 | + switch (c->x86_model) { | |
| 575 | + case 0x00 ... 0x0f: | |
| 576 | + case 0x20 ... 0x2f: | |
| 577 | + case 0x40 ... 0x4f: | |
| 578 | + case 0x70 ... 0x7f: | |
| 579 | + setup_force_cpu_cap(X86_FEATURE_ZEN5); | |
| 580 | + break; | |
| 581 | + default: | |
| 582 | + goto warn; | |
| 583 | + } | |
| 584 | + break; | |
| 585 | + | |
| 573 | 586 | default: |
| 574 | 587 | break; |
| 575 | 588 | } |
| @@ -1039,6 +1052,11 @@ static void init_amd_zen4(struct cpuinfo_x86 *c) · 463 unmodified lines | ||
| 1039 | 1052 | msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT); |
| 1040 | 1053 | } |
| 1041 | 1054 | |
| 1055 | +static void init_amd_zen5(struct cpuinfo_x86 *c) | |
| 1056 | +{ | |
| 1057 | + init_amd_zen_common(); | |
| 1058 | +} | |
| 1059 | + | |
| 1042 | 1060 | static void init_amd(struct cpuinfo_x86 *c) |
| 1043 | 1061 | { |
| 1044 | 1062 | u64 vm_cr; |
| @@ -1084,6 +1102,8 @@ static void init_amd(struct cpuinfo_x86 *c) · 39 unmodified lines | ||
| 1084 | 1102 | init_amd_zen3(c); |
| 1085 | 1103 | else if (boot_cpu_has(X86_FEATURE_ZEN4)) |
| 1086 | 1104 | init_amd_zen4(c); |
| 1105 | + else if (boot_cpu_has(X86_FEATURE_ZEN5)) | |
| 1106 | + init_amd_zen5(c); | |
| 1087 | 1107 | |
| 1088 | 1108 | /* |
| 1089 | 1109 | * Enable workaround for FXSAVE leak on CPUs |
| @@ -274,12 +274,13 @@ static int __restore_fpregs_from_user(void __user *buf, u64 ufeatures, · 273 unmodified lines | ||
| 274 | 274 | * Attempt to restore the FPU registers directly from user memory. |
| 275 | 275 | * Pagefaults are handled and any errors returned are fatal. |
| 276 | 276 | */ |
| 277 | −static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, | |
| 278 | − bool fx_only, unsigned int size) | |
| 277 | +static bool restore_fpregs_from_user(void __user *buf, u64 xrestore, bool fx_only) | |
| 279 | 278 | { |
| 280 | 279 | struct fpu *fpu = ¤t->thread.fpu; |
| 281 | 280 | int ret; |
| 282 | 281 | |
| 282 | + /* Restore enabled features only. */ | |
| 283 | + xrestore &= fpu->fpstate->user_xfeatures; | |
| 283 | 284 | retry: |
| 284 | 285 | fpregs_lock(); |
| 285 | 286 | /* Ensure that XFD is up to date */ |
| @@ -309,7 +310,7 @@ retry: · 23 unmodified lines | ||
| 309 | 310 | if (ret != X86_TRAP_PF) |
| 310 | 311 | return false; |
| 311 | 312 | |
| 312 | − if (!fault_in_readable(buf, size)) | |
| 313 | + if (!fault_in_readable(buf, fpu->fpstate->user_size)) | |
| 313 | 314 | goto retry; |
| 314 | 315 | return false; |
| 315 | 316 | } |
| @@ -339,7 +340,6 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx, · 23 unmodified lines | ||
| 339 | 340 | struct user_i387_ia32_struct env; |
| 340 | 341 | bool success, fx_only = false; |
| 341 | 342 | union fpregs_state *fpregs; |
| 342 | − unsigned int state_size; | |
| 343 | 343 | u64 user_xfeatures = 0; |
| 344 | 344 | |
| 345 | 345 | if (use_xsave()) { |
| @@ -349,17 +349,14 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx, · 3 unmodified lines | ||
| 349 | 349 | return false; |
| 350 | 350 | |
| 351 | 351 | fx_only = !fx_sw_user.magic1; |
| 352 | − state_size = fx_sw_user.xstate_size; | |
| 353 | 352 | user_xfeatures = fx_sw_user.xfeatures; |
| 354 | 353 | } else { |
| 355 | 354 | user_xfeatures = XFEATURE_MASK_FPSSE; |
| 356 | − state_size = fpu->fpstate->user_size; | |
| 357 | 355 | } |
| 358 | 356 | |
| 359 | 357 | if (likely(!ia32_fxstate)) { |
| 360 | 358 | /* Restore the FPU registers directly from user memory. */ |
| 361 | − return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only, | |
| 362 | − state_size); | |
| 359 | + return restore_fpregs_from_user(buf_fx, user_xfeatures, fx_only); | |
| 363 | 360 | } |
| 364 | 361 | |
| 365 | 362 | /* |
| @@ -434,7 +434,8 @@ static void __init sev_map_percpu_data(void) · 433 unmodified lines | ||
| 434 | 434 | { |
| 435 | 435 | int cpu; |
| 436 | 436 | |
| 437 | − if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | |
| 437 | + if (cc_vendor != CC_VENDOR_AMD || | |
| 438 | + !cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | |
| 438 | 439 | return; |
| 439 | 440 | |
| 440 | 441 | for_each_possible_cpu(cpu) { |
| @@ -1322,6 +1322,56 @@ static bool hv_check_msr_access(struct kvm_vcpu_hv *hv_vcpu, u32 msr) · 1321 unmodified lines | ||
| 1322 | 1322 | return false; |
| 1323 | 1323 | } |
| 1324 | 1324 | |
| 1325 | +#define KVM_HV_WIN2016_GUEST_ID 0x1040a00003839 | |
| 1326 | +#define KVM_HV_WIN2016_GUEST_ID_MASK (~GENMASK_ULL(23, 16)) /* mask out the service version */ | |
| 1327 | + | |
| 1328 | +/* | |
| 1329 | + * Hyper-V enabled Windows Server 2016 SMP VMs fail to boot in !XSAVES && XSAVEC | |
| 1330 | + * configuration. | |
| 1331 | + * Such configuration can result from, for example, AMD Erratum 1386 workaround. | |
| 1332 | + * | |
| 1333 | + * Print a notice so users aren't left wondering what's suddenly gone wrong. | |
| 1334 | + */ | |
| 1335 | +static void __kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) | |
| 1336 | +{ | |
| 1337 | + struct kvm *kvm = vcpu->kvm; | |
| 1338 | + struct kvm_hv *hv = to_kvm_hv(kvm); | |
| 1339 | + | |
| 1340 | + /* Check again under the hv_lock. */ | |
| 1341 | + if (hv->xsaves_xsavec_checked) | |
| 1342 | + return; | |
| 1343 | + | |
| 1344 | + if ((hv->hv_guest_os_id & KVM_HV_WIN2016_GUEST_ID_MASK) != | |
| 1345 | + KVM_HV_WIN2016_GUEST_ID) | |
| 1346 | + return; | |
| 1347 | + | |
| 1348 | + hv->xsaves_xsavec_checked = true; | |
| 1349 | + | |
| 1350 | + /* UP configurations aren't affected */ | |
| 1351 | + if (atomic_read(&kvm->online_vcpus) < 2) | |
| 1352 | + return; | |
| 1353 | + | |
| 1354 | + if (guest_cpuid_has(vcpu, X86_FEATURE_XSAVES) || | |
| 1355 | + !guest_cpuid_has(vcpu, X86_FEATURE_XSAVEC)) | |
| 1356 | + return; | |
| 1357 | + | |
| 1358 | + pr_notice_ratelimited("Booting SMP Windows KVM VM with !XSAVES && XSAVEC. " | |
| 1359 | + "If it fails to boot try disabling XSAVEC in the VM config.\n"); | |
| 1360 | +} | |
| 1361 | + | |
| 1362 | +void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) | |
| 1363 | +{ | |
| 1364 | + struct kvm_hv *hv = to_kvm_hv(vcpu->kvm); | |
| 1365 | + | |
| 1366 | + if (!vcpu->arch.hyperv_enabled || | |
| 1367 | + hv->xsaves_xsavec_checked) | |
| 1368 | + return; | |
| 1369 | + | |
| 1370 | + mutex_lock(&hv->hv_lock); | |
| 1371 | + __kvm_hv_xsaves_xsavec_maybe_warn(vcpu); | |
| 1372 | + mutex_unlock(&hv->hv_lock); | |
| 1373 | +} | |
| 1374 | + | |
| 1325 | 1375 | static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data, |
| 1326 | 1376 | bool host) |
| 1327 | 1377 | { |
| @@ -182,6 +182,8 @@ void kvm_hv_setup_tsc_page(struct kvm *kvm, · 181 unmodified lines | ||
| 182 | 182 | struct pvclock_vcpu_time_info *hv_clock); |
| 183 | 183 | void kvm_hv_request_tsc_page_update(struct kvm *kvm); |
| 184 | 184 | |
| 185 | +void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu); | |
| 186 | + | |
| 185 | 187 | void kvm_hv_init_vm(struct kvm *kvm); |
| 186 | 188 | void kvm_hv_destroy_vm(struct kvm *kvm); |
| 187 | 189 | int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); |
| @@ -267,6 +269,7 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu); · 79 unmodified lines | ||
| 267 | 269 | static inline void kvm_hv_setup_tsc_page(struct kvm *kvm, |
| 268 | 270 | struct pvclock_vcpu_time_info *hv_clock) {} |
| 269 | 271 | static inline void kvm_hv_request_tsc_page_update(struct kvm *kvm) {} |
| 272 | +static inline void kvm_hv_xsaves_xsavec_maybe_warn(struct kvm_vcpu *vcpu) {} | |
| 270 | 273 | static inline void kvm_hv_init_vm(struct kvm *kvm) {} |
| 271 | 274 | static inline void kvm_hv_destroy_vm(struct kvm *kvm) {} |
| 272 | 275 | static inline int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) |
| @@ -8,7 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #define svm_asm(insn, clobber...) \ |
| 10 | 10 | do { \ |
| 11 | − asm_volatile_goto("1: " __stringify(insn) "\n\t" \ | |
| 11 | + asm goto("1: " __stringify(insn) "\n\t" \ | |
| 12 | 12 | _ASM_EXTABLE(1b, %l[fault]) \ |
| 13 | 13 | ::: clobber : fault); \ |
| 14 | 14 | return; \ |
| @@ -18,7 +18,7 @@ fault: \ · 3 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #define svm_asm1(insn, op1, clobber...) \ |
| 20 | 20 | do { \ |
| 21 | − asm_volatile_goto("1: " __stringify(insn) " %0\n\t" \ | |
| 21 | + asm goto("1: " __stringify(insn) " %0\n\t" \ | |
| 22 | 22 | _ASM_EXTABLE(1b, %l[fault]) \ |
| 23 | 23 | :: op1 : clobber : fault); \ |
| 24 | 24 | return; \ |
| @@ -28,7 +28,7 @@ fault: \ · 3 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | #define svm_asm2(insn, op1, op2, clobber...) \ |
| 30 | 30 | do { \ |
| 31 | − asm_volatile_goto("1: " __stringify(insn) " %1, %0\n\t" \ | |
| 31 | + asm goto("1: " __stringify(insn) " %1, %0\n\t" \ | |
| 32 | 32 | _ASM_EXTABLE(1b, %l[fault]) \ |
| 33 | 33 | :: op1, op2 : clobber : fault); \ |
| 34 | 34 | return; \ |
| @@ -738,7 +738,7 @@ static int vmx_set_guest_uret_msr(struct vcpu_vmx *vmx, · 737 unmodified lines | ||
| 738 | 738 | */ |
| 739 | 739 | static int kvm_cpu_vmxoff(void) |
| 740 | 740 | { |
| 741 | − asm_volatile_goto("1: vmxoff\n\t" | |
| 741 | + asm goto("1: vmxoff\n\t" | |
| 742 | 742 | _ASM_EXTABLE(1b, %l[fault]) |
| 743 | 743 | ::: "cc", "memory" : fault); |
| 744 | 744 | |
| @@ -2784,7 +2784,7 @@ static int kvm_cpu_vmxon(u64 vmxon_pointer) · 2039 unmodified lines | ||
| 2784 | 2784 | |
| 2785 | 2785 | cr4_set_bits(X86_CR4_VMXE); |
| 2786 | 2786 | |
| 2787 | − asm_volatile_goto("1: vmxon %[vmxon_pointer]\n\t" | |
| 2787 | + asm goto("1: vmxon %[vmxon_pointer]\n\t" | |
| 2788 | 2788 | _ASM_EXTABLE(1b, %l[fault]) |
| 2789 | 2789 | : : [vmxon_pointer] "m"(vmxon_pointer) |
| 2790 | 2790 | : : fault); |
| @@ -94,7 +94,7 @@ static __always_inline unsigned long __vmcs_readl(unsigned long field) · 93 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT |
| 96 | 96 | |
| 97 | − asm_volatile_goto("1: vmread %[field], %[output]\n\t" | |
| 97 | + asm_goto_output("1: vmread %[field], %[output]\n\t" | |
| 98 | 98 | "jna %l[do_fail]\n\t" |
| 99 | 99 | |
| 100 | 100 | _ASM_EXTABLE(1b, %l[do_exception]) |
| @@ -188,7 +188,7 @@ static __always_inline unsigned long vmcs_readl(unsigned long field) · 87 unmodified lines | ||
| 188 | 188 | |
| 189 | 189 | #define vmx_asm1(insn, op1, error_args...) \ |
| 190 | 190 | do { \ |
| 191 | − asm_volatile_goto("1: " __stringify(insn) " %0\n\t" \ | |
| 191 | + asm goto("1: " __stringify(insn) " %0\n\t" \ | |
| 192 | 192 | ".byte 0x2e\n\t" /* branch not taken hint */ \ |
| 193 | 193 | "jna %l[error]\n\t" \ |
| 194 | 194 | _ASM_EXTABLE(1b, %l[fault]) \ |
| @@ -205,7 +205,7 @@ fault: \ · 10 unmodified lines | ||
| 205 | 205 | |
| 206 | 206 | #define vmx_asm2(insn, op1, op2, error_args...) \ |
| 207 | 207 | do { \ |
| 208 | − asm_volatile_goto("1: " __stringify(insn) " %1, %0\n\t" \ | |
| 208 | + asm goto("1: " __stringify(insn) " %1, %0\n\t" \ | |
| 209 | 209 | ".byte 0x2e\n\t" /* branch not taken hint */ \ |
| 210 | 210 | "jna %l[error]\n\t" \ |
| 211 | 211 | _ASM_EXTABLE(1b, %l[fault]) \ |
| @@ -1782,6 +1782,10 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info) · 1781 unmodified lines | ||
| 1782 | 1782 | if ((efer ^ old_efer) & KVM_MMU_EFER_ROLE_BITS) |
| 1783 | 1783 | kvm_mmu_reset_context(vcpu); |
| 1784 | 1784 | |
| 1785 | + if (!static_cpu_has(X86_FEATURE_XSAVES) && | |
| 1786 | + (efer & EFER_SVME)) | |
| 1787 | + kvm_hv_xsaves_xsavec_maybe_warn(vcpu); | |
| 1788 | + | |
| 1785 | 1789 | return 0; |
| 1786 | 1790 | } |
| 1787 | 1791 | |
| @@ -7016,6 +7020,9 @@ set_identity_unlock: · 5228 unmodified lines | ||
| 7016 | 7020 | r = -EEXIST; |
| 7017 | 7021 | if (kvm->arch.vpit) |
| 7018 | 7022 | goto create_pit_unlock; |
| 7023 | + r = -ENOENT; | |
| 7024 | + if (!pic_in_kernel(kvm)) | |
| 7025 | + goto create_pit_unlock; | |
| 7019 | 7026 | r = -ENOMEM; |
| 7020 | 7027 | kvm->arch.vpit = kvm_create_pit(kvm, u.pit_config.flags); |
| 7021 | 7028 | if (kvm->arch.vpit) |
| @@ -163,23 +163,23 @@ SYM_CODE_END(__get_user_8_handle_exception) · 162 unmodified lines | ||
| 163 | 163 | #endif |
| 164 | 164 | |
| 165 | 165 | /* get_user */ |
| 166 | − _ASM_EXTABLE(1b, __get_user_handle_exception) | |
| 167 | − _ASM_EXTABLE(2b, __get_user_handle_exception) | |
| 168 | − _ASM_EXTABLE(3b, __get_user_handle_exception) | |
| 166 | + _ASM_EXTABLE_UA(1b, __get_user_handle_exception) | |
| 167 | + _ASM_EXTABLE_UA(2b, __get_user_handle_exception) | |
| 168 | + _ASM_EXTABLE_UA(3b, __get_user_handle_exception) | |
| 169 | 169 | #ifdef CONFIG_X86_64 |
| 170 | − _ASM_EXTABLE(4b, __get_user_handle_exception) | |
| 170 | + _ASM_EXTABLE_UA(4b, __get_user_handle_exception) | |
| 171 | 171 | #else |
| 172 | − _ASM_EXTABLE(4b, __get_user_8_handle_exception) | |
| 173 | − _ASM_EXTABLE(5b, __get_user_8_handle_exception) | |
| 172 | + _ASM_EXTABLE_UA(4b, __get_user_8_handle_exception) | |
| 173 | + _ASM_EXTABLE_UA(5b, __get_user_8_handle_exception) | |
| 174 | 174 | #endif |
| 175 | 175 | |
| 176 | 176 | /* __get_user */ |
| 177 | − _ASM_EXTABLE(6b, __get_user_handle_exception) | |
| 178 | − _ASM_EXTABLE(7b, __get_user_handle_exception) | |
| 179 | − _ASM_EXTABLE(8b, __get_user_handle_exception) | |
| 177 | + _ASM_EXTABLE_UA(6b, __get_user_handle_exception) | |
| 178 | + _ASM_EXTABLE_UA(7b, __get_user_handle_exception) | |
| 179 | + _ASM_EXTABLE_UA(8b, __get_user_handle_exception) | |
| 180 | 180 | #ifdef CONFIG_X86_64 |
| 181 | − _ASM_EXTABLE(9b, __get_user_handle_exception) | |
| 181 | + _ASM_EXTABLE_UA(9b, __get_user_handle_exception) | |
| 182 | 182 | #else |
| 183 | − _ASM_EXTABLE(9b, __get_user_8_handle_exception) | |
| 184 | − _ASM_EXTABLE(10b, __get_user_8_handle_exception) | |
| 183 | + _ASM_EXTABLE_UA(9b, __get_user_8_handle_exception) | |
| 184 | + _ASM_EXTABLE_UA(10b, __get_user_8_handle_exception) | |
| 185 | 185 | #endif |
| @@ -133,15 +133,15 @@ SYM_CODE_START_LOCAL(__put_user_handle_exception) · 132 unmodified lines | ||
| 133 | 133 | RET |
| 134 | 134 | SYM_CODE_END(__put_user_handle_exception) |
| 135 | 135 | |
| 136 | − _ASM_EXTABLE(1b, __put_user_handle_exception) | |
| 137 | − _ASM_EXTABLE(2b, __put_user_handle_exception) | |
| 138 | − _ASM_EXTABLE(3b, __put_user_handle_exception) | |
| 139 | − _ASM_EXTABLE(4b, __put_user_handle_exception) | |
| 140 | − _ASM_EXTABLE(5b, __put_user_handle_exception) | |
| 141 | − _ASM_EXTABLE(6b, __put_user_handle_exception) | |
| 142 | − _ASM_EXTABLE(7b, __put_user_handle_exception) | |
| 143 | − _ASM_EXTABLE(9b, __put_user_handle_exception) | |
| 136 | + _ASM_EXTABLE_UA(1b, __put_user_handle_exception) | |
| 137 | + _ASM_EXTABLE_UA(2b, __put_user_handle_exception) | |
| 138 | + _ASM_EXTABLE_UA(3b, __put_user_handle_exception) | |
| 139 | + _ASM_EXTABLE_UA(4b, __put_user_handle_exception) | |
| 140 | + _ASM_EXTABLE_UA(5b, __put_user_handle_exception) | |
| 141 | + _ASM_EXTABLE_UA(6b, __put_user_handle_exception) | |
| 142 | + _ASM_EXTABLE_UA(7b, __put_user_handle_exception) | |
| 143 | + _ASM_EXTABLE_UA(9b, __put_user_handle_exception) | |
| 144 | 144 | #ifdef CONFIG_X86_32 |
| 145 | − _ASM_EXTABLE(8b, __put_user_handle_exception) | |
| 146 | − _ASM_EXTABLE(10b, __put_user_handle_exception) | |
| 145 | + _ASM_EXTABLE_UA(8b, __put_user_handle_exception) | |
| 146 | + _ASM_EXTABLE_UA(10b, __put_user_handle_exception) | |
| 147 | 147 | #endif |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | static __always_inline bool arch_static_branch(struct static_key *key, |
| 14 | 14 | bool branch) |
| 15 | 15 | { |
| 16 | − asm_volatile_goto("1:\n\t" | |
| 16 | + asm goto("1:\n\t" | |
| 17 | 17 | "_nop\n\t" |
| 18 | 18 | ".pushsection __jump_table, \"aw\"\n\t" |
| 19 | 19 | ".word 1b, %l[l_yes], %c0\n\t" |
| @@ -38,7 +38,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, · 18 unmodified lines | ||
| 38 | 38 | * make it reachable and wrap both into a no-transform block |
| 39 | 39 | * to avoid any assembler interference with this. |
| 40 | 40 | */ |
| 41 | − asm_volatile_goto("1:\n\t" | |
| 41 | + asm goto("1:\n\t" | |
| 42 | 42 | ".begin no-transform\n\t" |
| 43 | 43 | "_j %l[l_yes]\n\t" |
| 44 | 44 | "2:\n\t" |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #include "blk-pm.h" |
| 50 | 50 | #include "blk-cgroup.h" |
| 51 | 51 | #include "blk-throttle.h" |
| 52 | +#include "blk-ioprio.h" | |
| 52 | 53 | |
| 53 | 54 | struct dentry *blk_debugfs_root; |
| 54 | 55 | |
| @@ -833,6 +834,14 @@ end_io: · 778 unmodified lines | ||
| 833 | 834 | } |
| 834 | 835 | EXPORT_SYMBOL(submit_bio_noacct); |
| 835 | 836 | |
| 837 | +static void bio_set_ioprio(struct bio *bio) | |
| 838 | +{ | |
| 839 | + /* Nobody set ioprio so far? Initialize it based on task's nice value */ | |
| 840 | + if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE) | |
| 841 | + bio->bi_ioprio = get_current_ioprio(); | |
| 842 | + blkcg_set_ioprio(bio); | |
| 843 | +} | |
| 844 | + | |
| 836 | 845 | /** |
| 837 | 846 | * submit_bio - submit a bio to the block device layer for I/O |
| 838 | 847 | * @bio: The &struct bio which describes the I/O |
| @@ -855,6 +864,7 @@ void submit_bio(struct bio *bio) · 16 unmodified lines | ||
| 855 | 864 | count_vm_events(PGPGOUT, bio_sectors(bio)); |
| 856 | 865 | } |
| 857 | 866 | |
| 867 | + bio_set_ioprio(bio); | |
| 858 | 868 | submit_bio_noacct(bio); |
| 859 | 869 | } |
| 860 | 870 | EXPORT_SYMBOL(submit_bio); |
| @@ -1353,6 +1353,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) · 1352 unmodified lines | ||
| 1353 | 1353 | |
| 1354 | 1354 | lockdep_assert_held(&iocg->waitq.lock); |
| 1355 | 1355 | |
| 1356 | + /* | |
| 1357 | + * If the delay is set by another CPU, we may be in the past. No need to | |
| 1358 | + * change anything if so. This avoids decay calculation underflow. | |
| 1359 | + */ | |
| 1360 | + if (time_before64(now->now, iocg->delay_at)) | |
| 1361 | + return false; | |
| 1362 | + | |
| 1356 | 1363 | /* calculate the current delay in effect - 1/2 every second */ |
| 1357 | 1364 | tdelta = now->now - iocg->delay_at; |
| 1358 | 1365 | if (iocg->delay) |
| @@ -205,12 +205,19 @@ static int bio_copy_user_iov(struct request *rq, struct rq_map_data *map_data, · 204 unmodified lines | ||
| 205 | 205 | /* |
| 206 | 206 | * success |
| 207 | 207 | */ |
| 208 | − if ((iov_iter_rw(iter) == WRITE && | |
| 209 | − (!map_data || !map_data->null_mapped)) || | |
| 210 | − (map_data && map_data->from_user)) { | |
| 208 | + if (iov_iter_rw(iter) == WRITE && | |
| 209 | + (!map_data || !map_data->null_mapped)) { | |
| 211 | 210 | ret = bio_copy_from_iter(bio, iter); |
| 212 | 211 | if (ret) |
| 213 | 212 | goto cleanup; |
| 213 | + } else if (map_data && map_data->from_user) { | |
| 214 | + struct iov_iter iter2 = *iter; | |
| 215 | + | |
| 216 | + /* This is the copy-in part of SG_DXFER_TO_FROM_DEV. */ | |
| 217 | + iter2.data_source = ITER_SOURCE; | |
| 218 | + ret = bio_copy_from_iter(bio, &iter2); | |
| 219 | + if (ret) | |
| 220 | + goto cleanup; | |
| 214 | 221 | } else { |
| 215 | 222 | if (bmd->is_our_pages) |
| 216 | 223 | zero_fill_bio(bio); |
| @@ -40,7 +40,6 @@ · 39 unmodified lines | ||
| 40 | 40 | #include "blk-stat.h" |
| 41 | 41 | #include "blk-mq-sched.h" |
| 42 | 42 | #include "blk-rq-qos.h" |
| 43 | −#include "blk-ioprio.h" | |
| 44 | 43 | |
| 45 | 44 | static DEFINE_PER_CPU(struct llist_head, blk_cpu_done); |
| 46 | 45 | static DEFINE_PER_CPU(call_single_data_t, blk_cpu_csd); |
| @@ -2944,14 +2943,6 @@ static bool blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug, · 2897 unmodified lines | ||
| 2944 | 2943 | return true; |
| 2945 | 2944 | } |
| 2946 | 2945 | |
| 2947 | −static void bio_set_ioprio(struct bio *bio) | |
| 2948 | −{ | |
| 2949 | − /* Nobody set ioprio so far? Initialize it based on task's nice value */ | |
| 2950 | − if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) == IOPRIO_CLASS_NONE) | |
| 2951 | − bio->bi_ioprio = get_current_ioprio(); | |
| 2952 | − blkcg_set_ioprio(bio); | |
| 2953 | −} | |
| 2954 | − | |
| 2955 | 2946 | /** |
| 2956 | 2947 | * blk_mq_submit_bio - Create and send a request to block device. |
| 2957 | 2948 | * @bio: Bio pointer. |
| @@ -2976,7 +2967,6 @@ void blk_mq_submit_bio(struct bio *bio) · 18 unmodified lines | ||
| 2976 | 2967 | blk_status_t ret; |
| 2977 | 2968 | |
| 2978 | 2969 | bio = blk_queue_bounce(bio, q); |
| 2979 | − bio_set_ioprio(bio); | |
| 2980 | 2970 | |
| 2981 | 2971 | if (plug) { |
| 2982 | 2972 | rq = rq_list_peek(&plug->cached_rq); |
| @@ -163,9 +163,9 @@ static void wb_timestamp(struct rq_wb *rwb, unsigned long *var) · 162 unmodified lines | ||
| 163 | 163 | */ |
| 164 | 164 | static bool wb_recent_wait(struct rq_wb *rwb) |
| 165 | 165 | { |
| 166 | − struct bdi_writeback *wb = &rwb->rqos.disk->bdi->wb; | |
| 166 | + struct backing_dev_info *bdi = rwb->rqos.disk->bdi; | |
| 167 | 167 | |
| 168 | − return time_before(jiffies, wb->dirty_sleep + HZ); | |
| 168 | + return time_before(jiffies, bdi->last_bdp_sleep + HZ); | |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | 171 | static inline struct rq_wait *get_rq_wait(struct rq_wb *rwb, |
| @@ -20,8 +20,6 @@ static int blkpg_do_ioctl(struct block_device *bdev, · 19 unmodified lines | ||
| 20 | 20 | struct blkpg_partition p; |
| 21 | 21 | sector_t start, length; |
| 22 | 22 | |
| 23 | − if (disk->flags & GENHD_FL_NO_PART) | |
| 24 | − return -EINVAL; | |
| 25 | 23 | if (!capable(CAP_SYS_ADMIN)) |
| 26 | 24 | return -EACCES; |
| 27 | 25 | if (copy_from_user(&p, upart, sizeof(struct blkpg_partition))) |
| @@ -439,6 +439,11 @@ int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, · 438 unmodified lines | ||
| 439 | 439 | goto out; |
| 440 | 440 | } |
| 441 | 441 | |
| 442 | + if (disk->flags & GENHD_FL_NO_PART) { | |
| 443 | + ret = -EINVAL; | |
| 444 | + goto out; | |
| 445 | + } | |
| 446 | + | |
| 442 | 447 | if (partition_overlaps(disk, start, length, -1)) { |
| 443 | 448 | ret = -EBUSY; |
| 444 | 449 | goto out; |
| @@ -91,13 +91,13 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg, · 90 unmodified lines | ||
| 91 | 91 | if (!(msg->msg_flags & MSG_MORE)) { |
| 92 | 92 | err = hash_alloc_result(sk, ctx); |
| 93 | 93 | if (err) |
| 94 | − goto unlock_free; | |
| 94 | + goto unlock_free_result; | |
| 95 | 95 | ahash_request_set_crypt(&ctx->req, NULL, |
| 96 | 96 | ctx->result, 0); |
| 97 | 97 | err = crypto_wait_req(crypto_ahash_final(&ctx->req), |
| 98 | 98 | &ctx->wait); |
| 99 | 99 | if (err) |
| 100 | − goto unlock_free; | |
| 100 | + goto unlock_free_result; | |
| 101 | 101 | } |
| 102 | 102 | goto done_more; |
| 103 | 103 | } |
| @@ -170,6 +170,7 @@ unlock: · 66 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | unlock_free: |
| 172 | 172 | af_alg_free_sg(&ctx->sgl); |
| 173 | +unlock_free_result: | |
| 173 | 174 | hash_free_result(sk, ctx); |
| 174 | 175 | ctx->more = false; |
| 175 | 176 | goto unlock; |
| @@ -148,6 +148,9 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb) · 147 unmodified lines | ||
| 148 | 148 | if (!is_power_of_2(inst->alg.co.base.cra_blocksize)) |
| 149 | 149 | goto out_free_inst; |
| 150 | 150 | |
| 151 | + if (inst->alg.co.statesize) | |
| 152 | + goto out_free_inst; | |
| 153 | + | |
| 151 | 154 | inst->alg.encrypt = crypto_cbc_encrypt; |
| 152 | 155 | inst->alg.decrypt = crypto_cbc_decrypt; |
| 153 | 156 | |
| @@ -102,7 +102,7 @@ static int reset_pending_show(struct seq_file *s, void *v) · 101 unmodified lines | ||
| 102 | 102 | { |
| 103 | 103 | struct ivpu_device *vdev = seq_to_ivpu(s); |
| 104 | 104 | |
| 105 | − seq_printf(s, "%d\n", atomic_read(&vdev->pm->in_reset)); | |
| 105 | + seq_printf(s, "%d\n", atomic_read(&vdev->pm->reset_pending)); | |
| 106 | 106 | return 0; |
| 107 | 107 | } |
| 108 | 108 | |
| @@ -130,7 +130,9 @@ dvfs_mode_fops_write(struct file *file, const char __user *user_buf, size_t size · 21 unmodified lines | ||
| 130 | 130 | |
| 131 | 131 | fw->dvfs_mode = dvfs_mode; |
| 132 | 132 | |
| 133 | − ivpu_pm_schedule_recovery(vdev); | |
| 133 | + ret = pci_try_reset_function(to_pci_dev(vdev->drm.dev)); | |
| 134 | + if (ret) | |
| 135 | + return ret; | |
| 134 | 136 | |
| 135 | 137 | return size; |
| 136 | 138 | } |
| @@ -190,7 +192,10 @@ fw_profiling_freq_fops_write(struct file *file, const char __user *user_buf, · 53 unmodified lines | ||
| 190 | 192 | return ret; |
| 191 | 193 | |
| 192 | 194 | ivpu_hw_profiling_freq_drive(vdev, enable); |
| 193 | − ivpu_pm_schedule_recovery(vdev); | |
| 195 | + | |
| 196 | + ret = pci_try_reset_function(to_pci_dev(vdev->drm.dev)); | |
| 197 | + if (ret) | |
| 198 | + return ret; | |
| 194 | 199 | |
| 195 | 200 | return size; |
| 196 | 201 | } |
| @@ -301,11 +306,18 @@ static ssize_t · 104 unmodified lines | ||
| 301 | 306 | ivpu_force_recovery_fn(struct file *file, const char __user *user_buf, size_t size, loff_t *pos) |
| 302 | 307 | { |
| 303 | 308 | struct ivpu_device *vdev = file->private_data; |
| 309 | + int ret; | |
| 304 | 310 | |
| 305 | 311 | if (!size) |
| 306 | 312 | return -EINVAL; |
| 307 | 313 | |
| 308 | − ivpu_pm_schedule_recovery(vdev); | |
| 314 | + ret = ivpu_rpm_get(vdev); | |
| 315 | + if (ret) | |
| 316 | + return ret; | |
| 317 | + | |
| 318 | + ivpu_pm_trigger_recovery(vdev, "debugfs"); | |
| 319 | + flush_work(&vdev->pm->recovery_work); | |
| 320 | + ivpu_rpm_put(vdev); | |
| 309 | 321 | return size; |
| 310 | 322 | } |
| 311 | 323 | |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/firmware.h> |
| 7 | 7 | #include <linux/module.h> |
| 8 | 8 | #include <linux/pci.h> |
| 9 | +#include <linux/pm_runtime.h> | |
| 9 | 10 | |
| 10 | 11 | #include <drm/drm_accel.h> |
| 11 | 12 | #include <drm/drm_file.h> |
| @@ -17,6 +18,7 @@ · 5 unmodified lines | ||
| 17 | 18 | #include "ivpu_debugfs.h" |
| 18 | 19 | #include "ivpu_drv.h" |
| 19 | 20 | #include "ivpu_fw.h" |
| 21 | +#include "ivpu_fw_log.h" | |
| 20 | 22 | #include "ivpu_gem.h" |
| 21 | 23 | #include "ivpu_hw.h" |
| 22 | 24 | #include "ivpu_ipc.h" |
| @@ -65,22 +67,20 @@ struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv) · 42 unmodified lines | ||
| 65 | 67 | return file_priv; |
| 66 | 68 | } |
| 67 | 69 | |
| 68 | −struct ivpu_file_priv *ivpu_file_priv_get_by_ctx_id(struct ivpu_device *vdev, unsigned long id) | |
| 70 | +static void file_priv_unbind(struct ivpu_device *vdev, struct ivpu_file_priv *file_priv) | |
| 69 | 71 | { |
| 70 | − struct ivpu_file_priv *file_priv; | |
| 71 | − | |
| 72 | − xa_lock_irq(&vdev->context_xa); | |
| 73 | − file_priv = xa_load(&vdev->context_xa, id); | |
| 74 | − /* file_priv may still be in context_xa during file_priv_release() */ | |
| 75 | − if (file_priv && !kref_get_unless_zero(&file_priv->ref)) | |
| 76 | − file_priv = NULL; | |
| 77 | − xa_unlock_irq(&vdev->context_xa); | |
| 78 | − | |
| 79 | − if (file_priv) | |
| 80 | − ivpu_dbg(vdev, KREF, "file_priv get by id: ctx %u refcount %u\n", | |
| 81 | − file_priv->ctx.id, kref_read(&file_priv->ref)); | |
| 82 | − | |
| 83 | − return file_priv; | |
| 72 | + mutex_lock(&file_priv->lock); | |
| 73 | + if (file_priv->bound) { | |
| 74 | + ivpu_dbg(vdev, FILE, "file_priv unbind: ctx %u\n", file_priv->ctx.id); | |
| 75 | + | |
| 76 | + ivpu_cmdq_release_all_locked(file_priv); | |
| 77 | + ivpu_jsm_context_release(vdev, file_priv->ctx.id); | |
| 78 | + ivpu_bo_unbind_all_bos_from_context(vdev, &file_priv->ctx); | |
| 79 | + ivpu_mmu_user_context_fini(vdev, &file_priv->ctx); | |
| 80 | + file_priv->bound = false; | |
| 81 | + drm_WARN_ON(&vdev->drm, !xa_erase_irq(&vdev->context_xa, file_priv->ctx.id)); | |
| 82 | + } | |
| 83 | + mutex_unlock(&file_priv->lock); | |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | static void file_priv_release(struct kref *ref) |
| @@ -88,13 +88,15 @@ static void file_priv_release(struct kref *ref) · 1 unmodified line | ||
| 88 | 88 | struct ivpu_file_priv *file_priv = container_of(ref, struct ivpu_file_priv, ref); |
| 89 | 89 | struct ivpu_device *vdev = file_priv->vdev; |
| 90 | 90 | |
| 91 | − ivpu_dbg(vdev, FILE, "file_priv release: ctx %u\n", file_priv->ctx.id); | |
| 91 | + ivpu_dbg(vdev, FILE, "file_priv release: ctx %u bound %d\n", | |
| 92 | + file_priv->ctx.id, (bool)file_priv->bound); | |
| 93 | + | |
| 94 | + pm_runtime_get_sync(vdev->drm.dev); | |
| 95 | + mutex_lock(&vdev->context_list_lock); | |
| 96 | + file_priv_unbind(vdev, file_priv); | |
| 97 | + mutex_unlock(&vdev->context_list_lock); | |
| 98 | + pm_runtime_put_autosuspend(vdev->drm.dev); | |
| 92 | 99 | |
| 93 | − ivpu_cmdq_release_all(file_priv); | |
| 94 | − ivpu_jsm_context_release(vdev, file_priv->ctx.id); | |
| 95 | − ivpu_bo_remove_all_bos_from_context(vdev, &file_priv->ctx); | |
| 96 | − ivpu_mmu_user_context_fini(vdev, &file_priv->ctx); | |
| 97 | − drm_WARN_ON(&vdev->drm, xa_erase_irq(&vdev->context_xa, file_priv->ctx.id) != file_priv); | |
| 98 | 100 | mutex_destroy(&file_priv->lock); |
| 99 | 101 | kfree(file_priv); |
| 100 | 102 | } |
| @@ -176,9 +178,6 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f · 75 unmodified lines | ||
| 176 | 178 | case DRM_IVPU_PARAM_CONTEXT_BASE_ADDRESS: |
| 177 | 179 | args->value = vdev->hw->ranges.user.start; |
| 178 | 180 | break; |
| 179 | − case DRM_IVPU_PARAM_CONTEXT_PRIORITY: | |
| 180 | − args->value = file_priv->priority; | |
| 181 | − break; | |
| 182 | 181 | case DRM_IVPU_PARAM_CONTEXT_ID: |
| 183 | 182 | args->value = file_priv->ctx.id; |
| 184 | 183 | break; |
| @@ -218,17 +217,10 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f · 33 unmodified lines | ||
| 218 | 217 | |
| 219 | 218 | static int ivpu_set_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file) |
| 220 | 219 | { |
| 221 | − struct ivpu_file_priv *file_priv = file->driver_priv; | |
| 222 | 220 | struct drm_ivpu_param *args = data; |
| 223 | 221 | int ret = 0; |
| 224 | 222 | |
| 225 | 223 | switch (args->param) { |
| 226 | − case DRM_IVPU_PARAM_CONTEXT_PRIORITY: | |
| 227 | − if (args->value <= DRM_IVPU_CONTEXT_PRIORITY_REALTIME) | |
| 228 | − file_priv->priority = args->value; | |
| 229 | − else | |
| 230 | − ret = -EINVAL; | |
| 231 | − break; | |
| 232 | 224 | default: |
| 233 | 225 | ret = -EINVAL; |
| 234 | 226 | } |
| @@ -241,50 +233,53 @@ static int ivpu_open(struct drm_device *dev, struct drm_file *file) · 6 unmodified lines | ||
| 241 | 233 | struct ivpu_device *vdev = to_ivpu_device(dev); |
| 242 | 234 | struct ivpu_file_priv *file_priv; |
| 243 | 235 | u32 ctx_id; |
| 244 | − void *old; | |
| 245 | − int ret; | |
| 236 | + int idx, ret; | |
| 246 | 237 | |
| 247 | − ret = xa_alloc_irq(&vdev->context_xa, &ctx_id, NULL, vdev->context_xa_limit, GFP_KERNEL); | |
| 248 | − if (ret) { | |
| 249 | − ivpu_err(vdev, "Failed to allocate context id: %d\n", ret); | |
| 250 | − return ret; | |
| 251 | − } | |
| 238 | + if (!drm_dev_enter(dev, &idx)) | |
| 239 | + return -ENODEV; | |
| 252 | 240 | |
| 253 | 241 | file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); |
| 254 | 242 | if (!file_priv) { |
| 255 | 243 | ret = -ENOMEM; |
| 256 | − goto err_xa_erase; | |
| 244 | + goto err_dev_exit; | |
| 257 | 245 | } |
| 258 | 246 | |
| 259 | 247 | file_priv->vdev = vdev; |
| 260 | − file_priv->priority = DRM_IVPU_CONTEXT_PRIORITY_NORMAL; | |
| 248 | + file_priv->bound = true; | |
| 261 | 249 | kref_init(&file_priv->ref); |
| 262 | 250 | mutex_init(&file_priv->lock); |
| 263 | 251 | |
| 252 | + mutex_lock(&vdev->context_list_lock); | |
| 253 | + | |
| 254 | + ret = xa_alloc_irq(&vdev->context_xa, &ctx_id, file_priv, | |
| 255 | + vdev->context_xa_limit, GFP_KERNEL); | |
| 256 | + if (ret) { | |
| 257 | + ivpu_err(vdev, "Failed to allocate context id: %d\n", ret); | |
| 258 | + goto err_unlock; | |
| 259 | + } | |
| 260 | + | |
| 264 | 261 | ret = ivpu_mmu_user_context_init(vdev, &file_priv->ctx, ctx_id); |
| 265 | 262 | if (ret) |
| 266 | − goto err_mutex_destroy; | |
| 263 | + goto err_xa_erase; | |
| 267 | 264 | |
| 268 | − old = xa_store_irq(&vdev->context_xa, ctx_id, file_priv, GFP_KERNEL); | |
| 269 | − if (xa_is_err(old)) { | |
| 270 | − ret = xa_err(old); | |
| 271 | − ivpu_err(vdev, "Failed to store context %u: %d\n", ctx_id, ret); | |
| 272 | − goto err_ctx_fini; | |
| 273 | − } | |
| 265 | + mutex_unlock(&vdev->context_list_lock); | |
| 266 | + drm_dev_exit(idx); | |
| 267 | + | |
| 268 | + file->driver_priv = file_priv; | |
| 274 | 269 | |
| 275 | 270 | ivpu_dbg(vdev, FILE, "file_priv create: ctx %u process %s pid %d\n", |
| 276 | 271 | ctx_id, current->comm, task_pid_nr(current)); |
| 277 | 272 | |
| 278 | − file->driver_priv = file_priv; | |
| 279 | 273 | return 0; |
| 280 | 274 | |
| 281 | −err_ctx_fini: | |
| 282 | − ivpu_mmu_user_context_fini(vdev, &file_priv->ctx); | |
| 283 | −err_mutex_destroy: | |
| 284 | − mutex_destroy(&file_priv->lock); | |
| 285 | − kfree(file_priv); | |
| 286 | 275 | err_xa_erase: |
| 287 | 276 | xa_erase_irq(&vdev->context_xa, ctx_id); |
| 277 | +err_unlock: | |
| 278 | + mutex_unlock(&vdev->context_list_lock); | |
| 279 | + mutex_destroy(&file_priv->lock); | |
| 280 | + kfree(file_priv); | |
| 281 | +err_dev_exit: | |
| 282 | + drm_dev_exit(idx); | |
| 288 | 283 | return ret; |
| 289 | 284 | } |
| 290 | 285 | |
| @@ -340,8 +335,6 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev) · 49 unmodified lines | ||
| 340 | 335 | |
| 341 | 336 | if (!ret) |
| 342 | 337 | ivpu_dbg(vdev, PM, "VPU ready message received successfully\n"); |
| 343 | − else | |
| 344 | − ivpu_hw_diagnose_failure(vdev); | |
| 345 | 338 | |
| 346 | 339 | return ret; |
| 347 | 340 | } |
| @@ -369,6 +362,9 @@ int ivpu_boot(struct ivpu_device *vdev) · 21 unmodified lines | ||
| 369 | 362 | ret = ivpu_wait_for_ready(vdev); |
| 370 | 363 | if (ret) { |
| 371 | 364 | ivpu_err(vdev, "Failed to boot the firmware: %d\n", ret); |
| 365 | + ivpu_hw_diagnose_failure(vdev); | |
| 366 | + ivpu_mmu_evtq_dump(vdev); | |
| 367 | + ivpu_fw_log_dump(vdev); | |
| 372 | 368 | return ret; |
| 373 | 369 | } |
| 374 | 370 | |
| @@ -484,9 +480,8 @@ static int ivpu_pci_init(struct ivpu_device *vdev) · 109 unmodified lines | ||
| 484 | 480 | /* Clear any pending errors */ |
| 485 | 481 | pcie_capability_clear_word(pdev, PCI_EXP_DEVSTA, 0x3f); |
| 486 | 482 | |
| 487 | − /* VPU 37XX does not require 10m D3hot delay */ | |
| 488 | − if (ivpu_hw_gen(vdev) == IVPU_HW_37XX) | |
| 489 | − pdev->d3hot_delay = 0; | |
| 483 | + /* NPU does not require 10m D3hot delay */ | |
| 484 | + pdev->d3hot_delay = 0; | |
| 490 | 485 | |
| 491 | 486 | ret = pcim_enable_device(pdev); |
| 492 | 487 | if (ret) { |
| @@ -540,6 +535,10 @@ static int ivpu_dev_init(struct ivpu_device *vdev) · 47 unmodified lines | ||
| 540 | 535 | lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); |
| 541 | 536 | INIT_LIST_HEAD(&vdev->bo_list); |
| 542 | 537 | |
| 538 | + ret = drmm_mutex_init(&vdev->drm, &vdev->context_list_lock); | |
| 539 | + if (ret) | |
| 540 | + goto err_xa_destroy; | |
| 541 | + | |
| 543 | 542 | ret = drmm_mutex_init(&vdev->drm, &vdev->bo_list_lock); |
| 544 | 543 | if (ret) |
| 545 | 544 | goto err_xa_destroy; |
| @@ -611,14 +610,30 @@ err_xa_destroy: · 65 unmodified lines | ||
| 611 | 610 | return ret; |
| 612 | 611 | } |
| 613 | 612 | |
| 613 | +static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev) | |
| 614 | +{ | |
| 615 | + struct ivpu_file_priv *file_priv; | |
| 616 | + unsigned long ctx_id; | |
| 617 | + | |
| 618 | + mutex_lock(&vdev->context_list_lock); | |
| 619 | + | |
| 620 | + xa_for_each(&vdev->context_xa, ctx_id, file_priv) | |
| 621 | + file_priv_unbind(vdev, file_priv); | |
| 622 | + | |
| 623 | + mutex_unlock(&vdev->context_list_lock); | |
| 624 | +} | |
| 625 | + | |
| 614 | 626 | static void ivpu_dev_fini(struct ivpu_device *vdev) |
| 615 | 627 | { |
| 616 | 628 | ivpu_pm_disable(vdev); |
| 617 | 629 | ivpu_shutdown(vdev); |
| 618 | 630 | if (IVPU_WA(d3hot_after_power_off)) |
| 619 | 631 | pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); |
| 632 | + | |
| 633 | + ivpu_jobs_abort_all(vdev); | |
| 620 | 634 | ivpu_job_done_consumer_fini(vdev); |
| 621 | 635 | ivpu_pm_cancel_recovery(vdev); |
| 636 | + ivpu_bo_unbind_all_user_contexts(vdev); | |
| 622 | 637 | |
| 623 | 638 | ivpu_ipc_fini(vdev); |
| 624 | 639 | ivpu_fw_fini(vdev); |
| @@ -56,6 +56,7 @@ · 55 unmodified lines | ||
| 56 | 56 | #define IVPU_DBG_JSM BIT(10) |
| 57 | 57 | #define IVPU_DBG_KREF BIT(11) |
| 58 | 58 | #define IVPU_DBG_RPM BIT(12) |
| 59 | +#define IVPU_DBG_MMU_MAP BIT(13) | |
| 59 | 60 | |
| 60 | 61 | #define ivpu_err(vdev, fmt, ...) \ |
| 61 | 62 | drm_err(&(vdev)->drm, "%s(): " fmt, __func__, ##__VA_ARGS__) |
| @@ -114,6 +115,7 @@ struct ivpu_device { · 52 unmodified lines | ||
| 114 | 115 | |
| 115 | 116 | struct ivpu_mmu_context gctx; |
| 116 | 117 | struct ivpu_mmu_context rctx; |
| 118 | + struct mutex context_list_lock; /* Protects user context addition/removal */ | |
| 117 | 119 | struct xarray context_xa; |
| 118 | 120 | struct xa_limit context_xa_limit; |
| 119 | 121 | |
| @@ -145,8 +147,8 @@ struct ivpu_file_priv { · 25 unmodified lines | ||
| 145 | 147 | struct mutex lock; /* Protects cmdq */ |
| 146 | 148 | struct ivpu_cmdq *cmdq[IVPU_NUM_ENGINES]; |
| 147 | 149 | struct ivpu_mmu_context ctx; |
| 148 | − u32 priority; | |
| 149 | 150 | bool has_mmu_faults; |
| 151 | + bool bound; | |
| 150 | 152 | }; |
| 151 | 153 | |
| 152 | 154 | extern int ivpu_dbg_mask; |
| @@ -162,7 +164,6 @@ extern bool ivpu_disable_mmu_cont_pages; · 9 unmodified lines | ||
| 162 | 164 | extern int ivpu_test_mode; |
| 163 | 165 | |
| 164 | 166 | struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); |
| 165 | −struct ivpu_file_priv *ivpu_file_priv_get_by_ctx_id(struct ivpu_device *vdev, unsigned long id); | |
| 166 | 167 | void ivpu_file_priv_put(struct ivpu_file_priv **link); |
| 167 | 168 | |
| 168 | 169 | int ivpu_boot(struct ivpu_device *vdev); |
| @@ -222,7 +222,6 @@ ivpu_fw_init_wa(struct ivpu_device *vdev) · 221 unmodified lines | ||
| 222 | 222 | const struct vpu_firmware_header *fw_hdr = (const void *)vdev->fw->file->data; |
| 223 | 223 | |
| 224 | 224 | if (IVPU_FW_CHECK_API_VER_LT(vdev, fw_hdr, BOOT, 3, 17) || |
| 225 | − (ivpu_hw_gen(vdev) > IVPU_HW_37XX) || | |
| 226 | 225 | (ivpu_test_mode & IVPU_TEST_MODE_D0I3_MSG_DISABLE)) |
| 227 | 226 | vdev->wa.disable_d0i3_msg = true; |
| 228 | 227 | |
| @@ -24,14 +24,11 @@ static const struct drm_gem_object_funcs ivpu_gem_funcs; · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | static inline void ivpu_dbg_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, const char *action) |
| 26 | 26 | { |
| 27 | − if (bo->ctx) | |
| 28 | − ivpu_dbg(vdev, BO, "%6s: size %zu has_pages %d dma_mapped %d handle %u ctx %d vpu_addr 0x%llx mmu_mapped %d\n", | |
| 29 | − action, ivpu_bo_size(bo), (bool)bo->base.pages, (bool)bo->base.sgt, | |
| 30 | − bo->handle, bo->ctx->id, bo->vpu_addr, bo->mmu_mapped); | |
| 31 | − else | |
| 32 | − ivpu_dbg(vdev, BO, "%6s: size %zu has_pages %d dma_mapped %d handle %u (not added to context)\n", | |
| 33 | − action, ivpu_bo_size(bo), (bool)bo->base.pages, (bool)bo->base.sgt, | |
| 34 | − bo->handle); | |
| 27 | + ivpu_dbg(vdev, BO, | |
| 28 | + "%6s: bo %8p vpu_addr %9llx size %8zu ctx %d has_pages %d dma_mapped %d mmu_mapped %d wc %d imported %d\n", | |
| 29 | + action, bo, bo->vpu_addr, ivpu_bo_size(bo), bo->ctx ? bo->ctx->id : 0, | |
| 30 | + (bool)bo->base.pages, (bool)bo->base.sgt, bo->mmu_mapped, bo->base.map_wc, | |
| 31 | + (bool)bo->base.base.import_attach); | |
| 35 | 32 | } |
| 36 | 33 | |
| 37 | 34 | /* |
| @@ -49,12 +46,7 @@ int __must_check ivpu_bo_pin(struct ivpu_bo *bo) · 11 unmodified lines | ||
| 49 | 46 | mutex_lock(&bo->lock); |
| 50 | 47 | |
| 51 | 48 | ivpu_dbg_bo(vdev, bo, "pin"); |
| 52 | − | |
| 53 | − if (!bo->ctx) { | |
| 54 | − ivpu_err(vdev, "vpu_addr not allocated for BO %d\n", bo->handle); | |
| 55 | − ret = -EINVAL; | |
| 56 | − goto unlock; | |
| 57 | − } | |
| 49 | + drm_WARN_ON(&vdev->drm, !bo->ctx); | |
| 58 | 50 | |
| 59 | 51 | if (!bo->mmu_mapped) { |
| 60 | 52 | struct sg_table *sgt = drm_gem_shmem_get_pages_sgt(&bo->base); |
| @@ -85,7 +77,10 @@ ivpu_bo_alloc_vpu_addr(struct ivpu_bo *bo, struct ivpu_mmu_context *ctx, · 24 unmodified lines | ||
| 85 | 77 | const struct ivpu_addr_range *range) |
| 86 | 78 | { |
| 87 | 79 | struct ivpu_device *vdev = ivpu_bo_to_vdev(bo); |
| 88 | − int ret; | |
| 80 | + int idx, ret; | |
| 81 | + | |
| 82 | + if (!drm_dev_enter(&vdev->drm, &idx)) | |
| 83 | + return -ENODEV; | |
| 89 | 84 | |
| 90 | 85 | mutex_lock(&bo->lock); |
| 91 | 86 | |
| @@ -101,6 +96,8 @@ ivpu_bo_alloc_vpu_addr(struct ivpu_bo *bo, struct ivpu_mmu_context *ctx, · 9 unmodified lines | ||
| 101 | 96 | |
| 102 | 97 | mutex_unlock(&bo->lock); |
| 103 | 98 | |
| 99 | + drm_dev_exit(idx); | |
| 100 | + | |
| 104 | 101 | return ret; |
| 105 | 102 | } |
| 106 | 103 | |
| @@ -108,11 +105,7 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo) · 1 unmodified line | ||
| 108 | 105 | { |
| 109 | 106 | struct ivpu_device *vdev = ivpu_bo_to_vdev(bo); |
| 110 | 107 | |
| 111 | − lockdep_assert_held(&bo->lock); | |
| 112 | − | |
| 113 | − ivpu_dbg_bo(vdev, bo, "unbind"); | |
| 114 | − | |
| 115 | − /* TODO: dma_unmap */ | |
| 108 | + lockdep_assert(lockdep_is_held(&bo->lock) || !kref_read(&bo->base.base.refcount)); | |
| 116 | 109 | |
| 117 | 110 | if (bo->mmu_mapped) { |
| 118 | 111 | drm_WARN_ON(&vdev->drm, !bo->ctx); |
| @@ -124,19 +117,23 @@ static void ivpu_bo_unbind_locked(struct ivpu_bo *bo) · 5 unmodified lines | ||
| 124 | 117 | |
| 125 | 118 | if (bo->ctx) { |
| 126 | 119 | ivpu_mmu_context_remove_node(bo->ctx, &bo->mm_node); |
| 127 | − bo->vpu_addr = 0; | |
| 128 | 120 | bo->ctx = NULL; |
| 129 | 121 | } |
| 130 | −} | |
| 131 | 122 | |
| 132 | −static void ivpu_bo_unbind(struct ivpu_bo *bo) | |
| 133 | −{ | |
| 134 | − mutex_lock(&bo->lock); | |
| 135 | − ivpu_bo_unbind_locked(bo); | |
| 136 | − mutex_unlock(&bo->lock); | |
| 123 | + if (bo->base.base.import_attach) | |
| 124 | + return; | |
| 125 | + | |
| 126 | + dma_resv_lock(bo->base.base.resv, NULL); | |
| 127 | + if (bo->base.sgt) { | |
| 128 | + dma_unmap_sgtable(vdev->drm.dev, bo->base.sgt, DMA_BIDIRECTIONAL, 0); | |
| 129 | + sg_free_table(bo->base.sgt); | |
| 130 | + kfree(bo->base.sgt); | |
| 131 | + bo->base.sgt = NULL; | |
| 132 | + } | |
| 133 | + dma_resv_unlock(bo->base.base.resv); | |
| 137 | 134 | } |
| 138 | 135 | |
| 139 | −void ivpu_bo_remove_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx) | |
| 136 | +void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx) | |
| 140 | 137 | { |
| 141 | 138 | struct ivpu_bo *bo; |
| 142 | 139 | |
| @@ -146,8 +143,10 @@ void ivpu_bo_remove_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_m · 3 unmodified lines | ||
| 146 | 143 | mutex_lock(&vdev->bo_list_lock); |
| 147 | 144 | list_for_each_entry(bo, &vdev->bo_list, bo_list_node) { |
| 148 | 145 | mutex_lock(&bo->lock); |
| 149 | − if (bo->ctx == ctx) | |
| 146 | + if (bo->ctx == ctx) { | |
| 147 | + ivpu_dbg_bo(vdev, bo, "unbind"); | |
| 150 | 148 | ivpu_bo_unbind_locked(bo); |
| 149 | + } | |
| 151 | 150 | mutex_unlock(&bo->lock); |
| 152 | 151 | } |
| 153 | 152 | mutex_unlock(&vdev->bo_list_lock); |
| @@ -199,9 +198,6 @@ ivpu_bo_create(struct ivpu_device *vdev, u64 size, u32 flags) · 45 unmodified lines | ||
| 199 | 198 | list_add_tail(&bo->bo_list_node, &vdev->bo_list); |
| 200 | 199 | mutex_unlock(&vdev->bo_list_lock); |
| 201 | 200 | |
| 202 | − ivpu_dbg(vdev, BO, "create: vpu_addr 0x%llx size %zu flags 0x%x\n", | |
| 203 | − bo->vpu_addr, bo->base.base.size, flags); | |
| 204 | − | |
| 205 | 201 | return bo; |
| 206 | 202 | } |
| 207 | 203 | |
| @@ -212,6 +208,12 @@ static int ivpu_bo_open(struct drm_gem_object *obj, struct drm_file *file) · 4 unmodified lines | ||
| 212 | 208 | struct ivpu_bo *bo = to_ivpu_bo(obj); |
| 213 | 209 | struct ivpu_addr_range *range; |
| 214 | 210 | |
| 211 | + if (bo->ctx) { | |
| 212 | + ivpu_warn(vdev, "Can't add BO to ctx %u: already in ctx %u\n", | |
| 213 | + file_priv->ctx.id, bo->ctx->id); | |
| 214 | + return -EALREADY; | |
| 215 | + } | |
| 216 | + | |
| 215 | 217 | if (bo->flags & DRM_IVPU_BO_SHAVE_MEM) |
| 216 | 218 | range = &vdev->hw->ranges.shave; |
| 217 | 219 | else if (bo->flags & DRM_IVPU_BO_DMA_MEM) |
| @@ -227,62 +229,24 @@ static void ivpu_bo_free(struct drm_gem_object *obj) · 9 unmodified lines | ||
| 227 | 229 | struct ivpu_device *vdev = to_ivpu_device(obj->dev); |
| 228 | 230 | struct ivpu_bo *bo = to_ivpu_bo(obj); |
| 229 | 231 | |
| 232 | + ivpu_dbg_bo(vdev, bo, "free"); | |
| 233 | + | |
| 230 | 234 | mutex_lock(&vdev->bo_list_lock); |
| 231 | 235 | list_del(&bo->bo_list_node); |
| 232 | 236 | mutex_unlock(&vdev->bo_list_lock); |
| 233 | 237 | |
| 234 | 238 | drm_WARN_ON(&vdev->drm, !dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ)); |
| 235 | 239 | |
| 236 | − ivpu_dbg_bo(vdev, bo, "free"); | |
| 237 | − | |
| 238 | − ivpu_bo_unbind(bo); | |
| 240 | + ivpu_bo_unbind_locked(bo); | |
| 239 | 241 | mutex_destroy(&bo->lock); |
| 240 | 242 | |
| 241 | 243 | drm_WARN_ON(obj->dev, bo->base.pages_use_count > 1); |
| 242 | 244 | drm_gem_shmem_free(&bo->base); |
| 243 | 245 | } |
| 244 | 246 | |
| 245 | −static const struct dma_buf_ops ivpu_bo_dmabuf_ops = { | |
| 246 | − .cache_sgt_mapping = true, | |
| 247 | − .attach = drm_gem_map_attach, | |
| 248 | − .detach = drm_gem_map_detach, | |
| 249 | − .map_dma_buf = drm_gem_map_dma_buf, | |
| 250 | − .unmap_dma_buf = drm_gem_unmap_dma_buf, | |
| 251 | − .release = drm_gem_dmabuf_release, | |
| 252 | − .mmap = drm_gem_dmabuf_mmap, | |
| 253 | − .vmap = drm_gem_dmabuf_vmap, | |
| 254 | − .vunmap = drm_gem_dmabuf_vunmap, | |
| 255 | −}; | |
| 256 | − | |
| 257 | −static struct dma_buf *ivpu_bo_export(struct drm_gem_object *obj, int flags) | |
| 258 | −{ | |
| 259 | − struct drm_device *dev = obj->dev; | |
| 260 | − struct dma_buf_export_info exp_info = { | |
| 261 | − .exp_name = KBUILD_MODNAME, | |
| 262 | − .owner = dev->driver->fops->owner, | |
| 263 | − .ops = &ivpu_bo_dmabuf_ops, | |
| 264 | − .size = obj->size, | |
| 265 | − .flags = flags, | |
| 266 | − .priv = obj, | |
| 267 | − .resv = obj->resv, | |
| 268 | − }; | |
| 269 | − void *sgt; | |
| 270 | − | |
| 271 | − /* | |
| 272 | − * Make sure that pages are allocated and dma-mapped before exporting the bo. | |
| 273 | − * DMA-mapping is required if the bo will be imported to the same device. | |
| 274 | − */ | |
| 275 | − sgt = drm_gem_shmem_get_pages_sgt(to_drm_gem_shmem_obj(obj)); | |
| 276 | − if (IS_ERR(sgt)) | |
| 277 | − return sgt; | |
| 278 | − | |
| 279 | − return drm_gem_dmabuf_export(dev, &exp_info); | |
| 280 | −} | |
| 281 | − | |
| 282 | 247 | static const struct drm_gem_object_funcs ivpu_gem_funcs = { |
| 283 | 248 | .free = ivpu_bo_free, |
| 284 | 249 | .open = ivpu_bo_open, |
| 285 | − .export = ivpu_bo_export, | |
| 286 | 250 | .print_info = drm_gem_shmem_object_print_info, |
| 287 | 251 | .pin = drm_gem_shmem_object_pin, |
| 288 | 252 | .unpin = drm_gem_shmem_object_unpin, |
| @@ -315,11 +279,9 @@ int ivpu_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fi · 26 unmodified lines | ||
| 315 | 279 | return PTR_ERR(bo); |
| 316 | 280 | } |
| 317 | 281 | |
| 318 | − ret = drm_gem_handle_create(file, &bo->base.base, &bo->handle); | |
| 319 | − if (!ret) { | |
| 282 | + ret = drm_gem_handle_create(file, &bo->base.base, &args->handle); | |
| 283 | + if (!ret) | |
| 320 | 284 | args->vpu_addr = bo->vpu_addr; |
| 321 | − args->handle = bo->handle; | |
| 322 | − } | |
| 323 | 285 | |
| 324 | 286 | drm_gem_object_put(&bo->base.base); |
| 325 | 287 | |
| @@ -361,7 +323,9 @@ ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 fla · 35 unmodified lines | ||
| 361 | 323 | if (ret) |
| 362 | 324 | goto err_put; |
| 363 | 325 | |
| 326 | + dma_resv_lock(bo->base.base.resv, NULL); | |
| 364 | 327 | ret = drm_gem_shmem_vmap(&bo->base, &map); |
| 328 | + dma_resv_unlock(bo->base.base.resv); | |
| 365 | 329 | if (ret) |
| 366 | 330 | goto err_put; |
| 367 | 331 | |
| @@ -376,7 +340,10 @@ void ivpu_bo_free_internal(struct ivpu_bo *bo) · 8 unmodified lines | ||
| 376 | 340 | { |
| 377 | 341 | struct iosys_map map = IOSYS_MAP_INIT_VADDR(bo->base.vaddr); |
| 378 | 342 | |
| 343 | + dma_resv_lock(bo->base.base.resv, NULL); | |
| 379 | 344 | drm_gem_shmem_vunmap(&bo->base, &map); |
| 345 | + dma_resv_unlock(bo->base.base.resv); | |
| 346 | + | |
| 380 | 347 | drm_gem_object_put(&bo->base.base); |
| 381 | 348 | } |
| 382 | 349 | |
| @@ -432,19 +399,11 @@ int ivpu_bo_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file · 49 unmodified lines | ||
| 432 | 399 | |
| 433 | 400 | static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p) |
| 434 | 401 | { |
| 435 | − unsigned long dma_refcount = 0; | |
| 436 | − | |
| 437 | 402 | mutex_lock(&bo->lock); |
| 438 | 403 | |
| 439 | − if (bo->base.base.dma_buf && bo->base.base.dma_buf->file) | |
| 440 | − dma_refcount = atomic_long_read(&bo->base.base.dma_buf->file->f_count); | |
| 441 | − | |
| 442 | − drm_printf(p, "%-3u %-6d 0x%-12llx %-10lu 0x%-8x %-4u %-8lu", | |
| 443 | − bo->ctx->id, bo->handle, bo->vpu_addr, bo->base.base.size, | |
| 444 | − bo->flags, kref_read(&bo->base.base.refcount), dma_refcount); | |
| 445 | − | |
| 446 | − if (bo->base.base.import_attach) | |
| 447 | − drm_printf(p, " imported"); | |
| 404 | + drm_printf(p, "%-9p %-3u 0x%-12llx %-10lu 0x%-8x %-4u", | |
| 405 | + bo, bo->ctx->id, bo->vpu_addr, bo->base.base.size, | |
| 406 | + bo->flags, kref_read(&bo->base.base.refcount)); | |
| 448 | 407 | |
| 449 | 408 | if (bo->base.pages) |
| 450 | 409 | drm_printf(p, " has_pages"); |
| @@ -452,6 +411,9 @@ static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p) · 1 unmodified line | ||
| 452 | 411 | if (bo->mmu_mapped) |
| 453 | 412 | drm_printf(p, " mmu_mapped"); |
| 454 | 413 | |
| 414 | + if (bo->base.base.import_attach) | |
| 415 | + drm_printf(p, " imported"); | |
| 416 | + | |
| 455 | 417 | drm_printf(p, "\n"); |
| 456 | 418 | |
| 457 | 419 | mutex_unlock(&bo->lock); |
| @@ -462,8 +424,8 @@ void ivpu_bo_list(struct drm_device *dev, struct drm_printer *p) · 4 unmodified lines | ||
| 462 | 424 | struct ivpu_device *vdev = to_ivpu_device(dev); |
| 463 | 425 | struct ivpu_bo *bo; |
| 464 | 426 | |
| 465 | − drm_printf(p, "%-3s %-6s %-14s %-10s %-10s %-4s %-8s %s\n", | |
| 466 | − "ctx", "handle", "vpu_addr", "size", "flags", "refs", "dma_refs", "attribs"); | |
| 427 | + drm_printf(p, "%-9s %-3s %-14s %-10s %-10s %-4s %s\n", | |
| 428 | + "bo", "ctx", "vpu_addr", "size", "flags", "refs", "attribs"); | |
| 467 | 429 | |
| 468 | 430 | mutex_lock(&vdev->bo_list_lock); |
| 469 | 431 | list_for_each_entry(bo, &vdev->bo_list, bo_list_node) |
| @@ -19,14 +19,13 @@ struct ivpu_bo { · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | struct mutex lock; /* Protects: ctx, mmu_mapped, vpu_addr */ |
| 21 | 21 | u64 vpu_addr; |
| 22 | − u32 handle; | |
| 23 | 22 | u32 flags; |
| 24 | 23 | u32 job_status; /* Valid only for command buffer */ |
| 25 | 24 | bool mmu_mapped; |
| 26 | 25 | }; |
| 27 | 26 | |
| 28 | 27 | int ivpu_bo_pin(struct ivpu_bo *bo); |
| 29 | −void ivpu_bo_remove_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx); | |
| 28 | +void ivpu_bo_unbind_all_bos_from_context(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx); | |
| 30 | 29 | |
| 31 | 30 | struct drm_gem_object *ivpu_gem_create_object(struct drm_device *dev, size_t size); |
| 32 | 31 | struct ivpu_bo *ivpu_bo_alloc_internal(struct ivpu_device *vdev, u64 vpu_addr, u64 size, u32 flags); |
| @@ -525,7 +525,7 @@ static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) · 524 unmodified lines | ||
| 525 | 525 | u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); |
| 526 | 526 | |
| 527 | 527 | val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, NOSNOOP_OVERRIDE_EN, val); |
| 528 | − val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); | |
| 528 | + val = REG_CLR_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AW_NOSNOOP_OVERRIDE, val); | |
| 529 | 529 | val = REG_SET_FLD(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, AR_NOSNOOP_OVERRIDE, val); |
| 530 | 530 | |
| 531 | 531 | REGV_WR32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES, val); |
| @@ -875,24 +875,18 @@ static void ivpu_hw_37xx_irq_disable(struct ivpu_device *vdev) · 343 unmodified lines | ||
| 875 | 875 | |
| 876 | 876 | static void ivpu_hw_37xx_irq_wdt_nce_handler(struct ivpu_device *vdev) |
| 877 | 877 | { |
| 878 | − ivpu_err_ratelimited(vdev, "WDT NCE irq\n"); | |
| 879 | − | |
| 880 | − ivpu_pm_schedule_recovery(vdev); | |
| 878 | + ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ"); | |
| 881 | 879 | } |
| 882 | 880 | |
| 883 | 881 | static void ivpu_hw_37xx_irq_wdt_mss_handler(struct ivpu_device *vdev) |
| 884 | 882 | { |
| 885 | − ivpu_err_ratelimited(vdev, "WDT MSS irq\n"); | |
| 886 | − | |
| 887 | 883 | ivpu_hw_wdt_disable(vdev); |
| 888 | − ivpu_pm_schedule_recovery(vdev); | |
| 884 | + ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ"); | |
| 889 | 885 | } |
| 890 | 886 | |
| 891 | 887 | static void ivpu_hw_37xx_irq_noc_firewall_handler(struct ivpu_device *vdev) |
| 892 | 888 | { |
| 893 | − ivpu_err_ratelimited(vdev, "NOC Firewall irq\n"); | |
| 894 | − | |
| 895 | − ivpu_pm_schedule_recovery(vdev); | |
| 889 | + ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ"); | |
| 896 | 890 | } |
| 897 | 891 | |
| 898 | 892 | /* Handler for IRQs from VPU core (irqV) */ |
| @@ -970,7 +964,7 @@ static bool ivpu_hw_37xx_irqb_handler(struct ivpu_device *vdev, int irq) · 71 unmodified lines | ||
| 970 | 964 | REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, status); |
| 971 | 965 | |
| 972 | 966 | if (schedule_recovery) |
| 973 | − ivpu_pm_schedule_recovery(vdev); | |
| 967 | + ivpu_pm_trigger_recovery(vdev, "Buttress IRQ"); | |
| 974 | 968 | |
| 975 | 969 | return true; |
| 976 | 970 | } |
| @@ -530,7 +530,7 @@ static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) · 529 unmodified lines | ||
| 530 | 530 | u32 val = REGV_RD32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES); |
| 531 | 531 | |
| 532 | 532 | val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, SNOOP_OVERRIDE_EN, val); |
| 533 | − val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val); | |
| 533 | + val = REG_SET_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AW_SNOOP_OVERRIDE, val); | |
| 534 | 534 | val = REG_CLR_FLD(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, AR_SNOOP_OVERRIDE, val); |
| 535 | 535 | |
| 536 | 536 | REGV_WR32(VPU_40XX_HOST_IF_TCU_PTW_OVERRIDES, val); |
| @@ -704,7 +704,6 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev) · 167 unmodified lines | ||
| 704 | 704 | { |
| 705 | 705 | struct ivpu_hw_info *hw = vdev->hw; |
| 706 | 706 | u32 tile_disable; |
| 707 | − u32 tile_enable; | |
| 708 | 707 | u32 fuse; |
| 709 | 708 | |
| 710 | 709 | fuse = REGB_RD32(VPU_40XX_BUTTRESS_TILE_FUSE); |
| @@ -725,10 +724,6 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev) · 14 unmodified lines | ||
| 725 | 724 | else |
| 726 | 725 | ivpu_dbg(vdev, MISC, "Fuse: All %d tiles enabled\n", TILE_MAX_NUM); |
| 727 | 726 | |
| 728 | − tile_enable = (~tile_disable) & TILE_MAX_MASK; | |
| 729 | − | |
| 730 | − hw->sku = REG_SET_FLD_NUM(SKU, HW_ID, LNL_HW_ID, hw->sku); | |
| 731 | − hw->sku = REG_SET_FLD_NUM(SKU, TILE, tile_enable, hw->sku); | |
| 732 | 727 | hw->tile_fuse = tile_disable; |
| 733 | 728 | hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; |
| 734 | 729 | |
| @@ -746,7 +741,7 @@ static int ivpu_hw_40xx_info_init(struct ivpu_device *vdev) · 11 unmodified lines | ||
| 746 | 741 | return 0; |
| 747 | 742 | } |
| 748 | 743 | |
| 749 | −static int ivpu_hw_40xx_reset(struct ivpu_device *vdev) | |
| 744 | +static int ivpu_hw_40xx_ip_reset(struct ivpu_device *vdev) | |
| 750 | 745 | { |
| 751 | 746 | int ret; |
| 752 | 747 | u32 val; |
| @@ -768,6 +763,23 @@ static int ivpu_hw_40xx_reset(struct ivpu_device *vdev) · 15 unmodified lines | ||
| 768 | 763 | return ret; |
| 769 | 764 | } |
| 770 | 765 | |
| 766 | +static int ivpu_hw_40xx_reset(struct ivpu_device *vdev) | |
| 767 | +{ | |
| 768 | + int ret = 0; | |
| 769 | + | |
| 770 | + if (ivpu_hw_40xx_ip_reset(vdev)) { | |
| 771 | + ivpu_err(vdev, "Failed to reset VPU IP\n"); | |
| 772 | + ret = -EIO; | |
| 773 | + } | |
| 774 | + | |
| 775 | + if (ivpu_pll_disable(vdev)) { | |
| 776 | + ivpu_err(vdev, "Failed to disable PLL\n"); | |
| 777 | + ret = -EIO; | |
| 778 | + } | |
| 779 | + | |
| 780 | + return ret; | |
| 781 | +} | |
| 782 | + | |
| 771 | 783 | static int ivpu_hw_40xx_d0i3_enable(struct ivpu_device *vdev) |
| 772 | 784 | { |
| 773 | 785 | int ret; |
| @@ -913,7 +925,7 @@ static int ivpu_hw_40xx_power_down(struct ivpu_device *vdev) · 139 unmodified lines | ||
| 913 | 925 | |
| 914 | 926 | ivpu_hw_40xx_save_d0i3_entry_timestamp(vdev); |
| 915 | 927 | |
| 916 | − if (!ivpu_hw_40xx_is_idle(vdev) && ivpu_hw_40xx_reset(vdev)) | |
| 928 | + if (!ivpu_hw_40xx_is_idle(vdev) && ivpu_hw_40xx_ip_reset(vdev)) | |
| 917 | 929 | ivpu_warn(vdev, "Failed to reset the VPU\n"); |
| 918 | 930 | |
| 919 | 931 | if (ivpu_pll_disable(vdev)) { |
| @@ -1032,18 +1044,18 @@ static void ivpu_hw_40xx_irq_disable(struct ivpu_device *vdev) · 112 unmodified lines | ||
| 1032 | 1044 | static void ivpu_hw_40xx_irq_wdt_nce_handler(struct ivpu_device *vdev) |
| 1033 | 1045 | { |
| 1034 | 1046 | /* TODO: For LNN hang consider engine reset instead of full recovery */ |
| 1035 | − ivpu_pm_schedule_recovery(vdev); | |
| 1047 | + ivpu_pm_trigger_recovery(vdev, "WDT NCE IRQ"); | |
| 1036 | 1048 | } |
| 1037 | 1049 | |
| 1038 | 1050 | static void ivpu_hw_40xx_irq_wdt_mss_handler(struct ivpu_device *vdev) |
| 1039 | 1051 | { |
| 1040 | 1052 | ivpu_hw_wdt_disable(vdev); |
| 1041 | − ivpu_pm_schedule_recovery(vdev); | |
| 1053 | + ivpu_pm_trigger_recovery(vdev, "WDT MSS IRQ"); | |
| 1042 | 1054 | } |
| 1043 | 1055 | |
| 1044 | 1056 | static void ivpu_hw_40xx_irq_noc_firewall_handler(struct ivpu_device *vdev) |
| 1045 | 1057 | { |
| 1046 | − ivpu_pm_schedule_recovery(vdev); | |
| 1058 | + ivpu_pm_trigger_recovery(vdev, "NOC Firewall IRQ"); | |
| 1047 | 1059 | } |
| 1048 | 1060 | |
| 1049 | 1061 | /* Handler for IRQs from VPU core (irqV) */ |
| @@ -1137,7 +1149,7 @@ static bool ivpu_hw_40xx_irqb_handler(struct ivpu_device *vdev, int irq) · 87 unmodified lines | ||
| 1137 | 1149 | REGB_WR32(VPU_40XX_BUTTRESS_INTERRUPT_STAT, status); |
| 1138 | 1150 | |
| 1139 | 1151 | if (schedule_recovery) |
| 1140 | − ivpu_pm_schedule_recovery(vdev); | |
| 1152 | + ivpu_pm_trigger_recovery(vdev, "Buttress IRQ"); | |
| 1141 | 1153 | |
| 1142 | 1154 | return true; |
| 1143 | 1155 | } |
| @@ -343,10 +343,8 @@ int ivpu_ipc_send_receive_active(struct ivpu_device *vdev, struct vpu_jsm_msg *r · 342 unmodified lines | ||
| 343 | 343 | hb_ret = ivpu_ipc_send_receive_internal(vdev, &hb_req, VPU_JSM_MSG_QUERY_ENGINE_HB_DONE, |
| 344 | 344 | &hb_resp, VPU_IPC_CHAN_ASYNC_CMD, |
| 345 | 345 | vdev->timeout.jsm); |
| 346 | − if (hb_ret == -ETIMEDOUT) { | |
| 347 | − ivpu_hw_diagnose_failure(vdev); | |
| 348 | − ivpu_pm_schedule_recovery(vdev); | |
| 349 | − } | |
| 346 | + if (hb_ret == -ETIMEDOUT) | |
| 347 | + ivpu_pm_trigger_recovery(vdev, "IPC timeout"); | |
| 350 | 348 | |
| 351 | 349 | return ret; |
| 352 | 350 | } |
| @@ -112,22 +112,20 @@ static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u16 engin · 111 unmodified lines | ||
| 112 | 112 | } |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | −void ivpu_cmdq_release_all(struct ivpu_file_priv *file_priv) | |
| 115 | +void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) | |
| 116 | 116 | { |
| 117 | 117 | int i; |
| 118 | 118 | |
| 119 | − mutex_lock(&file_priv->lock); | |
| 119 | + lockdep_assert_held(&file_priv->lock); | |
| 120 | 120 | |
| 121 | 121 | for (i = 0; i < IVPU_NUM_ENGINES; i++) |
| 122 | 122 | ivpu_cmdq_release_locked(file_priv, i); |
| 123 | − | |
| 124 | − mutex_unlock(&file_priv->lock); | |
| 125 | 123 | } |
| 126 | 124 | |
| 127 | 125 | /* |
| 128 | 126 | * Mark the doorbell as unregistered and reset job queue pointers. |
| 129 | 127 | * This function needs to be called when the VPU hardware is restarted |
| 130 | − * and FW looses job queue state. The next time job queue is used it | |
| 128 | + * and FW loses job queue state. The next time job queue is used it | |
| 131 | 129 | * will be registered again. |
| 132 | 130 | */ |
| 133 | 131 | static void ivpu_cmdq_reset_locked(struct ivpu_file_priv *file_priv, u16 engine) |
| @@ -161,15 +159,13 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev) · 27 unmodified lines | ||
| 161 | 159 | struct ivpu_file_priv *file_priv; |
| 162 | 160 | unsigned long ctx_id; |
| 163 | 161 | |
| 164 | − xa_for_each(&vdev->context_xa, ctx_id, file_priv) { | |
| 165 | − file_priv = ivpu_file_priv_get_by_ctx_id(vdev, ctx_id); | |
| 166 | − if (!file_priv) | |
| 167 | − continue; | |
| 162 | + mutex_lock(&vdev->context_list_lock); | |
| 168 | 163 | |
| 164 | + xa_for_each(&vdev->context_xa, ctx_id, file_priv) | |
| 169 | 165 | ivpu_cmdq_reset_all(file_priv); |
| 170 | 166 | |
| 171 | − ivpu_file_priv_put(&file_priv); | |
| 172 | − } | |
| 167 | + mutex_unlock(&vdev->context_list_lock); | |
| 168 | + | |
| 173 | 169 | } |
| 174 | 170 | |
| 175 | 171 | static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job) |
| @@ -243,60 +239,32 @@ static struct dma_fence *ivpu_fence_create(struct ivpu_device *vdev) · 67 unmodified lines | ||
| 243 | 239 | return &fence->base; |
| 244 | 240 | } |
| 245 | 241 | |
| 246 | −static void job_get(struct ivpu_job *job, struct ivpu_job **link) | |
| 242 | +static void ivpu_job_destroy(struct ivpu_job *job) | |
| 247 | 243 | { |
| 248 | 244 | struct ivpu_device *vdev = job->vdev; |
| 249 | − | |
| 250 | − kref_get(&job->ref); | |
| 251 | − *link = job; | |
| 252 | − | |
| 253 | − ivpu_dbg(vdev, KREF, "Job get: id %u refcount %u\n", job->job_id, kref_read(&job->ref)); | |
| 254 | −} | |
| 255 | − | |
| 256 | −static void job_release(struct kref *ref) | |
| 257 | −{ | |
| 258 | − struct ivpu_job *job = container_of(ref, struct ivpu_job, ref); | |
| 259 | − struct ivpu_device *vdev = job->vdev; | |
| 260 | 245 | u32 i; |
| 261 | 246 | |
| 247 | + ivpu_dbg(vdev, JOB, "Job destroyed: id %3u ctx %2d engine %d", | |
| 248 | + job->job_id, job->file_priv->ctx.id, job->engine_idx); | |
| 249 | + | |
| 262 | 250 | for (i = 0; i < job->bo_count; i++) |
| 263 | 251 | if (job->bos[i]) |
| 264 | 252 | drm_gem_object_put(&job->bos[i]->base.base); |
| 265 | 253 | |
| 266 | 254 | dma_fence_put(job->done_fence); |
| 267 | 255 | ivpu_file_priv_put(&job->file_priv); |
| 268 | − | |
| 269 | − ivpu_dbg(vdev, KREF, "Job released: id %u\n", job->job_id); | |
| 270 | 256 | kfree(job); |
| 271 | − | |
| 272 | − /* Allow the VPU to get suspended, must be called after ivpu_file_priv_put() */ | |
| 273 | − ivpu_rpm_put(vdev); | |
| 274 | −} | |
| 275 | − | |
| 276 | −static void job_put(struct ivpu_job *job) | |
| 277 | −{ | |
| 278 | − struct ivpu_device *vdev = job->vdev; | |
| 279 | − | |
| 280 | − ivpu_dbg(vdev, KREF, "Job put: id %u refcount %u\n", job->job_id, kref_read(&job->ref)); | |
| 281 | − kref_put(&job->ref, job_release); | |
| 282 | 257 | } |
| 283 | 258 | |
| 284 | 259 | static struct ivpu_job * |
| 285 | −ivpu_create_job(struct ivpu_file_priv *file_priv, u32 engine_idx, u32 bo_count) | |
| 260 | +ivpu_job_create(struct ivpu_file_priv *file_priv, u32 engine_idx, u32 bo_count) | |
| 286 | 261 | { |
| 287 | 262 | struct ivpu_device *vdev = file_priv->vdev; |
| 288 | 263 | struct ivpu_job *job; |
| 289 | − int ret; | |
| 290 | − | |
| 291 | − ret = ivpu_rpm_get(vdev); | |
| 292 | − if (ret < 0) | |
| 293 | − return NULL; | |
| 294 | 264 | |
| 295 | 265 | job = kzalloc(struct_size(job, bos, bo_count), GFP_KERNEL); |
| 296 | 266 | if (!job) |
| 297 | − goto err_rpm_put; | |
| 298 | − | |
| 299 | − kref_init(&job->ref); | |
| 267 | + return NULL; | |
| 300 | 268 | |
| 301 | 269 | job->vdev = vdev; |
| 302 | 270 | job->engine_idx = engine_idx; |
| @@ -310,17 +278,14 @@ ivpu_create_job(struct ivpu_file_priv *file_priv, u32 engine_idx, u32 bo_count) · 7 unmodified lines | ||
| 310 | 278 | job->file_priv = ivpu_file_priv_get(file_priv); |
| 311 | 279 | |
| 312 | 280 | ivpu_dbg(vdev, JOB, "Job created: ctx %2d engine %d", file_priv->ctx.id, job->engine_idx); |
| 313 | − | |
| 314 | 281 | return job; |
| 315 | 282 | |
| 316 | 283 | err_free_job: |
| 317 | 284 | kfree(job); |
| 318 | −err_rpm_put: | |
| 319 | − ivpu_rpm_put(vdev); | |
| 320 | 285 | return NULL; |
| 321 | 286 | } |
| 322 | 287 | |
| 323 | −static int ivpu_job_done(struct ivpu_device *vdev, u32 job_id, u32 job_status) | |
| 288 | +static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 job_status) | |
| 324 | 289 | { |
| 325 | 290 | struct ivpu_job *job; |
| 326 | 291 | |
| @@ -329,7 +294,7 @@ static int ivpu_job_done(struct ivpu_device *vdev, u32 job_id, u32 job_status) · 2 unmodified lines | ||
| 329 | 294 | return -ENOENT; |
| 330 | 295 | |
| 331 | 296 | if (job->file_priv->has_mmu_faults) |
| 332 | − job_status = VPU_JSM_STATUS_ABORTED; | |
| 297 | + job_status = DRM_IVPU_JOB_STATUS_ABORTED; | |
| 333 | 298 | |
| 334 | 299 | job->bos[CMD_BUF_IDX]->job_status = job_status; |
| 335 | 300 | dma_fence_signal(job->done_fence); |
| @@ -337,9 +302,10 @@ static int ivpu_job_done(struct ivpu_device *vdev, u32 job_id, u32 job_status) · 1 unmodified line | ||
| 337 | 302 | ivpu_dbg(vdev, JOB, "Job complete: id %3u ctx %2d engine %d status 0x%x\n", |
| 338 | 303 | job->job_id, job->file_priv->ctx.id, job->engine_idx, job_status); |
| 339 | 304 | |
| 305 | + ivpu_job_destroy(job); | |
| 340 | 306 | ivpu_stop_job_timeout_detection(vdev); |
| 341 | 307 | |
| 342 | − job_put(job); | |
| 308 | + ivpu_rpm_put(vdev); | |
| 343 | 309 | return 0; |
| 344 | 310 | } |
| 345 | 311 | |
| @@ -349,10 +315,10 @@ void ivpu_jobs_abort_all(struct ivpu_device *vdev) · 3 unmodified lines | ||
| 349 | 315 | unsigned long id; |
| 350 | 316 | |
| 351 | 317 | xa_for_each(&vdev->submitted_jobs_xa, id, job) |
| 352 | − ivpu_job_done(vdev, id, VPU_JSM_STATUS_ABORTED); | |
| 318 | + ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED); | |
| 353 | 319 | } |
| 354 | 320 | |
| 355 | −static int ivpu_direct_job_submission(struct ivpu_job *job) | |
| 321 | +static int ivpu_job_submit(struct ivpu_job *job) | |
| 356 | 322 | { |
| 357 | 323 | struct ivpu_file_priv *file_priv = job->file_priv; |
| 358 | 324 | struct ivpu_device *vdev = job->vdev; |
| @@ -360,53 +326,65 @@ static int ivpu_direct_job_submission(struct ivpu_job *job) · 1 unmodified line | ||
| 360 | 326 | struct ivpu_cmdq *cmdq; |
| 361 | 327 | int ret; |
| 362 | 328 | |
| 329 | + ret = ivpu_rpm_get(vdev); | |
| 330 | + if (ret < 0) | |
| 331 | + return ret; | |
| 332 | + | |
| 363 | 333 | mutex_lock(&file_priv->lock); |
| 364 | 334 | |
| 365 | 335 | cmdq = ivpu_cmdq_acquire(job->file_priv, job->engine_idx); |
| 366 | 336 | if (!cmdq) { |
| 367 | − ivpu_warn(vdev, "Failed get job queue, ctx %d engine %d\n", | |
| 368 | − file_priv->ctx.id, job->engine_idx); | |
| 337 | + ivpu_warn_ratelimited(vdev, "Failed get job queue, ctx %d engine %d\n", | |
| 338 | + file_priv->ctx.id, job->engine_idx); | |
| 369 | 339 | ret = -EINVAL; |
| 370 | − goto err_unlock; | |
| 340 | + goto err_unlock_file_priv; | |
| 371 | 341 | } |
| 372 | 342 | |
| 373 | 343 | job_id_range.min = FIELD_PREP(JOB_ID_CONTEXT_MASK, (file_priv->ctx.id - 1)); |
| 374 | 344 | job_id_range.max = job_id_range.min | JOB_ID_JOB_MASK; |
| 375 | 345 | |
| 376 | − job_get(job, &job); | |
| 377 | − ret = xa_alloc(&vdev->submitted_jobs_xa, &job->job_id, job, job_id_range, GFP_KERNEL); | |
| 346 | + xa_lock(&vdev->submitted_jobs_xa); | |
| 347 | + ret = __xa_alloc(&vdev->submitted_jobs_xa, &job->job_id, job, job_id_range, GFP_KERNEL); | |
| 378 | 348 | if (ret) { |
| 379 | − ivpu_warn_ratelimited(vdev, "Failed to allocate job id: %d\n", ret); | |
| 380 | − goto err_job_put; | |
| 349 | + ivpu_dbg(vdev, JOB, "Too many active jobs in ctx %d\n", | |
| 350 | + file_priv->ctx.id); | |
| 351 | + ret = -EBUSY; | |
| 352 | + goto err_unlock_submitted_jobs_xa; | |
| 381 | 353 | } |
| 382 | 354 | |
| 383 | 355 | ret = ivpu_cmdq_push_job(cmdq, job); |
| 384 | 356 | if (ret) |
| 385 | − goto err_xa_erase; | |
| 357 | + goto err_erase_xa; | |
| 386 | 358 | |
| 387 | 359 | ivpu_start_job_timeout_detection(vdev); |
| 388 | 360 | |
| 389 | − ivpu_dbg(vdev, JOB, "Job submitted: id %3u addr 0x%llx ctx %2d engine %d next %d\n", | |
| 390 | − job->job_id, job->cmd_buf_vpu_addr, file_priv->ctx.id, | |
| 391 | − job->engine_idx, cmdq->jobq->header.tail); | |
| 392 | − | |
| 393 | − if (ivpu_test_mode & IVPU_TEST_MODE_NULL_HW) { | |
| 394 | − ivpu_job_done(vdev, job->job_id, VPU_JSM_STATUS_SUCCESS); | |
| 361 | + if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) { | |
| 395 | 362 | cmdq->jobq->header.head = cmdq->jobq->header.tail; |
| 396 | 363 | wmb(); /* Flush WC buffer for jobq header */ |
| 397 | 364 | } else { |
| 398 | 365 | ivpu_cmdq_ring_db(vdev, cmdq); |
| 399 | 366 | } |
| 400 | 367 | |
| 368 | + ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d addr 0x%llx next %d\n", | |
| 369 | + job->job_id, file_priv->ctx.id, job->engine_idx, | |
| 370 | + job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); | |
| 371 | + | |
| 372 | + xa_unlock(&vdev->submitted_jobs_xa); | |
| 373 | + | |
| 401 | 374 | mutex_unlock(&file_priv->lock); |
| 375 | + | |
| 376 | + if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) | |
| 377 | + ivpu_job_signal_and_destroy(vdev, job->job_id, VPU_JSM_STATUS_SUCCESS); | |
| 378 | + | |
| 402 | 379 | return 0; |
| 403 | 380 | |
| 404 | −err_xa_erase: | |
| 405 | − xa_erase(&vdev->submitted_jobs_xa, job->job_id); | |
| 406 | −err_job_put: | |
| 407 | − job_put(job); | |
| 408 | −err_unlock: | |
| 381 | +err_erase_xa: | |
| 382 | + __xa_erase(&vdev->submitted_jobs_xa, job->job_id); | |
| 383 | +err_unlock_submitted_jobs_xa: | |
| 384 | + xa_unlock(&vdev->submitted_jobs_xa); | |
| 385 | +err_unlock_file_priv: | |
| 409 | 386 | mutex_unlock(&file_priv->lock); |
| 387 | + ivpu_rpm_put(vdev); | |
| 410 | 388 | return ret; |
| 411 | 389 | } |
| 412 | 390 | |
| @@ -488,6 +466,9 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 75 unmodified lines | ||
| 488 | 466 | if (params->engine > DRM_IVPU_ENGINE_COPY) |
| 489 | 467 | return -EINVAL; |
| 490 | 468 | |
| 469 | + if (params->priority > DRM_IVPU_JOB_PRIORITY_REALTIME) | |
| 470 | + return -EINVAL; | |
| 471 | + | |
| 491 | 472 | if (params->buffer_count == 0 || params->buffer_count > JOB_MAX_BUFFER_COUNT) |
| 492 | 473 | return -EINVAL; |
| 493 | 474 | |
| @@ -509,44 +490,49 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 15 unmodified lines | ||
| 509 | 490 | params->buffer_count * sizeof(u32)); |
| 510 | 491 | if (ret) { |
| 511 | 492 | ret = -EFAULT; |
| 512 | − goto free_handles; | |
| 493 | + goto err_free_handles; | |
| 513 | 494 | } |
| 514 | 495 | |
| 515 | 496 | if (!drm_dev_enter(&vdev->drm, &idx)) { |
| 516 | 497 | ret = -ENODEV; |
| 517 | − goto free_handles; | |
| 498 | + goto err_free_handles; | |
| 518 | 499 | } |
| 519 | 500 | |
| 520 | 501 | ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u buf_count %u\n", |
| 521 | 502 | file_priv->ctx.id, params->buffer_count); |
| 522 | 503 | |
| 523 | − job = ivpu_create_job(file_priv, params->engine, params->buffer_count); | |
| 504 | + job = ivpu_job_create(file_priv, params->engine, params->buffer_count); | |
| 524 | 505 | if (!job) { |
| 525 | 506 | ivpu_err(vdev, "Failed to create job\n"); |
| 526 | 507 | ret = -ENOMEM; |
| 527 | − goto dev_exit; | |
| 508 | + goto err_exit_dev; | |
| 528 | 509 | } |
| 529 | 510 | |
| 530 | 511 | ret = ivpu_job_prepare_bos_for_submit(file, job, buf_handles, params->buffer_count, |
| 531 | 512 | params->commands_offset); |
| 532 | 513 | if (ret) { |
| 533 | − ivpu_err(vdev, "Failed to prepare job, ret %d\n", ret); | |
| 534 | − goto job_put; | |
| 514 | + ivpu_err(vdev, "Failed to prepare job: %d\n", ret); | |
| 515 | + goto err_destroy_job; | |
| 535 | 516 | } |
| 536 | 517 | |
| 537 | − ret = ivpu_direct_job_submission(job); | |
| 538 | − if (ret) { | |
| 539 | − dma_fence_signal(job->done_fence); | |
| 540 | − ivpu_err(vdev, "Failed to submit job to the HW, ret %d\n", ret); | |
| 541 | − } | |
| 518 | + down_read(&vdev->pm->reset_lock); | |
| 519 | + ret = ivpu_job_submit(job); | |
| 520 | + up_read(&vdev->pm->reset_lock); | |
| 521 | + if (ret) | |
| 522 | + goto err_signal_fence; | |
| 542 | 523 | |
| 543 | −job_put: | |
| 544 | − job_put(job); | |
| 545 | −dev_exit: | |
| 546 | 524 | drm_dev_exit(idx); |
| 547 | −free_handles: | |
| 548 | 525 | kfree(buf_handles); |
| 526 | + return ret; | |
| 549 | 527 | |
| 528 | +err_signal_fence: | |
| 529 | + dma_fence_signal(job->done_fence); | |
| 530 | +err_destroy_job: | |
| 531 | + ivpu_job_destroy(job); | |
| 532 | +err_exit_dev: | |
| 533 | + drm_dev_exit(idx); | |
| 534 | +err_free_handles: | |
| 535 | + kfree(buf_handles); | |
| 550 | 536 | return ret; |
| 551 | 537 | } |
| 552 | 538 | |
| @@ -568,7 +554,7 @@ ivpu_job_done_callback(struct ivpu_device *vdev, struct ivpu_ipc_hdr *ipc_hdr, · 15 unmodified lines | ||
| 568 | 554 | } |
| 569 | 555 | |
| 570 | 556 | payload = (struct vpu_ipc_msg_payload_job_done *)&jsm_msg->payload; |
| 571 | − ret = ivpu_job_done(vdev, payload->job_id, payload->job_status); | |
| 557 | + ret = ivpu_job_signal_and_destroy(vdev, payload->job_id, payload->job_status); | |
| 572 | 558 | if (!ret && !xa_empty(&vdev->submitted_jobs_xa)) |
| 573 | 559 | ivpu_start_job_timeout_detection(vdev); |
| 574 | 560 | } |
| @@ -43,7 +43,6 @@ struct ivpu_cmdq { · 42 unmodified lines | ||
| 43 | 43 | will update the job status |
| 44 | 44 | */ |
| 45 | 45 | struct ivpu_job { |
| 46 | − struct kref ref; | |
| 47 | 46 | struct ivpu_device *vdev; |
| 48 | 47 | struct ivpu_file_priv *file_priv; |
| 49 | 48 | struct dma_fence *done_fence; |
| @@ -56,7 +55,7 @@ struct ivpu_job { · 6 unmodified lines | ||
| 56 | 55 | |
| 57 | 56 | int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file); |
| 58 | 57 | |
| 59 | −void ivpu_cmdq_release_all(struct ivpu_file_priv *file_priv); | |
| 58 | +void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv); | |
| 60 | 59 | void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev); |
| 61 | 60 | |
| 62 | 61 | void ivpu_job_done_consumer_init(struct ivpu_device *vdev); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <linux/highmem.h> |
| 8 | 8 | |
| 9 | 9 | #include "ivpu_drv.h" |
| 10 | +#include "ivpu_hw.h" | |
| 10 | 11 | #include "ivpu_hw_reg_io.h" |
| 11 | 12 | #include "ivpu_mmu.h" |
| 12 | 13 | #include "ivpu_mmu_context.h" |
| @@ -71,10 +72,10 @@ · 58 unmodified lines | ||
| 71 | 72 | |
| 72 | 73 | #define IVPU_MMU_Q_COUNT_LOG2 4 /* 16 entries */ |
| 73 | 74 | #define IVPU_MMU_Q_COUNT ((u32)1 << IVPU_MMU_Q_COUNT_LOG2) |
| 74 | −#define IVPU_MMU_Q_WRAP_BIT (IVPU_MMU_Q_COUNT << 1) | |
| 75 | −#define IVPU_MMU_Q_WRAP_MASK (IVPU_MMU_Q_WRAP_BIT - 1) | |
| 76 | −#define IVPU_MMU_Q_IDX_MASK (IVPU_MMU_Q_COUNT - 1) | |
| 75 | +#define IVPU_MMU_Q_WRAP_MASK GENMASK(IVPU_MMU_Q_COUNT_LOG2, 0) | |
| 76 | +#define IVPU_MMU_Q_IDX_MASK (IVPU_MMU_Q_COUNT - 1) | |
| 77 | 77 | #define IVPU_MMU_Q_IDX(val) ((val) & IVPU_MMU_Q_IDX_MASK) |
| 78 | +#define IVPU_MMU_Q_WRP(val) ((val) & IVPU_MMU_Q_COUNT) | |
| 78 | 79 | |
| 79 | 80 | #define IVPU_MMU_CMDQ_CMD_SIZE 16 |
| 80 | 81 | #define IVPU_MMU_CMDQ_SIZE (IVPU_MMU_Q_COUNT * IVPU_MMU_CMDQ_CMD_SIZE) |
| @@ -474,20 +475,32 @@ static int ivpu_mmu_cmdq_wait_for_cons(struct ivpu_device *vdev) · 393 unmodified lines | ||
| 474 | 475 | return 0; |
| 475 | 476 | } |
| 476 | 477 | |
| 478 | +static bool ivpu_mmu_queue_is_full(struct ivpu_mmu_queue *q) | |
| 479 | +{ | |
| 480 | + return ((IVPU_MMU_Q_IDX(q->prod) == IVPU_MMU_Q_IDX(q->cons)) && | |
| 481 | + (IVPU_MMU_Q_WRP(q->prod) != IVPU_MMU_Q_WRP(q->cons))); | |
| 482 | +} | |
| 483 | + | |
| 484 | +static bool ivpu_mmu_queue_is_empty(struct ivpu_mmu_queue *q) | |
| 485 | +{ | |
| 486 | + return ((IVPU_MMU_Q_IDX(q->prod) == IVPU_MMU_Q_IDX(q->cons)) && | |
| 487 | + (IVPU_MMU_Q_WRP(q->prod) == IVPU_MMU_Q_WRP(q->cons))); | |
| 488 | +} | |
| 489 | + | |
| 477 | 490 | static int ivpu_mmu_cmdq_cmd_write(struct ivpu_device *vdev, const char *name, u64 data0, u64 data1) |
| 478 | 491 | { |
| 479 | − struct ivpu_mmu_queue *q = &vdev->mmu->cmdq; | |
| 480 | − u64 *queue_buffer = q->base; | |
| 481 | − int idx = IVPU_MMU_Q_IDX(q->prod) * (IVPU_MMU_CMDQ_CMD_SIZE / sizeof(*queue_buffer)); | |
| 492 | + struct ivpu_mmu_queue *cmdq = &vdev->mmu->cmdq; | |
| 493 | + u64 *queue_buffer = cmdq->base; | |
| 494 | + int idx = IVPU_MMU_Q_IDX(cmdq->prod) * (IVPU_MMU_CMDQ_CMD_SIZE / sizeof(*queue_buffer)); | |
| 482 | 495 | |
| 483 | − if (!CIRC_SPACE(IVPU_MMU_Q_IDX(q->prod), IVPU_MMU_Q_IDX(q->cons), IVPU_MMU_Q_COUNT)) { | |
| 496 | + if (ivpu_mmu_queue_is_full(cmdq)) { | |
| 484 | 497 | ivpu_err(vdev, "Failed to write MMU CMD %s\n", name); |
| 485 | 498 | return -EBUSY; |
| 486 | 499 | } |
| 487 | 500 | |
| 488 | 501 | queue_buffer[idx] = data0; |
| 489 | 502 | queue_buffer[idx + 1] = data1; |
| 490 | − q->prod = (q->prod + 1) & IVPU_MMU_Q_WRAP_MASK; | |
| 503 | + cmdq->prod = (cmdq->prod + 1) & IVPU_MMU_Q_WRAP_MASK; | |
| 491 | 504 | |
| 492 | 505 | ivpu_dbg(vdev, MMU, "CMD write: %s data: 0x%llx 0x%llx\n", name, data0, data1); |
| 493 | 506 | |
| @@ -518,6 +531,7 @@ static int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev) · 24 unmodified lines | ||
| 518 | 531 | |
| 519 | 532 | ivpu_err(vdev, "Timed out waiting for MMU consumer: %d, error: %s\n", ret, |
| 520 | 533 | ivpu_mmu_cmdq_err_to_str(err)); |
| 534 | + ivpu_hw_diagnose_failure(vdev); | |
| 521 | 535 | } |
| 522 | 536 | |
| 523 | 537 | return ret; |
| @@ -558,7 +572,6 @@ static int ivpu_mmu_reset(struct ivpu_device *vdev) · 34 unmodified lines | ||
| 558 | 572 | mmu->cmdq.cons = 0; |
| 559 | 573 | |
| 560 | 574 | memset(mmu->evtq.base, 0, IVPU_MMU_EVTQ_SIZE); |
| 561 | − clflush_cache_range(mmu->evtq.base, IVPU_MMU_EVTQ_SIZE); | |
| 562 | 575 | mmu->evtq.prod = 0; |
| 563 | 576 | mmu->evtq.cons = 0; |
| 564 | 577 | |
| @@ -872,20 +885,15 @@ static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) · 307 unmodified lines | ||
| 872 | 885 | u32 *evt = evtq->base + (idx * IVPU_MMU_EVTQ_CMD_SIZE); |
| 873 | 886 | |
| 874 | 887 | evtq->prod = REGV_RD32(IVPU_MMU_REG_EVTQ_PROD_SEC); |
| 875 | − if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT)) | |
| 888 | + if (ivpu_mmu_queue_is_empty(evtq)) | |
| 876 | 889 | return NULL; |
| 877 | 890 | |
| 878 | − clflush_cache_range(evt, IVPU_MMU_EVTQ_CMD_SIZE); | |
| 879 | − | |
| 880 | 891 | evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK; |
| 881 | − REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, evtq->cons); | |
| 882 | − | |
| 883 | 892 | return evt; |
| 884 | 893 | } |
| 885 | 894 | |
| 886 | 895 | void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) |
| 887 | 896 | { |
| 888 | − bool schedule_recovery = false; | |
| 889 | 897 | u32 *event; |
| 890 | 898 | u32 ssid; |
| 891 | 899 | |
| @@ -895,14 +903,22 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) · 3 unmodified lines | ||
| 895 | 903 | ivpu_mmu_dump_event(vdev, event); |
| 896 | 904 | |
| 897 | 905 | ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); |
| 898 | − if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) | |
| 899 | − schedule_recovery = true; | |
| 900 | − else | |
| 901 | − ivpu_mmu_user_context_mark_invalid(vdev, ssid); | |
| 906 | + if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) { | |
| 907 | + ivpu_pm_trigger_recovery(vdev, "MMU event"); | |
| 908 | + return; | |
| 909 | + } | |
| 910 | + | |
| 911 | + ivpu_mmu_user_context_mark_invalid(vdev, ssid); | |
| 912 | + REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons); | |
| 902 | 913 | } |
| 914 | +} | |
| 903 | 915 | |
| 904 | − if (schedule_recovery) | |
| 905 | − ivpu_pm_schedule_recovery(vdev); | |
| 916 | +void ivpu_mmu_evtq_dump(struct ivpu_device *vdev) | |
| 917 | +{ | |
| 918 | + u32 *event; | |
| 919 | + | |
| 920 | + while ((event = ivpu_mmu_get_event(vdev)) != NULL) | |
| 921 | + ivpu_mmu_dump_event(vdev, event); | |
| 906 | 922 | } |
| 907 | 923 | |
| 908 | 924 | void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev) |
| @@ -46,5 +46,6 @@ int ivpu_mmu_invalidate_tlb(struct ivpu_device *vdev, u16 ssid); · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev); |
| 48 | 48 | void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev); |
| 49 | +void ivpu_mmu_evtq_dump(struct ivpu_device *vdev); | |
| 49 | 50 | |
| 50 | 51 | #endif /* __IVPU_MMU_H__ */ |
| @@ -355,6 +355,9 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, · 354 unmodified lines | ||
| 355 | 355 | dma_addr_t dma_addr = sg_dma_address(sg) - sg->offset; |
| 356 | 356 | size_t size = sg_dma_len(sg) + sg->offset; |
| 357 | 357 | |
| 358 | + ivpu_dbg(vdev, MMU_MAP, "Map ctx: %u dma_addr: 0x%llx vpu_addr: 0x%llx size: %lu\n", | |
| 359 | + ctx->id, dma_addr, vpu_addr, size); | |
| 360 | + | |
| 358 | 361 | ret = ivpu_mmu_context_map_pages(vdev, ctx, vpu_addr, dma_addr, size, prot); |
| 359 | 362 | if (ret) { |
| 360 | 363 | ivpu_err(vdev, "Failed to map context pages\n"); |
| @@ -366,6 +369,7 @@ ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, · 5 unmodified lines | ||
| 366 | 369 | |
| 367 | 370 | /* Ensure page table modifications are flushed from wc buffers to memory */ |
| 368 | 371 | wmb(); |
| 372 | + | |
| 369 | 373 | mutex_unlock(&ctx->lock); |
| 370 | 374 | |
| 371 | 375 | ret = ivpu_mmu_invalidate_tlb(vdev, ctx->id); |
| @@ -388,14 +392,19 @@ ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ct · 16 unmodified lines | ||
| 388 | 392 | mutex_lock(&ctx->lock); |
| 389 | 393 | |
| 390 | 394 | for_each_sgtable_dma_sg(sgt, sg, i) { |
| 395 | + dma_addr_t dma_addr = sg_dma_address(sg) - sg->offset; | |
| 391 | 396 | size_t size = sg_dma_len(sg) + sg->offset; |
| 392 | 397 | |
| 398 | + ivpu_dbg(vdev, MMU_MAP, "Unmap ctx: %u dma_addr: 0x%llx vpu_addr: 0x%llx size: %lu\n", | |
| 399 | + ctx->id, dma_addr, vpu_addr, size); | |
| 400 | + | |
| 393 | 401 | ivpu_mmu_context_unmap_pages(ctx, vpu_addr, size); |
| 394 | 402 | vpu_addr += size; |
| 395 | 403 | } |
| 396 | 404 | |
| 397 | 405 | /* Ensure page table modifications are flushed from wc buffers to memory */ |
| 398 | 406 | wmb(); |
| 407 | + | |
| 399 | 408 | mutex_unlock(&ctx->lock); |
| 400 | 409 | |
| 401 | 410 | ret = ivpu_mmu_invalidate_tlb(vdev, ctx->id); |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "ivpu_drv.h" |
| 14 | 14 | #include "ivpu_hw.h" |
| 15 | 15 | #include "ivpu_fw.h" |
| 16 | +#include "ivpu_fw_log.h" | |
| 16 | 17 | #include "ivpu_ipc.h" |
| 17 | 18 | #include "ivpu_job.h" |
| 18 | 19 | #include "ivpu_jsm_msg.h" |
| @@ -111,6 +112,14 @@ static void ivpu_pm_recovery_work(struct work_struct *work) · 92 unmodified lines | ||
| 111 | 112 | char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL}; |
| 112 | 113 | int ret; |
| 113 | 114 | |
| 115 | + ivpu_err(vdev, "Recovering the VPU (reset #%d)\n", atomic_read(&vdev->pm->reset_counter)); | |
| 116 | + | |
| 117 | + ret = pm_runtime_resume_and_get(vdev->drm.dev); | |
| 118 | + if (ret) | |
| 119 | + ivpu_err(vdev, "Failed to resume VPU: %d\n", ret); | |
| 120 | + | |
| 121 | + ivpu_fw_log_dump(vdev); | |
| 122 | + | |
| 114 | 123 | retry: |
| 115 | 124 | ret = pci_try_reset_function(to_pci_dev(vdev->drm.dev)); |
| 116 | 125 | if (ret == -EAGAIN && !drm_dev_is_unplugged(&vdev->drm)) { |
| @@ -122,11 +131,13 @@ retry: · 5 unmodified lines | ||
| 122 | 131 | ivpu_err(vdev, "Failed to reset VPU: %d\n", ret); |
| 123 | 132 | |
| 124 | 133 | kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt); |
| 134 | + pm_runtime_mark_last_busy(vdev->drm.dev); | |
| 135 | + pm_runtime_put_autosuspend(vdev->drm.dev); | |
| 125 | 136 | } |
| 126 | 137 | |
| 127 | −void ivpu_pm_schedule_recovery(struct ivpu_device *vdev) | |
| 138 | +void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason) | |
| 128 | 139 | { |
| 129 | − struct ivpu_pm_info *pm = vdev->pm; | |
| 140 | + ivpu_err(vdev, "Recovery triggered by %s\n", reason); | |
| 130 | 141 | |
| 131 | 142 | if (ivpu_disable_recovery) { |
| 132 | 143 | ivpu_err(vdev, "Recovery not available when disable_recovery param is set\n"); |
| @@ -138,10 +149,11 @@ void ivpu_pm_schedule_recovery(struct ivpu_device *vdev) · 5 unmodified lines | ||
| 138 | 149 | return; |
| 139 | 150 | } |
| 140 | 151 | |
| 141 | − /* Schedule recovery if it's not in progress */ | |
| 142 | − if (atomic_cmpxchg(&pm->in_reset, 0, 1) == 0) { | |
| 143 | − ivpu_hw_irq_disable(vdev); | |
| 144 | − queue_work(system_long_wq, &pm->recovery_work); | |
| 152 | + /* Trigger recovery if it's not in progress */ | |
| 153 | + if (atomic_cmpxchg(&vdev->pm->reset_pending, 0, 1) == 0) { | |
| 154 | + ivpu_hw_diagnose_failure(vdev); | |
| 155 | + ivpu_hw_irq_disable(vdev); /* Disable IRQ early to protect from IRQ storm */ | |
| 156 | + queue_work(system_long_wq, &vdev->pm->recovery_work); | |
| 145 | 157 | } |
| 146 | 158 | } |
| 147 | 159 | |
| @@ -149,12 +161,8 @@ static void ivpu_job_timeout_work(struct work_struct *work) · 1 unmodified line | ||
| 149 | 161 | { |
| 150 | 162 | struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, job_timeout_work.work); |
| 151 | 163 | struct ivpu_device *vdev = pm->vdev; |
| 152 | − unsigned long timeout_ms = ivpu_tdr_timeout_ms ? ivpu_tdr_timeout_ms : vdev->timeout.tdr; | |
| 153 | 164 | |
| 154 | − ivpu_err(vdev, "TDR detected, timeout %lu ms", timeout_ms); | |
| 155 | − ivpu_hw_diagnose_failure(vdev); | |
| 156 | − | |
| 157 | − ivpu_pm_schedule_recovery(vdev); | |
| 165 | + ivpu_pm_trigger_recovery(vdev, "TDR"); | |
| 158 | 166 | } |
| 159 | 167 | |
| 160 | 168 | void ivpu_start_job_timeout_detection(struct ivpu_device *vdev) |
| @@ -227,6 +235,9 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev) · 66 unmodified lines | ||
| 227 | 235 | bool hw_is_idle = true; |
| 228 | 236 | int ret; |
| 229 | 237 | |
| 238 | + drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa)); | |
| 239 | + drm_WARN_ON(&vdev->drm, work_pending(&vdev->pm->recovery_work)); | |
| 240 | + | |
| 230 | 241 | ivpu_dbg(vdev, PM, "Runtime suspend..\n"); |
| 231 | 242 | |
| 232 | 243 | if (!ivpu_hw_is_idle(vdev) && vdev->pm->suspend_reschedule_counter) { |
| @@ -247,7 +258,8 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev) · 14 unmodified lines | ||
| 247 | 258 | ivpu_err(vdev, "Failed to set suspend VPU: %d\n", ret); |
| 248 | 259 | |
| 249 | 260 | if (!hw_is_idle) { |
| 250 | − ivpu_warn(vdev, "VPU failed to enter idle, force suspended.\n"); | |
| 261 | + ivpu_err(vdev, "VPU failed to enter idle, force suspended.\n"); | |
| 262 | + ivpu_fw_log_dump(vdev); | |
| 251 | 263 | ivpu_pm_prepare_cold_boot(vdev); |
| 252 | 264 | } else { |
| 253 | 265 | ivpu_pm_prepare_warm_boot(vdev); |
| @@ -308,11 +320,12 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev) · 54 unmodified lines | ||
| 308 | 320 | { |
| 309 | 321 | struct ivpu_device *vdev = pci_get_drvdata(pdev); |
| 310 | 322 | |
| 311 | − pm_runtime_get_sync(vdev->drm.dev); | |
| 312 | − | |
| 313 | 323 | ivpu_dbg(vdev, PM, "Pre-reset..\n"); |
| 314 | 324 | atomic_inc(&vdev->pm->reset_counter); |
| 315 | − atomic_set(&vdev->pm->in_reset, 1); | |
| 325 | + atomic_set(&vdev->pm->reset_pending, 1); | |
| 326 | + | |
| 327 | + pm_runtime_get_sync(vdev->drm.dev); | |
| 328 | + down_write(&vdev->pm->reset_lock); | |
| 316 | 329 | ivpu_prepare_for_reset(vdev); |
| 317 | 330 | ivpu_hw_reset(vdev); |
| 318 | 331 | ivpu_pm_prepare_cold_boot(vdev); |
| @@ -329,9 +342,11 @@ void ivpu_pm_reset_done_cb(struct pci_dev *pdev) · 10 unmodified lines | ||
| 329 | 342 | ret = ivpu_resume(vdev); |
| 330 | 343 | if (ret) |
| 331 | 344 | ivpu_err(vdev, "Failed to set RESUME state: %d\n", ret); |
| 332 | − atomic_set(&vdev->pm->in_reset, 0); | |
| 345 | + up_write(&vdev->pm->reset_lock); | |
| 346 | + atomic_set(&vdev->pm->reset_pending, 0); | |
| 333 | 347 | ivpu_dbg(vdev, PM, "Post-reset done.\n"); |
| 334 | 348 | |
| 349 | + pm_runtime_mark_last_busy(vdev->drm.dev); | |
| 335 | 350 | pm_runtime_put_autosuspend(vdev->drm.dev); |
| 336 | 351 | } |
| 337 | 352 | |
| @@ -344,7 +359,10 @@ void ivpu_pm_init(struct ivpu_device *vdev) · 6 unmodified lines | ||
| 344 | 359 | pm->vdev = vdev; |
| 345 | 360 | pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT; |
| 346 | 361 | |
| 347 | − atomic_set(&pm->in_reset, 0); | |
| 362 | + init_rwsem(&pm->reset_lock); | |
| 363 | + atomic_set(&pm->reset_pending, 0); | |
| 364 | + atomic_set(&pm->reset_counter, 0); | |
| 365 | + | |
| 348 | 366 | INIT_WORK(&pm->recovery_work, ivpu_pm_recovery_work); |
| 349 | 367 | INIT_DELAYED_WORK(&pm->job_timeout_work, ivpu_job_timeout_work); |
| 350 | 368 | |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #ifndef __IVPU_PM_H__ |
| 7 | 7 | #define __IVPU_PM_H__ |
| 8 | 8 | |
| 9 | +#include <linux/rwsem.h> | |
| 9 | 10 | #include <linux/types.h> |
| 10 | 11 | |
| 11 | 12 | struct ivpu_device; |
| @@ -14,8 +15,9 @@ struct ivpu_pm_info { · 2 unmodified lines | ||
| 14 | 15 | struct ivpu_device *vdev; |
| 15 | 16 | struct delayed_work job_timeout_work; |
| 16 | 17 | struct work_struct recovery_work; |
| 17 | − atomic_t in_reset; | |
| 18 | + struct rw_semaphore reset_lock; | |
| 18 | 19 | atomic_t reset_counter; |
| 20 | + atomic_t reset_pending; | |
| 19 | 21 | bool is_warmboot; |
| 20 | 22 | u32 suspend_reschedule_counter; |
| 21 | 23 | }; |
| @@ -37,7 +39,7 @@ int __must_check ivpu_rpm_get(struct ivpu_device *vdev); · 15 unmodified lines | ||
| 37 | 39 | int __must_check ivpu_rpm_get_if_active(struct ivpu_device *vdev); |
| 38 | 40 | void ivpu_rpm_put(struct ivpu_device *vdev); |
| 39 | 41 | |
| 40 | −void ivpu_pm_schedule_recovery(struct ivpu_device *vdev); | |
| 42 | +void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason); | |
| 41 | 43 | void ivpu_start_job_timeout_detection(struct ivpu_device *vdev); |
| 42 | 44 | void ivpu_stop_job_timeout_detection(struct ivpu_device *vdev); |
| 43 | 45 | |
| @@ -680,32 +680,6 @@ static void ghes_defer_non_standard_event(struct acpi_hest_generic_data *gdata, · 679 unmodified lines | ||
| 680 | 680 | static DECLARE_RWSEM(cxl_cper_rw_sem); |
| 681 | 681 | static cxl_cper_callback cper_callback; |
| 682 | 682 | |
| 683 | −/* CXL Event record UUIDs are formatted as GUIDs and reported in section type */ | |
| 684 | − | |
| 685 | −/* | |
| 686 | − * General Media Event Record | |
| 687 | − * CXL rev 3.0 Section 8.2.9.2.1.1; Table 8-43 | |
| 688 | − */ | |
| 689 | −#define CPER_SEC_CXL_GEN_MEDIA_GUID \ | |
| 690 | − GUID_INIT(0xfbcd0a77, 0xc260, 0x417f, \ | |
| 691 | − 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6) | |
| 692 | − | |
| 693 | −/* | |
| 694 | − * DRAM Event Record | |
| 695 | − * CXL rev 3.0 section 8.2.9.2.1.2; Table 8-44 | |
| 696 | − */ | |
| 697 | −#define CPER_SEC_CXL_DRAM_GUID \ | |
| 698 | − GUID_INIT(0x601dcbb3, 0x9c06, 0x4eab, \ | |
| 699 | − 0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24) | |
| 700 | − | |
| 701 | −/* | |
| 702 | − * Memory Module Event Record | |
| 703 | − * CXL rev 3.0 section 8.2.9.2.1.3; Table 8-45 | |
| 704 | − */ | |
| 705 | −#define CPER_SEC_CXL_MEM_MODULE_GUID \ | |
| 706 | − GUID_INIT(0xfe927475, 0xdd59, 0x4339, \ | |
| 707 | − 0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74) | |
| 708 | − | |
| 709 | 683 | static void cxl_cper_post_event(enum cxl_event_type event_type, |
| 710 | 684 | struct cxl_cper_event_rec *rec) |
| 711 | 685 | { |
| @@ -478,6 +478,16 @@ binder_enqueue_thread_work_ilocked(struct binder_thread *thread, · 477 unmodified lines | ||
| 478 | 478 | { |
| 479 | 479 | WARN_ON(!list_empty(&thread->waiting_thread_node)); |
| 480 | 480 | binder_enqueue_work_ilocked(work, &thread->todo); |
| 481 | + | |
| 482 | + /* (e)poll-based threads require an explicit wakeup signal when | |
| 483 | + * queuing their own work; they rely on these events to consume | |
| 484 | + * messages without I/O block. Without it, threads risk waiting | |
| 485 | + * indefinitely without handling the work. | |
| 486 | + */ | |
| 487 | + if (thread->looper & BINDER_LOOPER_STATE_POLL && | |
| 488 | + thread->pid == current->pid && !thread->process_todo) | |
| 489 | + wake_up_interruptible_sync(&thread->wait); | |
| 490 | + | |
| 481 | 491 | thread->process_todo = true; |
| 482 | 492 | } |
| 483 | 493 | |
| @@ -48,6 +48,7 @@ enum { · 47 unmodified lines | ||
| 48 | 48 | enum board_ids { |
| 49 | 49 | /* board IDs by feature in alphabetical order */ |
| 50 | 50 | board_ahci, |
| 51 | + board_ahci_43bit_dma, | |
| 51 | 52 | board_ahci_ign_iferr, |
| 52 | 53 | board_ahci_low_power, |
| 53 | 54 | board_ahci_no_debounce_delay, |
| @@ -128,6 +129,13 @@ static const struct ata_port_info ahci_port_info[] = { · 74 unmodified lines | ||
| 128 | 129 | .udma_mask = ATA_UDMA6, |
| 129 | 130 | .port_ops = &ahci_ops, |
| 130 | 131 | }, |
| 132 | + [board_ahci_43bit_dma] = { | |
| 133 | + AHCI_HFLAGS (AHCI_HFLAG_43BIT_ONLY), | |
| 134 | + .flags = AHCI_FLAG_COMMON, | |
| 135 | + .pio_mask = ATA_PIO4, | |
| 136 | + .udma_mask = ATA_UDMA6, | |
| 137 | + .port_ops = &ahci_ops, | |
| 138 | + }, | |
| 131 | 139 | [board_ahci_ign_iferr] = { |
| 132 | 140 | AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), |
| 133 | 141 | .flags = AHCI_FLAG_COMMON, |
| @@ -597,14 +605,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { · 463 unmodified lines | ||
| 597 | 605 | { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ |
| 598 | 606 | { PCI_VDEVICE(PROMISE, 0x3781), board_ahci }, /* FastTrak TX8660 ahci-mode */ |
| 599 | 607 | |
| 600 | − /* Asmedia */ | |
| 601 | − { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ | |
| 602 | − { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ | |
| 603 | − { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ | |
| 604 | − { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ | |
| 605 | − { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci }, /* ASM1061R */ | |
| 606 | − { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci }, /* ASM1062R */ | |
| 607 | − { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci }, /* ASM1062+JMB575 */ | |
| 608 | + /* ASMedia */ | |
| 609 | + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci_43bit_dma }, /* ASM1060 */ | |
| 610 | + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci_43bit_dma }, /* ASM1060 */ | |
| 611 | + { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma }, /* ASM1061 */ | |
| 612 | + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma }, /* ASM1061/1062 */ | |
| 613 | + { PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci_43bit_dma }, /* ASM1061R */ | |
| 614 | + { PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci_43bit_dma }, /* ASM1062R */ | |
| 615 | + { PCI_VDEVICE(ASMEDIA, 0x0624), board_ahci_43bit_dma }, /* ASM1062+JMB575 */ | |
| 608 | 616 | { PCI_VDEVICE(ASMEDIA, 0x1062), board_ahci }, /* ASM1062A */ |
| 609 | 617 | { PCI_VDEVICE(ASMEDIA, 0x1064), board_ahci }, /* ASM1064 */ |
| 610 | 618 | { PCI_VDEVICE(ASMEDIA, 0x1164), board_ahci }, /* ASM1164 */ |
| @@ -663,6 +671,11 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); · 52 unmodified lines | ||
| 663 | 671 | static void ahci_pci_save_initial_config(struct pci_dev *pdev, |
| 664 | 672 | struct ahci_host_priv *hpriv) |
| 665 | 673 | { |
| 674 | + if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && pdev->device == 0x1166) { | |
| 675 | + dev_info(&pdev->dev, "ASM1166 has only six ports\n"); | |
| 676 | + hpriv->saved_port_map = 0x3f; | |
| 677 | + } | |
| 678 | + | |
| 666 | 679 | if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) { |
| 667 | 680 | dev_info(&pdev->dev, "JMB361 has only one port\n"); |
| 668 | 681 | hpriv->saved_port_map = 1; |
| @@ -949,11 +962,20 @@ static int ahci_pci_device_resume(struct device *dev) · 280 unmodified lines | ||
| 949 | 962 | |
| 950 | 963 | #endif /* CONFIG_PM */ |
| 951 | 964 | |
| 952 | −static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac) | |
| 965 | +static int ahci_configure_dma_masks(struct pci_dev *pdev, | |
| 966 | + struct ahci_host_priv *hpriv) | |
| 953 | 967 | { |
| 954 | − const int dma_bits = using_dac ? 64 : 32; | |
| 968 | + int dma_bits; | |
| 955 | 969 | int rc; |
| 956 | 970 | |
| 971 | + if (hpriv->cap & HOST_CAP_64) { | |
| 972 | + dma_bits = 64; | |
| 973 | + if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY) | |
| 974 | + dma_bits = 43; | |
| 975 | + } else { | |
| 976 | + dma_bits = 32; | |
| 977 | + } | |
| 978 | + | |
| 957 | 979 | /* |
| 958 | 980 | * If the device fixup already set the dma_mask to some non-standard |
| 959 | 981 | * value, don't extend it here. This happens on STA2X11, for example. |
| @@ -1926,7 +1948,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) · 966 unmodified lines | ||
| 1926 | 1948 | ahci_gtf_filter_workaround(host); |
| 1927 | 1949 | |
| 1928 | 1950 | /* initialize adapter */ |
| 1929 | − rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64); | |
| 1951 | + rc = ahci_configure_dma_masks(pdev, hpriv); | |
| 1930 | 1952 | if (rc) |
| 1931 | 1953 | return rc; |
| 1932 | 1954 | |
| @@ -247,6 +247,7 @@ enum { · 246 unmodified lines | ||
| 247 | 247 | AHCI_HFLAG_SUSPEND_PHYS = BIT(26), /* handle PHYs during |
| 248 | 248 | suspend/resume */ |
| 249 | 249 | AHCI_HFLAG_NO_SXS = BIT(28), /* SXS not supported */ |
| 250 | + AHCI_HFLAG_43BIT_ONLY = BIT(29), /* 43bit DMA addr limit */ | |
| 250 | 251 | |
| 251 | 252 | /* ap->flags bits */ |
| 252 | 253 | |
| @@ -784,7 +784,7 @@ bool sata_lpm_ignore_phy_events(struct ata_link *link) · 783 unmodified lines | ||
| 784 | 784 | EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events); |
| 785 | 785 | |
| 786 | 786 | static const char *ata_lpm_policy_names[] = { |
| 787 | − [ATA_LPM_UNKNOWN] = "max_performance", | |
| 787 | + [ATA_LPM_UNKNOWN] = "keep_firmware_settings", | |
| 788 | 788 | [ATA_LPM_MAX_POWER] = "max_performance", |
| 789 | 789 | [ATA_LPM_MED_POWER] = "medium_power", |
| 790 | 790 | [ATA_LPM_MED_POWER_WITH_DIPM] = "med_power_with_dipm", |
| @@ -2930,6 +2930,8 @@ open_card_ubr0(struct idt77252_dev *card) · 2929 unmodified lines | ||
| 2930 | 2930 | vc->scq = alloc_scq(card, vc->class); |
| 2931 | 2931 | if (!vc->scq) { |
| 2932 | 2932 | printk("%s: can't get SCQ.\n", card->name); |
| 2933 | + kfree(card->vcs[0]); | |
| 2934 | + card->vcs[0] = NULL; | |
| 2933 | 2935 | return -ENOMEM; |
| 2934 | 2936 | } |
| 2935 | 2937 | |
| @@ -333,6 +333,7 @@ aoeblk_gdalloc(void *vp) · 332 unmodified lines | ||
| 333 | 333 | struct gendisk *gd; |
| 334 | 334 | mempool_t *mp; |
| 335 | 335 | struct blk_mq_tag_set *set; |
| 336 | + sector_t ssize; | |
| 336 | 337 | ulong flags; |
| 337 | 338 | int late = 0; |
| 338 | 339 | int err; |
| @@ -396,7 +397,7 @@ aoeblk_gdalloc(void *vp) · 57 unmodified lines | ||
| 396 | 397 | gd->minors = AOE_PARTITIONS; |
| 397 | 398 | gd->fops = &aoe_bdops; |
| 398 | 399 | gd->private_data = d; |
| 399 | − set_capacity(gd, d->ssize); | |
| 400 | + ssize = d->ssize; | |
| 400 | 401 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", |
| 401 | 402 | d->aoemajor, d->aoeminor); |
| 402 | 403 | |
| @@ -405,6 +406,8 @@ aoeblk_gdalloc(void *vp) · 2 unmodified lines | ||
| 405 | 406 | |
| 406 | 407 | spin_unlock_irqrestore(&d->lock, flags); |
| 407 | 408 | |
| 409 | + set_capacity(gd, ssize); | |
| 410 | + | |
| 408 | 411 | err = device_add_disk(NULL, gd, aoe_attr_groups); |
| 409 | 412 | if (err) |
| 410 | 413 | goto out_disk_cleanup; |
| @@ -3452,14 +3452,15 @@ static bool rbd_lock_add_request(struct rbd_img_request *img_req) · 3451 unmodified lines | ||
| 3452 | 3452 | static void rbd_lock_del_request(struct rbd_img_request *img_req) |
| 3453 | 3453 | { |
| 3454 | 3454 | struct rbd_device *rbd_dev = img_req->rbd_dev; |
| 3455 | − bool need_wakeup; | |
| 3455 | + bool need_wakeup = false; | |
| 3456 | 3456 | |
| 3457 | 3457 | lockdep_assert_held(&rbd_dev->lock_rwsem); |
| 3458 | 3458 | spin_lock(&rbd_dev->lock_lists_lock); |
| 3459 | − rbd_assert(!list_empty(&img_req->lock_item)); | |
| 3460 | − list_del_init(&img_req->lock_item); | |
| 3461 | − need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_RELEASING && | |
| 3462 | − list_empty(&rbd_dev->running_list)); | |
| 3459 | + if (!list_empty(&img_req->lock_item)) { | |
| 3460 | + list_del_init(&img_req->lock_item); | |
| 3461 | + need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_RELEASING && | |
| 3462 | + list_empty(&rbd_dev->running_list)); | |
| 3463 | + } | |
| 3463 | 3464 | spin_unlock(&rbd_dev->lock_lists_lock); |
| 3464 | 3465 | if (need_wakeup) |
| 3465 | 3466 | complete(&rbd_dev->releasing_wait); |
| @@ -3842,14 +3843,19 @@ static void wake_lock_waiters(struct rbd_device *rbd_dev, int result) · 376 unmodified lines | ||
| 3842 | 3843 | return; |
| 3843 | 3844 | } |
| 3844 | 3845 | |
| 3845 | − list_for_each_entry(img_req, &rbd_dev->acquiring_list, lock_item) { | |
| 3846 | + while (!list_empty(&rbd_dev->acquiring_list)) { | |
| 3847 | + img_req = list_first_entry(&rbd_dev->acquiring_list, | |
| 3848 | + struct rbd_img_request, lock_item); | |
| 3846 | 3849 | mutex_lock(&img_req->state_mutex); |
| 3847 | 3850 | rbd_assert(img_req->state == RBD_IMG_EXCLUSIVE_LOCK); |
| 3851 | + if (!result) | |
| 3852 | + list_move_tail(&img_req->lock_item, | |
| 3853 | + &rbd_dev->running_list); | |
| 3854 | + else | |
| 3855 | + list_del_init(&img_req->lock_item); | |
| 3848 | 3856 | rbd_img_schedule(img_req, result); |
| 3849 | 3857 | mutex_unlock(&img_req->state_mutex); |
| 3850 | 3858 | } |
| 3851 | − | |
| 3852 | − list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list); | |
| 3853 | 3859 | } |
| 3854 | 3860 | |
| 3855 | 3861 | static bool locker_equal(const struct ceph_locker *lhs, |
| @@ -5326,7 +5332,7 @@ static void rbd_dev_release(struct device *dev) · 1470 unmodified lines | ||
| 5326 | 5332 | |
| 5327 | 5333 | if (need_put) { |
| 5328 | 5334 | destroy_workqueue(rbd_dev->task_wq); |
| 5329 | − ida_simple_remove(&rbd_dev_id_ida, rbd_dev->dev_id); | |
| 5335 | + ida_free(&rbd_dev_id_ida, rbd_dev->dev_id); | |
| 5330 | 5336 | } |
| 5331 | 5337 | |
| 5332 | 5338 | rbd_dev_free(rbd_dev); |
| @@ -5402,9 +5408,9 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc, · 69 unmodified lines | ||
| 5402 | 5408 | return NULL; |
| 5403 | 5409 | |
| 5404 | 5410 | /* get an id and fill in device name */ |
| 5405 | − rbd_dev->dev_id = ida_simple_get(&rbd_dev_id_ida, 0, | |
| 5406 | − minor_to_rbd_dev_id(1 << MINORBITS), | |
| 5407 | − GFP_KERNEL); | |
| 5411 | + rbd_dev->dev_id = ida_alloc_max(&rbd_dev_id_ida, | |
| 5412 | + minor_to_rbd_dev_id(1 << MINORBITS) - 1, | |
| 5413 | + GFP_KERNEL); | |
| 5408 | 5414 | if (rbd_dev->dev_id < 0) |
| 5409 | 5415 | goto fail_rbd_dev; |
| 5410 | 5416 | |
| @@ -5425,7 +5431,7 @@ static struct rbd_device *rbd_dev_create(struct rbd_client *rbdc, · 14 unmodified lines | ||
| 5425 | 5431 | return rbd_dev; |
| 5426 | 5432 | |
| 5427 | 5433 | fail_dev_id: |
| 5428 | − ida_simple_remove(&rbd_dev_id_ida, rbd_dev->dev_id); | |
| 5434 | + ida_free(&rbd_dev_id_ida, rbd_dev->dev_id); | |
| 5429 | 5435 | fail_rbd_dev: |
| 5430 | 5436 | rbd_dev_free(rbd_dev); |
| 5431 | 5437 | return NULL; |
| @@ -1593,14 +1593,15 @@ static int virtblk_freeze(struct virtio_device *vdev) · 1592 unmodified lines | ||
| 1593 | 1593 | { |
| 1594 | 1594 | struct virtio_blk *vblk = vdev->priv; |
| 1595 | 1595 | |
| 1596 | + /* Ensure no requests in virtqueues before deleting vqs. */ | |
| 1597 | + blk_mq_freeze_queue(vblk->disk->queue); | |
| 1598 | + | |
| 1596 | 1599 | /* Ensure we don't receive any more interrupts */ |
| 1597 | 1600 | virtio_reset_device(vdev); |
| 1598 | 1601 | |
| 1599 | 1602 | /* Make sure no work handler is accessing the device. */ |
| 1600 | 1603 | flush_work(&vblk->config_work); |
| 1601 | 1604 | |
| 1602 | − blk_mq_quiesce_queue(vblk->disk->queue); | |
| 1603 | − | |
| 1604 | 1605 | vdev->config->del_vqs(vdev); |
| 1605 | 1606 | kfree(vblk->vqs); |
| 1606 | 1607 | |
| @@ -1618,7 +1619,7 @@ static int virtblk_restore(struct virtio_device *vdev) · 11 unmodified lines | ||
| 1618 | 1619 | |
| 1619 | 1620 | virtio_device_ready(vdev); |
| 1620 | 1621 | |
| 1621 | − blk_mq_unquiesce_queue(vblk->disk->queue); | |
| 1622 | + blk_mq_unfreeze_queue(vblk->disk->queue); | |
| 1622 | 1623 | return 0; |
| 1623 | 1624 | } |
| 1624 | 1625 | #endif |
| @@ -1232,14 +1232,13 @@ static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy) · 1231 unmodified lines | ||
| 1232 | 1232 | max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq); |
| 1233 | 1233 | min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq); |
| 1234 | 1234 | |
| 1235 | + WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf); | |
| 1236 | + WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf); | |
| 1237 | + | |
| 1235 | 1238 | max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf, |
| 1236 | 1239 | cpudata->max_limit_perf); |
| 1237 | 1240 | min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf, |
| 1238 | 1241 | cpudata->max_limit_perf); |
| 1239 | − | |
| 1240 | − WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf); | |
| 1241 | − WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf); | |
| 1242 | − | |
| 1243 | 1242 | value = READ_ONCE(cpudata->cppc_req_cached); |
| 1244 | 1243 | |
| 1245 | 1244 | if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) |
| @@ -529,6 +529,30 @@ static int intel_pstate_cppc_get_scaling(int cpu) · 528 unmodified lines | ||
| 529 | 529 | } |
| 530 | 530 | #endif /* CONFIG_ACPI_CPPC_LIB */ |
| 531 | 531 | |
| 532 | +static int intel_pstate_freq_to_hwp_rel(struct cpudata *cpu, int freq, | |
| 533 | + unsigned int relation) | |
| 534 | +{ | |
| 535 | + if (freq == cpu->pstate.turbo_freq) | |
| 536 | + return cpu->pstate.turbo_pstate; | |
| 537 | + | |
| 538 | + if (freq == cpu->pstate.max_freq) | |
| 539 | + return cpu->pstate.max_pstate; | |
| 540 | + | |
| 541 | + switch (relation) { | |
| 542 | + case CPUFREQ_RELATION_H: | |
| 543 | + return freq / cpu->pstate.scaling; | |
| 544 | + case CPUFREQ_RELATION_C: | |
| 545 | + return DIV_ROUND_CLOSEST(freq, cpu->pstate.scaling); | |
| 546 | + } | |
| 547 | + | |
| 548 | + return DIV_ROUND_UP(freq, cpu->pstate.scaling); | |
| 549 | +} | |
| 550 | + | |
| 551 | +static int intel_pstate_freq_to_hwp(struct cpudata *cpu, int freq) | |
| 552 | +{ | |
| 553 | + return intel_pstate_freq_to_hwp_rel(cpu, freq, CPUFREQ_RELATION_L); | |
| 554 | +} | |
| 555 | + | |
| 532 | 556 | /** |
| 533 | 557 | * intel_pstate_hybrid_hwp_adjust - Calibrate HWP performance levels. |
| 534 | 558 | * @cpu: Target CPU. |
| @@ -546,6 +570,7 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) · 11 unmodified lines | ||
| 546 | 570 | int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling; |
| 547 | 571 | int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu); |
| 548 | 572 | int scaling = cpu->pstate.scaling; |
| 573 | + int freq; | |
| 549 | 574 | |
| 550 | 575 | pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys); |
| 551 | 576 | pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo); |
| @@ -559,16 +584,16 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu) · 7 unmodified lines | ||
| 559 | 584 | cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling, |
| 560 | 585 | perf_ctl_scaling); |
| 561 | 586 | |
| 562 | − cpu->pstate.max_pstate_physical = | |
| 563 | − DIV_ROUND_UP(perf_ctl_max_phys * perf_ctl_scaling, | |
| 564 | − scaling); | |
| 587 | + freq = perf_ctl_max_phys * perf_ctl_scaling; | |
| 588 | + cpu->pstate.max_pstate_physical = intel_pstate_freq_to_hwp(cpu, freq); | |
| 565 | 589 | |
| 566 | − cpu->pstate.min_freq = cpu->pstate.min_pstate * perf_ctl_scaling; | |
| 590 | + freq = cpu->pstate.min_pstate * perf_ctl_scaling; | |
| 591 | + cpu->pstate.min_freq = freq; | |
| 567 | 592 | /* |
| 568 | 593 | * Cast the min P-state value retrieved via pstate_funcs.get_min() to |
| 569 | 594 | * the effective range of HWP performance levels. |
| 570 | 595 | */ |
| 571 | − cpu->pstate.min_pstate = DIV_ROUND_UP(cpu->pstate.min_freq, scaling); | |
| 596 | + cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, freq); | |
| 572 | 597 | } |
| 573 | 598 | |
| 574 | 599 | static inline void update_turbo_state(void) |
| @@ -2528,13 +2553,12 @@ static void intel_pstate_update_perf_limits(struct cpudata *cpu, · 1953 unmodified lines | ||
| 2528 | 2553 | * abstract values to represent performance rather than pure ratios. |
| 2529 | 2554 | */ |
| 2530 | 2555 | if (hwp_active && cpu->pstate.scaling != perf_ctl_scaling) { |
| 2531 | − int scaling = cpu->pstate.scaling; | |
| 2532 | 2556 | int freq; |
| 2533 | 2557 | |
| 2534 | 2558 | freq = max_policy_perf * perf_ctl_scaling; |
| 2535 | − max_policy_perf = DIV_ROUND_UP(freq, scaling); | |
| 2559 | + max_policy_perf = intel_pstate_freq_to_hwp(cpu, freq); | |
| 2536 | 2560 | freq = min_policy_perf * perf_ctl_scaling; |
| 2537 | − min_policy_perf = DIV_ROUND_UP(freq, scaling); | |
| 2561 | + min_policy_perf = intel_pstate_freq_to_hwp(cpu, freq); | |
| 2538 | 2562 | } |
| 2539 | 2563 | |
| 2540 | 2564 | pr_debug("cpu:%d min_policy_perf:%d max_policy_perf:%d\n", |
| @@ -2908,18 +2932,7 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy, · 367 unmodified lines | ||
| 2908 | 2932 | |
| 2909 | 2933 | cpufreq_freq_transition_begin(policy, &freqs); |
| 2910 | 2934 | |
| 2911 | − switch (relation) { | |
| 2912 | − case CPUFREQ_RELATION_L: | |
| 2913 | − target_pstate = DIV_ROUND_UP(freqs.new, cpu->pstate.scaling); | |
| 2914 | − break; | |
| 2915 | − case CPUFREQ_RELATION_H: | |
| 2916 | − target_pstate = freqs.new / cpu->pstate.scaling; | |
| 2917 | − break; | |
| 2918 | − default: | |
| 2919 | − target_pstate = DIV_ROUND_CLOSEST(freqs.new, cpu->pstate.scaling); | |
| 2920 | − break; | |
| 2921 | − } | |
| 2922 | − | |
| 2935 | + target_pstate = intel_pstate_freq_to_hwp_rel(cpu, freqs.new, relation); | |
| 2923 | 2936 | target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, false); |
| 2924 | 2937 | |
| 2925 | 2938 | freqs.new = target_pstate * cpu->pstate.scaling; |
| @@ -2937,7 +2950,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy, · 11 unmodified lines | ||
| 2937 | 2950 | |
| 2938 | 2951 | update_turbo_state(); |
| 2939 | 2952 | |
| 2940 | − target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling); | |
| 2953 | + target_pstate = intel_pstate_freq_to_hwp(cpu, target_freq); | |
| 2941 | 2954 | |
| 2942 | 2955 | target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true); |
| 2943 | 2956 | |
| @@ -4545,6 +4545,7 @@ struct caam_hash_alg { · 4544 unmodified lines | ||
| 4545 | 4545 | struct list_head entry; |
| 4546 | 4546 | struct device *dev; |
| 4547 | 4547 | int alg_type; |
| 4548 | + bool is_hmac; | |
| 4548 | 4549 | struct ahash_alg ahash_alg; |
| 4549 | 4550 | }; |
| 4550 | 4551 | |
| @@ -4571,7 +4572,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) · 20 unmodified lines | ||
| 4571 | 4572 | |
| 4572 | 4573 | ctx->dev = caam_hash->dev; |
| 4573 | 4574 | |
| 4574 | − if (alg->setkey) { | |
| 4575 | + if (caam_hash->is_hmac) { | |
| 4575 | 4576 | ctx->adata.key_dma = dma_map_single_attrs(ctx->dev, ctx->key, |
| 4576 | 4577 | ARRAY_SIZE(ctx->key), |
| 4577 | 4578 | DMA_TO_DEVICE, |
| @@ -4611,7 +4612,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) · 33 unmodified lines | ||
| 4611 | 4612 | * For keyed hash algorithms shared descriptors |
| 4612 | 4613 | * will be created later in setkey() callback |
| 4613 | 4614 | */ |
| 4614 | − return alg->setkey ? 0 : ahash_set_sh_desc(ahash); | |
| 4615 | + return caam_hash->is_hmac ? 0 : ahash_set_sh_desc(ahash); | |
| 4615 | 4616 | } |
| 4616 | 4617 | |
| 4617 | 4618 | static void caam_hash_cra_exit(struct crypto_tfm *tfm) |
| @@ -4646,12 +4647,14 @@ static struct caam_hash_alg *caam_hash_alloc(struct device *dev, · 28 unmodified lines | ||
| 4646 | 4647 | template->hmac_name); |
| 4647 | 4648 | snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", |
| 4648 | 4649 | template->hmac_driver_name); |
| 4650 | + t_alg->is_hmac = true; | |
| 4649 | 4651 | } else { |
| 4650 | 4652 | snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", |
| 4651 | 4653 | template->name); |
| 4652 | 4654 | snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", |
| 4653 | 4655 | template->driver_name); |
| 4654 | 4656 | t_alg->ahash_alg.setkey = NULL; |
| 4657 | + t_alg->is_hmac = false; | |
| 4655 | 4658 | } |
| 4656 | 4659 | alg->cra_module = THIS_MODULE; |
| 4657 | 4660 | alg->cra_init = caam_hash_cra_init; |
| @@ -1753,6 +1753,7 @@ static struct caam_hash_template driver_hash[] = { · 1752 unmodified lines | ||
| 1753 | 1753 | struct caam_hash_alg { |
| 1754 | 1754 | struct list_head entry; |
| 1755 | 1755 | int alg_type; |
| 1756 | + bool is_hmac; | |
| 1756 | 1757 | struct ahash_engine_alg ahash_alg; |
| 1757 | 1758 | }; |
| 1758 | 1759 | |
| @@ -1804,7 +1805,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) · 45 unmodified lines | ||
| 1804 | 1805 | } else { |
| 1805 | 1806 | if (priv->era >= 6) { |
| 1806 | 1807 | ctx->dir = DMA_BIDIRECTIONAL; |
| 1807 | − ctx->key_dir = alg->setkey ? DMA_TO_DEVICE : DMA_NONE; | |
| 1808 | + ctx->key_dir = caam_hash->is_hmac ? DMA_TO_DEVICE : DMA_NONE; | |
| 1808 | 1809 | } else { |
| 1809 | 1810 | ctx->dir = DMA_TO_DEVICE; |
| 1810 | 1811 | ctx->key_dir = DMA_NONE; |
| @@ -1862,7 +1863,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) · 51 unmodified lines | ||
| 1862 | 1863 | * For keyed hash algorithms shared descriptors |
| 1863 | 1864 | * will be created later in setkey() callback |
| 1864 | 1865 | */ |
| 1865 | − return alg->setkey ? 0 : ahash_set_sh_desc(ahash); | |
| 1866 | + return caam_hash->is_hmac ? 0 : ahash_set_sh_desc(ahash); | |
| 1866 | 1867 | } |
| 1867 | 1868 | |
| 1868 | 1869 | static void caam_hash_cra_exit(struct crypto_tfm *tfm) |
| @@ -1915,12 +1916,14 @@ caam_hash_alloc(struct caam_hash_template *template, · 46 unmodified lines | ||
| 1915 | 1916 | template->hmac_name); |
| 1916 | 1917 | snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", |
| 1917 | 1918 | template->hmac_driver_name); |
| 1919 | + t_alg->is_hmac = true; | |
| 1918 | 1920 | } else { |
| 1919 | 1921 | snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", |
| 1920 | 1922 | template->name); |
| 1921 | 1923 | snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", |
| 1922 | 1924 | template->driver_name); |
| 1923 | 1925 | halg->setkey = NULL; |
| 1926 | + t_alg->is_hmac = false; | |
| 1924 | 1927 | } |
| 1925 | 1928 | alg->cra_module = THIS_MODULE; |
| 1926 | 1929 | alg->cra_init = caam_hash_cra_init; |
| @@ -534,10 +534,16 @@ EXPORT_SYMBOL_GPL(sev_platform_init); · 533 unmodified lines | ||
| 534 | 534 | |
| 535 | 535 | static int __sev_platform_shutdown_locked(int *error) |
| 536 | 536 | { |
| 537 | − struct sev_device *sev = psp_master->sev_data; | |
| 537 | + struct psp_device *psp = psp_master; | |
| 538 | + struct sev_device *sev; | |
| 538 | 539 | int ret; |
| 539 | 540 | |
| 540 | − if (!sev || sev->state == SEV_STATE_UNINIT) | |
| 541 | + if (!psp || !psp->sev_data) | |
| 542 | + return 0; | |
| 543 | + | |
| 544 | + sev = psp->sev_data; | |
| 545 | + | |
| 546 | + if (sev->state == SEV_STATE_UNINIT) | |
| 541 | 547 | return 0; |
| 542 | 548 | |
| 543 | 549 | ret = __sev_do_cmd_locked(SEV_CMD_SHUTDOWN, NULL, error); |
| @@ -463,6 +463,7 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id) · 462 unmodified lines | ||
| 463 | 463 | hw_data->fw_name = ADF_402XX_FW; |
| 464 | 464 | hw_data->fw_mmp_name = ADF_402XX_MMP; |
| 465 | 465 | hw_data->uof_get_name = uof_get_name_402xx; |
| 466 | + hw_data->get_ena_thd_mask = get_ena_thd_mask; | |
| 466 | 467 | break; |
| 467 | 468 | case ADF_401XX_PCI_DEVICE_ID: |
| 468 | 469 | hw_data->fw_name = ADF_4XXX_FW; |
| @@ -525,7 +525,7 @@ static int alloc_hpa(struct cxl_region *cxlr, resource_size_t size) · 524 unmodified lines | ||
| 525 | 525 | struct cxl_root_decoder *cxlrd = to_cxl_root_decoder(cxlr->dev.parent); |
| 526 | 526 | struct cxl_region_params *p = &cxlr->params; |
| 527 | 527 | struct resource *res; |
| 528 | − u32 remainder = 0; | |
| 528 | + u64 remainder = 0; | |
| 529 | 529 | |
| 530 | 530 | lockdep_assert_held_write(&cxl_region_rwsem); |
| 531 | 531 | |
| @@ -545,7 +545,7 @@ static int alloc_hpa(struct cxl_region *cxlr, resource_size_t size) · 13 unmodified lines | ||
| 545 | 545 | (cxlr->mode == CXL_DECODER_PMEM && uuid_is_null(&p->uuid))) |
| 546 | 546 | return -ENXIO; |
| 547 | 547 | |
| 548 | − div_u64_rem(size, SZ_256M * p->interleave_ways, &remainder); | |
| 548 | + div64_u64_rem(size, (u64)SZ_256M * p->interleave_ways, &remainder); | |
| 549 | 549 | if (remainder) |
| 550 | 550 | return -EINVAL; |
| 551 | 551 | |
| @@ -338,7 +338,7 @@ TRACE_EVENT(cxl_general_media, · 337 unmodified lines | ||
| 338 | 338 | |
| 339 | 339 | TP_fast_assign( |
| 340 | 340 | CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr); |
| 341 | − memcpy(&__entry->hdr_uuid, &CXL_EVENT_GEN_MEDIA_UUID, sizeof(uuid_t)); | |
| 341 | + __entry->hdr_uuid = CXL_EVENT_GEN_MEDIA_UUID; | |
| 342 | 342 | |
| 343 | 343 | /* General Media */ |
| 344 | 344 | __entry->dpa = le64_to_cpu(rec->phys_addr); |
| @@ -425,7 +425,7 @@ TRACE_EVENT(cxl_dram, · 80 unmodified lines | ||
| 425 | 425 | |
| 426 | 426 | TP_fast_assign( |
| 427 | 427 | CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr); |
| 428 | − memcpy(&__entry->hdr_uuid, &CXL_EVENT_DRAM_UUID, sizeof(uuid_t)); | |
| 428 | + __entry->hdr_uuid = CXL_EVENT_DRAM_UUID; | |
| 429 | 429 | |
| 430 | 430 | /* DRAM */ |
| 431 | 431 | __entry->dpa = le64_to_cpu(rec->phys_addr); |
| @@ -573,7 +573,7 @@ TRACE_EVENT(cxl_memory_module, · 141 unmodified lines | ||
| 573 | 573 | |
| 574 | 574 | TP_fast_assign( |
| 575 | 575 | CXL_EVT_TP_fast_assign(cxlmd, log, rec->hdr); |
| 576 | − memcpy(&__entry->hdr_uuid, &CXL_EVENT_MEM_MODULE_UUID, sizeof(uuid_t)); | |
| 576 | + __entry->hdr_uuid = CXL_EVENT_MEM_MODULE_UUID; | |
| 577 | 577 | |
| 578 | 578 | /* Memory Module Event */ |
| 579 | 579 | __entry->event_type = rec->event_type; |
| @@ -382,7 +382,7 @@ static int cxl_pci_mbox_send(struct cxl_memdev_state *mds, · 381 unmodified lines | ||
| 382 | 382 | return rc; |
| 383 | 383 | } |
| 384 | 384 | |
| 385 | −static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds) | |
| 385 | +static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds, bool irq_avail) | |
| 386 | 386 | { |
| 387 | 387 | struct cxl_dev_state *cxlds = &mds->cxlds; |
| 388 | 388 | const int cap = readl(cxlds->regs.mbox + CXLDEV_MBOX_CAPS_OFFSET); |
| @@ -441,7 +441,7 @@ static int cxl_pci_setup_mailbox(struct cxl_memdev_state *mds) · 52 unmodified lines | ||
| 441 | 441 | INIT_DELAYED_WORK(&mds->security.poll_dwork, cxl_mbox_sanitize_work); |
| 442 | 442 | |
| 443 | 443 | /* background command interrupts are optional */ |
| 444 | − if (!(cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ)) | |
| 444 | + if (!(cap & CXLDEV_MBOX_CAP_BG_CMD_IRQ) || !irq_avail) | |
| 445 | 445 | return 0; |
| 446 | 446 | |
| 447 | 447 | msgnum = FIELD_GET(CXLDEV_MBOX_CAP_IRQ_MSGNUM_MASK, cap); |
| @@ -588,7 +588,7 @@ static int cxl_mem_alloc_event_buf(struct cxl_memdev_state *mds) · 140 unmodified lines | ||
| 588 | 588 | return devm_add_action_or_reset(mds->cxlds.dev, free_event_buf, buf); |
| 589 | 589 | } |
| 590 | 590 | |
| 591 | −static int cxl_alloc_irq_vectors(struct pci_dev *pdev) | |
| 591 | +static bool cxl_alloc_irq_vectors(struct pci_dev *pdev) | |
| 592 | 592 | { |
| 593 | 593 | int nvecs; |
| 594 | 594 | |
| @@ -605,9 +605,9 @@ static int cxl_alloc_irq_vectors(struct pci_dev *pdev) · 10 unmodified lines | ||
| 605 | 605 | PCI_IRQ_MSIX | PCI_IRQ_MSI); |
| 606 | 606 | if (nvecs < 1) { |
| 607 | 607 | dev_dbg(&pdev->dev, "Failed to alloc irq vectors: %d\n", nvecs); |
| 608 | − return -ENXIO; | |
| 608 | + return false; | |
| 609 | 609 | } |
| 610 | − return 0; | |
| 610 | + return true; | |
| 611 | 611 | } |
| 612 | 612 | |
| 613 | 613 | static irqreturn_t cxl_event_thread(int irq, void *id) |
| @@ -743,7 +743,7 @@ static bool cxl_event_int_is_fw(u8 setting) · 129 unmodified lines | ||
| 743 | 743 | } |
| 744 | 744 | |
| 745 | 745 | static int cxl_event_config(struct pci_host_bridge *host_bridge, |
| 746 | − struct cxl_memdev_state *mds) | |
| 746 | + struct cxl_memdev_state *mds, bool irq_avail) | |
| 747 | 747 | { |
| 748 | 748 | struct cxl_event_interrupt_policy policy; |
| 749 | 749 | int rc; |
| @@ -755,6 +755,11 @@ static int cxl_event_config(struct pci_host_bridge *host_bridge, · 5 unmodified lines | ||
| 755 | 755 | if (!host_bridge->native_cxl_error) |
| 756 | 756 | return 0; |
| 757 | 757 | |
| 758 | + if (!irq_avail) { | |
| 759 | + dev_info(mds->cxlds.dev, "No interrupt support, disable event processing.\n"); | |
| 760 | + return 0; | |
| 761 | + } | |
| 762 | + | |
| 758 | 763 | rc = cxl_mem_alloc_event_buf(mds); |
| 759 | 764 | if (rc) |
| 760 | 765 | return rc; |
| @@ -789,6 +794,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 28 unmodified lines | ||
| 789 | 794 | struct cxl_register_map map; |
| 790 | 795 | struct cxl_memdev *cxlmd; |
| 791 | 796 | int i, rc, pmu_count; |
| 797 | + bool irq_avail; | |
| 792 | 798 | |
| 793 | 799 | /* |
| 794 | 800 | * Double check the anonymous union trickery in struct cxl_regs |
| @@ -846,11 +852,9 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 51 unmodified lines | ||
| 846 | 852 | else |
| 847 | 853 | dev_warn(&pdev->dev, "Media not active (%d)\n", rc); |
| 848 | 854 | |
| 849 | − rc = cxl_alloc_irq_vectors(pdev); | |
| 850 | − if (rc) | |
| 851 | − return rc; | |
| 855 | + irq_avail = cxl_alloc_irq_vectors(pdev); | |
| 852 | 856 | |
| 853 | − rc = cxl_pci_setup_mailbox(mds); | |
| 857 | + rc = cxl_pci_setup_mailbox(mds, irq_avail); | |
| 854 | 858 | if (rc) |
| 855 | 859 | return rc; |
| 856 | 860 | |
| @@ -909,7 +913,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 52 unmodified lines | ||
| 909 | 913 | } |
| 910 | 914 | } |
| 911 | 915 | |
| 912 | − rc = cxl_event_config(host_bridge, mds); | |
| 916 | + rc = cxl_event_config(host_bridge, mds, irq_avail); | |
| 913 | 917 | if (rc) |
| 914 | 918 | return rc; |
| 915 | 919 | |
| @@ -168,10 +168,7 @@ static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) · 167 unmodified lines | ||
| 168 | 168 | if (vmf->pgoff > buffer->pagecount) |
| 169 | 169 | return VM_FAULT_SIGBUS; |
| 170 | 170 | |
| 171 | − vmf->page = buffer->pages[vmf->pgoff]; | |
| 172 | − get_page(vmf->page); | |
| 173 | − | |
| 174 | − return 0; | |
| 171 | + return vmf_insert_pfn(vma, vmf->address, page_to_pfn(buffer->pages[vmf->pgoff])); | |
| 175 | 172 | } |
| 176 | 173 | |
| 177 | 174 | static const struct vm_operations_struct dma_heap_vm_ops = { |
| @@ -185,6 +182,8 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) · 7 unmodified lines | ||
| 185 | 182 | if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) |
| 186 | 183 | return -EINVAL; |
| 187 | 184 | |
| 185 | + vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); | |
| 186 | + | |
| 188 | 187 | vma->vm_ops = &dma_heap_vm_ops; |
| 189 | 188 | vma->vm_private_data = buffer; |
| 190 | 189 | |
| @@ -222,8 +222,14 @@ struct atdma_sg { · 221 unmodified lines | ||
| 222 | 222 | * @vd: pointer to the virtual dma descriptor. |
| 223 | 223 | * @atchan: pointer to the atmel dma channel. |
| 224 | 224 | * @total_len: total transaction byte count |
| 225 | − * @sg_len: number of sg entries. | |
| 225 | + * @sglen: number of sg entries. | |
| 226 | 226 | * @sg: array of sgs. |
| 227 | + * @boundary: number of transfers to perform before the automatic address increment operation | |
| 228 | + * @dst_hole: value to add to the destination address when the boundary has been reached | |
| 229 | + * @src_hole: value to add to the source address when the boundary has been reached | |
| 230 | + * @memset_buffer: buffer used for the memset operation | |
| 231 | + * @memset_paddr: physical address of the buffer used for the memset operation | |
| 232 | + * @memset_vaddr: virtual address of the buffer used for the memset operation | |
| 227 | 233 | */ |
| 228 | 234 | struct at_desc { |
| 229 | 235 | struct virt_dma_desc vd; |
| @@ -245,7 +251,10 @@ struct at_desc { · 15 unmodified lines | ||
| 245 | 251 | /*-- Channels --------------------------------------------------------*/ |
| 246 | 252 | |
| 247 | 253 | /** |
| 248 | − * atc_status - information bits stored in channel status flag | |
| 254 | + * enum atc_status - information bits stored in channel status flag | |
| 255 | + * | |
| 256 | + * @ATC_IS_PAUSED: If channel is pauses | |
| 257 | + * @ATC_IS_CYCLIC: If channel is cyclic | |
| 249 | 258 | * |
| 250 | 259 | * Manipulated with atomic operations. |
| 251 | 260 | */ |
| @@ -282,7 +291,6 @@ struct at_dma_chan { · 30 unmodified lines | ||
| 282 | 291 | u32 save_cfg; |
| 283 | 292 | u32 save_dscr; |
| 284 | 293 | struct dma_slave_config dma_sconfig; |
| 285 | − bool cyclic; | |
| 286 | 294 | struct at_desc *desc; |
| 287 | 295 | }; |
| 288 | 296 | |
| @@ -328,12 +336,12 @@ static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width) · 39 unmodified lines | ||
| 328 | 336 | /** |
| 329 | 337 | * struct at_dma - internal representation of an Atmel HDMA Controller |
| 330 | 338 | * @dma_device: dmaengine dma_device object members |
| 331 | − * @atdma_devtype: identifier of DMA controller compatibility | |
| 332 | − * @ch_regs: memory mapped register base | |
| 339 | + * @regs: memory mapped register base | |
| 333 | 340 | * @clk: dma controller clock |
| 334 | 341 | * @save_imr: interrupt mask register that is saved on suspend/resume cycle |
| 335 | 342 | * @all_chan_mask: all channels availlable in a mask |
| 336 | 343 | * @lli_pool: hw lli table |
| 344 | + * @memset_pool: hw memset pool | |
| 337 | 345 | * @chan: channels table to store at_dma_chan structures |
| 338 | 346 | */ |
| 339 | 347 | struct at_dma { |
| @@ -626,6 +634,9 @@ static inline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla) · 286 unmodified lines | ||
| 626 | 634 | |
| 627 | 635 | /** |
| 628 | 636 | * atc_get_llis_residue - Get residue for a hardware linked list transfer |
| 637 | + * @atchan: pointer to an atmel hdmac channel. | |
| 638 | + * @desc: pointer to the descriptor for which the residue is calculated. | |
| 639 | + * @residue: residue to be set to dma_tx_state. | |
| 629 | 640 | * |
| 630 | 641 | * Calculate the residue by removing the length of the Linked List Item (LLI) |
| 631 | 642 | * already transferred from the total length. To get the current LLI we can use |
| @@ -661,10 +672,8 @@ static inline u32 atc_calc_bytes_left(u32 current_len, u32 ctrla) · 29 unmodified lines | ||
| 661 | 672 | * two DSCR values are different, we read again the CTRLA then the DSCR till two |
| 662 | 673 | * consecutive read values from DSCR are equal or till the maximum trials is |
| 663 | 674 | * reach. This algorithm is very unlikely not to find a stable value for DSCR. |
| 664 | − * @atchan: pointer to an atmel hdmac channel. | |
| 665 | − * @desc: pointer to the descriptor for which the residue is calculated. | |
| 666 | − * @residue: residue to be set to dma_tx_state. | |
| 667 | − * Returns 0 on success, -errno otherwise. | |
| 675 | + * | |
| 676 | + * Returns: %0 on success, -errno otherwise. | |
| 668 | 677 | */ |
| 669 | 678 | static int atc_get_llis_residue(struct at_dma_chan *atchan, |
| 670 | 679 | struct at_desc *desc, u32 *residue) |
| @@ -731,7 +740,8 @@ static int atc_get_llis_residue(struct at_dma_chan *atchan, · 60 unmodified lines | ||
| 731 | 740 | * @chan: DMA channel |
| 732 | 741 | * @cookie: transaction identifier to check status of |
| 733 | 742 | * @residue: residue to be updated. |
| 734 | − * Return 0 on success, -errono otherwise. | |
| 743 | + * | |
| 744 | + * Return: %0 on success, -errno otherwise. | |
| 735 | 745 | */ |
| 736 | 746 | static int atc_get_residue(struct dma_chan *chan, dma_cookie_t cookie, |
| 737 | 747 | u32 *residue) |
| @@ -1710,7 +1720,7 @@ static void atc_issue_pending(struct dma_chan *chan) · 972 unmodified lines | ||
| 1710 | 1720 | * atc_alloc_chan_resources - allocate resources for DMA channel |
| 1711 | 1721 | * @chan: allocate descriptor resources for this channel |
| 1712 | 1722 | * |
| 1713 | − * return - the number of allocated descriptors | |
| 1723 | + * Return: the number of allocated descriptors | |
| 1714 | 1724 | */ |
| 1715 | 1725 | static int atc_alloc_chan_resources(struct dma_chan *chan) |
| 1716 | 1726 | { |
| @@ -38,15 +38,17 @@ static int dpaa2_qdma_alloc_chan_resources(struct dma_chan *chan) · 37 unmodified lines | ||
| 38 | 38 | if (!dpaa2_chan->fd_pool) |
| 39 | 39 | goto err; |
| 40 | 40 | |
| 41 | − dpaa2_chan->fl_pool = dma_pool_create("fl_pool", dev, | |
| 42 | − sizeof(struct dpaa2_fl_entry), | |
| 43 | − sizeof(struct dpaa2_fl_entry), 0); | |
| 41 | + dpaa2_chan->fl_pool = | |
| 42 | + dma_pool_create("fl_pool", dev, | |
| 43 | + sizeof(struct dpaa2_fl_entry) * 3, | |
| 44 | + sizeof(struct dpaa2_fl_entry), 0); | |
| 45 | + | |
| 44 | 46 | if (!dpaa2_chan->fl_pool) |
| 45 | 47 | goto err_fd; |
| 46 | 48 | |
| 47 | 49 | dpaa2_chan->sdd_pool = |
| 48 | 50 | dma_pool_create("sdd_pool", dev, |
| 49 | − sizeof(struct dpaa2_qdma_sd_d), | |
| 51 | + sizeof(struct dpaa2_qdma_sd_d) * 2, | |
| 50 | 52 | sizeof(struct dpaa2_qdma_sd_d), 0); |
| 51 | 53 | if (!dpaa2_chan->sdd_pool) |
| 52 | 54 | goto err_fl; |
| @@ -514,11 +514,11 @@ static struct fsl_qdma_queue · 513 unmodified lines | ||
| 514 | 514 | queue_temp = queue_head + i + (j * queue_num); |
| 515 | 515 | |
| 516 | 516 | queue_temp->cq = |
| 517 | − dma_alloc_coherent(&pdev->dev, | |
| 518 | − sizeof(struct fsl_qdma_format) * | |
| 519 | − queue_size[i], | |
| 520 | − &queue_temp->bus_addr, | |
| 521 | − GFP_KERNEL); | |
| 517 | + dmam_alloc_coherent(&pdev->dev, | |
| 518 | + sizeof(struct fsl_qdma_format) * | |
| 519 | + queue_size[i], | |
| 520 | + &queue_temp->bus_addr, | |
| 521 | + GFP_KERNEL); | |
| 522 | 522 | if (!queue_temp->cq) |
| 523 | 523 | return NULL; |
| 524 | 524 | queue_temp->block_base = fsl_qdma->block_base + |
| @@ -563,15 +563,14 @@ static struct fsl_qdma_queue · 38 unmodified lines | ||
| 563 | 563 | /* |
| 564 | 564 | * Buffer for queue command |
| 565 | 565 | */ |
| 566 | − status_head->cq = dma_alloc_coherent(&pdev->dev, | |
| 567 | − sizeof(struct fsl_qdma_format) * | |
| 568 | − status_size, | |
| 569 | − &status_head->bus_addr, | |
| 570 | − GFP_KERNEL); | |
| 571 | − if (!status_head->cq) { | |
| 572 | − devm_kfree(&pdev->dev, status_head); | |
| 566 | + status_head->cq = dmam_alloc_coherent(&pdev->dev, | |
| 567 | + sizeof(struct fsl_qdma_format) * | |
| 568 | + status_size, | |
| 569 | + &status_head->bus_addr, | |
| 570 | + GFP_KERNEL); | |
| 571 | + if (!status_head->cq) | |
| 573 | 572 | return NULL; |
| 574 | − } | |
| 573 | + | |
| 575 | 574 | status_head->n_cq = status_size; |
| 576 | 575 | status_head->virt_head = status_head->cq; |
| 577 | 576 | status_head->virt_tail = status_head->cq; |
| @@ -1268,8 +1267,6 @@ static void fsl_qdma_cleanup_vchan(struct dma_device *dmadev) · 690 unmodified lines | ||
| 1268 | 1267 | |
| 1269 | 1268 | static void fsl_qdma_remove(struct platform_device *pdev) |
| 1270 | 1269 | { |
| 1271 | − int i; | |
| 1272 | − struct fsl_qdma_queue *status; | |
| 1273 | 1270 | struct device_node *np = pdev->dev.of_node; |
| 1274 | 1271 | struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev); |
| 1275 | 1272 | |
| @@ -1277,12 +1274,6 @@ static void fsl_qdma_remove(struct platform_device *pdev) · 1 unmodified line | ||
| 1277 | 1274 | fsl_qdma_cleanup_vchan(&fsl_qdma->dma_dev); |
| 1278 | 1275 | of_dma_controller_free(np); |
| 1279 | 1276 | dma_async_device_unregister(&fsl_qdma->dma_dev); |
| 1280 | − | |
| 1281 | − for (i = 0; i < fsl_qdma->block_number; i++) { | |
| 1282 | − status = fsl_qdma->status[i]; | |
| 1283 | − dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) * | |
| 1284 | − status->n_cq, status->cq, status->bus_addr); | |
| 1285 | − } | |
| 1286 | 1277 | } |
| 1287 | 1278 | |
| 1288 | 1279 | static const struct of_device_id fsl_qdma_dt_ids[] = { |
| @@ -2404,6 +2404,11 @@ static int edma_probe(struct platform_device *pdev) · 2403 unmodified lines | ||
| 2404 | 2404 | if (irq > 0) { |
| 2405 | 2405 | irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint", |
| 2406 | 2406 | dev_name(dev)); |
| 2407 | + if (!irq_name) { | |
| 2408 | + ret = -ENOMEM; | |
| 2409 | + goto err_disable_pm; | |
| 2410 | + } | |
| 2411 | + | |
| 2407 | 2412 | ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name, |
| 2408 | 2413 | ecc); |
| 2409 | 2414 | if (ret) { |
| @@ -2420,6 +2425,11 @@ static int edma_probe(struct platform_device *pdev) · 10 unmodified lines | ||
| 2420 | 2425 | if (irq > 0) { |
| 2421 | 2426 | irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint", |
| 2422 | 2427 | dev_name(dev)); |
| 2428 | + if (!irq_name) { | |
| 2429 | + ret = -ENOMEM; | |
| 2430 | + goto err_disable_pm; | |
| 2431 | + } | |
| 2432 | + | |
| 2423 | 2433 | ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name, |
| 2424 | 2434 | ecc); |
| 2425 | 2435 | if (ret) { |
| @@ -3968,6 +3968,7 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, · 3967 unmodified lines | ||
| 3968 | 3968 | { |
| 3969 | 3969 | struct udma_chan *uc = to_udma_chan(&vc->chan); |
| 3970 | 3970 | struct udma_desc *d; |
| 3971 | + u8 status; | |
| 3971 | 3972 | |
| 3972 | 3973 | if (!vd) |
| 3973 | 3974 | return; |
| @@ -3977,12 +3978,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, · 3 unmodified lines | ||
| 3977 | 3978 | if (d->metadata_size) |
| 3978 | 3979 | udma_fetch_epib(uc, d); |
| 3979 | 3980 | |
| 3980 | − /* Provide residue information for the client */ | |
| 3981 | 3981 | if (result) { |
| 3982 | 3982 | void *desc_vaddr = udma_curr_cppi5_desc_vaddr(d, d->desc_idx); |
| 3983 | 3983 | |
| 3984 | 3984 | if (cppi5_desc_get_type(desc_vaddr) == |
| 3985 | 3985 | CPPI5_INFO0_DESC_TYPE_VAL_HOST) { |
| 3986 | + /* Provide residue information for the client */ | |
| 3986 | 3987 | result->residue = d->residue - |
| 3987 | 3988 | cppi5_hdesc_get_pktlen(desc_vaddr); |
| 3988 | 3989 | if (result->residue) |
| @@ -3991,7 +3992,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, · 2 unmodified lines | ||
| 3991 | 3992 | result->result = DMA_TRANS_NOERROR; |
| 3992 | 3993 | } else { |
| 3993 | 3994 | result->residue = 0; |
| 3994 | − result->result = DMA_TRANS_NOERROR; | |
| 3995 | + /* Propagate TR Response errors to the client */ | |
| 3996 | + status = d->hwdesc[0].tr_resp_base->status; | |
| 3997 | + if (status) | |
| 3998 | + result->result = DMA_TRANS_ABORTED; | |
| 3999 | + else | |
| 4000 | + result->result = DMA_TRANS_NOERROR; | |
| 3995 | 4001 | } |
| 3996 | 4002 | } |
| 3997 | 4003 | } |
| @@ -29,8 +29,6 @@ static u32 dpll_pin_xa_id; · 28 unmodified lines | ||
| 29 | 29 | WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) |
| 30 | 30 | #define ASSERT_DPLL_NOT_REGISTERED(d) \ |
| 31 | 31 | WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) |
| 32 | −#define ASSERT_PIN_REGISTERED(p) \ | |
| 33 | − WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED)) | |
| 34 | 32 | |
| 35 | 33 | struct dpll_device_registration { |
| 36 | 34 | struct list_head list; |
| @@ -425,6 +423,53 @@ void dpll_device_unregister(struct dpll_device *dpll, · 388 unmodified lines | ||
| 425 | 423 | } |
| 426 | 424 | EXPORT_SYMBOL_GPL(dpll_device_unregister); |
| 427 | 425 | |
| 426 | +static void dpll_pin_prop_free(struct dpll_pin_properties *prop) | |
| 427 | +{ | |
| 428 | + kfree(prop->package_label); | |
| 429 | + kfree(prop->panel_label); | |
| 430 | + kfree(prop->board_label); | |
| 431 | + kfree(prop->freq_supported); | |
| 432 | +} | |
| 433 | + | |
| 434 | +static int dpll_pin_prop_dup(const struct dpll_pin_properties *src, | |
| 435 | + struct dpll_pin_properties *dst) | |
| 436 | +{ | |
| 437 | + memcpy(dst, src, sizeof(*dst)); | |
| 438 | + if (src->freq_supported && src->freq_supported_num) { | |
| 439 | + size_t freq_size = src->freq_supported_num * | |
| 440 | + sizeof(*src->freq_supported); | |
| 441 | + dst->freq_supported = kmemdup(src->freq_supported, | |
| 442 | + freq_size, GFP_KERNEL); | |
| 443 | + if (!src->freq_supported) | |
| 444 | + return -ENOMEM; | |
| 445 | + } | |
| 446 | + if (src->board_label) { | |
| 447 | + dst->board_label = kstrdup(src->board_label, GFP_KERNEL); | |
| 448 | + if (!dst->board_label) | |
| 449 | + goto err_board_label; | |
| 450 | + } | |
| 451 | + if (src->panel_label) { | |
| 452 | + dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL); | |
| 453 | + if (!dst->panel_label) | |
| 454 | + goto err_panel_label; | |
| 455 | + } | |
| 456 | + if (src->package_label) { | |
| 457 | + dst->package_label = kstrdup(src->package_label, GFP_KERNEL); | |
| 458 | + if (!dst->package_label) | |
| 459 | + goto err_package_label; | |
| 460 | + } | |
| 461 | + | |
| 462 | + return 0; | |
| 463 | + | |
| 464 | +err_package_label: | |
| 465 | + kfree(dst->panel_label); | |
| 466 | +err_panel_label: | |
| 467 | + kfree(dst->board_label); | |
| 468 | +err_board_label: | |
| 469 | + kfree(dst->freq_supported); | |
| 470 | + return -ENOMEM; | |
| 471 | +} | |
| 472 | + | |
| 428 | 473 | static struct dpll_pin * |
| 429 | 474 | dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module, |
| 430 | 475 | const struct dpll_pin_properties *prop) |
| @@ -441,20 +486,24 @@ dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module, · 10 unmodified lines | ||
| 441 | 486 | if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || |
| 442 | 487 | prop->type > DPLL_PIN_TYPE_MAX)) { |
| 443 | 488 | ret = -EINVAL; |
| 444 | − goto err; | |
| 489 | + goto err_pin_prop; | |
| 445 | 490 | } |
| 446 | − pin->prop = prop; | |
| 491 | + ret = dpll_pin_prop_dup(prop, &pin->prop); | |
| 492 | + if (ret) | |
| 493 | + goto err_pin_prop; | |
| 447 | 494 | refcount_set(&pin->refcount, 1); |
| 448 | 495 | xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); |
| 449 | 496 | xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); |
| 450 | 497 | ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, |
| 451 | 498 | &dpll_pin_xa_id, GFP_KERNEL); |
| 452 | 499 | if (ret) |
| 453 | − goto err; | |
| 500 | + goto err_xa_alloc; | |
| 454 | 501 | return pin; |
| 455 | −err: | |
| 502 | +err_xa_alloc: | |
| 456 | 503 | xa_destroy(&pin->dpll_refs); |
| 457 | 504 | xa_destroy(&pin->parent_refs); |
| 505 | + dpll_pin_prop_free(&pin->prop); | |
| 506 | +err_pin_prop: | |
| 458 | 507 | kfree(pin); |
| 459 | 508 | return ERR_PTR(ret); |
| 460 | 509 | } |
| @@ -514,6 +563,7 @@ void dpll_pin_put(struct dpll_pin *pin) · 53 unmodified lines | ||
| 514 | 563 | xa_destroy(&pin->dpll_refs); |
| 515 | 564 | xa_destroy(&pin->parent_refs); |
| 516 | 565 | xa_erase(&dpll_pin_xa, pin->id); |
| 566 | + dpll_pin_prop_free(&pin->prop); | |
| 517 | 567 | kfree(pin); |
| 518 | 568 | } |
| 519 | 569 | mutex_unlock(&dpll_lock); |
| @@ -564,8 +614,6 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, · 44 unmodified lines | ||
| 564 | 614 | WARN_ON(!ops->state_on_dpll_get) || |
| 565 | 615 | WARN_ON(!ops->direction_get)) |
| 566 | 616 | return -EINVAL; |
| 567 | − if (ASSERT_DPLL_REGISTERED(dpll)) | |
| 568 | − return -EINVAL; | |
| 569 | 617 | |
| 570 | 618 | mutex_lock(&dpll_lock); |
| 571 | 619 | if (WARN_ON(!(dpll->module == pin->module && |
| @@ -636,15 +684,13 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, · 64 unmodified lines | ||
| 636 | 684 | unsigned long i, stop; |
| 637 | 685 | int ret; |
| 638 | 686 | |
| 639 | − if (WARN_ON(parent->prop->type != DPLL_PIN_TYPE_MUX)) | |
| 687 | + if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) | |
| 640 | 688 | return -EINVAL; |
| 641 | 689 | |
| 642 | 690 | if (WARN_ON(!ops) || |
| 643 | 691 | WARN_ON(!ops->state_on_pin_get) || |
| 644 | 692 | WARN_ON(!ops->direction_get)) |
| 645 | 693 | return -EINVAL; |
| 646 | − if (ASSERT_PIN_REGISTERED(parent)) | |
| 647 | − return -EINVAL; | |
| 648 | 694 | |
| 649 | 695 | mutex_lock(&dpll_lock); |
| 650 | 696 | ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv); |
| @@ -44,7 +44,7 @@ struct dpll_device { · 43 unmodified lines | ||
| 44 | 44 | * @module: module of creator |
| 45 | 45 | * @dpll_refs: hold referencees to dplls pin was registered with |
| 46 | 46 | * @parent_refs: hold references to parent pins pin was registered with |
| 47 | − * @prop: pointer to pin properties given by registerer | |
| 47 | + * @prop: pin properties copied from the registerer | |
| 48 | 48 | * @rclk_dev_name: holds name of device when pin can recover clock from it |
| 49 | 49 | * @refcount: refcount |
| 50 | 50 | **/ |
| @@ -55,7 +55,7 @@ struct dpll_pin { · 4 unmodified lines | ||
| 55 | 55 | struct module *module; |
| 56 | 56 | struct xarray dpll_refs; |
| 57 | 57 | struct xarray parent_refs; |
| 58 | − const struct dpll_pin_properties *prop; | |
| 58 | + struct dpll_pin_properties prop; | |
| 59 | 59 | refcount_t refcount; |
| 60 | 60 | }; |
| 61 | 61 | |
| @@ -303,17 +303,17 @@ dpll_msg_add_pin_freq(struct sk_buff *msg, struct dpll_pin *pin, · 302 unmodified lines | ||
| 303 | 303 | if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq, |
| 304 | 304 | DPLL_A_PIN_PAD)) |
| 305 | 305 | return -EMSGSIZE; |
| 306 | − for (fs = 0; fs < pin->prop->freq_supported_num; fs++) { | |
| 306 | + for (fs = 0; fs < pin->prop.freq_supported_num; fs++) { | |
| 307 | 307 | nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED); |
| 308 | 308 | if (!nest) |
| 309 | 309 | return -EMSGSIZE; |
| 310 | − freq = pin->prop->freq_supported[fs].min; | |
| 310 | + freq = pin->prop.freq_supported[fs].min; | |
| 311 | 311 | if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq), |
| 312 | 312 | &freq, DPLL_A_PIN_PAD)) { |
| 313 | 313 | nla_nest_cancel(msg, nest); |
| 314 | 314 | return -EMSGSIZE; |
| 315 | 315 | } |
| 316 | − freq = pin->prop->freq_supported[fs].max; | |
| 316 | + freq = pin->prop.freq_supported[fs].max; | |
| 317 | 317 | if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq), |
| 318 | 318 | &freq, DPLL_A_PIN_PAD)) { |
| 319 | 319 | nla_nest_cancel(msg, nest); |
| @@ -329,9 +329,9 @@ static bool dpll_pin_is_freq_supported(struct dpll_pin *pin, u32 freq) · 9 unmodified lines | ||
| 329 | 329 | { |
| 330 | 330 | int fs; |
| 331 | 331 | |
| 332 | − for (fs = 0; fs < pin->prop->freq_supported_num; fs++) | |
| 333 | − if (freq >= pin->prop->freq_supported[fs].min && | |
| 334 | − freq <= pin->prop->freq_supported[fs].max) | |
| 332 | + for (fs = 0; fs < pin->prop.freq_supported_num; fs++) | |
| 333 | + if (freq >= pin->prop.freq_supported[fs].min && | |
| 334 | + freq <= pin->prop.freq_supported[fs].max) | |
| 335 | 335 | return true; |
| 336 | 336 | return false; |
| 337 | 337 | } |
| @@ -421,7 +421,7 @@ static int · 83 unmodified lines | ||
| 421 | 421 | dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, |
| 422 | 422 | struct netlink_ext_ack *extack) |
| 423 | 423 | { |
| 424 | − const struct dpll_pin_properties *prop = pin->prop; | |
| 424 | + const struct dpll_pin_properties *prop = &pin->prop; | |
| 425 | 425 | struct dpll_pin_ref *ref; |
| 426 | 426 | int ret; |
| 427 | 427 | |
| @@ -553,6 +553,24 @@ __dpll_device_change_ntf(struct dpll_device *dpll) · 125 unmodified lines | ||
| 553 | 553 | return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll); |
| 554 | 554 | } |
| 555 | 555 | |
| 556 | +static bool dpll_pin_available(struct dpll_pin *pin) | |
| 557 | +{ | |
| 558 | + struct dpll_pin_ref *par_ref; | |
| 559 | + unsigned long i; | |
| 560 | + | |
| 561 | + if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED)) | |
| 562 | + return false; | |
| 563 | + xa_for_each(&pin->parent_refs, i, par_ref) | |
| 564 | + if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id, | |
| 565 | + DPLL_REGISTERED)) | |
| 566 | + return true; | |
| 567 | + xa_for_each(&pin->dpll_refs, i, par_ref) | |
| 568 | + if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id, | |
| 569 | + DPLL_REGISTERED)) | |
| 570 | + return true; | |
| 571 | + return false; | |
| 572 | +} | |
| 573 | + | |
| 556 | 574 | /** |
| 557 | 575 | * dpll_device_change_ntf - notify that the dpll device has been changed |
| 558 | 576 | * @dpll: registered dpll pointer |
| @@ -579,7 +597,7 @@ dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin) · 20 unmodified lines | ||
| 579 | 597 | int ret = -ENOMEM; |
| 580 | 598 | void *hdr; |
| 581 | 599 | |
| 582 | − if (WARN_ON(!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED))) | |
| 600 | + if (!dpll_pin_available(pin)) | |
| 583 | 601 | return -ENODEV; |
| 584 | 602 | |
| 585 | 603 | msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); |
| @@ -717,7 +735,7 @@ dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx, · 131 unmodified lines | ||
| 717 | 735 | int ret; |
| 718 | 736 | |
| 719 | 737 | if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE & |
| 720 | − pin->prop->capabilities)) { | |
| 738 | + pin->prop.capabilities)) { | |
| 721 | 739 | NL_SET_ERR_MSG(extack, "state changing is not allowed"); |
| 722 | 740 | return -EOPNOTSUPP; |
| 723 | 741 | } |
| @@ -753,7 +771,7 @@ dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin, · 29 unmodified lines | ||
| 753 | 771 | int ret; |
| 754 | 772 | |
| 755 | 773 | if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE & |
| 756 | − pin->prop->capabilities)) { | |
| 774 | + pin->prop.capabilities)) { | |
| 757 | 775 | NL_SET_ERR_MSG(extack, "state changing is not allowed"); |
| 758 | 776 | return -EOPNOTSUPP; |
| 759 | 777 | } |
| @@ -780,7 +798,7 @@ dpll_pin_prio_set(struct dpll_device *dpll, struct dpll_pin *pin, · 20 unmodified lines | ||
| 780 | 798 | int ret; |
| 781 | 799 | |
| 782 | 800 | if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE & |
| 783 | − pin->prop->capabilities)) { | |
| 801 | + pin->prop.capabilities)) { | |
| 784 | 802 | NL_SET_ERR_MSG(extack, "prio changing is not allowed"); |
| 785 | 803 | return -EOPNOTSUPP; |
| 786 | 804 | } |
| @@ -808,7 +826,7 @@ dpll_pin_direction_set(struct dpll_pin *pin, struct dpll_device *dpll, · 21 unmodified lines | ||
| 808 | 826 | int ret; |
| 809 | 827 | |
| 810 | 828 | if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE & |
| 811 | − pin->prop->capabilities)) { | |
| 829 | + pin->prop.capabilities)) { | |
| 812 | 830 | NL_SET_ERR_MSG(extack, "direction changing is not allowed"); |
| 813 | 831 | return -EOPNOTSUPP; |
| 814 | 832 | } |
| @@ -838,8 +856,8 @@ dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr, · 23 unmodified lines | ||
| 838 | 856 | int ret; |
| 839 | 857 | |
| 840 | 858 | phase_adj = nla_get_s32(phase_adj_attr); |
| 841 | − if (phase_adj > pin->prop->phase_range.max || | |
| 842 | − phase_adj < pin->prop->phase_range.min) { | |
| 859 | + if (phase_adj > pin->prop.phase_range.max || | |
| 860 | + phase_adj < pin->prop.phase_range.min) { | |
| 843 | 861 | NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr, |
| 844 | 862 | "phase adjust value not supported"); |
| 845 | 863 | return -EINVAL; |
| @@ -1023,7 +1041,7 @@ dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr, · 177 unmodified lines | ||
| 1023 | 1041 | unsigned long i; |
| 1024 | 1042 | |
| 1025 | 1043 | xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) { |
| 1026 | − prop = pin->prop; | |
| 1044 | + prop = &pin->prop; | |
| 1027 | 1045 | cid_match = clock_id ? pin->clock_id == clock_id : true; |
| 1028 | 1046 | mod_match = mod_name_attr && module_name(pin->module) ? |
| 1029 | 1047 | !nla_strcmp(mod_name_attr, |
| @@ -1130,6 +1148,10 @@ int dpll_nl_pin_id_get_doit(struct sk_buff *skb, struct genl_info *info) · 100 unmodified lines | ||
| 1130 | 1148 | } |
| 1131 | 1149 | pin = dpll_pin_find_from_nlattr(info); |
| 1132 | 1150 | if (!IS_ERR(pin)) { |
| 1151 | + if (!dpll_pin_available(pin)) { | |
| 1152 | + nlmsg_free(msg); | |
| 1153 | + return -ENODEV; | |
| 1154 | + } | |
| 1133 | 1155 | ret = dpll_msg_add_pin_handle(msg, pin); |
| 1134 | 1156 | if (ret) { |
| 1135 | 1157 | nlmsg_free(msg); |
| @@ -1179,6 +1201,8 @@ int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) · 43 unmodified lines | ||
| 1179 | 1201 | |
| 1180 | 1202 | xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED, |
| 1181 | 1203 | ctx->idx) { |
| 1204 | + if (!dpll_pin_available(pin)) | |
| 1205 | + continue; | |
| 1182 | 1206 | hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, |
| 1183 | 1207 | cb->nlh->nlmsg_seq, |
| 1184 | 1208 | &dpll_nl_family, NLM_F_MULTI, |
| @@ -1441,7 +1465,8 @@ int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, · 256 unmodified lines | ||
| 1441 | 1465 | } |
| 1442 | 1466 | info->user_ptr[0] = xa_load(&dpll_pin_xa, |
| 1443 | 1467 | nla_get_u32(info->attrs[DPLL_A_PIN_ID])); |
| 1444 | − if (!info->user_ptr[0]) { | |
| 1468 | + if (!info->user_ptr[0] || | |
| 1469 | + !dpll_pin_available(info->user_ptr[0])) { | |
| 1445 | 1470 | NL_SET_ERR_MSG(info->extack, "pin not found"); |
| 1446 | 1471 | ret = -ENODEV; |
| 1447 | 1472 | goto unlock_dev; |
| @@ -429,7 +429,23 @@ static void bm_work(struct work_struct *work) · 428 unmodified lines | ||
| 429 | 429 | */ |
| 430 | 430 | card->bm_generation = generation; |
| 431 | 431 | |
| 432 | − if (root_device == NULL) { | |
| 432 | + if (card->gap_count == 0) { | |
| 433 | + /* | |
| 434 | + * If self IDs have inconsistent gap counts, do a | |
| 435 | + * bus reset ASAP. The config rom read might never | |
| 436 | + * complete, so don't wait for it. However, still | |
| 437 | + * send a PHY configuration packet prior to the | |
| 438 | + * bus reset. The PHY configuration packet might | |
| 439 | + * fail, but 1394-2008 8.4.5.2 explicitly permits | |
| 440 | + * it in this case, so it should be safe to try. | |
| 441 | + */ | |
| 442 | + new_root_id = local_id; | |
| 443 | + /* | |
| 444 | + * We must always send a bus reset if the gap count | |
| 445 | + * is inconsistent, so bypass the 5-reset limit. | |
| 446 | + */ | |
| 447 | + card->bm_retries = 0; | |
| 448 | + } else if (root_device == NULL) { | |
| 433 | 449 | /* |
| 434 | 450 | * Either link_on is false, or we failed to read the |
| 435 | 451 | * config rom. In either case, pick another root. |
| @@ -118,10 +118,9 @@ static int textual_leaf_to_string(const u32 *block, char *buf, size_t size) · 117 unmodified lines | ||
| 118 | 118 | * @buf: where to put the string |
| 119 | 119 | * @size: size of @buf, in bytes |
| 120 | 120 | * |
| 121 | − * The string is taken from a minimal ASCII text descriptor leaf after | |
| 122 | − * the immediate entry with @key. The string is zero-terminated. | |
| 123 | − * An overlong string is silently truncated such that it and the | |
| 124 | − * zero byte fit into @size. | |
| 121 | + * The string is taken from a minimal ASCII text descriptor leaf just after the entry with the | |
| 122 | + * @key. The string is zero-terminated. An overlong string is silently truncated such that it | |
| 123 | + * and the zero byte fit into @size. | |
| 125 | 124 | * |
| 126 | 125 | * Returns strlen(buf) or a negative error code. |
| 127 | 126 | */ |
| @@ -368,8 +367,17 @@ static ssize_t show_text_leaf(struct device *dev, · 240 unmodified lines | ||
| 368 | 367 | for (i = 0; i < ARRAY_SIZE(directories) && !!directories[i]; ++i) { |
| 369 | 368 | int result = fw_csr_string(directories[i], attr->key, buf, bufsize); |
| 370 | 369 | // Detected. |
| 371 | − if (result >= 0) | |
| 370 | + if (result >= 0) { | |
| 372 | 371 | ret = result; |
| 372 | + } else if (i == 0 && attr->key == CSR_VENDOR) { | |
| 373 | + // Sony DVMC-DA1 has configuration ROM such that the descriptor leaf entry | |
| 374 | + // in the root directory follows to the directory entry for vendor ID | |
| 375 | + // instead of the immediate value for vendor ID. | |
| 376 | + result = fw_csr_string(directories[i], CSR_DIRECTORY | attr->key, buf, | |
| 377 | + bufsize); | |
| 378 | + if (result >= 0) | |
| 379 | + ret = result; | |
| 380 | + } | |
| 373 | 381 | } |
| 374 | 382 | |
| 375 | 383 | if (ret >= 0) { |
| @@ -107,12 +107,12 @@ struct ffa_drv_info { · 106 unmodified lines | ||
| 107 | 107 | struct work_struct notif_pcpu_work; |
| 108 | 108 | struct work_struct irq_work; |
| 109 | 109 | struct xarray partition_info; |
| 110 | − unsigned int partition_count; | |
| 111 | 110 | DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS)); |
| 112 | 111 | struct mutex notify_lock; /* lock to protect notifier hashtable */ |
| 113 | 112 | }; |
| 114 | 113 | |
| 115 | 114 | static struct ffa_drv_info *drv_info; |
| 115 | +static void ffa_partitions_cleanup(void); | |
| 116 | 116 | |
| 117 | 117 | /* |
| 118 | 118 | * The driver must be able to support all the versions from the earliest |
| @@ -733,6 +733,11 @@ static void __do_sched_recv_cb(u16 part_id, u16 vcpu, bool is_per_vcpu) · 614 unmodified lines | ||
| 733 | 733 | void *cb_data; |
| 734 | 734 | |
| 735 | 735 | partition = xa_load(&drv_info->partition_info, part_id); |
| 736 | + if (!partition) { | |
| 737 | + pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id); | |
| 738 | + return; | |
| 739 | + } | |
| 740 | + | |
| 736 | 741 | read_lock(&partition->rw_lock); |
| 737 | 742 | callback = partition->callback; |
| 738 | 743 | cb_data = partition->cb_data; |
| @@ -915,6 +920,11 @@ static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback, · 176 unmodified lines | ||
| 915 | 920 | return -EOPNOTSUPP; |
| 916 | 921 | |
| 917 | 922 | partition = xa_load(&drv_info->partition_info, part_id); |
| 923 | + if (!partition) { | |
| 924 | + pr_err("%s: Invalid partition ID 0x%x\n", __func__, part_id); | |
| 925 | + return -EINVAL; | |
| 926 | + } | |
| 927 | + | |
| 918 | 928 | write_lock(&partition->rw_lock); |
| 919 | 929 | |
| 920 | 930 | cb_valid = !!partition->callback; |
| @@ -1186,9 +1196,9 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid) · 265 unmodified lines | ||
| 1186 | 1196 | kfree(pbuf); |
| 1187 | 1197 | } |
| 1188 | 1198 | |
| 1189 | −static void ffa_setup_partitions(void) | |
| 1199 | +static int ffa_setup_partitions(void) | |
| 1190 | 1200 | { |
| 1191 | − int count, idx; | |
| 1201 | + int count, idx, ret; | |
| 1192 | 1202 | uuid_t uuid; |
| 1193 | 1203 | struct ffa_device *ffa_dev; |
| 1194 | 1204 | struct ffa_dev_part_info *info; |
| @@ -1197,7 +1207,7 @@ static void ffa_setup_partitions(void) · 2 unmodified lines | ||
| 1197 | 1207 | count = ffa_partition_probe(&uuid_null, &pbuf); |
| 1198 | 1208 | if (count <= 0) { |
| 1199 | 1209 | pr_info("%s: No partitions found, error %d\n", __func__, count); |
| 1200 | − return; | |
| 1210 | + return -EINVAL; | |
| 1201 | 1211 | } |
| 1202 | 1212 | |
| 1203 | 1213 | xa_init(&drv_info->partition_info); |
| @@ -1226,40 +1236,53 @@ static void ffa_setup_partitions(void) · 22 unmodified lines | ||
| 1226 | 1236 | ffa_device_unregister(ffa_dev); |
| 1227 | 1237 | continue; |
| 1228 | 1238 | } |
| 1229 | − xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL); | |
| 1239 | + rwlock_init(&info->rw_lock); | |
| 1240 | + ret = xa_insert(&drv_info->partition_info, tpbuf->id, | |
| 1241 | + info, GFP_KERNEL); | |
| 1242 | + if (ret) { | |
| 1243 | + pr_err("%s: failed to save partition ID 0x%x - ret:%d\n", | |
| 1244 | + __func__, tpbuf->id, ret); | |
| 1245 | + ffa_device_unregister(ffa_dev); | |
| 1246 | + kfree(info); | |
| 1247 | + } | |
| 1230 | 1248 | } |
| 1231 | − drv_info->partition_count = count; | |
| 1232 | 1249 | |
| 1233 | 1250 | kfree(pbuf); |
| 1234 | 1251 | |
| 1235 | 1252 | /* Allocate for the host */ |
| 1236 | 1253 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
| 1237 | − if (!info) | |
| 1238 | − return; | |
| 1239 | − xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL); | |
| 1240 | − drv_info->partition_count++; | |
| 1254 | + if (!info) { | |
| 1255 | + pr_err("%s: failed to alloc Host partition ID 0x%x. Abort.\n", | |
| 1256 | + __func__, drv_info->vm_id); | |
| 1257 | + /* Already registered devices are freed on bus_exit */ | |
| 1258 | + ffa_partitions_cleanup(); | |
| 1259 | + return -ENOMEM; | |
| 1260 | + } | |
| 1261 | + | |
| 1262 | + rwlock_init(&info->rw_lock); | |
| 1263 | + ret = xa_insert(&drv_info->partition_info, drv_info->vm_id, | |
| 1264 | + info, GFP_KERNEL); | |
| 1265 | + if (ret) { | |
| 1266 | + pr_err("%s: failed to save Host partition ID 0x%x - ret:%d. Abort.\n", | |
| 1267 | + __func__, drv_info->vm_id, ret); | |
| 1268 | + kfree(info); | |
| 1269 | + /* Already registered devices are freed on bus_exit */ | |
| 1270 | + ffa_partitions_cleanup(); | |
| 1271 | + } | |
| 1272 | + | |
| 1273 | + return ret; | |
| 1241 | 1274 | } |
| 1242 | 1275 | |
| 1243 | 1276 | static void ffa_partitions_cleanup(void) |
| 1244 | 1277 | { |
| 1245 | − struct ffa_dev_part_info **info; | |
| 1246 | − int idx, count = drv_info->partition_count; | |
| 1247 | − | |
| 1248 | − if (!count) | |
| 1249 | − return; | |
| 1250 | − | |
| 1251 | − info = kcalloc(count, sizeof(*info), GFP_KERNEL); | |
| 1252 | − if (!info) | |
| 1253 | − return; | |
| 1254 | − | |
| 1255 | − xa_extract(&drv_info->partition_info, (void **)info, 0, VM_ID_MASK, | |
| 1256 | − count, XA_PRESENT); | |
| 1278 | + struct ffa_dev_part_info *info; | |
| 1279 | + unsigned long idx; | |
| 1257 | 1280 | |
| 1258 | − for (idx = 0; idx < count; idx++) | |
| 1259 | − kfree(info[idx]); | |
| 1260 | − kfree(info); | |
| 1281 | + xa_for_each(&drv_info->partition_info, idx, info) { | |
| 1282 | + xa_erase(&drv_info->partition_info, idx); | |
| 1283 | + kfree(info); | |
| 1284 | + } | |
| 1261 | 1285 | |
| 1262 | − drv_info->partition_count = 0; | |
| 1263 | 1286 | xa_destroy(&drv_info->partition_info); |
| 1264 | 1287 | } |
| 1265 | 1288 | |
| @@ -1508,7 +1531,11 @@ static int __init ffa_init(void) · 242 unmodified lines | ||
| 1508 | 1531 | |
| 1509 | 1532 | ffa_notifications_setup(); |
| 1510 | 1533 | |
| 1511 | − ffa_setup_partitions(); | |
| 1534 | + ret = ffa_setup_partitions(); | |
| 1535 | + if (ret) { | |
| 1536 | + pr_err("failed to setup partitions\n"); | |
| 1537 | + goto cleanup_notifs; | |
| 1538 | + } | |
| 1512 | 1539 | |
| 1513 | 1540 | ret = ffa_sched_recv_cb_update(drv_info->vm_id, ffa_self_notif_handle, |
| 1514 | 1541 | drv_info, true); |
| @@ -1516,6 +1543,9 @@ static int __init ffa_init(void) · 1 unmodified line | ||
| 1516 | 1543 | pr_info("Failed to register driver sched callback %d\n", ret); |
| 1517 | 1544 | |
| 1518 | 1545 | return 0; |
| 1546 | + | |
| 1547 | +cleanup_notifs: | |
| 1548 | + ffa_notifications_cleanup(); | |
| 1519 | 1549 | free_pages: |
| 1520 | 1550 | if (drv_info->tx_buffer) |
| 1521 | 1551 | free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE); |
| @@ -1535,7 +1565,6 @@ static void __exit ffa_exit(void) · 13 unmodified lines | ||
| 1535 | 1565 | ffa_rxtx_unmap(drv_info->vm_id); |
| 1536 | 1566 | free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE); |
| 1537 | 1567 | free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE); |
| 1538 | − xa_destroy(&drv_info->partition_info); | |
| 1539 | 1568 | kfree(drv_info); |
| 1540 | 1569 | arm_ffa_bus_exit(); |
| 1541 | 1570 | } |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include "notify.h" |
| 14 | 14 | |
| 15 | 15 | /* Updated only after ALL the mandatory features for that version are merged */ |
| 16 | −#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001 | |
| 16 | +#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000 | |
| 17 | 17 | |
| 18 | 18 | enum scmi_clock_protocol_cmd { |
| 19 | 19 | CLOCK_ATTRIBUTES = 0x3, |
| @@ -954,8 +954,7 @@ static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph) · 934 unmodified lines | ||
| 954 | 954 | scmi_clock_describe_rates_get(ph, clkid, clk); |
| 955 | 955 | } |
| 956 | 956 | |
| 957 | − if (PROTOCOL_REV_MAJOR(version) >= 0x2 && | |
| 958 | − PROTOCOL_REV_MINOR(version) >= 0x1) { | |
| 957 | + if (PROTOCOL_REV_MAJOR(version) >= 0x3) { | |
| 959 | 958 | cinfo->clock_config_set = scmi_clock_config_set_v2; |
| 960 | 959 | cinfo->clock_config_get = scmi_clock_config_get_v2; |
| 961 | 960 | } else { |
| @@ -314,6 +314,7 @@ void shmem_fetch_notification(struct scmi_shared_mem __iomem *shmem, · 313 unmodified lines | ||
| 314 | 314 | void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem); |
| 315 | 315 | bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, |
| 316 | 316 | struct scmi_xfer *xfer); |
| 317 | +bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem); | |
| 317 | 318 | |
| 318 | 319 | /* declarations for message passing transports */ |
| 319 | 320 | struct scmi_msg_payld; |
| @@ -45,6 +45,20 @@ static void rx_callback(struct mbox_client *cl, void *m) · 44 unmodified lines | ||
| 45 | 45 | { |
| 46 | 46 | struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl); |
| 47 | 47 | |
| 48 | + /* | |
| 49 | + * An A2P IRQ is NOT valid when received while the platform still has | |
| 50 | + * the ownership of the channel, because the platform at first releases | |
| 51 | + * the SMT channel and then sends the completion interrupt. | |
| 52 | + * | |
| 53 | + * This addresses a possible race condition in which a spurious IRQ from | |
| 54 | + * a previous timed-out reply which arrived late could be wrongly | |
| 55 | + * associated with the next pending transaction. | |
| 56 | + */ | |
| 57 | + if (cl->knows_txdone && !shmem_channel_free(smbox->shmem)) { | |
| 58 | + dev_warn(smbox->cinfo->dev, "Ignoring spurious A2P IRQ !\n"); | |
| 59 | + return; | |
| 60 | + } | |
| 61 | + | |
| 48 | 62 | scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem), NULL); |
| 49 | 63 | } |
| 50 | 64 | |
| @@ -350,8 +350,8 @@ process_response_opp(struct scmi_opp *opp, unsigned int loop_idx, · 349 unmodified lines | ||
| 350 | 350 | } |
| 351 | 351 | |
| 352 | 352 | static inline void |
| 353 | −process_response_opp_v4(struct perf_dom_info *dom, struct scmi_opp *opp, | |
| 354 | − unsigned int loop_idx, | |
| 353 | +process_response_opp_v4(struct device *dev, struct perf_dom_info *dom, | |
| 354 | + struct scmi_opp *opp, unsigned int loop_idx, | |
| 355 | 355 | const struct scmi_msg_resp_perf_describe_levels_v4 *r) |
| 356 | 356 | { |
| 357 | 357 | opp->perf = le32_to_cpu(r->opp[loop_idx].perf_val); |
| @@ -362,10 +362,23 @@ process_response_opp_v4(struct perf_dom_info *dom, struct scmi_opp *opp, · 4 unmodified lines | ||
| 362 | 362 | /* Note that PERF v4 reports always five 32-bit words */ |
| 363 | 363 | opp->indicative_freq = le32_to_cpu(r->opp[loop_idx].indicative_freq); |
| 364 | 364 | if (dom->level_indexing_mode) { |
| 365 | + int ret; | |
| 366 | + | |
| 365 | 367 | opp->level_index = le32_to_cpu(r->opp[loop_idx].level_index); |
| 366 | 368 | |
| 367 | − xa_store(&dom->opps_by_idx, opp->level_index, opp, GFP_KERNEL); | |
| 368 | − xa_store(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL); | |
| 369 | + ret = xa_insert(&dom->opps_by_idx, opp->level_index, opp, | |
| 370 | + GFP_KERNEL); | |
| 371 | + if (ret) | |
| 372 | + dev_warn(dev, | |
| 373 | + "Failed to add opps_by_idx at %d - ret:%d\n", | |
| 374 | + opp->level_index, ret); | |
| 375 | + | |
| 376 | + ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL); | |
| 377 | + if (ret) | |
| 378 | + dev_warn(dev, | |
| 379 | + "Failed to add opps_by_lvl at %d - ret:%d\n", | |
| 380 | + opp->perf, ret); | |
| 381 | + | |
| 369 | 382 | hash_add(dom->opps_by_freq, &opp->hash, opp->indicative_freq); |
| 370 | 383 | } |
| 371 | 384 | } |
| @@ -382,7 +395,7 @@ iter_perf_levels_process_response(const struct scmi_protocol_handle *ph, · 10 unmodified lines | ||
| 382 | 395 | if (PROTOCOL_REV_MAJOR(p->version) <= 0x3) |
| 383 | 396 | process_response_opp(opp, st->loop_idx, response); |
| 384 | 397 | else |
| 385 | − process_response_opp_v4(p->perf_dom, opp, st->loop_idx, | |
| 398 | + process_response_opp_v4(ph->dev, p->perf_dom, opp, st->loop_idx, | |
| 386 | 399 | response); |
| 387 | 400 | p->perf_dom->opp_count++; |
| 388 | 401 | |
| @@ -1111,7 +1111,6 @@ static int scmi_raw_mode_setup(struct scmi_raw_mode_info *raw, · 1110 unmodified lines | ||
| 1111 | 1111 | int i; |
| 1112 | 1112 | |
| 1113 | 1113 | for (i = 0; i < num_chans; i++) { |
| 1114 | − void *xret; | |
| 1115 | 1114 | struct scmi_raw_queue *q; |
| 1116 | 1115 | |
| 1117 | 1116 | q = scmi_raw_queue_init(raw); |
| @@ -1120,13 +1119,12 @@ static int scmi_raw_mode_setup(struct scmi_raw_mode_info *raw, · 2 unmodified lines | ||
| 1120 | 1119 | goto err_xa; |
| 1121 | 1120 | } |
| 1122 | 1121 | |
| 1123 | − xret = xa_store(&raw->chans_q, channels[i], q, | |
| 1122 | + ret = xa_insert(&raw->chans_q, channels[i], q, | |
| 1124 | 1123 | GFP_KERNEL); |
| 1125 | − if (xa_err(xret)) { | |
| 1124 | + if (ret) { | |
| 1126 | 1125 | dev_err(dev, |
| 1127 | 1126 | "Fail to allocate Raw queue 0x%02X\n", |
| 1128 | 1127 | channels[i]); |
| 1129 | − ret = xa_err(xret); | |
| 1130 | 1128 | goto err_xa; |
| 1131 | 1129 | } |
| 1132 | 1130 | } |
| @@ -1322,6 +1320,12 @@ void scmi_raw_message_report(void *r, struct scmi_xfer *xfer, · 189 unmodified lines | ||
| 1322 | 1320 | dev = raw->handle->dev; |
| 1323 | 1321 | q = scmi_raw_queue_select(raw, idx, |
| 1324 | 1322 | SCMI_XFER_IS_CHAN_SET(xfer) ? chan_id : 0); |
| 1323 | + if (!q) { | |
| 1324 | + dev_warn(dev, | |
| 1325 | + "RAW[%d] - NO queue for chan 0x%X. Dropping report.\n", | |
| 1326 | + idx, chan_id); | |
| 1327 | + return; | |
| 1328 | + } | |
| 1325 | 1329 | |
| 1326 | 1330 | /* |
| 1327 | 1331 | * Grab the msg_q_lock upfront to avoid a possible race between |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/processor.h> |
| 11 | 11 | #include <linux/types.h> |
| 12 | 12 | |
| 13 | −#include <asm-generic/bug.h> | |
| 13 | +#include <linux/bug.h> | |
| 14 | 14 | |
| 15 | 15 | #include "common.h" |
| 16 | 16 | |
| @@ -122,3 +122,9 @@ bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, · 105 unmodified lines | ||
| 122 | 122 | (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR | |
| 123 | 123 | SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); |
| 124 | 124 | } |
| 125 | + | |
| 126 | +bool shmem_channel_free(struct scmi_shared_mem __iomem *shmem) | |
| 127 | +{ | |
| 128 | + return (ioread32(&shmem->channel_status) & | |
| 129 | + SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); | |
| 130 | +} | |
| @@ -107,7 +107,7 @@ static int __init arm_enable_runtime_services(void) · 106 unmodified lines | ||
| 107 | 107 | efi_memory_desc_t *md; |
| 108 | 108 | |
| 109 | 109 | for_each_efi_memory_desc(md) { |
| 110 | − int md_size = md->num_pages << EFI_PAGE_SHIFT; | |
| 110 | + u64 md_size = md->num_pages << EFI_PAGE_SHIFT; | |
| 111 | 111 | struct resource *res; |
| 112 | 112 | |
| 113 | 113 | if (!(md->attribute & EFI_MEMORY_SP)) |
| @@ -523,6 +523,17 @@ static void cper_print_tstamp(const char *pfx, · 522 unmodified lines | ||
| 523 | 523 | } |
| 524 | 524 | } |
| 525 | 525 | |
| 526 | +struct ignore_section { | |
| 527 | + guid_t guid; | |
| 528 | + const char *name; | |
| 529 | +}; | |
| 530 | + | |
| 531 | +static const struct ignore_section ignore_sections[] = { | |
| 532 | + { .guid = CPER_SEC_CXL_GEN_MEDIA_GUID, .name = "CXL General Media Event" }, | |
| 533 | + { .guid = CPER_SEC_CXL_DRAM_GUID, .name = "CXL DRAM Event" }, | |
| 534 | + { .guid = CPER_SEC_CXL_MEM_MODULE_GUID, .name = "CXL Memory Module Event" }, | |
| 535 | +}; | |
| 536 | + | |
| 526 | 537 | static void |
| 527 | 538 | cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata, |
| 528 | 539 | int sec_no) |
| @@ -543,6 +554,14 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata · 14 unmodified lines | ||
| 543 | 554 | printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text); |
| 544 | 555 | |
| 545 | 556 | snprintf(newpfx, sizeof(newpfx), "%s ", pfx); |
| 557 | + | |
| 558 | + for (int i = 0; i < ARRAY_SIZE(ignore_sections); i++) { | |
| 559 | + if (guid_equal(sec_type, &ignore_sections[i].guid)) { | |
| 560 | + printk("%ssection_type: %s\n", newpfx, ignore_sections[i].name); | |
| 561 | + return; | |
| 562 | + } | |
| 563 | + } | |
| 564 | + | |
| 546 | 565 | if (guid_equal(sec_type, &CPER_SEC_PROC_GENERIC)) { |
| 547 | 566 | struct cper_sec_proc_generic *proc_err = acpi_hest_get_payload(gdata); |
| 548 | 567 | |
| @@ -143,15 +143,6 @@ static __init int is_usable_memory(efi_memory_desc_t *md) · 142 unmodified lines | ||
| 143 | 143 | case EFI_BOOT_SERVICES_DATA: |
| 144 | 144 | case EFI_CONVENTIONAL_MEMORY: |
| 145 | 145 | case EFI_PERSISTENT_MEMORY: |
| 146 | − /* | |
| 147 | − * Special purpose memory is 'soft reserved', which means it | |
| 148 | − * is set aside initially, but can be hotplugged back in or | |
| 149 | − * be assigned to the dax driver after boot. | |
| 150 | − */ | |
| 151 | − if (efi_soft_reserve_enabled() && | |
| 152 | − (md->attribute & EFI_MEMORY_SP)) | |
| 153 | − return false; | |
| 154 | − | |
| 155 | 146 | /* |
| 156 | 147 | * According to the spec, these regions are no longer reserved |
| 157 | 148 | * after calling ExitBootServices(). However, we can only use |
| @@ -196,6 +187,16 @@ static __init void reserve_regions(void) · 38 unmodified lines | ||
| 196 | 187 | size = npages << PAGE_SHIFT; |
| 197 | 188 | |
| 198 | 189 | if (is_memory(md)) { |
| 190 | + /* | |
| 191 | + * Special purpose memory is 'soft reserved', which | |
| 192 | + * means it is set aside initially. Don't add a memblock | |
| 193 | + * for it now so that it can be hotplugged back in or | |
| 194 | + * be assigned to the dax driver after boot. | |
| 195 | + */ | |
| 196 | + if (efi_soft_reserve_enabled() && | |
| 197 | + (md->attribute & EFI_MEMORY_SP)) | |
| 198 | + continue; | |
| 199 | + | |
| 199 | 200 | early_init_dt_add_memory_arch(paddr, size); |
| 200 | 201 | |
| 201 | 202 | if (!is_usable_memory(md)) |
| @@ -28,7 +28,7 @@ cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \ · 27 unmodified lines | ||
| 28 | 28 | -DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \ |
| 29 | 29 | -DEFI_HAVE_STRCMP -fno-builtin -fpic \ |
| 30 | 30 | $(call cc-option,-mno-single-pic-base) |
| 31 | −cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE | |
| 31 | +cflags-$(CONFIG_RISCV) += -fpic -DNO_ALTERNATIVE -mno-relax | |
| 32 | 32 | cflags-$(CONFIG_LOONGARCH) += -fpie |
| 33 | 33 | |
| 34 | 34 | cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt |
| @@ -143,7 +143,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS · 108 unmodified lines | ||
| 143 | 143 | # exist. |
| 144 | 144 | STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \ |
| 145 | 145 | --prefix-symbols=__efistub_ |
| 146 | −STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20 | |
| 146 | +STUBCOPY_RELOC-$(CONFIG_RISCV) := -E R_RISCV_HI20\|R_RISCV_$(BITS)\|R_RISCV_RELAX | |
| 147 | 147 | |
| 148 | 148 | # For LoongArch, keep all the symbols in .init section and make sure that no |
| 149 | 149 | # absolute symbols references exist. |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * @max: the address that the last allocated memory page shall not |
| 15 | 15 | * exceed |
| 16 | 16 | * @align: minimum alignment of the base of the allocation |
| 17 | + * @memory_type: the type of memory to allocate | |
| 17 | 18 | * |
| 18 | 19 | * Allocate pages as EFI_LOADER_DATA. The allocated pages are aligned according |
| 19 | 20 | * to @align, which should be >= EFI_ALLOC_ALIGN. The last allocated page will |
| @@ -956,7 +956,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); · 955 unmodified lines | ||
| 956 | 956 | |
| 957 | 957 | efi_status_t efi_random_alloc(unsigned long size, unsigned long align, |
| 958 | 958 | unsigned long *addr, unsigned long random_seed, |
| 959 | − int memory_type, unsigned long alloc_limit); | |
| 959 | + int memory_type, unsigned long alloc_min, | |
| 960 | + unsigned long alloc_max); | |
| 960 | 961 | |
| 961 | 962 | efi_status_t efi_random_get_seed(void); |
| 962 | 963 | |
| @@ -119,7 +119,7 @@ efi_status_t efi_kaslr_relocate_kernel(unsigned long *image_addr, · 118 unmodified lines | ||
| 119 | 119 | */ |
| 120 | 120 | status = efi_random_alloc(*reserve_size, min_kimg_align, |
| 121 | 121 | reserve_addr, phys_seed, |
| 122 | − EFI_LOADER_CODE, EFI_ALLOC_LIMIT); | |
| 122 | + EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT); | |
| 123 | 123 | if (status != EFI_SUCCESS) |
| 124 | 124 | efi_warn("efi_random_alloc() failed: 0x%lx\n", status); |
| 125 | 125 | } else { |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | static unsigned long get_entry_num_slots(efi_memory_desc_t *md, |
| 18 | 18 | unsigned long size, |
| 19 | 19 | unsigned long align_shift, |
| 20 | − u64 alloc_limit) | |
| 20 | + u64 alloc_min, u64 alloc_max) | |
| 21 | 21 | { |
| 22 | 22 | unsigned long align = 1UL << align_shift; |
| 23 | 23 | u64 first_slot, last_slot, region_end; |
| @@ -30,11 +30,11 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, · 6 unmodified lines | ||
| 30 | 30 | return 0; |
| 31 | 31 | |
| 32 | 32 | region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1, |
| 33 | − alloc_limit); | |
| 33 | + alloc_max); | |
| 34 | 34 | if (region_end < size) |
| 35 | 35 | return 0; |
| 36 | 36 | |
| 37 | − first_slot = round_up(md->phys_addr, align); | |
| 37 | + first_slot = round_up(max(md->phys_addr, alloc_min), align); | |
| 38 | 38 | last_slot = round_down(region_end - size + 1, align); |
| 39 | 39 | |
| 40 | 40 | if (first_slot > last_slot) |
| @@ -56,7 +56,8 @@ efi_status_t efi_random_alloc(unsigned long size, · 15 unmodified lines | ||
| 56 | 56 | unsigned long *addr, |
| 57 | 57 | unsigned long random_seed, |
| 58 | 58 | int memory_type, |
| 59 | − unsigned long alloc_limit) | |
| 59 | + unsigned long alloc_min, | |
| 60 | + unsigned long alloc_max) | |
| 60 | 61 | { |
| 61 | 62 | unsigned long total_slots = 0, target_slot; |
| 62 | 63 | unsigned long total_mirrored_slots = 0; |
| @@ -78,7 +79,8 @@ efi_status_t efi_random_alloc(unsigned long size, · 15 unmodified lines | ||
| 78 | 79 | efi_memory_desc_t *md = (void *)map->map + map_offset; |
| 79 | 80 | unsigned long slots; |
| 80 | 81 | |
| 81 | − slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit); | |
| 82 | + slots = get_entry_num_slots(md, size, ilog2(align), alloc_min, | |
| 83 | + alloc_max); | |
| 82 | 84 | MD_NUM_SLOTS(md) = slots; |
| 83 | 85 | total_slots += slots; |
| 84 | 86 | if (md->attribute & EFI_MEMORY_MORE_RELIABLE) |
| @@ -223,8 +223,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) · 222 unmodified lines | ||
| 223 | 223 | } |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | −void efi_adjust_memory_range_protection(unsigned long start, | |
| 227 | − unsigned long size) | |
| 226 | +efi_status_t efi_adjust_memory_range_protection(unsigned long start, | |
| 227 | + unsigned long size) | |
| 228 | 228 | { |
| 229 | 229 | efi_status_t status; |
| 230 | 230 | efi_gcd_memory_space_desc_t desc; |
| @@ -236,13 +236,17 @@ void efi_adjust_memory_range_protection(unsigned long start, · 5 unmodified lines | ||
| 236 | 236 | rounded_end = roundup(start + size, EFI_PAGE_SIZE); |
| 237 | 237 | |
| 238 | 238 | if (memattr != NULL) { |
| 239 | − efi_call_proto(memattr, clear_memory_attributes, rounded_start, | |
| 240 | − rounded_end - rounded_start, EFI_MEMORY_XP); | |
| 241 | − return; | |
| 239 | + status = efi_call_proto(memattr, clear_memory_attributes, | |
| 240 | + rounded_start, | |
| 241 | + rounded_end - rounded_start, | |
| 242 | + EFI_MEMORY_XP); | |
| 243 | + if (status != EFI_SUCCESS) | |
| 244 | + efi_warn("Failed to clear EFI_MEMORY_XP attribute\n"); | |
| 245 | + return status; | |
| 242 | 246 | } |
| 243 | 247 | |
| 244 | 248 | if (efi_dxe_table == NULL) |
| 245 | − return; | |
| 249 | + return EFI_SUCCESS; | |
| 246 | 250 | |
| 247 | 251 | /* |
| 248 | 252 | * Don't modify memory region attributes, they are |
| @@ -255,7 +259,7 @@ void efi_adjust_memory_range_protection(unsigned long start, · 6 unmodified lines | ||
| 255 | 259 | status = efi_dxe_call(get_memory_space_descriptor, start, &desc); |
| 256 | 260 | |
| 257 | 261 | if (status != EFI_SUCCESS) |
| 258 | − return; | |
| 262 | + break; | |
| 259 | 263 | |
| 260 | 264 | next = desc.base_address + desc.length; |
| 261 | 265 | |
| @@ -280,8 +284,10 @@ void efi_adjust_memory_range_protection(unsigned long start, · 18 unmodified lines | ||
| 280 | 284 | unprotect_start, |
| 281 | 285 | unprotect_start + unprotect_size, |
| 282 | 286 | status); |
| 287 | + break; | |
| 283 | 288 | } |
| 284 | 289 | } |
| 290 | + return EFI_SUCCESS; | |
| 285 | 291 | } |
| 286 | 292 | |
| 287 | 293 | static void setup_unaccepted_memory(void) |
| @@ -793,6 +799,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) · 505 unmodified lines | ||
| 793 | 799 | |
| 794 | 800 | status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr, |
| 795 | 801 | seed[0], EFI_LOADER_CODE, |
| 802 | + LOAD_PHYSICAL_ADDR, | |
| 796 | 803 | EFI_X86_KERNEL_ALLOC_LIMIT); |
| 797 | 804 | if (status != EFI_SUCCESS) |
| 798 | 805 | return status; |
| @@ -805,9 +812,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) · 6 unmodified lines | ||
| 805 | 812 | |
| 806 | 813 | *kernel_entry = addr + entry; |
| 807 | 814 | |
| 808 | − efi_adjust_memory_range_protection(addr, kernel_total_size); | |
| 809 | − | |
| 810 | − return EFI_SUCCESS; | |
| 815 | + return efi_adjust_memory_range_protection(addr, kernel_total_size); | |
| 811 | 816 | } |
| 812 | 817 | |
| 813 | 818 | static void __noreturn enter_kernel(unsigned long kernel_addr, |
| @@ -5,8 +5,8 @@ · 4 unmodified lines | ||
| 5 | 5 | extern void trampoline_32bit_src(void *, bool); |
| 6 | 6 | extern const u16 trampoline_ljmp_imm_offset; |
| 7 | 7 | |
| 8 | −void efi_adjust_memory_range_protection(unsigned long start, | |
| 9 | − unsigned long size); | |
| 8 | +efi_status_t efi_adjust_memory_range_protection(unsigned long start, | |
| 9 | + unsigned long size); | |
| 10 | 10 | |
| 11 | 11 | #ifdef CONFIG_X86_64 |
| 12 | 12 | efi_status_t efi_setup_5level_paging(void); |
| @@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) · 118 unmodified lines | ||
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | status = efi_random_alloc(alloc_size, min_kimg_align, &image_base, |
| 122 | − seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT); | |
| 122 | + seed, EFI_LOADER_CODE, 0, EFI_ALLOC_LIMIT); | |
| 123 | 123 | if (status != EFI_SUCCESS) { |
| 124 | 124 | efi_err("Failed to allocate memory\n"); |
| 125 | 125 | goto free_cmdline; |
| @@ -85,7 +85,7 @@ static int __init riscv_enable_runtime_services(void) · 84 unmodified lines | ||
| 85 | 85 | efi_memory_desc_t *md; |
| 86 | 86 | |
| 87 | 87 | for_each_efi_memory_desc(md) { |
| 88 | − int md_size = md->num_pages << EFI_PAGE_SHIFT; | |
| 88 | + u64 md_size = md->num_pages << EFI_PAGE_SHIFT; | |
| 89 | 89 | struct resource *res; |
| 90 | 90 | |
| 91 | 91 | if (!(md->attribute & EFI_MEMORY_SP)) |
| @@ -128,4 +128,4 @@ unlock_mutex: · 127 unmodified lines | ||
| 128 | 128 | } |
| 129 | 129 | |
| 130 | 130 | /* must execute after PCI subsystem for EFI quirks */ |
| 131 | −subsys_initcall_sync(sysfb_init); | |
| 131 | +device_initcall(sysfb_init); | |
| @@ -325,20 +325,27 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) · 324 unmodified lines | ||
| 325 | 325 | switch (flow_type) { |
| 326 | 326 | case IRQ_TYPE_LEVEL_HIGH: |
| 327 | 327 | sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1); |
| 328 | + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1); | |
| 328 | 329 | break; |
| 329 | 330 | case IRQ_TYPE_LEVEL_LOW: |
| 330 | 331 | sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0); |
| 332 | + sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1); | |
| 331 | 333 | break; |
| 332 | 334 | case IRQ_TYPE_EDGE_RISING: |
| 333 | 335 | case IRQ_TYPE_EDGE_FALLING: |
| 334 | 336 | case IRQ_TYPE_EDGE_BOTH: |
| 335 | 337 | state = sprd_eic_get(chip, offset); |
| 336 | − if (state) | |
| 338 | + if (state) { | |
| 337 | 339 | sprd_eic_update(chip, offset, |
| 338 | 340 | SPRD_EIC_DBNC_IEV, 0); |
| 339 | − else | |
| 341 | + sprd_eic_update(chip, offset, | |
| 342 | + SPRD_EIC_DBNC_IC, 1); | |
| 343 | + } else { | |
| 340 | 344 | sprd_eic_update(chip, offset, |
| 341 | 345 | SPRD_EIC_DBNC_IEV, 1); |
| 346 | + sprd_eic_update(chip, offset, | |
| 347 | + SPRD_EIC_DBNC_IC, 1); | |
| 348 | + } | |
| 342 | 349 | break; |
| 343 | 350 | default: |
| 344 | 351 | return -ENOTSUPP; |
| @@ -350,20 +357,27 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) · 5 unmodified lines | ||
| 350 | 357 | switch (flow_type) { |
| 351 | 358 | case IRQ_TYPE_LEVEL_HIGH: |
| 352 | 359 | sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0); |
| 360 | + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1); | |
| 353 | 361 | break; |
| 354 | 362 | case IRQ_TYPE_LEVEL_LOW: |
| 355 | 363 | sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1); |
| 364 | + sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1); | |
| 356 | 365 | break; |
| 357 | 366 | case IRQ_TYPE_EDGE_RISING: |
| 358 | 367 | case IRQ_TYPE_EDGE_FALLING: |
| 359 | 368 | case IRQ_TYPE_EDGE_BOTH: |
| 360 | 369 | state = sprd_eic_get(chip, offset); |
| 361 | − if (state) | |
| 370 | + if (state) { | |
| 362 | 371 | sprd_eic_update(chip, offset, |
| 363 | 372 | SPRD_EIC_LATCH_INTPOL, 0); |
| 364 | − else | |
| 373 | + sprd_eic_update(chip, offset, | |
| 374 | + SPRD_EIC_LATCH_INTCLR, 1); | |
| 375 | + } else { | |
| 365 | 376 | sprd_eic_update(chip, offset, |
| 366 | 377 | SPRD_EIC_LATCH_INTPOL, 1); |
| 378 | + sprd_eic_update(chip, offset, | |
| 379 | + SPRD_EIC_LATCH_INTCLR, 1); | |
| 380 | + } | |
| 367 | 381 | break; |
| 368 | 382 | default: |
| 369 | 383 | return -ENOTSUPP; |
| @@ -377,29 +391,34 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) · 7 unmodified lines | ||
| 377 | 391 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); |
| 378 | 392 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0); |
| 379 | 393 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1); |
| 394 | + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1); | |
| 380 | 395 | irq_set_handler_locked(data, handle_edge_irq); |
| 381 | 396 | break; |
| 382 | 397 | case IRQ_TYPE_EDGE_FALLING: |
| 383 | 398 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); |
| 384 | 399 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0); |
| 385 | 400 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0); |
| 401 | + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1); | |
| 386 | 402 | irq_set_handler_locked(data, handle_edge_irq); |
| 387 | 403 | break; |
| 388 | 404 | case IRQ_TYPE_EDGE_BOTH: |
| 389 | 405 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0); |
| 390 | 406 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1); |
| 407 | + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1); | |
| 391 | 408 | irq_set_handler_locked(data, handle_edge_irq); |
| 392 | 409 | break; |
| 393 | 410 | case IRQ_TYPE_LEVEL_HIGH: |
| 394 | 411 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); |
| 395 | 412 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1); |
| 396 | 413 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1); |
| 414 | + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1); | |
| 397 | 415 | irq_set_handler_locked(data, handle_level_irq); |
| 398 | 416 | break; |
| 399 | 417 | case IRQ_TYPE_LEVEL_LOW: |
| 400 | 418 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0); |
| 401 | 419 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1); |
| 402 | 420 | sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0); |
| 421 | + sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1); | |
| 403 | 422 | irq_set_handler_locked(data, handle_level_irq); |
| 404 | 423 | break; |
| 405 | 424 | default: |
| @@ -412,29 +431,34 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type) · 6 unmodified lines | ||
| 412 | 431 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); |
| 413 | 432 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0); |
| 414 | 433 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1); |
| 434 | + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1); | |
| 415 | 435 | irq_set_handler_locked(data, handle_edge_irq); |
| 416 | 436 | break; |
| 417 | 437 | case IRQ_TYPE_EDGE_FALLING: |
| 418 | 438 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); |
| 419 | 439 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0); |
| 420 | 440 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0); |
| 441 | + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1); | |
| 421 | 442 | irq_set_handler_locked(data, handle_edge_irq); |
| 422 | 443 | break; |
| 423 | 444 | case IRQ_TYPE_EDGE_BOTH: |
| 424 | 445 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0); |
| 425 | 446 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1); |
| 447 | + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1); | |
| 426 | 448 | irq_set_handler_locked(data, handle_edge_irq); |
| 427 | 449 | break; |
| 428 | 450 | case IRQ_TYPE_LEVEL_HIGH: |
| 429 | 451 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); |
| 430 | 452 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1); |
| 431 | 453 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1); |
| 454 | + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1); | |
| 432 | 455 | irq_set_handler_locked(data, handle_level_irq); |
| 433 | 456 | break; |
| 434 | 457 | case IRQ_TYPE_LEVEL_LOW: |
| 435 | 458 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0); |
| 436 | 459 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1); |
| 437 | 460 | sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0); |
| 461 | + sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1); | |
| 438 | 462 | irq_set_handler_locked(data, handle_level_irq); |
| 439 | 463 | break; |
| 440 | 464 | default: |
| @@ -1651,6 +1651,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = { · 1650 unmodified lines | ||
| 1651 | 1651 | .ignore_interrupt = "INT33FC:00@3", |
| 1652 | 1652 | }, |
| 1653 | 1653 | }, |
| 1654 | + { | |
| 1655 | + /* | |
| 1656 | + * Spurious wakeups from TP_ATTN# pin | |
| 1657 | + * Found in BIOS 0.35 | |
| 1658 | + * https://gitlab.freedesktop.org/drm/amd/-/issues/3073 | |
| 1659 | + */ | |
| 1660 | + .matches = { | |
| 1661 | + DMI_MATCH(DMI_SYS_VENDOR, "GPD"), | |
| 1662 | + DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"), | |
| 1663 | + }, | |
| 1664 | + .driver_data = &(struct acpi_gpiolib_dmi_quirk) { | |
| 1665 | + .ignore_wake = "PNP0C50:00@8", | |
| 1666 | + }, | |
| 1667 | + }, | |
| 1654 | 1668 | {} /* Terminating entry */ |
| 1655 | 1669 | }; |
| 1656 | 1670 | |
| @@ -1010,15 +1010,15 @@ err_remove_of_chip: · 1009 unmodified lines | ||
| 1010 | 1010 | err_free_gpiochip_mask: |
| 1011 | 1011 | gpiochip_remove_pin_ranges(gc); |
| 1012 | 1012 | gpiochip_free_valid_mask(gc); |
| 1013 | +err_remove_from_list: | |
| 1014 | + spin_lock_irqsave(&gpio_lock, flags); | |
| 1015 | + list_del(&gdev->list); | |
| 1016 | + spin_unlock_irqrestore(&gpio_lock, flags); | |
| 1013 | 1017 | if (gdev->dev.release) { |
| 1014 | 1018 | /* release() has been registered by gpiochip_setup_dev() */ |
| 1015 | 1019 | gpio_device_put(gdev); |
| 1016 | 1020 | goto err_print_message; |
| 1017 | 1021 | } |
| 1018 | −err_remove_from_list: | |
| 1019 | − spin_lock_irqsave(&gpio_lock, flags); | |
| 1020 | − list_del(&gdev->list); | |
| 1021 | − spin_unlock_irqrestore(&gpio_lock, flags); | |
| 1022 | 1022 | err_free_label: |
| 1023 | 1023 | kfree_const(gdev->label); |
| 1024 | 1024 | err_free_descs: |
| @@ -1078,6 +1078,8 @@ struct amdgpu_device { · 1077 unmodified lines | ||
| 1078 | 1078 | bool in_s3; |
| 1079 | 1079 | bool in_s4; |
| 1080 | 1080 | bool in_s0ix; |
| 1081 | + /* indicate amdgpu suspension status */ | |
| 1082 | + bool suspend_complete; | |
| 1081 | 1083 | |
| 1082 | 1084 | enum pp_mp1_state mp1_state; |
| 1083 | 1085 | struct amdgpu_doorbell_index doorbell_index; |
| @@ -141,11 +141,31 @@ static void amdgpu_amdkfd_reset_work(struct work_struct *work) · 140 unmodified lines | ||
| 141 | 141 | static const struct drm_client_funcs kfd_client_funcs = { |
| 142 | 142 | .unregister = drm_client_release, |
| 143 | 143 | }; |
| 144 | + | |
| 145 | +int amdgpu_amdkfd_drm_client_create(struct amdgpu_device *adev) | |
| 146 | +{ | |
| 147 | + int ret; | |
| 148 | + | |
| 149 | + if (!adev->kfd.init_complete) | |
| 150 | + return 0; | |
| 151 | + | |
| 152 | + ret = drm_client_init(&adev->ddev, &adev->kfd.client, "kfd", | |
| 153 | + &kfd_client_funcs); | |
| 154 | + if (ret) { | |
| 155 | + dev_err(adev->dev, "Failed to init DRM client: %d\n", | |
| 156 | + ret); | |
| 157 | + return ret; | |
| 158 | + } | |
| 159 | + | |
| 160 | + drm_client_register(&adev->kfd.client); | |
| 161 | + | |
| 162 | + return 0; | |
| 163 | +} | |
| 164 | + | |
| 144 | 165 | void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) |
| 145 | 166 | { |
| 146 | 167 | int i; |
| 147 | 168 | int last_valid_bit; |
| 148 | − int ret; | |
| 149 | 169 | |
| 150 | 170 | amdgpu_amdkfd_gpuvm_init_mem_limits(); |
| 151 | 171 | |
| @@ -164,12 +184,6 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 12 unmodified lines | ||
| 164 | 184 | .enable_mes = adev->enable_mes, |
| 165 | 185 | }; |
| 166 | 186 | |
| 167 | − ret = drm_client_init(&adev->ddev, &adev->kfd.client, "kfd", &kfd_client_funcs); | |
| 168 | − if (ret) { | |
| 169 | − dev_err(adev->dev, "Failed to init DRM client: %d\n", ret); | |
| 170 | − return; | |
| 171 | − } | |
| 172 | − | |
| 173 | 187 | /* this is going to have a few of the MSBs set that we need to |
| 174 | 188 | * clear |
| 175 | 189 | */ |
| @@ -208,10 +222,6 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) · 32 unmodified lines | ||
| 208 | 222 | |
| 209 | 223 | adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev, |
| 210 | 224 | &gpu_resources); |
| 211 | − if (adev->kfd.init_complete) | |
| 212 | − drm_client_register(&adev->kfd.client); | |
| 213 | − else | |
| 214 | − drm_client_release(&adev->kfd.client); | |
| 215 | 225 | |
| 216 | 226 | amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; |
| 217 | 227 | |
| @@ -182,6 +182,8 @@ int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev, · 181 unmodified lines | ||
| 182 | 182 | struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, |
| 183 | 183 | struct mm_struct *mm, |
| 184 | 184 | struct svm_range_bo *svm_bo); |
| 185 | + | |
| 186 | +int amdgpu_amdkfd_drm_client_create(struct amdgpu_device *adev); | |
| 185 | 187 | #if defined(CONFIG_DEBUG_FS) |
| 186 | 188 | int kfd_debugfs_kfd_mem_limits(struct seq_file *m, void *data); |
| 187 | 189 | #endif |
| @@ -301,7 +303,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev, · 113 unmodified lines | ||
| 301 | 303 | struct kgd_mem *mem, void *drm_priv); |
| 302 | 304 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( |
| 303 | 305 | struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv); |
| 304 | −void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv); | |
| 306 | +int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv); | |
| 305 | 307 | int amdgpu_amdkfd_gpuvm_sync_memory( |
| 306 | 308 | struct amdgpu_device *adev, struct kgd_mem *mem, bool intr); |
| 307 | 309 | int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem, |
| @@ -290,7 +290,7 @@ static int suspend_resume_compute_scheduler(struct amdgpu_device *adev, bool sus · 289 unmodified lines | ||
| 290 | 290 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { |
| 291 | 291 | struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; |
| 292 | 292 | |
| 293 | − if (!(ring && drm_sched_wqueue_ready(&ring->sched))) | |
| 293 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 294 | 294 | continue; |
| 295 | 295 | |
| 296 | 296 | /* stop secheduler and drain ring. */ |
| @@ -2085,21 +2085,35 @@ out: · 2084 unmodified lines | ||
| 2085 | 2085 | return ret; |
| 2086 | 2086 | } |
| 2087 | 2087 | |
| 2088 | −void amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv) | |
| 2088 | +int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv) | |
| 2089 | 2089 | { |
| 2090 | 2090 | struct kfd_mem_attachment *entry; |
| 2091 | 2091 | struct amdgpu_vm *vm; |
| 2092 | + int ret; | |
| 2092 | 2093 | |
| 2093 | 2094 | vm = drm_priv_to_vm(drm_priv); |
| 2094 | 2095 | |
| 2095 | 2096 | mutex_lock(&mem->lock); |
| 2096 | 2097 | |
| 2098 | + ret = amdgpu_bo_reserve(mem->bo, true); | |
| 2099 | + if (ret) | |
| 2100 | + goto out; | |
| 2101 | + | |
| 2097 | 2102 | list_for_each_entry(entry, &mem->attachments, list) { |
| 2098 | − if (entry->bo_va->base.vm == vm) | |
| 2099 | − kfd_mem_dmaunmap_attachment(mem, entry); | |
| 2103 | + if (entry->bo_va->base.vm != vm) | |
| 2104 | + continue; | |
| 2105 | + if (entry->bo_va->base.bo->tbo.ttm && | |
| 2106 | + !entry->bo_va->base.bo->tbo.ttm->sg) | |
| 2107 | + continue; | |
| 2108 | + | |
| 2109 | + kfd_mem_dmaunmap_attachment(mem, entry); | |
| 2100 | 2110 | } |
| 2101 | 2111 | |
| 2112 | + amdgpu_bo_unreserve(mem->bo); | |
| 2113 | +out: | |
| 2102 | 2114 | mutex_unlock(&mem->lock); |
| 2115 | + | |
| 2116 | + return ret; | |
| 2103 | 2117 | } |
| 2104 | 2118 | |
| 2105 | 2119 | int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( |
| @@ -1678,7 +1678,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) · 1677 unmodified lines | ||
| 1678 | 1678 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
| 1679 | 1679 | struct amdgpu_ring *ring = adev->rings[i]; |
| 1680 | 1680 | |
| 1681 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 1681 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 1682 | 1682 | continue; |
| 1683 | 1683 | drm_sched_wqueue_stop(&ring->sched); |
| 1684 | 1684 | } |
| @@ -1694,7 +1694,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) · 9 unmodified lines | ||
| 1694 | 1694 | for (i = 0; i < AMDGPU_MAX_RINGS; i++) { |
| 1695 | 1695 | struct amdgpu_ring *ring = adev->rings[i]; |
| 1696 | 1696 | |
| 1697 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 1697 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 1698 | 1698 | continue; |
| 1699 | 1699 | drm_sched_wqueue_start(&ring->sched); |
| 1700 | 1700 | } |
| @@ -1916,8 +1916,8 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) · 215 unmodified lines | ||
| 1916 | 1916 | |
| 1917 | 1917 | ring = adev->rings[val]; |
| 1918 | 1918 | |
| 1919 | − if (!ring || !ring->funcs->preempt_ib || | |
| 1920 | − !drm_sched_wqueue_ready(&ring->sched)) | |
| 1919 | + if (!amdgpu_ring_sched_ready(ring) || | |
| 1920 | + !ring->funcs->preempt_ib) | |
| 1921 | 1921 | return -EINVAL; |
| 1922 | 1922 | |
| 1923 | 1923 | /* the last preemption failed */ |
| @@ -4121,23 +4121,13 @@ int amdgpu_device_init(struct amdgpu_device *adev, · 4120 unmodified lines | ||
| 4121 | 4121 | } |
| 4122 | 4122 | } |
| 4123 | 4123 | } else { |
| 4124 | − switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { | |
| 4125 | − case IP_VERSION(13, 0, 0): | |
| 4126 | − case IP_VERSION(13, 0, 7): | |
| 4127 | − case IP_VERSION(13, 0, 10): | |
| 4128 | − r = psp_gpu_reset(adev); | |
| 4129 | − break; | |
| 4130 | − default: | |
| 4131 | − tmp = amdgpu_reset_method; | |
| 4132 | − /* It should do a default reset when loading or reloading the driver, | |
| 4133 | − * regardless of the module parameter reset_method. | |
| 4134 | − */ | |
| 4135 | − amdgpu_reset_method = AMD_RESET_METHOD_NONE; | |
| 4136 | − r = amdgpu_asic_reset(adev); | |
| 4137 | − amdgpu_reset_method = tmp; | |
| 4138 | − break; | |
| 4139 | − } | |
| 4140 | − | |
| 4124 | + tmp = amdgpu_reset_method; | |
| 4125 | + /* It should do a default reset when loading or reloading the driver, | |
| 4126 | + * regardless of the module parameter reset_method. | |
| 4127 | + */ | |
| 4128 | + amdgpu_reset_method = AMD_RESET_METHOD_NONE; | |
| 4129 | + r = amdgpu_asic_reset(adev); | |
| 4130 | + amdgpu_reset_method = tmp; | |
| 4141 | 4131 | if (r) { |
| 4142 | 4132 | dev_err(adev->dev, "asic reset on init failed\n"); |
| 4143 | 4133 | goto failed; |
| @@ -5031,7 +5021,7 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev) · 887 unmodified lines | ||
| 5031 | 5021 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5032 | 5022 | struct amdgpu_ring *ring = adev->rings[i]; |
| 5033 | 5023 | |
| 5034 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5024 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5035 | 5025 | continue; |
| 5036 | 5026 | |
| 5037 | 5027 | spin_lock(&ring->sched.job_list_lock); |
| @@ -5170,7 +5160,7 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, · 132 unmodified lines | ||
| 5170 | 5160 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5171 | 5161 | struct amdgpu_ring *ring = adev->rings[i]; |
| 5172 | 5162 | |
| 5173 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5163 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5174 | 5164 | continue; |
| 5175 | 5165 | |
| 5176 | 5166 | /* Clear job fence from fence drv to avoid force_completion |
| @@ -5637,7 +5627,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 460 unmodified lines | ||
| 5637 | 5627 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5638 | 5628 | struct amdgpu_ring *ring = tmp_adev->rings[i]; |
| 5639 | 5629 | |
| 5640 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5630 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5641 | 5631 | continue; |
| 5642 | 5632 | |
| 5643 | 5633 | drm_sched_stop(&ring->sched, job ? &job->base : NULL); |
| @@ -5706,7 +5696,7 @@ skip_hw_reset: · 62 unmodified lines | ||
| 5706 | 5696 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 5707 | 5697 | struct amdgpu_ring *ring = tmp_adev->rings[i]; |
| 5708 | 5698 | |
| 5709 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 5699 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 5710 | 5700 | continue; |
| 5711 | 5701 | |
| 5712 | 5702 | drm_sched_start(&ring->sched, true); |
| @@ -6061,7 +6051,7 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta · 348 unmodified lines | ||
| 6061 | 6051 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 6062 | 6052 | struct amdgpu_ring *ring = adev->rings[i]; |
| 6063 | 6053 | |
| 6064 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 6054 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 6065 | 6055 | continue; |
| 6066 | 6056 | |
| 6067 | 6057 | drm_sched_stop(&ring->sched, NULL); |
| @@ -6189,7 +6179,7 @@ void amdgpu_pci_resume(struct pci_dev *pdev) · 121 unmodified lines | ||
| 6189 | 6179 | for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { |
| 6190 | 6180 | struct amdgpu_ring *ring = adev->rings[i]; |
| 6191 | 6181 | |
| 6192 | − if (!ring || !drm_sched_wqueue_ready(&ring->sched)) | |
| 6182 | + if (!amdgpu_ring_sched_ready(ring)) | |
| 6193 | 6183 | continue; |
| 6194 | 6184 | |
| 6195 | 6185 | drm_sched_start(&ring->sched, true); |
| @@ -2255,6 +2255,10 @@ retry_init: · 2254 unmodified lines | ||
| 2255 | 2255 | if (ret) |
| 2256 | 2256 | goto err_pci; |
| 2257 | 2257 | |
| 2258 | + ret = amdgpu_amdkfd_drm_client_create(adev); | |
| 2259 | + if (ret) | |
| 2260 | + goto err_pci; | |
| 2261 | + | |
| 2258 | 2262 | /* |
| 2259 | 2263 | * 1. don't init fbdev on hw without DCE |
| 2260 | 2264 | * 2. don't init fbdev if there are no connectors |
| @@ -2472,6 +2476,7 @@ static int amdgpu_pmops_suspend(struct device *dev) · 211 unmodified lines | ||
| 2472 | 2476 | struct drm_device *drm_dev = dev_get_drvdata(dev); |
| 2473 | 2477 | struct amdgpu_device *adev = drm_to_adev(drm_dev); |
| 2474 | 2478 | |
| 2479 | + adev->suspend_complete = false; | |
| 2475 | 2480 | if (amdgpu_acpi_is_s0ix_active(adev)) |
| 2476 | 2481 | adev->in_s0ix = true; |
| 2477 | 2482 | else if (amdgpu_acpi_is_s3_active(adev)) |
| @@ -2486,6 +2491,7 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev) · 8 unmodified lines | ||
| 2486 | 2491 | struct drm_device *drm_dev = dev_get_drvdata(dev); |
| 2487 | 2492 | struct amdgpu_device *adev = drm_to_adev(drm_dev); |
| 2488 | 2493 | |
| 2494 | + adev->suspend_complete = true; | |
| 2489 | 2495 | if (amdgpu_acpi_should_gpu_reset(adev)) |
| 2490 | 2496 | return amdgpu_asic_reset(adev); |
| 2491 | 2497 | |
| @@ -121,6 +121,7 @@ int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev) · 120 unmodified lines | ||
| 121 | 121 | struct amdgpu_bo_param bp; |
| 122 | 122 | dma_addr_t dma_addr; |
| 123 | 123 | struct page *p; |
| 124 | + unsigned long x; | |
| 124 | 125 | int ret; |
| 125 | 126 | |
| 126 | 127 | if (adev->gart.bo != NULL) |
| @@ -130,6 +131,10 @@ int amdgpu_gart_table_ram_alloc(struct amdgpu_device *adev) · 3 unmodified lines | ||
| 130 | 131 | if (!p) |
| 131 | 132 | return -ENOMEM; |
| 132 | 133 | |
| 134 | + /* assign pages to this device */ | |
| 135 | + for (x = 0; x < (1UL << order); x++) | |
| 136 | + p[x].mapping = adev->mman.bdev.dev_mapping; | |
| 137 | + | |
| 133 | 138 | /* If the hardware does not support UTCL2 snooping of the CPU caches |
| 134 | 139 | * then set_memory_wc() could be used as a workaround to mark the pages |
| 135 | 140 | * as write combine memory. |
| @@ -223,6 +228,7 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev) · 87 unmodified lines | ||
| 223 | 228 | unsigned int order = get_order(adev->gart.table_size); |
| 224 | 229 | struct sg_table *sg = adev->gart.bo->tbo.sg; |
| 225 | 230 | struct page *p; |
| 231 | + unsigned long x; | |
| 226 | 232 | int ret; |
| 227 | 233 | |
| 228 | 234 | ret = amdgpu_bo_reserve(adev->gart.bo, false); |
| @@ -234,6 +240,8 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev) · 5 unmodified lines | ||
| 234 | 240 | sg_free_table(sg); |
| 235 | 241 | kfree(sg); |
| 236 | 242 | p = virt_to_page(adev->gart.ptr); |
| 243 | + for (x = 0; x < (1UL << order); x++) | |
| 244 | + p[x].mapping = NULL; | |
| 237 | 245 | __free_pages(p, order); |
| 238 | 246 | |
| 239 | 247 | adev->gart.ptr = NULL; |
| @@ -362,7 +362,7 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size · 361 unmodified lines | ||
| 362 | 362 | } |
| 363 | 363 | } |
| 364 | 364 | |
| 365 | − if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len)) | |
| 365 | + if (copy_to_user((char *)&buf[copy_pos], context->mem_context.shared_buf, shared_buf_len)) | |
| 366 | 366 | ret = -EFAULT; |
| 367 | 367 | |
| 368 | 368 | err_free_shared_buf: |
| @@ -635,6 +635,7 @@ int amdgpu_ring_test_helper(struct amdgpu_ring *ring) · 634 unmodified lines | ||
| 635 | 635 | ring->name); |
| 636 | 636 | |
| 637 | 637 | ring->sched.ready = !r; |
| 638 | + | |
| 638 | 639 | return r; |
| 639 | 640 | } |
| 640 | 641 | |
| @@ -717,3 +718,14 @@ void amdgpu_ring_ib_on_emit_de(struct amdgpu_ring *ring) · 76 unmodified lines | ||
| 717 | 718 | if (ring->is_sw_ring) |
| 718 | 719 | amdgpu_sw_ring_ib_mark_offset(ring, AMDGPU_MUX_OFFSET_TYPE_DE); |
| 719 | 720 | } |
| 721 | + | |
| 722 | +bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring) | |
| 723 | +{ | |
| 724 | + if (!ring) | |
| 725 | + return false; | |
| 726 | + | |
| 727 | + if (ring->no_scheduler || !drm_sched_wqueue_ready(&ring->sched)) | |
| 728 | + return false; | |
| 729 | + | |
| 730 | + return true; | |
| 731 | +} | |
| @@ -450,5 +450,5 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, · 449 unmodified lines | ||
| 450 | 450 | int amdgpu_ib_pool_init(struct amdgpu_device *adev); |
| 451 | 451 | void amdgpu_ib_pool_fini(struct amdgpu_device *adev); |
| 452 | 452 | int amdgpu_ib_ring_tests(struct amdgpu_device *adev); |
| 453 | − | |
| 453 | +bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring); | |
| 454 | 454 | #endif |
| @@ -221,8 +221,23 @@ static struct attribute *amdgpu_vram_mgr_attributes[] = { · 220 unmodified lines | ||
| 221 | 221 | NULL |
| 222 | 222 | }; |
| 223 | 223 | |
| 224 | +static umode_t amdgpu_vram_attrs_is_visible(struct kobject *kobj, | |
| 225 | + struct attribute *attr, int i) | |
| 226 | +{ | |
| 227 | + struct device *dev = kobj_to_dev(kobj); | |
| 228 | + struct drm_device *ddev = dev_get_drvdata(dev); | |
| 229 | + struct amdgpu_device *adev = drm_to_adev(ddev); | |
| 230 | + | |
| 231 | + if (attr == &dev_attr_mem_info_vram_vendor.attr && | |
| 232 | + !adev->gmc.vram_vendor) | |
| 233 | + return 0; | |
| 234 | + | |
| 235 | + return attr->mode; | |
| 236 | +} | |
| 237 | + | |
| 224 | 238 | const struct attribute_group amdgpu_vram_mgr_attr_group = { |
| 225 | − .attrs = amdgpu_vram_mgr_attributes | |
| 239 | + .attrs = amdgpu_vram_mgr_attributes, | |
| 240 | + .is_visible = amdgpu_vram_attrs_is_visible | |
| 226 | 241 | }; |
| 227 | 242 | |
| 228 | 243 | /** |
| @@ -204,6 +204,12 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev, · 203 unmodified lines | ||
| 204 | 204 | tmp = RREG32(mmIH_RB_CNTL); |
| 205 | 205 | tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; |
| 206 | 206 | WREG32(mmIH_RB_CNTL, tmp); |
| 207 | + | |
| 208 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 209 | + * can be detected. | |
| 210 | + */ | |
| 211 | + tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; | |
| 212 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 207 | 213 | } |
| 208 | 214 | return (wptr & ih->ptr_mask); |
| 209 | 215 | } |
| @@ -216,6 +216,11 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev, · 215 unmodified lines | ||
| 216 | 216 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 217 | 217 | WREG32(mmIH_RB_CNTL, tmp); |
| 218 | 218 | |
| 219 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 220 | + * can be detected. | |
| 221 | + */ | |
| 222 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 223 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 219 | 224 | |
| 220 | 225 | out: |
| 221 | 226 | return (wptr & ih->ptr_mask); |
| @@ -4027,8 +4027,6 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) · 4026 unmodified lines | ||
| 4027 | 4027 | err = 0; |
| 4028 | 4028 | adev->gfx.mec2_fw = NULL; |
| 4029 | 4029 | } |
| 4030 | − amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2); | |
| 4031 | − amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT); | |
| 4032 | 4030 | |
| 4033 | 4031 | gfx_v10_0_check_fw_write_wait(adev); |
| 4034 | 4032 | out: |
| @@ -6589,7 +6587,7 @@ static int gfx_v10_0_compute_mqd_init(struct amdgpu_device *adev, void *m, · 2554 unmodified lines | ||
| 6589 | 6587 | #ifdef __BIG_ENDIAN |
| 6590 | 6588 | tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1); |
| 6591 | 6589 | #endif |
| 6592 | − tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); | |
| 6590 | + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); | |
| 6593 | 6591 | tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, |
| 6594 | 6592 | prop->allow_tunneling); |
| 6595 | 6593 | tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); |
| @@ -107,23 +107,6 @@ static const struct soc15_reg_golden golden_settings_gc_11_0_1[] = · 106 unmodified lines | ||
| 107 | 107 | SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL2, 0xfcffffff, 0x0000000a) |
| 108 | 108 | }; |
| 109 | 109 | |
| 110 | −static const struct soc15_reg_golden golden_settings_gc_11_5_0[] = { | |
| 111 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regDB_DEBUG5, 0xffffffff, 0x00000800), | |
| 112 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGB_ADDR_CONFIG, 0x0c1807ff, 0x00000242), | |
| 113 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGCR_GENERAL_CNTL, 0x1ff1ffff, 0x00000500), | |
| 114 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2A_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3), | |
| 115 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_ADDR_MATCH_MASK, 0xffffffff, 0xfffffff3), | |
| 116 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL, 0xffffffff, 0xf37fff3f), | |
| 117 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL3, 0xfffffffb, 0x00f40188), | |
| 118 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regGL2C_CTRL4, 0xf0ffffff, 0x80009007), | |
| 119 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regPA_CL_ENHANCE, 0xf1ffffff, 0x00880007), | |
| 120 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regPC_CONFIG_CNTL_1, 0xffffffff, 0x00010000), | |
| 121 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regTA_CNTL_AUX, 0xf7f7ffff, 0x01030000), | |
| 122 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regTA_CNTL2, 0x007f0000, 0x00000000), | |
| 123 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regTCP_CNTL2, 0xffcfffff, 0x0000200a), | |
| 124 | − SOC15_REG_GOLDEN_VALUE(GC, 0, regUTCL1_CTRL_2, 0xffffffff, 0x0000048f) | |
| 125 | −}; | |
| 126 | − | |
| 127 | 110 | #define DEFAULT_SH_MEM_CONFIG \ |
| 128 | 111 | ((SH_MEM_ADDRESS_MODE_64 << SH_MEM_CONFIG__ADDRESS_MODE__SHIFT) | \ |
| 129 | 112 | (SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) | \ |
| @@ -304,11 +287,6 @@ static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev) · 174 unmodified lines | ||
| 304 | 287 | golden_settings_gc_11_0_1, |
| 305 | 288 | (const u32)ARRAY_SIZE(golden_settings_gc_11_0_1)); |
| 306 | 289 | break; |
| 307 | − case IP_VERSION(11, 5, 0): | |
| 308 | − soc15_program_register_sequence(adev, | |
| 309 | − golden_settings_gc_11_5_0, | |
| 310 | − (const u32)ARRAY_SIZE(golden_settings_gc_11_5_0)); | |
| 311 | − break; | |
| 312 | 290 | default: |
| 313 | 291 | break; |
| 314 | 292 | } |
| @@ -3846,7 +3824,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, · 3531 unmodified lines | ||
| 3846 | 3824 | (order_base_2(prop->queue_size / 4) - 1)); |
| 3847 | 3825 | tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, |
| 3848 | 3826 | (order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)); |
| 3849 | − tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); | |
| 3827 | + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); | |
| 3850 | 3828 | tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, |
| 3851 | 3829 | prop->allow_tunneling); |
| 3852 | 3830 | tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); |
| @@ -3034,6 +3034,14 @@ static int gfx_v9_0_cp_gfx_start(struct amdgpu_device *adev) · 3033 unmodified lines | ||
| 3034 | 3034 | |
| 3035 | 3035 | gfx_v9_0_cp_gfx_enable(adev, true); |
| 3036 | 3036 | |
| 3037 | + /* Now only limit the quirk on the APU gfx9 series and already | |
| 3038 | + * confirmed that the APU gfx10/gfx11 needn't such update. | |
| 3039 | + */ | |
| 3040 | + if (adev->flags & AMD_IS_APU && | |
| 3041 | + adev->in_s3 && !adev->suspend_complete) { | |
| 3042 | + DRM_INFO(" Will skip the CSB packet resubmit\n"); | |
| 3043 | + return 0; | |
| 3044 | + } | |
| 3037 | 3045 | r = amdgpu_ring_alloc(ring, gfx_v9_0_get_csb_size(adev) + 4 + 3); |
| 3038 | 3046 | if (r) { |
| 3039 | 3047 | DRM_ERROR("amdgpu: cp failed to lock ring (%d).\n", r); |
| @@ -915,8 +915,8 @@ static int gmc_v6_0_hw_init(void *handle) · 914 unmodified lines | ||
| 915 | 915 | |
| 916 | 916 | if (amdgpu_emu_mode == 1) |
| 917 | 917 | return amdgpu_gmc_vram_checking(adev); |
| 918 | − else | |
| 919 | − return r; | |
| 918 | + | |
| 919 | + return 0; | |
| 920 | 920 | } |
| 921 | 921 | |
| 922 | 922 | static int gmc_v6_0_hw_fini(void *handle) |
| @@ -1099,8 +1099,8 @@ static int gmc_v7_0_hw_init(void *handle) · 1098 unmodified lines | ||
| 1099 | 1099 | |
| 1100 | 1100 | if (amdgpu_emu_mode == 1) |
| 1101 | 1101 | return amdgpu_gmc_vram_checking(adev); |
| 1102 | − else | |
| 1103 | − return r; | |
| 1102 | + | |
| 1103 | + return 0; | |
| 1104 | 1104 | } |
| 1105 | 1105 | |
| 1106 | 1106 | static int gmc_v7_0_hw_fini(void *handle) |
| @@ -1219,8 +1219,8 @@ static int gmc_v8_0_hw_init(void *handle) · 1218 unmodified lines | ||
| 1219 | 1219 | |
| 1220 | 1220 | if (amdgpu_emu_mode == 1) |
| 1221 | 1221 | return amdgpu_gmc_vram_checking(adev); |
| 1222 | − else | |
| 1223 | − return r; | |
| 1222 | + | |
| 1223 | + return 0; | |
| 1224 | 1224 | } |
| 1225 | 1225 | |
| 1226 | 1226 | static int gmc_v8_0_hw_fini(void *handle) |
| @@ -1947,13 +1947,6 @@ static int gmc_v9_0_init_mem_ranges(struct amdgpu_device *adev) · 1946 unmodified lines | ||
| 1947 | 1947 | |
| 1948 | 1948 | static void gmc_v9_4_3_init_vram_info(struct amdgpu_device *adev) |
| 1949 | 1949 | { |
| 1950 | − static const u32 regBIF_BIOS_SCRATCH_4 = 0x50; | |
| 1951 | − u32 vram_info; | |
| 1952 | − | |
| 1953 | − if (!amdgpu_sriov_vf(adev)) { | |
| 1954 | − vram_info = RREG32(regBIF_BIOS_SCRATCH_4); | |
| 1955 | − adev->gmc.vram_vendor = vram_info & 0xF; | |
| 1956 | − } | |
| 1957 | 1950 | adev->gmc.vram_type = AMDGPU_VRAM_TYPE_HBM; |
| 1958 | 1951 | adev->gmc.vram_width = 128 * 64; |
| 1959 | 1952 | } |
| @@ -2340,8 +2333,8 @@ static int gmc_v9_0_hw_init(void *handle) · 380 unmodified lines | ||
| 2340 | 2333 | |
| 2341 | 2334 | if (amdgpu_emu_mode == 1) |
| 2342 | 2335 | return amdgpu_gmc_vram_checking(adev); |
| 2343 | − else | |
| 2344 | − return r; | |
| 2336 | + | |
| 2337 | + return 0; | |
| 2345 | 2338 | } |
| 2346 | 2339 | |
| 2347 | 2340 | /** |
| @@ -215,6 +215,11 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev, · 214 unmodified lines | ||
| 215 | 215 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 216 | 216 | WREG32(mmIH_RB_CNTL, tmp); |
| 217 | 217 | |
| 218 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 219 | + * can be detected. | |
| 220 | + */ | |
| 221 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 222 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 218 | 223 | |
| 219 | 224 | out: |
| 220 | 225 | return (wptr & ih->ptr_mask); |
| @@ -418,6 +418,12 @@ static u32 ih_v6_0_get_wptr(struct amdgpu_device *adev, · 417 unmodified lines | ||
| 418 | 418 | tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl); |
| 419 | 419 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 420 | 420 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 421 | + | |
| 422 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 423 | + * can be detected. | |
| 424 | + */ | |
| 425 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 426 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 421 | 427 | out: |
| 422 | 428 | return (wptr & ih->ptr_mask); |
| 423 | 429 | } |
| @@ -418,6 +418,13 @@ static u32 ih_v6_1_get_wptr(struct amdgpu_device *adev, · 417 unmodified lines | ||
| 418 | 418 | tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl); |
| 419 | 419 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 420 | 420 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 421 | + | |
| 422 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 423 | + * can be detected. | |
| 424 | + */ | |
| 425 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 426 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 427 | + | |
| 421 | 428 | out: |
| 422 | 429 | return (wptr & ih->ptr_mask); |
| 423 | 430 | } |
| @@ -674,14 +674,6 @@ static int jpeg_v4_0_set_powergating_state(void *handle, · 673 unmodified lines | ||
| 674 | 674 | return ret; |
| 675 | 675 | } |
| 676 | 676 | |
| 677 | −static int jpeg_v4_0_set_interrupt_state(struct amdgpu_device *adev, | |
| 678 | − struct amdgpu_irq_src *source, | |
| 679 | − unsigned type, | |
| 680 | − enum amdgpu_interrupt_state state) | |
| 681 | −{ | |
| 682 | − return 0; | |
| 683 | −} | |
| 684 | − | |
| 685 | 677 | static int jpeg_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev, |
| 686 | 678 | struct amdgpu_irq_src *source, |
| 687 | 679 | unsigned int type, |
| @@ -765,7 +757,6 @@ static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev) · 77 unmodified lines | ||
| 765 | 757 | } |
| 766 | 758 | |
| 767 | 759 | static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = { |
| 768 | − .set = jpeg_v4_0_set_interrupt_state, | |
| 769 | 760 | .process = jpeg_v4_0_process_interrupt, |
| 770 | 761 | }; |
| 771 | 762 | |
| @@ -181,7 +181,6 @@ static int jpeg_v4_0_5_hw_fini(void *handle) · 180 unmodified lines | ||
| 181 | 181 | RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS)) |
| 182 | 182 | jpeg_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE); |
| 183 | 183 | } |
| 184 | − amdgpu_irq_put(adev, &adev->jpeg.inst->irq, 0); | |
| 185 | 184 | |
| 186 | 185 | return 0; |
| 187 | 186 | } |
| @@ -516,14 +515,6 @@ static int jpeg_v4_0_5_set_powergating_state(void *handle, · 328 unmodified lines | ||
| 516 | 515 | return ret; |
| 517 | 516 | } |
| 518 | 517 | |
| 519 | −static int jpeg_v4_0_5_set_interrupt_state(struct amdgpu_device *adev, | |
| 520 | − struct amdgpu_irq_src *source, | |
| 521 | − unsigned type, | |
| 522 | − enum amdgpu_interrupt_state state) | |
| 523 | −{ | |
| 524 | − return 0; | |
| 525 | −} | |
| 526 | − | |
| 527 | 518 | static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev, |
| 528 | 519 | struct amdgpu_irq_src *source, |
| 529 | 520 | struct amdgpu_iv_entry *entry) |
| @@ -603,7 +594,6 @@ static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev) · 73 unmodified lines | ||
| 603 | 594 | } |
| 604 | 595 | |
| 605 | 596 | static const struct amdgpu_irq_src_funcs jpeg_v4_0_5_irq_funcs = { |
| 606 | − .set = jpeg_v4_0_5_set_interrupt_state, | |
| 607 | 597 | .process = jpeg_v4_0_5_process_interrupt, |
| 608 | 598 | }; |
| 609 | 599 | |
| @@ -442,6 +442,12 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev, · 441 unmodified lines | ||
| 442 | 442 | tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl); |
| 443 | 443 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 444 | 444 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 445 | + | |
| 446 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 447 | + * can be detected. | |
| 448 | + */ | |
| 449 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 450 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 445 | 451 | out: |
| 446 | 452 | return (wptr & ih->ptr_mask); |
| 447 | 453 | } |
| @@ -431,6 +431,12 @@ static void nbio_v7_9_init_registers(struct amdgpu_device *adev) · 430 unmodified lines | ||
| 431 | 431 | u32 inst_mask; |
| 432 | 432 | int i; |
| 433 | 433 | |
| 434 | + if (amdgpu_sriov_vf(adev)) | |
| 435 | + adev->rmmio_remap.reg_offset = | |
| 436 | + SOC15_REG_OFFSET( | |
| 437 | + NBIO, 0, | |
| 438 | + regBIF_BX_DEV0_EPF0_VF0_HDP_MEM_COHERENCY_FLUSH_CNTL) | |
| 439 | + << 2; | |
| 434 | 440 | WREG32_SOC15(NBIO, 0, regXCC_DOORBELL_FENCE, |
| 435 | 441 | 0xff & ~(adev->gfx.xcc_mask)); |
| 436 | 442 | |
| @@ -119,6 +119,12 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev, · 118 unmodified lines | ||
| 119 | 119 | tmp = RREG32(IH_RB_CNTL); |
| 120 | 120 | tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; |
| 121 | 121 | WREG32(IH_RB_CNTL, tmp); |
| 122 | + | |
| 123 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 124 | + * can be detected. | |
| 125 | + */ | |
| 126 | + tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; | |
| 127 | + WREG32(IH_RB_CNTL, tmp); | |
| 122 | 128 | } |
| 123 | 129 | return (wptr & ih->ptr_mask); |
| 124 | 130 | } |
| @@ -1298,10 +1298,32 @@ static int soc15_common_suspend(void *handle) · 1297 unmodified lines | ||
| 1298 | 1298 | return soc15_common_hw_fini(adev); |
| 1299 | 1299 | } |
| 1300 | 1300 | |
| 1301 | +static bool soc15_need_reset_on_resume(struct amdgpu_device *adev) | |
| 1302 | +{ | |
| 1303 | + u32 sol_reg; | |
| 1304 | + | |
| 1305 | + sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); | |
| 1306 | + | |
| 1307 | + /* Will reset for the following suspend abort cases. | |
| 1308 | + * 1) Only reset limit on APU side, dGPU hasn't checked yet. | |
| 1309 | + * 2) S3 suspend abort and TOS already launched. | |
| 1310 | + */ | |
| 1311 | + if (adev->flags & AMD_IS_APU && adev->in_s3 && | |
| 1312 | + !adev->suspend_complete && | |
| 1313 | + sol_reg) | |
| 1314 | + return true; | |
| 1315 | + | |
| 1316 | + return false; | |
| 1317 | +} | |
| 1318 | + | |
| 1301 | 1319 | static int soc15_common_resume(void *handle) |
| 1302 | 1320 | { |
| 1303 | 1321 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1304 | 1322 | |
| 1323 | + if (soc15_need_reset_on_resume(adev)) { | |
| 1324 | + dev_info(adev->dev, "S3 suspend abort case, let's reset ASIC.\n"); | |
| 1325 | + soc15_asic_reset(adev); | |
| 1326 | + } | |
| 1305 | 1327 | return soc15_common_hw_init(adev); |
| 1306 | 1328 | } |
| 1307 | 1329 | |
| @@ -219,6 +219,12 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev, · 218 unmodified lines | ||
| 219 | 219 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 220 | 220 | WREG32(mmIH_RB_CNTL, tmp); |
| 221 | 221 | |
| 222 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 223 | + * can be detected. | |
| 224 | + */ | |
| 225 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 226 | + WREG32(mmIH_RB_CNTL, tmp); | |
| 227 | + | |
| 222 | 228 | out: |
| 223 | 229 | return (wptr & ih->ptr_mask); |
| 224 | 230 | } |
| @@ -2017,22 +2017,6 @@ static int vcn_v4_0_set_powergating_state(void *handle, enum amd_powergating_sta · 2016 unmodified lines | ||
| 2017 | 2017 | return ret; |
| 2018 | 2018 | } |
| 2019 | 2019 | |
| 2020 | −/** | |
| 2021 | − * vcn_v4_0_set_interrupt_state - set VCN block interrupt state | |
| 2022 | − * | |
| 2023 | − * @adev: amdgpu_device pointer | |
| 2024 | − * @source: interrupt sources | |
| 2025 | − * @type: interrupt types | |
| 2026 | − * @state: interrupt states | |
| 2027 | − * | |
| 2028 | − * Set VCN block interrupt state | |
| 2029 | − */ | |
| 2030 | −static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, | |
| 2031 | − unsigned type, enum amdgpu_interrupt_state state) | |
| 2032 | −{ | |
| 2033 | − return 0; | |
| 2034 | −} | |
| 2035 | − | |
| 2036 | 2020 | /** |
| 2037 | 2021 | * vcn_v4_0_set_ras_interrupt_state - set VCN block RAS interrupt state |
| 2038 | 2022 | * |
| @@ -2097,7 +2081,6 @@ static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_ · 58 unmodified lines | ||
| 2097 | 2081 | } |
| 2098 | 2082 | |
| 2099 | 2083 | static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = { |
| 2100 | − .set = vcn_v4_0_set_interrupt_state, | |
| 2101 | 2084 | .process = vcn_v4_0_process_interrupt, |
| 2102 | 2085 | }; |
| 2103 | 2086 | |
| @@ -269,8 +269,6 @@ static int vcn_v4_0_5_hw_fini(void *handle) · 268 unmodified lines | ||
| 269 | 269 | vcn_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE); |
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | − | |
| 273 | − amdgpu_irq_put(adev, &adev->vcn.inst[i].irq, 0); | |
| 274 | 272 | } |
| 275 | 273 | |
| 276 | 274 | return 0; |
| @@ -1668,22 +1666,6 @@ static int vcn_v4_0_5_set_powergating_state(void *handle, enum amd_powergating_s · 1391 unmodified lines | ||
| 1668 | 1666 | return ret; |
| 1669 | 1667 | } |
| 1670 | 1668 | |
| 1671 | −/** | |
| 1672 | − * vcn_v4_0_5_set_interrupt_state - set VCN block interrupt state | |
| 1673 | − * | |
| 1674 | − * @adev: amdgpu_device pointer | |
| 1675 | − * @source: interrupt sources | |
| 1676 | − * @type: interrupt types | |
| 1677 | − * @state: interrupt states | |
| 1678 | − * | |
| 1679 | − * Set VCN block interrupt state | |
| 1680 | − */ | |
| 1681 | −static int vcn_v4_0_5_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source, | |
| 1682 | − unsigned type, enum amdgpu_interrupt_state state) | |
| 1683 | −{ | |
| 1684 | − return 0; | |
| 1685 | −} | |
| 1686 | − | |
| 1687 | 1669 | /** |
| 1688 | 1670 | * vcn_v4_0_5_process_interrupt - process VCN block interrupt |
| 1689 | 1671 | * |
| @@ -1726,7 +1708,6 @@ static int vcn_v4_0_5_process_interrupt(struct amdgpu_device *adev, struct amdgp · 36 unmodified lines | ||
| 1726 | 1708 | } |
| 1727 | 1709 | |
| 1728 | 1710 | static const struct amdgpu_irq_src_funcs vcn_v4_0_5_irq_funcs = { |
| 1729 | − .set = vcn_v4_0_5_set_interrupt_state, | |
| 1730 | 1711 | .process = vcn_v4_0_5_process_interrupt, |
| 1731 | 1712 | }; |
| 1732 | 1713 | |
| @@ -373,6 +373,12 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, · 372 unmodified lines | ||
| 373 | 373 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 374 | 374 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 375 | 375 | |
| 376 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 377 | + * can be detected. | |
| 378 | + */ | |
| 379 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 380 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 381 | + | |
| 376 | 382 | out: |
| 377 | 383 | return (wptr & ih->ptr_mask); |
| 378 | 384 | } |
| @@ -421,6 +421,12 @@ static u32 vega20_ih_get_wptr(struct amdgpu_device *adev, · 420 unmodified lines | ||
| 421 | 421 | tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1); |
| 422 | 422 | WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); |
| 423 | 423 | |
| 424 | + /* Unset the CLEAR_OVERFLOW bit immediately so new overflows | |
| 425 | + * can be detected. | |
| 426 | + */ | |
| 427 | + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0); | |
| 428 | + WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp); | |
| 429 | + | |
| 424 | 430 | out: |
| 425 | 431 | return (wptr & ih->ptr_mask); |
| 426 | 432 | } |
| @@ -674,7 +674,7 @@ static const uint32_t cwsr_trap_gfx9_hex[] = { · 673 unmodified lines | ||
| 674 | 674 | 0x86ea6a6a, 0x8f6e837a, |
| 675 | 675 | 0xb96ee0c2, 0xbf800002, |
| 676 | 676 | 0xb97a0002, 0xbf8a0000, |
| 677 | − 0xbe801f6c, 0xbf810000, | |
| 677 | + 0xbe801f6c, 0xbf9b0000, | |
| 678 | 678 | }; |
| 679 | 679 | |
| 680 | 680 | static const uint32_t cwsr_trap_nv1x_hex[] = { |
| @@ -1091,7 +1091,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { · 410 unmodified lines | ||
| 1091 | 1091 | 0xb9eef807, 0x876dff6d, |
| 1092 | 1092 | 0x0000ffff, 0x87fe7e7e, |
| 1093 | 1093 | 0x87ea6a6a, 0xb9faf802, |
| 1094 | − 0xbe80226c, 0xbf810000, | |
| 1094 | + 0xbe80226c, 0xbf9b0000, | |
| 1095 | 1095 | 0xbf9f0000, 0xbf9f0000, |
| 1096 | 1096 | 0xbf9f0000, 0xbf9f0000, |
| 1097 | 1097 | 0xbf9f0000, 0x00000000, |
| @@ -1574,7 +1574,7 @@ static const uint32_t cwsr_trap_arcturus_hex[] = { · 476 unmodified lines | ||
| 1574 | 1574 | 0x86ea6a6a, 0x8f6e837a, |
| 1575 | 1575 | 0xb96ee0c2, 0xbf800002, |
| 1576 | 1576 | 0xb97a0002, 0xbf8a0000, |
| 1577 | − 0xbe801f6c, 0xbf810000, | |
| 1577 | + 0xbe801f6c, 0xbf9b0000, | |
| 1578 | 1578 | }; |
| 1579 | 1579 | |
| 1580 | 1580 | static const uint32_t cwsr_trap_aldebaran_hex[] = { |
| @@ -2065,7 +2065,7 @@ static const uint32_t cwsr_trap_aldebaran_hex[] = { · 484 unmodified lines | ||
| 2065 | 2065 | 0x86ea6a6a, 0x8f6e837a, |
| 2066 | 2066 | 0xb96ee0c2, 0xbf800002, |
| 2067 | 2067 | 0xb97a0002, 0xbf8a0000, |
| 2068 | − 0xbe801f6c, 0xbf810000, | |
| 2068 | + 0xbe801f6c, 0xbf9b0000, | |
| 2069 | 2069 | }; |
| 2070 | 2070 | |
| 2071 | 2071 | static const uint32_t cwsr_trap_gfx10_hex[] = { |
| @@ -2500,7 +2500,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { · 428 unmodified lines | ||
| 2500 | 2500 | 0x876dff6d, 0x0000ffff, |
| 2501 | 2501 | 0x87fe7e7e, 0x87ea6a6a, |
| 2502 | 2502 | 0xb9faf802, 0xbe80226c, |
| 2503 | − 0xbf810000, 0xbf9f0000, | |
| 2503 | + 0xbf9b0000, 0xbf9f0000, | |
| 2504 | 2504 | 0xbf9f0000, 0xbf9f0000, |
| 2505 | 2505 | 0xbf9f0000, 0xbf9f0000, |
| 2506 | 2506 | }; |
| @@ -2944,7 +2944,7 @@ static const uint32_t cwsr_trap_gfx11_hex[] = { · 437 unmodified lines | ||
| 2944 | 2944 | 0xb8eef802, 0xbf0d866e, |
| 2945 | 2945 | 0xbfa20002, 0xb97af802, |
| 2946 | 2946 | 0xbe80486c, 0xb97af802, |
| 2947 | − 0xbe804a6c, 0xbfb00000, | |
| 2947 | + 0xbe804a6c, 0xbfb10000, | |
| 2948 | 2948 | 0xbf9f0000, 0xbf9f0000, |
| 2949 | 2949 | 0xbf9f0000, 0xbf9f0000, |
| 2950 | 2950 | 0xbf9f0000, 0x00000000, |
| @@ -3436,5 +3436,5 @@ static const uint32_t cwsr_trap_gfx9_4_3_hex[] = { · 485 unmodified lines | ||
| 3436 | 3436 | 0x86ea6a6a, 0x8f6e837a, |
| 3437 | 3437 | 0xb96ee0c2, 0xbf800002, |
| 3438 | 3438 | 0xb97a0002, 0xbf8a0000, |
| 3439 | − 0xbe801f6c, 0xbf810000, | |
| 3439 | + 0xbe801f6c, 0xbf9b0000, | |
| 3440 | 3440 | }; |
| @@ -1104,7 +1104,7 @@ L_RETURN_WITHOUT_PRIV: · 1103 unmodified lines | ||
| 1104 | 1104 | s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution |
| 1105 | 1105 | |
| 1106 | 1106 | L_END_PGM: |
| 1107 | − s_endpgm | |
| 1107 | + s_endpgm_saved | |
| 1108 | 1108 | end |
| 1109 | 1109 | |
| 1110 | 1110 | function write_hwreg_to_mem(s, s_rsrc, s_mem_offset) |
| @@ -921,7 +921,7 @@ L_RESTORE: · 920 unmodified lines | ||
| 921 | 921 | /* the END */ |
| 922 | 922 | /**************************************************************************/ |
| 923 | 923 | L_END_PGM: |
| 924 | − s_endpgm | |
| 924 | + s_endpgm_saved | |
| 925 | 925 | |
| 926 | 926 | end |
| 927 | 927 | |
| @@ -1442,7 +1442,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, · 1441 unmodified lines | ||
| 1442 | 1442 | kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); |
| 1443 | 1443 | |
| 1444 | 1444 | /* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */ |
| 1445 | − amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv); | |
| 1445 | + err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv); | |
| 1446 | + if (err) | |
| 1447 | + goto sync_memory_failed; | |
| 1446 | 1448 | } |
| 1447 | 1449 | |
| 1448 | 1450 | mutex_unlock(&p->mutex); |
| @@ -574,7 +574,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, · 573 unmodified lines | ||
| 574 | 574 | pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start, |
| 575 | 575 | prange->last); |
| 576 | 576 | |
| 577 | − addr = prange->start << PAGE_SHIFT; | |
| 577 | + addr = migrate->start; | |
| 578 | 578 | |
| 579 | 579 | src = (uint64_t *)(scratch + npages); |
| 580 | 580 | dst = scratch; |
| @@ -170,6 +170,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, · 169 unmodified lines | ||
| 170 | 170 | m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; |
| 171 | 171 | m->cp_hqd_pq_control |= |
| 172 | 172 | ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; |
| 173 | + m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; | |
| 173 | 174 | pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); |
| 174 | 175 | |
| 175 | 176 | m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); |
| @@ -224,6 +224,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, · 223 unmodified lines | ||
| 224 | 224 | m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; |
| 225 | 225 | m->cp_hqd_pq_control |= |
| 226 | 226 | ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; |
| 227 | + m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; | |
| 227 | 228 | pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); |
| 228 | 229 | |
| 229 | 230 | m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); |
| @@ -1488,10 +1488,15 @@ void kfd_dec_compute_active(struct kfd_node *dev); · 1487 unmodified lines | ||
| 1488 | 1488 | |
| 1489 | 1489 | /* Cgroup Support */ |
| 1490 | 1490 | /* Check with device cgroup if @kfd device is accessible */ |
| 1491 | −static inline int kfd_devcgroup_check_permission(struct kfd_node *kfd) | |
| 1491 | +static inline int kfd_devcgroup_check_permission(struct kfd_node *node) | |
| 1492 | 1492 | { |
| 1493 | 1493 | #if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF) |
| 1494 | − struct drm_device *ddev = adev_to_drm(kfd->adev); | |
| 1494 | + struct drm_device *ddev; | |
| 1495 | + | |
| 1496 | + if (node->xcp) | |
| 1497 | + ddev = node->xcp->ddev; | |
| 1498 | + else | |
| 1499 | + ddev = adev_to_drm(node->adev); | |
| 1495 | 1500 | |
| 1496 | 1501 | return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR, |
| 1497 | 1502 | ddev->render->index, |
| @@ -272,6 +272,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, · 271 unmodified lines | ||
| 272 | 272 | { |
| 273 | 273 | u32 v_blank_start, v_blank_end, h_position, v_position; |
| 274 | 274 | struct amdgpu_crtc *acrtc = NULL; |
| 275 | + struct dc *dc = adev->dm.dc; | |
| 275 | 276 | |
| 276 | 277 | if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc)) |
| 277 | 278 | return -EINVAL; |
| @@ -284,6 +285,9 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, · 6 unmodified lines | ||
| 284 | 285 | return 0; |
| 285 | 286 | } |
| 286 | 287 | |
| 288 | + if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed) | |
| 289 | + dc_allow_idle_optimizations(dc, false); | |
| 290 | + | |
| 287 | 291 | /* |
| 288 | 292 | * TODO rework base driver to use values directly. |
| 289 | 293 | * for now parse it back into reg-format |
| @@ -1715,7 +1719,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) · 1425 unmodified lines | ||
| 1715 | 1719 | init_data.nbio_reg_offsets = adev->reg_offset[NBIO_HWIP][0]; |
| 1716 | 1720 | init_data.clk_reg_offsets = adev->reg_offset[CLK_HWIP][0]; |
| 1717 | 1721 | |
| 1718 | − init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL; | |
| 1722 | + if (amdgpu_dc_debug_mask & DC_DISABLE_IPS) | |
| 1723 | + init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL; | |
| 1724 | + | |
| 1725 | + init_data.flags.disable_ips_in_vpb = 1; | |
| 1719 | 1726 | |
| 1720 | 1727 | /* Enable DWB for tested platforms only */ |
| 1721 | 1728 | if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) |
| @@ -8976,16 +8983,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 7254 unmodified lines | ||
| 8976 | 8983 | |
| 8977 | 8984 | trace_amdgpu_dm_atomic_commit_tail_begin(state); |
| 8978 | 8985 | |
| 8979 | − if (dm->dc->caps.ips_support) { | |
| 8980 | − for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { | |
| 8981 | − if (new_con_state->crtc && | |
| 8982 | − new_con_state->crtc->state->active && | |
| 8983 | − drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) { | |
| 8984 | − dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false); | |
| 8985 | − break; | |
| 8986 | − } | |
| 8987 | − } | |
| 8988 | − } | |
| 8986 | + if (dm->dc->caps.ips_support && dm->dc->idle_optimizations_allowed) | |
| 8987 | + dc_allow_idle_optimizations(dm->dc, false); | |
| 8989 | 8988 | |
| 8990 | 8989 | drm_atomic_helper_update_legacy_modeset_state(dev, state); |
| 8991 | 8990 | drm_dp_mst_atomic_wait_for_dependencies(state); |
| @@ -9188,6 +9187,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) · 196 unmodified lines | ||
| 9188 | 9187 | * To fix this, DC should permit updating only stream properties. |
| 9189 | 9188 | */ |
| 9190 | 9189 | dummy_updates = kzalloc(sizeof(struct dc_surface_update) * MAX_SURFACES, GFP_ATOMIC); |
| 9190 | + if (!dummy_updates) { | |
| 9191 | + DRM_ERROR("Failed to allocate memory for dummy_updates.\n"); | |
| 9192 | + continue; | |
| 9193 | + } | |
| 9191 | 9194 | for (j = 0; j < status->plane_count; j++) |
| 9192 | 9195 | dummy_updates[j].surface = status->plane_states[0]; |
| 9193 | 9196 | |
| @@ -10728,11 +10731,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, · 1534 unmodified lines | ||
| 10728 | 10731 | goto fail; |
| 10729 | 10732 | } |
| 10730 | 10733 | |
| 10731 | − ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars); | |
| 10732 | − if (ret) { | |
| 10733 | − DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n"); | |
| 10734 | − ret = -EINVAL; | |
| 10735 | − goto fail; | |
| 10734 | + if (dc_resource_is_dsc_encoding_supported(dc)) { | |
| 10735 | + ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars); | |
| 10736 | + if (ret) { | |
| 10737 | + DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n"); | |
| 10738 | + ret = -EINVAL; | |
| 10739 | + goto fail; | |
| 10740 | + } | |
| 10736 | 10741 | } |
| 10737 | 10742 | |
| 10738 | 10743 | ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars); |
| @@ -711,7 +711,7 @@ static inline int dm_irq_state(struct amdgpu_device *adev, · 710 unmodified lines | ||
| 711 | 711 | { |
| 712 | 712 | bool st; |
| 713 | 713 | enum dc_irq_source irq_source; |
| 714 | − | |
| 714 | + struct dc *dc = adev->dm.dc; | |
| 715 | 715 | struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id]; |
| 716 | 716 | |
| 717 | 717 | if (!acrtc) { |
| @@ -729,6 +729,9 @@ static inline int dm_irq_state(struct amdgpu_device *adev, · 11 unmodified lines | ||
| 729 | 729 | |
| 730 | 730 | st = (state == AMDGPU_IRQ_STATE_ENABLE); |
| 731 | 731 | |
| 732 | + if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed) | |
| 733 | + dc_allow_idle_optimizations(dc, false); | |
| 734 | + | |
| 732 | 735 | dc_interrupt_set(adev->dm.dc, irq_source, st); |
| 733 | 736 | return 0; |
| 734 | 737 | } |
| @@ -437,32 +437,32 @@ static struct wm_table ddr5_wm_table = { · 436 unmodified lines | ||
| 437 | 437 | .wm_inst = WM_A, |
| 438 | 438 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 439 | 439 | .pstate_latency_us = 11.72, |
| 440 | − .sr_exit_time_us = 14.0, | |
| 441 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 440 | + .sr_exit_time_us = 28.0, | |
| 441 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 442 | 442 | .valid = true, |
| 443 | 443 | }, |
| 444 | 444 | { |
| 445 | 445 | .wm_inst = WM_B, |
| 446 | 446 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 447 | 447 | .pstate_latency_us = 11.72, |
| 448 | − .sr_exit_time_us = 14.0, | |
| 449 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 448 | + .sr_exit_time_us = 28.0, | |
| 449 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 450 | 450 | .valid = true, |
| 451 | 451 | }, |
| 452 | 452 | { |
| 453 | 453 | .wm_inst = WM_C, |
| 454 | 454 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 455 | 455 | .pstate_latency_us = 11.72, |
| 456 | − .sr_exit_time_us = 14.0, | |
| 457 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 456 | + .sr_exit_time_us = 28.0, | |
| 457 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 458 | 458 | .valid = true, |
| 459 | 459 | }, |
| 460 | 460 | { |
| 461 | 461 | .wm_inst = WM_D, |
| 462 | 462 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 463 | 463 | .pstate_latency_us = 11.72, |
| 464 | − .sr_exit_time_us = 14.0, | |
| 465 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 464 | + .sr_exit_time_us = 28.0, | |
| 465 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 466 | 466 | .valid = true, |
| 467 | 467 | }, |
| 468 | 468 | } |
| @@ -474,32 +474,32 @@ static struct wm_table lpddr5_wm_table = { · 5 unmodified lines | ||
| 474 | 474 | .wm_inst = WM_A, |
| 475 | 475 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 476 | 476 | .pstate_latency_us = 11.65333, |
| 477 | − .sr_exit_time_us = 14.0, | |
| 478 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 477 | + .sr_exit_time_us = 28.0, | |
| 478 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 479 | 479 | .valid = true, |
| 480 | 480 | }, |
| 481 | 481 | { |
| 482 | 482 | .wm_inst = WM_B, |
| 483 | 483 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 484 | 484 | .pstate_latency_us = 11.65333, |
| 485 | − .sr_exit_time_us = 14.0, | |
| 486 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 485 | + .sr_exit_time_us = 28.0, | |
| 486 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 487 | 487 | .valid = true, |
| 488 | 488 | }, |
| 489 | 489 | { |
| 490 | 490 | .wm_inst = WM_C, |
| 491 | 491 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 492 | 492 | .pstate_latency_us = 11.65333, |
| 493 | − .sr_exit_time_us = 14.0, | |
| 494 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 493 | + .sr_exit_time_us = 28.0, | |
| 494 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 495 | 495 | .valid = true, |
| 496 | 496 | }, |
| 497 | 497 | { |
| 498 | 498 | .wm_inst = WM_D, |
| 499 | 499 | .wm_type = WM_TYPE_PSTATE_CHG, |
| 500 | 500 | .pstate_latency_us = 11.65333, |
| 501 | − .sr_exit_time_us = 14.0, | |
| 502 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 501 | + .sr_exit_time_us = 28.0, | |
| 502 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 503 | 503 | .valid = true, |
| 504 | 504 | }, |
| 505 | 505 | } |
| @@ -3817,7 +3817,9 @@ static void commit_planes_for_stream(struct dc *dc, · 3816 unmodified lines | ||
| 3817 | 3817 | * programming has completed (we turn on phantom OTG in order |
| 3818 | 3818 | * to complete the plane disable for phantom pipes). |
| 3819 | 3819 | */ |
| 3820 | − dc->hwss.apply_ctx_to_hw(dc, context); | |
| 3820 | + | |
| 3821 | + if (dc->hwss.disable_phantom_streams) | |
| 3822 | + dc->hwss.disable_phantom_streams(dc, context); | |
| 3821 | 3823 | } |
| 3822 | 3824 | |
| 3823 | 3825 | if (update_type != UPDATE_TYPE_FAST) |
| @@ -291,11 +291,14 @@ void dc_state_destruct(struct dc_state *state) · 290 unmodified lines | ||
| 291 | 291 | dc_stream_release(state->phantom_streams[i]); |
| 292 | 292 | state->phantom_streams[i] = NULL; |
| 293 | 293 | } |
| 294 | + state->phantom_stream_count = 0; | |
| 294 | 295 | |
| 295 | 296 | for (i = 0; i < state->phantom_plane_count; i++) { |
| 296 | 297 | dc_plane_state_release(state->phantom_planes[i]); |
| 297 | 298 | state->phantom_planes[i] = NULL; |
| 298 | 299 | } |
| 300 | + state->phantom_plane_count = 0; | |
| 301 | + | |
| 299 | 302 | state->stream_mask = 0; |
| 300 | 303 | memset(&state->res_ctx, 0, sizeof(state->res_ctx)); |
| 301 | 304 | memset(&state->pp_display_cfg, 0, sizeof(state->pp_display_cfg)); |
| @@ -434,6 +434,7 @@ struct dc_config { · 433 unmodified lines | ||
| 434 | 434 | bool EnableMinDispClkODM; |
| 435 | 435 | bool enable_auto_dpm_test_logs; |
| 436 | 436 | unsigned int disable_ips; |
| 437 | + unsigned int disable_ips_in_vpb; | |
| 437 | 438 | }; |
| 438 | 439 | |
| 439 | 440 | enum visual_confirm { |
| @@ -1034,6 +1034,7 @@ enum replay_FW_Message_type { · 1033 unmodified lines | ||
| 1034 | 1034 | Replay_Msg_Not_Support = -1, |
| 1035 | 1035 | Replay_Set_Timing_Sync_Supported, |
| 1036 | 1036 | Replay_Set_Residency_Frameupdate_Timer, |
| 1037 | + Replay_Set_Pseudo_VTotal, | |
| 1037 | 1038 | }; |
| 1038 | 1039 | |
| 1039 | 1040 | union replay_error_status { |
| @@ -1089,6 +1090,10 @@ struct replay_settings { · 49 unmodified lines | ||
| 1089 | 1090 | uint16_t coasting_vtotal_table[PR_COASTING_TYPE_NUM]; |
| 1090 | 1091 | /* Maximum link off frame count */ |
| 1091 | 1092 | enum replay_link_off_frame_count_level link_off_frame_count_level; |
| 1093 | + /* Replay pseudo vtotal for abm + ips on full screen video which can improve ips residency */ | |
| 1094 | + uint16_t abm_with_ips_on_full_screen_video_pseudo_vtotal; | |
| 1095 | + /* Replay last pseudo vtotal set to DMUB */ | |
| 1096 | + uint16_t last_pseudo_vtotal; | |
| 1092 | 1097 | }; |
| 1093 | 1098 | |
| 1094 | 1099 | /* To split out "global" and "per-panel" config settings. |
| @@ -203,12 +203,12 @@ void dcn32_link_encoder_construct( · 202 unmodified lines | ||
| 203 | 203 | enc10->base.hpd_source = init_data->hpd_source; |
| 204 | 204 | enc10->base.connector = init_data->connector; |
| 205 | 205 | |
| 206 | − if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 207 | − enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 208 | 206 | |
| 209 | 207 | enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; |
| 210 | 208 | |
| 211 | 209 | enc10->base.features = *enc_features; |
| 210 | + if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 211 | + enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 212 | 212 | |
| 213 | 213 | enc10->base.transmitter = init_data->transmitter; |
| 214 | 214 | |
| @@ -184,8 +184,6 @@ void dcn35_link_encoder_construct( · 183 unmodified lines | ||
| 184 | 184 | enc10->base.hpd_source = init_data->hpd_source; |
| 185 | 185 | enc10->base.connector = init_data->connector; |
| 186 | 186 | |
| 187 | − if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 188 | − enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 189 | 187 | |
| 190 | 188 | enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; |
| 191 | 189 | |
| @@ -240,6 +238,8 @@ void dcn35_link_encoder_construct( · 48 unmodified lines | ||
| 240 | 238 | } |
| 241 | 239 | |
| 242 | 240 | enc10->base.features.flags.bits.HDMI_6GB_EN = 1; |
| 241 | + if (enc10->base.connector.id == CONNECTOR_ID_USBC) | |
| 242 | + enc10->base.features.flags.bits.DP_IS_USB_C = 1; | |
| 243 | 243 | |
| 244 | 244 | if (bp_funcs->get_connector_speed_cap_info) |
| 245 | 245 | result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, |
| @@ -72,11 +72,11 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) · 71 unmodified lines | ||
| 72 | 72 | CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags) |
| 73 | 73 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_ccflags) |
| 74 | 74 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags) |
| 75 | −CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) | |
| 75 | +CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) $(frame_warn_flag) | |
| 76 | 76 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags) |
| 77 | −CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) | |
| 77 | +CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) $(frame_warn_flag) | |
| 78 | 78 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags) |
| 79 | −CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) | |
| 79 | +CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) $(frame_warn_flag) | |
| 80 | 80 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags) |
| 81 | 81 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(frame_warn_flag) |
| 82 | 82 | CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) |
| @@ -1112,7 +1112,7 @@ struct pipe_slice_table { · 1111 unmodified lines | ||
| 1112 | 1112 | struct pipe_ctx *pri_pipe; |
| 1113 | 1113 | struct dc_plane_state *plane; |
| 1114 | 1114 | int slice_count; |
| 1115 | − } mpc_combines[MAX_SURFACES]; | |
| 1115 | + } mpc_combines[MAX_PLANES]; | |
| 1116 | 1116 | int mpc_combine_count; |
| 1117 | 1117 | }; |
| 1118 | 1118 | |
| @@ -1288,7 +1288,7 @@ static bool update_pipes_with_split_flags(struct dc *dc, struct dc_state *contex · 169 unmodified lines | ||
| 1288 | 1288 | return updated; |
| 1289 | 1289 | } |
| 1290 | 1290 | |
| 1291 | −static bool should_allow_odm_power_optimization(struct dc *dc, | |
| 1291 | +static bool should_apply_odm_power_optimization(struct dc *dc, | |
| 1292 | 1292 | struct dc_state *context, struct vba_vars_st *v, int *split, |
| 1293 | 1293 | bool *merge) |
| 1294 | 1294 | { |
| @@ -1392,9 +1392,12 @@ static void try_odm_power_optimization_and_revalidate( · 97 unmodified lines | ||
| 1392 | 1392 | { |
| 1393 | 1393 | int i; |
| 1394 | 1394 | unsigned int new_vlevel; |
| 1395 | + unsigned int cur_policy[MAX_PIPES]; | |
| 1395 | 1396 | |
| 1396 | − for (i = 0; i < pipe_cnt; i++) | |
| 1397 | + for (i = 0; i < pipe_cnt; i++) { | |
| 1398 | + cur_policy[i] = pipes[i].pipe.dest.odm_combine_policy; | |
| 1397 | 1399 | pipes[i].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; |
| 1400 | + } | |
| 1398 | 1401 | |
| 1399 | 1402 | new_vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); |
| 1400 | 1403 | |
| @@ -1403,6 +1406,9 @@ static void try_odm_power_optimization_and_revalidate( · 2 unmodified lines | ||
| 1403 | 1406 | memset(merge, 0, MAX_PIPES * sizeof(bool)); |
| 1404 | 1407 | *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, new_vlevel, split, merge); |
| 1405 | 1408 | context->bw_ctx.dml.vba.VoltageLevel = *vlevel; |
| 1409 | + } else { | |
| 1410 | + for (i = 0; i < pipe_cnt; i++) | |
| 1411 | + pipes[i].pipe.dest.odm_combine_policy = cur_policy[i]; | |
| 1406 | 1412 | } |
| 1407 | 1413 | } |
| 1408 | 1414 | |
| @@ -1580,7 +1586,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, · 171 unmodified lines | ||
| 1580 | 1586 | } |
| 1581 | 1587 | } |
| 1582 | 1588 | |
| 1583 | − if (should_allow_odm_power_optimization(dc, context, vba, split, merge)) | |
| 1589 | + if (should_apply_odm_power_optimization(dc, context, vba, split, merge)) | |
| 1584 | 1590 | try_odm_power_optimization_and_revalidate( |
| 1585 | 1591 | dc, context, pipes, split, merge, vlevel, *pipe_cnt); |
| 1586 | 1592 | |
| @@ -2209,7 +2215,8 @@ bool dcn32_internal_validate_bw(struct dc *dc, · 622 unmodified lines | ||
| 2209 | 2215 | int i; |
| 2210 | 2216 | |
| 2211 | 2217 | pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); |
| 2212 | − dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes); | |
| 2218 | + if (!dc->config.enable_windowed_mpo_odm) | |
| 2219 | + dcn32_update_dml_pipes_odm_policy_based_on_context(dc, context, pipes); | |
| 2213 | 2220 | |
| 2214 | 2221 | /* repopulate_pipes = 1 means the pipes were either split or merged. In this case |
| 2215 | 2222 | * we have to re-calculate the DET allocation and run through DML once more to |
| @@ -2753,7 +2760,7 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk · 537 unmodified lines | ||
| 2753 | 2760 | struct _vcs_dpi_voltage_scaling_st entry = {0}; |
| 2754 | 2761 | struct clk_limit_table_entry max_clk_data = {0}; |
| 2755 | 2762 | |
| 2756 | − unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299; | |
| 2763 | + unsigned int min_dcfclk_mhz = 399, min_fclk_mhz = 599; | |
| 2757 | 2764 | |
| 2758 | 2765 | static const unsigned int num_dcfclk_stas = 5; |
| 2759 | 2766 | unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {199, 615, 906, 1324, 1564}; |
| @@ -164,8 +164,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = { · 163 unmodified lines | ||
| 164 | 164 | }, |
| 165 | 165 | }, |
| 166 | 166 | .num_states = 5, |
| 167 | − .sr_exit_time_us = 14.0, | |
| 168 | − .sr_enter_plus_exit_time_us = 16.0, | |
| 167 | + .sr_exit_time_us = 28.0, | |
| 168 | + .sr_enter_plus_exit_time_us = 30.0, | |
| 169 | 169 | .sr_exit_z8_time_us = 210.0, |
| 170 | 170 | .sr_enter_plus_exit_z8_time_us = 320.0, |
| 171 | 171 | .fclk_change_latency_us = 24.0, |
| @@ -341,9 +341,6 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, · 340 unmodified lines | ||
| 341 | 341 | break; |
| 342 | 342 | } |
| 343 | 343 | |
| 344 | − if (dml2->config.bbox_overrides.clks_table.num_states) | |
| 345 | − p->in_states->num_states = dml2->config.bbox_overrides.clks_table.num_states; | |
| 346 | − | |
| 347 | 344 | /* Override from passed values, if available */ |
| 348 | 345 | for (i = 0; i < p->in_states->num_states; i++) { |
| 349 | 346 | if (dml2->config.bbox_overrides.sr_exit_latency_us) { |
| @@ -400,6 +397,7 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, · 50 unmodified lines | ||
| 400 | 397 | } |
| 401 | 398 | /* Copy clocks tables entries, if available */ |
| 402 | 399 | if (dml2->config.bbox_overrides.clks_table.num_states) { |
| 400 | + p->in_states->num_states = dml2->config.bbox_overrides.clks_table.num_states; | |
| 403 | 401 | |
| 404 | 402 | for (i = 0; i < dml2->config.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels; i++) { |
| 405 | 403 | p->in_states->state_array[i].dcfclk_mhz = dml2->config.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz; |
| @@ -793,35 +791,28 @@ static void populate_dml_surface_cfg_from_plane_state(enum dml_project_id dml2_p · 387 unmodified lines | ||
| 793 | 791 | } |
| 794 | 792 | } |
| 795 | 793 | |
| 796 | −/*TODO no support for mpc combine, need rework - should calculate scaling params based on plane+stream*/ | |
| 797 | −static struct scaler_data get_scaler_data_for_plane(const struct dc_plane_state *in, const struct dc_state *context) | |
| 794 | +static struct scaler_data get_scaler_data_for_plane(const struct dc_plane_state *in, struct dc_state *context) | |
| 798 | 795 | { |
| 799 | 796 | int i; |
| 800 | − struct scaler_data data = { 0 }; | |
| 797 | + struct pipe_ctx *temp_pipe = &context->res_ctx.temp_pipe; | |
| 798 | + | |
| 799 | + memset(temp_pipe, 0, sizeof(struct pipe_ctx)); | |
| 801 | 800 | |
| 802 | 801 | for (i = 0; i < MAX_PIPES; i++) { |
| 803 | 802 | const struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; |
| 804 | 803 | |
| 805 | 804 | if (pipe->plane_state == in && !pipe->prev_odm_pipe) { |
| 806 | − const struct pipe_ctx *next_pipe = pipe->next_odm_pipe; | |
| 807 | − | |
| 808 | − data = context->res_ctx.pipe_ctx[i].plane_res.scl_data; | |
| 809 | − while (next_pipe) { | |
| 810 | − data.h_active += next_pipe->plane_res.scl_data.h_active; | |
| 811 | − data.recout.width += next_pipe->plane_res.scl_data.recout.width; | |
| 812 | − if (in->rotation == ROTATION_ANGLE_0 || in->rotation == ROTATION_ANGLE_180) { | |
| 813 | − data.viewport.width += next_pipe->plane_res.scl_data.viewport.width; | |
| 814 | − } else { | |
| 815 | − data.viewport.height += next_pipe->plane_res.scl_data.viewport.height; | |
| 816 | − } | |
| 817 | − next_pipe = next_pipe->next_odm_pipe; | |
| 818 | − } | |
| 805 | + temp_pipe->stream = pipe->stream; | |
| 806 | + temp_pipe->plane_state = pipe->plane_state; | |
| 807 | + temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps; | |
| 808 | + | |
| 809 | + resource_build_scaling_params(temp_pipe); | |
| 819 | 810 | break; |
| 820 | 811 | } |
| 821 | 812 | } |
| 822 | 813 | |
| 823 | 814 | ASSERT(i < MAX_PIPES); |
| 824 | − return data; | |
| 815 | + return temp_pipe->plane_res.scl_data; | |
| 825 | 816 | } |
| 826 | 817 | |
| 827 | 818 | static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_stream_state *in) |
| @@ -866,7 +857,7 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned · 38 unmodified lines | ||
| 866 | 857 | out->ScalerEnabled[location] = false; |
| 867 | 858 | } |
| 868 | 859 | |
| 869 | −static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_plane_state *in, const struct dc_state *context) | |
| 860 | +static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_plane_state *in, struct dc_state *context) | |
| 870 | 861 | { |
| 871 | 862 | const struct scaler_data scaler_data = get_scaler_data_for_plane(in, context); |
| 872 | 863 | |
| @@ -1183,9 +1183,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) · 1182 unmodified lines | ||
| 1183 | 1183 | dto_params.timing = &pipe_ctx->stream->timing; |
| 1184 | 1184 | dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; |
| 1185 | 1185 | if (dccg) { |
| 1186 | − dccg->funcs->set_dtbclk_dto(dccg, &dto_params); | |
| 1187 | 1186 | dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst); |
| 1188 | 1187 | dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst); |
| 1188 | + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); | |
| 1189 | 1189 | } |
| 1190 | 1190 | } else if (dccg && dccg->funcs->disable_symclk_se) { |
| 1191 | 1191 | dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| @@ -1476,7 +1476,7 @@ static enum dc_status dce110_enable_stream_timing( · 284 unmodified lines | ||
| 1476 | 1476 | return DC_OK; |
| 1477 | 1477 | } |
| 1478 | 1478 | |
| 1479 | −static enum dc_status apply_single_controller_ctx_to_hw( | |
| 1479 | +enum dc_status dce110_apply_single_controller_ctx_to_hw( | |
| 1480 | 1480 | struct pipe_ctx *pipe_ctx, |
| 1481 | 1481 | struct dc_state *context, |
| 1482 | 1482 | struct dc *dc) |
| @@ -2302,7 +2302,7 @@ enum dc_status dce110_apply_ctx_to_hw( · 819 unmodified lines | ||
| 2302 | 2302 | if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe) |
| 2303 | 2303 | continue; |
| 2304 | 2304 | |
| 2305 | − status = apply_single_controller_ctx_to_hw( | |
| 2305 | + status = dce110_apply_single_controller_ctx_to_hw( | |
| 2306 | 2306 | pipe_ctx, |
| 2307 | 2307 | context, |
| 2308 | 2308 | dc); |
| @@ -39,6 +39,10 @@ enum dc_status dce110_apply_ctx_to_hw( · 38 unmodified lines | ||
| 39 | 39 | struct dc *dc, |
| 40 | 40 | struct dc_state *context); |
| 41 | 41 | |
| 42 | +enum dc_status dce110_apply_single_controller_ctx_to_hw( | |
| 43 | + struct pipe_ctx *pipe_ctx, | |
| 44 | + struct dc_state *context, | |
| 45 | + struct dc *dc); | |
| 42 | 46 | |
| 43 | 47 | void dce110_enable_stream(struct pipe_ctx *pipe_ctx); |
| 44 | 48 | |
| @@ -2561,7 +2561,7 @@ void dcn20_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx) · 2560 unmodified lines | ||
| 2561 | 2561 | tg->funcs->setup_vertical_interrupt2(tg, start_line); |
| 2562 | 2562 | } |
| 2563 | 2563 | |
| 2564 | −static void dcn20_reset_back_end_for_pipe( | |
| 2564 | +void dcn20_reset_back_end_for_pipe( | |
| 2565 | 2565 | struct dc *dc, |
| 2566 | 2566 | struct pipe_ctx *pipe_ctx, |
| 2567 | 2567 | struct dc_state *context) |
| @@ -2790,18 +2790,17 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) · 222 unmodified lines | ||
| 2790 | 2790 | } |
| 2791 | 2791 | |
| 2792 | 2792 | if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { |
| 2793 | − dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; | |
| 2794 | − dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); | |
| 2795 | − | |
| 2796 | − phyd32clk = get_phyd32clk_src(link); | |
| 2797 | − dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); | |
| 2798 | − | |
| 2799 | 2793 | dto_params.otg_inst = tg->inst; |
| 2800 | 2794 | dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; |
| 2801 | 2795 | dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); |
| 2802 | 2796 | dto_params.timing = &pipe_ctx->stream->timing; |
| 2803 | 2797 | dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); |
| 2804 | 2798 | dccg->funcs->set_dtbclk_dto(dccg, &dto_params); |
| 2799 | + dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; | |
| 2800 | + dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); | |
| 2801 | + | |
| 2802 | + phyd32clk = get_phyd32clk_src(link); | |
| 2803 | + dccg->funcs->enable_symclk32_se(dccg, dp_hpo_inst, phyd32clk); | |
| 2805 | 2804 | } else { |
| 2806 | 2805 | if (dccg->funcs->enable_symclk_se) |
| 2807 | 2806 | dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, |
| @@ -84,6 +84,10 @@ enum dc_status dcn20_enable_stream_timing( · 83 unmodified lines | ||
| 84 | 84 | void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx); |
| 85 | 85 | void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx); |
| 86 | 86 | void dcn20_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx); |
| 87 | +void dcn20_reset_back_end_for_pipe( | |
| 88 | + struct dc *dc, | |
| 89 | + struct pipe_ctx *pipe_ctx, | |
| 90 | + struct dc_state *context); | |
| 87 | 91 | void dcn20_init_blank( |
| 88 | 92 | struct dc *dc, |
| 89 | 93 | struct timing_generator *tg); |
| @@ -206,28 +206,32 @@ void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) · 205 unmodified lines | ||
| 206 | 206 | void dcn21_set_pipe(struct pipe_ctx *pipe_ctx) |
| 207 | 207 | { |
| 208 | 208 | struct abm *abm = pipe_ctx->stream_res.abm; |
| 209 | − uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; | |
| 209 | + struct timing_generator *tg = pipe_ctx->stream_res.tg; | |
| 210 | 210 | struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; |
| 211 | 211 | struct dmcu *dmcu = pipe_ctx->stream->ctx->dc->res_pool->dmcu; |
| 212 | + uint32_t otg_inst; | |
| 213 | + | |
| 214 | + if (!abm && !tg && !panel_cntl) | |
| 215 | + return; | |
| 216 | + | |
| 217 | + otg_inst = tg->inst; | |
| 212 | 218 | |
| 213 | 219 | if (dmcu) { |
| 214 | 220 | dce110_set_pipe(pipe_ctx); |
| 215 | 221 | return; |
| 216 | 222 | } |
| 217 | 223 | |
| 218 | − if (abm && panel_cntl) { | |
| 219 | − if (abm->funcs && abm->funcs->set_pipe_ex) { | |
| 220 | − abm->funcs->set_pipe_ex(abm, | |
| 224 | + if (abm->funcs && abm->funcs->set_pipe_ex) { | |
| 225 | + abm->funcs->set_pipe_ex(abm, | |
| 221 | 226 | otg_inst, |
| 222 | 227 | SET_ABM_PIPE_NORMAL, |
| 223 | 228 | panel_cntl->inst, |
| 224 | 229 | panel_cntl->pwrseq_inst); |
| 225 | − } else { | |
| 226 | − dmub_abm_set_pipe(abm, otg_inst, | |
| 227 | − SET_ABM_PIPE_NORMAL, | |
| 228 | − panel_cntl->inst, | |
| 229 | − panel_cntl->pwrseq_inst); | |
| 230 | − } | |
| 230 | + } else { | |
| 231 | + dmub_abm_set_pipe(abm, otg_inst, | |
| 232 | + SET_ABM_PIPE_NORMAL, | |
| 233 | + panel_cntl->inst, | |
| 234 | + panel_cntl->pwrseq_inst); | |
| 231 | 235 | } |
| 232 | 236 | } |
| 233 | 237 | |
| @@ -237,34 +241,35 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx, · 3 unmodified lines | ||
| 237 | 241 | { |
| 238 | 242 | struct dc_context *dc = pipe_ctx->stream->ctx; |
| 239 | 243 | struct abm *abm = pipe_ctx->stream_res.abm; |
| 244 | + struct timing_generator *tg = pipe_ctx->stream_res.tg; | |
| 240 | 245 | struct panel_cntl *panel_cntl = pipe_ctx->stream->link->panel_cntl; |
| 246 | + uint32_t otg_inst; | |
| 247 | + | |
| 248 | + if (!abm && !tg && !panel_cntl) | |
| 249 | + return false; | |
| 250 | + | |
| 251 | + otg_inst = tg->inst; | |
| 241 | 252 | |
| 242 | 253 | if (dc->dc->res_pool->dmcu) { |
| 243 | 254 | dce110_set_backlight_level(pipe_ctx, backlight_pwm_u16_16, frame_ramp); |
| 244 | 255 | return true; |
| 245 | 256 | } |
| 246 | 257 | |
| 247 | − if (abm != NULL) { | |
| 248 | − uint32_t otg_inst = pipe_ctx->stream_res.tg->inst; | |
| 249 | − | |
| 250 | − if (abm && panel_cntl) { | |
| 251 | − if (abm->funcs && abm->funcs->set_pipe_ex) { | |
| 252 | − abm->funcs->set_pipe_ex(abm, | |
| 253 | − otg_inst, | |
| 254 | − SET_ABM_PIPE_NORMAL, | |
| 255 | − panel_cntl->inst, | |
| 256 | − panel_cntl->pwrseq_inst); | |
| 257 | − } else { | |
| 258 | − dmub_abm_set_pipe(abm, | |
| 259 | − otg_inst, | |
| 260 | − SET_ABM_PIPE_NORMAL, | |
| 261 | − panel_cntl->inst, | |
| 262 | − panel_cntl->pwrseq_inst); | |
| 263 | − } | |
| 264 | − } | |
| 258 | + if (abm->funcs && abm->funcs->set_pipe_ex) { | |
| 259 | + abm->funcs->set_pipe_ex(abm, | |
| 260 | + otg_inst, | |
| 261 | + SET_ABM_PIPE_NORMAL, | |
| 262 | + panel_cntl->inst, | |
| 263 | + panel_cntl->pwrseq_inst); | |
| 264 | + } else { | |
| 265 | + dmub_abm_set_pipe(abm, | |
| 266 | + otg_inst, | |
| 267 | + SET_ABM_PIPE_NORMAL, | |
| 268 | + panel_cntl->inst, | |
| 269 | + panel_cntl->pwrseq_inst); | |
| 265 | 270 | } |
| 266 | 271 | |
| 267 | − if (abm && abm->funcs && abm->funcs->set_backlight_level_pwm) | |
| 272 | + if (abm->funcs && abm->funcs->set_backlight_level_pwm) | |
| 268 | 273 | abm->funcs->set_backlight_level_pwm(abm, backlight_pwm_u16_16, |
| 269 | 274 | frame_ramp, 0, panel_cntl->inst); |
| 270 | 275 | else |
| @@ -1474,9 +1474,44 @@ void dcn32_update_dsc_pg(struct dc *dc, · 1473 unmodified lines | ||
| 1474 | 1474 | } |
| 1475 | 1475 | } |
| 1476 | 1476 | |
| 1477 | +void dcn32_disable_phantom_streams(struct dc *dc, struct dc_state *context) | |
| 1478 | +{ | |
| 1479 | + struct dce_hwseq *hws = dc->hwseq; | |
| 1480 | + int i; | |
| 1481 | + | |
| 1482 | + for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { | |
| 1483 | + struct pipe_ctx *pipe_ctx_old = | |
| 1484 | + &dc->current_state->res_ctx.pipe_ctx[i]; | |
| 1485 | + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
| 1486 | + | |
| 1487 | + if (!pipe_ctx_old->stream) | |
| 1488 | + continue; | |
| 1489 | + | |
| 1490 | + if (dc_state_get_pipe_subvp_type(dc->current_state, pipe_ctx_old) != SUBVP_PHANTOM) | |
| 1491 | + continue; | |
| 1492 | + | |
| 1493 | + if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe) | |
| 1494 | + continue; | |
| 1495 | + | |
| 1496 | + if (!pipe_ctx->stream || pipe_need_reprogram(pipe_ctx_old, pipe_ctx) || | |
| 1497 | + (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)) { | |
| 1498 | + struct clock_source *old_clk = pipe_ctx_old->clock_source; | |
| 1499 | + | |
| 1500 | + if (hws->funcs.reset_back_end_for_pipe) | |
| 1501 | + hws->funcs.reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state); | |
| 1502 | + if (hws->funcs.enable_stream_gating) | |
| 1503 | + hws->funcs.enable_stream_gating(dc, pipe_ctx_old); | |
| 1504 | + if (old_clk) | |
| 1505 | + old_clk->funcs->cs_power_down(old_clk); | |
| 1506 | + } | |
| 1507 | + } | |
| 1508 | +} | |
| 1509 | + | |
| 1477 | 1510 | void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context) |
| 1478 | 1511 | { |
| 1479 | 1512 | unsigned int i; |
| 1513 | + enum dc_status status = DC_OK; | |
| 1514 | + struct dce_hwseq *hws = dc->hwseq; | |
| 1480 | 1515 | |
| 1481 | 1516 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
| 1482 | 1517 | struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; |
| @@ -1497,16 +1532,39 @@ void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context) · 14 unmodified lines | ||
| 1497 | 1532 | } |
| 1498 | 1533 | } |
| 1499 | 1534 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
| 1500 | − struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; | |
| 1501 | − | |
| 1502 | − if (new_pipe->stream && dc_state_get_pipe_subvp_type(context, new_pipe) == SUBVP_PHANTOM) { | |
| 1503 | − // If old context or new context has phantom pipes, apply | |
| 1504 | − // the phantom timings now. We can't change the phantom | |
| 1505 | − // pipe configuration safely without driver acquiring | |
| 1506 | − // the DMCUB lock first. | |
| 1507 | − dc->hwss.apply_ctx_to_hw(dc, context); | |
| 1508 | − break; | |
| 1535 | + struct pipe_ctx *pipe_ctx_old = | |
| 1536 | + &dc->current_state->res_ctx.pipe_ctx[i]; | |
| 1537 | + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | |
| 1538 | + | |
| 1539 | + if (pipe_ctx->stream == NULL) | |
| 1540 | + continue; | |
| 1541 | + | |
| 1542 | + if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) | |
| 1543 | + continue; | |
| 1544 | + | |
| 1545 | + if (pipe_ctx->stream == pipe_ctx_old->stream && | |
| 1546 | + pipe_ctx->stream->link->link_state_valid) { | |
| 1547 | + continue; | |
| 1509 | 1548 | } |
| 1549 | + | |
| 1550 | + if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) | |
| 1551 | + continue; | |
| 1552 | + | |
| 1553 | + if (pipe_ctx->top_pipe || pipe_ctx->prev_odm_pipe) | |
| 1554 | + continue; | |
| 1555 | + | |
| 1556 | + if (hws->funcs.apply_single_controller_ctx_to_hw) | |
| 1557 | + status = hws->funcs.apply_single_controller_ctx_to_hw( | |
| 1558 | + pipe_ctx, | |
| 1559 | + context, | |
| 1560 | + dc); | |
| 1561 | + | |
| 1562 | + ASSERT(status == DC_OK); | |
| 1563 | + | |
| 1564 | +#ifdef CONFIG_DRM_AMD_DC_FP | |
| 1565 | + if (hws->funcs.resync_fifo_dccg_dio) | |
| 1566 | + hws->funcs.resync_fifo_dccg_dio(hws, dc, context); | |
| 1567 | +#endif | |
| 1510 | 1568 | } |
| 1511 | 1569 | } |
| 1512 | 1570 | |
| @@ -111,6 +111,8 @@ void dcn32_update_dsc_pg(struct dc *dc, · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | void dcn32_enable_phantom_streams(struct dc *dc, struct dc_state *context); |
| 113 | 113 | |
| 114 | +void dcn32_disable_phantom_streams(struct dc *dc, struct dc_state *context); | |
| 115 | + | |
| 114 | 116 | void dcn32_init_blank( |
| 115 | 117 | struct dc *dc, |
| 116 | 118 | struct timing_generator *tg); |
| @@ -109,6 +109,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { · 108 unmodified lines | ||
| 109 | 109 | .get_dcc_en_bits = dcn10_get_dcc_en_bits, |
| 110 | 110 | .commit_subvp_config = dcn32_commit_subvp_config, |
| 111 | 111 | .enable_phantom_streams = dcn32_enable_phantom_streams, |
| 112 | + .disable_phantom_streams = dcn32_disable_phantom_streams, | |
| 112 | 113 | .subvp_pipe_control_lock = dcn32_subvp_pipe_control_lock, |
| 113 | 114 | .update_visual_confirm_color = dcn10_update_visual_confirm_color, |
| 114 | 115 | .subvp_pipe_control_lock_fast = dcn32_subvp_pipe_control_lock_fast, |
| @@ -159,6 +160,8 @@ static const struct hwseq_private_funcs dcn32_private_funcs = { · 44 unmodified lines | ||
| 159 | 160 | .set_pixels_per_cycle = dcn32_set_pixels_per_cycle, |
| 160 | 161 | .resync_fifo_dccg_dio = dcn32_resync_fifo_dccg_dio, |
| 161 | 162 | .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy, |
| 163 | + .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw, | |
| 164 | + .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe, | |
| 162 | 165 | }; |
| 163 | 166 | |
| 164 | 167 | void dcn32_hw_sequencer_init_functions(struct dc *dc) |
| @@ -680,7 +680,7 @@ void dcn35_power_down_on_boot(struct dc *dc) · 679 unmodified lines | ||
| 680 | 680 | bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) |
| 681 | 681 | { |
| 682 | 682 | struct dc_link *edp_links[MAX_NUM_EDP]; |
| 683 | − int edp_num; | |
| 683 | + int i, edp_num; | |
| 684 | 684 | if (dc->debug.dmcub_emulation) |
| 685 | 685 | return true; |
| 686 | 686 | |
| @@ -688,6 +688,13 @@ bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) · 1 unmodified line | ||
| 688 | 688 | dc_get_edp_links(dc, edp_links, &edp_num); |
| 689 | 689 | if (edp_num == 0 || edp_num > 1) |
| 690 | 690 | return false; |
| 691 | + | |
| 692 | + for (i = 0; i < dc->current_state->stream_count; ++i) { | |
| 693 | + struct dc_stream_state *stream = dc->current_state->streams[i]; | |
| 694 | + | |
| 695 | + if (!stream->dpms_off && !dc_is_embedded_signal(stream->signal)) | |
| 696 | + return false; | |
| 697 | + } | |
| 691 | 698 | } |
| 692 | 699 | |
| 693 | 700 | // TODO: review other cases when idle optimization is allowed |
| @@ -379,6 +379,7 @@ struct hw_sequencer_funcs { · 378 unmodified lines | ||
| 379 | 379 | struct dc_cursor_attributes *cursor_attr); |
| 380 | 380 | void (*commit_subvp_config)(struct dc *dc, struct dc_state *context); |
| 381 | 381 | void (*enable_phantom_streams)(struct dc *dc, struct dc_state *context); |
| 382 | + void (*disable_phantom_streams)(struct dc *dc, struct dc_state *context); | |
| 382 | 383 | void (*subvp_pipe_control_lock)(struct dc *dc, |
| 383 | 384 | struct dc_state *context, |
| 384 | 385 | bool lock, |
| @@ -165,8 +165,15 @@ struct hwseq_private_funcs { · 164 unmodified lines | ||
| 165 | 165 | void (*set_pixels_per_cycle)(struct pipe_ctx *pipe_ctx); |
| 166 | 166 | void (*resync_fifo_dccg_dio)(struct dce_hwseq *hws, struct dc *dc, |
| 167 | 167 | struct dc_state *context); |
| 168 | + enum dc_status (*apply_single_controller_ctx_to_hw)( | |
| 169 | + struct pipe_ctx *pipe_ctx, | |
| 170 | + struct dc_state *context, | |
| 171 | + struct dc *dc); | |
| 168 | 172 | bool (*is_dp_dig_pixel_rate_div_policy)(struct pipe_ctx *pipe_ctx); |
| 169 | 173 | #endif |
| 174 | + void (*reset_back_end_for_pipe)(struct dc *dc, | |
| 175 | + struct pipe_ctx *pipe_ctx, | |
| 176 | + struct dc_state *context); | |
| 170 | 177 | }; |
| 171 | 178 | |
| 172 | 179 | struct dce_hwseq { |
| @@ -469,6 +469,8 @@ struct resource_context { · 468 unmodified lines | ||
| 469 | 469 | unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS]; |
| 470 | 470 | int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS]; |
| 471 | 471 | bool is_mpc_3dlut_acquired[MAX_PIPES]; |
| 472 | + /* solely used for build scalar data in dml2 */ | |
| 473 | + struct pipe_ctx temp_pipe; | |
| 472 | 474 | }; |
| 473 | 475 | |
| 474 | 476 | struct dce_bw_output { |
| @@ -427,22 +427,18 @@ struct pipe_ctx *resource_get_primary_dpp_pipe(const struct pipe_ctx *dpp_pipe); · 426 unmodified lines | ||
| 427 | 427 | int resource_get_mpc_slice_index(const struct pipe_ctx *dpp_pipe); |
| 428 | 428 | |
| 429 | 429 | /* |
| 430 | − * Get number of MPC "cuts" of the plane associated with the pipe. MPC slice | |
| 431 | − * count is equal to MPC splits + 1. For example if a plane is cut 3 times, it | |
| 432 | − * will have 4 pieces of slice. | |
| 433 | − * return - 0 if pipe is not used for a plane with MPCC combine. otherwise | |
| 434 | − * the number of MPC "cuts" for the plane. | |
| 430 | + * Get the number of MPC slices associated with the pipe. | |
| 431 | + * The function returns 0 if the pipe is not associated with an MPC combine | |
| 432 | + * pipe topology. | |
| 435 | 433 | */ |
| 436 | −int resource_get_mpc_slice_count(const struct pipe_ctx *opp_head); | |
| 434 | +int resource_get_mpc_slice_count(const struct pipe_ctx *pipe); | |
| 437 | 435 | |
| 438 | 436 | /* |
| 439 | − * Get number of ODM "cuts" of the timing associated with the pipe. ODM slice | |
| 440 | − * count is equal to ODM splits + 1. For example if a timing is cut 3 times, it | |
| 441 | − * will have 4 pieces of slice. | |
| 442 | − * return - 0 if pipe is not used for ODM combine. otherwise | |
| 443 | − * the number of ODM "cuts" for the timing. | |
| 437 | + * Get the number of ODM slices associated with the pipe. | |
| 438 | + * The function returns 0 if the pipe is not associated with an ODM combine | |
| 439 | + * pipe topology. | |
| 444 | 440 | */ |
| 445 | −int resource_get_odm_slice_count(const struct pipe_ctx *otg_master); | |
| 441 | +int resource_get_odm_slice_count(const struct pipe_ctx *pipe); | |
| 446 | 442 | |
| 447 | 443 | /* Get the ODM slice index counting from 0 from left most slice */ |
| 448 | 444 | int resource_get_odm_slice_index(const struct pipe_ctx *opp_head); |
| @@ -196,7 +196,7 @@ static int get_host_router_total_dp_tunnel_bw(const struct dc *dc, uint8_t hr_in · 195 unmodified lines | ||
| 196 | 196 | struct dc_link *link_dpia_primary, *link_dpia_secondary; |
| 197 | 197 | int total_bw = 0; |
| 198 | 198 | |
| 199 | − for (uint8_t i = 0; i < MAX_PIPES * 2; ++i) { | |
| 199 | + for (uint8_t i = 0; i < (MAX_PIPES * 2) - 1; ++i) { | |
| 200 | 200 | |
| 201 | 201 | if (!dc->links[i] || dc->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) |
| 202 | 202 | continue; |
| @@ -205,7 +205,7 @@ enum dc_status core_link_read_dpcd( · 204 unmodified lines | ||
| 205 | 205 | uint32_t extended_size; |
| 206 | 206 | /* size of the remaining partitioned address space */ |
| 207 | 207 | uint32_t size_left_to_read; |
| 208 | − enum dc_status status; | |
| 208 | + enum dc_status status = DC_ERROR_UNEXPECTED; | |
| 209 | 209 | /* size of the next partition to be read from */ |
| 210 | 210 | uint32_t partition_size; |
| 211 | 211 | uint32_t data_index = 0; |
| @@ -234,7 +234,7 @@ enum dc_status core_link_write_dpcd( · 22 unmodified lines | ||
| 234 | 234 | { |
| 235 | 235 | uint32_t partition_size; |
| 236 | 236 | uint32_t data_index = 0; |
| 237 | − enum dc_status status; | |
| 237 | + enum dc_status status = DC_ERROR_UNEXPECTED; | |
| 238 | 238 | |
| 239 | 239 | while (size) { |
| 240 | 240 | partition_size = dpcd_get_next_partition_size(address, size); |
| @@ -999,7 +999,7 @@ static struct stream_encoder *dcn301_stream_encoder_create(enum engine_id eng_id · 998 unmodified lines | ||
| 999 | 999 | vpg = dcn301_vpg_create(ctx, vpg_inst); |
| 1000 | 1000 | afmt = dcn301_afmt_create(ctx, afmt_inst); |
| 1001 | 1001 | |
| 1002 | − if (!enc1 || !vpg || !afmt) { | |
| 1002 | + if (!enc1 || !vpg || !afmt || eng_id >= ARRAY_SIZE(stream_enc_regs)) { | |
| 1003 | 1003 | kfree(enc1); |
| 1004 | 1004 | kfree(vpg); |
| 1005 | 1005 | kfree(afmt); |
| @@ -1829,7 +1829,21 @@ int dcn32_populate_dml_pipes_from_context( · 1828 unmodified lines | ||
| 1829 | 1829 | dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt); |
| 1830 | 1830 | DC_FP_END(); |
| 1831 | 1831 | pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; |
| 1832 | − pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; | |
| 1832 | + if (dc->config.enable_windowed_mpo_odm && | |
| 1833 | + dc->debug.enable_single_display_2to1_odm_policy) { | |
| 1834 | + switch (resource_get_odm_slice_count(pipe)) { | |
| 1835 | + case 2: | |
| 1836 | + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; | |
| 1837 | + break; | |
| 1838 | + case 4: | |
| 1839 | + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_4to1; | |
| 1840 | + break; | |
| 1841 | + default: | |
| 1842 | + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; | |
| 1843 | + } | |
| 1844 | + } else { | |
| 1845 | + pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; | |
| 1846 | + } | |
| 1833 | 1847 | pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet |
| 1834 | 1848 | pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; |
| 1835 | 1849 | pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19; |
| @@ -780,8 +780,8 @@ static const struct dc_debug_options debug_defaults_drv = { · 779 unmodified lines | ||
| 780 | 780 | .disable_z10 = false, |
| 781 | 781 | .ignore_pg = true, |
| 782 | 782 | .psp_disabled_wa = true, |
| 783 | − .ips2_eval_delay_us = 200, | |
| 784 | − .ips2_entry_delay_us = 400, | |
| 783 | + .ips2_eval_delay_us = 1650, | |
| 784 | + .ips2_entry_delay_us = 800, | |
| 785 | 785 | .static_screen_wait_frames = 2, |
| 786 | 786 | }; |
| 787 | 787 | |
| @@ -2130,6 +2130,7 @@ static bool dcn35_resource_construct( · 1342 unmodified lines | ||
| 2130 | 2130 | dc->dml2_options.dcn_pipe_count = pool->base.pipe_count; |
| 2131 | 2131 | dc->dml2_options.use_native_pstate_optimization = true; |
| 2132 | 2132 | dc->dml2_options.use_native_soc_bb_construction = true; |
| 2133 | + dc->dml2_options.minimize_dispclk_using_odm = false; | |
| 2133 | 2134 | if (dc->config.EnableMinDispClkODM) |
| 2134 | 2135 | dc->dml2_options.minimize_dispclk_using_odm = true; |
| 2135 | 2136 | dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm; |
| @@ -2832,6 +2832,7 @@ struct dmub_rb_cmd_psr_set_power_opt { · 2831 unmodified lines | ||
| 2832 | 2832 | #define REPLAY_RESIDENCY_MODE_MASK (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) |
| 2833 | 2833 | # define REPLAY_RESIDENCY_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT) |
| 2834 | 2834 | # define REPLAY_RESIDENCY_MODE_ALPM (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) |
| 2835 | +# define REPLAY_RESIDENCY_MODE_IPS 0x10 | |
| 2835 | 2836 | |
| 2836 | 2837 | #define REPLAY_RESIDENCY_ENABLE_MASK (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT) |
| 2837 | 2838 | # define REPLAY_RESIDENCY_DISABLE (0x0 << REPLAY_RESIDENCY_ENABLE_SHIFT) |
| @@ -2894,6 +2895,10 @@ enum dmub_cmd_replay_type { · 56 unmodified lines | ||
| 2894 | 2895 | * Set Residency Frameupdate Timer. |
| 2895 | 2896 | */ |
| 2896 | 2897 | DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER = 6, |
| 2898 | + /** | |
| 2899 | + * Set pseudo vtotal | |
| 2900 | + */ | |
| 2901 | + DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL = 7, | |
| 2897 | 2902 | }; |
| 2898 | 2903 | |
| 2899 | 2904 | /** |
| @@ -3076,6 +3081,26 @@ struct dmub_cmd_replay_set_timing_sync_data { · 176 unmodified lines | ||
| 3076 | 3081 | uint8_t pad[2]; |
| 3077 | 3082 | }; |
| 3078 | 3083 | |
| 3084 | +/** | |
| 3085 | + * Data passed from driver to FW in a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command. | |
| 3086 | + */ | |
| 3087 | +struct dmub_cmd_replay_set_pseudo_vtotal { | |
| 3088 | + /** | |
| 3089 | + * Panel Instance. | |
| 3090 | + * Panel isntance to identify which replay_state to use | |
| 3091 | + * Currently the support is only for 0 or 1 | |
| 3092 | + */ | |
| 3093 | + uint8_t panel_inst; | |
| 3094 | + /** | |
| 3095 | + * Source Vtotal that Replay + IPS + ABM full screen video src vtotal | |
| 3096 | + */ | |
| 3097 | + uint16_t vtotal; | |
| 3098 | + /** | |
| 3099 | + * Explicit padding to 4 byte boundary. | |
| 3100 | + */ | |
| 3101 | + uint8_t pad; | |
| 3102 | +}; | |
| 3103 | + | |
| 3079 | 3104 | /** |
| 3080 | 3105 | * Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command. |
| 3081 | 3106 | */ |
| @@ -3156,6 +3181,20 @@ struct dmub_rb_cmd_replay_set_timing_sync { · 74 unmodified lines | ||
| 3156 | 3181 | struct dmub_cmd_replay_set_timing_sync_data replay_set_timing_sync_data; |
| 3157 | 3182 | }; |
| 3158 | 3183 | |
| 3184 | +/** | |
| 3185 | + * Definition of a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command. | |
| 3186 | + */ | |
| 3187 | +struct dmub_rb_cmd_replay_set_pseudo_vtotal { | |
| 3188 | + /** | |
| 3189 | + * Command header. | |
| 3190 | + */ | |
| 3191 | + struct dmub_cmd_header header; | |
| 3192 | + /** | |
| 3193 | + * Definition of DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command. | |
| 3194 | + */ | |
| 3195 | + struct dmub_cmd_replay_set_pseudo_vtotal data; | |
| 3196 | +}; | |
| 3197 | + | |
| 3159 | 3198 | /** |
| 3160 | 3199 | * Data passed from driver to FW in DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command. |
| 3161 | 3200 | */ |
| @@ -3207,6 +3246,10 @@ union dmub_replay_cmd_set { · 45 unmodified lines | ||
| 3207 | 3246 | * Definition of DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command data. |
| 3208 | 3247 | */ |
| 3209 | 3248 | struct dmub_cmd_replay_frameupdate_timer_data timer_data; |
| 3249 | + /** | |
| 3250 | + * Definition of DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command data. | |
| 3251 | + */ | |
| 3252 | + struct dmub_cmd_replay_set_pseudo_vtotal pseudo_vtotal_data; | |
| 3210 | 3253 | }; |
| 3211 | 3254 | |
| 3212 | 3255 | /** |
| @@ -4358,6 +4401,10 @@ union dmub_rb_cmd { · 1145 unmodified lines | ||
| 4358 | 4401 | * Definition of a DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command. |
| 4359 | 4402 | */ |
| 4360 | 4403 | struct dmub_rb_cmd_replay_set_frameupdate_timer replay_set_frameupdate_timer; |
| 4404 | + /** | |
| 4405 | + * Definition of a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command. | |
| 4406 | + */ | |
| 4407 | + struct dmub_rb_cmd_replay_set_pseudo_vtotal replay_set_pseudo_vtotal; | |
| 4361 | 4408 | }; |
| 4362 | 4409 | |
| 4363 | 4410 | /** |
| @@ -980,6 +980,11 @@ void set_replay_coasting_vtotal(struct dc_link *link, · 979 unmodified lines | ||
| 980 | 980 | link->replay_settings.coasting_vtotal_table[type] = vtotal; |
| 981 | 981 | } |
| 982 | 982 | |
| 983 | +void set_replay_ips_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal) | |
| 984 | +{ | |
| 985 | + link->replay_settings.abm_with_ips_on_full_screen_video_pseudo_vtotal = vtotal; | |
| 986 | +} | |
| 987 | + | |
| 983 | 988 | void calculate_replay_link_off_frame_count(struct dc_link *link, |
| 984 | 989 | uint16_t vtotal, uint16_t htotal) |
| 985 | 990 | { |
| @@ -57,6 +57,7 @@ void init_replay_config(struct dc_link *link, struct replay_config *pr_config); · 56 unmodified lines | ||
| 57 | 57 | void set_replay_coasting_vtotal(struct dc_link *link, |
| 58 | 58 | enum replay_coasting_vtotal_type type, |
| 59 | 59 | uint16_t vtotal); |
| 60 | +void set_replay_ips_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal); | |
| 60 | 61 | void calculate_replay_link_off_frame_count(struct dc_link *link, |
| 61 | 62 | uint16_t vtotal, uint16_t htotal); |
| 62 | 63 | |
| @@ -258,6 +258,7 @@ enum DC_DEBUG_MASK { · 257 unmodified lines | ||
| 258 | 258 | DC_ENABLE_DML2 = 0x100, |
| 259 | 259 | DC_DISABLE_PSR_SU = 0x200, |
| 260 | 260 | DC_DISABLE_REPLAY = 0x400, |
| 261 | + DC_DISABLE_IPS = 0x800, | |
| 261 | 262 | }; |
| 262 | 263 | |
| 263 | 264 | enum amd_dpm_forced_level; |
| @@ -138,7 +138,7 @@ static inline size_t amdgpu_reginst_size(uint16_t num_inst, size_t inst_size, · 137 unmodified lines | ||
| 138 | 138 | } |
| 139 | 139 | |
| 140 | 140 | #define amdgpu_asic_get_reg_state_supported(adev) \ |
| 141 | − ((adev)->asic_funcs->get_reg_state ? 1 : 0) | |
| 141 | + (((adev)->asic_funcs && (adev)->asic_funcs->get_reg_state) ? 1 : 0) | |
| 142 | 142 | |
| 143 | 143 | #define amdgpu_asic_get_reg_state(adev, state, buf, size) \ |
| 144 | 144 | ((adev)->asic_funcs->get_reg_state ? \ |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | #include <linux/firmware.h> |
| 26 | 26 | #include <linux/pci.h> |
| 27 | +#include <linux/power_supply.h> | |
| 27 | 28 | #include <linux/reboot.h> |
| 28 | 29 | |
| 29 | 30 | #include "amdgpu.h" |
| @@ -733,7 +734,7 @@ static int smu_early_init(void *handle) · 703 unmodified lines | ||
| 733 | 734 | smu->adev = adev; |
| 734 | 735 | smu->pm_enabled = !!amdgpu_dpm; |
| 735 | 736 | smu->is_apu = false; |
| 736 | − smu->smu_baco.state = SMU_BACO_STATE_NONE; | |
| 737 | + smu->smu_baco.state = SMU_BACO_STATE_EXIT; | |
| 737 | 738 | smu->smu_baco.platform_support = false; |
| 738 | 739 | smu->user_dpm_profile.fan_mode = -1; |
| 739 | 740 | |
| @@ -817,16 +818,8 @@ static int smu_late_init(void *handle) · 77 unmodified lines | ||
| 817 | 818 | * handle the switch automatically. Driver involvement |
| 818 | 819 | * is unnecessary. |
| 819 | 820 | */ |
| 820 | − if (!smu->dc_controlled_by_gpio) { | |
| 821 | − ret = smu_set_power_source(smu, | |
| 822 | − adev->pm.ac_power ? SMU_POWER_SOURCE_AC : | |
| 823 | − SMU_POWER_SOURCE_DC); | |
| 824 | − if (ret) { | |
| 825 | − dev_err(adev->dev, "Failed to switch to %s mode!\n", | |
| 826 | − adev->pm.ac_power ? "AC" : "DC"); | |
| 827 | − return ret; | |
| 828 | − } | |
| 829 | − } | |
| 821 | + adev->pm.ac_power = power_supply_is_system_supplied() > 0; | |
| 822 | + smu_set_ac_dc(smu); | |
| 830 | 823 | |
| 831 | 824 | if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 1)) || |
| 832 | 825 | (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 3))) |
| @@ -1961,31 +1954,10 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) · 1128 unmodified lines | ||
| 1961 | 1954 | return 0; |
| 1962 | 1955 | } |
| 1963 | 1956 | |
| 1964 | −static int smu_reset_mp1_state(struct smu_context *smu) | |
| 1965 | −{ | |
| 1966 | − struct amdgpu_device *adev = smu->adev; | |
| 1967 | − int ret = 0; | |
| 1968 | − | |
| 1969 | − if ((!adev->in_runpm) && (!adev->in_suspend) && | |
| 1970 | − (!amdgpu_in_reset(adev))) | |
| 1971 | − switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { | |
| 1972 | − case IP_VERSION(13, 0, 0): | |
| 1973 | − case IP_VERSION(13, 0, 7): | |
| 1974 | − case IP_VERSION(13, 0, 10): | |
| 1975 | − ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD); | |
| 1976 | − break; | |
| 1977 | − default: | |
| 1978 | − break; | |
| 1979 | − } | |
| 1980 | − | |
| 1981 | − return ret; | |
| 1982 | −} | |
| 1983 | − | |
| 1984 | 1957 | static int smu_hw_fini(void *handle) |
| 1985 | 1958 | { |
| 1986 | 1959 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1987 | 1960 | struct smu_context *smu = adev->powerplay.pp_handle; |
| 1988 | − int ret; | |
| 1989 | 1961 | |
| 1990 | 1962 | if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) |
| 1991 | 1963 | return 0; |
| @@ -2003,15 +1975,7 @@ static int smu_hw_fini(void *handle) · 11 unmodified lines | ||
| 2003 | 1975 | |
| 2004 | 1976 | adev->pm.dpm_enabled = false; |
| 2005 | 1977 | |
| 2006 | − ret = smu_smc_hw_cleanup(smu); | |
| 2007 | − if (ret) | |
| 2008 | − return ret; | |
| 2009 | − | |
| 2010 | − ret = smu_reset_mp1_state(smu); | |
| 2011 | − if (ret) | |
| 2012 | − return ret; | |
| 2013 | − | |
| 2014 | − return 0; | |
| 1978 | + return smu_smc_hw_cleanup(smu); | |
| 2015 | 1979 | } |
| 2016 | 1980 | |
| 2017 | 1981 | static void smu_late_fini(void *handle) |
| @@ -2710,6 +2674,7 @@ int smu_get_power_limit(void *handle, · 692 unmodified lines | ||
| 2710 | 2674 | case SMU_PPT_LIMIT_CURRENT: |
| 2711 | 2675 | switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { |
| 2712 | 2676 | case IP_VERSION(13, 0, 2): |
| 2677 | + case IP_VERSION(13, 0, 6): | |
| 2713 | 2678 | case IP_VERSION(11, 0, 7): |
| 2714 | 2679 | case IP_VERSION(11, 0, 11): |
| 2715 | 2680 | case IP_VERSION(11, 0, 12): |
| @@ -424,7 +424,6 @@ enum smu_reset_mode { · 423 unmodified lines | ||
| 424 | 424 | enum smu_baco_state { |
| 425 | 425 | SMU_BACO_STATE_ENTER = 0, |
| 426 | 426 | SMU_BACO_STATE_EXIT, |
| 427 | − SMU_BACO_STATE_NONE, | |
| 428 | 427 | }; |
| 429 | 428 | |
| 430 | 429 | struct smu_baco_context { |
| @@ -1442,10 +1442,12 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, · 1441 unmodified lines | ||
| 1442 | 1442 | case 0x3: |
| 1443 | 1443 | dev_dbg(adev->dev, "Switched to AC mode!\n"); |
| 1444 | 1444 | schedule_work(&smu->interrupt_work); |
| 1445 | + adev->pm.ac_power = true; | |
| 1445 | 1446 | break; |
| 1446 | 1447 | case 0x4: |
| 1447 | 1448 | dev_dbg(adev->dev, "Switched to DC mode!\n"); |
| 1448 | 1449 | schedule_work(&smu->interrupt_work); |
| 1450 | + adev->pm.ac_power = false; | |
| 1449 | 1451 | break; |
| 1450 | 1452 | case 0x7: |
| 1451 | 1453 | /* |
| @@ -1379,10 +1379,12 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev, · 1378 unmodified lines | ||
| 1379 | 1379 | case 0x3: |
| 1380 | 1380 | dev_dbg(adev->dev, "Switched to AC mode!\n"); |
| 1381 | 1381 | smu_v13_0_ack_ac_dc_interrupt(smu); |
| 1382 | + adev->pm.ac_power = true; | |
| 1382 | 1383 | break; |
| 1383 | 1384 | case 0x4: |
| 1384 | 1385 | dev_dbg(adev->dev, "Switched to DC mode!\n"); |
| 1385 | 1386 | smu_v13_0_ack_ac_dc_interrupt(smu); |
| 1387 | + adev->pm.ac_power = false; | |
| 1386 | 1388 | break; |
| 1387 | 1389 | case 0x7: |
| 1388 | 1390 | /* |
| @@ -2357,6 +2357,7 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu, · 2356 unmodified lines | ||
| 2357 | 2357 | PPTable_t *pptable = table_context->driver_pptable; |
| 2358 | 2358 | SkuTable_t *skutable = &pptable->SkuTable; |
| 2359 | 2359 | uint32_t power_limit, od_percent_upper, od_percent_lower; |
| 2360 | + uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; | |
| 2360 | 2361 | |
| 2361 | 2362 | if (smu_v13_0_get_current_power_limit(smu, &power_limit)) |
| 2362 | 2363 | power_limit = smu->adev->pm.ac_power ? |
| @@ -2380,7 +2381,7 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu, · 17 unmodified lines | ||
| 2380 | 2381 | od_percent_upper, od_percent_lower, power_limit); |
| 2381 | 2382 | |
| 2382 | 2383 | if (max_power_limit) { |
| 2383 | − *max_power_limit = power_limit * (100 + od_percent_upper); | |
| 2384 | + *max_power_limit = msg_limit * (100 + od_percent_upper); | |
| 2384 | 2385 | *max_power_limit /= 100; |
| 2385 | 2386 | } |
| 2386 | 2387 | |
| @@ -2747,13 +2748,7 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu, · 360 unmodified lines | ||
| 2747 | 2748 | |
| 2748 | 2749 | switch (mp1_state) { |
| 2749 | 2750 | case PP_MP1_STATE_UNLOAD: |
| 2750 | − ret = smu_cmn_send_smc_msg_with_param(smu, | |
| 2751 | − SMU_MSG_PrepareMp1ForUnload, | |
| 2752 | − 0x55, NULL); | |
| 2753 | − | |
| 2754 | − if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT) | |
| 2755 | − ret = smu_v13_0_disable_pmfw_state(smu); | |
| 2756 | − | |
| 2751 | + ret = smu_cmn_set_mp1_state(smu, mp1_state); | |
| 2757 | 2752 | break; |
| 2758 | 2753 | default: |
| 2759 | 2754 | /* Ignore others */ |
| @@ -2949,7 +2944,7 @@ static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu) · 189 unmodified lines | ||
| 2949 | 2944 | { |
| 2950 | 2945 | struct amdgpu_device *adev = smu->adev; |
| 2951 | 2946 | |
| 2952 | − switch (adev->ip_versions[MP1_HWIP][0]) { | |
| 2947 | + switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { | |
| 2953 | 2948 | case IP_VERSION(13, 0, 0): |
| 2954 | 2949 | return smu->smc_fw_version >= 0x004e6300; |
| 2955 | 2950 | case IP_VERSION(13, 0, 10): |
| @@ -2959,6 +2954,55 @@ static bool smu_v13_0_0_wbrf_support_check(struct smu_context *smu) · 3 unmodified lines | ||
| 2959 | 2954 | } |
| 2960 | 2955 | } |
| 2961 | 2956 | |
| 2957 | +static int smu_v13_0_0_set_power_limit(struct smu_context *smu, | |
| 2958 | + enum smu_ppt_limit_type limit_type, | |
| 2959 | + uint32_t limit) | |
| 2960 | +{ | |
| 2961 | + PPTable_t *pptable = smu->smu_table.driver_pptable; | |
| 2962 | + SkuTable_t *skutable = &pptable->SkuTable; | |
| 2963 | + uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; | |
| 2964 | + struct smu_table_context *table_context = &smu->smu_table; | |
| 2965 | + OverDriveTableExternal_t *od_table = | |
| 2966 | + (OverDriveTableExternal_t *)table_context->overdrive_table; | |
| 2967 | + int ret = 0; | |
| 2968 | + | |
| 2969 | + if (limit_type != SMU_DEFAULT_PPT_LIMIT) | |
| 2970 | + return -EINVAL; | |
| 2971 | + | |
| 2972 | + if (limit <= msg_limit) { | |
| 2973 | + if (smu->current_power_limit > msg_limit) { | |
| 2974 | + od_table->OverDriveTable.Ppt = 0; | |
| 2975 | + od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT; | |
| 2976 | + | |
| 2977 | + ret = smu_v13_0_0_upload_overdrive_table(smu, od_table); | |
| 2978 | + if (ret) { | |
| 2979 | + dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); | |
| 2980 | + return ret; | |
| 2981 | + } | |
| 2982 | + } | |
| 2983 | + return smu_v13_0_set_power_limit(smu, limit_type, limit); | |
| 2984 | + } else if (smu->od_enabled) { | |
| 2985 | + ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit); | |
| 2986 | + if (ret) | |
| 2987 | + return ret; | |
| 2988 | + | |
| 2989 | + od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100; | |
| 2990 | + od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT; | |
| 2991 | + | |
| 2992 | + ret = smu_v13_0_0_upload_overdrive_table(smu, od_table); | |
| 2993 | + if (ret) { | |
| 2994 | + dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); | |
| 2995 | + return ret; | |
| 2996 | + } | |
| 2997 | + | |
| 2998 | + smu->current_power_limit = limit; | |
| 2999 | + } else { | |
| 3000 | + return -EINVAL; | |
| 3001 | + } | |
| 3002 | + | |
| 3003 | + return 0; | |
| 3004 | +} | |
| 3005 | + | |
| 2962 | 3006 | static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { |
| 2963 | 3007 | .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask, |
| 2964 | 3008 | .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table, |
| @@ -3013,7 +3057,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { · 48 unmodified lines | ||
| 3013 | 3057 | .set_fan_control_mode = smu_v13_0_set_fan_control_mode, |
| 3014 | 3058 | .enable_mgpu_fan_boost = smu_v13_0_0_enable_mgpu_fan_boost, |
| 3015 | 3059 | .get_power_limit = smu_v13_0_0_get_power_limit, |
| 3016 | − .set_power_limit = smu_v13_0_set_power_limit, | |
| 3060 | + .set_power_limit = smu_v13_0_0_set_power_limit, | |
| 3017 | 3061 | .set_power_source = smu_v13_0_set_power_source, |
| 3018 | 3062 | .get_power_profile_mode = smu_v13_0_0_get_power_profile_mode, |
| 3019 | 3063 | .set_power_profile_mode = smu_v13_0_0_set_power_profile_mode, |
| @@ -160,8 +160,8 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU · 159 unmodified lines | ||
| 160 | 160 | MSG_MAP(GfxDriverResetRecovery, PPSMC_MSG_GfxDriverResetRecovery, 0), |
| 161 | 161 | MSG_MAP(GetMinGfxclkFrequency, PPSMC_MSG_GetMinGfxDpmFreq, 1), |
| 162 | 162 | MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxDpmFreq, 1), |
| 163 | − MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 0), | |
| 164 | − MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 0), | |
| 163 | + MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxClk, 1), | |
| 164 | + MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), | |
| 165 | 165 | MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareForDriverUnload, 0), |
| 166 | 166 | MSG_MAP(GetCTFLimit, PPSMC_MSG_GetCTFLimit, 0), |
| 167 | 167 | MSG_MAP(GetThermalLimit, PPSMC_MSG_ReadThrottlerLimit, 0), |
| @@ -2321,6 +2321,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu, · 2320 unmodified lines | ||
| 2321 | 2321 | PPTable_t *pptable = table_context->driver_pptable; |
| 2322 | 2322 | SkuTable_t *skutable = &pptable->SkuTable; |
| 2323 | 2323 | uint32_t power_limit, od_percent_upper, od_percent_lower; |
| 2324 | + uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; | |
| 2324 | 2325 | |
| 2325 | 2326 | if (smu_v13_0_get_current_power_limit(smu, &power_limit)) |
| 2326 | 2327 | power_limit = smu->adev->pm.ac_power ? |
| @@ -2344,7 +2345,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu, · 17 unmodified lines | ||
| 2344 | 2345 | od_percent_upper, od_percent_lower, power_limit); |
| 2345 | 2346 | |
| 2346 | 2347 | if (max_power_limit) { |
| 2347 | − *max_power_limit = power_limit * (100 + od_percent_upper); | |
| 2348 | + *max_power_limit = msg_limit * (100 + od_percent_upper); | |
| 2348 | 2349 | *max_power_limit /= 100; |
| 2349 | 2350 | } |
| 2350 | 2351 | |
| @@ -2504,13 +2505,7 @@ static int smu_v13_0_7_set_mp1_state(struct smu_context *smu, · 153 unmodified lines | ||
| 2504 | 2505 | |
| 2505 | 2506 | switch (mp1_state) { |
| 2506 | 2507 | case PP_MP1_STATE_UNLOAD: |
| 2507 | − ret = smu_cmn_send_smc_msg_with_param(smu, | |
| 2508 | − SMU_MSG_PrepareMp1ForUnload, | |
| 2509 | − 0x55, NULL); | |
| 2510 | − | |
| 2511 | − if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT) | |
| 2512 | − ret = smu_v13_0_disable_pmfw_state(smu); | |
| 2513 | − | |
| 2508 | + ret = smu_cmn_set_mp1_state(smu, mp1_state); | |
| 2514 | 2509 | break; |
| 2515 | 2510 | default: |
| 2516 | 2511 | /* Ignore others */ |
| @@ -2545,6 +2540,55 @@ static bool smu_v13_0_7_wbrf_support_check(struct smu_context *smu) · 28 unmodified lines | ||
| 2545 | 2540 | return smu->smc_fw_version > 0x00524600; |
| 2546 | 2541 | } |
| 2547 | 2542 | |
| 2543 | +static int smu_v13_0_7_set_power_limit(struct smu_context *smu, | |
| 2544 | + enum smu_ppt_limit_type limit_type, | |
| 2545 | + uint32_t limit) | |
| 2546 | +{ | |
| 2547 | + PPTable_t *pptable = smu->smu_table.driver_pptable; | |
| 2548 | + SkuTable_t *skutable = &pptable->SkuTable; | |
| 2549 | + uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; | |
| 2550 | + struct smu_table_context *table_context = &smu->smu_table; | |
| 2551 | + OverDriveTableExternal_t *od_table = | |
| 2552 | + (OverDriveTableExternal_t *)table_context->overdrive_table; | |
| 2553 | + int ret = 0; | |
| 2554 | + | |
| 2555 | + if (limit_type != SMU_DEFAULT_PPT_LIMIT) | |
| 2556 | + return -EINVAL; | |
| 2557 | + | |
| 2558 | + if (limit <= msg_limit) { | |
| 2559 | + if (smu->current_power_limit > msg_limit) { | |
| 2560 | + od_table->OverDriveTable.Ppt = 0; | |
| 2561 | + od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT; | |
| 2562 | + | |
| 2563 | + ret = smu_v13_0_7_upload_overdrive_table(smu, od_table); | |
| 2564 | + if (ret) { | |
| 2565 | + dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); | |
| 2566 | + return ret; | |
| 2567 | + } | |
| 2568 | + } | |
| 2569 | + return smu_v13_0_set_power_limit(smu, limit_type, limit); | |
| 2570 | + } else if (smu->od_enabled) { | |
| 2571 | + ret = smu_v13_0_set_power_limit(smu, limit_type, msg_limit); | |
| 2572 | + if (ret) | |
| 2573 | + return ret; | |
| 2574 | + | |
| 2575 | + od_table->OverDriveTable.Ppt = (limit * 100) / msg_limit - 100; | |
| 2576 | + od_table->OverDriveTable.FeatureCtrlMask |= 1U << PP_OD_FEATURE_PPT_BIT; | |
| 2577 | + | |
| 2578 | + ret = smu_v13_0_7_upload_overdrive_table(smu, od_table); | |
| 2579 | + if (ret) { | |
| 2580 | + dev_err(smu->adev->dev, "Failed to upload overdrive table!\n"); | |
| 2581 | + return ret; | |
| 2582 | + } | |
| 2583 | + | |
| 2584 | + smu->current_power_limit = limit; | |
| 2585 | + } else { | |
| 2586 | + return -EINVAL; | |
| 2587 | + } | |
| 2588 | + | |
| 2589 | + return 0; | |
| 2590 | +} | |
| 2591 | + | |
| 2548 | 2592 | static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { |
| 2549 | 2593 | .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask, |
| 2550 | 2594 | .set_default_dpm_table = smu_v13_0_7_set_default_dpm_table, |
| @@ -2596,7 +2640,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { · 45 unmodified lines | ||
| 2596 | 2640 | .set_fan_control_mode = smu_v13_0_set_fan_control_mode, |
| 2597 | 2641 | .enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost, |
| 2598 | 2642 | .get_power_limit = smu_v13_0_7_get_power_limit, |
| 2599 | − .set_power_limit = smu_v13_0_set_power_limit, | |
| 2643 | + .set_power_limit = smu_v13_0_7_set_power_limit, | |
| 2600 | 2644 | .set_power_source = smu_v13_0_set_power_source, |
| 2601 | 2645 | .get_power_profile_mode = smu_v13_0_7_get_power_profile_mode, |
| 2602 | 2646 | .set_power_profile_mode = smu_v13_0_7_set_power_profile_mode, |
| @@ -1762,6 +1762,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, · 1761 unmodified lines | ||
| 1762 | 1762 | u8 request = msg->request & ~DP_AUX_I2C_MOT; |
| 1763 | 1763 | int ret = 0; |
| 1764 | 1764 | |
| 1765 | + mutex_lock(&ctx->aux_lock); | |
| 1765 | 1766 | pm_runtime_get_sync(dev); |
| 1766 | 1767 | msg->reply = 0; |
| 1767 | 1768 | switch (request) { |
| @@ -1778,6 +1779,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, · 10 unmodified lines | ||
| 1778 | 1779 | msg->size, msg->buffer); |
| 1779 | 1780 | pm_runtime_mark_last_busy(dev); |
| 1780 | 1781 | pm_runtime_put_autosuspend(dev); |
| 1782 | + mutex_unlock(&ctx->aux_lock); | |
| 1781 | 1783 | |
| 1782 | 1784 | return ret; |
| 1783 | 1785 | } |
| @@ -2474,7 +2476,9 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge, · 690 unmodified lines | ||
| 2474 | 2476 | ctx->connector = NULL; |
| 2475 | 2477 | anx7625_dp_stop(ctx); |
| 2476 | 2478 | |
| 2477 | − pm_runtime_put_sync(dev); | |
| 2479 | + mutex_lock(&ctx->aux_lock); | |
| 2480 | + pm_runtime_put_sync_suspend(dev); | |
| 2481 | + mutex_unlock(&ctx->aux_lock); | |
| 2478 | 2482 | } |
| 2479 | 2483 | |
| 2480 | 2484 | static enum drm_connector_status |
| @@ -2668,6 +2672,7 @@ static int anx7625_i2c_probe(struct i2c_client *client) · 187 unmodified lines | ||
| 2668 | 2672 | |
| 2669 | 2673 | mutex_init(&platform->lock); |
| 2670 | 2674 | mutex_init(&platform->hdcp_wq_lock); |
| 2675 | + mutex_init(&platform->aux_lock); | |
| 2671 | 2676 | |
| 2672 | 2677 | INIT_DELAYED_WORK(&platform->hdcp_work, hdcp_check_work_func); |
| 2673 | 2678 | platform->hdcp_workqueue = create_workqueue("hdcp workqueue"); |
| @@ -475,6 +475,8 @@ struct anx7625_data { · 474 unmodified lines | ||
| 475 | 475 | struct workqueue_struct *hdcp_workqueue; |
| 476 | 476 | /* Lock for hdcp work queue */ |
| 477 | 477 | struct mutex hdcp_wq_lock; |
| 478 | + /* Lock for aux transfer and disable */ | |
| 479 | + struct mutex aux_lock; | |
| 478 | 480 | char edid_block; |
| 479 | 481 | struct display_timing dt; |
| 480 | 482 | u8 display_timing_valid; |
| @@ -107,6 +107,7 @@ struct ps8640 { · 106 unmodified lines | ||
| 107 | 107 | struct device_link *link; |
| 108 | 108 | bool pre_enabled; |
| 109 | 109 | bool need_post_hpd_delay; |
| 110 | + struct mutex aux_lock; | |
| 110 | 111 | }; |
| 111 | 112 | |
| 112 | 113 | static const struct regmap_config ps8640_regmap_config[] = { |
| @@ -345,11 +346,20 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, · 232 unmodified lines | ||
| 345 | 346 | struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev; |
| 346 | 347 | int ret; |
| 347 | 348 | |
| 349 | + mutex_lock(&ps_bridge->aux_lock); | |
| 348 | 350 | pm_runtime_get_sync(dev); |
| 351 | + ret = _ps8640_wait_hpd_asserted(ps_bridge, 200 * 1000); | |
| 352 | + if (ret) { | |
| 353 | + pm_runtime_put_sync_suspend(dev); | |
| 354 | + goto exit; | |
| 355 | + } | |
| 349 | 356 | ret = ps8640_aux_transfer_msg(aux, msg); |
| 350 | 357 | pm_runtime_mark_last_busy(dev); |
| 351 | 358 | pm_runtime_put_autosuspend(dev); |
| 352 | 359 | |
| 360 | +exit: | |
| 361 | + mutex_unlock(&ps_bridge->aux_lock); | |
| 362 | + | |
| 353 | 363 | return ret; |
| 354 | 364 | } |
| 355 | 365 | |
| @@ -470,7 +480,18 @@ static void ps8640_atomic_post_disable(struct drm_bridge *bridge, · 114 unmodified lines | ||
| 470 | 480 | ps_bridge->pre_enabled = false; |
| 471 | 481 | |
| 472 | 482 | ps8640_bridge_vdo_control(ps_bridge, DISABLE); |
| 483 | + | |
| 484 | + /* | |
| 485 | + * The bridge seems to expect everything to be power cycled at the | |
| 486 | + * disable process, so grab a lock here to make sure | |
| 487 | + * ps8640_aux_transfer() is not holding a runtime PM reference and | |
| 488 | + * preventing the bridge from suspend. | |
| 489 | + */ | |
| 490 | + mutex_lock(&ps_bridge->aux_lock); | |
| 491 | + | |
| 473 | 492 | pm_runtime_put_sync_suspend(&ps_bridge->page[PAGE0_DP_CNTL]->dev); |
| 493 | + | |
| 494 | + mutex_unlock(&ps_bridge->aux_lock); | |
| 474 | 495 | } |
| 475 | 496 | |
| 476 | 497 | static int ps8640_bridge_attach(struct drm_bridge *bridge, |
| @@ -619,6 +640,8 @@ static int ps8640_probe(struct i2c_client *client) · 142 unmodified lines | ||
| 619 | 640 | if (!ps_bridge) |
| 620 | 641 | return -ENOMEM; |
| 621 | 642 | |
| 643 | + mutex_init(&ps_bridge->aux_lock); | |
| 644 | + | |
| 622 | 645 | ps_bridge->supplies[0].supply = "vdd12"; |
| 623 | 646 | ps_bridge->supplies[1].supply = "vdd33"; |
| 624 | 647 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), |
| @@ -969,10 +969,6 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi) · 968 unmodified lines | ||
| 969 | 969 | reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); |
| 970 | 970 | reg &= ~DSIM_STOP_STATE_CNT_MASK; |
| 971 | 971 | reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]); |
| 972 | − | |
| 973 | − if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) | |
| 974 | − reg |= DSIM_FORCE_STOP_STATE; | |
| 975 | − | |
| 976 | 972 | samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg); |
| 977 | 973 | |
| 978 | 974 | reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff); |
| @@ -1431,18 +1427,6 @@ static void samsung_dsim_disable_irq(struct samsung_dsim *dsi) · 452 unmodified lines | ||
| 1431 | 1427 | disable_irq(dsi->irq); |
| 1432 | 1428 | } |
| 1433 | 1429 | |
| 1434 | −static void samsung_dsim_set_stop_state(struct samsung_dsim *dsi, bool enable) | |
| 1435 | −{ | |
| 1436 | − u32 reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); | |
| 1437 | − | |
| 1438 | − if (enable) | |
| 1439 | − reg |= DSIM_FORCE_STOP_STATE; | |
| 1440 | − else | |
| 1441 | − reg &= ~DSIM_FORCE_STOP_STATE; | |
| 1442 | − | |
| 1443 | − samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg); | |
| 1444 | −} | |
| 1445 | − | |
| 1446 | 1430 | static int samsung_dsim_init(struct samsung_dsim *dsi) |
| 1447 | 1431 | { |
| 1448 | 1432 | const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; |
| @@ -1492,9 +1476,6 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge, · 43 unmodified lines | ||
| 1492 | 1476 | ret = samsung_dsim_init(dsi); |
| 1493 | 1477 | if (ret) |
| 1494 | 1478 | return; |
| 1495 | − | |
| 1496 | − samsung_dsim_set_display_mode(dsi); | |
| 1497 | − samsung_dsim_set_display_enable(dsi, true); | |
| 1498 | 1479 | } |
| 1499 | 1480 | } |
| 1500 | 1481 | |
| @@ -1503,12 +1484,8 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge, · 2 unmodified lines | ||
| 1503 | 1484 | { |
| 1504 | 1485 | struct samsung_dsim *dsi = bridge_to_dsi(bridge); |
| 1505 | 1486 | |
| 1506 | − if (samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) { | |
| 1507 | − samsung_dsim_set_display_mode(dsi); | |
| 1508 | − samsung_dsim_set_display_enable(dsi, true); | |
| 1509 | − } else { | |
| 1510 | − samsung_dsim_set_stop_state(dsi, false); | |
| 1511 | − } | |
| 1487 | + samsung_dsim_set_display_mode(dsi); | |
| 1488 | + samsung_dsim_set_display_enable(dsi, true); | |
| 1512 | 1489 | |
| 1513 | 1490 | dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; |
| 1514 | 1491 | } |
| @@ -1521,9 +1498,6 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge, · 6 unmodified lines | ||
| 1521 | 1498 | if (!(dsi->state & DSIM_STATE_ENABLED)) |
| 1522 | 1499 | return; |
| 1523 | 1500 | |
| 1524 | − if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) | |
| 1525 | − samsung_dsim_set_stop_state(dsi, true); | |
| 1526 | − | |
| 1527 | 1501 | dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE; |
| 1528 | 1502 | } |
| 1529 | 1503 | |
| @@ -1828,8 +1802,6 @@ static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host, · 298 unmodified lines | ||
| 1828 | 1802 | if (ret) |
| 1829 | 1803 | return ret; |
| 1830 | 1804 | |
| 1831 | − samsung_dsim_set_stop_state(dsi, false); | |
| 1832 | − | |
| 1833 | 1805 | ret = mipi_dsi_create_packet(&xfer.packet, msg); |
| 1834 | 1806 | if (ret < 0) |
| 1835 | 1807 | return ret; |
| @@ -1080,6 +1080,26 @@ static int sii902x_init(struct sii902x *sii902x) · 1079 unmodified lines | ||
| 1080 | 1080 | return ret; |
| 1081 | 1081 | } |
| 1082 | 1082 | |
| 1083 | + ret = sii902x_audio_codec_init(sii902x, dev); | |
| 1084 | + if (ret) | |
| 1085 | + return ret; | |
| 1086 | + | |
| 1087 | + i2c_set_clientdata(sii902x->i2c, sii902x); | |
| 1088 | + | |
| 1089 | + sii902x->i2cmux = i2c_mux_alloc(sii902x->i2c->adapter, dev, | |
| 1090 | + 1, 0, I2C_MUX_GATE, | |
| 1091 | + sii902x_i2c_bypass_select, | |
| 1092 | + sii902x_i2c_bypass_deselect); | |
| 1093 | + if (!sii902x->i2cmux) { | |
| 1094 | + ret = -ENOMEM; | |
| 1095 | + goto err_unreg_audio; | |
| 1096 | + } | |
| 1097 | + | |
| 1098 | + sii902x->i2cmux->priv = sii902x; | |
| 1099 | + ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0); | |
| 1100 | + if (ret) | |
| 1101 | + goto err_unreg_audio; | |
| 1102 | + | |
| 1083 | 1103 | sii902x->bridge.funcs = &sii902x_bridge_funcs; |
| 1084 | 1104 | sii902x->bridge.of_node = dev->of_node; |
| 1085 | 1105 | sii902x->bridge.timings = &default_sii902x_timings; |
| @@ -1090,19 +1110,13 @@ static int sii902x_init(struct sii902x *sii902x) · 4 unmodified lines | ||
| 1090 | 1110 | |
| 1091 | 1111 | drm_bridge_add(&sii902x->bridge); |
| 1092 | 1112 | |
| 1093 | − sii902x_audio_codec_init(sii902x, dev); | |
| 1094 | − | |
| 1095 | − i2c_set_clientdata(sii902x->i2c, sii902x); | |
| 1113 | + return 0; | |
| 1096 | 1114 | |
| 1097 | − sii902x->i2cmux = i2c_mux_alloc(sii902x->i2c->adapter, dev, | |
| 1098 | − 1, 0, I2C_MUX_GATE, | |
| 1099 | − sii902x_i2c_bypass_select, | |
| 1100 | − sii902x_i2c_bypass_deselect); | |
| 1101 | − if (!sii902x->i2cmux) | |
| 1102 | − return -ENOMEM; | |
| 1115 | +err_unreg_audio: | |
| 1116 | + if (!PTR_ERR_OR_ZERO(sii902x->audio.pdev)) | |
| 1117 | + platform_device_unregister(sii902x->audio.pdev); | |
| 1103 | 1118 | |
| 1104 | − sii902x->i2cmux->priv = sii902x; | |
| 1105 | − return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0); | |
| 1119 | + return ret; | |
| 1106 | 1120 | } |
| 1107 | 1121 | |
| 1108 | 1122 | static int sii902x_probe(struct i2c_client *client) |
| @@ -1170,12 +1184,14 @@ static int sii902x_probe(struct i2c_client *client) · 61 unmodified lines | ||
| 1170 | 1184 | } |
| 1171 | 1185 | |
| 1172 | 1186 | static void sii902x_remove(struct i2c_client *client) |
| 1173 | − | |
| 1174 | 1187 | { |
| 1175 | 1188 | struct sii902x *sii902x = i2c_get_clientdata(client); |
| 1176 | 1189 | |
| 1177 | − i2c_mux_del_adapters(sii902x->i2cmux); | |
| 1178 | 1190 | drm_bridge_remove(&sii902x->bridge); |
| 1191 | + i2c_mux_del_adapters(sii902x->i2cmux); | |
| 1192 | + | |
| 1193 | + if (!PTR_ERR_OR_ZERO(sii902x->audio.pdev)) | |
| 1194 | + platform_device_unregister(sii902x->audio.pdev); | |
| 1179 | 1195 | } |
| 1180 | 1196 | |
| 1181 | 1197 | static const struct of_device_id sii902x_dt_ids[] = { |
| @@ -5491,6 +5491,7 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc); · 5490 unmodified lines | ||
| 5491 | 5491 | * - 0 if the new state is valid |
| 5492 | 5492 | * - %-ENOSPC, if the new state is invalid, because of BW limitation |
| 5493 | 5493 | * @failing_port is set to: |
| 5494 | + * | |
| 5494 | 5495 | * - The non-root port where a BW limit check failed |
| 5495 | 5496 | * with all the ports downstream of @failing_port passing |
| 5496 | 5497 | * the BW limit check. |
| @@ -5499,6 +5500,7 @@ EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc); · 2 unmodified lines | ||
| 5499 | 5500 | * - %NULL if the BW limit check failed at the root port |
| 5500 | 5501 | * with all the ports downstream of the root port passing |
| 5501 | 5502 | * the BW limit check. |
| 5503 | + * | |
| 5502 | 5504 | * - %-EINVAL, if the new state is invalid, because the root port has |
| 5503 | 5505 | * too many payloads. |
| 5504 | 5506 | */ |
| @@ -319,9 +319,9 @@ static void decon_win_set_bldmod(struct decon_context *ctx, unsigned int win, · 318 unmodified lines | ||
| 319 | 319 | static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, |
| 320 | 320 | struct drm_framebuffer *fb) |
| 321 | 321 | { |
| 322 | − struct exynos_drm_plane plane = ctx->planes[win]; | |
| 322 | + struct exynos_drm_plane *plane = &ctx->planes[win]; | |
| 323 | 323 | struct exynos_drm_plane_state *state = |
| 324 | − to_exynos_plane_state(plane.base.state); | |
| 324 | + to_exynos_plane_state(plane->base.state); | |
| 325 | 325 | unsigned int alpha = state->base.alpha; |
| 326 | 326 | unsigned int pixel_alpha; |
| 327 | 327 | unsigned long val; |
| @@ -480,7 +480,7 @@ static void fimd_commit(struct exynos_drm_crtc *crtc) · 479 unmodified lines | ||
| 480 | 480 | struct fimd_context *ctx = crtc->ctx; |
| 481 | 481 | struct drm_display_mode *mode = &crtc->base.state->adjusted_mode; |
| 482 | 482 | const struct fimd_driver_data *driver_data = ctx->driver_data; |
| 483 | − void *timing_base = ctx->regs + driver_data->timing_base; | |
| 483 | + void __iomem *timing_base = ctx->regs + driver_data->timing_base; | |
| 484 | 484 | u32 val; |
| 485 | 485 | |
| 486 | 486 | if (ctx->suspended) |
| @@ -661,9 +661,9 @@ static void fimd_win_set_bldmod(struct fimd_context *ctx, unsigned int win, · 174 unmodified lines | ||
| 661 | 661 | static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, |
| 662 | 662 | struct drm_framebuffer *fb, int width) |
| 663 | 663 | { |
| 664 | − struct exynos_drm_plane plane = ctx->planes[win]; | |
| 664 | + struct exynos_drm_plane *plane = &ctx->planes[win]; | |
| 665 | 665 | struct exynos_drm_plane_state *state = |
| 666 | − to_exynos_plane_state(plane.base.state); | |
| 666 | + to_exynos_plane_state(plane->base.state); | |
| 667 | 667 | uint32_t pixel_format = fb->format->format; |
| 668 | 668 | unsigned int alpha = state->base.alpha; |
| 669 | 669 | u32 val = WINCONx_ENWIN; |
| @@ -1341,7 +1341,7 @@ static int __maybe_unused gsc_runtime_resume(struct device *dev) · 1340 unmodified lines | ||
| 1341 | 1341 | for (i = 0; i < ctx->num_clocks; i++) { |
| 1342 | 1342 | ret = clk_prepare_enable(ctx->clocks[i]); |
| 1343 | 1343 | if (ret) { |
| 1344 | − while (--i > 0) | |
| 1344 | + while (--i >= 0) | |
| 1345 | 1345 | clk_disable_unprepare(ctx->clocks[i]); |
| 1346 | 1346 | return ret; |
| 1347 | 1347 | } |
| @@ -140,7 +140,7 @@ config DRM_I915_GVT_KVMGT · 139 unmodified lines | ||
| 140 | 140 | |
| 141 | 141 | Note that this driver only supports newer device from Broadwell on. |
| 142 | 142 | For further information and setup guide, you can visit: |
| 143 | − http://01.org/igvt-g. | |
| 143 | + https://github.com/intel/gvt-linux/wiki. | |
| 144 | 144 | |
| 145 | 145 | If in doubt, say "N". |
| 146 | 146 | |
| @@ -17,7 +17,6 @@ subdir-ccflags-y += $(call cc-option, -Wunused-const-variable) · 16 unmodified lines | ||
| 17 | 17 | subdir-ccflags-y += $(call cc-option, -Wpacked-not-aligned) |
| 18 | 18 | subdir-ccflags-y += $(call cc-option, -Wformat-overflow) |
| 19 | 19 | subdir-ccflags-y += $(call cc-option, -Wformat-truncation) |
| 20 | −subdir-ccflags-y += $(call cc-option, -Wstringop-overflow) | |
| 21 | 20 | subdir-ccflags-y += $(call cc-option, -Wstringop-truncation) |
| 22 | 21 | # The following turn off the warnings enabled by -Wextra |
| 23 | 22 | ifeq ($(findstring 2, $(KBUILD_EXTRA_WARN)),) |
| @@ -1155,6 +1155,7 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder) · 1154 unmodified lines | ||
| 1155 | 1155 | } |
| 1156 | 1156 | |
| 1157 | 1157 | intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP); |
| 1158 | + intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); | |
| 1158 | 1159 | |
| 1159 | 1160 | /* ensure all panel commands dispatched before enabling transcoder */ |
| 1160 | 1161 | wait_for_cmds_dispatched_to_panel(encoder); |
| @@ -1255,8 +1256,6 @@ static void gen11_dsi_enable(struct intel_atomic_state *state, · 94 unmodified lines | ||
| 1255 | 1256 | /* step6d: enable dsi transcoder */ |
| 1256 | 1257 | gen11_dsi_enable_transcoder(encoder); |
| 1257 | 1258 | |
| 1258 | − intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); | |
| 1259 | − | |
| 1260 | 1259 | /* step7: enable backlight */ |
| 1261 | 1260 | intel_backlight_enable(crtc_state, conn_state); |
| 1262 | 1261 | intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_ON); |
| @@ -1525,8 +1525,18 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, · 1524 unmodified lines | ||
| 1525 | 1525 | * can rely on frontbuffer tracking. |
| 1526 | 1526 | */ |
| 1527 | 1527 | mask = EDP_PSR_DEBUG_MASK_MEMUP | |
| 1528 | − EDP_PSR_DEBUG_MASK_HPD | | |
| 1529 | − EDP_PSR_DEBUG_MASK_LPSP; | |
| 1528 | + EDP_PSR_DEBUG_MASK_HPD; | |
| 1529 | + | |
| 1530 | + /* | |
| 1531 | + * For some unknown reason on HSW non-ULT (or at least on | |
| 1532 | + * Dell Latitude E6540) external displays start to flicker | |
| 1533 | + * when PSR is enabled on the eDP. SR/PC6 residency is much | |
| 1534 | + * higher than should be possible with an external display. | |
| 1535 | + * As a workaround leave LPSP unmasked to prevent PSR entry | |
| 1536 | + * when external displays are active. | |
| 1537 | + */ | |
| 1538 | + if (DISPLAY_VER(dev_priv) >= 8 || IS_HASWELL_ULT(dev_priv)) | |
| 1539 | + mask |= EDP_PSR_DEBUG_MASK_LPSP; | |
| 1530 | 1540 | |
| 1531 | 1541 | if (DISPLAY_VER(dev_priv) < 20) |
| 1532 | 1542 | mask |= EDP_PSR_DEBUG_MASK_MAX_SLEEP; |
| @@ -2849,8 +2849,7 @@ static int handle_mmio(struct intel_gvt_mmio_table_iter *iter, u32 offset, · 2848 unmodified lines | ||
| 2849 | 2849 | for (i = start; i < end; i += 4) { |
| 2850 | 2850 | p = intel_gvt_find_mmio_info(gvt, i); |
| 2851 | 2851 | if (p) { |
| 2852 | − WARN(1, "dup mmio definition offset %x\n", | |
| 2853 | − info->offset); | |
| 2852 | + WARN(1, "dup mmio definition offset %x\n", i); | |
| 2854 | 2853 | |
| 2855 | 2854 | /* We return -EEXIST here to make GVT-g load fail. |
| 2856 | 2855 | * So duplicated MMIO can be found as soon as |
| @@ -41,7 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | * To virtualize GPU resources GVT-g driver depends on hypervisor technology |
| 42 | 42 | * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability |
| 43 | 43 | * and be virtualized within GVT-g device module. More architectural design |
| 44 | − * doc is available on https://01.org/group/2230/documentation-list. | |
| 44 | + * doc is available on https://github.com/intel/gvt-linux/wiki. | |
| 45 | 45 | */ |
| 46 | 46 | |
| 47 | 47 | static LIST_HEAD(intel_gvt_devices); |
| @@ -144,10 +144,6 @@ enum dpu_enc_rc_states { · 143 unmodified lines | ||
| 144 | 144 | * to track crtc in the disable() hook which is called |
| 145 | 145 | * _after_ encoder_mask is cleared. |
| 146 | 146 | * @connector: If a mode is set, cached pointer to the active connector |
| 147 | − * @crtc_kickoff_cb: Callback into CRTC that will flush & start | |
| 148 | − * all CTL paths | |
| 149 | − * @crtc_kickoff_cb_data: Opaque user data given to crtc_kickoff_cb | |
| 150 | − * @debugfs_root: Debug file system root file node | |
| 151 | 147 | * @enc_lock: Lock around physical encoder |
| 152 | 148 | * create/destroy/enable/disable |
| 153 | 149 | * @frame_busy_mask: Bitmask tracking which phys_enc we are still |
| @@ -2072,7 +2068,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) · 1918 unmodified lines | ||
| 2072 | 2068 | } |
| 2073 | 2069 | |
| 2074 | 2070 | /* reset the merge 3D HW block */ |
| 2075 | − if (phys_enc->hw_pp->merge_3d) { | |
| 2071 | + if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) { | |
| 2076 | 2072 | phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d, |
| 2077 | 2073 | BLEND_3D_NONE); |
| 2078 | 2074 | if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d) |
| @@ -2103,7 +2099,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) · 24 unmodified lines | ||
| 2103 | 2099 | if (phys_enc->hw_wb) |
| 2104 | 2100 | intf_cfg.wb = phys_enc->hw_wb->idx; |
| 2105 | 2101 | |
| 2106 | − if (phys_enc->hw_pp->merge_3d) | |
| 2102 | + if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) | |
| 2107 | 2103 | intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; |
| 2108 | 2104 | |
| 2109 | 2105 | if (ctl->ops.reset_intf_cfg) |
| @@ -29,7 +29,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx, · 28 unmodified lines | ||
| 29 | 29 | /** |
| 30 | 30 | * struct dpu_rm_requirements - Reservation requirements parameter bundle |
| 31 | 31 | * @topology: selected topology for the display |
| 32 | − * @hw_res: Hardware resources required as reported by the encoders | |
| 33 | 32 | */ |
| 34 | 33 | struct dpu_rm_requirements { |
| 35 | 34 | struct msm_display_topology topology; |
| @@ -204,6 +203,8 @@ static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top) · 168 unmodified lines | ||
| 204 | 203 | * _dpu_rm_get_lm_peer - get the id of a mixer which is a peer of the primary |
| 205 | 204 | * @rm: dpu resource manager handle |
| 206 | 205 | * @primary_idx: index of primary mixer in rm->mixer_blks[] |
| 206 | + * | |
| 207 | + * Returns: lm peer mixed id on success or %-EINVAL on error | |
| 207 | 208 | */ |
| 208 | 209 | static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx) |
| 209 | 210 | { |
| @@ -135,11 +135,6 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl) · 134 unmodified lines | ||
| 135 | 135 | tbd = dp_link_get_test_bits_depth(ctrl->link, |
| 136 | 136 | ctrl->panel->dp_mode.bpp); |
| 137 | 137 | |
| 138 | − if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN) { | |
| 139 | − pr_debug("BIT_DEPTH not set. Configure default\n"); | |
| 140 | − tbd = DP_TEST_BIT_DEPTH_8; | |
| 141 | − } | |
| 142 | − | |
| 143 | 138 | config |= tbd << DP_CONFIGURATION_CTRL_BPC_SHIFT; |
| 144 | 139 | |
| 145 | 140 | /* Num of Lanes */ |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <drm/drm_print.h> |
| 9 | 9 | |
| 10 | +#include "dp_reg.h" | |
| 10 | 11 | #include "dp_link.h" |
| 11 | 12 | #include "dp_panel.h" |
| 12 | 13 | |
| @@ -1082,7 +1083,7 @@ int dp_link_process_request(struct dp_link *dp_link) · 1069 unmodified lines | ||
| 1082 | 1083 | |
| 1083 | 1084 | int dp_link_get_colorimetry_config(struct dp_link *dp_link) |
| 1084 | 1085 | { |
| 1085 | − u32 cc; | |
| 1086 | + u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB; | |
| 1086 | 1087 | struct dp_link_private *link; |
| 1087 | 1088 | |
| 1088 | 1089 | if (!dp_link) { |
| @@ -1096,10 +1097,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) · 7 unmodified lines | ||
| 1096 | 1097 | * Unless a video pattern CTS test is ongoing, use RGB_VESA |
| 1097 | 1098 | * Only RGB_VESA and RGB_CEA supported for now |
| 1098 | 1099 | */ |
| 1099 | − if (dp_link_is_video_pattern_requested(link)) | |
| 1100 | − cc = link->dp_link.test_video.test_dyn_range; | |
| 1101 | − else | |
| 1102 | − cc = DP_TEST_DYNAMIC_RANGE_VESA; | |
| 1100 | + if (dp_link_is_video_pattern_requested(link)) { | |
| 1101 | + if (link->dp_link.test_video.test_dyn_range & | |
| 1102 | + DP_TEST_DYNAMIC_RANGE_CEA) | |
| 1103 | + cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB; | |
| 1104 | + } | |
| 1103 | 1105 | |
| 1104 | 1106 | return cc; |
| 1105 | 1107 | } |
| @@ -1179,6 +1181,9 @@ void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link) · 73 unmodified lines | ||
| 1179 | 1181 | u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) |
| 1180 | 1182 | { |
| 1181 | 1183 | u32 tbd; |
| 1184 | + struct dp_link_private *link; | |
| 1185 | + | |
| 1186 | + link = container_of(dp_link, struct dp_link_private, dp_link); | |
| 1182 | 1187 | |
| 1183 | 1188 | /* |
| 1184 | 1189 | * Few simplistic rules and assumptions made here: |
| @@ -1196,12 +1201,13 @@ u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp) · 11 unmodified lines | ||
| 1196 | 1201 | tbd = DP_TEST_BIT_DEPTH_10; |
| 1197 | 1202 | break; |
| 1198 | 1203 | default: |
| 1199 | − tbd = DP_TEST_BIT_DEPTH_UNKNOWN; | |
| 1204 | + drm_dbg_dp(link->drm_dev, "bpp=%d not supported, use bpc=8\n", | |
| 1205 | + bpp); | |
| 1206 | + tbd = DP_TEST_BIT_DEPTH_8; | |
| 1200 | 1207 | break; |
| 1201 | 1208 | } |
| 1202 | 1209 | |
| 1203 | − if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN) | |
| 1204 | − tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); | |
| 1210 | + tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT); | |
| 1205 | 1211 | |
| 1206 | 1212 | return tbd; |
| 1207 | 1213 | } |
| @@ -143,6 +143,9 @@ · 142 unmodified lines | ||
| 143 | 143 | #define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x00000001) |
| 144 | 144 | #define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x00000005) |
| 145 | 145 | |
| 146 | +#define DP_MISC0_COLORIMERY_CFG_LEGACY_RGB (0) | |
| 147 | +#define DP_MISC0_COLORIMERY_CFG_CEA_RGB (0x04) | |
| 148 | + | |
| 146 | 149 | #define REG_DP_VALID_BOUNDARY (0x00000030) |
| 147 | 150 | #define REG_DP_VALID_BOUNDARY_2 (0x00000034) |
| 148 | 151 | |
| @@ -562,6 +562,7 @@ static const struct msm_mdss_data sdm670_data = { · 561 unmodified lines | ||
| 562 | 562 | .ubwc_enc_version = UBWC_2_0, |
| 563 | 563 | .ubwc_dec_version = UBWC_2_0, |
| 564 | 564 | .highest_bank_bit = 1, |
| 565 | + .reg_bus_bw = 76800, | |
| 565 | 566 | }; |
| 566 | 567 | |
| 567 | 568 | static const struct msm_mdss_data sdm845_data = { |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #define GSP_PAGE_SIZE BIT(GSP_PAGE_SHIFT) |
| 10 | 10 | |
| 11 | 11 | struct nvkm_gsp_mem { |
| 12 | − u32 size; | |
| 12 | + size_t size; | |
| 13 | 13 | void *data; |
| 14 | 14 | dma_addr_t addr; |
| 15 | 15 | }; |
| @@ -62,7 +62,7 @@ nouveau_fence_signal(struct nouveau_fence *fence) · 61 unmodified lines | ||
| 62 | 62 | if (test_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags)) { |
| 63 | 63 | struct nouveau_fence_chan *fctx = nouveau_fctx(fence); |
| 64 | 64 | |
| 65 | − if (atomic_dec_and_test(&fctx->notify_ref)) | |
| 65 | + if (!--fctx->notify_ref) | |
| 66 | 66 | drop = 1; |
| 67 | 67 | } |
| 68 | 68 | |
| @@ -103,7 +103,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) · 34 unmodified lines | ||
| 103 | 103 | void |
| 104 | 104 | nouveau_fence_context_del(struct nouveau_fence_chan *fctx) |
| 105 | 105 | { |
| 106 | − cancel_work_sync(&fctx->allow_block_work); | |
| 106 | + cancel_work_sync(&fctx->uevent_work); | |
| 107 | 107 | nouveau_fence_context_kill(fctx, 0); |
| 108 | 108 | nvif_event_dtor(&fctx->event); |
| 109 | 109 | fctx->dead = 1; |
| @@ -146,12 +146,13 @@ nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fc · 36 unmodified lines | ||
| 146 | 146 | return drop; |
| 147 | 147 | } |
| 148 | 148 | |
| 149 | −static int | |
| 150 | −nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc) | |
| 149 | +static void | |
| 150 | +nouveau_fence_uevent_work(struct work_struct *work) | |
| 151 | 151 | { |
| 152 | − struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event); | |
| 152 | + struct nouveau_fence_chan *fctx = container_of(work, struct nouveau_fence_chan, | |
| 153 | + uevent_work); | |
| 153 | 154 | unsigned long flags; |
| 154 | − int ret = NVIF_EVENT_KEEP; | |
| 155 | + int drop = 0; | |
| 155 | 156 | |
| 156 | 157 | spin_lock_irqsave(&fctx->lock, flags); |
| 157 | 158 | if (!list_empty(&fctx->pending)) { |
| @@ -161,23 +162,20 @@ nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc · 3 unmodified lines | ||
| 161 | 162 | fence = list_entry(fctx->pending.next, typeof(*fence), head); |
| 162 | 163 | chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock)); |
| 163 | 164 | if (nouveau_fence_update(chan, fctx)) |
| 164 | − ret = NVIF_EVENT_DROP; | |
| 165 | + drop = 1; | |
| 165 | 166 | } |
| 166 | − spin_unlock_irqrestore(&fctx->lock, flags); | |
| 167 | + if (drop) | |
| 168 | + nvif_event_block(&fctx->event); | |
| 167 | 169 | |
| 168 | − return ret; | |
| 170 | + spin_unlock_irqrestore(&fctx->lock, flags); | |
| 169 | 171 | } |
| 170 | 172 | |
| 171 | −static void | |
| 172 | −nouveau_fence_work_allow_block(struct work_struct *work) | |
| 173 | +static int | |
| 174 | +nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc) | |
| 173 | 175 | { |
| 174 | − struct nouveau_fence_chan *fctx = container_of(work, struct nouveau_fence_chan, | |
| 175 | − allow_block_work); | |
| 176 | − | |
| 177 | − if (atomic_read(&fctx->notify_ref) == 0) | |
| 178 | − nvif_event_block(&fctx->event); | |
| 179 | − else | |
| 180 | − nvif_event_allow(&fctx->event); | |
| 176 | + struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event); | |
| 177 | + schedule_work(&fctx->uevent_work); | |
| 178 | + return NVIF_EVENT_KEEP; | |
| 181 | 179 | } |
| 182 | 180 | |
| 183 | 181 | void |
| @@ -191,7 +189,7 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha · 7 unmodified lines | ||
| 191 | 189 | } args; |
| 192 | 190 | int ret; |
| 193 | 191 | |
| 194 | − INIT_WORK(&fctx->allow_block_work, nouveau_fence_work_allow_block); | |
| 192 | + INIT_WORK(&fctx->uevent_work, nouveau_fence_uevent_work); | |
| 195 | 193 | INIT_LIST_HEAD(&fctx->flip); |
| 196 | 194 | INIT_LIST_HEAD(&fctx->pending); |
| 197 | 195 | spin_lock_init(&fctx->lock); |
| @@ -535,19 +533,15 @@ static bool nouveau_fence_enable_signaling(struct dma_fence *f) · 337 unmodified lines | ||
| 535 | 533 | struct nouveau_fence *fence = from_fence(f); |
| 536 | 534 | struct nouveau_fence_chan *fctx = nouveau_fctx(fence); |
| 537 | 535 | bool ret; |
| 538 | − bool do_work; | |
| 539 | 536 | |
| 540 | − if (atomic_inc_return(&fctx->notify_ref) == 0) | |
| 541 | − do_work = true; | |
| 537 | + if (!fctx->notify_ref++) | |
| 538 | + nvif_event_allow(&fctx->event); | |
| 542 | 539 | |
| 543 | 540 | ret = nouveau_fence_no_signaling(f); |
| 544 | 541 | if (ret) |
| 545 | 542 | set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags); |
| 546 | − else if (atomic_dec_and_test(&fctx->notify_ref)) | |
| 547 | − do_work = true; | |
| 548 | − | |
| 549 | − if (do_work) | |
| 550 | − schedule_work(&fctx->allow_block_work); | |
| 543 | + else if (!--fctx->notify_ref) | |
| 544 | + nvif_event_block(&fctx->event); | |
| 551 | 545 | |
| 552 | 546 | return ret; |
| 553 | 547 | } |
| @@ -3,7 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | #define __NOUVEAU_FENCE_H__ |
| 4 | 4 | |
| 5 | 5 | #include <linux/dma-fence.h> |
| 6 | −#include <linux/workqueue.h> | |
| 7 | 6 | #include <nvif/event.h> |
| 8 | 7 | |
| 9 | 8 | struct nouveau_drm; |
| @@ -45,10 +44,9 @@ struct nouveau_fence_chan { · 35 unmodified lines | ||
| 45 | 44 | u32 context; |
| 46 | 45 | char name[32]; |
| 47 | 46 | |
| 47 | + struct work_struct uevent_work; | |
| 48 | 48 | struct nvif_event event; |
| 49 | − struct work_struct allow_block_work; | |
| 50 | − atomic_t notify_ref; | |
| 51 | − int dead, killed; | |
| 49 | + int notify_ref, dead, killed; | |
| 52 | 50 | }; |
| 53 | 51 | |
| 54 | 52 | struct nouveau_fence_priv { |
| @@ -997,6 +997,32 @@ r535_gsp_rpc_get_gsp_static_info(struct nvkm_gsp *gsp) · 996 unmodified lines | ||
| 997 | 997 | return 0; |
| 998 | 998 | } |
| 999 | 999 | |
| 1000 | +static void | |
| 1001 | +nvkm_gsp_mem_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_mem *mem) | |
| 1002 | +{ | |
| 1003 | + if (mem->data) { | |
| 1004 | + /* | |
| 1005 | + * Poison the buffer to catch any unexpected access from | |
| 1006 | + * GSP-RM if the buffer was prematurely freed. | |
| 1007 | + */ | |
| 1008 | + memset(mem->data, 0xFF, mem->size); | |
| 1009 | + | |
| 1010 | + dma_free_coherent(gsp->subdev.device->dev, mem->size, mem->data, mem->addr); | |
| 1011 | + memset(mem, 0, sizeof(*mem)); | |
| 1012 | + } | |
| 1013 | +} | |
| 1014 | + | |
| 1015 | +static int | |
| 1016 | +nvkm_gsp_mem_ctor(struct nvkm_gsp *gsp, size_t size, struct nvkm_gsp_mem *mem) | |
| 1017 | +{ | |
| 1018 | + mem->size = size; | |
| 1019 | + mem->data = dma_alloc_coherent(gsp->subdev.device->dev, size, &mem->addr, GFP_KERNEL); | |
| 1020 | + if (WARN_ON(!mem->data)) | |
| 1021 | + return -ENOMEM; | |
| 1022 | + | |
| 1023 | + return 0; | |
| 1024 | +} | |
| 1025 | + | |
| 1000 | 1026 | static int |
| 1001 | 1027 | r535_gsp_postinit(struct nvkm_gsp *gsp) |
| 1002 | 1028 | { |
| @@ -1024,6 +1050,13 @@ r535_gsp_postinit(struct nvkm_gsp *gsp) · 21 unmodified lines | ||
| 1024 | 1050 | |
| 1025 | 1051 | nvkm_inth_allow(&gsp->subdev.inth); |
| 1026 | 1052 | nvkm_wr32(device, 0x110004, 0x00000040); |
| 1053 | + | |
| 1054 | + /* Release the DMA buffers that were needed only for boot and init */ | |
| 1055 | + nvkm_gsp_mem_dtor(gsp, &gsp->boot.fw); | |
| 1056 | + nvkm_gsp_mem_dtor(gsp, &gsp->libos); | |
| 1057 | + nvkm_gsp_mem_dtor(gsp, &gsp->rmargs); | |
| 1058 | + nvkm_gsp_mem_dtor(gsp, &gsp->wpr_meta); | |
| 1059 | + | |
| 1027 | 1060 | return ret; |
| 1028 | 1061 | } |
| 1029 | 1062 | |
| @@ -1078,7 +1111,6 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) · 48 unmodified lines | ||
| 1078 | 1111 | if (IS_ERR(rpc)) |
| 1079 | 1112 | return PTR_ERR(rpc); |
| 1080 | 1113 | |
| 1081 | − rpc->size = sizeof(*rpc); | |
| 1082 | 1114 | rpc->numEntries = NV_GSP_REG_NUM_ENTRIES; |
| 1083 | 1115 | |
| 1084 | 1116 | str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]); |
| @@ -1094,6 +1126,7 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) · 9 unmodified lines | ||
| 1094 | 1126 | strings += name_len; |
| 1095 | 1127 | str_offset += name_len; |
| 1096 | 1128 | } |
| 1129 | + rpc->size = str_offset; | |
| 1097 | 1130 | |
| 1098 | 1131 | return nvkm_gsp_rpc_wr(gsp, rpc, false); |
| 1099 | 1132 | } |
| @@ -1532,27 +1565,6 @@ r535_gsp_msg_run_cpu_sequencer(void *priv, u32 fn, void *repv, u32 repc) · 432 unmodified lines | ||
| 1532 | 1565 | return 0; |
| 1533 | 1566 | } |
| 1534 | 1567 | |
| 1535 | −static void | |
| 1536 | −nvkm_gsp_mem_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_mem *mem) | |
| 1537 | −{ | |
| 1538 | − if (mem->data) { | |
| 1539 | − dma_free_coherent(gsp->subdev.device->dev, mem->size, mem->data, mem->addr); | |
| 1540 | − mem->data = NULL; | |
| 1541 | − } | |
| 1542 | −} | |
| 1543 | − | |
| 1544 | −static int | |
| 1545 | −nvkm_gsp_mem_ctor(struct nvkm_gsp *gsp, u32 size, struct nvkm_gsp_mem *mem) | |
| 1546 | −{ | |
| 1547 | − mem->size = size; | |
| 1548 | − mem->data = dma_alloc_coherent(gsp->subdev.device->dev, size, &mem->addr, GFP_KERNEL); | |
| 1549 | − if (WARN_ON(!mem->data)) | |
| 1550 | − return -ENOMEM; | |
| 1551 | − | |
| 1552 | − return 0; | |
| 1553 | −} | |
| 1554 | − | |
| 1555 | − | |
| 1556 | 1568 | static int |
| 1557 | 1569 | r535_gsp_booter_unload(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1) |
| 1558 | 1570 | { |
| @@ -1938,20 +1950,20 @@ nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3) · 379 unmodified lines | ||
| 1938 | 1950 | * See kgspCreateRadix3_IMPL |
| 1939 | 1951 | */ |
| 1940 | 1952 | static int |
| 1941 | −nvkm_gsp_radix3_sg(struct nvkm_device *device, struct sg_table *sgt, u64 size, | |
| 1953 | +nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size, | |
| 1942 | 1954 | struct nvkm_gsp_radix3 *rx3) |
| 1943 | 1955 | { |
| 1944 | 1956 | u64 addr; |
| 1945 | 1957 | |
| 1946 | 1958 | for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) { |
| 1947 | 1959 | u64 *ptes; |
| 1948 | − int idx; | |
| 1960 | + size_t bufsize; | |
| 1961 | + int ret, idx; | |
| 1949 | 1962 | |
| 1950 | − rx3->mem[i].size = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE); | |
| 1951 | − rx3->mem[i].data = dma_alloc_coherent(device->dev, rx3->mem[i].size, | |
| 1952 | − &rx3->mem[i].addr, GFP_KERNEL); | |
| 1953 | − if (WARN_ON(!rx3->mem[i].data)) | |
| 1954 | − return -ENOMEM; | |
| 1963 | + bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE); | |
| 1964 | + ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]); | |
| 1965 | + if (ret) | |
| 1966 | + return ret; | |
| 1955 | 1967 | |
| 1956 | 1968 | ptes = rx3->mem[i].data; |
| 1957 | 1969 | if (i == 2) { |
| @@ -1991,7 +2003,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend) · 33 unmodified lines | ||
| 1991 | 2003 | if (ret) |
| 1992 | 2004 | return ret; |
| 1993 | 2005 | |
| 1994 | − ret = nvkm_gsp_radix3_sg(gsp->subdev.device, &gsp->sr.sgt, len, &gsp->sr.radix3); | |
| 2006 | + ret = nvkm_gsp_radix3_sg(gsp, &gsp->sr.sgt, len, &gsp->sr.radix3); | |
| 1995 | 2007 | if (ret) |
| 1996 | 2008 | return ret; |
| 1997 | 2009 | |
| @@ -2150,6 +2162,11 @@ r535_gsp_dtor(struct nvkm_gsp *gsp) · 152 unmodified lines | ||
| 2150 | 2162 | mutex_destroy(&gsp->cmdq.mutex); |
| 2151 | 2163 | |
| 2152 | 2164 | r535_gsp_dtor_fws(gsp); |
| 2165 | + | |
| 2166 | + nvkm_gsp_mem_dtor(gsp, &gsp->shm.mem); | |
| 2167 | + nvkm_gsp_mem_dtor(gsp, &gsp->loginit); | |
| 2168 | + nvkm_gsp_mem_dtor(gsp, &gsp->logintr); | |
| 2169 | + nvkm_gsp_mem_dtor(gsp, &gsp->logrm); | |
| 2153 | 2170 | } |
| 2154 | 2171 | |
| 2155 | 2172 | int |
| @@ -2194,7 +2211,7 @@ r535_gsp_oneinit(struct nvkm_gsp *gsp) · 38 unmodified lines | ||
| 2194 | 2211 | memcpy(gsp->sig.data, data, size); |
| 2195 | 2212 | |
| 2196 | 2213 | /* Build radix3 page table for ELF image. */ |
| 2197 | − ret = nvkm_gsp_radix3_sg(device, &gsp->fw.mem.sgt, gsp->fw.len, &gsp->radix3); | |
| 2214 | + ret = nvkm_gsp_radix3_sg(gsp, &gsp->fw.mem.sgt, gsp->fw.len, &gsp->radix3); | |
| 2198 | 2215 | if (ret) |
| 2199 | 2216 | return ret; |
| 2200 | 2217 | |
| @@ -539,6 +539,8 @@ config DRM_PANEL_RAYDIUM_RM692E5 · 538 unmodified lines | ||
| 539 | 539 | depends on OF |
| 540 | 540 | depends on DRM_MIPI_DSI |
| 541 | 541 | depends on BACKLIGHT_CLASS_DEVICE |
| 542 | + select DRM_DISPLAY_DP_HELPER | |
| 543 | + select DRM_DISPLAY_HELPER | |
| 542 | 544 | help |
| 543 | 545 | Say Y here if you want to enable support for Raydium RM692E5-based |
| 544 | 546 | display panels, such as the one found in the Fairphone 5 smartphone. |
| @@ -309,7 +309,7 @@ static const struct s6d7aa0_panel_desc s6d7aa0_lsl080al02_desc = { · 308 unmodified lines | ||
| 309 | 309 | .off_func = s6d7aa0_lsl080al02_off, |
| 310 | 310 | .drm_mode = &s6d7aa0_lsl080al02_mode, |
| 311 | 311 | .mode_flags = MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_NO_HFP, |
| 312 | − .bus_flags = DRM_BUS_FLAG_DE_HIGH, | |
| 312 | + .bus_flags = 0, | |
| 313 | 313 | |
| 314 | 314 | .has_backlight = false, |
| 315 | 315 | .use_passwd3 = false, |
| @@ -3948,6 +3948,7 @@ static const struct panel_desc tianma_tm070jdhg30 = { · 3947 unmodified lines | ||
| 3948 | 3948 | }, |
| 3949 | 3949 | .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, |
| 3950 | 3950 | .connector_type = DRM_MODE_CONNECTOR_LVDS, |
| 3951 | + .bus_flags = DRM_BUS_FLAG_DE_HIGH, | |
| 3951 | 3952 | }; |
| 3952 | 3953 | |
| 3953 | 3954 | static const struct panel_desc tianma_tm070jvhg33 = { |
| @@ -3960,6 +3961,7 @@ static const struct panel_desc tianma_tm070jvhg33 = { · 6 unmodified lines | ||
| 3960 | 3961 | }, |
| 3961 | 3962 | .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, |
| 3962 | 3963 | .connector_type = DRM_MODE_CONNECTOR_LVDS, |
| 3964 | + .bus_flags = DRM_BUS_FLAG_DE_HIGH, | |
| 3963 | 3965 | }; |
| 3964 | 3966 | |
| 3965 | 3967 | static const struct display_timing tianma_tm070rvhg71_timing = { |
| @@ -1184,14 +1184,16 @@ static void drm_sched_run_job_work(struct work_struct *w) · 1183 unmodified lines | ||
| 1184 | 1184 | if (READ_ONCE(sched->pause_submit)) |
| 1185 | 1185 | return; |
| 1186 | 1186 | |
| 1187 | + /* Find entity with a ready job */ | |
| 1187 | 1188 | entity = drm_sched_select_entity(sched); |
| 1188 | 1189 | if (!entity) |
| 1189 | − return; | |
| 1190 | + return; /* No more work */ | |
| 1190 | 1191 | |
| 1191 | 1192 | sched_job = drm_sched_entity_pop_job(entity); |
| 1192 | 1193 | if (!sched_job) { |
| 1193 | 1194 | complete_all(&entity->entity_idle); |
| 1194 | − return; /* No more work */ | |
| 1195 | + drm_sched_run_job_queue(sched); | |
| 1196 | + return; | |
| 1195 | 1197 | } |
| 1196 | 1198 | |
| 1197 | 1199 | s_fence = sched_job->s_fence; |
| @@ -960,7 +960,8 @@ int host1x_client_iommu_attach(struct host1x_client *client) · 959 unmodified lines | ||
| 960 | 960 | * not the shared IOMMU domain, don't try to attach it to a different |
| 961 | 961 | * domain. This allows using the IOMMU-backed DMA API. |
| 962 | 962 | */ |
| 963 | − if (domain && domain != tegra->domain) | |
| 963 | + if (domain && domain->type != IOMMU_DOMAIN_IDENTITY && | |
| 964 | + domain != tegra->domain) | |
| 964 | 965 | return 0; |
| 965 | 966 | |
| 966 | 967 | if (tegra->domain) { |
| @@ -188,13 +188,13 @@ out: · 187 unmodified lines | ||
| 188 | 188 | |
| 189 | 189 | static void drm_test_mm_debug(struct kunit *test) |
| 190 | 190 | { |
| 191 | + struct drm_printer p = drm_debug_printer(test->name); | |
| 191 | 192 | struct drm_mm mm; |
| 192 | 193 | struct drm_mm_node nodes[2]; |
| 193 | 194 | |
| 194 | 195 | /* Create a small drm_mm with a couple of nodes and a few holes, and |
| 195 | 196 | * check that the debug iterator doesn't explode over a trivial drm_mm. |
| 196 | 197 | */ |
| 197 | − | |
| 198 | 198 | drm_mm_init(&mm, 0, 4096); |
| 199 | 199 | |
| 200 | 200 | memset(nodes, 0, sizeof(nodes)); |
| @@ -209,6 +209,9 @@ static void drm_test_mm_debug(struct kunit *test) · 8 unmodified lines | ||
| 209 | 209 | KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[1]), |
| 210 | 210 | "failed to reserve node[0] {start=%lld, size=%lld)\n", |
| 211 | 211 | nodes[0].start, nodes[0].size); |
| 212 | + | |
| 213 | + drm_mm_print(&mm, &p); | |
| 214 | + KUNIT_SUCCEED(test); | |
| 212 | 215 | } |
| 213 | 216 | |
| 214 | 217 | static bool expect_insert(struct kunit *test, struct drm_mm *mm, |
| @@ -95,11 +95,17 @@ static int ttm_global_init(void) · 94 unmodified lines | ||
| 95 | 95 | ttm_pool_mgr_init(num_pages); |
| 96 | 96 | ttm_tt_mgr_init(num_pages, num_dma32); |
| 97 | 97 | |
| 98 | − glob->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32); | |
| 98 | + glob->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32 | | |
| 99 | + __GFP_NOWARN); | |
| 99 | 100 | |
| 101 | + /* Retry without GFP_DMA32 for platforms DMA32 is not available */ | |
| 100 | 102 | if (unlikely(glob->dummy_read_page == NULL)) { |
| 101 | − ret = -ENOMEM; | |
| 102 | − goto out; | |
| 103 | + glob->dummy_read_page = alloc_page(__GFP_ZERO); | |
| 104 | + if (unlikely(glob->dummy_read_page == NULL)) { | |
| 105 | + ret = -ENOMEM; | |
| 106 | + goto out; | |
| 107 | + } | |
| 108 | + pr_warn("Using GFP_DMA32 fallback for dummy_read_page\n"); | |
| 103 | 109 | } |
| 104 | 110 | |
| 105 | 111 | INIT_LIST_HEAD(&glob->device_list); |
| @@ -195,7 +201,7 @@ int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *func · 89 unmodified lines | ||
| 195 | 201 | bool use_dma_alloc, bool use_dma32) |
| 196 | 202 | { |
| 197 | 203 | struct ttm_global *glob = &ttm_glob; |
| 198 | − int ret; | |
| 204 | + int ret, nid; | |
| 199 | 205 | |
| 200 | 206 | if (WARN_ON(vma_manager == NULL)) |
| 201 | 207 | return -EINVAL; |
| @@ -215,7 +221,12 @@ int ttm_device_init(struct ttm_device *bdev, const struct ttm_device_funcs *func · 13 unmodified lines | ||
| 215 | 221 | |
| 216 | 222 | ttm_sys_man_init(bdev); |
| 217 | 223 | |
| 218 | − ttm_pool_init(&bdev->pool, dev, dev_to_node(dev), use_dma_alloc, use_dma32); | |
| 224 | + if (dev) | |
| 225 | + nid = dev_to_node(dev); | |
| 226 | + else | |
| 227 | + nid = NUMA_NO_NODE; | |
| 228 | + | |
| 229 | + ttm_pool_init(&bdev->pool, dev, nid, use_dma_alloc, use_dma32); | |
| 219 | 230 | |
| 220 | 231 | bdev->vma_manager = vma_manager; |
| 221 | 232 | spin_lock_init(&bdev->lru_lock); |
| @@ -147,6 +147,13 @@ v3d_job_allocate(void **container, size_t size) · 146 unmodified lines | ||
| 147 | 147 | return 0; |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | +static void | |
| 151 | +v3d_job_deallocate(void **container) | |
| 152 | +{ | |
| 153 | + kfree(*container); | |
| 154 | + *container = NULL; | |
| 155 | +} | |
| 156 | + | |
| 150 | 157 | static int |
| 151 | 158 | v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, |
| 152 | 159 | struct v3d_job *job, void (*free)(struct kref *ref), |
| @@ -273,8 +280,10 @@ v3d_setup_csd_jobs_and_bos(struct drm_file *file_priv, · 120 unmodified lines | ||
| 273 | 280 | |
| 274 | 281 | ret = v3d_job_init(v3d, file_priv, &(*job)->base, |
| 275 | 282 | v3d_job_free, args->in_sync, se, V3D_CSD); |
| 276 | − if (ret) | |
| 283 | + if (ret) { | |
| 284 | + v3d_job_deallocate((void *)job); | |
| 277 | 285 | return ret; |
| 286 | + } | |
| 278 | 287 | |
| 279 | 288 | ret = v3d_job_allocate((void *)clean_job, sizeof(**clean_job)); |
| 280 | 289 | if (ret) |
| @@ -282,8 +291,10 @@ v3d_setup_csd_jobs_and_bos(struct drm_file *file_priv, · 1 unmodified line | ||
| 282 | 291 | |
| 283 | 292 | ret = v3d_job_init(v3d, file_priv, *clean_job, |
| 284 | 293 | v3d_job_free, 0, NULL, V3D_CACHE_CLEAN); |
| 285 | − if (ret) | |
| 294 | + if (ret) { | |
| 295 | + v3d_job_deallocate((void *)clean_job); | |
| 286 | 296 | return ret; |
| 297 | + } | |
| 287 | 298 | |
| 288 | 299 | (*job)->args = *args; |
| 289 | 300 | |
| @@ -860,8 +871,10 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 570 unmodified lines | ||
| 860 | 871 | |
| 861 | 872 | ret = v3d_job_init(v3d, file_priv, &render->base, |
| 862 | 873 | v3d_render_job_free, args->in_sync_rcl, &se, V3D_RENDER); |
| 863 | − if (ret) | |
| 874 | + if (ret) { | |
| 875 | + v3d_job_deallocate((void *)&render); | |
| 864 | 876 | goto fail; |
| 877 | + } | |
| 865 | 878 | |
| 866 | 879 | render->start = args->rcl_start; |
| 867 | 880 | render->end = args->rcl_end; |
| @@ -874,8 +887,10 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 6 unmodified lines | ||
| 874 | 887 | |
| 875 | 888 | ret = v3d_job_init(v3d, file_priv, &bin->base, |
| 876 | 889 | v3d_job_free, args->in_sync_bcl, &se, V3D_BIN); |
| 877 | − if (ret) | |
| 890 | + if (ret) { | |
| 891 | + v3d_job_deallocate((void *)&bin); | |
| 878 | 892 | goto fail; |
| 893 | + } | |
| 879 | 894 | |
| 880 | 895 | bin->start = args->bcl_start; |
| 881 | 896 | bin->end = args->bcl_end; |
| @@ -892,8 +907,10 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data, · 10 unmodified lines | ||
| 892 | 907 | |
| 893 | 908 | ret = v3d_job_init(v3d, file_priv, clean_job, |
| 894 | 909 | v3d_job_free, 0, NULL, V3D_CACHE_CLEAN); |
| 895 | − if (ret) | |
| 910 | + if (ret) { | |
| 911 | + v3d_job_deallocate((void *)&clean_job); | |
| 896 | 912 | goto fail; |
| 913 | + } | |
| 897 | 914 | |
| 898 | 915 | last_job = clean_job; |
| 899 | 916 | } else { |
| @@ -1015,8 +1032,10 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, · 115 unmodified lines | ||
| 1015 | 1032 | |
| 1016 | 1033 | ret = v3d_job_init(v3d, file_priv, &job->base, |
| 1017 | 1034 | v3d_job_free, args->in_sync, &se, V3D_TFU); |
| 1018 | − if (ret) | |
| 1035 | + if (ret) { | |
| 1036 | + v3d_job_deallocate((void *)&job); | |
| 1019 | 1037 | goto fail; |
| 1038 | + } | |
| 1020 | 1039 | |
| 1021 | 1040 | job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles), |
| 1022 | 1041 | sizeof(*job->base.bo), GFP_KERNEL); |
| @@ -1233,8 +1252,10 @@ v3d_submit_cpu_ioctl(struct drm_device *dev, void *data, · 210 unmodified lines | ||
| 1233 | 1252 | |
| 1234 | 1253 | ret = v3d_job_init(v3d, file_priv, &cpu_job->base, |
| 1235 | 1254 | v3d_job_free, 0, &se, V3D_CPU); |
| 1236 | − if (ret) | |
| 1255 | + if (ret) { | |
| 1256 | + v3d_job_deallocate((void *)&cpu_job); | |
| 1237 | 1257 | goto fail; |
| 1258 | + } | |
| 1238 | 1259 | |
| 1239 | 1260 | clean_job = cpu_job->indirect_csd.clean_job; |
| 1240 | 1261 | csd_job = cpu_job->indirect_csd.job; |
| @@ -94,6 +94,7 @@ static int virtio_gpu_probe(struct virtio_device *vdev) · 93 unmodified lines | ||
| 94 | 94 | goto err_free; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | + dma_set_max_seg_size(dev->dev, dma_max_mapping_size(dev->dev) ?: UINT_MAX); | |
| 97 | 98 | ret = virtio_gpu_init(vdev, dev); |
| 98 | 99 | if (ret) |
| 99 | 100 | goto err_free; |
| @@ -50,8 +50,8 @@ · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_LEN (GUC_HXG_REQUEST_MSG_MIN_LEN + 3u) |
| 52 | 52 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0 |
| 53 | −#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_KEY (0xffff << 16) | |
| 54 | −#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_LEN (0xffff << 0) | |
| 53 | +#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_KEY (0xffffu << 16) | |
| 54 | +#define HOST2GUC_SELF_CFG_REQUEST_MSG_1_KLV_LEN (0xffffu << 0) | |
| 55 | 55 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_2_VALUE32 GUC_HXG_REQUEST_MSG_n_DATAn |
| 56 | 56 | #define HOST2GUC_SELF_CFG_REQUEST_MSG_3_VALUE64 GUC_HXG_REQUEST_MSG_n_DATAn |
| 57 | 57 | |
| @@ -242,8 +242,8 @@ struct slpc_shared_data { · 241 unmodified lines | ||
| 242 | 242 | (HOST2GUC_PC_SLPC_REQUEST_REQUEST_MSG_MIN_LEN + \ |
| 243 | 243 | HOST2GUC_PC_SLPC_EVENT_MAX_INPUT_ARGS) |
| 244 | 244 | #define HOST2GUC_PC_SLPC_REQUEST_MSG_0_MBZ GUC_HXG_REQUEST_MSG_0_DATA0 |
| 245 | −#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID (0xff << 8) | |
| 246 | −#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC (0xff << 0) | |
| 245 | +#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ID (0xffu << 8) | |
| 246 | +#define HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC (0xffu << 0) | |
| 247 | 247 | #define HOST2GUC_PC_SLPC_REQUEST_MSG_N_EVENT_DATA_N GUC_HXG_REQUEST_MSG_n_DATAn |
| 248 | 248 | |
| 249 | 249 | #endif |
| @@ -82,11 +82,11 @@ static_assert(sizeof(struct guc_ct_buffer_desc) == 64); · 81 unmodified lines | ||
| 82 | 82 | #define GUC_CTB_HDR_LEN 1u |
| 83 | 83 | #define GUC_CTB_MSG_MIN_LEN GUC_CTB_HDR_LEN |
| 84 | 84 | #define GUC_CTB_MSG_MAX_LEN 256u |
| 85 | −#define GUC_CTB_MSG_0_FENCE (0xffff << 16) | |
| 86 | −#define GUC_CTB_MSG_0_FORMAT (0xf << 12) | |
| 85 | +#define GUC_CTB_MSG_0_FENCE (0xffffu << 16) | |
| 86 | +#define GUC_CTB_MSG_0_FORMAT (0xfu << 12) | |
| 87 | 87 | #define GUC_CTB_FORMAT_HXG 0u |
| 88 | −#define GUC_CTB_MSG_0_RESERVED (0xf << 8) | |
| 89 | −#define GUC_CTB_MSG_0_NUM_DWORDS (0xff << 0) | |
| 88 | +#define GUC_CTB_MSG_0_RESERVED (0xfu << 8) | |
| 89 | +#define GUC_CTB_MSG_0_NUM_DWORDS (0xffu << 0) | |
| 90 | 90 | |
| 91 | 91 | /** |
| 92 | 92 | * DOC: CTB HXG Message |
| @@ -31,9 +31,9 @@ · 30 unmodified lines | ||
| 31 | 31 | */ |
| 32 | 32 | |
| 33 | 33 | #define GUC_KLV_LEN_MIN 1u |
| 34 | −#define GUC_KLV_0_KEY (0xffff << 16) | |
| 35 | −#define GUC_KLV_0_LEN (0xffff << 0) | |
| 36 | −#define GUC_KLV_n_VALUE (0xffffffff << 0) | |
| 34 | +#define GUC_KLV_0_KEY (0xffffu << 16) | |
| 35 | +#define GUC_KLV_0_LEN (0xffffu << 0) | |
| 36 | +#define GUC_KLV_n_VALUE (0xffffffffu << 0) | |
| 37 | 37 | |
| 38 | 38 | /** |
| 39 | 39 | * DOC: GuC Self Config KLVs |
| @@ -40,18 +40,18 @@ · 39 unmodified lines | ||
| 40 | 40 | */ |
| 41 | 41 | |
| 42 | 42 | #define GUC_HXG_MSG_MIN_LEN 1u |
| 43 | −#define GUC_HXG_MSG_0_ORIGIN (0x1 << 31) | |
| 43 | +#define GUC_HXG_MSG_0_ORIGIN (0x1u << 31) | |
| 44 | 44 | #define GUC_HXG_ORIGIN_HOST 0u |
| 45 | 45 | #define GUC_HXG_ORIGIN_GUC 1u |
| 46 | −#define GUC_HXG_MSG_0_TYPE (0x7 << 28) | |
| 46 | +#define GUC_HXG_MSG_0_TYPE (0x7u << 28) | |
| 47 | 47 | #define GUC_HXG_TYPE_REQUEST 0u |
| 48 | 48 | #define GUC_HXG_TYPE_EVENT 1u |
| 49 | 49 | #define GUC_HXG_TYPE_NO_RESPONSE_BUSY 3u |
| 50 | 50 | #define GUC_HXG_TYPE_NO_RESPONSE_RETRY 5u |
| 51 | 51 | #define GUC_HXG_TYPE_RESPONSE_FAILURE 6u |
| 52 | 52 | #define GUC_HXG_TYPE_RESPONSE_SUCCESS 7u |
| 53 | −#define GUC_HXG_MSG_0_AUX (0xfffffff << 0) | |
| 54 | −#define GUC_HXG_MSG_n_PAYLOAD (0xffffffff << 0) | |
| 53 | +#define GUC_HXG_MSG_0_AUX (0xfffffffu << 0) | |
| 54 | +#define GUC_HXG_MSG_n_PAYLOAD (0xffffffffu << 0) | |
| 55 | 55 | |
| 56 | 56 | /** |
| 57 | 57 | * DOC: HXG Request |
| @@ -85,8 +85,8 @@ · 27 unmodified lines | ||
| 85 | 85 | */ |
| 86 | 86 | |
| 87 | 87 | #define GUC_HXG_REQUEST_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN |
| 88 | −#define GUC_HXG_REQUEST_MSG_0_DATA0 (0xfff << 16) | |
| 89 | −#define GUC_HXG_REQUEST_MSG_0_ACTION (0xffff << 0) | |
| 88 | +#define GUC_HXG_REQUEST_MSG_0_DATA0 (0xfffu << 16) | |
| 89 | +#define GUC_HXG_REQUEST_MSG_0_ACTION (0xffffu << 0) | |
| 90 | 90 | #define GUC_HXG_REQUEST_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD |
| 91 | 91 | |
| 92 | 92 | /** |
| @@ -117,8 +117,8 @@ · 24 unmodified lines | ||
| 117 | 117 | */ |
| 118 | 118 | |
| 119 | 119 | #define GUC_HXG_EVENT_MSG_MIN_LEN GUC_HXG_MSG_MIN_LEN |
| 120 | −#define GUC_HXG_EVENT_MSG_0_DATA0 (0xfff << 16) | |
| 121 | −#define GUC_HXG_EVENT_MSG_0_ACTION (0xffff << 0) | |
| 120 | +#define GUC_HXG_EVENT_MSG_0_DATA0 (0xfffu << 16) | |
| 121 | +#define GUC_HXG_EVENT_MSG_0_ACTION (0xffffu << 0) | |
| 122 | 122 | #define GUC_HXG_EVENT_MSG_n_DATAn GUC_HXG_MSG_n_PAYLOAD |
| 123 | 123 | |
| 124 | 124 | /** |
| @@ -188,8 +188,8 @@ · 63 unmodified lines | ||
| 188 | 188 | */ |
| 189 | 189 | |
| 190 | 190 | #define GUC_HXG_FAILURE_MSG_LEN GUC_HXG_MSG_MIN_LEN |
| 191 | −#define GUC_HXG_FAILURE_MSG_0_HINT (0xfff << 16) | |
| 192 | −#define GUC_HXG_FAILURE_MSG_0_ERROR (0xffff << 0) | |
| 191 | +#define GUC_HXG_FAILURE_MSG_0_HINT (0xfffu << 16) | |
| 192 | +#define GUC_HXG_FAILURE_MSG_0_ERROR (0xffffu << 0) | |
| 193 | 193 | |
| 194 | 194 | /** |
| 195 | 195 | * DOC: HXG Response |
| @@ -35,12 +35,10 @@ static inline int i915_gem_object_read_from_page(struct xe_bo *bo, · 34 unmodified lines | ||
| 35 | 35 | u32 ofs, u64 *ptr, u32 size) |
| 36 | 36 | { |
| 37 | 37 | struct ttm_bo_kmap_obj map; |
| 38 | − void *virtual; | |
| 38 | + void *src; | |
| 39 | 39 | bool is_iomem; |
| 40 | 40 | int ret; |
| 41 | 41 | |
| 42 | − XE_WARN_ON(size != 8); | |
| 43 | − | |
| 44 | 42 | ret = xe_bo_lock(bo, true); |
| 45 | 43 | if (ret) |
| 46 | 44 | return ret; |
| @@ -50,11 +48,12 @@ static inline int i915_gem_object_read_from_page(struct xe_bo *bo, · 3 unmodified lines | ||
| 50 | 48 | goto out_unlock; |
| 51 | 49 | |
| 52 | 50 | ofs &= ~PAGE_MASK; |
| 53 | − virtual = ttm_kmap_obj_virtual(&map, &is_iomem); | |
| 51 | + src = ttm_kmap_obj_virtual(&map, &is_iomem); | |
| 52 | + src += ofs; | |
| 54 | 53 | if (is_iomem) |
| 55 | − *ptr = readq((void __iomem *)(virtual + ofs)); | |
| 54 | + memcpy_fromio(ptr, (void __iomem *)src, size); | |
| 56 | 55 | else |
| 57 | − *ptr = *(u64 *)(virtual + ofs); | |
| 56 | + memcpy(ptr, src, size); | |
| 58 | 57 | |
| 59 | 58 | ttm_bo_kunmap(&map); |
| 60 | 59 | out_unlock: |
| @@ -74,9 +74,6 @@ static const struct platform_test_case cases[] = { · 73 unmodified lines | ||
| 74 | 74 | SUBPLATFORM_CASE(DG2, G11, B1), |
| 75 | 75 | SUBPLATFORM_CASE(DG2, G12, A0), |
| 76 | 76 | SUBPLATFORM_CASE(DG2, G12, A1), |
| 77 | − PLATFORM_CASE(PVC, B0), | |
| 78 | − PLATFORM_CASE(PVC, B1), | |
| 79 | − PLATFORM_CASE(PVC, C0), | |
| 80 | 77 | GMDID_CASE(METEORLAKE, 1270, A0, 1300, A0), |
| 81 | 78 | GMDID_CASE(METEORLAKE, 1271, A0, 1300, A0), |
| 82 | 79 | GMDID_CASE(LUNARLAKE, 2004, A0, 2000, A0), |
| @@ -613,7 +613,7 @@ void xe_device_wmb(struct xe_device *xe) · 612 unmodified lines | ||
| 613 | 613 | u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size) |
| 614 | 614 | { |
| 615 | 615 | return xe_device_has_flat_ccs(xe) ? |
| 616 | − DIV_ROUND_UP(size, NUM_BYTES_PER_CCS_BYTE(xe)) : 0; | |
| 616 | + DIV_ROUND_UP_ULL(size, NUM_BYTES_PER_CCS_BYTE(xe)) : 0; | |
| 617 | 617 | } |
| 618 | 618 | |
| 619 | 619 | bool xe_device_mem_access_ongoing(struct xe_device *xe) |
| @@ -134,8 +134,6 @@ static void xe_display_fini_nommio(struct drm_device *dev, void *dummy) · 133 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | int xe_display_init_nommio(struct xe_device *xe) |
| 136 | 136 | { |
| 137 | − int err; | |
| 138 | − | |
| 139 | 137 | if (!xe->info.enable_display) |
| 140 | 138 | return 0; |
| 141 | 139 | |
| @@ -145,10 +143,6 @@ int xe_display_init_nommio(struct xe_device *xe) · 3 unmodified lines | ||
| 145 | 143 | /* This must be called before any calls to HAS_PCH_* */ |
| 146 | 144 | intel_detect_pch(xe); |
| 147 | 145 | |
| 148 | − err = intel_power_domains_init(xe); | |
| 149 | − if (err) | |
| 150 | − return err; | |
| 151 | − | |
| 152 | 146 | return drmm_add_action_or_reset(&xe->drm, xe_display_fini_nommio, xe); |
| 153 | 147 | } |
| 154 | 148 | |
| @@ -175,7 +175,7 @@ static int xe_dma_buf_begin_cpu_access(struct dma_buf *dma_buf, · 174 unmodified lines | ||
| 175 | 175 | return 0; |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | −const struct dma_buf_ops xe_dmabuf_ops = { | |
| 178 | +static const struct dma_buf_ops xe_dmabuf_ops = { | |
| 179 | 179 | .attach = xe_dma_buf_attach, |
| 180 | 180 | .detach = xe_dma_buf_detach, |
| 181 | 181 | .pin = xe_dma_buf_pin, |
| @@ -111,7 +111,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 110 unmodified lines | ||
| 111 | 111 | u64 addresses[XE_HW_ENGINE_MAX_INSTANCE]; |
| 112 | 112 | struct drm_gpuvm_exec vm_exec = {.extra.fn = xe_exec_fn}; |
| 113 | 113 | struct drm_exec *exec = &vm_exec.exec; |
| 114 | − u32 i, num_syncs = 0; | |
| 114 | + u32 i, num_syncs = 0, num_ufence = 0; | |
| 115 | 115 | struct xe_sched_job *job; |
| 116 | 116 | struct dma_fence *rebind_fence; |
| 117 | 117 | struct xe_vm *vm; |
| @@ -157,6 +157,14 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 39 unmodified lines | ||
| 157 | 157 | SYNC_PARSE_FLAG_LR_MODE : 0)); |
| 158 | 158 | if (err) |
| 159 | 159 | goto err_syncs; |
| 160 | + | |
| 161 | + if (xe_sync_is_ufence(&syncs[i])) | |
| 162 | + num_ufence++; | |
| 163 | + } | |
| 164 | + | |
| 165 | + if (XE_IOCTL_DBG(xe, num_ufence > 1)) { | |
| 166 | + err = -EINVAL; | |
| 167 | + goto err_syncs; | |
| 160 | 168 | } |
| 161 | 169 | |
| 162 | 170 | if (xe_exec_queue_is_parallel(q)) { |
| @@ -926,20 +926,24 @@ void xe_exec_queue_last_fence_put_unlocked(struct xe_exec_queue *q) · 925 unmodified lines | ||
| 926 | 926 | * @q: The exec queue |
| 927 | 927 | * @vm: The VM the engine does a bind or exec for |
| 928 | 928 | * |
| 929 | − * Get last fence, does not take a ref | |
| 929 | + * Get last fence, takes a ref | |
| 930 | 930 | * |
| 931 | 931 | * Returns: last fence if not signaled, dma fence stub if signaled |
| 932 | 932 | */ |
| 933 | 933 | struct dma_fence *xe_exec_queue_last_fence_get(struct xe_exec_queue *q, |
| 934 | 934 | struct xe_vm *vm) |
| 935 | 935 | { |
| 936 | + struct dma_fence *fence; | |
| 937 | + | |
| 936 | 938 | xe_exec_queue_last_fence_lockdep_assert(q, vm); |
| 937 | 939 | |
| 938 | 940 | if (q->last_fence && |
| 939 | 941 | test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &q->last_fence->flags)) |
| 940 | 942 | xe_exec_queue_last_fence_put(q, vm); |
| 941 | 943 | |
| 942 | − return q->last_fence ? q->last_fence : dma_fence_get_stub(); | |
| 944 | + fence = q->last_fence ? q->last_fence : dma_fence_get_stub(); | |
| 945 | + dma_fence_get(fence); | |
| 946 | + return fence; | |
| 943 | 947 | } |
| 944 | 948 | |
| 945 | 949 | /** |
| @@ -437,7 +437,10 @@ static int all_fw_domain_init(struct xe_gt *gt) · 436 unmodified lines | ||
| 437 | 437 | * USM has its only SA pool to non-block behind user operations |
| 438 | 438 | */ |
| 439 | 439 | if (gt_to_xe(gt)->info.has_usm) { |
| 440 | − gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), SZ_1M, 16); | |
| 440 | + struct xe_device *xe = gt_to_xe(gt); | |
| 441 | + | |
| 442 | + gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), | |
| 443 | + IS_DGFX(xe) ? SZ_1M : SZ_512K, 16); | |
| 441 | 444 | if (IS_ERR(gt->usm.bb_pool)) { |
| 442 | 445 | err = PTR_ERR(gt->usm.bb_pool); |
| 443 | 446 | goto err_force_wake; |
| @@ -480,7 +480,7 @@ static bool xe_gt_mcr_get_nonterminated_steering(struct xe_gt *gt, · 479 unmodified lines | ||
| 480 | 480 | * to synchronize with external clients (e.g., firmware), so a semaphore |
| 481 | 481 | * register will also need to be taken. |
| 482 | 482 | */ |
| 483 | −static void mcr_lock(struct xe_gt *gt) | |
| 483 | +static void mcr_lock(struct xe_gt *gt) __acquires(>->mcr_lock) | |
| 484 | 484 | { |
| 485 | 485 | struct xe_device *xe = gt_to_xe(gt); |
| 486 | 486 | int ret = 0; |
| @@ -500,7 +500,7 @@ static void mcr_lock(struct xe_gt *gt) · 13 unmodified lines | ||
| 500 | 500 | drm_WARN_ON_ONCE(&xe->drm, ret == -ETIMEDOUT); |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | −static void mcr_unlock(struct xe_gt *gt) | |
| 503 | +static void mcr_unlock(struct xe_gt *gt) __releases(>->mcr_lock) | |
| 504 | 504 | { |
| 505 | 505 | /* Release hardware semaphore - this is done by writing 1 to the register */ |
| 506 | 506 | if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) |
| @@ -165,7 +165,8 @@ retry_userptr: · 164 unmodified lines | ||
| 165 | 165 | goto unlock_vm; |
| 166 | 166 | } |
| 167 | 167 | |
| 168 | − if (!xe_vma_is_userptr(vma) || !xe_vma_userptr_check_repin(vma)) { | |
| 168 | + if (!xe_vma_is_userptr(vma) || | |
| 169 | + !xe_vma_userptr_check_repin(to_userptr_vma(vma))) { | |
| 169 | 170 | downgrade_write(&vm->lock); |
| 170 | 171 | write_locked = false; |
| 171 | 172 | } |
| @@ -181,11 +182,13 @@ retry_userptr: · 9 unmodified lines | ||
| 181 | 182 | /* TODO: Validate fault */ |
| 182 | 183 | |
| 183 | 184 | if (xe_vma_is_userptr(vma) && write_locked) { |
| 185 | + struct xe_userptr_vma *uvma = to_userptr_vma(vma); | |
| 186 | + | |
| 184 | 187 | spin_lock(&vm->userptr.invalidated_lock); |
| 185 | − list_del_init(&vma->userptr.invalidate_link); | |
| 188 | + list_del_init(&uvma->userptr.invalidate_link); | |
| 186 | 189 | spin_unlock(&vm->userptr.invalidated_lock); |
| 187 | 190 | |
| 188 | − ret = xe_vma_userptr_pin_pages(vma); | |
| 191 | + ret = xe_vma_userptr_pin_pages(uvma); | |
| 189 | 192 | if (ret) |
| 190 | 193 | goto unlock_vm; |
| 191 | 194 | |
| @@ -220,7 +223,7 @@ retry_userptr: · 28 unmodified lines | ||
| 220 | 223 | dma_fence_put(fence); |
| 221 | 224 | |
| 222 | 225 | if (xe_vma_is_userptr(vma)) |
| 223 | − ret = xe_vma_userptr_check_repin(vma); | |
| 226 | + ret = xe_vma_userptr_check_repin(to_userptr_vma(vma)); | |
| 224 | 227 | vma->usm.tile_invalidated &= ~BIT(tile->id); |
| 225 | 228 | |
| 226 | 229 | unlock_dma_resv: |
| @@ -332,7 +335,7 @@ int xe_guc_pagefault_handler(struct xe_guc *guc, u32 *msg, u32 len) · 105 unmodified lines | ||
| 332 | 335 | return -EPROTO; |
| 333 | 336 | |
| 334 | 337 | asid = FIELD_GET(PFD_ASID, msg[1]); |
| 335 | − pf_queue = >->usm.pf_queue[asid % NUM_PF_QUEUE]; | |
| 338 | + pf_queue = gt->usm.pf_queue + (asid % NUM_PF_QUEUE); | |
| 336 | 339 | |
| 337 | 340 | spin_lock_irqsave(&pf_queue->lock, flags); |
| 338 | 341 | full = pf_queue_full(pf_queue); |
| @@ -963,7 +963,9 @@ void xe_guc_pc_fini(struct xe_guc_pc *pc) · 962 unmodified lines | ||
| 963 | 963 | struct xe_device *xe = pc_to_xe(pc); |
| 964 | 964 | |
| 965 | 965 | if (xe->info.skip_guc_pc) { |
| 966 | + xe_device_mem_access_get(xe); | |
| 966 | 967 | xe_gt_idle_disable_c6(pc_to_gt(pc)); |
| 968 | + xe_device_mem_access_put(xe); | |
| 967 | 969 | return; |
| 968 | 970 | } |
| 969 | 971 | |
| @@ -217,13 +217,13 @@ struct xe_hw_fence *xe_hw_fence_create(struct xe_hw_fence_ctx *ctx, · 216 unmodified lines | ||
| 217 | 217 | if (!fence) |
| 218 | 218 | return ERR_PTR(-ENOMEM); |
| 219 | 219 | |
| 220 | − dma_fence_init(&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock, | |
| 221 | − ctx->dma_fence_ctx, ctx->next_seqno++); | |
| 222 | − | |
| 223 | 220 | fence->ctx = ctx; |
| 224 | 221 | fence->seqno_map = seqno_map; |
| 225 | 222 | INIT_LIST_HEAD(&fence->irq_link); |
| 226 | 223 | |
| 224 | + dma_fence_init(&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock, | |
| 225 | + ctx->dma_fence_ctx, ctx->next_seqno++); | |
| 226 | + | |
| 227 | 227 | trace_xe_hw_fence_create(fence); |
| 228 | 228 | |
| 229 | 229 | return fence; |
| @@ -419,7 +419,7 @@ static int xe_hwmon_pcode_read_i1(struct xe_gt *gt, u32 *uval) · 418 unmodified lines | ||
| 419 | 419 | |
| 420 | 420 | return xe_pcode_read(gt, PCODE_MBOX(PCODE_POWER_SETUP, |
| 421 | 421 | POWER_SETUP_SUBCOMMAND_READ_I1, 0), |
| 422 | − uval, 0); | |
| 422 | + uval, NULL); | |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | 425 | static int xe_hwmon_pcode_write_i1(struct xe_gt *gt, u32 uval) |
| @@ -21,10 +21,10 @@ · 20 unmodified lines | ||
| 21 | 21 | #include "xe_map.h" |
| 22 | 22 | #include "xe_vm.h" |
| 23 | 23 | |
| 24 | −#define CTX_VALID (1 << 0) | |
| 25 | −#define CTX_PRIVILEGE (1 << 8) | |
| 26 | −#define CTX_ADDRESSING_MODE_SHIFT 3 | |
| 27 | −#define LEGACY_64B_CONTEXT 3 | |
| 24 | +#define LRC_VALID (1 << 0) | |
| 25 | +#define LRC_PRIVILEGE (1 << 8) | |
| 26 | +#define LRC_ADDRESSING_MODE_SHIFT 3 | |
| 27 | +#define LRC_LEGACY_64B_CONTEXT 3 | |
| 28 | 28 | |
| 29 | 29 | #define ENGINE_CLASS_SHIFT 61 |
| 30 | 30 | #define ENGINE_INSTANCE_SHIFT 48 |
| @@ -762,15 +762,15 @@ int xe_lrc_init(struct xe_lrc *lrc, struct xe_hw_engine *hwe, · 731 unmodified lines | ||
| 762 | 762 | (q->usm.acc_notify << ACC_NOTIFY_S) | |
| 763 | 763 | q->usm.acc_trigger); |
| 764 | 764 | |
| 765 | − lrc->desc = CTX_VALID; | |
| 766 | − lrc->desc |= LEGACY_64B_CONTEXT << CTX_ADDRESSING_MODE_SHIFT; | |
| 765 | + lrc->desc = LRC_VALID; | |
| 766 | + lrc->desc |= LRC_LEGACY_64B_CONTEXT << LRC_ADDRESSING_MODE_SHIFT; | |
| 767 | 767 | /* TODO: Priority */ |
| 768 | 768 | |
| 769 | 769 | /* While this appears to have something about privileged batches or |
| 770 | 770 | * some such, it really just means PPGTT mode. |
| 771 | 771 | */ |
| 772 | 772 | if (vm) |
| 773 | − lrc->desc |= CTX_PRIVILEGE; | |
| 773 | + lrc->desc |= LRC_PRIVILEGE; | |
| 774 | 774 | |
| 775 | 775 | if (GRAPHICS_VERx100(xe) < 1250) { |
| 776 | 776 | lrc->desc |= (u64)hwe->instance << ENGINE_INSTANCE_SHIFT; |
| @@ -170,11 +170,6 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, · 169 unmodified lines | ||
| 170 | 170 | if (!IS_DGFX(xe)) { |
| 171 | 171 | /* Write out batch too */ |
| 172 | 172 | m->batch_base_ofs = NUM_PT_SLOTS * XE_PAGE_SIZE; |
| 173 | − if (xe->info.has_usm) { | |
| 174 | − batch = tile->primary_gt->usm.bb_pool->bo; | |
| 175 | − m->usm_batch_base_ofs = m->batch_base_ofs; | |
| 176 | − } | |
| 177 | − | |
| 178 | 173 | for (i = 0; i < batch->size; |
| 179 | 174 | i += vm->flags & XE_VM_FLAG_64K ? XE_64K_PAGE_SIZE : |
| 180 | 175 | XE_PAGE_SIZE) { |
| @@ -185,6 +180,24 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, · 4 unmodified lines | ||
| 185 | 180 | entry); |
| 186 | 181 | level++; |
| 187 | 182 | } |
| 183 | + if (xe->info.has_usm) { | |
| 184 | + xe_tile_assert(tile, batch->size == SZ_1M); | |
| 185 | + | |
| 186 | + batch = tile->primary_gt->usm.bb_pool->bo; | |
| 187 | + m->usm_batch_base_ofs = m->batch_base_ofs + SZ_1M; | |
| 188 | + xe_tile_assert(tile, batch->size == SZ_512K); | |
| 189 | + | |
| 190 | + for (i = 0; i < batch->size; | |
| 191 | + i += vm->flags & XE_VM_FLAG_64K ? XE_64K_PAGE_SIZE : | |
| 192 | + XE_PAGE_SIZE) { | |
| 193 | + entry = vm->pt_ops->pte_encode_bo(batch, i, | |
| 194 | + pat_index, 0); | |
| 195 | + | |
| 196 | + xe_map_wr(xe, &bo->vmap, map_ofs + level * 8, u64, | |
| 197 | + entry); | |
| 198 | + level++; | |
| 199 | + } | |
| 200 | + } | |
| 188 | 201 | } else { |
| 189 | 202 | u64 batch_addr = xe_bo_addr(batch, 0, XE_PAGE_SIZE); |
| 190 | 203 | |
| @@ -472,7 +485,7 @@ static void emit_pte(struct xe_migrate *m, · 281 unmodified lines | ||
| 472 | 485 | /* Indirect access needs compression enabled uncached PAT index */ |
| 473 | 486 | if (GRAPHICS_VERx100(xe) >= 2000) |
| 474 | 487 | pat_index = is_comp_pte ? xe->pat.idx[XE_CACHE_NONE_COMPRESSION] : |
| 475 | − xe->pat.idx[XE_CACHE_NONE]; | |
| 488 | + xe->pat.idx[XE_CACHE_WB]; | |
| 476 | 489 | else |
| 477 | 490 | pat_index = xe->pat.idx[XE_CACHE_WB]; |
| 478 | 491 | |
| @@ -760,14 +773,14 @@ struct dma_fence *xe_migrate_copy(struct xe_migrate *m, · 281 unmodified lines | ||
| 760 | 773 | if (src_is_vram && xe_migrate_allow_identity(src_L0, &src_it)) |
| 761 | 774 | xe_res_next(&src_it, src_L0); |
| 762 | 775 | else |
| 763 | − emit_pte(m, bb, src_L0_pt, src_is_vram, true, &src_it, src_L0, | |
| 764 | − src); | |
| 776 | + emit_pte(m, bb, src_L0_pt, src_is_vram, copy_system_ccs, | |
| 777 | + &src_it, src_L0, src); | |
| 765 | 778 | |
| 766 | 779 | if (dst_is_vram && xe_migrate_allow_identity(src_L0, &dst_it)) |
| 767 | 780 | xe_res_next(&dst_it, src_L0); |
| 768 | 781 | else |
| 769 | − emit_pte(m, bb, dst_L0_pt, dst_is_vram, true, &dst_it, src_L0, | |
| 770 | − dst); | |
| 782 | + emit_pte(m, bb, dst_L0_pt, dst_is_vram, copy_system_ccs, | |
| 783 | + &dst_it, src_L0, dst); | |
| 771 | 784 | |
| 772 | 785 | if (copy_system_ccs) |
| 773 | 786 | emit_pte(m, bb, ccs_pt, false, false, &ccs_it, ccs_size, src); |
| @@ -1009,8 +1022,8 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m, · 235 unmodified lines | ||
| 1009 | 1022 | if (clear_vram && xe_migrate_allow_identity(clear_L0, &src_it)) |
| 1010 | 1023 | xe_res_next(&src_it, clear_L0); |
| 1011 | 1024 | else |
| 1012 | − emit_pte(m, bb, clear_L0_pt, clear_vram, true, &src_it, clear_L0, | |
| 1013 | − dst); | |
| 1025 | + emit_pte(m, bb, clear_L0_pt, clear_vram, clear_system_ccs, | |
| 1026 | + &src_it, clear_L0, dst); | |
| 1014 | 1027 | |
| 1015 | 1028 | bb->cs[bb->len++] = MI_BATCH_BUFFER_END; |
| 1016 | 1029 | update_idx = bb->len; |
| @@ -1204,8 +1217,11 @@ static bool no_in_syncs(struct xe_vm *vm, struct xe_exec_queue *q, · 187 unmodified lines | ||
| 1204 | 1217 | } |
| 1205 | 1218 | if (q) { |
| 1206 | 1219 | fence = xe_exec_queue_last_fence_get(q, vm); |
| 1207 | − if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) | |
| 1220 | + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { | |
| 1221 | + dma_fence_put(fence); | |
| 1208 | 1222 | return false; |
| 1223 | + } | |
| 1224 | + dma_fence_put(fence); | |
| 1209 | 1225 | } |
| 1210 | 1226 | |
| 1211 | 1227 | return true; |
| @@ -272,8 +272,8 @@ int xe_mmio_probe_vram(struct xe_device *xe) · 271 unmodified lines | ||
| 272 | 272 | drm_info(&xe->drm, "VRAM[%u, %u]: Actual physical size %pa, usable size exclude stolen %pa, CPU accessible size %pa\n", id, |
| 273 | 273 | tile->id, &tile->mem.vram.actual_physical_size, &tile->mem.vram.usable_size, &tile->mem.vram.io_size); |
| 274 | 274 | drm_info(&xe->drm, "VRAM[%u, %u]: DPA range: [%pa-%llx], io range: [%pa-%llx]\n", id, tile->id, |
| 275 | − &tile->mem.vram.dpa_base, tile->mem.vram.dpa_base + tile->mem.vram.actual_physical_size, | |
| 276 | − &tile->mem.vram.io_start, tile->mem.vram.io_start + tile->mem.vram.io_size); | |
| 275 | + &tile->mem.vram.dpa_base, tile->mem.vram.dpa_base + (u64)tile->mem.vram.actual_physical_size, | |
| 276 | + &tile->mem.vram.io_start, tile->mem.vram.io_start + (u64)tile->mem.vram.io_size); | |
| 277 | 277 | |
| 278 | 278 | /* calculate total size using tile size to get the correct HW sizing */ |
| 279 | 279 | total_size += tile_size; |
| @@ -618,8 +618,8 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma, · 617 unmodified lines | ||
| 618 | 618 | |
| 619 | 619 | if (!xe_vma_is_null(vma)) { |
| 620 | 620 | if (xe_vma_is_userptr(vma)) |
| 621 | − xe_res_first_sg(vma->userptr.sg, 0, xe_vma_size(vma), | |
| 622 | − &curs); | |
| 621 | + xe_res_first_sg(to_userptr_vma(vma)->userptr.sg, 0, | |
| 622 | + xe_vma_size(vma), &curs); | |
| 623 | 623 | else if (xe_bo_is_vram(bo) || xe_bo_is_stolen(bo)) |
| 624 | 624 | xe_res_first(bo->ttm.resource, xe_vma_bo_offset(vma), |
| 625 | 625 | xe_vma_size(vma), &curs); |
| @@ -906,17 +906,17 @@ static void xe_vm_dbg_print_entries(struct xe_device *xe, · 280 unmodified lines | ||
| 906 | 906 | |
| 907 | 907 | #ifdef CONFIG_DRM_XE_USERPTR_INVAL_INJECT |
| 908 | 908 | |
| 909 | −static int xe_pt_userptr_inject_eagain(struct xe_vma *vma) | |
| 909 | +static int xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) | |
| 910 | 910 | { |
| 911 | − u32 divisor = vma->userptr.divisor ? vma->userptr.divisor : 2; | |
| 911 | + u32 divisor = uvma->userptr.divisor ? uvma->userptr.divisor : 2; | |
| 912 | 912 | static u32 count; |
| 913 | 913 | |
| 914 | 914 | if (count++ % divisor == divisor - 1) { |
| 915 | − struct xe_vm *vm = xe_vma_vm(vma); | |
| 915 | + struct xe_vm *vm = xe_vma_vm(&uvma->vma); | |
| 916 | 916 | |
| 917 | − vma->userptr.divisor = divisor << 1; | |
| 917 | + uvma->userptr.divisor = divisor << 1; | |
| 918 | 918 | spin_lock(&vm->userptr.invalidated_lock); |
| 919 | − list_move_tail(&vma->userptr.invalidate_link, | |
| 919 | + list_move_tail(&uvma->userptr.invalidate_link, | |
| 920 | 920 | &vm->userptr.invalidated); |
| 921 | 921 | spin_unlock(&vm->userptr.invalidated_lock); |
| 922 | 922 | return true; |
| @@ -927,7 +927,7 @@ static int xe_pt_userptr_inject_eagain(struct xe_vma *vma) · 4 unmodified lines | ||
| 927 | 927 | |
| 928 | 928 | #else |
| 929 | 929 | |
| 930 | −static bool xe_pt_userptr_inject_eagain(struct xe_vma *vma) | |
| 930 | +static bool xe_pt_userptr_inject_eagain(struct xe_userptr_vma *uvma) | |
| 931 | 931 | { |
| 932 | 932 | return false; |
| 933 | 933 | } |
| @@ -1000,9 +1000,9 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) · 66 unmodified lines | ||
| 1000 | 1000 | { |
| 1001 | 1001 | struct xe_pt_migrate_pt_update *userptr_update = |
| 1002 | 1002 | container_of(pt_update, typeof(*userptr_update), base); |
| 1003 | − struct xe_vma *vma = pt_update->vma; | |
| 1004 | − unsigned long notifier_seq = vma->userptr.notifier_seq; | |
| 1005 | − struct xe_vm *vm = xe_vma_vm(vma); | |
| 1003 | + struct xe_userptr_vma *uvma = to_userptr_vma(pt_update->vma); | |
| 1004 | + unsigned long notifier_seq = uvma->userptr.notifier_seq; | |
| 1005 | + struct xe_vm *vm = xe_vma_vm(&uvma->vma); | |
| 1006 | 1006 | int err = xe_pt_vm_dependencies(pt_update->job, |
| 1007 | 1007 | &vm->rftree[pt_update->tile_id], |
| 1008 | 1008 | pt_update->start, |
| @@ -1023,7 +1023,7 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) · 14 unmodified lines | ||
| 1023 | 1023 | */ |
| 1024 | 1024 | do { |
| 1025 | 1025 | down_read(&vm->userptr.notifier_lock); |
| 1026 | − if (!mmu_interval_read_retry(&vma->userptr.notifier, | |
| 1026 | + if (!mmu_interval_read_retry(&uvma->userptr.notifier, | |
| 1027 | 1027 | notifier_seq)) |
| 1028 | 1028 | break; |
| 1029 | 1029 | |
| @@ -1032,11 +1032,11 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) · 2 unmodified lines | ||
| 1032 | 1032 | if (userptr_update->bind) |
| 1033 | 1033 | return -EAGAIN; |
| 1034 | 1034 | |
| 1035 | − notifier_seq = mmu_interval_read_begin(&vma->userptr.notifier); | |
| 1035 | + notifier_seq = mmu_interval_read_begin(&uvma->userptr.notifier); | |
| 1036 | 1036 | } while (true); |
| 1037 | 1037 | |
| 1038 | 1038 | /* Inject errors to test_whether they are handled correctly */ |
| 1039 | − if (userptr_update->bind && xe_pt_userptr_inject_eagain(vma)) { | |
| 1039 | + if (userptr_update->bind && xe_pt_userptr_inject_eagain(uvma)) { | |
| 1040 | 1040 | up_read(&vm->userptr.notifier_lock); |
| 1041 | 1041 | return -EAGAIN; |
| 1042 | 1042 | } |
| @@ -1297,7 +1297,7 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue · 254 unmodified lines | ||
| 1297 | 1297 | vma->tile_present |= BIT(tile->id); |
| 1298 | 1298 | |
| 1299 | 1299 | if (bind_pt_update.locked) { |
| 1300 | − vma->userptr.initial_bind = true; | |
| 1300 | + to_userptr_vma(vma)->userptr.initial_bind = true; | |
| 1301 | 1301 | up_read(&vm->userptr.notifier_lock); |
| 1302 | 1302 | xe_bo_put_commit(&deferred); |
| 1303 | 1303 | } |
| @@ -1642,7 +1642,7 @@ __xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queu · 338 unmodified lines | ||
| 1642 | 1642 | |
| 1643 | 1643 | if (!vma->tile_present) { |
| 1644 | 1644 | spin_lock(&vm->userptr.invalidated_lock); |
| 1645 | − list_del_init(&vma->userptr.invalidate_link); | |
| 1645 | + list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link); | |
| 1646 | 1646 | spin_unlock(&vm->userptr.invalidated_lock); |
| 1647 | 1647 | } |
| 1648 | 1648 | up_read(&vm->userptr.notifier_lock); |
| @@ -459,21 +459,21 @@ static size_t calc_topo_query_size(struct xe_device *xe) · 458 unmodified lines | ||
| 459 | 459 | sizeof_field(struct xe_gt, fuse_topo.eu_mask_per_dss)); |
| 460 | 460 | } |
| 461 | 461 | |
| 462 | −static void __user *copy_mask(void __user *ptr, | |
| 463 | − struct drm_xe_query_topology_mask *topo, | |
| 464 | − void *mask, size_t mask_size) | |
| 462 | +static int copy_mask(void __user **ptr, | |
| 463 | + struct drm_xe_query_topology_mask *topo, | |
| 464 | + void *mask, size_t mask_size) | |
| 465 | 465 | { |
| 466 | 466 | topo->num_bytes = mask_size; |
| 467 | 467 | |
| 468 | − if (copy_to_user(ptr, topo, sizeof(*topo))) | |
| 469 | − return ERR_PTR(-EFAULT); | |
| 470 | − ptr += sizeof(topo); | |
| 468 | + if (copy_to_user(*ptr, topo, sizeof(*topo))) | |
| 469 | + return -EFAULT; | |
| 470 | + *ptr += sizeof(topo); | |
| 471 | 471 | |
| 472 | − if (copy_to_user(ptr, mask, mask_size)) | |
| 473 | − return ERR_PTR(-EFAULT); | |
| 474 | − ptr += mask_size; | |
| 472 | + if (copy_to_user(*ptr, mask, mask_size)) | |
| 473 | + return -EFAULT; | |
| 474 | + *ptr += mask_size; | |
| 475 | 475 | |
| 476 | − return ptr; | |
| 476 | + return 0; | |
| 477 | 477 | } |
| 478 | 478 | |
| 479 | 479 | static int query_gt_topology(struct xe_device *xe, |
| @@ -493,28 +493,28 @@ static int query_gt_topology(struct xe_device *xe, · 13 unmodified lines | ||
| 493 | 493 | } |
| 494 | 494 | |
| 495 | 495 | for_each_gt(gt, xe, id) { |
| 496 | + int err; | |
| 497 | + | |
| 496 | 498 | topo.gt_id = id; |
| 497 | 499 | |
| 498 | 500 | topo.type = DRM_XE_TOPO_DSS_GEOMETRY; |
| 499 | − query_ptr = copy_mask(query_ptr, &topo, | |
| 500 | − gt->fuse_topo.g_dss_mask, | |
| 501 | − sizeof(gt->fuse_topo.g_dss_mask)); | |
| 502 | − if (IS_ERR(query_ptr)) | |
| 503 | − return PTR_ERR(query_ptr); | |
| 501 | + err = copy_mask(&query_ptr, &topo, gt->fuse_topo.g_dss_mask, | |
| 502 | + sizeof(gt->fuse_topo.g_dss_mask)); | |
| 503 | + if (err) | |
| 504 | + return err; | |
| 504 | 505 | |
| 505 | 506 | topo.type = DRM_XE_TOPO_DSS_COMPUTE; |
| 506 | − query_ptr = copy_mask(query_ptr, &topo, | |
| 507 | − gt->fuse_topo.c_dss_mask, | |
| 508 | − sizeof(gt->fuse_topo.c_dss_mask)); | |
| 509 | − if (IS_ERR(query_ptr)) | |
| 510 | − return PTR_ERR(query_ptr); | |
| 507 | + err = copy_mask(&query_ptr, &topo, gt->fuse_topo.c_dss_mask, | |
| 508 | + sizeof(gt->fuse_topo.c_dss_mask)); | |
| 509 | + if (err) | |
| 510 | + return err; | |
| 511 | 511 | |
| 512 | 512 | topo.type = DRM_XE_TOPO_EU_PER_DSS; |
| 513 | − query_ptr = copy_mask(query_ptr, &topo, | |
| 514 | − gt->fuse_topo.eu_mask_per_dss, | |
| 515 | − sizeof(gt->fuse_topo.eu_mask_per_dss)); | |
| 516 | − if (IS_ERR(query_ptr)) | |
| 517 | − return PTR_ERR(query_ptr); | |
| 513 | + err = copy_mask(&query_ptr, &topo, | |
| 514 | + gt->fuse_topo.eu_mask_per_dss, | |
| 515 | + sizeof(gt->fuse_topo.eu_mask_per_dss)); | |
| 516 | + if (err) | |
| 517 | + return err; | |
| 518 | 518 | } |
| 519 | 519 | |
| 520 | 520 | return 0; |
| @@ -274,7 +274,6 @@ int xe_sched_job_last_fence_add_dep(struct xe_sched_job *job, struct xe_vm *vm) · 273 unmodified lines | ||
| 274 | 274 | struct dma_fence *fence; |
| 275 | 275 | |
| 276 | 276 | fence = xe_exec_queue_last_fence_get(job->q, vm); |
| 277 | − dma_fence_get(fence); | |
| 278 | 277 | |
| 279 | 278 | return drm_sched_job_add_dependency(&job->drm, fence); |
| 280 | 279 | } |
| @@ -307,7 +307,6 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync, · 306 unmodified lines | ||
| 307 | 307 | /* Easy case... */ |
| 308 | 308 | if (!num_in_fence) { |
| 309 | 309 | fence = xe_exec_queue_last_fence_get(q, vm); |
| 310 | − dma_fence_get(fence); | |
| 311 | 310 | return fence; |
| 312 | 311 | } |
| 313 | 312 | |
| @@ -322,7 +321,6 @@ xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync, · 8 unmodified lines | ||
| 322 | 321 | } |
| 323 | 322 | } |
| 324 | 323 | fences[current_fence++] = xe_exec_queue_last_fence_get(q, vm); |
| 325 | − dma_fence_get(fences[current_fence - 1]); | |
| 326 | 324 | cf = dma_fence_array_create(num_in_fence, fences, |
| 327 | 325 | vm->composite_fence_ctx, |
| 328 | 326 | vm->composite_fence_seqno++, |
| @@ -33,4 +33,9 @@ struct dma_fence * · 32 unmodified lines | ||
| 33 | 33 | xe_sync_in_fence_get(struct xe_sync_entry *sync, int num_sync, |
| 34 | 34 | struct xe_exec_queue *q, struct xe_vm *vm); |
| 35 | 35 | |
| 36 | +static inline bool xe_sync_is_ufence(struct xe_sync_entry *sync) | |
| 37 | +{ | |
| 38 | + return !!sync->ufence; | |
| 39 | +} | |
| 40 | + | |
| 36 | 41 | #endif |
| @@ -37,8 +37,6 @@ · 36 unmodified lines | ||
| 37 | 37 | #include "generated/xe_wa_oob.h" |
| 38 | 38 | #include "xe_wa.h" |
| 39 | 39 | |
| 40 | −#define TEST_VM_ASYNC_OPS_ERROR | |
| 41 | − | |
| 42 | 40 | static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm) |
| 43 | 41 | { |
| 44 | 42 | return vm->gpuvm.r_obj; |
| @@ -46,7 +44,7 @@ static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm) · 1 unmodified line | ||
| 46 | 44 | |
| 47 | 45 | /** |
| 48 | 46 | * xe_vma_userptr_check_repin() - Advisory check for repin needed |
| 49 | − * @vma: The userptr vma | |
| 47 | + * @uvma: The userptr vma | |
| 50 | 48 | * |
| 51 | 49 | * Check if the userptr vma has been invalidated since last successful |
| 52 | 50 | * repin. The check is advisory only and can the function can be called |
| @@ -56,15 +54,17 @@ static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm) · 3 unmodified lines | ||
| 56 | 54 | * |
| 57 | 55 | * Return: 0 if userptr vma is valid, -EAGAIN otherwise; repin recommended. |
| 58 | 56 | */ |
| 59 | −int xe_vma_userptr_check_repin(struct xe_vma *vma) | |
| 57 | +int xe_vma_userptr_check_repin(struct xe_userptr_vma *uvma) | |
| 60 | 58 | { |
| 61 | − return mmu_interval_check_retry(&vma->userptr.notifier, | |
| 62 | − vma->userptr.notifier_seq) ? | |
| 59 | + return mmu_interval_check_retry(&uvma->userptr.notifier, | |
| 60 | + uvma->userptr.notifier_seq) ? | |
| 63 | 61 | -EAGAIN : 0; |
| 64 | 62 | } |
| 65 | 63 | |
| 66 | −int xe_vma_userptr_pin_pages(struct xe_vma *vma) | |
| 64 | +int xe_vma_userptr_pin_pages(struct xe_userptr_vma *uvma) | |
| 67 | 65 | { |
| 66 | + struct xe_userptr *userptr = &uvma->userptr; | |
| 67 | + struct xe_vma *vma = &uvma->vma; | |
| 68 | 68 | struct xe_vm *vm = xe_vma_vm(vma); |
| 69 | 69 | struct xe_device *xe = vm->xe; |
| 70 | 70 | const unsigned long num_pages = xe_vma_size(vma) >> PAGE_SHIFT; |
| @@ -80,30 +80,30 @@ retry: · 9 unmodified lines | ||
| 80 | 80 | if (vma->gpuva.flags & XE_VMA_DESTROYED) |
| 81 | 81 | return 0; |
| 82 | 82 | |
| 83 | − notifier_seq = mmu_interval_read_begin(&vma->userptr.notifier); | |
| 84 | − if (notifier_seq == vma->userptr.notifier_seq) | |
| 83 | + notifier_seq = mmu_interval_read_begin(&userptr->notifier); | |
| 84 | + if (notifier_seq == userptr->notifier_seq) | |
| 85 | 85 | return 0; |
| 86 | 86 | |
| 87 | 87 | pages = kvmalloc_array(num_pages, sizeof(*pages), GFP_KERNEL); |
| 88 | 88 | if (!pages) |
| 89 | 89 | return -ENOMEM; |
| 90 | 90 | |
| 91 | − if (vma->userptr.sg) { | |
| 91 | + if (userptr->sg) { | |
| 92 | 92 | dma_unmap_sgtable(xe->drm.dev, |
| 93 | − vma->userptr.sg, | |
| 93 | + userptr->sg, | |
| 94 | 94 | read_only ? DMA_TO_DEVICE : |
| 95 | 95 | DMA_BIDIRECTIONAL, 0); |
| 96 | − sg_free_table(vma->userptr.sg); | |
| 97 | − vma->userptr.sg = NULL; | |
| 96 | + sg_free_table(userptr->sg); | |
| 97 | + userptr->sg = NULL; | |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | 100 | pinned = ret = 0; |
| 101 | 101 | if (in_kthread) { |
| 102 | − if (!mmget_not_zero(vma->userptr.notifier.mm)) { | |
| 102 | + if (!mmget_not_zero(userptr->notifier.mm)) { | |
| 103 | 103 | ret = -EFAULT; |
| 104 | 104 | goto mm_closed; |
| 105 | 105 | } |
| 106 | − kthread_use_mm(vma->userptr.notifier.mm); | |
| 106 | + kthread_use_mm(userptr->notifier.mm); | |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | 109 | while (pinned < num_pages) { |
| @@ -112,43 +112,40 @@ retry: · 2 unmodified lines | ||
| 112 | 112 | num_pages - pinned, |
| 113 | 113 | read_only ? 0 : FOLL_WRITE, |
| 114 | 114 | &pages[pinned]); |
| 115 | − if (ret < 0) { | |
| 116 | − if (in_kthread) | |
| 117 | − ret = 0; | |
| 115 | + if (ret < 0) | |
| 118 | 116 | break; |
| 119 | − } | |
| 120 | 117 | |
| 121 | 118 | pinned += ret; |
| 122 | 119 | ret = 0; |
| 123 | 120 | } |
| 124 | 121 | |
| 125 | 122 | if (in_kthread) { |
| 126 | − kthread_unuse_mm(vma->userptr.notifier.mm); | |
| 127 | − mmput(vma->userptr.notifier.mm); | |
| 123 | + kthread_unuse_mm(userptr->notifier.mm); | |
| 124 | + mmput(userptr->notifier.mm); | |
| 128 | 125 | } |
| 129 | 126 | mm_closed: |
| 130 | 127 | if (ret) |
| 131 | 128 | goto out; |
| 132 | 129 | |
| 133 | − ret = sg_alloc_table_from_pages_segment(&vma->userptr.sgt, pages, | |
| 130 | + ret = sg_alloc_table_from_pages_segment(&userptr->sgt, pages, | |
| 134 | 131 | pinned, 0, |
| 135 | 132 | (u64)pinned << PAGE_SHIFT, |
| 136 | 133 | xe_sg_segment_size(xe->drm.dev), |
| 137 | 134 | GFP_KERNEL); |
| 138 | 135 | if (ret) { |
| 139 | − vma->userptr.sg = NULL; | |
| 136 | + userptr->sg = NULL; | |
| 140 | 137 | goto out; |
| 141 | 138 | } |
| 142 | − vma->userptr.sg = &vma->userptr.sgt; | |
| 139 | + userptr->sg = &userptr->sgt; | |
| 143 | 140 | |
| 144 | − ret = dma_map_sgtable(xe->drm.dev, vma->userptr.sg, | |
| 141 | + ret = dma_map_sgtable(xe->drm.dev, userptr->sg, | |
| 145 | 142 | read_only ? DMA_TO_DEVICE : |
| 146 | 143 | DMA_BIDIRECTIONAL, |
| 147 | 144 | DMA_ATTR_SKIP_CPU_SYNC | |
| 148 | 145 | DMA_ATTR_NO_KERNEL_MAPPING); |
| 149 | 146 | if (ret) { |
| 150 | − sg_free_table(vma->userptr.sg); | |
| 151 | − vma->userptr.sg = NULL; | |
| 147 | + sg_free_table(userptr->sg); | |
| 148 | + userptr->sg = NULL; | |
| 152 | 149 | goto out; |
| 153 | 150 | } |
| 154 | 151 | |
| @@ -167,8 +164,8 @@ out: · 12 unmodified lines | ||
| 167 | 164 | kvfree(pages); |
| 168 | 165 | |
| 169 | 166 | if (!(ret < 0)) { |
| 170 | − vma->userptr.notifier_seq = notifier_seq; | |
| 171 | − if (xe_vma_userptr_check_repin(vma) == -EAGAIN) | |
| 167 | + userptr->notifier_seq = notifier_seq; | |
| 168 | + if (xe_vma_userptr_check_repin(uvma) == -EAGAIN) | |
| 172 | 169 | goto retry; |
| 173 | 170 | } |
| 174 | 171 | |
| @@ -635,7 +632,9 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, · 460 unmodified lines | ||
| 635 | 632 | const struct mmu_notifier_range *range, |
| 636 | 633 | unsigned long cur_seq) |
| 637 | 634 | { |
| 638 | − struct xe_vma *vma = container_of(mni, struct xe_vma, userptr.notifier); | |
| 635 | + struct xe_userptr *userptr = container_of(mni, typeof(*userptr), notifier); | |
| 636 | + struct xe_userptr_vma *uvma = container_of(userptr, typeof(*uvma), userptr); | |
| 637 | + struct xe_vma *vma = &uvma->vma; | |
| 639 | 638 | struct xe_vm *vm = xe_vma_vm(vma); |
| 640 | 639 | struct dma_resv_iter cursor; |
| 641 | 640 | struct dma_fence *fence; |
| @@ -651,7 +650,7 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, · 9 unmodified lines | ||
| 651 | 650 | mmu_interval_set_seq(mni, cur_seq); |
| 652 | 651 | |
| 653 | 652 | /* No need to stop gpu access if the userptr is not yet bound. */ |
| 654 | − if (!vma->userptr.initial_bind) { | |
| 653 | + if (!userptr->initial_bind) { | |
| 655 | 654 | up_write(&vm->userptr.notifier_lock); |
| 656 | 655 | return true; |
| 657 | 656 | } |
| @@ -663,7 +662,7 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni, · 5 unmodified lines | ||
| 663 | 662 | if (!xe_vm_in_fault_mode(vm) && |
| 664 | 663 | !(vma->gpuva.flags & XE_VMA_DESTROYED) && vma->tile_present) { |
| 665 | 664 | spin_lock(&vm->userptr.invalidated_lock); |
| 666 | − list_move_tail(&vma->userptr.invalidate_link, | |
| 665 | + list_move_tail(&userptr->invalidate_link, | |
| 667 | 666 | &vm->userptr.invalidated); |
| 668 | 667 | spin_unlock(&vm->userptr.invalidated_lock); |
| 669 | 668 | } |
| @@ -703,7 +702,7 @@ static const struct mmu_interval_notifier_ops vma_userptr_notifier_ops = { · 33 unmodified lines | ||
| 703 | 702 | |
| 704 | 703 | int xe_vm_userptr_pin(struct xe_vm *vm) |
| 705 | 704 | { |
| 706 | − struct xe_vma *vma, *next; | |
| 705 | + struct xe_userptr_vma *uvma, *next; | |
| 707 | 706 | int err = 0; |
| 708 | 707 | LIST_HEAD(tmp_evict); |
| 709 | 708 | |
| @@ -711,22 +710,23 @@ int xe_vm_userptr_pin(struct xe_vm *vm) · 1 unmodified line | ||
| 711 | 710 | |
| 712 | 711 | /* Collect invalidated userptrs */ |
| 713 | 712 | spin_lock(&vm->userptr.invalidated_lock); |
| 714 | − list_for_each_entry_safe(vma, next, &vm->userptr.invalidated, | |
| 713 | + list_for_each_entry_safe(uvma, next, &vm->userptr.invalidated, | |
| 715 | 714 | userptr.invalidate_link) { |
| 716 | − list_del_init(&vma->userptr.invalidate_link); | |
| 717 | − list_move_tail(&vma->combined_links.userptr, | |
| 715 | + list_del_init(&uvma->userptr.invalidate_link); | |
| 716 | + list_move_tail(&uvma->userptr.repin_link, | |
| 718 | 717 | &vm->userptr.repin_list); |
| 719 | 718 | } |
| 720 | 719 | spin_unlock(&vm->userptr.invalidated_lock); |
| 721 | 720 | |
| 722 | 721 | /* Pin and move to temporary list */ |
| 723 | − list_for_each_entry_safe(vma, next, &vm->userptr.repin_list, | |
| 724 | − combined_links.userptr) { | |
| 725 | − err = xe_vma_userptr_pin_pages(vma); | |
| 722 | + list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list, | |
| 723 | + userptr.repin_link) { | |
| 724 | + err = xe_vma_userptr_pin_pages(uvma); | |
| 726 | 725 | if (err < 0) |
| 727 | 726 | return err; |
| 728 | 727 | |
| 729 | − list_move_tail(&vma->combined_links.userptr, &vm->rebind_list); | |
| 728 | + list_del_init(&uvma->userptr.repin_link); | |
| 729 | + list_move_tail(&uvma->vma.combined_links.rebind, &vm->rebind_list); | |
| 730 | 730 | } |
| 731 | 731 | |
| 732 | 732 | return 0; |
| @@ -782,6 +782,14 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker) · 49 unmodified lines | ||
| 782 | 782 | return fence; |
| 783 | 783 | } |
| 784 | 784 | |
| 785 | +static void xe_vma_free(struct xe_vma *vma) | |
| 786 | +{ | |
| 787 | + if (xe_vma_is_userptr(vma)) | |
| 788 | + kfree(to_userptr_vma(vma)); | |
| 789 | + else | |
| 790 | + kfree(vma); | |
| 791 | +} | |
| 792 | + | |
| 785 | 793 | #define VMA_CREATE_FLAG_READ_ONLY BIT(0) |
| 786 | 794 | #define VMA_CREATE_FLAG_IS_NULL BIT(1) |
| 787 | 795 | |
| @@ -800,14 +808,26 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 12 unmodified lines | ||
| 800 | 808 | xe_assert(vm->xe, start < end); |
| 801 | 809 | xe_assert(vm->xe, end < vm->size); |
| 802 | 810 | |
| 803 | − if (!bo && !is_null) /* userptr */ | |
| 811 | + /* | |
| 812 | + * Allocate and ensure that the xe_vma_is_userptr() return | |
| 813 | + * matches what was allocated. | |
| 814 | + */ | |
| 815 | + if (!bo && !is_null) { | |
| 816 | + struct xe_userptr_vma *uvma = kzalloc(sizeof(*uvma), GFP_KERNEL); | |
| 817 | + | |
| 818 | + if (!uvma) | |
| 819 | + return ERR_PTR(-ENOMEM); | |
| 820 | + | |
| 821 | + vma = &uvma->vma; | |
| 822 | + } else { | |
| 804 | 823 | vma = kzalloc(sizeof(*vma), GFP_KERNEL); |
| 805 | − else | |
| 806 | − vma = kzalloc(sizeof(*vma) - sizeof(struct xe_userptr), | |
| 807 | − GFP_KERNEL); | |
| 808 | − if (!vma) { | |
| 809 | − vma = ERR_PTR(-ENOMEM); | |
| 810 | − return vma; | |
| 824 | + if (!vma) | |
| 825 | + return ERR_PTR(-ENOMEM); | |
| 826 | + | |
| 827 | + if (is_null) | |
| 828 | + vma->gpuva.flags |= DRM_GPUVA_SPARSE; | |
| 829 | + if (bo) | |
| 830 | + vma->gpuva.gem.obj = &bo->ttm.base; | |
| 811 | 831 | } |
| 812 | 832 | |
| 813 | 833 | INIT_LIST_HEAD(&vma->combined_links.rebind); |
| @@ -818,8 +838,6 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 4 unmodified lines | ||
| 818 | 838 | vma->gpuva.va.range = end - start + 1; |
| 819 | 839 | if (read_only) |
| 820 | 840 | vma->gpuva.flags |= XE_VMA_READ_ONLY; |
| 821 | − if (is_null) | |
| 822 | − vma->gpuva.flags |= DRM_GPUVA_SPARSE; | |
| 823 | 841 | |
| 824 | 842 | for_each_tile(tile, vm->xe, id) |
| 825 | 843 | vma->tile_mask |= 0x1 << id; |
| @@ -836,35 +854,35 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 10 unmodified lines | ||
| 836 | 854 | |
| 837 | 855 | vm_bo = drm_gpuvm_bo_obtain(vma->gpuva.vm, &bo->ttm.base); |
| 838 | 856 | if (IS_ERR(vm_bo)) { |
| 839 | − kfree(vma); | |
| 857 | + xe_vma_free(vma); | |
| 840 | 858 | return ERR_CAST(vm_bo); |
| 841 | 859 | } |
| 842 | 860 | |
| 843 | 861 | drm_gpuvm_bo_extobj_add(vm_bo); |
| 844 | 862 | drm_gem_object_get(&bo->ttm.base); |
| 845 | − vma->gpuva.gem.obj = &bo->ttm.base; | |
| 846 | 863 | vma->gpuva.gem.offset = bo_offset_or_userptr; |
| 847 | 864 | drm_gpuva_link(&vma->gpuva, vm_bo); |
| 848 | 865 | drm_gpuvm_bo_put(vm_bo); |
| 849 | 866 | } else /* userptr or null */ { |
| 850 | 867 | if (!is_null) { |
| 868 | + struct xe_userptr *userptr = &to_userptr_vma(vma)->userptr; | |
| 851 | 869 | u64 size = end - start + 1; |
| 852 | 870 | int err; |
| 853 | 871 | |
| 854 | − INIT_LIST_HEAD(&vma->userptr.invalidate_link); | |
| 872 | + INIT_LIST_HEAD(&userptr->invalidate_link); | |
| 873 | + INIT_LIST_HEAD(&userptr->repin_link); | |
| 855 | 874 | vma->gpuva.gem.offset = bo_offset_or_userptr; |
| 856 | 875 | |
| 857 | − err = mmu_interval_notifier_insert(&vma->userptr.notifier, | |
| 876 | + err = mmu_interval_notifier_insert(&userptr->notifier, | |
| 858 | 877 | current->mm, |
| 859 | 878 | xe_vma_userptr(vma), size, |
| 860 | 879 | &vma_userptr_notifier_ops); |
| 861 | 880 | if (err) { |
| 862 | − kfree(vma); | |
| 863 | − vma = ERR_PTR(err); | |
| 864 | − return vma; | |
| 881 | + xe_vma_free(vma); | |
| 882 | + return ERR_PTR(err); | |
| 865 | 883 | } |
| 866 | 884 | |
| 867 | − vma->userptr.notifier_seq = LONG_MAX; | |
| 885 | + userptr->notifier_seq = LONG_MAX; | |
| 868 | 886 | } |
| 869 | 887 | |
| 870 | 888 | xe_vm_get(vm); |
| @@ -880,13 +898,15 @@ static void xe_vma_destroy_late(struct xe_vma *vma) · 9 unmodified lines | ||
| 880 | 898 | bool read_only = xe_vma_read_only(vma); |
| 881 | 899 | |
| 882 | 900 | if (xe_vma_is_userptr(vma)) { |
| 883 | − if (vma->userptr.sg) { | |
| 901 | + struct xe_userptr *userptr = &to_userptr_vma(vma)->userptr; | |
| 902 | + | |
| 903 | + if (userptr->sg) { | |
| 884 | 904 | dma_unmap_sgtable(xe->drm.dev, |
| 885 | − vma->userptr.sg, | |
| 905 | + userptr->sg, | |
| 886 | 906 | read_only ? DMA_TO_DEVICE : |
| 887 | 907 | DMA_BIDIRECTIONAL, 0); |
| 888 | − sg_free_table(vma->userptr.sg); | |
| 889 | − vma->userptr.sg = NULL; | |
| 908 | + sg_free_table(userptr->sg); | |
| 909 | + userptr->sg = NULL; | |
| 890 | 910 | } |
| 891 | 911 | |
| 892 | 912 | /* |
| @@ -894,7 +914,7 @@ static void xe_vma_destroy_late(struct xe_vma *vma) · 1 unmodified line | ||
| 894 | 914 | * the notifer until we're sure the GPU is not accessing |
| 895 | 915 | * them anymore |
| 896 | 916 | */ |
| 897 | − mmu_interval_notifier_remove(&vma->userptr.notifier); | |
| 917 | + mmu_interval_notifier_remove(&userptr->notifier); | |
| 898 | 918 | xe_vm_put(vm); |
| 899 | 919 | } else if (xe_vma_is_null(vma)) { |
| 900 | 920 | xe_vm_put(vm); |
| @@ -902,7 +922,7 @@ static void xe_vma_destroy_late(struct xe_vma *vma) · 1 unmodified line | ||
| 902 | 922 | xe_bo_put(xe_vma_bo(vma)); |
| 903 | 923 | } |
| 904 | 924 | |
| 905 | − kfree(vma); | |
| 925 | + xe_vma_free(vma); | |
| 906 | 926 | } |
| 907 | 927 | |
| 908 | 928 | static void vma_destroy_work_func(struct work_struct *w) |
| @@ -933,7 +953,7 @@ static void xe_vma_destroy(struct xe_vma *vma, struct dma_fence *fence) · 24 unmodified lines | ||
| 933 | 953 | xe_assert(vm->xe, vma->gpuva.flags & XE_VMA_DESTROYED); |
| 934 | 954 | |
| 935 | 955 | spin_lock(&vm->userptr.invalidated_lock); |
| 936 | − list_del(&vma->userptr.invalidate_link); | |
| 956 | + list_del(&to_userptr_vma(vma)->userptr.invalidate_link); | |
| 937 | 957 | spin_unlock(&vm->userptr.invalidated_lock); |
| 938 | 958 | } else if (!xe_vma_is_null(vma)) { |
| 939 | 959 | xe_bo_assert_held(xe_vma_bo(vma)); |
| @@ -1855,10 +1875,8 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, · 915 unmodified lines | ||
| 1855 | 1875 | mutex_lock(&xef->vm.lock); |
| 1856 | 1876 | err = xa_alloc(&xef->vm.xa, &id, vm, xa_limit_32b, GFP_KERNEL); |
| 1857 | 1877 | mutex_unlock(&xef->vm.lock); |
| 1858 | − if (err) { | |
| 1859 | − xe_vm_close_and_put(vm); | |
| 1860 | − return err; | |
| 1861 | − } | |
| 1878 | + if (err) | |
| 1879 | + goto err_close_and_put; | |
| 1862 | 1880 | |
| 1863 | 1881 | if (xe->info.has_asid) { |
| 1864 | 1882 | mutex_lock(&xe->usm.lock); |
| @@ -1866,11 +1884,9 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, · 1 unmodified line | ||
| 1866 | 1884 | XA_LIMIT(1, XE_MAX_ASID - 1), |
| 1867 | 1885 | &xe->usm.next_asid, GFP_KERNEL); |
| 1868 | 1886 | mutex_unlock(&xe->usm.lock); |
| 1869 | − if (err < 0) { | |
| 1870 | − xe_vm_close_and_put(vm); | |
| 1871 | − return err; | |
| 1872 | − } | |
| 1873 | − err = 0; | |
| 1887 | + if (err < 0) | |
| 1888 | + goto err_free_id; | |
| 1889 | + | |
| 1874 | 1890 | vm->usm.asid = asid; |
| 1875 | 1891 | } |
| 1876 | 1892 | |
| @@ -1888,6 +1904,15 @@ int xe_vm_create_ioctl(struct drm_device *dev, void *data, · 11 unmodified lines | ||
| 1888 | 1904 | #endif |
| 1889 | 1905 | |
| 1890 | 1906 | return 0; |
| 1907 | + | |
| 1908 | +err_free_id: | |
| 1909 | + mutex_lock(&xef->vm.lock); | |
| 1910 | + xa_erase(&xef->vm.xa, id); | |
| 1911 | + mutex_unlock(&xef->vm.lock); | |
| 1912 | +err_close_and_put: | |
| 1913 | + xe_vm_close_and_put(vm); | |
| 1914 | + | |
| 1915 | + return err; | |
| 1891 | 1916 | } |
| 1892 | 1917 | |
| 1893 | 1918 | int xe_vm_destroy_ioctl(struct drm_device *dev, void *data, |
| @@ -1954,6 +1979,7 @@ static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma, · 60 unmodified lines | ||
| 1954 | 1979 | xe_exec_queue_last_fence_get(wait_exec_queue, vm); |
| 1955 | 1980 | |
| 1956 | 1981 | xe_sync_entry_signal(&syncs[i], NULL, fence); |
| 1982 | + dma_fence_put(fence); | |
| 1957 | 1983 | } |
| 1958 | 1984 | } |
| 1959 | 1985 | |
| @@ -2034,7 +2060,6 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, · 74 unmodified lines | ||
| 2034 | 2060 | struct drm_gem_object *obj = bo ? &bo->ttm.base : NULL; |
| 2035 | 2061 | struct drm_gpuva_ops *ops; |
| 2036 | 2062 | struct drm_gpuva_op *__op; |
| 2037 | − struct xe_vma_op *op; | |
| 2038 | 2063 | struct drm_gpuvm_bo *vm_bo; |
| 2039 | 2064 | int err; |
| 2040 | 2065 | |
| @@ -2081,15 +2106,6 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo, · 40 unmodified lines | ||
| 2081 | 2106 | if (IS_ERR(ops)) |
| 2082 | 2107 | return ops; |
| 2083 | 2108 | |
| 2084 | −#ifdef TEST_VM_ASYNC_OPS_ERROR | |
| 2085 | − if (operation & FORCE_ASYNC_OP_ERROR) { | |
| 2086 | − op = list_first_entry_or_null(&ops->list, struct xe_vma_op, | |
| 2087 | − base.entry); | |
| 2088 | − if (op) | |
| 2089 | − op->inject_error = true; | |
| 2090 | − } | |
| 2091 | −#endif | |
| 2092 | − | |
| 2093 | 2109 | drm_gpuva_for_each_op(__op, ops) { |
| 2094 | 2110 | struct xe_vma_op *op = gpuva_op_to_vma_op(__op); |
| 2095 | 2111 | |
| @@ -2145,7 +2161,7 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op, · 49 unmodified lines | ||
| 2145 | 2161 | drm_exec_fini(&exec); |
| 2146 | 2162 | |
| 2147 | 2163 | if (xe_vma_is_userptr(vma)) { |
| 2148 | − err = xe_vma_userptr_pin_pages(vma); | |
| 2164 | + err = xe_vma_userptr_pin_pages(to_userptr_vma(vma)); | |
| 2149 | 2165 | if (err) { |
| 2150 | 2166 | prep_vma_destroy(vm, vma, false); |
| 2151 | 2167 | xe_vma_destroy_unlocked(vma); |
| @@ -2169,8 +2185,10 @@ static u64 xe_vma_max_pte_size(struct xe_vma *vma) · 17 unmodified lines | ||
| 2169 | 2185 | return SZ_1G; |
| 2170 | 2186 | else if (vma->gpuva.flags & XE_VMA_PTE_2M) |
| 2171 | 2187 | return SZ_2M; |
| 2188 | + else if (vma->gpuva.flags & XE_VMA_PTE_4K) | |
| 2189 | + return SZ_4K; | |
| 2172 | 2190 | |
| 2173 | − return SZ_4K; | |
| 2191 | + return SZ_1G; /* Uninitialized, used max size */ | |
| 2174 | 2192 | } |
| 2175 | 2193 | |
| 2176 | 2194 | static u64 xe_vma_set_pte_size(struct xe_vma *vma, u64 size) |
| @@ -2500,13 +2518,25 @@ retry_userptr: · 323 unmodified lines | ||
| 2500 | 2518 | } |
| 2501 | 2519 | drm_exec_fini(&exec); |
| 2502 | 2520 | |
| 2503 | − if (err == -EAGAIN && xe_vma_is_userptr(vma)) { | |
| 2521 | + if (err == -EAGAIN) { | |
| 2504 | 2522 | lockdep_assert_held_write(&vm->lock); |
| 2505 | − err = xe_vma_userptr_pin_pages(vma); | |
| 2506 | − if (!err) | |
| 2507 | − goto retry_userptr; | |
| 2508 | 2523 | |
| 2509 | − trace_xe_vma_fail(vma); | |
| 2524 | + if (op->base.op == DRM_GPUVA_OP_REMAP) { | |
| 2525 | + if (!op->remap.unmap_done) | |
| 2526 | + vma = gpuva_to_vma(op->base.remap.unmap->va); | |
| 2527 | + else if (op->remap.prev) | |
| 2528 | + vma = op->remap.prev; | |
| 2529 | + else | |
| 2530 | + vma = op->remap.next; | |
| 2531 | + } | |
| 2532 | + | |
| 2533 | + if (xe_vma_is_userptr(vma)) { | |
| 2534 | + err = xe_vma_userptr_pin_pages(to_userptr_vma(vma)); | |
| 2535 | + if (!err) | |
| 2536 | + goto retry_userptr; | |
| 2537 | + | |
| 2538 | + trace_xe_vma_fail(vma); | |
| 2539 | + } | |
| 2510 | 2540 | } |
| 2511 | 2541 | |
| 2512 | 2542 | return err; |
| @@ -2518,13 +2548,6 @@ static int xe_vma_op_execute(struct xe_vm *vm, struct xe_vma_op *op) · 5 unmodified lines | ||
| 2518 | 2548 | |
| 2519 | 2549 | lockdep_assert_held_write(&vm->lock); |
| 2520 | 2550 | |
| 2521 | −#ifdef TEST_VM_ASYNC_OPS_ERROR | |
| 2522 | − if (op->inject_error) { | |
| 2523 | − op->inject_error = false; | |
| 2524 | − return -ENOMEM; | |
| 2525 | − } | |
| 2526 | −#endif | |
| 2527 | − | |
| 2528 | 2551 | switch (op->base.op) { |
| 2529 | 2552 | case DRM_GPUVA_OP_MAP: |
| 2530 | 2553 | ret = __xe_vma_op_execute(vm, op->map.vma, op); |
| @@ -2639,7 +2662,7 @@ static void vm_bind_ioctl_ops_unwind(struct xe_vm *vm, · 108 unmodified lines | ||
| 2639 | 2662 | { |
| 2640 | 2663 | int i; |
| 2641 | 2664 | |
| 2642 | − for (i = num_ops_list - 1; i; ++i) { | |
| 2665 | + for (i = num_ops_list - 1; i >= 0; --i) { | |
| 2643 | 2666 | struct drm_gpuva_ops *__ops = ops[i]; |
| 2644 | 2667 | struct drm_gpuva_op *__op; |
| 2645 | 2668 | |
| @@ -2684,16 +2707,9 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm, · 38 unmodified lines | ||
| 2684 | 2707 | return 0; |
| 2685 | 2708 | } |
| 2686 | 2709 | |
| 2687 | −#ifdef TEST_VM_ASYNC_OPS_ERROR | |
| 2688 | −#define SUPPORTED_FLAGS \ | |
| 2689 | − (FORCE_ASYNC_OP_ERROR | DRM_XE_VM_BIND_FLAG_READONLY | \ | |
| 2690 | − DRM_XE_VM_BIND_FLAG_IMMEDIATE | DRM_XE_VM_BIND_FLAG_NULL | 0xffff) | |
| 2691 | −#else | |
| 2692 | 2710 | #define SUPPORTED_FLAGS \ |
| 2693 | 2711 | (DRM_XE_VM_BIND_FLAG_READONLY | \ |
| 2694 | − DRM_XE_VM_BIND_FLAG_IMMEDIATE | DRM_XE_VM_BIND_FLAG_NULL | \ | |
| 2695 | − 0xffff) | |
| 2696 | −#endif | |
| 2712 | + DRM_XE_VM_BIND_FLAG_IMMEDIATE | DRM_XE_VM_BIND_FLAG_NULL) | |
| 2697 | 2713 | #define XE_64K_PAGE_MASK 0xffffull |
| 2698 | 2714 | #define ALL_DRM_XE_SYNCS_FLAGS (DRM_XE_SYNCS_FLAG_WAIT_FOR_OP) |
| 2699 | 2715 | |
| @@ -2846,7 +2862,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 146 unmodified lines | ||
| 2846 | 2862 | struct drm_gpuva_ops **ops = NULL; |
| 2847 | 2863 | struct xe_vm *vm; |
| 2848 | 2864 | struct xe_exec_queue *q = NULL; |
| 2849 | − u32 num_syncs; | |
| 2865 | + u32 num_syncs, num_ufence = 0; | |
| 2850 | 2866 | struct xe_sync_entry *syncs = NULL; |
| 2851 | 2867 | struct drm_xe_vm_bind_op *bind_ops; |
| 2852 | 2868 | LIST_HEAD(ops_list); |
| @@ -2983,6 +2999,14 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file) · 130 unmodified lines | ||
| 2983 | 2999 | SYNC_PARSE_FLAG_DISALLOW_USER_FENCE : 0)); |
| 2984 | 3000 | if (err) |
| 2985 | 3001 | goto free_syncs; |
| 3002 | + | |
| 3003 | + if (xe_sync_is_ufence(&syncs[num_syncs])) | |
| 3004 | + num_ufence++; | |
| 3005 | + } | |
| 3006 | + | |
| 3007 | + if (XE_IOCTL_DBG(xe, num_ufence > 1)) { | |
| 3008 | + err = -EINVAL; | |
| 3009 | + goto free_syncs; | |
| 2986 | 3010 | } |
| 2987 | 3011 | |
| 2988 | 3012 | if (!args->num_binds) { |
| @@ -3125,8 +3149,8 @@ int xe_vm_invalidate_vma(struct xe_vma *vma) · 136 unmodified lines | ||
| 3125 | 3149 | if (IS_ENABLED(CONFIG_PROVE_LOCKING)) { |
| 3126 | 3150 | if (xe_vma_is_userptr(vma)) { |
| 3127 | 3151 | WARN_ON_ONCE(!mmu_interval_check_retry |
| 3128 | − (&vma->userptr.notifier, | |
| 3129 | − vma->userptr.notifier_seq)); | |
| 3152 | + (&to_userptr_vma(vma)->userptr.notifier, | |
| 3153 | + to_userptr_vma(vma)->userptr.notifier_seq)); | |
| 3130 | 3154 | WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)), |
| 3131 | 3155 | DMA_RESV_USAGE_BOOKKEEP)); |
| 3132 | 3156 | |
| @@ -3187,11 +3211,11 @@ int xe_analyze_vm(struct drm_printer *p, struct xe_vm *vm, int gt_id) · 54 unmodified lines | ||
| 3187 | 3211 | if (is_null) { |
| 3188 | 3212 | addr = 0; |
| 3189 | 3213 | } else if (is_userptr) { |
| 3214 | + struct sg_table *sg = to_userptr_vma(vma)->userptr.sg; | |
| 3190 | 3215 | struct xe_res_cursor cur; |
| 3191 | 3216 | |
| 3192 | − if (vma->userptr.sg) { | |
| 3193 | − xe_res_first_sg(vma->userptr.sg, 0, XE_PAGE_SIZE, | |
| 3194 | − &cur); | |
| 3217 | + if (sg) { | |
| 3218 | + xe_res_first_sg(sg, 0, XE_PAGE_SIZE, &cur); | |
| 3195 | 3219 | addr = xe_res_dma(&cur); |
| 3196 | 3220 | } else { |
| 3197 | 3221 | addr = 0; |
| @@ -160,6 +160,18 @@ static inline bool xe_vma_is_userptr(struct xe_vma *vma) · 159 unmodified lines | ||
| 160 | 160 | return xe_vma_has_no_bo(vma) && !xe_vma_is_null(vma); |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | +/** | |
| 164 | + * to_userptr_vma() - Return a pointer to an embedding userptr vma | |
| 165 | + * @vma: Pointer to the embedded struct xe_vma | |
| 166 | + * | |
| 167 | + * Return: Pointer to the embedding userptr vma | |
| 168 | + */ | |
| 169 | +static inline struct xe_userptr_vma *to_userptr_vma(struct xe_vma *vma) | |
| 170 | +{ | |
| 171 | + xe_assert(xe_vma_vm(vma)->xe, xe_vma_is_userptr(vma)); | |
| 172 | + return container_of(vma, struct xe_userptr_vma, vma); | |
| 173 | +} | |
| 174 | + | |
| 163 | 175 | u64 xe_vm_pdp4_descriptor(struct xe_vm *vm, struct xe_tile *tile); |
| 164 | 176 | |
| 165 | 177 | int xe_vm_create_ioctl(struct drm_device *dev, void *data, |
| @@ -224,9 +236,9 @@ static inline void xe_vm_reactivate_rebind(struct xe_vm *vm) · 58 unmodified lines | ||
| 224 | 236 | } |
| 225 | 237 | } |
| 226 | 238 | |
| 227 | −int xe_vma_userptr_pin_pages(struct xe_vma *vma); | |
| 239 | +int xe_vma_userptr_pin_pages(struct xe_userptr_vma *uvma); | |
| 228 | 240 | |
| 229 | −int xe_vma_userptr_check_repin(struct xe_vma *vma); | |
| 241 | +int xe_vma_userptr_check_repin(struct xe_userptr_vma *uvma); | |
| 230 | 242 | |
| 231 | 243 | bool xe_vm_validate_should_retry(struct drm_exec *exec, int err, ktime_t *end); |
| 232 | 244 | |
| @@ -21,9 +21,6 @@ struct xe_bo; · 20 unmodified lines | ||
| 21 | 21 | struct xe_sync_entry; |
| 22 | 22 | struct xe_vm; |
| 23 | 23 | |
| 24 | −#define TEST_VM_ASYNC_OPS_ERROR | |
| 25 | −#define FORCE_ASYNC_OP_ERROR BIT(31) | |
| 26 | − | |
| 27 | 24 | #define XE_VMA_READ_ONLY DRM_GPUVA_USERBITS |
| 28 | 25 | #define XE_VMA_DESTROYED (DRM_GPUVA_USERBITS << 1) |
| 29 | 26 | #define XE_VMA_ATOMIC_PTE_BIT (DRM_GPUVA_USERBITS << 2) |
| @@ -37,6 +34,8 @@ struct xe_vm; · 7 unmodified lines | ||
| 37 | 34 | struct xe_userptr { |
| 38 | 35 | /** @invalidate_link: Link for the vm::userptr.invalidated list */ |
| 39 | 36 | struct list_head invalidate_link; |
| 37 | + /** @userptr: link into VM repin list if userptr. */ | |
| 38 | + struct list_head repin_link; | |
| 40 | 39 | /** |
| 41 | 40 | * @notifier: MMU notifier for user pointer (invalidation call back) |
| 42 | 41 | */ |
| @@ -68,8 +67,6 @@ struct xe_vma { · 25 unmodified lines | ||
| 68 | 67 | * resv. |
| 69 | 68 | */ |
| 70 | 69 | union { |
| 71 | − /** @userptr: link into VM repin list if userptr. */ | |
| 72 | − struct list_head userptr; | |
| 73 | 70 | /** @rebind: link into VM if this VMA needs rebinding. */ |
| 74 | 71 | struct list_head rebind; |
| 75 | 72 | /** @destroy: link to contested list when VM is being closed. */ |
| @@ -105,11 +102,15 @@ struct xe_vma { · 29 unmodified lines | ||
| 105 | 102 | * @pat_index: The pat index to use when encoding the PTEs for this vma. |
| 106 | 103 | */ |
| 107 | 104 | u16 pat_index; |
| 105 | +}; | |
| 108 | 106 | |
| 109 | − /** | |
| 110 | − * @userptr: user pointer state, only allocated for VMAs that are | |
| 111 | − * user pointers | |
| 112 | − */ | |
| 107 | +/** | |
| 108 | + * struct xe_userptr_vma - A userptr vma subclass | |
| 109 | + * @vma: The vma. | |
| 110 | + * @userptr: Additional userptr information. | |
| 111 | + */ | |
| 112 | +struct xe_userptr_vma { | |
| 113 | + struct xe_vma vma; | |
| 113 | 114 | struct xe_userptr userptr; |
| 114 | 115 | }; |
| 115 | 116 | |
| @@ -356,11 +357,6 @@ struct xe_vma_op { · 240 unmodified lines | ||
| 356 | 357 | /** @flags: operation flags */ |
| 357 | 358 | enum xe_vma_op_flags flags; |
| 358 | 359 | |
| 359 | −#ifdef TEST_VM_ASYNC_OPS_ERROR | |
| 360 | − /** @inject_error: inject error to test async op error handling */ | |
| 361 | − bool inject_error; | |
| 362 | −#endif | |
| 363 | − | |
| 364 | 360 | union { |
| 365 | 361 | /** @map: VMA map operation specific data */ |
| 366 | 362 | struct xe_vma_op_map map; |
| @@ -143,6 +143,9 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s · 142 unmodified lines | ||
| 143 | 143 | } |
| 144 | 144 | EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup); |
| 145 | 145 | |
| 146 | +/* Disables missing prototype warnings */ | |
| 147 | +__bpf_kfunc_start_defs(); | |
| 148 | + | |
| 146 | 149 | /** |
| 147 | 150 | * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx |
| 148 | 151 | * |
| @@ -152,7 +155,7 @@ EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup); · 3 unmodified lines | ||
| 152 | 155 | * |
| 153 | 156 | * @returns %NULL on error, an %__u8 memory pointer on success |
| 154 | 157 | */ |
| 155 | −noinline __u8 * | |
| 158 | +__bpf_kfunc __u8 * | |
| 156 | 159 | hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size) |
| 157 | 160 | { |
| 158 | 161 | struct hid_bpf_ctx_kern *ctx_kern; |
| @@ -167,6 +170,7 @@ hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr · 8 unmodified lines | ||
| 167 | 170 | |
| 168 | 171 | return ctx_kern->data + offset; |
| 169 | 172 | } |
| 173 | +__bpf_kfunc_end_defs(); | |
| 170 | 174 | |
| 171 | 175 | /* |
| 172 | 176 | * The following set contains all functions we agree BPF programs |
| @@ -241,6 +245,42 @@ int hid_bpf_reconnect(struct hid_device *hdev) · 68 unmodified lines | ||
| 241 | 245 | return 0; |
| 242 | 246 | } |
| 243 | 247 | |
| 248 | +static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog, | |
| 249 | + __u32 flags) | |
| 250 | +{ | |
| 251 | + int fd, err, prog_type; | |
| 252 | + | |
| 253 | + prog_type = hid_bpf_get_prog_attach_type(prog); | |
| 254 | + if (prog_type < 0) | |
| 255 | + return prog_type; | |
| 256 | + | |
| 257 | + if (prog_type >= HID_BPF_PROG_TYPE_MAX) | |
| 258 | + return -EINVAL; | |
| 259 | + | |
| 260 | + if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) { | |
| 261 | + err = hid_bpf_allocate_event_data(hdev); | |
| 262 | + if (err) | |
| 263 | + return err; | |
| 264 | + } | |
| 265 | + | |
| 266 | + fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags); | |
| 267 | + if (fd < 0) | |
| 268 | + return fd; | |
| 269 | + | |
| 270 | + if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) { | |
| 271 | + err = hid_bpf_reconnect(hdev); | |
| 272 | + if (err) { | |
| 273 | + close_fd(fd); | |
| 274 | + return err; | |
| 275 | + } | |
| 276 | + } | |
| 277 | + | |
| 278 | + return fd; | |
| 279 | +} | |
| 280 | + | |
| 281 | +/* Disables missing prototype warnings */ | |
| 282 | +__bpf_kfunc_start_defs(); | |
| 283 | + | |
| 244 | 284 | /** |
| 245 | 285 | * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device |
| 246 | 286 | * |
| @@ -253,22 +293,17 @@ int hid_bpf_reconnect(struct hid_device *hdev) · 6 unmodified lines | ||
| 253 | 293 | * is pinned to the BPF file system). |
| 254 | 294 | */ |
| 255 | 295 | /* called from syscall */ |
| 256 | −noinline int | |
| 296 | +__bpf_kfunc int | |
| 257 | 297 | hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags) |
| 258 | 298 | { |
| 259 | 299 | struct hid_device *hdev; |
| 300 | + struct bpf_prog *prog; | |
| 260 | 301 | struct device *dev; |
| 261 | − int fd, err, prog_type = hid_bpf_get_prog_attach_type(prog_fd); | |
| 302 | + int err, fd; | |
| 262 | 303 | |
| 263 | 304 | if (!hid_bpf_ops) |
| 264 | 305 | return -EINVAL; |
| 265 | 306 | |
| 266 | − if (prog_type < 0) | |
| 267 | − return prog_type; | |
| 268 | − | |
| 269 | − if (prog_type >= HID_BPF_PROG_TYPE_MAX) | |
| 270 | − return -EINVAL; | |
| 271 | − | |
| 272 | 307 | if ((flags & ~HID_BPF_FLAG_MASK)) |
| 273 | 308 | return -EINVAL; |
| 274 | 309 | |
| @@ -278,25 +313,29 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags) · 3 unmodified lines | ||
| 278 | 313 | |
| 279 | 314 | hdev = to_hid_device(dev); |
| 280 | 315 | |
| 281 | − if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) { | |
| 282 | − err = hid_bpf_allocate_event_data(hdev); | |
| 283 | − if (err) | |
| 284 | − return err; | |
| 316 | + /* | |
| 317 | + * take a ref on the prog itself, it will be released | |
| 318 | + * on errors or when it'll be detached | |
| 319 | + */ | |
| 320 | + prog = bpf_prog_get(prog_fd); | |
| 321 | + if (IS_ERR(prog)) { | |
| 322 | + err = PTR_ERR(prog); | |
| 323 | + goto out_dev_put; | |
| 285 | 324 | } |
| 286 | 325 | |
| 287 | − fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags); | |
| 288 | − if (fd < 0) | |
| 289 | − return fd; | |
| 290 | − | |
| 291 | − if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) { | |
| 292 | − err = hid_bpf_reconnect(hdev); | |
| 293 | − if (err) { | |
| 294 | − close_fd(fd); | |
| 295 | − return err; | |
| 296 | − } | |
| 326 | + fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags); | |
| 327 | + if (fd < 0) { | |
| 328 | + err = fd; | |
| 329 | + goto out_prog_put; | |
| 297 | 330 | } |
| 298 | 331 | |
| 299 | 332 | return fd; |
| 333 | + | |
| 334 | + out_prog_put: | |
| 335 | + bpf_prog_put(prog); | |
| 336 | + out_dev_put: | |
| 337 | + put_device(dev); | |
| 338 | + return err; | |
| 300 | 339 | } |
| 301 | 340 | |
| 302 | 341 | /** |
| @@ -306,7 +345,7 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags) · 3 unmodified lines | ||
| 306 | 345 | * |
| 307 | 346 | * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error. |
| 308 | 347 | */ |
| 309 | −noinline struct hid_bpf_ctx * | |
| 348 | +__bpf_kfunc struct hid_bpf_ctx * | |
| 310 | 349 | hid_bpf_allocate_context(unsigned int hid_id) |
| 311 | 350 | { |
| 312 | 351 | struct hid_device *hdev; |
| @@ -323,8 +362,10 @@ hid_bpf_allocate_context(unsigned int hid_id) · 10 unmodified lines | ||
| 323 | 362 | hdev = to_hid_device(dev); |
| 324 | 363 | |
| 325 | 364 | ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL); |
| 326 | − if (!ctx_kern) | |
| 365 | + if (!ctx_kern) { | |
| 366 | + put_device(dev); | |
| 327 | 367 | return NULL; |
| 368 | + } | |
| 328 | 369 | |
| 329 | 370 | ctx_kern->ctx.hid = hdev; |
| 330 | 371 | |
| @@ -337,14 +378,19 @@ hid_bpf_allocate_context(unsigned int hid_id) · 6 unmodified lines | ||
| 337 | 378 | * @ctx: the HID-BPF context to release |
| 338 | 379 | * |
| 339 | 380 | */ |
| 340 | −noinline void | |
| 381 | +__bpf_kfunc void | |
| 341 | 382 | hid_bpf_release_context(struct hid_bpf_ctx *ctx) |
| 342 | 383 | { |
| 343 | 384 | struct hid_bpf_ctx_kern *ctx_kern; |
| 385 | + struct hid_device *hid; | |
| 344 | 386 | |
| 345 | 387 | ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx); |
| 388 | + hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */ | |
| 346 | 389 | |
| 347 | 390 | kfree(ctx_kern); |
| 391 | + | |
| 392 | + /* get_device() is called by bus_find_device() */ | |
| 393 | + put_device(&hid->dev); | |
| 348 | 394 | } |
| 349 | 395 | |
| 350 | 396 | /** |
| @@ -358,7 +404,7 @@ hid_bpf_release_context(struct hid_bpf_ctx *ctx) · 7 unmodified lines | ||
| 358 | 404 | * |
| 359 | 405 | * @returns %0 on success, a negative error code otherwise. |
| 360 | 406 | */ |
| 361 | −noinline int | |
| 407 | +__bpf_kfunc int | |
| 362 | 408 | hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, |
| 363 | 409 | enum hid_report_type rtype, enum hid_class_request reqtype) |
| 364 | 410 | { |
| @@ -426,6 +472,7 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, · 61 unmodified lines | ||
| 426 | 472 | kfree(dma_data); |
| 427 | 473 | return ret; |
| 428 | 474 | } |
| 475 | +__bpf_kfunc_end_defs(); | |
| 429 | 476 | |
| 430 | 477 | /* our HID-BPF entrypoints */ |
| 431 | 478 | BTF_SET8_START(hid_bpf_fmodret_ids) |
| @@ -12,9 +12,9 @@ struct hid_bpf_ctx_kern { · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | int hid_bpf_preload_skel(void); |
| 14 | 14 | void hid_bpf_free_links_and_skel(void); |
| 15 | −int hid_bpf_get_prog_attach_type(int prog_fd); | |
| 15 | +int hid_bpf_get_prog_attach_type(struct bpf_prog *prog); | |
| 16 | 16 | int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd, |
| 17 | − __u32 flags); | |
| 17 | + struct bpf_prog *prog, __u32 flags); | |
| 18 | 18 | void __hid_bpf_destroy_device(struct hid_device *hdev); |
| 19 | 19 | int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type, |
| 20 | 20 | struct hid_bpf_ctx_kern *ctx_kern); |
| @@ -196,6 +196,7 @@ static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx) · 195 unmodified lines | ||
| 196 | 196 | static void hid_bpf_release_progs(struct work_struct *work) |
| 197 | 197 | { |
| 198 | 198 | int i, j, n, map_fd = -1; |
| 199 | + bool hdev_destroyed; | |
| 199 | 200 | |
| 200 | 201 | if (!jmp_table.map) |
| 201 | 202 | return; |
| @@ -220,6 +221,12 @@ static void hid_bpf_release_progs(struct work_struct *work) · 18 unmodified lines | ||
| 220 | 221 | if (entry->hdev) { |
| 221 | 222 | hdev = entry->hdev; |
| 222 | 223 | type = entry->type; |
| 224 | + /* | |
| 225 | + * hdev is still valid, even if we are called after hid_destroy_device(): | |
| 226 | + * when hid_bpf_attach() gets called, it takes a ref on the dev through | |
| 227 | + * bus_find_device() | |
| 228 | + */ | |
| 229 | + hdev_destroyed = hdev->bpf.destroyed; | |
| 223 | 230 | |
| 224 | 231 | hid_bpf_populate_hdev(hdev, type); |
| 225 | 232 | |
| @@ -232,12 +239,19 @@ static void hid_bpf_release_progs(struct work_struct *work) · 6 unmodified lines | ||
| 232 | 239 | if (test_bit(next->idx, jmp_table.enabled)) |
| 233 | 240 | continue; |
| 234 | 241 | |
| 235 | − if (next->hdev == hdev && next->type == type) | |
| 242 | + if (next->hdev == hdev && next->type == type) { | |
| 243 | + /* | |
| 244 | + * clear the hdev reference and decrement the device ref | |
| 245 | + * that was taken during bus_find_device() while calling | |
| 246 | + * hid_bpf_attach() | |
| 247 | + */ | |
| 236 | 248 | next->hdev = NULL; |
| 249 | + put_device(&hdev->dev); | |
| 250 | + } | |
| 237 | 251 | } |
| 238 | 252 | |
| 239 | − /* if type was rdesc fixup, reconnect device */ | |
| 240 | − if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP) | |
| 253 | + /* if type was rdesc fixup and the device is not gone, reconnect device */ | |
| 254 | + if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && !hdev_destroyed) | |
| 241 | 255 | hid_bpf_reconnect(hdev); |
| 242 | 256 | } |
| 243 | 257 | } |
| @@ -333,15 +347,10 @@ static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog) · 89 unmodified lines | ||
| 333 | 347 | return err; |
| 334 | 348 | } |
| 335 | 349 | |
| 336 | −int hid_bpf_get_prog_attach_type(int prog_fd) | |
| 350 | +int hid_bpf_get_prog_attach_type(struct bpf_prog *prog) | |
| 337 | 351 | { |
| 338 | − struct bpf_prog *prog = NULL; | |
| 339 | − int i; | |
| 340 | 352 | int prog_type = HID_BPF_PROG_TYPE_UNDEF; |
| 341 | − | |
| 342 | − prog = bpf_prog_get(prog_fd); | |
| 343 | − if (IS_ERR(prog)) | |
| 344 | − return PTR_ERR(prog); | |
| 353 | + int i; | |
| 345 | 354 | |
| 346 | 355 | for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) { |
| 347 | 356 | if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) { |
| @@ -350,8 +359,6 @@ int hid_bpf_get_prog_attach_type(int prog_fd) · 2 unmodified lines | ||
| 350 | 359 | } |
| 351 | 360 | } |
| 352 | 361 | |
| 353 | − bpf_prog_put(prog); | |
| 354 | − | |
| 355 | 362 | return prog_type; |
| 356 | 363 | } |
| 357 | 364 | |
| @@ -388,19 +395,13 @@ static const struct bpf_link_ops hid_bpf_link_lops = { · 30 unmodified lines | ||
| 388 | 395 | /* called from syscall */ |
| 389 | 396 | noinline int |
| 390 | 397 | __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, |
| 391 | − int prog_fd, __u32 flags) | |
| 398 | + int prog_fd, struct bpf_prog *prog, __u32 flags) | |
| 392 | 399 | { |
| 393 | 400 | struct bpf_link_primer link_primer; |
| 394 | 401 | struct hid_bpf_link *link; |
| 395 | − struct bpf_prog *prog = NULL; | |
| 396 | 402 | struct hid_bpf_prog_entry *prog_entry; |
| 397 | 403 | int cnt, err = -EINVAL, prog_table_idx = -1; |
| 398 | 404 | |
| 399 | − /* take a ref on the prog itself */ | |
| 400 | − prog = bpf_prog_get(prog_fd); | |
| 401 | − if (IS_ERR(prog)) | |
| 402 | − return PTR_ERR(prog); | |
| 403 | − | |
| 404 | 405 | mutex_lock(&hid_bpf_attach_lock); |
| 405 | 406 | |
| 406 | 407 | link = kzalloc(sizeof(*link), GFP_USER); |
| @@ -467,7 +468,6 @@ __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, · 60 unmodified lines | ||
| 467 | 468 | err_unlock: |
| 468 | 469 | mutex_unlock(&hid_bpf_attach_lock); |
| 469 | 470 | |
| 470 | − bpf_prog_put(prog); | |
| 471 | 471 | kfree(link); |
| 472 | 472 | |
| 473 | 473 | return err; |
| @@ -298,6 +298,9 @@ · 297 unmodified lines | ||
| 298 | 298 | |
| 299 | 299 | #define USB_VENDOR_ID_CIDC 0x1677 |
| 300 | 300 | |
| 301 | +#define I2C_VENDOR_ID_CIRQUE 0x0488 | |
| 302 | +#define I2C_PRODUCT_ID_CIRQUE_1063 0x1063 | |
| 303 | + | |
| 301 | 304 | #define USB_VENDOR_ID_CJTOUCH 0x24b8 |
| 302 | 305 | #define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020 |
| 303 | 306 | #define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040 0x0040 |
| @@ -4610,6 +4610,8 @@ static const struct hid_device_id hidpp_devices[] = { · 4609 unmodified lines | ||
| 4610 | 4610 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) }, |
| 4611 | 4611 | { /* Logitech G Pro X Superlight Gaming Mouse over USB */ |
| 4612 | 4612 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC094) }, |
| 4613 | + { /* Logitech G Pro X Superlight 2 Gaming Mouse over USB */ | |
| 4614 | + HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC09b) }, | |
| 4613 | 4615 | |
| 4614 | 4616 | { /* G935 Gaming Headset */ |
| 4615 | 4617 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87), |
| @@ -800,6 +800,8 @@ static inline int thunderstrike_led_create(struct thunderstrike *ts) · 799 unmodified lines | ||
| 800 | 800 | |
| 801 | 801 | led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, |
| 802 | 802 | "thunderstrike%d:blue:led", ts->id); |
| 803 | + if (!led->name) | |
| 804 | + return -ENOMEM; | |
| 803 | 805 | led->max_brightness = 1; |
| 804 | 806 | led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN; |
| 805 | 807 | led->brightness_get = &thunderstrike_led_get_brightness; |
| @@ -831,6 +833,8 @@ static inline int thunderstrike_psy_create(struct shield_device *shield_dev) · 25 unmodified lines | ||
| 831 | 833 | shield_dev->battery_dev.desc.name = |
| 832 | 834 | devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, |
| 833 | 835 | "thunderstrike_%d", ts->id); |
| 836 | + if (!shield_dev->battery_dev.desc.name) | |
| 837 | + return -ENOMEM; | |
| 834 | 838 | |
| 835 | 839 | shield_dev->battery_dev.psy = power_supply_register( |
| 836 | 840 | &hdev->dev, &shield_dev->battery_dev.desc, &psy_cfg); |
| @@ -1109,10 +1109,9 @@ static int steam_probe(struct hid_device *hdev, · 1108 unmodified lines | ||
| 1109 | 1109 | return hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
| 1110 | 1110 | |
| 1111 | 1111 | steam = devm_kzalloc(&hdev->dev, sizeof(*steam), GFP_KERNEL); |
| 1112 | − if (!steam) { | |
| 1113 | − ret = -ENOMEM; | |
| 1114 | − goto steam_alloc_fail; | |
| 1115 | − } | |
| 1112 | + if (!steam) | |
| 1113 | + return -ENOMEM; | |
| 1114 | + | |
| 1116 | 1115 | steam->hdev = hdev; |
| 1117 | 1116 | hid_set_drvdata(hdev, steam); |
| 1118 | 1117 | spin_lock_init(&steam->lock); |
| @@ -1129,14 +1128,14 @@ static int steam_probe(struct hid_device *hdev, · 10 unmodified lines | ||
| 1129 | 1128 | */ |
| 1130 | 1129 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDRAW); |
| 1131 | 1130 | if (ret) |
| 1132 | − goto hid_hw_start_fail; | |
| 1131 | + goto err_cancel_work; | |
| 1133 | 1132 | |
| 1134 | 1133 | ret = hid_hw_open(hdev); |
| 1135 | 1134 | if (ret) { |
| 1136 | 1135 | hid_err(hdev, |
| 1137 | 1136 | "%s:hid_hw_open\n", |
| 1138 | 1137 | __func__); |
| 1139 | − goto hid_hw_open_fail; | |
| 1138 | + goto err_hw_stop; | |
| 1140 | 1139 | } |
| 1141 | 1140 | |
| 1142 | 1141 | if (steam->quirks & STEAM_QUIRK_WIRELESS) { |
| @@ -1152,36 +1151,37 @@ static int steam_probe(struct hid_device *hdev, · 9 unmodified lines | ||
| 1152 | 1151 | hid_err(hdev, |
| 1153 | 1152 | "%s:steam_register failed with error %d\n", |
| 1154 | 1153 | __func__, ret); |
| 1155 | − goto input_register_fail; | |
| 1154 | + goto err_hw_close; | |
| 1156 | 1155 | } |
| 1157 | 1156 | } |
| 1158 | 1157 | |
| 1159 | 1158 | steam->client_hdev = steam_create_client_hid(hdev); |
| 1160 | 1159 | if (IS_ERR(steam->client_hdev)) { |
| 1161 | 1160 | ret = PTR_ERR(steam->client_hdev); |
| 1162 | − goto client_hdev_fail; | |
| 1161 | + goto err_stream_unregister; | |
| 1163 | 1162 | } |
| 1164 | 1163 | steam->client_hdev->driver_data = steam; |
| 1165 | 1164 | |
| 1166 | 1165 | ret = hid_add_device(steam->client_hdev); |
| 1167 | 1166 | if (ret) |
| 1168 | − goto client_hdev_add_fail; | |
| 1167 | + goto err_destroy; | |
| 1169 | 1168 | |
| 1170 | 1169 | return 0; |
| 1171 | 1170 | |
| 1172 | −client_hdev_add_fail: | |
| 1173 | − hid_hw_stop(hdev); | |
| 1174 | −client_hdev_fail: | |
| 1171 | +err_destroy: | |
| 1175 | 1172 | hid_destroy_device(steam->client_hdev); |
| 1176 | −input_register_fail: | |
| 1177 | −hid_hw_open_fail: | |
| 1178 | −hid_hw_start_fail: | |
| 1173 | +err_stream_unregister: | |
| 1174 | + if (steam->connected) | |
| 1175 | + steam_unregister(steam); | |
| 1176 | +err_hw_close: | |
| 1177 | + hid_hw_close(hdev); | |
| 1178 | +err_hw_stop: | |
| 1179 | + hid_hw_stop(hdev); | |
| 1180 | +err_cancel_work: | |
| 1179 | 1181 | cancel_work_sync(&steam->work_connect); |
| 1180 | 1182 | cancel_delayed_work_sync(&steam->mode_switch); |
| 1181 | 1183 | cancel_work_sync(&steam->rumble_work); |
| 1182 | −steam_alloc_fail: | |
| 1183 | − hid_err(hdev, "%s: failed with error %d\n", | |
| 1184 | − __func__, ret); | |
| 1184 | + | |
| 1185 | 1185 | return ret; |
| 1186 | 1186 | } |
| 1187 | 1187 | |
| @@ -357,8 +357,11 @@ static int hidraw_release(struct inode * inode, struct file * file) · 356 unmodified lines | ||
| 357 | 357 | down_write(&minors_rwsem); |
| 358 | 358 | |
| 359 | 359 | spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags); |
| 360 | − for (int i = list->tail; i < list->head; i++) | |
| 361 | − kfree(list->buffer[i].value); | |
| 360 | + while (list->tail != list->head) { | |
| 361 | + kfree(list->buffer[list->tail].value); | |
| 362 | + list->buffer[list->tail].value = NULL; | |
| 363 | + list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); | |
| 364 | + } | |
| 362 | 365 | list_del(&list->node); |
| 363 | 366 | spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags); |
| 364 | 367 | kfree(list); |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #define I2C_HID_QUIRK_RESET_ON_RESUME BIT(2) |
| 50 | 50 | #define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(3) |
| 51 | 51 | #define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(4) |
| 52 | +#define I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND BIT(5) | |
| 52 | 53 | |
| 53 | 54 | /* Command opcodes */ |
| 54 | 55 | #define I2C_HID_OPCODE_RESET 0x01 |
| @@ -131,6 +132,8 @@ static const struct i2c_hid_quirks { · 76 unmodified lines | ||
| 131 | 132 | I2C_HID_QUIRK_RESET_ON_RESUME }, |
| 132 | 133 | { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720, |
| 133 | 134 | I2C_HID_QUIRK_BAD_INPUT_SIZE }, |
| 135 | + { I2C_VENDOR_ID_CIRQUE, I2C_PRODUCT_ID_CIRQUE_1063, | |
| 136 | + I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND }, | |
| 134 | 137 | /* |
| 135 | 138 | * Sending the wakeup after reset actually break ELAN touchscreen controller |
| 136 | 139 | */ |
| @@ -956,7 +959,8 @@ static int i2c_hid_core_suspend(struct i2c_hid *ihid, bool force_poweroff) · 819 unmodified lines | ||
| 956 | 959 | return ret; |
| 957 | 960 | |
| 958 | 961 | /* Save some power */ |
| 959 | − i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP); | |
| 962 | + if (!(ihid->quirks & I2C_HID_QUIRK_NO_SLEEP_ON_SUSPEND)) | |
| 963 | + i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP); | |
| 960 | 964 | |
| 961 | 965 | disable_irq(client->irq); |
| 962 | 966 | |
| @@ -87,6 +87,7 @@ static int i2c_hid_of_probe(struct i2c_client *client) · 86 unmodified lines | ||
| 87 | 87 | if (!ihid_of) |
| 88 | 88 | return -ENOMEM; |
| 89 | 89 | |
| 90 | + ihid_of->client = client; | |
| 90 | 91 | ihid_of->ops.power_up = i2c_hid_of_power_up; |
| 91 | 92 | ihid_of->ops.power_down = i2c_hid_of_power_down; |
| 92 | 93 | |
| @@ -195,6 +195,8 @@ struct aspeed_pwm_tacho_data { · 194 unmodified lines | ||
| 195 | 195 | u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS]; |
| 196 | 196 | struct aspeed_cooling_device *cdev[8]; |
| 197 | 197 | const struct attribute_group *groups[3]; |
| 198 | + /* protects access to shared ASPEED_PTCR_RESULT */ | |
| 199 | + struct mutex tach_lock; | |
| 198 | 200 | }; |
| 199 | 201 | |
| 200 | 202 | enum type { TYPEM, TYPEN, TYPEO }; |
| @@ -529,6 +531,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, · 328 unmodified lines | ||
| 529 | 531 | u8 fan_tach_ch_source, type, mode, both; |
| 530 | 532 | int ret; |
| 531 | 533 | |
| 534 | + mutex_lock(&priv->tach_lock); | |
| 535 | + | |
| 532 | 536 | regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); |
| 533 | 537 | regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); |
| 534 | 538 | |
| @@ -546,6 +550,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, · 11 unmodified lines | ||
| 546 | 550 | ASPEED_RPM_STATUS_SLEEP_USEC, |
| 547 | 551 | usec); |
| 548 | 552 | |
| 553 | + mutex_unlock(&priv->tach_lock); | |
| 554 | + | |
| 549 | 555 | /* return -ETIMEDOUT if we didn't get an answer. */ |
| 550 | 556 | if (ret) |
| 551 | 557 | return ret; |
| @@ -915,6 +921,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev) · 363 unmodified lines | ||
| 915 | 921 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); |
| 916 | 922 | if (!priv) |
| 917 | 923 | return -ENOMEM; |
| 924 | + mutex_init(&priv->tach_lock); | |
| 918 | 925 | priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, |
| 919 | 926 | &aspeed_pwm_tacho_regmap_config); |
| 920 | 927 | if (IS_ERR(priv->regmap)) |
| @@ -41,7 +41,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); · 40 unmodified lines | ||
| 41 | 41 | |
| 42 | 42 | #define PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */ |
| 43 | 43 | #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ |
| 44 | −#define NUM_REAL_CORES 128 /* Number of Real cores per cpu */ | |
| 44 | +#define NUM_REAL_CORES 512 /* Number of Real cores per cpu */ | |
| 45 | 45 | #define CORETEMP_NAME_LENGTH 28 /* String Length of attrs */ |
| 46 | 46 | #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ |
| 47 | 47 | #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) |
| @@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev, · 371 unmodified lines | ||
| 419 | 419 | } |
| 420 | 420 | |
| 421 | 421 | static int create_core_attrs(struct temp_data *tdata, struct device *dev, |
| 422 | − int attr_no) | |
| 422 | + int index) | |
| 423 | 423 | { |
| 424 | 424 | int i; |
| 425 | 425 | static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, |
| @@ -431,13 +431,20 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev, · 5 unmodified lines | ||
| 431 | 431 | }; |
| 432 | 432 | |
| 433 | 433 | for (i = 0; i < tdata->attr_size; i++) { |
| 434 | + /* | |
| 435 | + * We map the attr number to core id of the CPU | |
| 436 | + * The attr number is always core id + 2 | |
| 437 | + * The Pkgtemp will always show up as temp1_*, if available | |
| 438 | + */ | |
| 439 | + int attr_no = tdata->is_pkg_data ? 1 : tdata->cpu_core_id + 2; | |
| 440 | + | |
| 434 | 441 | snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, |
| 435 | 442 | "temp%d_%s", attr_no, suffixes[i]); |
| 436 | 443 | sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); |
| 437 | 444 | tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; |
| 438 | 445 | tdata->sd_attrs[i].dev_attr.attr.mode = 0444; |
| 439 | 446 | tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; |
| 440 | − tdata->sd_attrs[i].index = attr_no; | |
| 447 | + tdata->sd_attrs[i].index = index; | |
| 441 | 448 | tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr; |
| 442 | 449 | } |
| 443 | 450 | tdata->attr_group.attrs = tdata->attrs; |
| @@ -495,30 +502,25 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, · 51 unmodified lines | ||
| 495 | 502 | struct platform_data *pdata = platform_get_drvdata(pdev); |
| 496 | 503 | struct cpuinfo_x86 *c = &cpu_data(cpu); |
| 497 | 504 | u32 eax, edx; |
| 498 | − int err, index, attr_no; | |
| 505 | + int err, index; | |
| 499 | 506 | |
| 500 | 507 | if (!housekeeping_cpu(cpu, HK_TYPE_MISC)) |
| 501 | 508 | return 0; |
| 502 | 509 | |
| 503 | 510 | /* |
| 504 | − * Find attr number for sysfs: | |
| 505 | − * We map the attr number to core id of the CPU | |
| 506 | − * The attr number is always core id + 2 | |
| 507 | − * The Pkgtemp will always show up as temp1_*, if available | |
| 511 | + * Get the index of tdata in pdata->core_data[] | |
| 512 | + * tdata for package: pdata->core_data[1] | |
| 513 | + * tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1] | |
| 508 | 514 | */ |
| 509 | 515 | if (pkg_flag) { |
| 510 | − attr_no = PKG_SYSFS_ATTR_NO; | |
| 516 | + index = PKG_SYSFS_ATTR_NO; | |
| 511 | 517 | } else { |
| 512 | − index = ida_alloc(&pdata->ida, GFP_KERNEL); | |
| 518 | + index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL); | |
| 513 | 519 | if (index < 0) |
| 514 | 520 | return index; |
| 515 | − pdata->cpu_map[index] = topology_core_id(cpu); | |
| 516 | − attr_no = index + BASE_SYSFS_ATTR_NO; | |
| 517 | − } | |
| 518 | 521 | |
| 519 | − if (attr_no > MAX_CORE_DATA - 1) { | |
| 520 | − err = -ERANGE; | |
| 521 | − goto ida_free; | |
| 522 | + pdata->cpu_map[index] = topology_core_id(cpu); | |
| 523 | + index += BASE_SYSFS_ATTR_NO; | |
| 522 | 524 | } |
| 523 | 525 | |
| 524 | 526 | tdata = init_temp_data(cpu, pkg_flag); |
| @@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, · 19 unmodified lines | ||
| 544 | 546 | if (get_ttarget(tdata, &pdev->dev) >= 0) |
| 545 | 547 | tdata->attr_size++; |
| 546 | 548 | |
| 547 | − pdata->core_data[attr_no] = tdata; | |
| 549 | + pdata->core_data[index] = tdata; | |
| 548 | 550 | |
| 549 | 551 | /* Create sysfs interfaces */ |
| 550 | − err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no); | |
| 552 | + err = create_core_attrs(tdata, pdata->hwmon_dev, index); | |
| 551 | 553 | if (err) |
| 552 | 554 | goto exit_free; |
| 553 | 555 | |
| 554 | 556 | return 0; |
| 555 | 557 | exit_free: |
| 556 | − pdata->core_data[attr_no] = NULL; | |
| 558 | + pdata->core_data[index] = NULL; | |
| 557 | 559 | kfree(tdata); |
| 558 | 560 | ida_free: |
| 559 | 561 | if (!pkg_flag) |
| 560 | − ida_free(&pdata->ida, index); | |
| 562 | + ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO); | |
| 561 | 563 | return err; |
| 562 | 564 | } |
| 563 | 565 | |
| @@ -146,7 +146,7 @@ static int waterforce_get_status(struct waterforce_data *priv) · 145 unmodified lines | ||
| 146 | 146 | /* Send command for getting status */ |
| 147 | 147 | ret = waterforce_write_expanded(priv, get_status_cmd, GET_STATUS_CMD_LENGTH); |
| 148 | 148 | if (ret < 0) |
| 149 | − return ret; | |
| 149 | + goto unlock_and_return; | |
| 150 | 150 | |
| 151 | 151 | ret = wait_for_completion_interruptible_timeout(&priv->status_report_received, |
| 152 | 152 | msecs_to_jiffies(STATUS_VALIDITY)); |
| @@ -126,6 +126,21 @@ static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = { · 125 unmodified lines | ||
| 126 | 126 | |
| 127 | 127 | #define to_mp2975_data(x) container_of(x, struct mp2975_data, info) |
| 128 | 128 | |
| 129 | +static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg) | |
| 130 | +{ | |
| 131 | + switch (reg) { | |
| 132 | + case PMBUS_VOUT_MODE: | |
| 133 | + /* | |
| 134 | + * Report direct format as configured by MFR_DC_LOOP_CTRL. | |
| 135 | + * Unlike on MP2971/MP2973 the reported VOUT_MODE isn't automatically | |
| 136 | + * internally updated, but always reads as PB_VOUT_MODE_VID. | |
| 137 | + */ | |
| 138 | + return PB_VOUT_MODE_DIRECT; | |
| 139 | + default: | |
| 140 | + return -ENODATA; | |
| 141 | + } | |
| 142 | +} | |
| 143 | + | |
| 129 | 144 | static int |
| 130 | 145 | mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg, |
| 131 | 146 | u16 mask) |
| @@ -869,6 +884,7 @@ static struct pmbus_driver_info mp2975_info = { · 737 unmodified lines | ||
| 869 | 884 | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | |
| 870 | 885 | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | |
| 871 | 886 | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL, |
| 887 | + .read_byte_data = mp2975_read_byte_data, | |
| 872 | 888 | .read_word_data = mp2975_read_word_data, |
| 873 | 889 | #if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) |
| 874 | 890 | .num_regulators = 1, |
| @@ -294,6 +294,7 @@ static const struct xpad_device { · 293 unmodified lines | ||
| 294 | 294 | { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, |
| 295 | 295 | { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, |
| 296 | 296 | { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, |
| 297 | + { 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 }, | |
| 297 | 298 | { 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 }, |
| 298 | 299 | { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, |
| 299 | 300 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
| @@ -491,6 +492,7 @@ static const struct usb_device_id xpad_table[] = { · 191 unmodified lines | ||
| 491 | 492 | XPAD_XBOX360_VENDOR(0x15e4), /* Numark Xbox 360 controllers */ |
| 492 | 493 | XPAD_XBOX360_VENDOR(0x162e), /* Joytech Xbox 360 controllers */ |
| 493 | 494 | XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ |
| 495 | + XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */ | |
| 494 | 496 | XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ |
| 495 | 497 | XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ |
| 496 | 498 | XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ |
| @@ -811,7 +811,6 @@ static int atkbd_probe(struct atkbd *atkbd) · 810 unmodified lines | ||
| 811 | 811 | { |
| 812 | 812 | struct ps2dev *ps2dev = &atkbd->ps2dev; |
| 813 | 813 | unsigned char param[2]; |
| 814 | − bool skip_getid; | |
| 815 | 814 | |
| 816 | 815 | /* |
| 817 | 816 | * Some systems, where the bit-twiddling when testing the io-lines of the |
| @@ -825,6 +824,11 @@ static int atkbd_probe(struct atkbd *atkbd) · 7 unmodified lines | ||
| 825 | 824 | "keyboard reset failed on %s\n", |
| 826 | 825 | ps2dev->serio->phys); |
| 827 | 826 | |
| 827 | + if (atkbd_skip_getid(atkbd)) { | |
| 828 | + atkbd->id = 0xab83; | |
| 829 | + goto deactivate_kbd; | |
| 830 | + } | |
| 831 | + | |
| 828 | 832 | /* |
| 829 | 833 | * Then we check the keyboard ID. We should get 0xab83 under normal conditions. |
| 830 | 834 | * Some keyboards report different values, but the first byte is always 0xab or |
| @@ -833,18 +837,17 @@ static int atkbd_probe(struct atkbd *atkbd) · 2 unmodified lines | ||
| 833 | 837 | */ |
| 834 | 838 | |
| 835 | 839 | param[0] = param[1] = 0xa5; /* initialize with invalid values */ |
| 836 | − skip_getid = atkbd_skip_getid(atkbd); | |
| 837 | − if (skip_getid || ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { | |
| 840 | + if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) { | |
| 838 | 841 | |
| 839 | 842 | /* |
| 840 | − * If the get ID command was skipped or failed, we check if we can at least set | |
| 843 | + * If the get ID command failed, we check if we can at least set | |
| 841 | 844 | * the LEDs on the keyboard. This should work on every keyboard out there. |
| 842 | 845 | * It also turns the LEDs off, which we want anyway. |
| 843 | 846 | */ |
| 844 | 847 | param[0] = 0; |
| 845 | 848 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) |
| 846 | 849 | return -1; |
| 847 | − atkbd->id = skip_getid ? 0xab83 : 0xabba; | |
| 850 | + atkbd->id = 0xabba; | |
| 848 | 851 | return 0; |
| 849 | 852 | } |
| 850 | 853 | |
| @@ -860,6 +863,7 @@ static int atkbd_probe(struct atkbd *atkbd) · 9 unmodified lines | ||
| 860 | 863 | return -1; |
| 861 | 864 | } |
| 862 | 865 | |
| 866 | +deactivate_kbd: | |
| 863 | 867 | /* |
| 864 | 868 | * Make sure nothing is coming from the keyboard and disturbs our |
| 865 | 869 | * internal state. |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | * Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch) |
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | +#include "linux/usb.h" | |
| 22 | 23 | #include <linux/kernel.h> |
| 23 | 24 | #include <linux/errno.h> |
| 24 | 25 | #include <linux/slab.h> |
| @@ -193,6 +194,8 @@ enum tp_type { · 168 unmodified lines | ||
| 193 | 194 | |
| 194 | 195 | /* list of device capability bits */ |
| 195 | 196 | #define HAS_INTEGRATED_BUTTON 1 |
| 197 | +/* maximum number of supported endpoints (currently trackpad and button) */ | |
| 198 | +#define MAX_ENDPOINTS 2 | |
| 196 | 199 | |
| 197 | 200 | /* trackpad finger data block size */ |
| 198 | 201 | #define FSIZE_TYPE1 (14 * sizeof(__le16)) |
| @@ -891,6 +894,18 @@ static int bcm5974_resume(struct usb_interface *iface) · 692 unmodified lines | ||
| 891 | 894 | return error; |
| 892 | 895 | } |
| 893 | 896 | |
| 897 | +static bool bcm5974_check_endpoints(struct usb_interface *iface, | |
| 898 | + const struct bcm5974_config *cfg) | |
| 899 | +{ | |
| 900 | + u8 ep_addr[MAX_ENDPOINTS + 1] = {0}; | |
| 901 | + | |
| 902 | + ep_addr[0] = cfg->tp_ep; | |
| 903 | + if (cfg->tp_type == TYPE1) | |
| 904 | + ep_addr[1] = cfg->bt_ep; | |
| 905 | + | |
| 906 | + return usb_check_int_endpoints(iface, ep_addr); | |
| 907 | +} | |
| 908 | + | |
| 894 | 909 | static int bcm5974_probe(struct usb_interface *iface, |
| 895 | 910 | const struct usb_device_id *id) |
| 896 | 911 | { |
| @@ -903,6 +918,11 @@ static int bcm5974_probe(struct usb_interface *iface, · 6 unmodified lines | ||
| 903 | 918 | /* find the product index */ |
| 904 | 919 | cfg = bcm5974_get_config(udev); |
| 905 | 920 | |
| 921 | + if (!bcm5974_check_endpoints(iface, cfg)) { | |
| 922 | + dev_err(&iface->dev, "Unexpected non-int endpoint\n"); | |
| 923 | + return -ENODEV; | |
| 924 | + } | |
| 925 | + | |
| 906 | 926 | /* allocate memory for our device state and initialize it */ |
| 907 | 927 | dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); |
| 908 | 928 | input_dev = input_allocate_device(); |
| @@ -634,6 +634,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { · 633 unmodified lines | ||
| 634 | 634 | }, |
| 635 | 635 | .driver_data = (void *)(SERIO_QUIRK_NOAUX) |
| 636 | 636 | }, |
| 637 | + { | |
| 638 | + /* Fujitsu Lifebook U728 */ | |
| 639 | + .matches = { | |
| 640 | + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | |
| 641 | + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U728"), | |
| 642 | + }, | |
| 643 | + .driver_data = (void *)(SERIO_QUIRK_NOAUX) | |
| 644 | + }, | |
| 637 | 645 | { |
| 638 | 646 | /* Gigabyte M912 */ |
| 639 | 647 | .matches = { |
| @@ -1208,6 +1216,12 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { · 568 unmodified lines | ||
| 1208 | 1216 | SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | |
| 1209 | 1217 | SERIO_QUIRK_NOPNP) |
| 1210 | 1218 | }, |
| 1219 | + { | |
| 1220 | + .matches = { | |
| 1221 | + DMI_MATCH(DMI_BOARD_NAME, "NS5x_7xPU"), | |
| 1222 | + }, | |
| 1223 | + .driver_data = (void *)(SERIO_QUIRK_NOAUX) | |
| 1224 | + }, | |
| 1211 | 1225 | { |
| 1212 | 1226 | .matches = { |
| 1213 | 1227 | DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"), |
| @@ -884,7 +884,8 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) · 883 unmodified lines | ||
| 884 | 884 | } |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | − if (ts->gpio_count == 2 && ts->gpio_int_idx == 0) { | |
| 887 | + /* Some devices with gpio_int_idx 0 list a third unused GPIO */ | |
| 888 | + if ((ts->gpio_count == 2 || ts->gpio_count == 3) && ts->gpio_int_idx == 0) { | |
| 888 | 889 | ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; |
| 889 | 890 | gpio_mapping = acpi_goodix_int_first_gpios; |
| 890 | 891 | } else if (ts->gpio_count == 2 && ts->gpio_int_idx == 1) { |
| @@ -1799,7 +1799,7 @@ iommu_group_alloc_default_domain(struct iommu_group *group, int req_type) · 1798 unmodified lines | ||
| 1799 | 1799 | * domain. Do not use in new drivers. |
| 1800 | 1800 | */ |
| 1801 | 1801 | if (ops->default_domain) { |
| 1802 | − if (req_type) | |
| 1802 | + if (req_type != ops->default_domain->type) | |
| 1803 | 1803 | return ERR_PTR(-EINVAL); |
| 1804 | 1804 | return ops->default_domain; |
| 1805 | 1805 | } |
| @@ -1871,10 +1871,18 @@ static int iommu_get_def_domain_type(struct iommu_group *group, · 65 unmodified lines | ||
| 1871 | 1871 | const struct iommu_ops *ops = dev_iommu_ops(dev); |
| 1872 | 1872 | int type; |
| 1873 | 1873 | |
| 1874 | − if (!ops->def_domain_type) | |
| 1875 | − return cur_type; | |
| 1876 | − | |
| 1877 | − type = ops->def_domain_type(dev); | |
| 1874 | + if (ops->default_domain) { | |
| 1875 | + /* | |
| 1876 | + * Drivers that declare a global static default_domain will | |
| 1877 | + * always choose that. | |
| 1878 | + */ | |
| 1879 | + type = ops->default_domain->type; | |
| 1880 | + } else { | |
| 1881 | + if (ops->def_domain_type) | |
| 1882 | + type = ops->def_domain_type(dev); | |
| 1883 | + else | |
| 1884 | + return cur_type; | |
| 1885 | + } | |
| 1878 | 1886 | if (!type || cur_type == type) |
| 1879 | 1887 | return cur_type; |
| 1880 | 1888 | if (!cur_type) |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | #include "dm-ima.h" |
| 23 | 23 | |
| 24 | 24 | #define DM_RESERVED_MAX_IOS 1024 |
| 25 | +#define DM_MAX_TARGETS 1048576 | |
| 26 | +#define DM_MAX_TARGET_PARAMS 1024 | |
| 25 | 27 | |
| 26 | 28 | struct dm_io; |
| 27 | 29 | |
| @@ -73,10 +73,8 @@ struct dm_crypt_io { · 72 unmodified lines | ||
| 73 | 73 | struct bio *base_bio; |
| 74 | 74 | u8 *integrity_metadata; |
| 75 | 75 | bool integrity_metadata_from_pool:1; |
| 76 | − bool in_tasklet:1; | |
| 77 | 76 | |
| 78 | 77 | struct work_struct work; |
| 79 | − struct tasklet_struct tasklet; | |
| 80 | 78 | |
| 81 | 79 | struct convert_context ctx; |
| 82 | 80 | |
| @@ -1762,7 +1760,6 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc, · 1679 unmodified lines | ||
| 1762 | 1760 | io->ctx.r.req = NULL; |
| 1763 | 1761 | io->integrity_metadata = NULL; |
| 1764 | 1762 | io->integrity_metadata_from_pool = false; |
| 1765 | − io->in_tasklet = false; | |
| 1766 | 1763 | atomic_set(&io->io_pending, 0); |
| 1767 | 1764 | } |
| 1768 | 1765 | |
| @@ -1771,13 +1768,6 @@ static void crypt_inc_pending(struct dm_crypt_io *io) · 2 unmodified lines | ||
| 1771 | 1768 | atomic_inc(&io->io_pending); |
| 1772 | 1769 | } |
| 1773 | 1770 | |
| 1774 | −static void kcryptd_io_bio_endio(struct work_struct *work) | |
| 1775 | −{ | |
| 1776 | − struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work); | |
| 1777 | − | |
| 1778 | − bio_endio(io->base_bio); | |
| 1779 | −} | |
| 1780 | − | |
| 1781 | 1771 | /* |
| 1782 | 1772 | * One of the bios was finished. Check for completion of |
| 1783 | 1773 | * the whole request and correctly clean up the buffer. |
| @@ -1801,20 +1791,6 @@ static void crypt_dec_pending(struct dm_crypt_io *io) · 17 unmodified lines | ||
| 1801 | 1791 | |
| 1802 | 1792 | base_bio->bi_status = error; |
| 1803 | 1793 | |
| 1804 | − /* | |
| 1805 | − * If we are running this function from our tasklet, | |
| 1806 | − * we can't call bio_endio() here, because it will call | |
| 1807 | − * clone_endio() from dm.c, which in turn will | |
| 1808 | − * free the current struct dm_crypt_io structure with | |
| 1809 | − * our tasklet. In this case we need to delay bio_endio() | |
| 1810 | − * execution to after the tasklet is done and dequeued. | |
| 1811 | − */ | |
| 1812 | − if (io->in_tasklet) { | |
| 1813 | − INIT_WORK(&io->work, kcryptd_io_bio_endio); | |
| 1814 | − queue_work(cc->io_queue, &io->work); | |
| 1815 | − return; | |
| 1816 | − } | |
| 1817 | − | |
| 1818 | 1794 | bio_endio(base_bio); |
| 1819 | 1795 | } |
| 1820 | 1796 | |
| @@ -2246,11 +2222,6 @@ static void kcryptd_crypt(struct work_struct *work) · 425 unmodified lines | ||
| 2246 | 2222 | kcryptd_crypt_write_convert(io); |
| 2247 | 2223 | } |
| 2248 | 2224 | |
| 2249 | −static void kcryptd_crypt_tasklet(unsigned long work) | |
| 2250 | −{ | |
| 2251 | − kcryptd_crypt((struct work_struct *)work); | |
| 2252 | −} | |
| 2253 | − | |
| 2254 | 2225 | static void kcryptd_queue_crypt(struct dm_crypt_io *io) |
| 2255 | 2226 | { |
| 2256 | 2227 | struct crypt_config *cc = io->cc; |
| @@ -2262,15 +2233,10 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io) · 5 unmodified lines | ||
| 2262 | 2233 | * irqs_disabled(): the kernel may run some IO completion from the idle thread, but |
| 2263 | 2234 | * it is being executed with irqs disabled. |
| 2264 | 2235 | */ |
| 2265 | − if (in_hardirq() || irqs_disabled()) { | |
| 2266 | − io->in_tasklet = true; | |
| 2267 | − tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work); | |
| 2268 | − tasklet_schedule(&io->tasklet); | |
| 2236 | + if (!(in_hardirq() || irqs_disabled())) { | |
| 2237 | + kcryptd_crypt(&io->work); | |
| 2269 | 2238 | return; |
| 2270 | 2239 | } |
| 2271 | − | |
| 2272 | − kcryptd_crypt(&io->work); | |
| 2273 | − return; | |
| 2274 | 2240 | } |
| 2275 | 2241 | |
| 2276 | 2242 | INIT_WORK(&io->work, kcryptd_crypt); |
| @@ -1941,7 +1941,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern · 1940 unmodified lines | ||
| 1941 | 1941 | minimum_data_size - sizeof(param_kernel->version))) |
| 1942 | 1942 | return -EFAULT; |
| 1943 | 1943 | |
| 1944 | − if (param_kernel->data_size < minimum_data_size) { | |
| 1944 | + if (unlikely(param_kernel->data_size < minimum_data_size) || | |
| 1945 | + unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS)) { | |
| 1945 | 1946 | DMERR("Invalid data size in the ioctl structure: %u", |
| 1946 | 1947 | param_kernel->data_size); |
| 1947 | 1948 | return -EINVAL; |
| @@ -66,6 +66,9 @@ struct dm_stats_last_position { · 65 unmodified lines | ||
| 66 | 66 | unsigned int last_rw; |
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | +#define DM_STAT_MAX_ENTRIES 8388608 | |
| 70 | +#define DM_STAT_MAX_HISTOGRAM_ENTRIES 134217728 | |
| 71 | + | |
| 69 | 72 | /* |
| 70 | 73 | * A typo on the command line could possibly make the kernel run out of memory |
| 71 | 74 | * and crash. To prevent the crash we account all used memory. We fail if we |
| @@ -285,6 +288,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end, · 213 unmodified lines | ||
| 285 | 288 | if (n_entries != (size_t)n_entries || !(size_t)(n_entries + 1)) |
| 286 | 289 | return -EOVERFLOW; |
| 287 | 290 | |
| 291 | + if (n_entries > DM_STAT_MAX_ENTRIES) | |
| 292 | + return -EOVERFLOW; | |
| 293 | + | |
| 288 | 294 | shared_alloc_size = struct_size(s, stat_shared, n_entries); |
| 289 | 295 | if ((shared_alloc_size - sizeof(struct dm_stat)) / sizeof(struct dm_stat_shared) != n_entries) |
| 290 | 296 | return -EOVERFLOW; |
| @@ -297,6 +303,9 @@ static int dm_stats_create(struct dm_stats *stats, sector_t start, sector_t end, · 6 unmodified lines | ||
| 297 | 303 | if (histogram_alloc_size / (n_histogram_entries + 1) != (size_t)n_entries * sizeof(unsigned long long)) |
| 298 | 304 | return -EOVERFLOW; |
| 299 | 305 | |
| 306 | + if ((n_histogram_entries + 1) * (size_t)n_entries > DM_STAT_MAX_HISTOGRAM_ENTRIES) | |
| 307 | + return -EOVERFLOW; | |
| 308 | + | |
| 300 | 309 | if (!check_shared_memory(shared_alloc_size + histogram_alloc_size + |
| 301 | 310 | num_possible_cpus() * (percpu_alloc_size + histogram_alloc_size))) |
| 302 | 311 | return -ENOMEM; |
| @@ -129,7 +129,12 @@ static int alloc_targets(struct dm_table *t, unsigned int num) · 128 unmodified lines | ||
| 129 | 129 | int dm_table_create(struct dm_table **result, blk_mode_t mode, |
| 130 | 130 | unsigned int num_targets, struct mapped_device *md) |
| 131 | 131 | { |
| 132 | − struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL); | |
| 132 | + struct dm_table *t; | |
| 133 | + | |
| 134 | + if (num_targets > DM_MAX_TARGETS) | |
| 135 | + return -EOVERFLOW; | |
| 136 | + | |
| 137 | + t = kzalloc(sizeof(*t), GFP_KERNEL); | |
| 133 | 138 | |
| 134 | 139 | if (!t) |
| 135 | 140 | return -ENOMEM; |
| @@ -144,7 +149,7 @@ int dm_table_create(struct dm_table **result, blk_mode_t mode, · 8 unmodified lines | ||
| 144 | 149 | |
| 145 | 150 | if (!num_targets) { |
| 146 | 151 | kfree(t); |
| 147 | − return -ENOMEM; | |
| 152 | + return -EOVERFLOW; | |
| 148 | 153 | } |
| 149 | 154 | |
| 150 | 155 | if (alloc_targets(t, num_targets)) { |
| @@ -645,23 +645,6 @@ static void verity_work(struct work_struct *w) · 644 unmodified lines | ||
| 645 | 645 | verity_finish_io(io, errno_to_blk_status(verity_verify_io(io))); |
| 646 | 646 | } |
| 647 | 647 | |
| 648 | −static void verity_tasklet(unsigned long data) | |
| 649 | −{ | |
| 650 | − struct dm_verity_io *io = (struct dm_verity_io *)data; | |
| 651 | − int err; | |
| 652 | − | |
| 653 | − io->in_tasklet = true; | |
| 654 | − err = verity_verify_io(io); | |
| 655 | − if (err == -EAGAIN || err == -ENOMEM) { | |
| 656 | − /* fallback to retrying with work-queue */ | |
| 657 | − INIT_WORK(&io->work, verity_work); | |
| 658 | − queue_work(io->v->verify_wq, &io->work); | |
| 659 | − return; | |
| 660 | − } | |
| 661 | − | |
| 662 | − verity_finish_io(io, errno_to_blk_status(err)); | |
| 663 | −} | |
| 664 | − | |
| 665 | 648 | static void verity_end_io(struct bio *bio) |
| 666 | 649 | { |
| 667 | 650 | struct dm_verity_io *io = bio->bi_private; |
| @@ -674,13 +657,8 @@ static void verity_end_io(struct bio *bio) · 6 unmodified lines | ||
| 674 | 657 | return; |
| 675 | 658 | } |
| 676 | 659 | |
| 677 | − if (static_branch_unlikely(&use_tasklet_enabled) && io->v->use_tasklet) { | |
| 678 | − tasklet_init(&io->tasklet, verity_tasklet, (unsigned long)io); | |
| 679 | − tasklet_schedule(&io->tasklet); | |
| 680 | − } else { | |
| 681 | − INIT_WORK(&io->work, verity_work); | |
| 682 | − queue_work(io->v->verify_wq, &io->work); | |
| 683 | − } | |
| 660 | + INIT_WORK(&io->work, verity_work); | |
| 661 | + queue_work(io->v->verify_wq, &io->work); | |
| 684 | 662 | } |
| 685 | 663 | |
| 686 | 664 | /* |
| @@ -83,7 +83,6 @@ struct dm_verity_io { · 82 unmodified lines | ||
| 83 | 83 | struct bvec_iter iter; |
| 84 | 84 | |
| 85 | 85 | struct work_struct work; |
| 86 | − struct tasklet_struct tasklet; | |
| 87 | 86 | |
| 88 | 87 | /* |
| 89 | 88 | * Three variably-size fields follow this struct: |
| @@ -299,7 +299,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) · 298 unmodified lines | ||
| 299 | 299 | long i; |
| 300 | 300 | |
| 301 | 301 | wc->memory_map = NULL; |
| 302 | − pages = kvmalloc_array(p, sizeof(struct page *), GFP_KERNEL); | |
| 302 | + pages = vmalloc_array(p, sizeof(struct page *)); | |
| 303 | 303 | if (!pages) { |
| 304 | 304 | r = -ENOMEM; |
| 305 | 305 | goto err2; |
| @@ -330,7 +330,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) · 24 unmodified lines | ||
| 330 | 330 | r = -ENOMEM; |
| 331 | 331 | goto err3; |
| 332 | 332 | } |
| 333 | − kvfree(pages); | |
| 333 | + vfree(pages); | |
| 334 | 334 | wc->memory_vmapped = true; |
| 335 | 335 | } |
| 336 | 336 | |
| @@ -341,7 +341,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) · 4 unmodified lines | ||
| 341 | 341 | |
| 342 | 342 | return 0; |
| 343 | 343 | err3: |
| 344 | − kvfree(pages); | |
| 344 | + vfree(pages); | |
| 345 | 345 | err2: |
| 346 | 346 | dax_read_unlock(id); |
| 347 | 347 | err1: |
| @@ -962,7 +962,7 @@ static int writecache_alloc_entries(struct dm_writecache *wc) · 614 unmodified lines | ||
| 962 | 962 | |
| 963 | 963 | if (wc->entries) |
| 964 | 964 | return 0; |
| 965 | − wc->entries = vmalloc(array_size(sizeof(struct wc_entry), wc->n_blocks)); | |
| 965 | + wc->entries = vmalloc_array(wc->n_blocks, sizeof(struct wc_entry)); | |
| 966 | 966 | if (!wc->entries) |
| 967 | 967 | return -ENOMEM; |
| 968 | 968 | for (b = 0; b < wc->n_blocks; b++) { |
| @@ -2262,7 +2262,7 @@ static void fix_read_error(struct r1conf *conf, struct r1bio *r1_bio) · 2261 unmodified lines | ||
| 2262 | 2262 | int sectors = r1_bio->sectors; |
| 2263 | 2263 | int read_disk = r1_bio->read_disk; |
| 2264 | 2264 | struct mddev *mddev = conf->mddev; |
| 2265 | − struct md_rdev *rdev = rcu_dereference(conf->mirrors[read_disk].rdev); | |
| 2265 | + struct md_rdev *rdev = conf->mirrors[read_disk].rdev; | |
| 2266 | 2266 | |
| 2267 | 2267 | if (exceed_read_errors(mddev, rdev)) { |
| 2268 | 2268 | r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED; |
| @@ -989,7 +989,7 @@ int vb2_core_create_bufs(struct vb2_queue *q, enum vb2_memory memory, · 988 unmodified lines | ||
| 989 | 989 | bool no_previous_buffers = !q_num_bufs; |
| 990 | 990 | int ret = 0; |
| 991 | 991 | |
| 992 | − if (q->num_buffers == q->max_num_buffers) { | |
| 992 | + if (q_num_bufs == q->max_num_buffers) { | |
| 993 | 993 | dprintk(q, 1, "maximum number of buffers already allocated\n"); |
| 994 | 994 | return -ENOBUFS; |
| 995 | 995 | } |
| @@ -671,8 +671,20 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) · 670 unmodified lines | ||
| 671 | 671 | } |
| 672 | 672 | EXPORT_SYMBOL(vb2_querybuf); |
| 673 | 673 | |
| 674 | −static void fill_buf_caps(struct vb2_queue *q, u32 *caps) | |
| 674 | +static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 memory, | |
| 675 | + u32 *flags, u32 *caps, u32 *max_num_bufs) | |
| 675 | 676 | { |
| 677 | + if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP) { | |
| 678 | + /* | |
| 679 | + * This needs to clear V4L2_MEMORY_FLAG_NON_COHERENT only, | |
| 680 | + * but in order to avoid bugs we zero out all bits. | |
| 681 | + */ | |
| 682 | + *flags = 0; | |
| 683 | + } else { | |
| 684 | + /* Clear all unknown flags. */ | |
| 685 | + *flags &= V4L2_MEMORY_FLAG_NON_COHERENT; | |
| 686 | + } | |
| 687 | + | |
| 676 | 688 | *caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS; |
| 677 | 689 | if (q->io_modes & VB2_MMAP) |
| 678 | 690 | *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP; |
| @@ -686,21 +698,9 @@ static void fill_buf_caps(struct vb2_queue *q, u32 *caps) · 7 unmodified lines | ||
| 686 | 698 | *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS; |
| 687 | 699 | if (q->supports_requests) |
| 688 | 700 | *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS; |
| 689 | −} | |
| 690 | − | |
| 691 | −static void validate_memory_flags(struct vb2_queue *q, | |
| 692 | − int memory, | |
| 693 | − u32 *flags) | |
| 694 | −{ | |
| 695 | − if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP) { | |
| 696 | − /* | |
| 697 | − * This needs to clear V4L2_MEMORY_FLAG_NON_COHERENT only, | |
| 698 | − * but in order to avoid bugs we zero out all bits. | |
| 699 | − */ | |
| 700 | − *flags = 0; | |
| 701 | − } else { | |
| 702 | − /* Clear all unknown flags. */ | |
| 703 | − *flags &= V4L2_MEMORY_FLAG_NON_COHERENT; | |
| 701 | + if (max_num_bufs) { | |
| 702 | + *max_num_bufs = q->max_num_buffers; | |
| 703 | + *caps |= V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS; | |
| 704 | 704 | } |
| 705 | 705 | } |
| 706 | 706 | |
| @@ -709,8 +709,8 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) · 2 unmodified lines | ||
| 709 | 709 | int ret = vb2_verify_memory_type(q, req->memory, req->type); |
| 710 | 710 | u32 flags = req->flags; |
| 711 | 711 | |
| 712 | − fill_buf_caps(q, &req->capabilities); | |
| 713 | − validate_memory_flags(q, req->memory, &flags); | |
| 712 | + vb2_set_flags_and_caps(q, req->memory, &flags, | |
| 713 | + &req->capabilities, NULL); | |
| 714 | 714 | req->flags = flags; |
| 715 | 715 | return ret ? ret : vb2_core_reqbufs(q, req->memory, |
| 716 | 716 | req->flags, &req->count); |
| @@ -751,11 +751,9 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) · 34 unmodified lines | ||
| 751 | 751 | int ret = vb2_verify_memory_type(q, create->memory, f->type); |
| 752 | 752 | unsigned i; |
| 753 | 753 | |
| 754 | − fill_buf_caps(q, &create->capabilities); | |
| 755 | − validate_memory_flags(q, create->memory, &create->flags); | |
| 756 | 754 | create->index = vb2_get_num_buffers(q); |
| 757 | − create->max_num_buffers = q->max_num_buffers; | |
| 758 | − create->capabilities |= V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS; | |
| 755 | + vb2_set_flags_and_caps(q, create->memory, &create->flags, | |
| 756 | + &create->capabilities, &create->max_num_buffers); | |
| 759 | 757 | if (create->count == 0) |
| 760 | 758 | return ret != -EBUSY ? ret : 0; |
| 761 | 759 | |
| @@ -1006,8 +1004,8 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv, · 244 unmodified lines | ||
| 1006 | 1004 | int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type); |
| 1007 | 1005 | u32 flags = p->flags; |
| 1008 | 1006 | |
| 1009 | − fill_buf_caps(vdev->queue, &p->capabilities); | |
| 1010 | − validate_memory_flags(vdev->queue, p->memory, &flags); | |
| 1007 | + vb2_set_flags_and_caps(vdev->queue, p->memory, &flags, | |
| 1008 | + &p->capabilities, NULL); | |
| 1011 | 1009 | p->flags = flags; |
| 1012 | 1010 | if (res) |
| 1013 | 1011 | return res; |
| @@ -1026,12 +1024,11 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv, · 12 unmodified lines | ||
| 1026 | 1024 | struct v4l2_create_buffers *p) |
| 1027 | 1025 | { |
| 1028 | 1026 | struct video_device *vdev = video_devdata(file); |
| 1029 | − int res = vb2_verify_memory_type(vdev->queue, p->memory, | |
| 1030 | − p->format.type); | |
| 1027 | + int res = vb2_verify_memory_type(vdev->queue, p->memory, p->format.type); | |
| 1031 | 1028 | |
| 1032 | − p->index = vdev->queue->num_buffers; | |
| 1033 | − fill_buf_caps(vdev->queue, &p->capabilities); | |
| 1034 | − validate_memory_flags(vdev->queue, p->memory, &p->flags); | |
| 1029 | + p->index = vb2_get_num_buffers(vdev->queue); | |
| 1030 | + vb2_set_flags_and_caps(vdev->queue, p->memory, &p->flags, | |
| 1031 | + &p->capabilities, &p->max_num_buffers); | |
| 1035 | 1032 | /* |
| 1036 | 1033 | * If count == 0, then just check if memory and type are valid. |
| 1037 | 1034 | * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. |
| @@ -272,7 +272,7 @@ static const struct wave5_match_data ti_wave521c_data = { · 271 unmodified lines | ||
| 272 | 272 | }; |
| 273 | 273 | |
| 274 | 274 | static const struct of_device_id wave5_dt_ids[] = { |
| 275 | − { .compatible = "ti,k3-j721s2-wave521c", .data = &ti_wave521c_data }, | |
| 275 | + { .compatible = "ti,j721s2-wave521c", .data = &ti_wave521c_data }, | |
| 276 | 276 | { /* sentinel */ } |
| 277 | 277 | }; |
| 278 | 278 | MODULE_DEVICE_TABLE(of, wave5_dt_ids); |
| @@ -2191,7 +2191,7 @@ static int fastrpc_cb_remove(struct platform_device *pdev) · 2190 unmodified lines | ||
| 2191 | 2191 | int i; |
| 2192 | 2192 | |
| 2193 | 2193 | spin_lock_irqsave(&cctx->lock, flags); |
| 2194 | − for (i = 1; i < FASTRPC_MAX_SESSIONS; i++) { | |
| 2194 | + for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) { | |
| 2195 | 2195 | if (cctx->session[i].sid == sess->sid) { |
| 2196 | 2196 | cctx->session[i].valid = false; |
| 2197 | 2197 | cctx->sesscount--; |
| @@ -140,7 +140,6 @@ static int __init open_dice_probe(struct platform_device *pdev) · 139 unmodified lines | ||
| 140 | 140 | return -ENOMEM; |
| 141 | 141 | |
| 142 | 142 | *drvdata = (struct open_dice_drvdata){ |
| 143 | − .lock = __MUTEX_INITIALIZER(drvdata->lock), | |
| 144 | 143 | .rmem = rmem, |
| 145 | 144 | .misc = (struct miscdevice){ |
| 146 | 145 | .parent = dev, |
| @@ -150,6 +149,7 @@ static int __init open_dice_probe(struct platform_device *pdev) · 3 unmodified lines | ||
| 150 | 149 | .mode = 0600, |
| 151 | 150 | }, |
| 152 | 151 | }; |
| 152 | + mutex_init(&drvdata->lock); | |
| 153 | 153 | |
| 154 | 154 | /* Index overflow check not needed, misc_register() will fail. */ |
| 155 | 155 | snprintf(drvdata->name, sizeof(drvdata->name), DRIVER_NAME"%u", dev_idx++); |
| @@ -75,11 +75,15 @@ EXPORT_SYMBOL(mmc_gpio_set_cd_irq); · 74 unmodified lines | ||
| 75 | 75 | int mmc_gpio_get_ro(struct mmc_host *host) |
| 76 | 76 | { |
| 77 | 77 | struct mmc_gpio *ctx = host->slot.handler_priv; |
| 78 | + int cansleep; | |
| 78 | 79 | |
| 79 | 80 | if (!ctx || !ctx->ro_gpio) |
| 80 | 81 | return -ENOSYS; |
| 81 | 82 | |
| 82 | − return gpiod_get_value_cansleep(ctx->ro_gpio); | |
| 83 | + cansleep = gpiod_cansleep(ctx->ro_gpio); | |
| 84 | + return cansleep ? | |
| 85 | + gpiod_get_value_cansleep(ctx->ro_gpio) : | |
| 86 | + gpiod_get_value(ctx->ro_gpio); | |
| 83 | 87 | } |
| 84 | 88 | EXPORT_SYMBOL(mmc_gpio_get_ro); |
| 85 | 89 | |
| @@ -693,6 +693,35 @@ static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *io · 692 unmodified lines | ||
| 693 | 693 | return 0; |
| 694 | 694 | } |
| 695 | 695 | |
| 696 | +static void sdhci_pci_o2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) | |
| 697 | +{ | |
| 698 | + struct sdhci_pci_chip *chip; | |
| 699 | + struct sdhci_pci_slot *slot = sdhci_priv(host); | |
| 700 | + u32 scratch_32 = 0; | |
| 701 | + u8 scratch_8 = 0; | |
| 702 | + | |
| 703 | + chip = slot->chip; | |
| 704 | + | |
| 705 | + if (mode == MMC_POWER_OFF) { | |
| 706 | + /* UnLock WP */ | |
| 707 | + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); | |
| 708 | + scratch_8 &= 0x7f; | |
| 709 | + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
| 710 | + | |
| 711 | + /* Set PCR 0x354[16] to switch Clock Source back to OPE Clock */ | |
| 712 | + pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); | |
| 713 | + scratch_32 &= ~(O2_SD_SEL_DLL); | |
| 714 | + pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32); | |
| 715 | + | |
| 716 | + /* Lock WP */ | |
| 717 | + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); | |
| 718 | + scratch_8 |= 0x80; | |
| 719 | + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); | |
| 720 | + } | |
| 721 | + | |
| 722 | + sdhci_set_power(host, mode, vdd); | |
| 723 | +} | |
| 724 | + | |
| 696 | 725 | static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) |
| 697 | 726 | { |
| 698 | 727 | struct sdhci_pci_chip *chip; |
| @@ -1051,6 +1080,7 @@ static const struct sdhci_ops sdhci_pci_o2_ops = { · 352 unmodified lines | ||
| 1051 | 1080 | .set_bus_width = sdhci_set_bus_width, |
| 1052 | 1081 | .reset = sdhci_reset, |
| 1053 | 1082 | .set_uhs_signaling = sdhci_set_uhs_signaling, |
| 1083 | + .set_power = sdhci_pci_o2_set_power, | |
| 1054 | 1084 | }; |
| 1055 | 1085 | |
| 1056 | 1086 | const struct sdhci_pci_fixes sdhci_o2 = { |
| @@ -2838,8 +2838,7 @@ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, · 2837 unmodified lines | ||
| 2838 | 2838 | /* MT753x MAC works in 1G full duplex mode for all up-clocked |
| 2839 | 2839 | * variants. |
| 2840 | 2840 | */ |
| 2841 | − if (interface == PHY_INTERFACE_MODE_INTERNAL || | |
| 2842 | − interface == PHY_INTERFACE_MODE_TRGMII || | |
| 2841 | + if (interface == PHY_INTERFACE_MODE_TRGMII || | |
| 2843 | 2842 | (phy_interface_mode_is_8023z(interface))) { |
| 2844 | 2843 | speed = SPEED_1000; |
| 2845 | 2844 | duplex = DUPLEX_FULL; |
| @@ -3659,7 +3659,7 @@ static int mv88e6xxx_mdio_read_c45(struct mii_bus *bus, int phy, int devad, · 3658 unmodified lines | ||
| 3659 | 3659 | int err; |
| 3660 | 3660 | |
| 3661 | 3661 | if (!chip->info->ops->phy_read_c45) |
| 3662 | − return -EOPNOTSUPP; | |
| 3662 | + return 0xffff; | |
| 3663 | 3663 | |
| 3664 | 3664 | mv88e6xxx_reg_lock(chip); |
| 3665 | 3665 | err = chip->info->ops->phy_read_c45(chip, bus, phy, devad, reg, &val); |
| @@ -2051,12 +2051,11 @@ qca8k_sw_probe(struct mdio_device *mdiodev) · 2050 unmodified lines | ||
| 2051 | 2051 | priv->info = of_device_get_match_data(priv->dev); |
| 2052 | 2052 | |
| 2053 | 2053 | priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset", |
| 2054 | − GPIOD_ASIS); | |
| 2054 | + GPIOD_OUT_HIGH); | |
| 2055 | 2055 | if (IS_ERR(priv->reset_gpio)) |
| 2056 | 2056 | return PTR_ERR(priv->reset_gpio); |
| 2057 | 2057 | |
| 2058 | 2058 | if (priv->reset_gpio) { |
| 2059 | − gpiod_set_value_cansleep(priv->reset_gpio, 1); | |
| 2060 | 2059 | /* The active low duration must be greater than 10 ms |
| 2061 | 2060 | * and checkpatch.pl wants 20 ms. |
| 2062 | 2061 | */ |
| @@ -100,4 +100,5 @@ static void __exit ns8390_module_exit(void) · 99 unmodified lines | ||
| 100 | 100 | module_init(ns8390_module_init); |
| 101 | 101 | module_exit(ns8390_module_exit); |
| 102 | 102 | #endif /* MODULE */ |
| 103 | +MODULE_DESCRIPTION("National Semiconductor 8390 core driver"); | |
| 103 | 104 | MODULE_LICENSE("GPL"); |
| @@ -102,4 +102,5 @@ static void __exit NS8390p_cleanup_module(void) · 101 unmodified lines | ||
| 102 | 102 | |
| 103 | 103 | module_init(NS8390p_init_module); |
| 104 | 104 | module_exit(NS8390p_cleanup_module); |
| 105 | +MODULE_DESCRIPTION("National Semiconductor 8390 core for ISA driver"); | |
| 105 | 106 | MODULE_LICENSE("GPL"); |
| @@ -610,4 +610,5 @@ static int init_pcmcia(void) · 609 unmodified lines | ||
| 610 | 610 | return 1; |
| 611 | 611 | } |
| 612 | 612 | |
| 613 | +MODULE_DESCRIPTION("National Semiconductor 8390 Amiga PCMCIA ethernet driver"); | |
| 613 | 614 | MODULE_LICENSE("GPL"); |
| @@ -270,4 +270,5 @@ static void __exit hydra_cleanup_module(void) · 269 unmodified lines | ||
| 270 | 270 | module_init(hydra_init_module); |
| 271 | 271 | module_exit(hydra_cleanup_module); |
| 272 | 272 | |
| 273 | +MODULE_DESCRIPTION("Zorro-II Hydra 8390 ethernet driver"); | |
| 273 | 274 | MODULE_LICENSE("GPL"); |
| @@ -296,4 +296,5 @@ static void __exit stnic_cleanup(void) · 295 unmodified lines | ||
| 296 | 296 | |
| 297 | 297 | module_init(stnic_probe); |
| 298 | 298 | module_exit(stnic_cleanup); |
| 299 | +MODULE_DESCRIPTION("National Semiconductor DP83902AV ethernet driver"); | |
| 299 | 300 | MODULE_LICENSE("GPL"); |
| @@ -443,4 +443,5 @@ static void __exit zorro8390_cleanup_module(void) · 442 unmodified lines | ||
| 443 | 443 | module_init(zorro8390_init_module); |
| 444 | 444 | module_exit(zorro8390_cleanup_module); |
| 445 | 445 | |
| 446 | +MODULE_DESCRIPTION("Zorro NS8390-based ethernet driver"); | |
| 446 | 447 | MODULE_LICENSE("GPL"); |
| @@ -63,6 +63,15 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq) · 62 unmodified lines | ||
| 63 | 63 | return nq_work; |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | +static bool pdsc_adminq_inc_if_up(struct pdsc *pdsc) | |
| 67 | +{ | |
| 68 | + if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER) || | |
| 69 | + pdsc->state & BIT_ULL(PDSC_S_FW_DEAD)) | |
| 70 | + return false; | |
| 71 | + | |
| 72 | + return refcount_inc_not_zero(&pdsc->adminq_refcnt); | |
| 73 | +} | |
| 74 | + | |
| 66 | 75 | void pdsc_process_adminq(struct pdsc_qcq *qcq) |
| 67 | 76 | { |
| 68 | 77 | union pds_core_adminq_comp *comp; |
| @@ -75,9 +84,9 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq) · 6 unmodified lines | ||
| 75 | 84 | int aq_work = 0; |
| 76 | 85 | int credits; |
| 77 | 86 | |
| 78 | − /* Don't process AdminQ when shutting down */ | |
| 79 | − if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER)) { | |
| 80 | − dev_err(pdsc->dev, "%s: called while PDSC_S_STOPPING_DRIVER\n", | |
| 87 | + /* Don't process AdminQ when it's not up */ | |
| 88 | + if (!pdsc_adminq_inc_if_up(pdsc)) { | |
| 89 | + dev_err(pdsc->dev, "%s: called while adminq is unavailable\n", | |
| 81 | 90 | __func__); |
| 82 | 91 | return; |
| 83 | 92 | } |
| @@ -124,6 +133,7 @@ credits: · 40 unmodified lines | ||
| 124 | 133 | pds_core_intr_credits(&pdsc->intr_ctrl[qcq->intx], |
| 125 | 134 | credits, |
| 126 | 135 | PDS_CORE_INTR_CRED_REARM); |
| 136 | + refcount_dec(&pdsc->adminq_refcnt); | |
| 127 | 137 | } |
| 128 | 138 | |
| 129 | 139 | void pdsc_work_thread(struct work_struct *work) |
| @@ -135,18 +145,20 @@ void pdsc_work_thread(struct work_struct *work) · 5 unmodified lines | ||
| 135 | 145 | |
| 136 | 146 | irqreturn_t pdsc_adminq_isr(int irq, void *data) |
| 137 | 147 | { |
| 138 | − struct pdsc_qcq *qcq = data; | |
| 139 | − struct pdsc *pdsc = qcq->pdsc; | |
| 148 | + struct pdsc *pdsc = data; | |
| 149 | + struct pdsc_qcq *qcq; | |
| 140 | 150 | |
| 141 | − /* Don't process AdminQ when shutting down */ | |
| 142 | − if (pdsc->state & BIT_ULL(PDSC_S_STOPPING_DRIVER)) { | |
| 143 | − dev_err(pdsc->dev, "%s: called while PDSC_S_STOPPING_DRIVER\n", | |
| 151 | + /* Don't process AdminQ when it's not up */ | |
| 152 | + if (!pdsc_adminq_inc_if_up(pdsc)) { | |
| 153 | + dev_err(pdsc->dev, "%s: called while adminq is unavailable\n", | |
| 144 | 154 | __func__); |
| 145 | 155 | return IRQ_HANDLED; |
| 146 | 156 | } |
| 147 | 157 | |
| 158 | + qcq = &pdsc->adminqcq; | |
| 148 | 159 | queue_work(pdsc->wq, &qcq->work); |
| 149 | 160 | pds_core_intr_mask(&pdsc->intr_ctrl[qcq->intx], PDS_CORE_INTR_MASK_CLEAR); |
| 161 | + refcount_dec(&pdsc->adminq_refcnt); | |
| 150 | 162 | |
| 151 | 163 | return IRQ_HANDLED; |
| 152 | 164 | } |
| @@ -179,10 +191,16 @@ static int __pdsc_adminq_post(struct pdsc *pdsc, · 26 unmodified lines | ||
| 179 | 191 | |
| 180 | 192 | /* Check that the FW is running */ |
| 181 | 193 | if (!pdsc_is_fw_running(pdsc)) { |
| 182 | − u8 fw_status = ioread8(&pdsc->info_regs->fw_status); | |
| 183 | − | |
| 184 | − dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n", | |
| 185 | − __func__, fw_status); | |
| 194 | + if (pdsc->info_regs) { | |
| 195 | + u8 fw_status = | |
| 196 | + ioread8(&pdsc->info_regs->fw_status); | |
| 197 | + | |
| 198 | + dev_info(pdsc->dev, "%s: post failed - fw not running %#02x:\n", | |
| 199 | + __func__, fw_status); | |
| 200 | + } else { | |
| 201 | + dev_info(pdsc->dev, "%s: post failed - BARs not setup\n", | |
| 202 | + __func__); | |
| 203 | + } | |
| 186 | 204 | ret = -ENXIO; |
| 187 | 205 | |
| 188 | 206 | goto err_out_unlock; |
| @@ -230,6 +248,12 @@ int pdsc_adminq_post(struct pdsc *pdsc, · 41 unmodified lines | ||
| 230 | 248 | int err = 0; |
| 231 | 249 | int index; |
| 232 | 250 | |
| 251 | + if (!pdsc_adminq_inc_if_up(pdsc)) { | |
| 252 | + dev_dbg(pdsc->dev, "%s: preventing adminq cmd %u\n", | |
| 253 | + __func__, cmd->opcode); | |
| 254 | + return -ENXIO; | |
| 255 | + } | |
| 256 | + | |
| 233 | 257 | wc.qcq = &pdsc->adminqcq; |
| 234 | 258 | index = __pdsc_adminq_post(pdsc, &pdsc->adminqcq, cmd, comp, &wc); |
| 235 | 259 | if (index < 0) { |
| @@ -248,10 +272,16 @@ int pdsc_adminq_post(struct pdsc *pdsc, · 12 unmodified lines | ||
| 248 | 272 | break; |
| 249 | 273 | |
| 250 | 274 | if (!pdsc_is_fw_running(pdsc)) { |
| 251 | − u8 fw_status = ioread8(&pdsc->info_regs->fw_status); | |
| 252 | − | |
| 253 | − dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n", | |
| 254 | − __func__, fw_status); | |
| 275 | + if (pdsc->info_regs) { | |
| 276 | + u8 fw_status = | |
| 277 | + ioread8(&pdsc->info_regs->fw_status); | |
| 278 | + | |
| 279 | + dev_dbg(pdsc->dev, "%s: post wait failed - fw not running %#02x:\n", | |
| 280 | + __func__, fw_status); | |
| 281 | + } else { | |
| 282 | + dev_dbg(pdsc->dev, "%s: post wait failed - BARs not setup\n", | |
| 283 | + __func__); | |
| 284 | + } | |
| 255 | 285 | err = -ENXIO; |
| 256 | 286 | break; |
| 257 | 287 | } |
| @@ -285,6 +315,8 @@ err_out: · 27 unmodified lines | ||
| 285 | 315 | queue_work(pdsc->wq, &pdsc->health_work); |
| 286 | 316 | } |
| 287 | 317 | |
| 318 | + refcount_dec(&pdsc->adminq_refcnt); | |
| 319 | + | |
| 288 | 320 | return err; |
| 289 | 321 | } |
| 290 | 322 | EXPORT_SYMBOL_GPL(pdsc_adminq_post); |
| @@ -125,7 +125,7 @@ static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq) · 124 unmodified lines | ||
| 125 | 125 | |
| 126 | 126 | snprintf(name, sizeof(name), "%s-%d-%s", |
| 127 | 127 | PDS_CORE_DRV_NAME, pdsc->pdev->bus->number, qcq->q.name); |
| 128 | − index = pdsc_intr_alloc(pdsc, name, pdsc_adminq_isr, qcq); | |
| 128 | + index = pdsc_intr_alloc(pdsc, name, pdsc_adminq_isr, pdsc); | |
| 129 | 129 | if (index < 0) |
| 130 | 130 | return index; |
| 131 | 131 | qcq->intx = index; |
| @@ -404,10 +404,7 @@ int pdsc_setup(struct pdsc *pdsc, bool init) · 272 unmodified lines | ||
| 404 | 404 | int numdescs; |
| 405 | 405 | int err; |
| 406 | 406 | |
| 407 | − if (init) | |
| 408 | − err = pdsc_dev_init(pdsc); | |
| 409 | − else | |
| 410 | − err = pdsc_dev_reinit(pdsc); | |
| 407 | + err = pdsc_dev_init(pdsc); | |
| 411 | 408 | if (err) |
| 412 | 409 | return err; |
| 413 | 410 | |
| @@ -450,6 +447,7 @@ int pdsc_setup(struct pdsc *pdsc, bool init) · 36 unmodified lines | ||
| 450 | 447 | pdsc_debugfs_add_viftype(pdsc); |
| 451 | 448 | } |
| 452 | 449 | |
| 450 | + refcount_set(&pdsc->adminq_refcnt, 1); | |
| 453 | 451 | clear_bit(PDSC_S_FW_DEAD, &pdsc->state); |
| 454 | 452 | return 0; |
| 455 | 453 | |
| @@ -464,6 +462,8 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) · 8 unmodified lines | ||
| 464 | 462 | |
| 465 | 463 | if (!pdsc->pdev->is_virtfn) |
| 466 | 464 | pdsc_devcmd_reset(pdsc); |
| 465 | + if (pdsc->adminqcq.work.func) | |
| 466 | + cancel_work_sync(&pdsc->adminqcq.work); | |
| 467 | 467 | pdsc_qcq_free(pdsc, &pdsc->notifyqcq); |
| 468 | 468 | pdsc_qcq_free(pdsc, &pdsc->adminqcq); |
| 469 | 469 | |
| @@ -476,10 +476,9 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) · 6 unmodified lines | ||
| 476 | 476 | for (i = 0; i < pdsc->nintrs; i++) |
| 477 | 477 | pdsc_intr_free(pdsc, i); |
| 478 | 478 | |
| 479 | − if (removing) { | |
| 480 | − kfree(pdsc->intr_info); | |
| 481 | − pdsc->intr_info = NULL; | |
| 482 | − } | |
| 479 | + kfree(pdsc->intr_info); | |
| 480 | + pdsc->intr_info = NULL; | |
| 481 | + pdsc->nintrs = 0; | |
| 483 | 482 | } |
| 484 | 483 | |
| 485 | 484 | if (pdsc->kern_dbpage) { |
| @@ -487,6 +486,7 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) · 1 unmodified line | ||
| 487 | 486 | pdsc->kern_dbpage = NULL; |
| 488 | 487 | } |
| 489 | 488 | |
| 489 | + pci_free_irq_vectors(pdsc->pdev); | |
| 490 | 490 | set_bit(PDSC_S_FW_DEAD, &pdsc->state); |
| 491 | 491 | } |
| 492 | 492 | |
| @@ -512,6 +512,24 @@ void pdsc_stop(struct pdsc *pdsc) · 19 unmodified lines | ||
| 512 | 512 | PDS_CORE_INTR_MASK_SET); |
| 513 | 513 | } |
| 514 | 514 | |
| 515 | +static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc) | |
| 516 | +{ | |
| 517 | + /* The driver initializes the adminq_refcnt to 1 when the adminq is | |
| 518 | + * allocated and ready for use. Other users/requesters will increment | |
| 519 | + * the refcnt while in use. If the refcnt is down to 1 then the adminq | |
| 520 | + * is not in use and the refcnt can be cleared and adminq freed. Before | |
| 521 | + * calling this function the driver will set PDSC_S_FW_DEAD, which | |
| 522 | + * prevent subsequent attempts to use the adminq and increment the | |
| 523 | + * refcnt to fail. This guarantees that this function will eventually | |
| 524 | + * exit. | |
| 525 | + */ | |
| 526 | + while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) { | |
| 527 | + dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n", | |
| 528 | + __func__); | |
| 529 | + cpu_relax(); | |
| 530 | + } | |
| 531 | +} | |
| 532 | + | |
| 515 | 533 | void pdsc_fw_down(struct pdsc *pdsc) |
| 516 | 534 | { |
| 517 | 535 | union pds_core_notifyq_comp reset_event = { |
| @@ -527,6 +545,8 @@ void pdsc_fw_down(struct pdsc *pdsc) · 9 unmodified lines | ||
| 527 | 545 | if (pdsc->pdev->is_virtfn) |
| 528 | 546 | return; |
| 529 | 547 | |
| 548 | + pdsc_adminq_wait_and_dec_once_unused(pdsc); | |
| 549 | + | |
| 530 | 550 | /* Notify clients of fw_down */ |
| 531 | 551 | if (pdsc->fw_reporter) |
| 532 | 552 | devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); |
| @@ -577,7 +597,13 @@ err_out: · 44 unmodified lines | ||
| 577 | 597 | |
| 578 | 598 | static void pdsc_check_pci_health(struct pdsc *pdsc) |
| 579 | 599 | { |
| 580 | − u8 fw_status = ioread8(&pdsc->info_regs->fw_status); | |
| 600 | + u8 fw_status; | |
| 601 | + | |
| 602 | + /* some sort of teardown already in progress */ | |
| 603 | + if (!pdsc->info_regs) | |
| 604 | + return; | |
| 605 | + | |
| 606 | + fw_status = ioread8(&pdsc->info_regs->fw_status); | |
| 581 | 607 | |
| 582 | 608 | /* is PCI broken? */ |
| 583 | 609 | if (fw_status != PDS_RC_BAD_PCI) |
| @@ -184,6 +184,7 @@ struct pdsc { · 183 unmodified lines | ||
| 184 | 184 | struct mutex devcmd_lock; /* lock for dev_cmd operations */ |
| 185 | 185 | struct mutex config_lock; /* lock for configuration operations */ |
| 186 | 186 | spinlock_t adminq_lock; /* lock for adminq operations */ |
| 187 | + refcount_t adminq_refcnt; | |
| 187 | 188 | struct pds_core_dev_info_regs __iomem *info_regs; |
| 188 | 189 | struct pds_core_dev_cmd_regs __iomem *cmd_regs; |
| 189 | 190 | struct pds_core_intr __iomem *intr_ctrl; |
| @@ -280,7 +281,6 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd, · 90 unmodified lines | ||
| 280 | 281 | union pds_core_dev_comp *comp, int max_seconds); |
| 281 | 282 | int pdsc_devcmd_init(struct pdsc *pdsc); |
| 282 | 283 | int pdsc_devcmd_reset(struct pdsc *pdsc); |
| 283 | −int pdsc_dev_reinit(struct pdsc *pdsc); | |
| 284 | 284 | int pdsc_dev_init(struct pdsc *pdsc); |
| 285 | 285 | |
| 286 | 286 | void pdsc_reset_prepare(struct pci_dev *pdev); |
| @@ -64,6 +64,10 @@ DEFINE_SHOW_ATTRIBUTE(identity); · 63 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | void pdsc_debugfs_add_ident(struct pdsc *pdsc) |
| 66 | 66 | { |
| 67 | + /* This file will already exist in the reset flow */ | |
| 68 | + if (debugfs_lookup("identity", pdsc->dentry)) | |
| 69 | + return; | |
| 70 | + | |
| 67 | 71 | debugfs_create_file("identity", 0400, pdsc->dentry, |
| 68 | 72 | pdsc, &identity_fops); |
| 69 | 73 | } |
| @@ -57,6 +57,9 @@ int pdsc_err_to_errno(enum pds_core_status_code code) · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | bool pdsc_is_fw_running(struct pdsc *pdsc) |
| 59 | 59 | { |
| 60 | + if (!pdsc->info_regs) | |
| 61 | + return false; | |
| 62 | + | |
| 60 | 63 | pdsc->fw_status = ioread8(&pdsc->info_regs->fw_status); |
| 61 | 64 | pdsc->last_fw_time = jiffies; |
| 62 | 65 | pdsc->last_hb = ioread32(&pdsc->info_regs->fw_heartbeat); |
| @@ -182,13 +185,17 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd, · 119 unmodified lines | ||
| 182 | 185 | { |
| 183 | 186 | int err; |
| 184 | 187 | |
| 188 | + if (!pdsc->cmd_regs) | |
| 189 | + return -ENXIO; | |
| 190 | + | |
| 185 | 191 | memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd)); |
| 186 | 192 | pdsc_devcmd_dbell(pdsc); |
| 187 | 193 | err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds); |
| 188 | − memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp)); | |
| 189 | 194 | |
| 190 | 195 | if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq) |
| 191 | 196 | queue_work(pdsc->wq, &pdsc->health_work); |
| 197 | + else | |
| 198 | + memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp)); | |
| 192 | 199 | |
| 193 | 200 | return err; |
| 194 | 201 | } |
| @@ -309,13 +316,6 @@ static int pdsc_identify(struct pdsc *pdsc) · 114 unmodified lines | ||
| 309 | 316 | return 0; |
| 310 | 317 | } |
| 311 | 318 | |
| 312 | −int pdsc_dev_reinit(struct pdsc *pdsc) | |
| 313 | −{ | |
| 314 | − pdsc_init_devinfo(pdsc); | |
| 315 | − | |
| 316 | − return pdsc_identify(pdsc); | |
| 317 | −} | |
| 318 | − | |
| 319 | 319 | int pdsc_dev_init(struct pdsc *pdsc) |
| 320 | 320 | { |
| 321 | 321 | unsigned int nintrs; |
| @@ -111,7 +111,8 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req, · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | mutex_lock(&pdsc->devcmd_lock); |
| 113 | 113 | err = pdsc_devcmd_locked(pdsc, &cmd, &comp, pdsc->devcmd_timeout * 2); |
| 114 | − memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list)); | |
| 114 | + if (!err) | |
| 115 | + memcpy_fromio(&fw_list, pdsc->cmd_regs->data, sizeof(fw_list)); | |
| 115 | 116 | mutex_unlock(&pdsc->devcmd_lock); |
| 116 | 117 | if (err && err != -EIO) |
| 117 | 118 | return err; |
| @@ -107,6 +107,9 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw, · 106 unmodified lines | ||
| 107 | 107 | |
| 108 | 108 | dev_info(pdsc->dev, "Installing firmware\n"); |
| 109 | 109 | |
| 110 | + if (!pdsc->cmd_regs) | |
| 111 | + return -ENXIO; | |
| 112 | + | |
| 110 | 113 | dl = priv_to_devlink(pdsc); |
| 111 | 114 | devlink_flash_update_status_notify(dl, "Preparing to flash", |
| 112 | 115 | NULL, 0, 0); |
| @@ -37,6 +37,11 @@ static void pdsc_unmap_bars(struct pdsc *pdsc) · 36 unmodified lines | ||
| 37 | 37 | struct pdsc_dev_bar *bars = pdsc->bars; |
| 38 | 38 | unsigned int i; |
| 39 | 39 | |
| 40 | + pdsc->info_regs = NULL; | |
| 41 | + pdsc->cmd_regs = NULL; | |
| 42 | + pdsc->intr_status = NULL; | |
| 43 | + pdsc->intr_ctrl = NULL; | |
| 44 | + | |
| 40 | 45 | for (i = 0; i < PDS_CORE_BARS_MAX; i++) { |
| 41 | 46 | if (bars[i].vaddr) |
| 42 | 47 | pci_iounmap(pdsc->pdev, bars[i].vaddr); |
| @@ -293,7 +298,7 @@ err_out_stop: · 250 unmodified lines | ||
| 293 | 298 | err_out_teardown: |
| 294 | 299 | pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); |
| 295 | 300 | err_out_unmap_bars: |
| 296 | − del_timer_sync(&pdsc->wdtimer); | |
| 301 | + timer_shutdown_sync(&pdsc->wdtimer); | |
| 297 | 302 | if (pdsc->wq) |
| 298 | 303 | destroy_workqueue(pdsc->wq); |
| 299 | 304 | mutex_destroy(&pdsc->config_lock); |
| @@ -420,7 +425,7 @@ static void pdsc_remove(struct pci_dev *pdev) · 120 unmodified lines | ||
| 420 | 425 | */ |
| 421 | 426 | pdsc_sriov_configure(pdev, 0); |
| 422 | 427 | |
| 423 | − del_timer_sync(&pdsc->wdtimer); | |
| 428 | + timer_shutdown_sync(&pdsc->wdtimer); | |
| 424 | 429 | if (pdsc->wq) |
| 425 | 430 | destroy_workqueue(pdsc->wq); |
| 426 | 431 | |
| @@ -433,7 +438,6 @@ static void pdsc_remove(struct pci_dev *pdev) · 6 unmodified lines | ||
| 433 | 438 | mutex_destroy(&pdsc->config_lock); |
| 434 | 439 | mutex_destroy(&pdsc->devcmd_lock); |
| 435 | 440 | |
| 436 | − pci_free_irq_vectors(pdev); | |
| 437 | 441 | pdsc_unmap_bars(pdsc); |
| 438 | 442 | pci_release_regions(pdev); |
| 439 | 443 | } |
| @@ -445,13 +449,26 @@ static void pdsc_remove(struct pci_dev *pdev) · 5 unmodified lines | ||
| 445 | 449 | devlink_free(dl); |
| 446 | 450 | } |
| 447 | 451 | |
| 452 | +static void pdsc_stop_health_thread(struct pdsc *pdsc) | |
| 453 | +{ | |
| 454 | + timer_shutdown_sync(&pdsc->wdtimer); | |
| 455 | + if (pdsc->health_work.func) | |
| 456 | + cancel_work_sync(&pdsc->health_work); | |
| 457 | +} | |
| 458 | + | |
| 459 | +static void pdsc_restart_health_thread(struct pdsc *pdsc) | |
| 460 | +{ | |
| 461 | + timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0); | |
| 462 | + mod_timer(&pdsc->wdtimer, jiffies + 1); | |
| 463 | +} | |
| 464 | + | |
| 448 | 465 | void pdsc_reset_prepare(struct pci_dev *pdev) |
| 449 | 466 | { |
| 450 | 467 | struct pdsc *pdsc = pci_get_drvdata(pdev); |
| 451 | 468 | |
| 469 | + pdsc_stop_health_thread(pdsc); | |
| 452 | 470 | pdsc_fw_down(pdsc); |
| 453 | 471 | |
| 454 | − pci_free_irq_vectors(pdev); | |
| 455 | 472 | pdsc_unmap_bars(pdsc); |
| 456 | 473 | pci_release_regions(pdev); |
| 457 | 474 | pci_disable_device(pdev); |
| @@ -486,6 +503,7 @@ void pdsc_reset_done(struct pci_dev *pdev) · 28 unmodified lines | ||
| 486 | 503 | } |
| 487 | 504 | |
| 488 | 505 | pdsc_fw_up(pdsc); |
| 506 | + pdsc_restart_health_thread(pdsc); | |
| 489 | 507 | } |
| 490 | 508 | |
| 491 | 509 | static const struct pci_error_handlers pdsc_err_handler = { |
| @@ -993,7 +993,7 @@ int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic) · 992 unmodified lines | ||
| 993 | 993 | return 0; |
| 994 | 994 | |
| 995 | 995 | err_exit_hwts_rx: |
| 996 | − aq_ring_free(&aq_ptp->hwts_rx); | |
| 996 | + aq_ring_hwts_rx_free(&aq_ptp->hwts_rx); | |
| 997 | 997 | err_exit_ptp_rx: |
| 998 | 998 | aq_ring_free(&aq_ptp->ptp_rx); |
| 999 | 999 | err_exit_ptp_tx: |
| @@ -1011,7 +1011,7 @@ void aq_ptp_ring_free(struct aq_nic_s *aq_nic) · 11 unmodified lines | ||
| 1011 | 1011 | |
| 1012 | 1012 | aq_ring_free(&aq_ptp->ptp_tx); |
| 1013 | 1013 | aq_ring_free(&aq_ptp->ptp_rx); |
| 1014 | − aq_ring_free(&aq_ptp->hwts_rx); | |
| 1014 | + aq_ring_hwts_rx_free(&aq_ptp->hwts_rx); | |
| 1015 | 1015 | |
| 1016 | 1016 | aq_ptp_skb_ring_release(&aq_ptp->skb_ring); |
| 1017 | 1017 | } |
| @@ -919,6 +919,19 @@ void aq_ring_free(struct aq_ring_s *self) · 918 unmodified lines | ||
| 919 | 919 | } |
| 920 | 920 | } |
| 921 | 921 | |
| 922 | +void aq_ring_hwts_rx_free(struct aq_ring_s *self) | |
| 923 | +{ | |
| 924 | + if (!self) | |
| 925 | + return; | |
| 926 | + | |
| 927 | + if (self->dx_ring) { | |
| 928 | + dma_free_coherent(aq_nic_get_dev(self->aq_nic), | |
| 929 | + self->size * self->dx_size + AQ_CFG_RXDS_DEF, | |
| 930 | + self->dx_ring, self->dx_ring_pa); | |
| 931 | + self->dx_ring = NULL; | |
| 932 | + } | |
| 933 | +} | |
| 934 | + | |
| 922 | 935 | unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data) |
| 923 | 936 | { |
| 924 | 937 | unsigned int count; |
| @@ -210,6 +210,7 @@ int aq_ring_rx_fill(struct aq_ring_s *self); · 209 unmodified lines | ||
| 210 | 210 | int aq_ring_hwts_rx_alloc(struct aq_ring_s *self, |
| 211 | 211 | struct aq_nic_s *aq_nic, unsigned int idx, |
| 212 | 212 | unsigned int size, unsigned int dx_size); |
| 213 | +void aq_ring_hwts_rx_free(struct aq_ring_s *self); | |
| 213 | 214 | void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); |
| 214 | 215 | |
| 215 | 216 | unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data); |
| @@ -793,5 +793,6 @@ static struct platform_driver bcm4908_enet_driver = { · 792 unmodified lines | ||
| 793 | 793 | }; |
| 794 | 794 | module_platform_driver(bcm4908_enet_driver); |
| 795 | 795 | |
| 796 | +MODULE_DESCRIPTION("Broadcom BCM4908 Gigabit Ethernet driver"); | |
| 796 | 797 | MODULE_LICENSE("GPL v2"); |
| 797 | 798 | MODULE_DEVICE_TABLE(of, bcm4908_enet_of_match); |
| @@ -260,4 +260,5 @@ void bcma_mdio_mii_unregister(struct mii_bus *mii_bus) · 259 unmodified lines | ||
| 260 | 260 | EXPORT_SYMBOL_GPL(bcma_mdio_mii_unregister); |
| 261 | 261 | |
| 262 | 262 | MODULE_AUTHOR("Rafał Miłecki"); |
| 263 | +MODULE_DESCRIPTION("Broadcom iProc GBit BCMA MDIO helpers"); | |
| 263 | 264 | MODULE_LICENSE("GPL"); |
| @@ -362,4 +362,5 @@ module_init(bgmac_init) · 361 unmodified lines | ||
| 362 | 362 | module_exit(bgmac_exit) |
| 363 | 363 | |
| 364 | 364 | MODULE_AUTHOR("Rafał Miłecki"); |
| 365 | +MODULE_DESCRIPTION("Broadcom iProc GBit BCMA interface driver"); | |
| 365 | 366 | MODULE_LICENSE("GPL"); |
| @@ -298,4 +298,5 @@ static struct platform_driver bgmac_enet_driver = { · 297 unmodified lines | ||
| 298 | 298 | }; |
| 299 | 299 | |
| 300 | 300 | module_platform_driver(bgmac_enet_driver); |
| 301 | +MODULE_DESCRIPTION("Broadcom iProc GBit platform interface driver"); | |
| 301 | 302 | MODULE_LICENSE("GPL"); |
| @@ -1626,4 +1626,5 @@ int bgmac_enet_resume(struct bgmac *bgmac) · 1625 unmodified lines | ||
| 1626 | 1626 | EXPORT_SYMBOL_GPL(bgmac_enet_resume); |
| 1627 | 1627 | |
| 1628 | 1628 | MODULE_AUTHOR("Rafał Miłecki"); |
| 1629 | +MODULE_DESCRIPTION("Broadcom iProc GBit driver"); | |
| 1629 | 1630 | MODULE_LICENSE("GPL"); |
| @@ -3817,7 +3817,7 @@ static int bnxt_alloc_cp_rings(struct bnxt *bp) · 3816 unmodified lines | ||
| 3817 | 3817 | { |
| 3818 | 3818 | bool sh = !!(bp->flags & BNXT_FLAG_SHARED_RINGS); |
| 3819 | 3819 | int i, j, rc, ulp_base_vec, ulp_msix; |
| 3820 | − int tcs = netdev_get_num_tc(bp->dev); | |
| 3820 | + int tcs = bp->num_tc; | |
| 3821 | 3821 | |
| 3822 | 3822 | if (!tcs) |
| 3823 | 3823 | tcs = 1; |
| @@ -5935,8 +5935,12 @@ static u16 bnxt_get_max_rss_ring(struct bnxt *bp) · 2111 unmodified lines | ||
| 5935 | 5935 | |
| 5936 | 5936 | int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings) |
| 5937 | 5937 | { |
| 5938 | − if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) | |
| 5939 | − return DIV_ROUND_UP(rx_rings, BNXT_RSS_TABLE_ENTRIES_P5); | |
| 5938 | + if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { | |
| 5939 | + if (!rx_rings) | |
| 5940 | + return 0; | |
| 5941 | + return bnxt_calc_nr_ring_pages(rx_rings - 1, | |
| 5942 | + BNXT_RSS_TABLE_ENTRIES_P5); | |
| 5943 | + } | |
| 5940 | 5944 | if (BNXT_CHIP_TYPE_NITRO_A0(bp)) |
| 5941 | 5945 | return 2; |
| 5942 | 5946 | return 1; |
| @@ -6926,7 +6930,7 @@ static int bnxt_hwrm_get_rings(struct bnxt *bp) · 983 unmodified lines | ||
| 6926 | 6930 | if (cp < (rx + tx)) { |
| 6927 | 6931 | rc = __bnxt_trim_rings(bp, &rx, &tx, cp, false); |
| 6928 | 6932 | if (rc) |
| 6929 | − return rc; | |
| 6933 | + goto get_rings_exit; | |
| 6930 | 6934 | if (bp->flags & BNXT_FLAG_AGG_RINGS) |
| 6931 | 6935 | rx <<= 1; |
| 6932 | 6936 | hw_resc->resv_rx_rings = rx; |
| @@ -6938,8 +6942,9 @@ static int bnxt_hwrm_get_rings(struct bnxt *bp) · 5 unmodified lines | ||
| 6938 | 6942 | hw_resc->resv_cp_rings = cp; |
| 6939 | 6943 | hw_resc->resv_stat_ctxs = stats; |
| 6940 | 6944 | } |
| 6945 | +get_rings_exit: | |
| 6941 | 6946 | hwrm_req_drop(bp, req); |
| 6942 | − return 0; | |
| 6947 | + return rc; | |
| 6943 | 6948 | } |
| 6944 | 6949 | |
| 6945 | 6950 | int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings) |
| @@ -7000,10 +7005,11 @@ __bnxt_hwrm_reserve_pf_rings(struct bnxt *bp, int tx_rings, int rx_rings, · 54 unmodified lines | ||
| 7000 | 7005 | |
| 7001 | 7006 | req->num_rx_rings = cpu_to_le16(rx_rings); |
| 7002 | 7007 | if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { |
| 7008 | + u16 rss_ctx = bnxt_get_nr_rss_ctxs(bp, ring_grps); | |
| 7009 | + | |
| 7003 | 7010 | req->num_cmpl_rings = cpu_to_le16(tx_rings + ring_grps); |
| 7004 | 7011 | req->num_msix = cpu_to_le16(cp_rings); |
| 7005 | − req->num_rsscos_ctxs = | |
| 7006 | − cpu_to_le16(DIV_ROUND_UP(ring_grps, 64)); | |
| 7012 | + req->num_rsscos_ctxs = cpu_to_le16(rss_ctx); | |
| 7007 | 7013 | } else { |
| 7008 | 7014 | req->num_cmpl_rings = cpu_to_le16(cp_rings); |
| 7009 | 7015 | req->num_hw_ring_grps = cpu_to_le16(ring_grps); |
| @@ -7050,8 +7056,10 @@ __bnxt_hwrm_reserve_vf_rings(struct bnxt *bp, int tx_rings, int rx_rings, · 40 unmodified lines | ||
| 7050 | 7056 | req->num_tx_rings = cpu_to_le16(tx_rings); |
| 7051 | 7057 | req->num_rx_rings = cpu_to_le16(rx_rings); |
| 7052 | 7058 | if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { |
| 7059 | + u16 rss_ctx = bnxt_get_nr_rss_ctxs(bp, ring_grps); | |
| 7060 | + | |
| 7053 | 7061 | req->num_cmpl_rings = cpu_to_le16(tx_rings + ring_grps); |
| 7054 | − req->num_rsscos_ctxs = cpu_to_le16(DIV_ROUND_UP(ring_grps, 64)); | |
| 7062 | + req->num_rsscos_ctxs = cpu_to_le16(rss_ctx); | |
| 7055 | 7063 | } else { |
| 7056 | 7064 | req->num_cmpl_rings = cpu_to_le16(cp_rings); |
| 7057 | 7065 | req->num_hw_ring_grps = cpu_to_le16(ring_grps); |
| @@ -9938,7 +9946,7 @@ static int __bnxt_num_tx_to_cp(struct bnxt *bp, int tx, int tx_sets, int tx_xdp) · 2880 unmodified lines | ||
| 9938 | 9946 | |
| 9939 | 9947 | int bnxt_num_tx_to_cp(struct bnxt *bp, int tx) |
| 9940 | 9948 | { |
| 9941 | − int tcs = netdev_get_num_tc(bp->dev); | |
| 9949 | + int tcs = bp->num_tc; | |
| 9942 | 9950 | |
| 9943 | 9951 | if (!tcs) |
| 9944 | 9952 | tcs = 1; |
| @@ -9947,7 +9955,7 @@ int bnxt_num_tx_to_cp(struct bnxt *bp, int tx) · 2 unmodified lines | ||
| 9947 | 9955 | |
| 9948 | 9956 | static int bnxt_num_cp_to_tx(struct bnxt *bp, int tx_cp) |
| 9949 | 9957 | { |
| 9950 | − int tcs = netdev_get_num_tc(bp->dev); | |
| 9958 | + int tcs = bp->num_tc; | |
| 9951 | 9959 | |
| 9952 | 9960 | return (tx_cp - bp->tx_nr_rings_xdp) * tcs + |
| 9953 | 9961 | bp->tx_nr_rings_xdp; |
| @@ -9977,7 +9985,7 @@ static void bnxt_setup_msix(struct bnxt *bp) · 23 unmodified lines | ||
| 9977 | 9985 | struct net_device *dev = bp->dev; |
| 9978 | 9986 | int tcs, i; |
| 9979 | 9987 | |
| 9980 | − tcs = netdev_get_num_tc(dev); | |
| 9988 | + tcs = bp->num_tc; | |
| 9981 | 9989 | if (tcs) { |
| 9982 | 9990 | int i, off, count; |
| 9983 | 9991 | |
| @@ -10009,8 +10017,10 @@ static void bnxt_setup_inta(struct bnxt *bp) · 25 unmodified lines | ||
| 10009 | 10017 | { |
| 10010 | 10018 | const int len = sizeof(bp->irq_tbl[0].name); |
| 10011 | 10019 | |
| 10012 | − if (netdev_get_num_tc(bp->dev)) | |
| 10020 | + if (bp->num_tc) { | |
| 10013 | 10021 | netdev_reset_tc(bp->dev); |
| 10022 | + bp->num_tc = 0; | |
| 10023 | + } | |
| 10014 | 10024 | |
| 10015 | 10025 | snprintf(bp->irq_tbl[0].name, len, "%s-%s-%d", bp->dev->name, "TxRx", |
| 10016 | 10026 | 0); |
| @@ -10236,8 +10246,8 @@ static void bnxt_clear_int_mode(struct bnxt *bp) · 219 unmodified lines | ||
| 10236 | 10246 | |
| 10237 | 10247 | int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init) |
| 10238 | 10248 | { |
| 10239 | − int tcs = netdev_get_num_tc(bp->dev); | |
| 10240 | 10249 | bool irq_cleared = false; |
| 10250 | + int tcs = bp->num_tc; | |
| 10241 | 10251 | int rc; |
| 10242 | 10252 | |
| 10243 | 10253 | if (!bnxt_need_reserve_rings(bp)) |
| @@ -10263,6 +10273,7 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init) · 19 unmodified lines | ||
| 10263 | 10273 | bp->tx_nr_rings - bp->tx_nr_rings_xdp)) { |
| 10264 | 10274 | netdev_err(bp->dev, "tx ring reservation failure\n"); |
| 10265 | 10275 | netdev_reset_tc(bp->dev); |
| 10276 | + bp->num_tc = 0; | |
| 10266 | 10277 | if (bp->tx_nr_rings_xdp) |
| 10267 | 10278 | bp->tx_nr_rings_per_tc = bp->tx_nr_rings_xdp; |
| 10268 | 10279 | else |
| @@ -11564,10 +11575,12 @@ int bnxt_half_open_nic(struct bnxt *bp) · 1295 unmodified lines | ||
| 11564 | 11575 | netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); |
| 11565 | 11576 | goto half_open_err; |
| 11566 | 11577 | } |
| 11578 | + bnxt_init_napi(bp); | |
| 11567 | 11579 | set_bit(BNXT_STATE_HALF_OPEN, &bp->state); |
| 11568 | 11580 | rc = bnxt_init_nic(bp, true); |
| 11569 | 11581 | if (rc) { |
| 11570 | 11582 | clear_bit(BNXT_STATE_HALF_OPEN, &bp->state); |
| 11583 | + bnxt_del_napi(bp); | |
| 11571 | 11584 | netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc); |
| 11572 | 11585 | goto half_open_err; |
| 11573 | 11586 | } |
| @@ -11586,6 +11599,7 @@ half_open_err: · 12 unmodified lines | ||
| 11586 | 11599 | void bnxt_half_close_nic(struct bnxt *bp) |
| 11587 | 11600 | { |
| 11588 | 11601 | bnxt_hwrm_resource_free(bp, false, true); |
| 11602 | + bnxt_del_napi(bp); | |
| 11589 | 11603 | bnxt_free_skbs(bp); |
| 11590 | 11604 | bnxt_free_mem(bp, true); |
| 11591 | 11605 | clear_bit(BNXT_STATE_HALF_OPEN, &bp->state); |
| @@ -13232,6 +13246,11 @@ static int bnxt_fw_init_one_p1(struct bnxt *bp) · 1640 unmodified lines | ||
| 13232 | 13246 | |
| 13233 | 13247 | bp->fw_cap = 0; |
| 13234 | 13248 | rc = bnxt_hwrm_ver_get(bp); |
| 13249 | + /* FW may be unresponsive after FLR. FLR must complete within 100 msec | |
| 13250 | + * so wait before continuing with recovery. | |
| 13251 | + */ | |
| 13252 | + if (rc) | |
| 13253 | + msleep(100); | |
| 13235 | 13254 | bnxt_try_map_fw_health_reg(bp); |
| 13236 | 13255 | if (rc) { |
| 13237 | 13256 | rc = bnxt_try_recover_fw(bp); |
| @@ -13784,7 +13803,7 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc) · 546 unmodified lines | ||
| 13784 | 13803 | return -EINVAL; |
| 13785 | 13804 | } |
| 13786 | 13805 | |
| 13787 | − if (netdev_get_num_tc(dev) == tc) | |
| 13806 | + if (bp->num_tc == tc) | |
| 13788 | 13807 | return 0; |
| 13789 | 13808 | |
| 13790 | 13809 | if (bp->flags & BNXT_FLAG_SHARED_RINGS) |
| @@ -13802,9 +13821,11 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc) · 11 unmodified lines | ||
| 13802 | 13821 | if (tc) { |
| 13803 | 13822 | bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc; |
| 13804 | 13823 | netdev_set_num_tc(dev, tc); |
| 13824 | + bp->num_tc = tc; | |
| 13805 | 13825 | } else { |
| 13806 | 13826 | bp->tx_nr_rings = bp->tx_nr_rings_per_tc; |
| 13807 | 13827 | netdev_reset_tc(dev); |
| 13828 | + bp->num_tc = 0; | |
| 13808 | 13829 | } |
| 13809 | 13830 | bp->tx_nr_rings += bp->tx_nr_rings_xdp; |
| 13810 | 13831 | tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_nr_rings); |
| @@ -2225,6 +2225,7 @@ struct bnxt { · 2224 unmodified lines | ||
| 2225 | 2225 | u8 tc_to_qidx[BNXT_MAX_QUEUE]; |
| 2226 | 2226 | u8 q_ids[BNXT_MAX_QUEUE]; |
| 2227 | 2227 | u8 max_q; |
| 2228 | + u8 num_tc; | |
| 2228 | 2229 | |
| 2229 | 2230 | unsigned int current_interval; |
| 2230 | 2231 | #define BNXT_TIMER_INTERVAL HZ |
| @@ -228,7 +228,7 @@ static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask) · 227 unmodified lines | ||
| 228 | 228 | } |
| 229 | 229 | } |
| 230 | 230 | if (bp->ieee_ets) { |
| 231 | − int tc = netdev_get_num_tc(bp->dev); | |
| 231 | + int tc = bp->num_tc; | |
| 232 | 232 | |
| 233 | 233 | if (!tc) |
| 234 | 234 | tc = 1; |
| @@ -884,7 +884,7 @@ static void bnxt_get_channels(struct net_device *dev, · 883 unmodified lines | ||
| 884 | 884 | if (max_tx_sch_inputs) |
| 885 | 885 | max_tx_rings = min_t(int, max_tx_rings, max_tx_sch_inputs); |
| 886 | 886 | |
| 887 | − tcs = netdev_get_num_tc(dev); | |
| 887 | + tcs = bp->num_tc; | |
| 888 | 888 | tx_grps = max(tcs, 1); |
| 889 | 889 | if (bp->tx_nr_rings_xdp) |
| 890 | 890 | tx_grps++; |
| @@ -944,7 +944,7 @@ static int bnxt_set_channels(struct net_device *dev, · 53 unmodified lines | ||
| 944 | 944 | if (channel->combined_count) |
| 945 | 945 | sh = true; |
| 946 | 946 | |
| 947 | − tcs = netdev_get_num_tc(dev); | |
| 947 | + tcs = bp->num_tc; | |
| 948 | 948 | |
| 949 | 949 | req_tx_rings = sh ? channel->combined_count : channel->tx_count; |
| 950 | 950 | req_rx_rings = sh ? channel->combined_count : channel->rx_count; |
| @@ -1574,7 +1574,8 @@ u32 bnxt_get_rxfh_indir_size(struct net_device *dev) · 623 unmodified lines | ||
| 1574 | 1574 | struct bnxt *bp = netdev_priv(dev); |
| 1575 | 1575 | |
| 1576 | 1576 | if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) |
| 1577 | − return ALIGN(bp->rx_nr_rings, BNXT_RSS_TABLE_ENTRIES_P5); | |
| 1577 | + return bnxt_get_nr_rss_ctxs(bp, bp->rx_nr_rings) * | |
| 1578 | + BNXT_RSS_TABLE_ENTRIES_P5; | |
| 1578 | 1579 | return HW_HASH_INDEX_SIZE; |
| 1579 | 1580 | } |
| 1580 | 1581 | |
| @@ -684,7 +684,7 @@ static void bnxt_stamp_tx_skb(struct bnxt *bp, struct sk_buff *skb) · 683 unmodified lines | ||
| 684 | 684 | timestamp.hwtstamp = ns_to_ktime(ns); |
| 685 | 685 | skb_tstamp_tx(ptp->tx_skb, ×tamp); |
| 686 | 686 | } else { |
| 687 | − netdev_WARN_ONCE(bp->dev, | |
| 687 | + netdev_warn_once(bp->dev, | |
| 688 | 688 | "TS query for TX timer failed rc = %x\n", rc); |
| 689 | 689 | } |
| 690 | 690 | |
| @@ -407,7 +407,7 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog) · 406 unmodified lines | ||
| 407 | 407 | if (prog) |
| 408 | 408 | tx_xdp = bp->rx_nr_rings; |
| 409 | 409 | |
| 410 | − tc = netdev_get_num_tc(dev); | |
| 410 | + tc = bp->num_tc; | |
| 411 | 411 | if (!tc) |
| 412 | 412 | tc = 1; |
| 413 | 413 | rc = bnxt_check_rings(bp, bp->tx_nr_rings_per_tc, bp->rx_nr_rings, |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #include "octeon_network.h" |
| 28 | 28 | |
| 29 | 29 | MODULE_AUTHOR("Cavium Networks, <support@cavium.com>"); |
| 30 | +MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Core"); | |
| 30 | 31 | MODULE_LICENSE("GPL"); |
| 31 | 32 | |
| 32 | 33 | /* OOM task polling interval */ |
| @@ -868,5 +868,6 @@ static struct platform_driver ep93xx_eth_driver = { · 867 unmodified lines | ||
| 868 | 868 | |
| 869 | 869 | module_platform_driver(ep93xx_eth_driver); |
| 870 | 870 | |
| 871 | +MODULE_DESCRIPTION("Cirrus EP93xx Ethernet driver"); | |
| 871 | 872 | MODULE_LICENSE("GPL"); |
| 872 | 873 | MODULE_ALIAS("platform:ep93xx-eth"); |
| @@ -719,17 +719,25 @@ static void tsnep_xdp_xmit_flush(struct tsnep_tx *tx) · 718 unmodified lines | ||
| 719 | 719 | |
| 720 | 720 | static bool tsnep_xdp_xmit_back(struct tsnep_adapter *adapter, |
| 721 | 721 | struct xdp_buff *xdp, |
| 722 | − struct netdev_queue *tx_nq, struct tsnep_tx *tx) | |
| 722 | + struct netdev_queue *tx_nq, struct tsnep_tx *tx, | |
| 723 | + bool zc) | |
| 723 | 724 | { |
| 724 | 725 | struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); |
| 725 | 726 | bool xmit; |
| 727 | + u32 type; | |
| 726 | 728 | |
| 727 | 729 | if (unlikely(!xdpf)) |
| 728 | 730 | return false; |
| 729 | 731 | |
| 732 | + /* no page pool for zero copy */ | |
| 733 | + if (zc) | |
| 734 | + type = TSNEP_TX_TYPE_XDP_NDO; | |
| 735 | + else | |
| 736 | + type = TSNEP_TX_TYPE_XDP_TX; | |
| 737 | + | |
| 730 | 738 | __netif_tx_lock(tx_nq, smp_processor_id()); |
| 731 | 739 | |
| 732 | − xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, TSNEP_TX_TYPE_XDP_TX); | |
| 740 | + xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, type); | |
| 733 | 741 | |
| 734 | 742 | /* Avoid transmit queue timeout since we share it with the slow path */ |
| 735 | 743 | if (xmit) |
| @@ -1273,7 +1281,7 @@ static bool tsnep_xdp_run_prog(struct tsnep_rx *rx, struct bpf_prog *prog, · 537 unmodified lines | ||
| 1273 | 1281 | case XDP_PASS: |
| 1274 | 1282 | return false; |
| 1275 | 1283 | case XDP_TX: |
| 1276 | − if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) | |
| 1284 | + if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, false)) | |
| 1277 | 1285 | goto out_failure; |
| 1278 | 1286 | *status |= TSNEP_XDP_TX; |
| 1279 | 1287 | return true; |
| @@ -1323,7 +1331,7 @@ static bool tsnep_xdp_run_prog_zc(struct tsnep_rx *rx, struct bpf_prog *prog, · 43 unmodified lines | ||
| 1323 | 1331 | case XDP_PASS: |
| 1324 | 1332 | return false; |
| 1325 | 1333 | case XDP_TX: |
| 1326 | − if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) | |
| 1334 | + if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, true)) | |
| 1327 | 1335 | goto out_failure; |
| 1328 | 1336 | *status |= TSNEP_XDP_TX; |
| 1329 | 1337 | return true; |
| @@ -1485,7 +1493,7 @@ static int tsnep_rx_poll(struct tsnep_rx *rx, struct napi_struct *napi, · 155 unmodified lines | ||
| 1485 | 1493 | |
| 1486 | 1494 | xdp_prepare_buff(&xdp, page_address(entry->page), |
| 1487 | 1495 | XDP_PACKET_HEADROOM + TSNEP_RX_INLINE_METADATA_SIZE, |
| 1488 | − length, false); | |
| 1496 | + length - ETH_FCS_LEN, false); | |
| 1489 | 1497 | |
| 1490 | 1498 | consume = tsnep_xdp_run_prog(rx, prog, &xdp, |
| 1491 | 1499 | &xdp_status, tx_nq, tx); |
| @@ -1568,7 +1576,7 @@ static int tsnep_rx_poll_zc(struct tsnep_rx *rx, struct napi_struct *napi, · 76 unmodified lines | ||
| 1568 | 1576 | prefetch(entry->xdp->data); |
| 1569 | 1577 | length = __le32_to_cpu(entry->desc_wb->properties) & |
| 1570 | 1578 | TSNEP_DESC_LENGTH_MASK; |
| 1571 | − xsk_buff_set_size(entry->xdp, length); | |
| 1579 | + xsk_buff_set_size(entry->xdp, length - ETH_FCS_LEN); | |
| 1572 | 1580 | xsk_buff_dma_sync_for_cpu(entry->xdp, rx->xsk_pool); |
| 1573 | 1581 | |
| 1574 | 1582 | /* RX metadata with timestamps is in front of actual data, |
| @@ -1762,6 +1770,19 @@ static void tsnep_rx_reopen_xsk(struct tsnep_rx *rx) · 187 unmodified lines | ||
| 1762 | 1770 | allocated--; |
| 1763 | 1771 | } |
| 1764 | 1772 | } |
| 1773 | + | |
| 1774 | + /* set need wakeup flag immediately if ring is not filled completely, | |
| 1775 | + * first polling would be too late as need wakeup signalisation would | |
| 1776 | + * be delayed for an indefinite time | |
| 1777 | + */ | |
| 1778 | + if (xsk_uses_need_wakeup(rx->xsk_pool)) { | |
| 1779 | + int desc_available = tsnep_rx_desc_available(rx); | |
| 1780 | + | |
| 1781 | + if (desc_available) | |
| 1782 | + xsk_set_rx_need_wakeup(rx->xsk_pool); | |
| 1783 | + else | |
| 1784 | + xsk_clear_rx_need_wakeup(rx->xsk_pool); | |
| 1785 | + } | |
| 1765 | 1786 | } |
| 1766 | 1787 | |
| 1767 | 1788 | static bool tsnep_pending(struct tsnep_queue *queue) |
| @@ -661,4 +661,5 @@ static struct platform_driver nps_enet_driver = { · 660 unmodified lines | ||
| 661 | 661 | module_platform_driver(nps_enet_driver); |
| 662 | 662 | |
| 663 | 663 | MODULE_AUTHOR("EZchip Semiconductor"); |
| 664 | +MODULE_DESCRIPTION("EZchip NPS Ethernet driver"); | |
| 664 | 665 | MODULE_LICENSE("GPL v2"); |
| @@ -3216,4 +3216,5 @@ void enetc_pci_remove(struct pci_dev *pdev) · 3215 unmodified lines | ||
| 3216 | 3216 | } |
| 3217 | 3217 | EXPORT_SYMBOL_GPL(enetc_pci_remove); |
| 3218 | 3218 | |
| 3219 | +MODULE_DESCRIPTION("NXP ENETC Ethernet driver"); | |
| 3219 | 3220 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -2036,6 +2036,7 @@ static void fec_enet_adjust_link(struct net_device *ndev) · 2035 unmodified lines | ||
| 2036 | 2036 | |
| 2037 | 2037 | /* if any of the above changed restart the FEC */ |
| 2038 | 2038 | if (status_change) { |
| 2039 | + netif_stop_queue(ndev); | |
| 2039 | 2040 | napi_disable(&fep->napi); |
| 2040 | 2041 | netif_tx_lock_bh(ndev); |
| 2041 | 2042 | fec_restart(ndev); |
| @@ -2045,6 +2046,7 @@ static void fec_enet_adjust_link(struct net_device *ndev) · 3 unmodified lines | ||
| 2045 | 2046 | } |
| 2046 | 2047 | } else { |
| 2047 | 2048 | if (fep->link) { |
| 2049 | + netif_stop_queue(ndev); | |
| 2048 | 2050 | napi_disable(&fep->napi); |
| 2049 | 2051 | netif_tx_lock_bh(ndev); |
| 2050 | 2052 | fec_stop(ndev); |
| @@ -4769,4 +4771,5 @@ static struct platform_driver fec_driver = { · 2718 unmodified lines | ||
| 4769 | 4771 | |
| 4770 | 4772 | module_platform_driver(fec_driver); |
| 4771 | 4773 | |
| 4774 | +MODULE_DESCRIPTION("NXP Fast Ethernet Controller (FEC) driver"); | |
| 4772 | 4775 | MODULE_LICENSE("GPL"); |
| @@ -531,4 +531,5 @@ static struct platform_driver fsl_pq_mdio_driver = { · 530 unmodified lines | ||
| 531 | 531 | |
| 532 | 532 | module_platform_driver(fsl_pq_mdio_driver); |
| 533 | 533 | |
| 534 | +MODULE_DESCRIPTION("Freescale PQ MDIO helpers"); | |
| 534 | 535 | MODULE_LICENSE("GPL"); |
| @@ -356,7 +356,7 @@ static enum pkt_hash_types gve_rss_type(__be16 pkt_flags) · 355 unmodified lines | ||
| 356 | 356 | |
| 357 | 357 | static struct sk_buff *gve_rx_add_frags(struct napi_struct *napi, |
| 358 | 358 | struct gve_rx_slot_page_info *page_info, |
| 359 | − u16 packet_buffer_size, u16 len, | |
| 359 | + unsigned int truesize, u16 len, | |
| 360 | 360 | struct gve_rx_ctx *ctx) |
| 361 | 361 | { |
| 362 | 362 | u32 offset = page_info->page_offset + page_info->pad; |
| @@ -389,10 +389,10 @@ static struct sk_buff *gve_rx_add_frags(struct napi_struct *napi, · 26 unmodified lines | ||
| 389 | 389 | if (skb != ctx->skb_head) { |
| 390 | 390 | ctx->skb_head->len += len; |
| 391 | 391 | ctx->skb_head->data_len += len; |
| 392 | − ctx->skb_head->truesize += packet_buffer_size; | |
| 392 | + ctx->skb_head->truesize += truesize; | |
| 393 | 393 | } |
| 394 | 394 | skb_add_rx_frag(skb, num_frags, page_info->page, |
| 395 | − offset, len, packet_buffer_size); | |
| 395 | + offset, len, truesize); | |
| 396 | 396 | |
| 397 | 397 | return ctx->skb_head; |
| 398 | 398 | } |
| @@ -486,7 +486,7 @@ static struct sk_buff *gve_rx_copy_to_pool(struct gve_rx_ring *rx, · 87 unmodified lines | ||
| 486 | 486 | |
| 487 | 487 | memcpy(alloc_page_info.page_address, src, page_info->pad + len); |
| 488 | 488 | skb = gve_rx_add_frags(napi, &alloc_page_info, |
| 489 | − rx->packet_buffer_size, | |
| 489 | + PAGE_SIZE, | |
| 490 | 490 | len, ctx); |
| 491 | 491 | |
| 492 | 492 | u64_stats_update_begin(&rx->statss); |
| @@ -360,23 +360,43 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca); · 359 unmodified lines | ||
| 360 | 360 | * As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of |
| 361 | 361 | * INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n) |
| 362 | 362 | * bits to count nanoseconds leaving the rest for fractional nonseconds. |
| 363 | + * | |
| 364 | + * Any given INCVALUE also has an associated maximum adjustment value. This | |
| 365 | + * maximum adjustment value is the largest increase (or decrease) which can be | |
| 366 | + * safely applied without overflowing the INCVALUE. Since INCVALUE has | |
| 367 | + * a maximum range of 24 bits, its largest value is 0xFFFFFF. | |
| 368 | + * | |
| 369 | + * To understand where the maximum value comes from, consider the following | |
| 370 | + * equation: | |
| 371 | + * | |
| 372 | + * new_incval = base_incval + (base_incval * adjustment) / 1billion | |
| 373 | + * | |
| 374 | + * To avoid overflow that means: | |
| 375 | + * max_incval = base_incval + (base_incval * max_adj) / billion | |
| 376 | + * | |
| 377 | + * Re-arranging: | |
| 378 | + * max_adj = floor(((max_incval - base_incval) * 1billion) / 1billion) | |
| 363 | 379 | */ |
| 364 | 380 | #define INCVALUE_96MHZ 125 |
| 365 | 381 | #define INCVALUE_SHIFT_96MHZ 17 |
| 366 | 382 | #define INCPERIOD_SHIFT_96MHZ 2 |
| 367 | 383 | #define INCPERIOD_96MHZ (12 >> INCPERIOD_SHIFT_96MHZ) |
| 384 | +#define MAX_PPB_96MHZ 23999900 /* 23,999,900 ppb */ | |
| 368 | 385 | |
| 369 | 386 | #define INCVALUE_25MHZ 40 |
| 370 | 387 | #define INCVALUE_SHIFT_25MHZ 18 |
| 371 | 388 | #define INCPERIOD_25MHZ 1 |
| 389 | +#define MAX_PPB_25MHZ 599999900 /* 599,999,900 ppb */ | |
| 372 | 390 | |
| 373 | 391 | #define INCVALUE_24MHZ 125 |
| 374 | 392 | #define INCVALUE_SHIFT_24MHZ 14 |
| 375 | 393 | #define INCPERIOD_24MHZ 3 |
| 394 | +#define MAX_PPB_24MHZ 999999999 /* 999,999,999 ppb */ | |
| 376 | 395 | |
| 377 | 396 | #define INCVALUE_38400KHZ 26 |
| 378 | 397 | #define INCVALUE_SHIFT_38400KHZ 19 |
| 379 | 398 | #define INCPERIOD_38400KHZ 1 |
| 399 | +#define MAX_PPB_38400KHZ 230769100 /* 230,769,100 ppb */ | |
| 380 | 400 | |
| 381 | 401 | /* Another drawback of scaling the incvalue by a large factor is the |
| 382 | 402 | * 64-bit SYSTIM register overflows more quickly. This is dealt with |
| @@ -280,8 +280,17 @@ void e1000e_ptp_init(struct e1000_adapter *adapter) · 279 unmodified lines | ||
| 280 | 280 | |
| 281 | 281 | switch (hw->mac.type) { |
| 282 | 282 | case e1000_pch2lan: |
| 283 | + adapter->ptp_clock_info.max_adj = MAX_PPB_96MHZ; | |
| 284 | + break; | |
| 283 | 285 | case e1000_pch_lpt: |
| 286 | + if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) | |
| 287 | + adapter->ptp_clock_info.max_adj = MAX_PPB_96MHZ; | |
| 288 | + else | |
| 289 | + adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ; | |
| 290 | + break; | |
| 284 | 291 | case e1000_pch_spt: |
| 292 | + adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ; | |
| 293 | + break; | |
| 285 | 294 | case e1000_pch_cnp: |
| 286 | 295 | case e1000_pch_tgp: |
| 287 | 296 | case e1000_pch_adp: |
| @@ -289,15 +298,14 @@ void e1000e_ptp_init(struct e1000_adapter *adapter) · 1 unmodified line | ||
| 289 | 298 | case e1000_pch_lnp: |
| 290 | 299 | case e1000_pch_ptp: |
| 291 | 300 | case e1000_pch_nvp: |
| 292 | − if ((hw->mac.type < e1000_pch_lpt) || | |
| 293 | − (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { | |
| 294 | − adapter->ptp_clock_info.max_adj = 24000000 - 1; | |
| 295 | − break; | |
| 296 | − } | |
| 297 | − fallthrough; | |
| 301 | + if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) | |
| 302 | + adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ; | |
| 303 | + else | |
| 304 | + adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ; | |
| 305 | + break; | |
| 298 | 306 | case e1000_82574: |
| 299 | 307 | case e1000_82583: |
| 300 | − adapter->ptp_clock_info.max_adj = 600000000 - 1; | |
| 308 | + adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ; | |
| 301 | 309 | break; |
| 302 | 310 | default: |
| 303 | 311 | break; |
| @@ -43,7 +43,7 @@ · 42 unmodified lines | ||
| 43 | 43 | #define I40E_LLDP_TLV_SUBTYPE_SHIFT 0 |
| 44 | 44 | #define I40E_LLDP_TLV_SUBTYPE_MASK (0xFF << I40E_LLDP_TLV_SUBTYPE_SHIFT) |
| 45 | 45 | #define I40E_LLDP_TLV_OUI_SHIFT 8 |
| 46 | −#define I40E_LLDP_TLV_OUI_MASK (0xFFFFFF << I40E_LLDP_TLV_OUI_SHIFT) | |
| 46 | +#define I40E_LLDP_TLV_OUI_MASK (0xFFFFFFU << I40E_LLDP_TLV_OUI_SHIFT) | |
| 47 | 47 | |
| 48 | 48 | /* Defines for IEEE ETS TLV */ |
| 49 | 49 | #define I40E_IEEE_ETS_MAXTC_SHIFT 0 |
| @@ -3588,40 +3588,55 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring) · 3587 unmodified lines | ||
| 3588 | 3588 | struct i40e_hmc_obj_rxq rx_ctx; |
| 3589 | 3589 | int err = 0; |
| 3590 | 3590 | bool ok; |
| 3591 | − int ret; | |
| 3592 | 3591 | |
| 3593 | 3592 | bitmap_zero(ring->state, __I40E_RING_STATE_NBITS); |
| 3594 | 3593 | |
| 3595 | 3594 | /* clear the context structure first */ |
| 3596 | 3595 | memset(&rx_ctx, 0, sizeof(rx_ctx)); |
| 3597 | 3596 | |
| 3598 | − if (ring->vsi->type == I40E_VSI_MAIN) | |
| 3599 | − xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); | |
| 3597 | + ring->rx_buf_len = vsi->rx_buf_len; | |
| 3598 | + | |
| 3599 | + /* XDP RX-queue info only needed for RX rings exposed to XDP */ | |
| 3600 | + if (ring->vsi->type != I40E_VSI_MAIN) | |
| 3601 | + goto skip; | |
| 3602 | + | |
| 3603 | + if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) { | |
| 3604 | + err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, | |
| 3605 | + ring->queue_index, | |
| 3606 | + ring->q_vector->napi.napi_id, | |
| 3607 | + ring->rx_buf_len); | |
| 3608 | + if (err) | |
| 3609 | + return err; | |
| 3610 | + } | |
| 3600 | 3611 | |
| 3601 | 3612 | ring->xsk_pool = i40e_xsk_pool(ring); |
| 3602 | 3613 | if (ring->xsk_pool) { |
| 3603 | − ring->rx_buf_len = | |
| 3604 | − xsk_pool_get_rx_frame_size(ring->xsk_pool); | |
| 3605 | − ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, | |
| 3614 | + xdp_rxq_info_unreg(&ring->xdp_rxq); | |
| 3615 | + ring->rx_buf_len = xsk_pool_get_rx_frame_size(ring->xsk_pool); | |
| 3616 | + err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, | |
| 3617 | + ring->queue_index, | |
| 3618 | + ring->q_vector->napi.napi_id, | |
| 3619 | + ring->rx_buf_len); | |
| 3620 | + if (err) | |
| 3621 | + return err; | |
| 3622 | + err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, | |
| 3606 | 3623 | MEM_TYPE_XSK_BUFF_POOL, |
| 3607 | 3624 | NULL); |
| 3608 | − if (ret) | |
| 3609 | − return ret; | |
| 3625 | + if (err) | |
| 3626 | + return err; | |
| 3610 | 3627 | dev_info(&vsi->back->pdev->dev, |
| 3611 | 3628 | "Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n", |
| 3612 | 3629 | ring->queue_index); |
| 3613 | 3630 | |
| 3614 | 3631 | } else { |
| 3615 | − ring->rx_buf_len = vsi->rx_buf_len; | |
| 3616 | − if (ring->vsi->type == I40E_VSI_MAIN) { | |
| 3617 | − ret = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, | |
| 3618 | − MEM_TYPE_PAGE_SHARED, | |
| 3619 | − NULL); | |
| 3620 | − if (ret) | |
| 3621 | − return ret; | |
| 3622 | − } | |
| 3632 | + err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, | |
| 3633 | + MEM_TYPE_PAGE_SHARED, | |
| 3634 | + NULL); | |
| 3635 | + if (err) | |
| 3636 | + return err; | |
| 3623 | 3637 | } |
| 3624 | 3638 | |
| 3639 | +skip: | |
| 3625 | 3640 | xdp_init_buff(&ring->xdp, i40e_rx_pg_size(ring) / 2, &ring->xdp_rxq); |
| 3626 | 3641 | |
| 3627 | 3642 | rx_ctx.dbuff = DIV_ROUND_UP(ring->rx_buf_len, |
| @@ -1548,7 +1548,6 @@ void i40e_free_rx_resources(struct i40e_ring *rx_ring) · 1547 unmodified lines | ||
| 1548 | 1548 | int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring) |
| 1549 | 1549 | { |
| 1550 | 1550 | struct device *dev = rx_ring->dev; |
| 1551 | − int err; | |
| 1552 | 1551 | |
| 1553 | 1552 | u64_stats_init(&rx_ring->syncp); |
| 1554 | 1553 | |
| @@ -1569,14 +1568,6 @@ int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring) · 14 unmodified lines | ||
| 1569 | 1568 | rx_ring->next_to_process = 0; |
| 1570 | 1569 | rx_ring->next_to_use = 0; |
| 1571 | 1570 | |
| 1572 | − /* XDP RX-queue info only needed for RX rings exposed to XDP */ | |
| 1573 | − if (rx_ring->vsi->type == I40E_VSI_MAIN) { | |
| 1574 | − err = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, | |
| 1575 | − rx_ring->queue_index, rx_ring->q_vector->napi.napi_id); | |
| 1576 | − if (err < 0) | |
| 1577 | − return err; | |
| 1578 | − } | |
| 1579 | − | |
| 1580 | 1571 | rx_ring->xdp_prog = rx_ring->vsi->xdp_prog; |
| 1581 | 1572 | |
| 1582 | 1573 | rx_ring->rx_bi = |
| @@ -2087,7 +2078,8 @@ static void i40e_put_rx_buffer(struct i40e_ring *rx_ring, · 504 unmodified lines | ||
| 2087 | 2078 | static void i40e_process_rx_buffs(struct i40e_ring *rx_ring, int xdp_res, |
| 2088 | 2079 | struct xdp_buff *xdp) |
| 2089 | 2080 | { |
| 2090 | − u32 next = rx_ring->next_to_clean; | |
| 2081 | + u32 nr_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags; | |
| 2082 | + u32 next = rx_ring->next_to_clean, i = 0; | |
| 2091 | 2083 | struct i40e_rx_buffer *rx_buffer; |
| 2092 | 2084 | |
| 2093 | 2085 | xdp->flags = 0; |
| @@ -2100,10 +2092,10 @@ static void i40e_process_rx_buffs(struct i40e_ring *rx_ring, int xdp_res, · 6 unmodified lines | ||
| 2100 | 2092 | if (!rx_buffer->page) |
| 2101 | 2093 | continue; |
| 2102 | 2094 | |
| 2103 | − if (xdp_res == I40E_XDP_CONSUMED) | |
| 2104 | − rx_buffer->pagecnt_bias++; | |
| 2105 | − else | |
| 2095 | + if (xdp_res != I40E_XDP_CONSUMED) | |
| 2106 | 2096 | i40e_rx_buffer_flip(rx_buffer, xdp->frame_sz); |
| 2097 | + else if (i++ <= nr_frags) | |
| 2098 | + rx_buffer->pagecnt_bias++; | |
| 2107 | 2099 | |
| 2108 | 2100 | /* EOP buffer will be put in i40e_clean_rx_irq() */ |
| 2109 | 2101 | if (next == rx_ring->next_to_process) |
| @@ -2117,20 +2109,20 @@ static void i40e_process_rx_buffs(struct i40e_ring *rx_ring, int xdp_res, · 7 unmodified lines | ||
| 2117 | 2109 | * i40e_construct_skb - Allocate skb and populate it |
| 2118 | 2110 | * @rx_ring: rx descriptor ring to transact packets on |
| 2119 | 2111 | * @xdp: xdp_buff pointing to the data |
| 2120 | − * @nr_frags: number of buffers for the packet | |
| 2121 | 2112 | * |
| 2122 | 2113 | * This function allocates an skb. It then populates it with the page |
| 2123 | 2114 | * data from the current receive descriptor, taking care to set up the |
| 2124 | 2115 | * skb correctly. |
| 2125 | 2116 | */ |
| 2126 | 2117 | static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring, |
| 2127 | − struct xdp_buff *xdp, | |
| 2128 | − u32 nr_frags) | |
| 2118 | + struct xdp_buff *xdp) | |
| 2129 | 2119 | { |
| 2130 | 2120 | unsigned int size = xdp->data_end - xdp->data; |
| 2131 | 2121 | struct i40e_rx_buffer *rx_buffer; |
| 2122 | + struct skb_shared_info *sinfo; | |
| 2132 | 2123 | unsigned int headlen; |
| 2133 | 2124 | struct sk_buff *skb; |
| 2125 | + u32 nr_frags = 0; | |
| 2134 | 2126 | |
| 2135 | 2127 | /* prefetch first cache line of first page */ |
| 2136 | 2128 | net_prefetch(xdp->data); |
| @@ -2168,6 +2160,10 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring, · 31 unmodified lines | ||
| 2168 | 2160 | memcpy(__skb_put(skb, headlen), xdp->data, |
| 2169 | 2161 | ALIGN(headlen, sizeof(long))); |
| 2170 | 2162 | |
| 2163 | + if (unlikely(xdp_buff_has_frags(xdp))) { | |
| 2164 | + sinfo = xdp_get_shared_info_from_buff(xdp); | |
| 2165 | + nr_frags = sinfo->nr_frags; | |
| 2166 | + } | |
| 2171 | 2167 | rx_buffer = i40e_rx_bi(rx_ring, rx_ring->next_to_clean); |
| 2172 | 2168 | /* update all of the pointers */ |
| 2173 | 2169 | size -= headlen; |
| @@ -2187,9 +2183,8 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring, · 13 unmodified lines | ||
| 2187 | 2183 | } |
| 2188 | 2184 | |
| 2189 | 2185 | if (unlikely(xdp_buff_has_frags(xdp))) { |
| 2190 | − struct skb_shared_info *sinfo, *skinfo = skb_shinfo(skb); | |
| 2186 | + struct skb_shared_info *skinfo = skb_shinfo(skb); | |
| 2191 | 2187 | |
| 2192 | − sinfo = xdp_get_shared_info_from_buff(xdp); | |
| 2193 | 2188 | memcpy(&skinfo->frags[skinfo->nr_frags], &sinfo->frags[0], |
| 2194 | 2189 | sizeof(skb_frag_t) * nr_frags); |
| 2195 | 2190 | |
| @@ -2212,17 +2207,17 @@ static struct sk_buff *i40e_construct_skb(struct i40e_ring *rx_ring, · 16 unmodified lines | ||
| 2212 | 2207 | * i40e_build_skb - Build skb around an existing buffer |
| 2213 | 2208 | * @rx_ring: Rx descriptor ring to transact packets on |
| 2214 | 2209 | * @xdp: xdp_buff pointing to the data |
| 2215 | − * @nr_frags: number of buffers for the packet | |
| 2216 | 2210 | * |
| 2217 | 2211 | * This function builds an skb around an existing Rx buffer, taking care |
| 2218 | 2212 | * to set up the skb correctly and avoid any memcpy overhead. |
| 2219 | 2213 | */ |
| 2220 | 2214 | static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, |
| 2221 | − struct xdp_buff *xdp, | |
| 2222 | − u32 nr_frags) | |
| 2215 | + struct xdp_buff *xdp) | |
| 2223 | 2216 | { |
| 2224 | 2217 | unsigned int metasize = xdp->data - xdp->data_meta; |
| 2218 | + struct skb_shared_info *sinfo; | |
| 2225 | 2219 | struct sk_buff *skb; |
| 2220 | + u32 nr_frags; | |
| 2226 | 2221 | |
| 2227 | 2222 | /* Prefetch first cache line of first page. If xdp->data_meta |
| 2228 | 2223 | * is unused, this points exactly as xdp->data, otherwise we |
| @@ -2231,6 +2226,11 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, · 2 unmodified lines | ||
| 2231 | 2226 | */ |
| 2232 | 2227 | net_prefetch(xdp->data_meta); |
| 2233 | 2228 | |
| 2229 | + if (unlikely(xdp_buff_has_frags(xdp))) { | |
| 2230 | + sinfo = xdp_get_shared_info_from_buff(xdp); | |
| 2231 | + nr_frags = sinfo->nr_frags; | |
| 2232 | + } | |
| 2233 | + | |
| 2234 | 2234 | /* build an skb around the page buffer */ |
| 2235 | 2235 | skb = napi_build_skb(xdp->data_hard_start, xdp->frame_sz); |
| 2236 | 2236 | if (unlikely(!skb)) |
| @@ -2243,9 +2243,6 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring, · 6 unmodified lines | ||
| 2243 | 2243 | skb_metadata_set(skb, metasize); |
| 2244 | 2244 | |
| 2245 | 2245 | if (unlikely(xdp_buff_has_frags(xdp))) { |
| 2246 | − struct skb_shared_info *sinfo; | |
| 2247 | − | |
| 2248 | − sinfo = xdp_get_shared_info_from_buff(xdp); | |
| 2249 | 2246 | xdp_update_skb_shared_info(skb, nr_frags, |
| 2250 | 2247 | sinfo->xdp_frags_size, |
| 2251 | 2248 | nr_frags * xdp->frame_sz, |
| @@ -2589,9 +2586,9 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget, · 337 unmodified lines | ||
| 2589 | 2586 | total_rx_bytes += size; |
| 2590 | 2587 | } else { |
| 2591 | 2588 | if (ring_uses_build_skb(rx_ring)) |
| 2592 | − skb = i40e_build_skb(rx_ring, xdp, nfrags); | |
| 2589 | + skb = i40e_build_skb(rx_ring, xdp); | |
| 2593 | 2590 | else |
| 2594 | − skb = i40e_construct_skb(rx_ring, xdp, nfrags); | |
| 2591 | + skb = i40e_construct_skb(rx_ring, xdp); | |
| 2595 | 2592 | |
| 2596 | 2593 | /* drop if we failed to retrieve a buffer */ |
| 2597 | 2594 | if (!skb) { |
| @@ -414,7 +414,8 @@ i40e_add_xsk_frag(struct i40e_ring *rx_ring, struct xdp_buff *first, · 413 unmodified lines | ||
| 414 | 414 | } |
| 415 | 415 | |
| 416 | 416 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, |
| 417 | − virt_to_page(xdp->data_hard_start), 0, size); | |
| 417 | + virt_to_page(xdp->data_hard_start), | |
| 418 | + XDP_PACKET_HEADROOM, size); | |
| 418 | 419 | sinfo->xdp_frags_size += size; |
| 419 | 420 | xsk_buff_add_frag(xdp); |
| 420 | 421 | |
| @@ -498,7 +499,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget) · 77 unmodified lines | ||
| 498 | 499 | xdp_res = i40e_run_xdp_zc(rx_ring, first, xdp_prog); |
| 499 | 500 | i40e_handle_xdp_result_zc(rx_ring, first, rx_desc, &rx_packets, |
| 500 | 501 | &rx_bytes, xdp_res, &failure); |
| 501 | − first->flags = 0; | |
| 502 | 502 | next_to_clean = next_to_process; |
| 503 | 503 | if (failure) |
| 504 | 504 | break; |
| @@ -547,19 +547,27 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) · 546 unmodified lines | ||
| 547 | 547 | ring->rx_buf_len = ring->vsi->rx_buf_len; |
| 548 | 548 | |
| 549 | 549 | if (ring->vsi->type == ICE_VSI_PF) { |
| 550 | − if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) | |
| 551 | − /* coverity[check_return] */ | |
| 552 | − __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, | |
| 553 | − ring->q_index, | |
| 554 | − ring->q_vector->napi.napi_id, | |
| 555 | − ring->vsi->rx_buf_len); | |
| 550 | + if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) { | |
| 551 | + err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, | |
| 552 | + ring->q_index, | |
| 553 | + ring->q_vector->napi.napi_id, | |
| 554 | + ring->rx_buf_len); | |
| 555 | + if (err) | |
| 556 | + return err; | |
| 557 | + } | |
| 556 | 558 | |
| 557 | 559 | ring->xsk_pool = ice_xsk_pool(ring); |
| 558 | 560 | if (ring->xsk_pool) { |
| 559 | − xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq); | |
| 561 | + xdp_rxq_info_unreg(&ring->xdp_rxq); | |
| 560 | 562 | |
| 561 | 563 | ring->rx_buf_len = |
| 562 | 564 | xsk_pool_get_rx_frame_size(ring->xsk_pool); |
| 565 | + err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, | |
| 566 | + ring->q_index, | |
| 567 | + ring->q_vector->napi.napi_id, | |
| 568 | + ring->rx_buf_len); | |
| 569 | + if (err) | |
| 570 | + return err; | |
| 563 | 571 | err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, |
| 564 | 572 | MEM_TYPE_XSK_BUFF_POOL, |
| 565 | 573 | NULL); |
| @@ -571,13 +579,14 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring) · 5 unmodified lines | ||
| 571 | 579 | dev_info(dev, "Registered XDP mem model MEM_TYPE_XSK_BUFF_POOL on Rx ring %d\n", |
| 572 | 580 | ring->q_index); |
| 573 | 581 | } else { |
| 574 | − if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) | |
| 575 | − /* coverity[check_return] */ | |
| 576 | − __xdp_rxq_info_reg(&ring->xdp_rxq, | |
| 577 | − ring->netdev, | |
| 578 | − ring->q_index, | |
| 579 | − ring->q_vector->napi.napi_id, | |
| 580 | − ring->vsi->rx_buf_len); | |
| 582 | + if (!xdp_rxq_info_is_reg(&ring->xdp_rxq)) { | |
| 583 | + err = __xdp_rxq_info_reg(&ring->xdp_rxq, ring->netdev, | |
| 584 | + ring->q_index, | |
| 585 | + ring->q_vector->napi.napi_id, | |
| 586 | + ring->rx_buf_len); | |
| 587 | + if (err) | |
| 588 | + return err; | |
| 589 | + } | |
| 581 | 590 | |
| 582 | 591 | err = xdp_rxq_info_reg_mem_model(&ring->xdp_rxq, |
| 583 | 592 | MEM_TYPE_PAGE_SHARED, |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #define rd64(a, reg) readq((a)->hw_addr + (reg)) |
| 25 | 25 | |
| 26 | 26 | #define ice_flush(a) rd32((a), GLGEN_STAT) |
| 27 | −#define ICE_M(m, s) ((m) << (s)) | |
| 27 | +#define ICE_M(m, s) ((m ## U) << (s)) | |
| 28 | 28 | |
| 29 | 29 | struct ice_dma_mem { |
| 30 | 30 | void *va; |
| @@ -513,11 +513,6 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring) · 512 unmodified lines | ||
| 513 | 513 | if (ice_is_xdp_ena_vsi(rx_ring->vsi)) |
| 514 | 514 | WRITE_ONCE(rx_ring->xdp_prog, rx_ring->vsi->xdp_prog); |
| 515 | 515 | |
| 516 | − if (rx_ring->vsi->type == ICE_VSI_PF && | |
| 517 | − !xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) | |
| 518 | − if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, | |
| 519 | − rx_ring->q_index, rx_ring->q_vector->napi.napi_id)) | |
| 520 | − goto err; | |
| 521 | 516 | return 0; |
| 522 | 517 | |
| 523 | 518 | err: |
| @@ -603,9 +598,7 @@ out_failure: · 79 unmodified lines | ||
| 603 | 598 | ret = ICE_XDP_CONSUMED; |
| 604 | 599 | } |
| 605 | 600 | exit: |
| 606 | − rx_buf->act = ret; | |
| 607 | − if (unlikely(xdp_buff_has_frags(xdp))) | |
| 608 | − ice_set_rx_bufs_act(xdp, rx_ring, ret); | |
| 601 | + ice_set_rx_bufs_act(xdp, rx_ring, ret); | |
| 609 | 602 | } |
| 610 | 603 | |
| 611 | 604 | /** |
| @@ -893,14 +886,17 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, · 281 unmodified lines | ||
| 893 | 886 | } |
| 894 | 887 | |
| 895 | 888 | if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) { |
| 896 | − if (unlikely(xdp_buff_has_frags(xdp))) | |
| 897 | − ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED); | |
| 889 | + ice_set_rx_bufs_act(xdp, rx_ring, ICE_XDP_CONSUMED); | |
| 898 | 890 | return -ENOMEM; |
| 899 | 891 | } |
| 900 | 892 | |
| 901 | 893 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, |
| 902 | 894 | rx_buf->page_offset, size); |
| 903 | 895 | sinfo->xdp_frags_size += size; |
| 896 | + /* remember frag count before XDP prog execution; bpf_xdp_adjust_tail() | |
| 897 | + * can pop off frags but driver has to handle it on its own | |
| 898 | + */ | |
| 899 | + rx_ring->nr_frags = sinfo->nr_frags; | |
| 904 | 900 | |
| 905 | 901 | if (page_is_pfmemalloc(rx_buf->page)) |
| 906 | 902 | xdp_buff_set_frag_pfmemalloc(xdp); |
| @@ -1251,6 +1247,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) · 344 unmodified lines | ||
| 1251 | 1247 | |
| 1252 | 1248 | xdp->data = NULL; |
| 1253 | 1249 | rx_ring->first_desc = ntc; |
| 1250 | + rx_ring->nr_frags = 0; | |
| 1254 | 1251 | continue; |
| 1255 | 1252 | construct_skb: |
| 1256 | 1253 | if (likely(ice_ring_uses_build_skb(rx_ring))) |
| @@ -1266,10 +1263,12 @@ construct_skb: · 9 unmodified lines | ||
| 1266 | 1263 | ICE_XDP_CONSUMED); |
| 1267 | 1264 | xdp->data = NULL; |
| 1268 | 1265 | rx_ring->first_desc = ntc; |
| 1266 | + rx_ring->nr_frags = 0; | |
| 1269 | 1267 | break; |
| 1270 | 1268 | } |
| 1271 | 1269 | xdp->data = NULL; |
| 1272 | 1270 | rx_ring->first_desc = ntc; |
| 1271 | + rx_ring->nr_frags = 0; | |
| 1273 | 1272 | |
| 1274 | 1273 | stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_RXE_S); |
| 1275 | 1274 | if (unlikely(ice_test_staterr(rx_desc->wb.status_error0, |
| @@ -358,6 +358,7 @@ struct ice_rx_ring { · 357 unmodified lines | ||
| 358 | 358 | struct ice_tx_ring *xdp_ring; |
| 359 | 359 | struct ice_rx_ring *next; /* pointer to next ring in q_vector */ |
| 360 | 360 | struct xsk_buff_pool *xsk_pool; |
| 361 | + u32 nr_frags; | |
| 361 | 362 | dma_addr_t dma; /* physical address of ring */ |
| 362 | 363 | u16 rx_buf_len; |
| 363 | 364 | u8 dcb_tc; /* Traffic class of ring */ |
| @@ -12,26 +12,39 @@ · 11 unmodified lines | ||
| 12 | 12 | * act: action to store onto Rx buffers related to XDP buffer parts |
| 13 | 13 | * |
| 14 | 14 | * Set action that should be taken before putting Rx buffer from first frag |
| 15 | − * to one before last. Last one is handled by caller of this function as it | |
| 16 | − * is the EOP frag that is currently being processed. This function is | |
| 17 | − * supposed to be called only when XDP buffer contains frags. | |
| 15 | + * to the last. | |
| 18 | 16 | */ |
| 19 | 17 | static inline void |
| 20 | 18 | ice_set_rx_bufs_act(struct xdp_buff *xdp, const struct ice_rx_ring *rx_ring, |
| 21 | 19 | const unsigned int act) |
| 22 | 20 | { |
| 23 | − const struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); | |
| 24 | − u32 first = rx_ring->first_desc; | |
| 25 | − u32 nr_frags = sinfo->nr_frags; | |
| 21 | + u32 sinfo_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags; | |
| 22 | + u32 nr_frags = rx_ring->nr_frags + 1; | |
| 23 | + u32 idx = rx_ring->first_desc; | |
| 26 | 24 | u32 cnt = rx_ring->count; |
| 27 | 25 | struct ice_rx_buf *buf; |
| 28 | 26 | |
| 29 | 27 | for (int i = 0; i < nr_frags; i++) { |
| 30 | − buf = &rx_ring->rx_buf[first]; | |
| 28 | + buf = &rx_ring->rx_buf[idx]; | |
| 31 | 29 | buf->act = act; |
| 32 | 30 | |
| 33 | − if (++first == cnt) | |
| 34 | − first = 0; | |
| 31 | + if (++idx == cnt) | |
| 32 | + idx = 0; | |
| 33 | + } | |
| 34 | + | |
| 35 | + /* adjust pagecnt_bias on frags freed by XDP prog */ | |
| 36 | + if (sinfo_frags < rx_ring->nr_frags && act == ICE_XDP_CONSUMED) { | |
| 37 | + u32 delta = rx_ring->nr_frags - sinfo_frags; | |
| 38 | + | |
| 39 | + while (delta) { | |
| 40 | + if (idx == 0) | |
| 41 | + idx = cnt - 1; | |
| 42 | + else | |
| 43 | + idx--; | |
| 44 | + buf = &rx_ring->rx_buf[idx]; | |
| 45 | + buf->pagecnt_bias--; | |
| 46 | + delta--; | |
| 47 | + } | |
| 35 | 48 | } |
| 36 | 49 | } |
| 37 | 50 | |
| @@ -1072,7 +1072,7 @@ struct ice_aq_get_set_rss_lut_params { · 1071 unmodified lines | ||
| 1072 | 1072 | #define ICE_OROM_VER_BUILD_SHIFT 8 |
| 1073 | 1073 | #define ICE_OROM_VER_BUILD_MASK (0xffff << ICE_OROM_VER_BUILD_SHIFT) |
| 1074 | 1074 | #define ICE_OROM_VER_SHIFT 24 |
| 1075 | −#define ICE_OROM_VER_MASK (0xff << ICE_OROM_VER_SHIFT) | |
| 1075 | +#define ICE_OROM_VER_MASK (0xffU << ICE_OROM_VER_SHIFT) | |
| 1076 | 1076 | #define ICE_SR_PFA_PTR 0x40 |
| 1077 | 1077 | #define ICE_SR_1ST_NVM_BANK_PTR 0x42 |
| 1078 | 1078 | #define ICE_SR_NVM_BANK_SIZE 0x43 |
| @@ -825,7 +825,8 @@ ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first, · 824 unmodified lines | ||
| 825 | 825 | } |
| 826 | 826 | |
| 827 | 827 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, |
| 828 | − virt_to_page(xdp->data_hard_start), 0, size); | |
| 828 | + virt_to_page(xdp->data_hard_start), | |
| 829 | + XDP_PACKET_HEADROOM, size); | |
| 829 | 830 | sinfo->xdp_frags_size += size; |
| 830 | 831 | xsk_buff_add_frag(xdp); |
| 831 | 832 | |
| @@ -895,7 +896,6 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget) · 63 unmodified lines | ||
| 895 | 896 | |
| 896 | 897 | if (!first) { |
| 897 | 898 | first = xdp; |
| 898 | − xdp_buff_clear_frags_flag(first); | |
| 899 | 899 | } else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) { |
| 900 | 900 | break; |
| 901 | 901 | } |
| @@ -783,6 +783,8 @@ static int idpf_cfg_netdev(struct idpf_vport *vport) · 782 unmodified lines | ||
| 783 | 783 | /* setup watchdog timeout value to be 5 second */ |
| 784 | 784 | netdev->watchdog_timeo = 5 * HZ; |
| 785 | 785 | |
| 786 | + netdev->dev_port = idx; | |
| 787 | + | |
| 786 | 788 | /* configure default MTU size */ |
| 787 | 789 | netdev->min_mtu = ETH_MIN_MTU; |
| 788 | 790 | netdev->max_mtu = vport->max_mtu; |
| @@ -978,7 +978,7 @@ struct virtchnl2_ptype { · 977 unmodified lines | ||
| 978 | 978 | u8 proto_id_count; |
| 979 | 979 | __le16 pad; |
| 980 | 980 | __le16 proto_id[]; |
| 981 | −}; | |
| 981 | +} __packed __aligned(2); | |
| 982 | 982 | VIRTCHNL2_CHECK_STRUCT_LEN(6, virtchnl2_ptype); |
| 983 | 983 | |
| 984 | 984 | /** |
| @@ -716,7 +716,8 @@ static s32 ixgbe_read_iosf_sb_reg_x550(struct ixgbe_hw *hw, u32 reg_addr, · 715 unmodified lines | ||
| 716 | 716 | if ((command & IXGBE_SB_IOSF_CTRL_RESP_STAT_MASK) != 0) { |
| 717 | 717 | error = FIELD_GET(IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK, command); |
| 718 | 718 | hw_dbg(hw, "Failed to read, error %x\n", error); |
| 719 | − return -EIO; | |
| 719 | + ret = -EIO; | |
| 720 | + goto out; | |
| 720 | 721 | } |
| 721 | 722 | |
| 722 | 723 | if (!ret) |
| @@ -318,4 +318,5 @@ static struct platform_driver liteeth_driver = { · 317 unmodified lines | ||
| 318 | 318 | module_platform_driver(liteeth_driver); |
| 319 | 319 | |
| 320 | 320 | MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>"); |
| 321 | +MODULE_DESCRIPTION("LiteX Liteeth Ethernet driver"); | |
| 321 | 322 | MODULE_LICENSE("GPL"); |
| @@ -614,12 +614,38 @@ static void mvpp23_bm_set_8pool_mode(struct mvpp2 *priv) · 613 unmodified lines | ||
| 614 | 614 | mvpp2_write(priv, MVPP22_BM_POOL_BASE_ADDR_HIGH_REG, val); |
| 615 | 615 | } |
| 616 | 616 | |
| 617 | +/* Cleanup pool before actual initialization in the OS */ | |
| 618 | +static void mvpp2_bm_pool_cleanup(struct mvpp2 *priv, int pool_id) | |
| 619 | +{ | |
| 620 | + unsigned int thread = mvpp2_cpu_to_thread(priv, get_cpu()); | |
| 621 | + u32 val; | |
| 622 | + int i; | |
| 623 | + | |
| 624 | + /* Drain the BM from all possible residues left by firmware */ | |
| 625 | + for (i = 0; i < MVPP2_BM_POOL_SIZE_MAX; i++) | |
| 626 | + mvpp2_thread_read(priv, thread, MVPP2_BM_PHY_ALLOC_REG(pool_id)); | |
| 627 | + | |
| 628 | + put_cpu(); | |
| 629 | + | |
| 630 | + /* Stop the BM pool */ | |
| 631 | + val = mvpp2_read(priv, MVPP2_BM_POOL_CTRL_REG(pool_id)); | |
| 632 | + val |= MVPP2_BM_STOP_MASK; | |
| 633 | + mvpp2_write(priv, MVPP2_BM_POOL_CTRL_REG(pool_id), val); | |
| 634 | +} | |
| 635 | + | |
| 617 | 636 | static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv) |
| 618 | 637 | { |
| 619 | 638 | enum dma_data_direction dma_dir = DMA_FROM_DEVICE; |
| 620 | 639 | int i, err, poolnum = MVPP2_BM_POOLS_NUM; |
| 621 | 640 | struct mvpp2_port *port; |
| 622 | 641 | |
| 642 | + if (priv->percpu_pools) | |
| 643 | + poolnum = mvpp2_get_nrxqs(priv) * 2; | |
| 644 | + | |
| 645 | + /* Clean up the pool state in case it contains stale state */ | |
| 646 | + for (i = 0; i < poolnum; i++) | |
| 647 | + mvpp2_bm_pool_cleanup(priv, i); | |
| 648 | + | |
| 623 | 649 | if (priv->percpu_pools) { |
| 624 | 650 | for (i = 0; i < priv->port_count; i++) { |
| 625 | 651 | port = priv->port_list[i]; |
| @@ -629,7 +655,6 @@ static int mvpp2_bm_init(struct device *dev, struct mvpp2 *priv) · 3 unmodified lines | ||
| 629 | 655 | } |
| 630 | 656 | } |
| 631 | 657 | |
| 632 | − poolnum = mvpp2_get_nrxqs(priv) * 2; | |
| 633 | 658 | for (i = 0; i < poolnum; i++) { |
| 634 | 659 | /* the pool in use */ |
| 635 | 660 | int pn = i / (poolnum / 2); |
| @@ -413,4 +413,5 @@ const char *otx2_mbox_id2name(u16 id) · 412 unmodified lines | ||
| 413 | 413 | EXPORT_SYMBOL(otx2_mbox_id2name); |
| 414 | 414 | |
| 415 | 415 | MODULE_AUTHOR("Marvell."); |
| 416 | +MODULE_DESCRIPTION("Marvell RVU NIC Mbox helpers"); | |
| 416 | 417 | MODULE_LICENSE("GPL v2"); |
| @@ -1850,8 +1850,8 @@ void npc_mcam_rsrcs_deinit(struct rvu *rvu) · 1849 unmodified lines | ||
| 1850 | 1850 | { |
| 1851 | 1851 | struct npc_mcam *mcam = &rvu->hw->mcam; |
| 1852 | 1852 | |
| 1853 | − kfree(mcam->bmap); | |
| 1854 | − kfree(mcam->bmap_reverse); | |
| 1853 | + bitmap_free(mcam->bmap); | |
| 1854 | + bitmap_free(mcam->bmap_reverse); | |
| 1855 | 1855 | kfree(mcam->entry2pfvf_map); |
| 1856 | 1856 | kfree(mcam->cntr2pfvf_map); |
| 1857 | 1857 | kfree(mcam->entry2cntr_map); |
| @@ -1904,21 +1904,20 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr) · 46 unmodified lines | ||
| 1904 | 1904 | mcam->pf_offset = mcam->nixlf_offset + nixlf_count; |
| 1905 | 1905 | |
| 1906 | 1906 | /* Allocate bitmaps for managing MCAM entries */ |
| 1907 | − mcam->bmap = kmalloc_array(BITS_TO_LONGS(mcam->bmap_entries), | |
| 1908 | − sizeof(long), GFP_KERNEL); | |
| 1907 | + mcam->bmap = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL); | |
| 1909 | 1908 | if (!mcam->bmap) |
| 1910 | 1909 | return -ENOMEM; |
| 1911 | 1910 | |
| 1912 | − mcam->bmap_reverse = kmalloc_array(BITS_TO_LONGS(mcam->bmap_entries), | |
| 1913 | − sizeof(long), GFP_KERNEL); | |
| 1911 | + mcam->bmap_reverse = bitmap_zalloc(mcam->bmap_entries, GFP_KERNEL); | |
| 1914 | 1912 | if (!mcam->bmap_reverse) |
| 1915 | 1913 | goto free_bmap; |
| 1916 | 1914 | |
| 1917 | 1915 | mcam->bmap_fcnt = mcam->bmap_entries; |
| 1918 | 1916 | |
| 1919 | 1917 | /* Alloc memory for saving entry to RVU PFFUNC allocation mapping */ |
| 1920 | − mcam->entry2pfvf_map = kmalloc_array(mcam->bmap_entries, | |
| 1921 | − sizeof(u16), GFP_KERNEL); | |
| 1918 | + mcam->entry2pfvf_map = kcalloc(mcam->bmap_entries, sizeof(u16), | |
| 1919 | + GFP_KERNEL); | |
| 1920 | + | |
| 1922 | 1921 | if (!mcam->entry2pfvf_map) |
| 1923 | 1922 | goto free_bmap_reverse; |
| 1924 | 1923 | |
| @@ -1941,21 +1940,21 @@ int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr) · 16 unmodified lines | ||
| 1941 | 1940 | if (err) |
| 1942 | 1941 | goto free_entry_map; |
| 1943 | 1942 | |
| 1944 | − mcam->cntr2pfvf_map = kmalloc_array(mcam->counters.max, | |
| 1945 | − sizeof(u16), GFP_KERNEL); | |
| 1943 | + mcam->cntr2pfvf_map = kcalloc(mcam->counters.max, sizeof(u16), | |
| 1944 | + GFP_KERNEL); | |
| 1946 | 1945 | if (!mcam->cntr2pfvf_map) |
| 1947 | 1946 | goto free_cntr_bmap; |
| 1948 | 1947 | |
| 1949 | 1948 | /* Alloc memory for MCAM entry to counter mapping and for tracking |
| 1950 | 1949 | * counter's reference count. |
| 1951 | 1950 | */ |
| 1952 | − mcam->entry2cntr_map = kmalloc_array(mcam->bmap_entries, | |
| 1953 | − sizeof(u16), GFP_KERNEL); | |
| 1951 | + mcam->entry2cntr_map = kcalloc(mcam->bmap_entries, sizeof(u16), | |
| 1952 | + GFP_KERNEL); | |
| 1954 | 1953 | if (!mcam->entry2cntr_map) |
| 1955 | 1954 | goto free_cntr_map; |
| 1956 | 1955 | |
| 1957 | − mcam->cntr_refcnt = kmalloc_array(mcam->counters.max, | |
| 1958 | − sizeof(u16), GFP_KERNEL); | |
| 1956 | + mcam->cntr_refcnt = kcalloc(mcam->counters.max, sizeof(u16), | |
| 1957 | + GFP_KERNEL); | |
| 1959 | 1958 | if (!mcam->cntr_refcnt) |
| 1960 | 1959 | goto free_entry_cntr_map; |
| 1961 | 1960 | |
| @@ -1988,9 +1987,9 @@ free_cntr_bmap: · 26 unmodified lines | ||
| 1988 | 1987 | free_entry_map: |
| 1989 | 1988 | kfree(mcam->entry2pfvf_map); |
| 1990 | 1989 | free_bmap_reverse: |
| 1991 | − kfree(mcam->bmap_reverse); | |
| 1990 | + bitmap_free(mcam->bmap_reverse); | |
| 1992 | 1991 | free_bmap: |
| 1993 | − kfree(mcam->bmap); | |
| 1992 | + bitmap_free(mcam->bmap); | |
| 1994 | 1993 | |
| 1995 | 1994 | return -ENOMEM; |
| 1996 | 1995 | } |
| @@ -951,8 +951,11 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) · 950 unmodified lines | ||
| 951 | 951 | if (pfvf->ptp && qidx < pfvf->hw.tx_queues) { |
| 952 | 952 | err = qmem_alloc(pfvf->dev, &sq->timestamps, qset->sqe_cnt, |
| 953 | 953 | sizeof(*sq->timestamps)); |
| 954 | − if (err) | |
| 954 | + if (err) { | |
| 955 | + kfree(sq->sg); | |
| 956 | + sq->sg = NULL; | |
| 955 | 957 | return err; |
| 958 | + } | |
| 956 | 959 | } |
| 957 | 960 | |
| 958 | 961 | sq->head = 0; |
| @@ -968,7 +971,14 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura) · 9 unmodified lines | ||
| 968 | 971 | sq->stats.bytes = 0; |
| 969 | 972 | sq->stats.pkts = 0; |
| 970 | 973 | |
| 971 | − return pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura); | |
| 974 | + err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, sqb_aura); | |
| 975 | + if (err) { | |
| 976 | + kfree(sq->sg); | |
| 977 | + sq->sg = NULL; | |
| 978 | + return err; | |
| 979 | + } | |
| 980 | + | |
| 981 | + return 0; | |
| 972 | 982 | |
| 973 | 983 | } |
| 974 | 984 | |
| @@ -314,7 +314,6 @@ static int otx2_set_channels(struct net_device *dev, · 313 unmodified lines | ||
| 314 | 314 | pfvf->hw.tx_queues = channel->tx_count; |
| 315 | 315 | if (pfvf->xdp_prog) |
| 316 | 316 | pfvf->hw.xdp_queues = channel->rx_count; |
| 317 | − pfvf->hw.non_qos_queues = pfvf->hw.tx_queues + pfvf->hw.xdp_queues; | |
| 318 | 317 | |
| 319 | 318 | if (if_up) |
| 320 | 319 | err = dev->netdev_ops->ndo_open(dev); |
| @@ -1744,6 +1744,7 @@ int otx2_open(struct net_device *netdev) · 1743 unmodified lines | ||
| 1744 | 1744 | /* RQ and SQs are mapped to different CQs, |
| 1745 | 1745 | * so find out max CQ IRQs (i.e CINTs) needed. |
| 1746 | 1746 | */ |
| 1747 | + pf->hw.non_qos_queues = pf->hw.tx_queues + pf->hw.xdp_queues; | |
| 1747 | 1748 | pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues, |
| 1748 | 1749 | pf->hw.tc_tx_queues); |
| 1749 | 1750 | |
| @@ -2643,8 +2644,6 @@ static int otx2_xdp_setup(struct otx2_nic *pf, struct bpf_prog *prog) · 893 unmodified lines | ||
| 2643 | 2644 | xdp_features_clear_redirect_target(dev); |
| 2644 | 2645 | } |
| 2645 | 2646 | |
| 2646 | − pf->hw.non_qos_queues += pf->hw.xdp_queues; | |
| 2647 | − | |
| 2648 | 2647 | if (if_up) |
| 2649 | 2648 | otx2_open(pf->netdev); |
| 2650 | 2649 | |
| @@ -1403,7 +1403,7 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf, · 1402 unmodified lines | ||
| 1403 | 1403 | struct otx2_cq_queue *cq, |
| 1404 | 1404 | bool *need_xdp_flush) |
| 1405 | 1405 | { |
| 1406 | − unsigned char *hard_start, *data; | |
| 1406 | + unsigned char *hard_start; | |
| 1407 | 1407 | int qidx = cq->cq_idx; |
| 1408 | 1408 | struct xdp_buff xdp; |
| 1409 | 1409 | struct page *page; |
| @@ -1417,9 +1417,8 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf, · 7 unmodified lines | ||
| 1417 | 1417 | |
| 1418 | 1418 | xdp_init_buff(&xdp, pfvf->rbsize, &cq->xdp_rxq); |
| 1419 | 1419 | |
| 1420 | − data = (unsigned char *)phys_to_virt(pa); | |
| 1421 | − hard_start = page_address(page); | |
| 1422 | − xdp_prepare_buff(&xdp, hard_start, data - hard_start, | |
| 1420 | + hard_start = (unsigned char *)phys_to_virt(pa); | |
| 1421 | + xdp_prepare_buff(&xdp, hard_start, OTX2_HEAD_ROOM, | |
| 1423 | 1422 | cqe->sg.seg_size, false); |
| 1424 | 1423 | |
| 1425 | 1424 | act = bpf_prog_run_xdp(prog, &xdp); |
| @@ -4761,7 +4761,10 @@ static int mtk_probe(struct platform_device *pdev) · 4760 unmodified lines | ||
| 4761 | 4761 | } |
| 4762 | 4762 | |
| 4763 | 4763 | if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { |
| 4764 | − err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36)); | |
| 4764 | + err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36)); | |
| 4765 | + if (!err) | |
| 4766 | + err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); | |
| 4767 | + | |
| 4765 | 4768 | if (err) { |
| 4766 | 4769 | dev_err(&pdev->dev, "Wrong DMA config\n"); |
| 4767 | 4770 | return -EINVAL; |
| @@ -1923,6 +1923,7 @@ static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, · 1922 unmodified lines | ||
| 1923 | 1923 | { |
| 1924 | 1924 | const char *namep = mlx5_command_str(opcode); |
| 1925 | 1925 | struct mlx5_cmd_stats *stats; |
| 1926 | + unsigned long flags; | |
| 1926 | 1927 | |
| 1927 | 1928 | if (!err || !(strcmp(namep, "unknown command opcode"))) |
| 1928 | 1929 | return; |
| @@ -1930,7 +1931,7 @@ static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, · 1 unmodified line | ||
| 1930 | 1931 | stats = xa_load(&dev->cmd.stats, opcode); |
| 1931 | 1932 | if (!stats) |
| 1932 | 1933 | return; |
| 1933 | − spin_lock_irq(&stats->lock); | |
| 1934 | + spin_lock_irqsave(&stats->lock, flags); | |
| 1934 | 1935 | stats->failed++; |
| 1935 | 1936 | if (err < 0) |
| 1936 | 1937 | stats->last_failed_errno = -err; |
| @@ -1939,7 +1940,7 @@ static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, · 2 unmodified lines | ||
| 1939 | 1940 | stats->last_failed_mbox_status = status; |
| 1940 | 1941 | stats->last_failed_syndrome = syndrome; |
| 1941 | 1942 | } |
| 1942 | − spin_unlock_irq(&stats->lock); | |
| 1943 | + spin_unlock_irqrestore(&stats->lock, flags); | |
| 1943 | 1944 | } |
| 1944 | 1945 | |
| 1945 | 1946 | /* preserve -EREMOTEIO for outbox.status != OK, otherwise return err as is */ |
| @@ -1124,7 +1124,7 @@ static inline bool mlx5_tx_swp_supported(struct mlx5_core_dev *mdev) · 1123 unmodified lines | ||
| 1124 | 1124 | extern const struct ethtool_ops mlx5e_ethtool_ops; |
| 1125 | 1125 | |
| 1126 | 1126 | int mlx5e_create_mkey(struct mlx5_core_dev *mdev, u32 pdn, u32 *mkey); |
| 1127 | −int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev); | |
| 1127 | +int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises); | |
| 1128 | 1128 | void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev); |
| 1129 | 1129 | int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb, |
| 1130 | 1130 | bool enable_mc_lb); |
| @@ -436,6 +436,7 @@ static int fs_any_create_groups(struct mlx5e_flow_table *ft) · 435 unmodified lines | ||
| 436 | 436 | in = kvzalloc(inlen, GFP_KERNEL); |
| 437 | 437 | if (!in || !ft->g) { |
| 438 | 438 | kfree(ft->g); |
| 439 | + ft->g = NULL; | |
| 439 | 440 | kvfree(in); |
| 440 | 441 | return -ENOMEM; |
| 441 | 442 | } |
| @@ -1064,8 +1064,8 @@ void mlx5e_build_sq_param(struct mlx5_core_dev *mdev, · 1063 unmodified lines | ||
| 1064 | 1064 | void *wq = MLX5_ADDR_OF(sqc, sqc, wq); |
| 1065 | 1065 | bool allow_swp; |
| 1066 | 1066 | |
| 1067 | − allow_swp = | |
| 1068 | − mlx5_geneve_tx_allowed(mdev) || !!mlx5_ipsec_device_caps(mdev); | |
| 1067 | + allow_swp = mlx5_geneve_tx_allowed(mdev) || | |
| 1068 | + (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_CRYPTO); | |
| 1069 | 1069 | mlx5e_build_sq_param_common(mdev, param); |
| 1070 | 1070 | MLX5_SET(wq, wq, log_wq_sz, params->log_sq_size); |
| 1071 | 1071 | MLX5_SET(sqc, sqc, allow_swp, allow_swp); |
| @@ -213,7 +213,7 @@ static void mlx5e_ptp_handle_ts_cqe(struct mlx5e_ptpsq *ptpsq, · 212 unmodified lines | ||
| 213 | 213 | mlx5e_ptpsq_mark_ts_cqes_undelivered(ptpsq, hwtstamp); |
| 214 | 214 | out: |
| 215 | 215 | napi_consume_skb(skb, budget); |
| 216 | − md_buff[*md_buff_sz++] = metadata_id; | |
| 216 | + md_buff[(*md_buff_sz)++] = metadata_id; | |
| 217 | 217 | if (unlikely(mlx5e_ptp_metadata_map_unhealthy(&ptpsq->metadata_map)) && |
| 218 | 218 | !test_and_set_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) |
| 219 | 219 | queue_work(ptpsq->txqsq.priv->wq, &ptpsq->report_unhealthy_work); |
| @@ -336,12 +336,17 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, · 335 unmodified lines | ||
| 336 | 336 | /* iv len */ |
| 337 | 337 | aes_gcm->icv_len = x->aead->alg_icv_len; |
| 338 | 338 | |
| 339 | + attrs->dir = x->xso.dir; | |
| 340 | + | |
| 339 | 341 | /* esn */ |
| 340 | 342 | if (x->props.flags & XFRM_STATE_ESN) { |
| 341 | 343 | attrs->replay_esn.trigger = true; |
| 342 | 344 | attrs->replay_esn.esn = sa_entry->esn_state.esn; |
| 343 | 345 | attrs->replay_esn.esn_msb = sa_entry->esn_state.esn_msb; |
| 344 | 346 | attrs->replay_esn.overlap = sa_entry->esn_state.overlap; |
| 347 | + if (attrs->dir == XFRM_DEV_OFFLOAD_OUT) | |
| 348 | + goto skip_replay_window; | |
| 349 | + | |
| 345 | 350 | switch (x->replay_esn->replay_window) { |
| 346 | 351 | case 32: |
| 347 | 352 | attrs->replay_esn.replay_window = |
| @@ -365,7 +370,7 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, · 17 unmodified lines | ||
| 365 | 370 | } |
| 366 | 371 | } |
| 367 | 372 | |
| 368 | − attrs->dir = x->xso.dir; | |
| 373 | +skip_replay_window: | |
| 369 | 374 | /* spi */ |
| 370 | 375 | attrs->spi = be32_to_cpu(x->id.spi); |
| 371 | 376 | |
| @@ -501,7 +506,8 @@ static int mlx5e_xfrm_validate_state(struct mlx5_core_dev *mdev, · 129 unmodified lines | ||
| 501 | 506 | return -EINVAL; |
| 502 | 507 | } |
| 503 | 508 | |
| 504 | − if (x->replay_esn && x->replay_esn->replay_window != 32 && | |
| 509 | + if (x->replay_esn && x->xso.dir == XFRM_DEV_OFFLOAD_IN && | |
| 510 | + x->replay_esn->replay_window != 32 && | |
| 505 | 511 | x->replay_esn->replay_window != 64 && |
| 506 | 512 | x->replay_esn->replay_window != 128 && |
| 507 | 513 | x->replay_esn->replay_window != 256) { |
| @@ -254,11 +254,13 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft, · 253 unmodified lines | ||
| 254 | 254 | |
| 255 | 255 | ft->g = kcalloc(MLX5E_ARFS_NUM_GROUPS, |
| 256 | 256 | sizeof(*ft->g), GFP_KERNEL); |
| 257 | − in = kvzalloc(inlen, GFP_KERNEL); | |
| 258 | − if (!in || !ft->g) { | |
| 259 | − kfree(ft->g); | |
| 260 | − kvfree(in); | |
| 257 | + if (!ft->g) | |
| 261 | 258 | return -ENOMEM; |
| 259 | + | |
| 260 | + in = kvzalloc(inlen, GFP_KERNEL); | |
| 261 | + if (!in) { | |
| 262 | + err = -ENOMEM; | |
| 263 | + goto err_free_g; | |
| 262 | 264 | } |
| 263 | 265 | |
| 264 | 266 | mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); |
| @@ -278,7 +280,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft, · 13 unmodified lines | ||
| 278 | 280 | break; |
| 279 | 281 | default: |
| 280 | 282 | err = -EINVAL; |
| 281 | − goto out; | |
| 283 | + goto err_free_in; | |
| 282 | 284 | } |
| 283 | 285 | |
| 284 | 286 | switch (type) { |
| @@ -300,7 +302,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft, · 15 unmodified lines | ||
| 300 | 302 | break; |
| 301 | 303 | default: |
| 302 | 304 | err = -EINVAL; |
| 303 | − goto out; | |
| 305 | + goto err_free_in; | |
| 304 | 306 | } |
| 305 | 307 | |
| 306 | 308 | MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); |
| @@ -309,7 +311,7 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft, · 2 unmodified lines | ||
| 309 | 311 | MLX5_SET_CFG(in, end_flow_index, ix - 1); |
| 310 | 312 | ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); |
| 311 | 313 | if (IS_ERR(ft->g[ft->num_groups])) |
| 312 | − goto err; | |
| 314 | + goto err_clean_group; | |
| 313 | 315 | ft->num_groups++; |
| 314 | 316 | |
| 315 | 317 | memset(in, 0, inlen); |
| @@ -318,18 +320,20 @@ static int arfs_create_groups(struct mlx5e_flow_table *ft, · 2 unmodified lines | ||
| 318 | 320 | MLX5_SET_CFG(in, end_flow_index, ix - 1); |
| 319 | 321 | ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in); |
| 320 | 322 | if (IS_ERR(ft->g[ft->num_groups])) |
| 321 | − goto err; | |
| 323 | + goto err_clean_group; | |
| 322 | 324 | ft->num_groups++; |
| 323 | 325 | |
| 324 | 326 | kvfree(in); |
| 325 | 327 | return 0; |
| 326 | 328 | |
| 327 | −err: | |
| 329 | +err_clean_group: | |
| 328 | 330 | err = PTR_ERR(ft->g[ft->num_groups]); |
| 329 | 331 | ft->g[ft->num_groups] = NULL; |
| 330 | −out: | |
| 332 | +err_free_in: | |
| 331 | 333 | kvfree(in); |
| 332 | − | |
| 334 | +err_free_g: | |
| 335 | + kfree(ft->g); | |
| 336 | + ft->g = NULL; | |
| 333 | 337 | return err; |
| 334 | 338 | } |
| 335 | 339 | |
| @@ -95,7 +95,7 @@ static void mlx5e_destroy_tises(struct mlx5_core_dev *mdev, u32 tisn[MLX5_MAX_PO · 94 unmodified lines | ||
| 95 | 95 | { |
| 96 | 96 | int tc, i; |
| 97 | 97 | |
| 98 | − for (i = 0; i < MLX5_MAX_PORTS; i++) | |
| 98 | + for (i = 0; i < mlx5e_get_num_lag_ports(mdev); i++) | |
| 99 | 99 | for (tc = 0; tc < MLX5_MAX_NUM_TC; tc++) |
| 100 | 100 | mlx5e_destroy_tis(mdev, tisn[i][tc]); |
| 101 | 101 | } |
| @@ -110,7 +110,7 @@ static int mlx5e_create_tises(struct mlx5_core_dev *mdev, u32 tisn[MLX5_MAX_PORT · 8 unmodified lines | ||
| 110 | 110 | int tc, i; |
| 111 | 111 | int err; |
| 112 | 112 | |
| 113 | − for (i = 0; i < MLX5_MAX_PORTS; i++) { | |
| 113 | + for (i = 0; i < mlx5e_get_num_lag_ports(mdev); i++) { | |
| 114 | 114 | for (tc = 0; tc < MLX5_MAX_NUM_TC; tc++) { |
| 115 | 115 | u32 in[MLX5_ST_SZ_DW(create_tis_in)] = {}; |
| 116 | 116 | void *tisc; |
| @@ -140,7 +140,7 @@ err_close_tises: · 23 unmodified lines | ||
| 140 | 140 | return err; |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | −int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) | |
| 143 | +int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev, bool create_tises) | |
| 144 | 144 | { |
| 145 | 145 | struct mlx5e_hw_objs *res = &mdev->mlx5e_res.hw_objs; |
| 146 | 146 | int err; |
| @@ -169,11 +169,15 @@ int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev) · 22 unmodified lines | ||
| 169 | 169 | goto err_destroy_mkey; |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | − err = mlx5e_create_tises(mdev, res->tisn); | |
| 173 | − if (err) { | |
| 174 | − mlx5_core_err(mdev, "alloc tises failed, %d\n", err); | |
| 175 | − goto err_destroy_bfreg; | |
| 172 | + if (create_tises) { | |
| 173 | + err = mlx5e_create_tises(mdev, res->tisn); | |
| 174 | + if (err) { | |
| 175 | + mlx5_core_err(mdev, "alloc tises failed, %d\n", err); | |
| 176 | + goto err_destroy_bfreg; | |
| 177 | + } | |
| 178 | + res->tisn_valid = true; | |
| 176 | 179 | } |
| 180 | + | |
| 177 | 181 | INIT_LIST_HEAD(&res->td.tirs_list); |
| 178 | 182 | mutex_init(&res->td.list_lock); |
| 179 | 183 | |
| @@ -203,7 +207,8 @@ void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev) · 23 unmodified lines | ||
| 203 | 207 | |
| 204 | 208 | mlx5_crypto_dek_cleanup(mdev->mlx5e_res.dek_priv); |
| 205 | 209 | mdev->mlx5e_res.dek_priv = NULL; |
| 206 | − mlx5e_destroy_tises(mdev, res->tisn); | |
| 210 | + if (res->tisn_valid) | |
| 211 | + mlx5e_destroy_tises(mdev, res->tisn); | |
| 207 | 212 | mlx5_free_bfreg(mdev, &res->bfreg); |
| 208 | 213 | mlx5_core_destroy_mkey(mdev, res->mkey); |
| 209 | 214 | mlx5_core_dealloc_transport_domain(mdev, res->td.tdn); |
| @@ -5992,7 +5992,7 @@ static int mlx5e_resume(struct auxiliary_device *adev) · 5991 unmodified lines | ||
| 5992 | 5992 | if (netif_device_present(netdev)) |
| 5993 | 5993 | return 0; |
| 5994 | 5994 | |
| 5995 | − err = mlx5e_create_mdev_resources(mdev); | |
| 5995 | + err = mlx5e_create_mdev_resources(mdev, true); | |
| 5996 | 5996 | if (err) |
| 5997 | 5997 | return err; |
| 5998 | 5998 | |
| @@ -761,7 +761,7 @@ static int mlx5e_hairpin_create_indirect_rqt(struct mlx5e_hairpin *hp) · 760 unmodified lines | ||
| 761 | 761 | |
| 762 | 762 | err = mlx5e_rss_params_indir_init(&indir, mdev, |
| 763 | 763 | mlx5e_rqt_size(mdev, hp->num_channels), |
| 764 | − mlx5e_rqt_size(mdev, priv->max_nch)); | |
| 764 | + mlx5e_rqt_size(mdev, hp->num_channels)); | |
| 765 | 765 | if (err) |
| 766 | 766 | return err; |
| 767 | 767 | |
| @@ -2014,9 +2014,10 @@ static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow, · 1246 unmodified lines | ||
| 2014 | 2014 | list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) { |
| 2015 | 2015 | if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev)) |
| 2016 | 2016 | continue; |
| 2017 | + | |
| 2018 | + list_del(&peer_flow->peer_flows); | |
| 2017 | 2019 | if (refcount_dec_and_test(&peer_flow->refcnt)) { |
| 2018 | 2020 | mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow); |
| 2019 | − list_del(&peer_flow->peer_flows); | |
| 2020 | 2021 | kfree(peer_flow); |
| 2021 | 2022 | } |
| 2022 | 2023 | } |
| @@ -83,6 +83,7 @@ mlx5_esw_bridge_mdb_flow_create(u16 esw_owner_vhca_id, struct mlx5_esw_bridge_md · 82 unmodified lines | ||
| 83 | 83 | i++; |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | + rule_spec->flow_context.flags |= FLOW_CONTEXT_UPLINK_HAIRPIN_EN; | |
| 86 | 87 | rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; |
| 87 | 88 | dmac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value, outer_headers.dmac_47_16); |
| 88 | 89 | ether_addr_copy(dmac_v, entry->key.addr); |
| @@ -587,6 +588,7 @@ mlx5_esw_bridge_mcast_vlan_flow_create(u16 vlan_proto, struct mlx5_esw_bridge_po · 498 unmodified lines | ||
| 587 | 588 | if (!rule_spec) |
| 588 | 589 | return ERR_PTR(-ENOMEM); |
| 589 | 590 | |
| 591 | + rule_spec->flow_context.flags |= FLOW_CONTEXT_UPLINK_HAIRPIN_EN; | |
| 590 | 592 | rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; |
| 591 | 593 | |
| 592 | 594 | flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; |
| @@ -662,6 +664,7 @@ mlx5_esw_bridge_mcast_fwd_flow_create(struct mlx5_esw_bridge_port *port) · 69 unmodified lines | ||
| 662 | 664 | dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID; |
| 663 | 665 | dest.vport.vhca_id = port->esw_owner_vhca_id; |
| 664 | 666 | } |
| 667 | + rule_spec->flow_context.flags |= FLOW_CONTEXT_UPLINK_HAIRPIN_EN; | |
| 665 | 668 | handle = mlx5_add_flow_rules(port->mcast.ft, rule_spec, &flow_act, &dest, 1); |
| 666 | 669 | |
| 667 | 670 | kvfree(rule_spec); |
| @@ -566,6 +566,8 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, · 565 unmodified lines | ||
| 566 | 566 | fte->flow_context.flow_tag); |
| 567 | 567 | MLX5_SET(flow_context, in_flow_context, flow_source, |
| 568 | 568 | fte->flow_context.flow_source); |
| 569 | + MLX5_SET(flow_context, in_flow_context, uplink_hairpin_en, | |
| 570 | + !!(fte->flow_context.flags & FLOW_CONTEXT_UPLINK_HAIRPIN_EN)); | |
| 569 | 571 | |
| 570 | 572 | MLX5_SET(flow_context, in_flow_context, extended_destination, |
| 571 | 573 | extended_dest); |
| @@ -783,7 +783,7 @@ static int mlx5_rdma_setup_rn(struct ib_device *ibdev, u32 port_num, · 782 unmodified lines | ||
| 783 | 783 | } |
| 784 | 784 | |
| 785 | 785 | /* This should only be called once per mdev */ |
| 786 | − err = mlx5e_create_mdev_resources(mdev); | |
| 786 | + err = mlx5e_create_mdev_resources(mdev, false); | |
| 787 | 787 | if (err) |
| 788 | 788 | goto destroy_ht; |
| 789 | 789 | } |
| @@ -98,7 +98,7 @@ static int create_aso_cq(struct mlx5_aso_cq *cq, void *cqc_data) · 97 unmodified lines | ||
| 98 | 98 | mlx5_fill_page_frag_array(&cq->wq_ctrl.buf, |
| 99 | 99 | (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas)); |
| 100 | 100 | |
| 101 | − MLX5_SET(cqc, cqc, cq_period_mode, DIM_CQ_PERIOD_MODE_START_FROM_EQE); | |
| 101 | + MLX5_SET(cqc, cqc, cq_period_mode, MLX5_CQ_PERIOD_MODE_START_FROM_EQE); | |
| 102 | 102 | MLX5_SET(cqc, cqc, c_eqn_or_apu_element, eqn); |
| 103 | 103 | MLX5_SET(cqc, cqc, uar_page, mdev->priv.uar->index); |
| 104 | 104 | MLX5_SET(cqc, cqc, log_page_size, cq->wq_ctrl.buf.page_shift - |
| @@ -788,6 +788,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher, · 787 unmodified lines | ||
| 788 | 788 | switch (action_type) { |
| 789 | 789 | case DR_ACTION_TYP_DROP: |
| 790 | 790 | attr.final_icm_addr = nic_dmn->drop_icm_addr; |
| 791 | + attr.hit_gvmi = nic_dmn->drop_icm_addr >> 48; | |
| 791 | 792 | break; |
| 792 | 793 | case DR_ACTION_TYP_FT: |
| 793 | 794 | dest_action = action; |
| @@ -873,11 +874,17 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher, · 79 unmodified lines | ||
| 873 | 874 | action->sampler->tx_icm_addr; |
| 874 | 875 | break; |
| 875 | 876 | case DR_ACTION_TYP_VPORT: |
| 876 | − attr.hit_gvmi = action->vport->caps->vhca_gvmi; | |
| 877 | − dest_action = action; | |
| 878 | − attr.final_icm_addr = rx_rule ? | |
| 879 | − action->vport->caps->icm_address_rx : | |
| 880 | − action->vport->caps->icm_address_tx; | |
| 877 | + if (unlikely(rx_rule && action->vport->caps->num == MLX5_VPORT_UPLINK)) { | |
| 878 | + /* can't go to uplink on RX rule - dropping instead */ | |
| 879 | + attr.final_icm_addr = nic_dmn->drop_icm_addr; | |
| 880 | + attr.hit_gvmi = nic_dmn->drop_icm_addr >> 48; | |
| 881 | + } else { | |
| 882 | + attr.hit_gvmi = action->vport->caps->vhca_gvmi; | |
| 883 | + dest_action = action; | |
| 884 | + attr.final_icm_addr = rx_rule ? | |
| 885 | + action->vport->caps->icm_address_rx : | |
| 886 | + action->vport->caps->icm_address_tx; | |
| 887 | + } | |
| 881 | 888 | break; |
| 882 | 889 | case DR_ACTION_TYP_POP_VLAN: |
| 883 | 890 | if (!rx_rule && !(dmn->ste_ctx->actions_caps & |
| @@ -440,6 +440,27 @@ out: · 439 unmodified lines | ||
| 440 | 440 | } |
| 441 | 441 | EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_system_image_guid); |
| 442 | 442 | |
| 443 | +int mlx5_query_nic_vport_sd_group(struct mlx5_core_dev *mdev, u8 *sd_group) | |
| 444 | +{ | |
| 445 | + int outlen = MLX5_ST_SZ_BYTES(query_nic_vport_context_out); | |
| 446 | + u32 *out; | |
| 447 | + int err; | |
| 448 | + | |
| 449 | + out = kvzalloc(outlen, GFP_KERNEL); | |
| 450 | + if (!out) | |
| 451 | + return -ENOMEM; | |
| 452 | + | |
| 453 | + err = mlx5_query_nic_vport_context(mdev, 0, out); | |
| 454 | + if (err) | |
| 455 | + goto out; | |
| 456 | + | |
| 457 | + *sd_group = MLX5_GET(query_nic_vport_context_out, out, | |
| 458 | + nic_vport_context.sd_group); | |
| 459 | +out: | |
| 460 | + kvfree(out); | |
| 461 | + return err; | |
| 462 | +} | |
| 463 | + | |
| 443 | 464 | int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid) |
| 444 | 465 | { |
| 445 | 466 | u32 *out; |
| @@ -168,9 +168,10 @@ static void lan966x_port_link_up(struct lan966x_port *port) · 167 unmodified lines | ||
| 168 | 168 | lan966x_taprio_speed_set(port, config->speed); |
| 169 | 169 | |
| 170 | 170 | /* Also the GIGA_MODE_ENA(1) needs to be set regardless of the |
| 171 | − * port speed for QSGMII ports. | |
| 171 | + * port speed for QSGMII or SGMII ports. | |
| 172 | 172 | */ |
| 173 | − if (phy_interface_num_ports(config->portmode) == 4) | |
| 173 | + if (phy_interface_num_ports(config->portmode) == 4 || | |
| 174 | + config->portmode == PHY_INTERFACE_MODE_SGMII) | |
| 174 | 175 | mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1); |
| 175 | 176 | |
| 176 | 177 | lan_wr(config->duplex | mode, |
| @@ -1424,10 +1424,30 @@ static void nfp_nft_ct_translate_mangle_action(struct flow_action_entry *mangle_ · 1423 unmodified lines | ||
| 1424 | 1424 | mangle_action->mangle.mask = (__force u32)cpu_to_be32(mangle_action->mangle.mask); |
| 1425 | 1425 | return; |
| 1426 | 1426 | |
| 1427 | + /* Both struct tcphdr and struct udphdr start with | |
| 1428 | + * __be16 source; | |
| 1429 | + * __be16 dest; | |
| 1430 | + * so we can use the same code for both. | |
| 1431 | + */ | |
| 1427 | 1432 | case FLOW_ACT_MANGLE_HDR_TYPE_TCP: |
| 1428 | 1433 | case FLOW_ACT_MANGLE_HDR_TYPE_UDP: |
| 1429 | − mangle_action->mangle.val = (__force u16)cpu_to_be16(mangle_action->mangle.val); | |
| 1430 | − mangle_action->mangle.mask = (__force u16)cpu_to_be16(mangle_action->mangle.mask); | |
| 1434 | + if (mangle_action->mangle.offset == offsetof(struct tcphdr, source)) { | |
| 1435 | + mangle_action->mangle.val = | |
| 1436 | + (__force u32)cpu_to_be32(mangle_action->mangle.val << 16); | |
| 1437 | + /* The mask of mangle action is inverse mask, | |
| 1438 | + * so clear the dest tp port with 0xFFFF to | |
| 1439 | + * instead of rotate-left operation. | |
| 1440 | + */ | |
| 1441 | + mangle_action->mangle.mask = | |
| 1442 | + (__force u32)cpu_to_be32(mangle_action->mangle.mask << 16 | 0xFFFF); | |
| 1443 | + } | |
| 1444 | + if (mangle_action->mangle.offset == offsetof(struct tcphdr, dest)) { | |
| 1445 | + mangle_action->mangle.offset = 0; | |
| 1446 | + mangle_action->mangle.val = | |
| 1447 | + (__force u32)cpu_to_be32(mangle_action->mangle.val); | |
| 1448 | + mangle_action->mangle.mask = | |
| 1449 | + (__force u32)cpu_to_be32(mangle_action->mangle.mask); | |
| 1450 | + } | |
| 1431 | 1451 | return; |
| 1432 | 1452 | |
| 1433 | 1453 | default: |
| @@ -1864,10 +1884,30 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv, · 430 unmodified lines | ||
| 1864 | 1884 | { |
| 1865 | 1885 | struct flow_rule *rule = flow_cls_offload_flow_rule(flow); |
| 1866 | 1886 | struct nfp_fl_ct_flow_entry *ct_entry; |
| 1887 | + struct flow_action_entry *ct_goto; | |
| 1867 | 1888 | struct nfp_fl_ct_zone_entry *zt; |
| 1889 | + struct flow_action_entry *act; | |
| 1868 | 1890 | bool wildcarded = false; |
| 1869 | 1891 | struct flow_match_ct ct; |
| 1870 | − struct flow_action_entry *ct_goto; | |
| 1892 | + int i; | |
| 1893 | + | |
| 1894 | + flow_action_for_each(i, act, &rule->action) { | |
| 1895 | + switch (act->id) { | |
| 1896 | + case FLOW_ACTION_REDIRECT: | |
| 1897 | + case FLOW_ACTION_REDIRECT_INGRESS: | |
| 1898 | + case FLOW_ACTION_MIRRED: | |
| 1899 | + case FLOW_ACTION_MIRRED_INGRESS: | |
| 1900 | + if (act->dev->rtnl_link_ops && | |
| 1901 | + !strcmp(act->dev->rtnl_link_ops->kind, "openvswitch")) { | |
| 1902 | + NL_SET_ERR_MSG_MOD(extack, | |
| 1903 | + "unsupported offload: out port is openvswitch internal port"); | |
| 1904 | + return -EOPNOTSUPP; | |
| 1905 | + } | |
| 1906 | + break; | |
| 1907 | + default: | |
| 1908 | + break; | |
| 1909 | + } | |
| 1910 | + } | |
| 1871 | 1911 | |
| 1872 | 1912 | flow_rule_match_ct(rule, &ct); |
| 1873 | 1913 | if (!ct.mask->ct_zone) { |
| @@ -1084,7 +1084,7 @@ nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev, · 1083 unmodified lines | ||
| 1084 | 1084 | u16 nfp_mac_idx = 0; |
| 1085 | 1085 | |
| 1086 | 1086 | entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr); |
| 1087 | − if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) { | |
| 1087 | + if (entry && (nfp_tunnel_is_mac_idx_global(entry->index) || netif_is_lag_port(netdev))) { | |
| 1088 | 1088 | if (entry->bridge_count || |
| 1089 | 1089 | !nfp_flower_is_supported_bridge(netdev)) { |
| 1090 | 1090 | nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, |
| @@ -2776,6 +2776,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn) · 2775 unmodified lines | ||
| 2776 | 2776 | case NFP_NFD_VER_NFD3: |
| 2777 | 2777 | netdev->netdev_ops = &nfp_nfd3_netdev_ops; |
| 2778 | 2778 | netdev->xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY; |
| 2779 | + netdev->xdp_features |= NETDEV_XDP_ACT_REDIRECT; | |
| 2779 | 2780 | break; |
| 2780 | 2781 | case NFP_NFD_VER_NFDK: |
| 2781 | 2782 | netdev->netdev_ops = &nfp_nfdk_netdev_ops; |
| @@ -537,11 +537,13 @@ static int enable_bars(struct nfp6000_pcie *nfp, u16 interface) · 536 unmodified lines | ||
| 537 | 537 | const u32 barcfg_msix_general = |
| 538 | 538 | NFP_PCIE_BAR_PCIE2CPP_MapType( |
| 539 | 539 | NFP_PCIE_BAR_PCIE2CPP_MapType_GENERAL) | |
| 540 | − NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT; | |
| 540 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect( | |
| 541 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT); | |
| 541 | 542 | const u32 barcfg_msix_xpb = |
| 542 | 543 | NFP_PCIE_BAR_PCIE2CPP_MapType( |
| 543 | 544 | NFP_PCIE_BAR_PCIE2CPP_MapType_BULK) | |
| 544 | − NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT | | |
| 545 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect( | |
| 546 | + NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT) | | |
| 545 | 547 | NFP_PCIE_BAR_PCIE2CPP_Target_BaseAddress( |
| 546 | 548 | NFP_CPP_TARGET_ISLAND_XPB); |
| 547 | 549 | const u32 barcfg_explicit[4] = { |
| @@ -59,28 +59,51 @@ · 58 unmodified lines | ||
| 59 | 59 | #undef FRAME_FILTER_DEBUG |
| 60 | 60 | /* #define FRAME_FILTER_DEBUG */ |
| 61 | 61 | |
| 62 | +struct stmmac_q_tx_stats { | |
| 63 | + u64_stats_t tx_bytes; | |
| 64 | + u64_stats_t tx_set_ic_bit; | |
| 65 | + u64_stats_t tx_tso_frames; | |
| 66 | + u64_stats_t tx_tso_nfrags; | |
| 67 | +}; | |
| 68 | + | |
| 69 | +struct stmmac_napi_tx_stats { | |
| 70 | + u64_stats_t tx_packets; | |
| 71 | + u64_stats_t tx_pkt_n; | |
| 72 | + u64_stats_t poll; | |
| 73 | + u64_stats_t tx_clean; | |
| 74 | + u64_stats_t tx_set_ic_bit; | |
| 75 | +}; | |
| 76 | + | |
| 62 | 77 | struct stmmac_txq_stats { |
| 63 | − u64 tx_bytes; | |
| 64 | − u64 tx_packets; | |
| 65 | − u64 tx_pkt_n; | |
| 66 | − u64 tx_normal_irq_n; | |
| 67 | − u64 napi_poll; | |
| 68 | − u64 tx_clean; | |
| 69 | − u64 tx_set_ic_bit; | |
| 70 | − u64 tx_tso_frames; | |
| 71 | − u64 tx_tso_nfrags; | |
| 72 | − struct u64_stats_sync syncp; | |
| 78 | + /* Updates protected by tx queue lock. */ | |
| 79 | + struct u64_stats_sync q_syncp; | |
| 80 | + struct stmmac_q_tx_stats q; | |
| 81 | + | |
| 82 | + /* Updates protected by NAPI poll logic. */ | |
| 83 | + struct u64_stats_sync napi_syncp; | |
| 84 | + struct stmmac_napi_tx_stats napi; | |
| 73 | 85 | } ____cacheline_aligned_in_smp; |
| 74 | 86 | |
| 87 | +struct stmmac_napi_rx_stats { | |
| 88 | + u64_stats_t rx_bytes; | |
| 89 | + u64_stats_t rx_packets; | |
| 90 | + u64_stats_t rx_pkt_n; | |
| 91 | + u64_stats_t poll; | |
| 92 | +}; | |
| 93 | + | |
| 75 | 94 | struct stmmac_rxq_stats { |
| 76 | − u64 rx_bytes; | |
| 77 | − u64 rx_packets; | |
| 78 | − u64 rx_pkt_n; | |
| 79 | − u64 rx_normal_irq_n; | |
| 80 | − u64 napi_poll; | |
| 81 | − struct u64_stats_sync syncp; | |
| 95 | + /* Updates protected by NAPI poll logic. */ | |
| 96 | + struct u64_stats_sync napi_syncp; | |
| 97 | + struct stmmac_napi_rx_stats napi; | |
| 82 | 98 | } ____cacheline_aligned_in_smp; |
| 83 | 99 | |
| 100 | +/* Updates on each CPU protected by not allowing nested irqs. */ | |
| 101 | +struct stmmac_pcpu_stats { | |
| 102 | + struct u64_stats_sync syncp; | |
| 103 | + u64_stats_t rx_normal_irq_n[MTL_MAX_TX_QUEUES]; | |
| 104 | + u64_stats_t tx_normal_irq_n[MTL_MAX_RX_QUEUES]; | |
| 105 | +}; | |
| 106 | + | |
| 84 | 107 | /* Extra statistic and debug information exposed by ethtool */ |
| 85 | 108 | struct stmmac_extra_stats { |
| 86 | 109 | /* Transmit errors */ |
| @@ -205,6 +228,7 @@ struct stmmac_extra_stats { · 118 unmodified lines | ||
| 205 | 228 | /* per queue statistics */ |
| 206 | 229 | struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES]; |
| 207 | 230 | struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES]; |
| 231 | + struct stmmac_pcpu_stats __percpu *pcpu_stats; | |
| 208 | 232 | unsigned long rx_dropped; |
| 209 | 233 | unsigned long rx_errors; |
| 210 | 234 | unsigned long tx_dropped; |
| @@ -216,6 +240,7 @@ struct stmmac_safety_stats { · 5 unmodified lines | ||
| 216 | 240 | unsigned long mac_errors[32]; |
| 217 | 241 | unsigned long mtl_errors[32]; |
| 218 | 242 | unsigned long dma_errors[32]; |
| 243 | + unsigned long dma_dpp_errors[32]; | |
| 219 | 244 | }; |
| 220 | 245 | |
| 221 | 246 | /* Number of fields in Safety Stats */ |
| @@ -353,6 +353,10 @@ static int imx_dwmac_probe(struct platform_device *pdev) · 352 unmodified lines | ||
| 353 | 353 | if (data->flags & STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY) |
| 354 | 354 | plat_dat->flags |= STMMAC_FLAG_HWTSTAMP_CORRECT_LATENCY; |
| 355 | 355 | |
| 356 | + /* Default TX Q0 to use TSO and rest TXQ for TBS */ | |
| 357 | + for (int i = 1; i < plat_dat->tx_queues_to_use; i++) | |
| 358 | + plat_dat->tx_queues_cfg[i].tbs_en = 1; | |
| 359 | + | |
| 356 | 360 | plat_dat->host_dma_width = dwmac->ops->addr_width; |
| 357 | 361 | plat_dat->init = imx_dwmac_init; |
| 358 | 362 | plat_dat->exit = imx_dwmac_exit; |
| @@ -441,8 +441,7 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, · 440 unmodified lines | ||
| 441 | 441 | struct stmmac_extra_stats *x, u32 chan, |
| 442 | 442 | u32 dir) |
| 443 | 443 | { |
| 444 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 445 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 444 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 446 | 445 | int ret = 0; |
| 447 | 446 | u32 v; |
| 448 | 447 | |
| @@ -455,9 +454,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, · 6 unmodified lines | ||
| 455 | 454 | |
| 456 | 455 | if (v & EMAC_TX_INT) { |
| 457 | 456 | ret |= handle_tx; |
| 458 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 459 | − txq_stats->tx_normal_irq_n++; | |
| 460 | − u64_stats_update_end(&txq_stats->syncp); | |
| 457 | + u64_stats_update_begin(&stats->syncp); | |
| 458 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 459 | + u64_stats_update_end(&stats->syncp); | |
| 461 | 460 | } |
| 462 | 461 | |
| 463 | 462 | if (v & EMAC_TX_DMA_STOP_INT) |
| @@ -479,9 +478,9 @@ static int sun8i_dwmac_dma_interrupt(struct stmmac_priv *priv, · 15 unmodified lines | ||
| 479 | 478 | |
| 480 | 479 | if (v & EMAC_RX_INT) { |
| 481 | 480 | ret |= handle_rx; |
| 482 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 483 | − rxq_stats->rx_normal_irq_n++; | |
| 484 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 481 | + u64_stats_update_begin(&stats->syncp); | |
| 482 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 483 | + u64_stats_update_end(&stats->syncp); | |
| 485 | 484 | } |
| 486 | 485 | |
| 487 | 486 | if (v & EMAC_RX_BUF_UA_INT) |
| @@ -171,8 +171,7 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, · 170 unmodified lines | ||
| 171 | 171 | const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; |
| 172 | 172 | u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(dwmac4_addrs, chan)); |
| 173 | 173 | u32 intr_en = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); |
| 174 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 175 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 174 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 176 | 175 | int ret = 0; |
| 177 | 176 | |
| 178 | 177 | if (dir == DMA_DIR_RX) |
| @@ -201,15 +200,15 @@ int dwmac4_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, · 22 unmodified lines | ||
| 201 | 200 | } |
| 202 | 201 | /* TX/RX NORMAL interrupts */ |
| 203 | 202 | if (likely(intr_status & DMA_CHAN_STATUS_RI)) { |
| 204 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 205 | − rxq_stats->rx_normal_irq_n++; | |
| 206 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 203 | + u64_stats_update_begin(&stats->syncp); | |
| 204 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 205 | + u64_stats_update_end(&stats->syncp); | |
| 207 | 206 | ret |= handle_rx; |
| 208 | 207 | } |
| 209 | 208 | if (likely(intr_status & DMA_CHAN_STATUS_TI)) { |
| 210 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 211 | − txq_stats->tx_normal_irq_n++; | |
| 212 | − u64_stats_update_end(&txq_stats->syncp); | |
| 209 | + u64_stats_update_begin(&stats->syncp); | |
| 210 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 211 | + u64_stats_update_end(&stats->syncp); | |
| 213 | 212 | ret |= handle_tx; |
| 214 | 213 | } |
| 215 | 214 | |
| @@ -162,8 +162,7 @@ static void show_rx_process_state(unsigned int status) · 161 unmodified lines | ||
| 162 | 162 | int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, |
| 163 | 163 | struct stmmac_extra_stats *x, u32 chan, u32 dir) |
| 164 | 164 | { |
| 165 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 166 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 165 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 167 | 166 | int ret = 0; |
| 168 | 167 | /* read the status register (CSR5) */ |
| 169 | 168 | u32 intr_status = readl(ioaddr + DMA_STATUS); |
| @@ -215,16 +214,16 @@ int dwmac_dma_interrupt(struct stmmac_priv *priv, void __iomem *ioaddr, · 45 unmodified lines | ||
| 215 | 214 | u32 value = readl(ioaddr + DMA_INTR_ENA); |
| 216 | 215 | /* to schedule NAPI on real RIE event. */ |
| 217 | 216 | if (likely(value & DMA_INTR_ENA_RIE)) { |
| 218 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 219 | − rxq_stats->rx_normal_irq_n++; | |
| 220 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 217 | + u64_stats_update_begin(&stats->syncp); | |
| 218 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 219 | + u64_stats_update_end(&stats->syncp); | |
| 221 | 220 | ret |= handle_rx; |
| 222 | 221 | } |
| 223 | 222 | } |
| 224 | 223 | if (likely(intr_status & DMA_STATUS_TI)) { |
| 225 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 226 | − txq_stats->tx_normal_irq_n++; | |
| 227 | − u64_stats_update_end(&txq_stats->syncp); | |
| 224 | + u64_stats_update_begin(&stats->syncp); | |
| 225 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 226 | + u64_stats_update_end(&stats->syncp); | |
| 228 | 227 | ret |= handle_tx; |
| 229 | 228 | } |
| 230 | 229 | if (unlikely(intr_status & DMA_STATUS_ERI)) |
| @@ -303,6 +303,8 @@ · 302 unmodified lines | ||
| 303 | 303 | #define XGMAC_RXCEIE BIT(4) |
| 304 | 304 | #define XGMAC_TXCEIE BIT(0) |
| 305 | 305 | #define XGMAC_MTL_ECC_INT_STATUS 0x000010cc |
| 306 | +#define XGMAC_MTL_DPP_CONTROL 0x000010e0 | |
| 307 | +#define XGMAC_DPP_DISABLE BIT(0) | |
| 306 | 308 | #define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) |
| 307 | 309 | #define XGMAC_TQS GENMASK(25, 16) |
| 308 | 310 | #define XGMAC_TQS_SHIFT 16 |
| @@ -385,6 +387,7 @@ · 76 unmodified lines | ||
| 385 | 387 | #define XGMAC_DCEIE BIT(1) |
| 386 | 388 | #define XGMAC_TCEIE BIT(0) |
| 387 | 389 | #define XGMAC_DMA_ECC_INT_STATUS 0x0000306c |
| 390 | +#define XGMAC_DMA_DPP_INT_STATUS 0x00003074 | |
| 388 | 391 | #define XGMAC_DMA_CH_CONTROL(x) (0x00003100 + (0x80 * (x))) |
| 389 | 392 | #define XGMAC_SPH BIT(24) |
| 390 | 393 | #define XGMAC_PBLx8 BIT(16) |
| @@ -830,6 +830,43 @@ static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= { · 829 unmodified lines | ||
| 830 | 830 | { false, "UNKNOWN", "Unknown Error" }, /* 31 */ |
| 831 | 831 | }; |
| 832 | 832 | |
| 833 | +static const char * const dpp_rx_err = "Read Rx Descriptor Parity checker Error"; | |
| 834 | +static const char * const dpp_tx_err = "Read Tx Descriptor Parity checker Error"; | |
| 835 | +static const struct dwxgmac3_error_desc dwxgmac3_dma_dpp_errors[32] = { | |
| 836 | + { true, "TDPES0", dpp_tx_err }, | |
| 837 | + { true, "TDPES1", dpp_tx_err }, | |
| 838 | + { true, "TDPES2", dpp_tx_err }, | |
| 839 | + { true, "TDPES3", dpp_tx_err }, | |
| 840 | + { true, "TDPES4", dpp_tx_err }, | |
| 841 | + { true, "TDPES5", dpp_tx_err }, | |
| 842 | + { true, "TDPES6", dpp_tx_err }, | |
| 843 | + { true, "TDPES7", dpp_tx_err }, | |
| 844 | + { true, "TDPES8", dpp_tx_err }, | |
| 845 | + { true, "TDPES9", dpp_tx_err }, | |
| 846 | + { true, "TDPES10", dpp_tx_err }, | |
| 847 | + { true, "TDPES11", dpp_tx_err }, | |
| 848 | + { true, "TDPES12", dpp_tx_err }, | |
| 849 | + { true, "TDPES13", dpp_tx_err }, | |
| 850 | + { true, "TDPES14", dpp_tx_err }, | |
| 851 | + { true, "TDPES15", dpp_tx_err }, | |
| 852 | + { true, "RDPES0", dpp_rx_err }, | |
| 853 | + { true, "RDPES1", dpp_rx_err }, | |
| 854 | + { true, "RDPES2", dpp_rx_err }, | |
| 855 | + { true, "RDPES3", dpp_rx_err }, | |
| 856 | + { true, "RDPES4", dpp_rx_err }, | |
| 857 | + { true, "RDPES5", dpp_rx_err }, | |
| 858 | + { true, "RDPES6", dpp_rx_err }, | |
| 859 | + { true, "RDPES7", dpp_rx_err }, | |
| 860 | + { true, "RDPES8", dpp_rx_err }, | |
| 861 | + { true, "RDPES9", dpp_rx_err }, | |
| 862 | + { true, "RDPES10", dpp_rx_err }, | |
| 863 | + { true, "RDPES11", dpp_rx_err }, | |
| 864 | + { true, "RDPES12", dpp_rx_err }, | |
| 865 | + { true, "RDPES13", dpp_rx_err }, | |
| 866 | + { true, "RDPES14", dpp_rx_err }, | |
| 867 | + { true, "RDPES15", dpp_rx_err }, | |
| 868 | +}; | |
| 869 | + | |
| 833 | 870 | static void dwxgmac3_handle_dma_err(struct net_device *ndev, |
| 834 | 871 | void __iomem *ioaddr, bool correctable, |
| 835 | 872 | struct stmmac_safety_stats *stats) |
| @@ -841,6 +878,13 @@ static void dwxgmac3_handle_dma_err(struct net_device *ndev, · 5 unmodified lines | ||
| 841 | 878 | |
| 842 | 879 | dwxgmac3_log_error(ndev, value, correctable, "DMA", |
| 843 | 880 | dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats); |
| 881 | + | |
| 882 | + value = readl(ioaddr + XGMAC_DMA_DPP_INT_STATUS); | |
| 883 | + writel(value, ioaddr + XGMAC_DMA_DPP_INT_STATUS); | |
| 884 | + | |
| 885 | + dwxgmac3_log_error(ndev, value, false, "DMA_DPP", | |
| 886 | + dwxgmac3_dma_dpp_errors, | |
| 887 | + STAT_OFF(dma_dpp_errors), stats); | |
| 844 | 888 | } |
| 845 | 889 | |
| 846 | 890 | static int |
| @@ -881,6 +925,12 @@ dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp, · 34 unmodified lines | ||
| 881 | 925 | value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */ |
| 882 | 926 | writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL); |
| 883 | 927 | |
| 928 | + /* 5. Enable Data Path Parity Protection */ | |
| 929 | + value = readl(ioaddr + XGMAC_MTL_DPP_CONTROL); | |
| 930 | + /* already enabled by default, explicit enable it again */ | |
| 931 | + value &= ~XGMAC_DPP_DISABLE; | |
| 932 | + writel(value, ioaddr + XGMAC_MTL_DPP_CONTROL); | |
| 933 | + | |
| 884 | 934 | return 0; |
| 885 | 935 | } |
| 886 | 936 | |
| @@ -914,7 +964,11 @@ static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev, · 27 unmodified lines | ||
| 914 | 964 | ret |= !corr; |
| 915 | 965 | } |
| 916 | 966 | |
| 917 | − err = dma & (XGMAC_DEUIS | XGMAC_DECIS); | |
| 967 | + /* DMA_DPP_Interrupt_Status is indicated by MCSIS bit in | |
| 968 | + * DMA_Safety_Interrupt_Status, so we handle DMA Data Path | |
| 969 | + * Parity Errors here | |
| 970 | + */ | |
| 971 | + err = dma & (XGMAC_DEUIS | XGMAC_DECIS | XGMAC_MCSIS); | |
| 918 | 972 | corr = dma & XGMAC_DECIS; |
| 919 | 973 | if (err) { |
| 920 | 974 | dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats); |
| @@ -930,6 +984,7 @@ static const struct dwxgmac3_error { · 9 unmodified lines | ||
| 930 | 984 | { dwxgmac3_mac_errors }, |
| 931 | 985 | { dwxgmac3_mtl_errors }, |
| 932 | 986 | { dwxgmac3_dma_errors }, |
| 987 | + { dwxgmac3_dma_dpp_errors }, | |
| 933 | 988 | }; |
| 934 | 989 | |
| 935 | 990 | static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats, |
| @@ -337,8 +337,7 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, · 336 unmodified lines | ||
| 337 | 337 | struct stmmac_extra_stats *x, u32 chan, |
| 338 | 338 | u32 dir) |
| 339 | 339 | { |
| 340 | − struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[chan]; | |
| 341 | − struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[chan]; | |
| 340 | + struct stmmac_pcpu_stats *stats = this_cpu_ptr(priv->xstats.pcpu_stats); | |
| 342 | 341 | u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan)); |
| 343 | 342 | u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan)); |
| 344 | 343 | int ret = 0; |
| @@ -367,15 +366,15 @@ static int dwxgmac2_dma_interrupt(struct stmmac_priv *priv, · 22 unmodified lines | ||
| 367 | 366 | /* TX/RX NORMAL interrupts */ |
| 368 | 367 | if (likely(intr_status & XGMAC_NIS)) { |
| 369 | 368 | if (likely(intr_status & XGMAC_RI)) { |
| 370 | − u64_stats_update_begin(&rxq_stats->syncp); | |
| 371 | − rxq_stats->rx_normal_irq_n++; | |
| 372 | − u64_stats_update_end(&rxq_stats->syncp); | |
| 369 | + u64_stats_update_begin(&stats->syncp); | |
| 370 | + u64_stats_inc(&stats->rx_normal_irq_n[chan]); | |
| 371 | + u64_stats_update_end(&stats->syncp); | |
| 373 | 372 | ret |= handle_rx; |
| 374 | 373 | } |
| 375 | 374 | if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { |
| 376 | − u64_stats_update_begin(&txq_stats->syncp); | |
| 377 | − txq_stats->tx_normal_irq_n++; | |
| 378 | − u64_stats_update_end(&txq_stats->syncp); | |
| 375 | + u64_stats_update_begin(&stats->syncp); | |
| 376 | + u64_stats_inc(&stats->tx_normal_irq_n[chan]); | |
| 377 | + u64_stats_update_end(&stats->syncp); | |
| 379 | 378 | ret |= handle_tx; |
| 380 | 379 | } |
| 381 | 380 | } |
| @@ -549,44 +549,79 @@ stmmac_set_pauseparam(struct net_device *netdev, · 548 unmodified lines | ||
| 549 | 549 | } |
| 550 | 550 | } |
| 551 | 551 | |
| 552 | +static u64 stmmac_get_rx_normal_irq_n(struct stmmac_priv *priv, int q) | |
| 553 | +{ | |
| 554 | + u64 total; | |
| 555 | + int cpu; | |
| 556 | + | |
| 557 | + total = 0; | |
| 558 | + for_each_possible_cpu(cpu) { | |
| 559 | + struct stmmac_pcpu_stats *pcpu; | |
| 560 | + unsigned int start; | |
| 561 | + u64 irq_n; | |
| 562 | + | |
| 563 | + pcpu = per_cpu_ptr(priv->xstats.pcpu_stats, cpu); | |
| 564 | + do { | |
| 565 | + start = u64_stats_fetch_begin(&pcpu->syncp); | |
| 566 | + irq_n = u64_stats_read(&pcpu->rx_normal_irq_n[q]); | |
| 567 | + } while (u64_stats_fetch_retry(&pcpu->syncp, start)); | |
| 568 | + total += irq_n; | |
| 569 | + } | |
| 570 | + return total; | |
| 571 | +} | |
| 572 | + | |
| 573 | +static u64 stmmac_get_tx_normal_irq_n(struct stmmac_priv *priv, int q) | |
| 574 | +{ | |
| 575 | + u64 total; | |
| 576 | + int cpu; | |
| 577 | + | |
| 578 | + total = 0; | |
| 579 | + for_each_possible_cpu(cpu) { | |
| 580 | + struct stmmac_pcpu_stats *pcpu; | |
| 581 | + unsigned int start; | |
| 582 | + u64 irq_n; | |
| 583 | + | |
| 584 | + pcpu = per_cpu_ptr(priv->xstats.pcpu_stats, cpu); | |
| 585 | + do { | |
| 586 | + start = u64_stats_fetch_begin(&pcpu->syncp); | |
| 587 | + irq_n = u64_stats_read(&pcpu->tx_normal_irq_n[q]); | |
| 588 | + } while (u64_stats_fetch_retry(&pcpu->syncp, start)); | |
| 589 | + total += irq_n; | |
| 590 | + } | |
| 591 | + return total; | |
| 592 | +} | |
| 593 | + | |
| 552 | 594 | static void stmmac_get_per_qstats(struct stmmac_priv *priv, u64 *data) |
| 553 | 595 | { |
| 554 | 596 | u32 tx_cnt = priv->plat->tx_queues_to_use; |
| 555 | 597 | u32 rx_cnt = priv->plat->rx_queues_to_use; |
| 556 | 598 | unsigned int start; |
| 557 | − int q, stat; | |
| 558 | − char *p; | |
| 599 | + int q; | |
| 559 | 600 | |
| 560 | 601 | for (q = 0; q < tx_cnt; q++) { |
| 561 | 602 | struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[q]; |
| 562 | − struct stmmac_txq_stats snapshot; | |
| 603 | + u64 pkt_n; | |
| 563 | 604 | |
| 564 | 605 | do { |
| 565 | − start = u64_stats_fetch_begin(&txq_stats->syncp); | |
| 566 | − snapshot = *txq_stats; | |
| 567 | − } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); | |
| 606 | + start = u64_stats_fetch_begin(&txq_stats->napi_syncp); | |
| 607 | + pkt_n = u64_stats_read(&txq_stats->napi.tx_pkt_n); | |
| 608 | + } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start)); | |
| 568 | 609 | |
| 569 | − p = (char *)&snapshot + offsetof(struct stmmac_txq_stats, tx_pkt_n); | |
| 570 | − for (stat = 0; stat < STMMAC_TXQ_STATS; stat++) { | |
| 571 | − *data++ = (*(u64 *)p); | |
| 572 | − p += sizeof(u64); | |
| 573 | − } | |
| 610 | + *data++ = pkt_n; | |
| 611 | + *data++ = stmmac_get_tx_normal_irq_n(priv, q); | |
| 574 | 612 | } |
| 575 | 613 | |
| 576 | 614 | for (q = 0; q < rx_cnt; q++) { |
| 577 | 615 | struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[q]; |
| 578 | − struct stmmac_rxq_stats snapshot; | |
| 616 | + u64 pkt_n; | |
| 579 | 617 | |
| 580 | 618 | do { |
| 581 | − start = u64_stats_fetch_begin(&rxq_stats->syncp); | |
| 582 | − snapshot = *rxq_stats; | |
| 583 | − } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); | |
| 619 | + start = u64_stats_fetch_begin(&rxq_stats->napi_syncp); | |
| 620 | + pkt_n = u64_stats_read(&rxq_stats->napi.rx_pkt_n); | |
| 621 | + } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start)); | |
| 584 | 622 | |
| 585 | − p = (char *)&snapshot + offsetof(struct stmmac_rxq_stats, rx_pkt_n); | |
| 586 | − for (stat = 0; stat < STMMAC_RXQ_STATS; stat++) { | |
| 587 | − *data++ = (*(u64 *)p); | |
| 588 | − p += sizeof(u64); | |
| 589 | − } | |
| 623 | + *data++ = pkt_n; | |
| 624 | + *data++ = stmmac_get_rx_normal_irq_n(priv, q); | |
| 590 | 625 | } |
| 591 | 626 | } |
| 592 | 627 | |
| @@ -645,39 +680,49 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, · 52 unmodified lines | ||
| 645 | 680 | pos = j; |
| 646 | 681 | for (i = 0; i < rx_queues_count; i++) { |
| 647 | 682 | struct stmmac_rxq_stats *rxq_stats = &priv->xstats.rxq_stats[i]; |
| 648 | − struct stmmac_rxq_stats snapshot; | |
| 683 | + struct stmmac_napi_rx_stats snapshot; | |
| 684 | + u64 n_irq; | |
| 649 | 685 | |
| 650 | 686 | j = pos; |
| 651 | 687 | do { |
| 652 | − start = u64_stats_fetch_begin(&rxq_stats->syncp); | |
| 653 | − snapshot = *rxq_stats; | |
| 654 | − } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); | |
| 655 | − | |
| 656 | − data[j++] += snapshot.rx_pkt_n; | |
| 657 | − data[j++] += snapshot.rx_normal_irq_n; | |
| 658 | − normal_irq_n += snapshot.rx_normal_irq_n; | |
| 659 | − napi_poll += snapshot.napi_poll; | |
| 688 | + start = u64_stats_fetch_begin(&rxq_stats->napi_syncp); | |
| 689 | + snapshot = rxq_stats->napi; | |
| 690 | + } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start)); | |
| 691 | + | |
| 692 | + data[j++] += u64_stats_read(&snapshot.rx_pkt_n); | |
| 693 | + n_irq = stmmac_get_rx_normal_irq_n(priv, i); | |
| 694 | + data[j++] += n_irq; | |
| 695 | + normal_irq_n += n_irq; | |
| 696 | + napi_poll += u64_stats_read(&snapshot.poll); | |
| 660 | 697 | } |
| 661 | 698 | |
| 662 | 699 | pos = j; |
| 663 | 700 | for (i = 0; i < tx_queues_count; i++) { |
| 664 | 701 | struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[i]; |
| 665 | − struct stmmac_txq_stats snapshot; | |
| 702 | + struct stmmac_napi_tx_stats napi_snapshot; | |
| 703 | + struct stmmac_q_tx_stats q_snapshot; | |
| 704 | + u64 n_irq; | |
| 666 | 705 | |
| 667 | 706 | j = pos; |
| 668 | 707 | do { |
| 669 | − start = u64_stats_fetch_begin(&txq_stats->syncp); | |
| 670 | − snapshot = *txq_stats; | |
| 671 | − } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); | |
| 672 | − | |
| 673 | − data[j++] += snapshot.tx_pkt_n; | |
| 674 | − data[j++] += snapshot.tx_normal_irq_n; | |
| 675 | − normal_irq_n += snapshot.tx_normal_irq_n; | |
| 676 | − data[j++] += snapshot.tx_clean; | |
| 677 | − data[j++] += snapshot.tx_set_ic_bit; | |
| 678 | − data[j++] += snapshot.tx_tso_frames; | |
| 679 | − data[j++] += snapshot.tx_tso_nfrags; | |
| 680 | − napi_poll += snapshot.napi_poll; | |
| 708 | + start = u64_stats_fetch_begin(&txq_stats->q_syncp); | |
| 709 | + q_snapshot = txq_stats->q; | |
| 710 | + } while (u64_stats_fetch_retry(&txq_stats->q_syncp, start)); | |
| 711 | + do { | |
| 712 | + start = u64_stats_fetch_begin(&txq_stats->napi_syncp); | |
| 713 | + napi_snapshot = txq_stats->napi; | |
| 714 | + } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start)); | |
| 715 | + | |
| 716 | + data[j++] += u64_stats_read(&napi_snapshot.tx_pkt_n); | |
| 717 | + n_irq = stmmac_get_tx_normal_irq_n(priv, i); | |
| 718 | + data[j++] += n_irq; | |
| 719 | + normal_irq_n += n_irq; | |
| 720 | + data[j++] += u64_stats_read(&napi_snapshot.tx_clean); | |
| 721 | + data[j++] += u64_stats_read(&q_snapshot.tx_set_ic_bit) + | |
| 722 | + u64_stats_read(&napi_snapshot.tx_set_ic_bit); | |
| 723 | + data[j++] += u64_stats_read(&q_snapshot.tx_tso_frames); | |
| 724 | + data[j++] += u64_stats_read(&q_snapshot.tx_tso_nfrags); | |
| 725 | + napi_poll += u64_stats_read(&napi_snapshot.poll); | |
| 681 | 726 | } |
| 682 | 727 | normal_irq_n += priv->xstats.rx_early_irq; |
| 683 | 728 | data[j++] = normal_irq_n; |
| @@ -2482,7 +2482,6 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) · 2481 unmodified lines | ||
| 2482 | 2482 | struct xdp_desc xdp_desc; |
| 2483 | 2483 | bool work_done = true; |
| 2484 | 2484 | u32 tx_set_ic_bit = 0; |
| 2485 | − unsigned long flags; | |
| 2486 | 2485 | |
| 2487 | 2486 | /* Avoids TX time-out as we are sharing with slow path */ |
| 2488 | 2487 | txq_trans_cond_update(nq); |
| @@ -2566,9 +2565,9 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget) · 77 unmodified lines | ||
| 2566 | 2565 | tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, priv->dma_conf.dma_tx_size); |
| 2567 | 2566 | entry = tx_q->cur_tx; |
| 2568 | 2567 | } |
| 2569 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 2570 | − txq_stats->tx_set_ic_bit += tx_set_ic_bit; | |
| 2571 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 2568 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 2569 | + u64_stats_add(&txq_stats->napi.tx_set_ic_bit, tx_set_ic_bit); | |
| 2570 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 2572 | 2571 | |
| 2573 | 2572 | if (tx_desc) { |
| 2574 | 2573 | stmmac_flush_tx_descriptors(priv, queue); |
| @@ -2616,7 +2615,6 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, · 41 unmodified lines | ||
| 2616 | 2615 | unsigned int bytes_compl = 0, pkts_compl = 0; |
| 2617 | 2616 | unsigned int entry, xmits = 0, count = 0; |
| 2618 | 2617 | u32 tx_packets = 0, tx_errors = 0; |
| 2619 | − unsigned long flags; | |
| 2620 | 2618 | |
| 2621 | 2619 | __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue)); |
| 2622 | 2620 | |
| @@ -2782,11 +2780,11 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue, · 159 unmodified lines | ||
| 2782 | 2780 | if (tx_q->dirty_tx != tx_q->cur_tx) |
| 2783 | 2781 | *pending_packets = true; |
| 2784 | 2782 | |
| 2785 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 2786 | − txq_stats->tx_packets += tx_packets; | |
| 2787 | − txq_stats->tx_pkt_n += tx_packets; | |
| 2788 | − txq_stats->tx_clean++; | |
| 2789 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 2783 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 2784 | + u64_stats_add(&txq_stats->napi.tx_packets, tx_packets); | |
| 2785 | + u64_stats_add(&txq_stats->napi.tx_pkt_n, tx_packets); | |
| 2786 | + u64_stats_inc(&txq_stats->napi.tx_clean); | |
| 2787 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 2790 | 2788 | |
| 2791 | 2789 | priv->xstats.tx_errors += tx_errors; |
| 2792 | 2790 | |
| @@ -3932,6 +3930,9 @@ static int __stmmac_open(struct net_device *dev, · 1139 unmodified lines | ||
| 3932 | 3930 | priv->rx_copybreak = STMMAC_RX_COPYBREAK; |
| 3933 | 3931 | |
| 3934 | 3932 | buf_sz = dma_conf->dma_buf_sz; |
| 3933 | + for (int i = 0; i < MTL_MAX_TX_QUEUES; i++) | |
| 3934 | + if (priv->dma_conf.tx_queue[i].tbs & STMMAC_TBS_EN) | |
| 3935 | + dma_conf->tx_queue[i].tbs = priv->dma_conf.tx_queue[i].tbs; | |
| 3935 | 3936 | memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf)); |
| 3936 | 3937 | |
| 3937 | 3938 | stmmac_reset_queues_param(priv); |
| @@ -4210,7 +4211,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) · 272 unmodified lines | ||
| 4210 | 4211 | struct stmmac_tx_queue *tx_q; |
| 4211 | 4212 | bool has_vlan, set_ic; |
| 4212 | 4213 | u8 proto_hdr_len, hdr; |
| 4213 | − unsigned long flags; | |
| 4214 | 4214 | u32 pay_len, mss; |
| 4215 | 4215 | dma_addr_t des; |
| 4216 | 4216 | int i; |
| @@ -4375,13 +4375,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) · 158 unmodified lines | ||
| 4375 | 4375 | netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); |
| 4376 | 4376 | } |
| 4377 | 4377 | |
| 4378 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 4379 | − txq_stats->tx_bytes += skb->len; | |
| 4380 | − txq_stats->tx_tso_frames++; | |
| 4381 | − txq_stats->tx_tso_nfrags += nfrags; | |
| 4378 | + u64_stats_update_begin(&txq_stats->q_syncp); | |
| 4379 | + u64_stats_add(&txq_stats->q.tx_bytes, skb->len); | |
| 4380 | + u64_stats_inc(&txq_stats->q.tx_tso_frames); | |
| 4381 | + u64_stats_add(&txq_stats->q.tx_tso_nfrags, nfrags); | |
| 4382 | 4382 | if (set_ic) |
| 4383 | − txq_stats->tx_set_ic_bit++; | |
| 4384 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 4383 | + u64_stats_inc(&txq_stats->q.tx_set_ic_bit); | |
| 4384 | + u64_stats_update_end(&txq_stats->q_syncp); | |
| 4385 | 4385 | |
| 4386 | 4386 | if (priv->sarc_type) |
| 4387 | 4387 | stmmac_set_desc_sarc(priv, first, priv->sarc_type); |
| @@ -4480,7 +4480,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) · 92 unmodified lines | ||
| 4480 | 4480 | struct stmmac_tx_queue *tx_q; |
| 4481 | 4481 | bool has_vlan, set_ic; |
| 4482 | 4482 | int entry, first_tx; |
| 4483 | − unsigned long flags; | |
| 4484 | 4483 | dma_addr_t des; |
| 4485 | 4484 | |
| 4486 | 4485 | tx_q = &priv->dma_conf.tx_queue[queue]; |
| @@ -4650,11 +4649,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) · 163 unmodified lines | ||
| 4650 | 4649 | netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); |
| 4651 | 4650 | } |
| 4652 | 4651 | |
| 4653 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 4654 | − txq_stats->tx_bytes += skb->len; | |
| 4652 | + u64_stats_update_begin(&txq_stats->q_syncp); | |
| 4653 | + u64_stats_add(&txq_stats->q.tx_bytes, skb->len); | |
| 4655 | 4654 | if (set_ic) |
| 4656 | − txq_stats->tx_set_ic_bit++; | |
| 4657 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 4655 | + u64_stats_inc(&txq_stats->q.tx_set_ic_bit); | |
| 4656 | + u64_stats_update_end(&txq_stats->q_syncp); | |
| 4658 | 4657 | |
| 4659 | 4658 | if (priv->sarc_type) |
| 4660 | 4659 | stmmac_set_desc_sarc(priv, first, priv->sarc_type); |
| @@ -4918,12 +4917,11 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue, · 257 unmodified lines | ||
| 4918 | 4917 | set_ic = false; |
| 4919 | 4918 | |
| 4920 | 4919 | if (set_ic) { |
| 4921 | − unsigned long flags; | |
| 4922 | 4920 | tx_q->tx_count_frames = 0; |
| 4923 | 4921 | stmmac_set_tx_ic(priv, tx_desc); |
| 4924 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 4925 | − txq_stats->tx_set_ic_bit++; | |
| 4926 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 4922 | + u64_stats_update_begin(&txq_stats->q_syncp); | |
| 4923 | + u64_stats_inc(&txq_stats->q.tx_set_ic_bit); | |
| 4924 | + u64_stats_update_end(&txq_stats->q_syncp); | |
| 4927 | 4925 | } |
| 4928 | 4926 | |
| 4929 | 4927 | stmmac_enable_dma_transmission(priv, priv->ioaddr); |
| @@ -5073,7 +5071,6 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, · 143 unmodified lines | ||
| 5073 | 5071 | unsigned int len = xdp->data_end - xdp->data; |
| 5074 | 5072 | enum pkt_hash_types hash_type; |
| 5075 | 5073 | int coe = priv->hw->rx_csum; |
| 5076 | − unsigned long flags; | |
| 5077 | 5074 | struct sk_buff *skb; |
| 5078 | 5075 | u32 hash; |
| 5079 | 5076 | |
| @@ -5103,10 +5100,10 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, · 23 unmodified lines | ||
| 5103 | 5100 | skb_record_rx_queue(skb, queue); |
| 5104 | 5101 | napi_gro_receive(&ch->rxtx_napi, skb); |
| 5105 | 5102 | |
| 5106 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5107 | − rxq_stats->rx_pkt_n++; | |
| 5108 | − rxq_stats->rx_bytes += len; | |
| 5109 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5103 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5104 | + u64_stats_inc(&rxq_stats->napi.rx_pkt_n); | |
| 5105 | + u64_stats_add(&rxq_stats->napi.rx_bytes, len); | |
| 5106 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5110 | 5107 | } |
| 5111 | 5108 | |
| 5112 | 5109 | static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget) |
| @@ -5188,7 +5185,6 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue) · 75 unmodified lines | ||
| 5188 | 5185 | unsigned int desc_size; |
| 5189 | 5186 | struct bpf_prog *prog; |
| 5190 | 5187 | bool failure = false; |
| 5191 | − unsigned long flags; | |
| 5192 | 5188 | int xdp_status = 0; |
| 5193 | 5189 | int status = 0; |
| 5194 | 5190 | |
| @@ -5343,9 +5339,9 @@ read_again: · 148 unmodified lines | ||
| 5343 | 5339 | |
| 5344 | 5340 | stmmac_finalize_xdp_rx(priv, xdp_status); |
| 5345 | 5341 | |
| 5346 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5347 | − rxq_stats->rx_pkt_n += count; | |
| 5348 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5342 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5343 | + u64_stats_add(&rxq_stats->napi.rx_pkt_n, count); | |
| 5344 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5349 | 5345 | |
| 5350 | 5346 | priv->xstats.rx_dropped += rx_dropped; |
| 5351 | 5347 | priv->xstats.rx_errors += rx_errors; |
| @@ -5383,7 +5379,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) · 31 unmodified lines | ||
| 5383 | 5379 | unsigned int desc_size; |
| 5384 | 5380 | struct sk_buff *skb = NULL; |
| 5385 | 5381 | struct stmmac_xdp_buff ctx; |
| 5386 | − unsigned long flags; | |
| 5387 | 5382 | int xdp_status = 0; |
| 5388 | 5383 | int buf_sz; |
| 5389 | 5384 | |
| @@ -5643,11 +5638,11 @@ drain_data: · 253 unmodified lines | ||
| 5643 | 5638 | |
| 5644 | 5639 | stmmac_rx_refill(priv, queue); |
| 5645 | 5640 | |
| 5646 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5647 | − rxq_stats->rx_packets += rx_packets; | |
| 5648 | − rxq_stats->rx_bytes += rx_bytes; | |
| 5649 | − rxq_stats->rx_pkt_n += count; | |
| 5650 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5641 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5642 | + u64_stats_add(&rxq_stats->napi.rx_packets, rx_packets); | |
| 5643 | + u64_stats_add(&rxq_stats->napi.rx_bytes, rx_bytes); | |
| 5644 | + u64_stats_add(&rxq_stats->napi.rx_pkt_n, count); | |
| 5645 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5651 | 5646 | |
| 5652 | 5647 | priv->xstats.rx_dropped += rx_dropped; |
| 5653 | 5648 | priv->xstats.rx_errors += rx_errors; |
| @@ -5662,13 +5657,12 @@ static int stmmac_napi_poll_rx(struct napi_struct *napi, int budget) · 8 unmodified lines | ||
| 5662 | 5657 | struct stmmac_priv *priv = ch->priv_data; |
| 5663 | 5658 | struct stmmac_rxq_stats *rxq_stats; |
| 5664 | 5659 | u32 chan = ch->index; |
| 5665 | − unsigned long flags; | |
| 5666 | 5660 | int work_done; |
| 5667 | 5661 | |
| 5668 | 5662 | rxq_stats = &priv->xstats.rxq_stats[chan]; |
| 5669 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5670 | − rxq_stats->napi_poll++; | |
| 5671 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5663 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5664 | + u64_stats_inc(&rxq_stats->napi.poll); | |
| 5665 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5672 | 5666 | |
| 5673 | 5667 | work_done = stmmac_rx(priv, budget, chan); |
| 5674 | 5668 | if (work_done < budget && napi_complete_done(napi, work_done)) { |
| @@ -5690,13 +5684,12 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget) · 15 unmodified lines | ||
| 5690 | 5684 | struct stmmac_txq_stats *txq_stats; |
| 5691 | 5685 | bool pending_packets = false; |
| 5692 | 5686 | u32 chan = ch->index; |
| 5693 | − unsigned long flags; | |
| 5694 | 5687 | int work_done; |
| 5695 | 5688 | |
| 5696 | 5689 | txq_stats = &priv->xstats.txq_stats[chan]; |
| 5697 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 5698 | − txq_stats->napi_poll++; | |
| 5699 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 5690 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 5691 | + u64_stats_inc(&txq_stats->napi.poll); | |
| 5692 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 5700 | 5693 | |
| 5701 | 5694 | work_done = stmmac_tx_clean(priv, budget, chan, &pending_packets); |
| 5702 | 5695 | work_done = min(work_done, budget); |
| @@ -5726,17 +5719,16 @@ static int stmmac_napi_poll_rxtx(struct napi_struct *napi, int budget) · 23 unmodified lines | ||
| 5726 | 5719 | struct stmmac_rxq_stats *rxq_stats; |
| 5727 | 5720 | struct stmmac_txq_stats *txq_stats; |
| 5728 | 5721 | u32 chan = ch->index; |
| 5729 | − unsigned long flags; | |
| 5730 | 5722 | |
| 5731 | 5723 | rxq_stats = &priv->xstats.rxq_stats[chan]; |
| 5732 | − flags = u64_stats_update_begin_irqsave(&rxq_stats->syncp); | |
| 5733 | − rxq_stats->napi_poll++; | |
| 5734 | − u64_stats_update_end_irqrestore(&rxq_stats->syncp, flags); | |
| 5724 | + u64_stats_update_begin(&rxq_stats->napi_syncp); | |
| 5725 | + u64_stats_inc(&rxq_stats->napi.poll); | |
| 5726 | + u64_stats_update_end(&rxq_stats->napi_syncp); | |
| 5735 | 5727 | |
| 5736 | 5728 | txq_stats = &priv->xstats.txq_stats[chan]; |
| 5737 | − flags = u64_stats_update_begin_irqsave(&txq_stats->syncp); | |
| 5738 | − txq_stats->napi_poll++; | |
| 5739 | − u64_stats_update_end_irqrestore(&txq_stats->syncp, flags); | |
| 5729 | + u64_stats_update_begin(&txq_stats->napi_syncp); | |
| 5730 | + u64_stats_inc(&txq_stats->napi.poll); | |
| 5731 | + u64_stats_update_end(&txq_stats->napi_syncp); | |
| 5740 | 5732 | |
| 5741 | 5733 | tx_done = stmmac_tx_clean(priv, budget, chan, &tx_pending_packets); |
| 5742 | 5734 | tx_done = min(tx_done, budget); |
| @@ -7062,10 +7054,13 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 · 1319 unmodified lines | ||
| 7062 | 7054 | u64 tx_bytes; |
| 7063 | 7055 | |
| 7064 | 7056 | do { |
| 7065 | − start = u64_stats_fetch_begin(&txq_stats->syncp); | |
| 7066 | − tx_packets = txq_stats->tx_packets; | |
| 7067 | − tx_bytes = txq_stats->tx_bytes; | |
| 7068 | − } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); | |
| 7057 | + start = u64_stats_fetch_begin(&txq_stats->q_syncp); | |
| 7058 | + tx_bytes = u64_stats_read(&txq_stats->q.tx_bytes); | |
| 7059 | + } while (u64_stats_fetch_retry(&txq_stats->q_syncp, start)); | |
| 7060 | + do { | |
| 7061 | + start = u64_stats_fetch_begin(&txq_stats->napi_syncp); | |
| 7062 | + tx_packets = u64_stats_read(&txq_stats->napi.tx_packets); | |
| 7063 | + } while (u64_stats_fetch_retry(&txq_stats->napi_syncp, start)); | |
| 7069 | 7064 | |
| 7070 | 7065 | stats->tx_packets += tx_packets; |
| 7071 | 7066 | stats->tx_bytes += tx_bytes; |
| @@ -7077,10 +7072,10 @@ static void stmmac_get_stats64(struct net_device *dev, struct rtnl_link_stats64 · 5 unmodified lines | ||
| 7077 | 7072 | u64 rx_bytes; |
| 7078 | 7073 | |
| 7079 | 7074 | do { |
| 7080 | − start = u64_stats_fetch_begin(&rxq_stats->syncp); | |
| 7081 | − rx_packets = rxq_stats->rx_packets; | |
| 7082 | − rx_bytes = rxq_stats->rx_bytes; | |
| 7083 | − } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); | |
| 7075 | + start = u64_stats_fetch_begin(&rxq_stats->napi_syncp); | |
| 7076 | + rx_packets = u64_stats_read(&rxq_stats->napi.rx_packets); | |
| 7077 | + rx_bytes = u64_stats_read(&rxq_stats->napi.rx_bytes); | |
| 7078 | + } while (u64_stats_fetch_retry(&rxq_stats->napi_syncp, start)); | |
| 7084 | 7079 | |
| 7085 | 7080 | stats->rx_packets += rx_packets; |
| 7086 | 7081 | stats->rx_bytes += rx_bytes; |
| @@ -7474,9 +7469,16 @@ int stmmac_dvr_probe(struct device *device, · 387 unmodified lines | ||
| 7474 | 7469 | priv->dev = ndev; |
| 7475 | 7470 | |
| 7476 | 7471 | for (i = 0; i < MTL_MAX_RX_QUEUES; i++) |
| 7477 | − u64_stats_init(&priv->xstats.rxq_stats[i].syncp); | |
| 7478 | − for (i = 0; i < MTL_MAX_TX_QUEUES; i++) | |
| 7479 | − u64_stats_init(&priv->xstats.txq_stats[i].syncp); | |
| 7472 | + u64_stats_init(&priv->xstats.rxq_stats[i].napi_syncp); | |
| 7473 | + for (i = 0; i < MTL_MAX_TX_QUEUES; i++) { | |
| 7474 | + u64_stats_init(&priv->xstats.txq_stats[i].q_syncp); | |
| 7475 | + u64_stats_init(&priv->xstats.txq_stats[i].napi_syncp); | |
| 7476 | + } | |
| 7477 | + | |
| 7478 | + priv->xstats.pcpu_stats = | |
| 7479 | + devm_netdev_alloc_pcpu_stats(device, struct stmmac_pcpu_stats); | |
| 7480 | + if (!priv->xstats.pcpu_stats) | |
| 7481 | + return -ENOMEM; | |
| 7480 | 7482 | |
| 7481 | 7483 | stmmac_set_ethtool_ops(ndev); |
| 7482 | 7484 | priv->pause = pause; |
| @@ -7542,6 +7544,9 @@ int stmmac_dvr_probe(struct device *device, · 59 unmodified lines | ||
| 7542 | 7544 | dev_err(priv->device, "unable to bring out of ahb reset: %pe\n", |
| 7543 | 7545 | ERR_PTR(ret)); |
| 7544 | 7546 | |
| 7547 | + /* Wait a bit for the reset to take effect */ | |
| 7548 | + udelay(10); | |
| 7549 | + | |
| 7545 | 7550 | /* Init MAC and get the capabilities */ |
| 7546 | 7551 | ret = stmmac_hw_init(priv); |
| 7547 | 7552 | if (ret) |
| @@ -631,6 +631,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) · 630 unmodified lines | ||
| 631 | 631 | } |
| 632 | 632 | } |
| 633 | 633 | |
| 634 | + phy->mac_managed_pm = true; | |
| 635 | + | |
| 634 | 636 | slave->phy = phy; |
| 635 | 637 | |
| 636 | 638 | phy_attached_info(slave->phy); |
| @@ -773,6 +773,9 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) · 772 unmodified lines | ||
| 773 | 773 | slave->slave_num); |
| 774 | 774 | return; |
| 775 | 775 | } |
| 776 | + | |
| 777 | + phy->mac_managed_pm = true; | |
| 778 | + | |
| 776 | 779 | slave->phy = phy; |
| 777 | 780 | |
| 778 | 781 | phy_attached_info(slave->phy); |
| @@ -221,21 +221,25 @@ static int fjes_hw_setup(struct fjes_hw *hw) · 220 unmodified lines | ||
| 221 | 221 | |
| 222 | 222 | mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid); |
| 223 | 223 | hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL); |
| 224 | − if (!(hw->hw_info.req_buf)) | |
| 225 | − return -ENOMEM; | |
| 224 | + if (!(hw->hw_info.req_buf)) { | |
| 225 | + result = -ENOMEM; | |
| 226 | + goto free_ep_info; | |
| 227 | + } | |
| 226 | 228 | |
| 227 | 229 | hw->hw_info.req_buf_size = mem_size; |
| 228 | 230 | |
| 229 | 231 | mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid); |
| 230 | 232 | hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL); |
| 231 | − if (!(hw->hw_info.res_buf)) | |
| 232 | − return -ENOMEM; | |
| 233 | + if (!(hw->hw_info.res_buf)) { | |
| 234 | + result = -ENOMEM; | |
| 235 | + goto free_req_buf; | |
| 236 | + } | |
| 233 | 237 | |
| 234 | 238 | hw->hw_info.res_buf_size = mem_size; |
| 235 | 239 | |
| 236 | 240 | result = fjes_hw_alloc_shared_status_region(hw); |
| 237 | 241 | if (result) |
| 238 | − return result; | |
| 242 | + goto free_res_buf; | |
| 239 | 243 | |
| 240 | 244 | hw->hw_info.buffer_share_bit = 0; |
| 241 | 245 | hw->hw_info.buffer_unshare_reserve_bit = 0; |
| @@ -246,11 +250,11 @@ static int fjes_hw_setup(struct fjes_hw *hw) · 4 unmodified lines | ||
| 246 | 250 | |
| 247 | 251 | result = fjes_hw_alloc_epbuf(&buf_pair->tx); |
| 248 | 252 | if (result) |
| 249 | − return result; | |
| 253 | + goto free_epbuf; | |
| 250 | 254 | |
| 251 | 255 | result = fjes_hw_alloc_epbuf(&buf_pair->rx); |
| 252 | 256 | if (result) |
| 253 | − return result; | |
| 257 | + goto free_epbuf; | |
| 254 | 258 | |
| 255 | 259 | spin_lock_irqsave(&hw->rx_status_lock, flags); |
| 256 | 260 | fjes_hw_setup_epbuf(&buf_pair->tx, mac, |
| @@ -273,6 +277,25 @@ static int fjes_hw_setup(struct fjes_hw *hw) · 16 unmodified lines | ||
| 273 | 277 | fjes_hw_init_command_registers(hw, ¶m); |
| 274 | 278 | |
| 275 | 279 | return 0; |
| 280 | + | |
| 281 | +free_epbuf: | |
| 282 | + for (epidx = 0; epidx < hw->max_epid ; epidx++) { | |
| 283 | + if (epidx == hw->my_epid) | |
| 284 | + continue; | |
| 285 | + fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx); | |
| 286 | + fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx); | |
| 287 | + } | |
| 288 | + fjes_hw_free_shared_status_region(hw); | |
| 289 | +free_res_buf: | |
| 290 | + kfree(hw->hw_info.res_buf); | |
| 291 | + hw->hw_info.res_buf = NULL; | |
| 292 | +free_req_buf: | |
| 293 | + kfree(hw->hw_info.req_buf); | |
| 294 | + hw->hw_info.req_buf = NULL; | |
| 295 | +free_ep_info: | |
| 296 | + kfree(hw->ep_shm_info); | |
| 297 | + hw->ep_shm_info = NULL; | |
| 298 | + return result; | |
| 276 | 299 | } |
| 277 | 300 | |
| 278 | 301 | static void fjes_hw_cleanup(struct fjes_hw *hw) |
| @@ -708,7 +708,10 @@ void netvsc_device_remove(struct hv_device *device) · 707 unmodified lines | ||
| 708 | 708 | /* Disable NAPI and disassociate its context from the device. */ |
| 709 | 709 | for (i = 0; i < net_device->num_chn; i++) { |
| 710 | 710 | /* See also vmbus_reset_channel_cb(). */ |
| 711 | − napi_disable(&net_device->chan_table[i].napi); | |
| 711 | + /* only disable enabled NAPI channel */ | |
| 712 | + if (i < ndev->real_num_rx_queues) | |
| 713 | + napi_disable(&net_device->chan_table[i].napi); | |
| 714 | + | |
| 712 | 715 | netif_napi_del(&net_device->chan_table[i].napi); |
| 713 | 716 | } |
| 714 | 717 | |
| @@ -42,9 +42,13 @@ · 41 unmodified lines | ||
| 42 | 42 | #define LINKCHANGE_INT (2 * HZ) |
| 43 | 43 | #define VF_TAKEOVER_INT (HZ / 10) |
| 44 | 44 | |
| 45 | +/* Macros to define the context of vf registration */ | |
| 46 | +#define VF_REG_IN_PROBE 1 | |
| 47 | +#define VF_REG_IN_NOTIFIER 2 | |
| 48 | + | |
| 45 | 49 | static unsigned int ring_size __ro_after_init = 128; |
| 46 | 50 | module_param(ring_size, uint, 0444); |
| 47 | −MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); | |
| 51 | +MODULE_PARM_DESC(ring_size, "Ring buffer size (# of 4K pages)"); | |
| 48 | 52 | unsigned int netvsc_ring_bytes __ro_after_init; |
| 49 | 53 | |
| 50 | 54 | static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | |
| @@ -2185,7 +2189,7 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb) · 2134 unmodified lines | ||
| 2185 | 2189 | } |
| 2186 | 2190 | |
| 2187 | 2191 | static int netvsc_vf_join(struct net_device *vf_netdev, |
| 2188 | − struct net_device *ndev) | |
| 2192 | + struct net_device *ndev, int context) | |
| 2189 | 2193 | { |
| 2190 | 2194 | struct net_device_context *ndev_ctx = netdev_priv(ndev); |
| 2191 | 2195 | int ret; |
| @@ -2208,7 +2212,11 @@ static int netvsc_vf_join(struct net_device *vf_netdev, · 16 unmodified lines | ||
| 2208 | 2212 | goto upper_link_failed; |
| 2209 | 2213 | } |
| 2210 | 2214 | |
| 2211 | − schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); | |
| 2215 | + /* If this registration is called from probe context vf_takeover | |
| 2216 | + * is taken care of later in probe itself. | |
| 2217 | + */ | |
| 2218 | + if (context == VF_REG_IN_NOTIFIER) | |
| 2219 | + schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT); | |
| 2212 | 2220 | |
| 2213 | 2221 | call_netdevice_notifiers(NETDEV_JOIN, vf_netdev); |
| 2214 | 2222 | |
| @@ -2346,7 +2354,7 @@ static int netvsc_prepare_bonding(struct net_device *vf_netdev) · 131 unmodified lines | ||
| 2346 | 2354 | return NOTIFY_DONE; |
| 2347 | 2355 | } |
| 2348 | 2356 | |
| 2349 | −static int netvsc_register_vf(struct net_device *vf_netdev) | |
| 2357 | +static int netvsc_register_vf(struct net_device *vf_netdev, int context) | |
| 2350 | 2358 | { |
| 2351 | 2359 | struct net_device_context *net_device_ctx; |
| 2352 | 2360 | struct netvsc_device *netvsc_dev; |
| @@ -2386,7 +2394,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev) · 33 unmodified lines | ||
| 2386 | 2394 | |
| 2387 | 2395 | netdev_info(ndev, "VF registering: %s\n", vf_netdev->name); |
| 2388 | 2396 | |
| 2389 | − if (netvsc_vf_join(vf_netdev, ndev) != 0) | |
| 2397 | + if (netvsc_vf_join(vf_netdev, ndev, context) != 0) | |
| 2390 | 2398 | return NOTIFY_DONE; |
| 2391 | 2399 | |
| 2392 | 2400 | dev_hold(vf_netdev); |
| @@ -2484,10 +2492,31 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev) · 91 unmodified lines | ||
| 2484 | 2492 | return NOTIFY_OK; |
| 2485 | 2493 | } |
| 2486 | 2494 | |
| 2495 | +static int check_dev_is_matching_vf(struct net_device *event_ndev) | |
| 2496 | +{ | |
| 2497 | + /* Skip NetVSC interfaces */ | |
| 2498 | + if (event_ndev->netdev_ops == &device_ops) | |
| 2499 | + return -ENODEV; | |
| 2500 | + | |
| 2501 | + /* Avoid non-Ethernet type devices */ | |
| 2502 | + if (event_ndev->type != ARPHRD_ETHER) | |
| 2503 | + return -ENODEV; | |
| 2504 | + | |
| 2505 | + /* Avoid Vlan dev with same MAC registering as VF */ | |
| 2506 | + if (is_vlan_dev(event_ndev)) | |
| 2507 | + return -ENODEV; | |
| 2508 | + | |
| 2509 | + /* Avoid Bonding master dev with same MAC registering as VF */ | |
| 2510 | + if (netif_is_bond_master(event_ndev)) | |
| 2511 | + return -ENODEV; | |
| 2512 | + | |
| 2513 | + return 0; | |
| 2514 | +} | |
| 2515 | + | |
| 2487 | 2516 | static int netvsc_probe(struct hv_device *dev, |
| 2488 | 2517 | const struct hv_vmbus_device_id *dev_id) |
| 2489 | 2518 | { |
| 2490 | − struct net_device *net = NULL; | |
| 2519 | + struct net_device *net = NULL, *vf_netdev; | |
| 2491 | 2520 | struct net_device_context *net_device_ctx; |
| 2492 | 2521 | struct netvsc_device_info *device_info = NULL; |
| 2493 | 2522 | struct netvsc_device *nvdev; |
| @@ -2599,6 +2628,30 @@ static int netvsc_probe(struct hv_device *dev, · 105 unmodified lines | ||
| 2599 | 2628 | } |
| 2600 | 2629 | |
| 2601 | 2630 | list_add(&net_device_ctx->list, &netvsc_dev_list); |
| 2631 | + | |
| 2632 | + /* When the hv_netvsc driver is unloaded and reloaded, the | |
| 2633 | + * NET_DEVICE_REGISTER for the vf device is replayed before probe | |
| 2634 | + * is complete. This is because register_netdevice_notifier() gets | |
| 2635 | + * registered before vmbus_driver_register() so that callback func | |
| 2636 | + * is set before probe and we don't miss events like NETDEV_POST_INIT | |
| 2637 | + * So, in this section we try to register the matching vf device that | |
| 2638 | + * is present as a netdevice, knowing that its register call is not | |
| 2639 | + * processed in the netvsc_netdev_notifier(as probing is progress and | |
| 2640 | + * get_netvsc_byslot fails). | |
| 2641 | + */ | |
| 2642 | + for_each_netdev(dev_net(net), vf_netdev) { | |
| 2643 | + ret = check_dev_is_matching_vf(vf_netdev); | |
| 2644 | + if (ret != 0) | |
| 2645 | + continue; | |
| 2646 | + | |
| 2647 | + if (net != get_netvsc_byslot(vf_netdev)) | |
| 2648 | + continue; | |
| 2649 | + | |
| 2650 | + netvsc_prepare_bonding(vf_netdev); | |
| 2651 | + netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE); | |
| 2652 | + __netvsc_vf_setup(net, vf_netdev); | |
| 2653 | + break; | |
| 2654 | + } | |
| 2602 | 2655 | rtnl_unlock(); |
| 2603 | 2656 | |
| 2604 | 2657 | netvsc_devinfo_put(device_info); |
| @@ -2754,28 +2807,17 @@ static int netvsc_netdev_event(struct notifier_block *this, · 149 unmodified lines | ||
| 2754 | 2807 | unsigned long event, void *ptr) |
| 2755 | 2808 | { |
| 2756 | 2809 | struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); |
| 2810 | + int ret = 0; | |
| 2757 | 2811 | |
| 2758 | − /* Skip our own events */ | |
| 2759 | − if (event_dev->netdev_ops == &device_ops) | |
| 2760 | − return NOTIFY_DONE; | |
| 2761 | − | |
| 2762 | − /* Avoid non-Ethernet type devices */ | |
| 2763 | − if (event_dev->type != ARPHRD_ETHER) | |
| 2764 | − return NOTIFY_DONE; | |
| 2765 | − | |
| 2766 | − /* Avoid Vlan dev with same MAC registering as VF */ | |
| 2767 | − if (is_vlan_dev(event_dev)) | |
| 2768 | − return NOTIFY_DONE; | |
| 2769 | − | |
| 2770 | − /* Avoid Bonding master dev with same MAC registering as VF */ | |
| 2771 | − if (netif_is_bond_master(event_dev)) | |
| 2812 | + ret = check_dev_is_matching_vf(event_dev); | |
| 2813 | + if (ret != 0) | |
| 2772 | 2814 | return NOTIFY_DONE; |
| 2773 | 2815 | |
| 2774 | 2816 | switch (event) { |
| 2775 | 2817 | case NETDEV_POST_INIT: |
| 2776 | 2818 | return netvsc_prepare_bonding(event_dev); |
| 2777 | 2819 | case NETDEV_REGISTER: |
| 2778 | − return netvsc_register_vf(event_dev); | |
| 2820 | + return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER); | |
| 2779 | 2821 | case NETDEV_UNREGISTER: |
| 2780 | 2822 | return netvsc_unregister_vf(event_dev); |
| 2781 | 2823 | case NETDEV_UP: |
| @@ -2807,7 +2849,7 @@ static int __init netvsc_drv_init(void) · 25 unmodified lines | ||
| 2807 | 2849 | pr_info("Increased ring_size to %u (min allowed)\n", |
| 2808 | 2850 | ring_size); |
| 2809 | 2851 | } |
| 2810 | − netvsc_ring_bytes = ring_size * PAGE_SIZE; | |
| 2852 | + netvsc_ring_bytes = VMBUS_RING_SIZE(ring_size * 4096); | |
| 2811 | 2853 | |
| 2812 | 2854 | register_netdevice_notifier(&netvsc_netdev_notifier); |
| 2813 | 2855 | |
| @@ -607,11 +607,26 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, · 606 unmodified lines | ||
| 607 | 607 | return ERR_PTR(-EINVAL); |
| 608 | 608 | } |
| 609 | 609 | |
| 610 | − ret = skb_ensure_writable_head_tail(skb, dev); | |
| 611 | − if (unlikely(ret < 0)) { | |
| 612 | − macsec_txsa_put(tx_sa); | |
| 613 | − kfree_skb(skb); | |
| 614 | − return ERR_PTR(ret); | |
| 610 | + if (unlikely(skb_headroom(skb) < MACSEC_NEEDED_HEADROOM || | |
| 611 | + skb_tailroom(skb) < MACSEC_NEEDED_TAILROOM)) { | |
| 612 | + struct sk_buff *nskb = skb_copy_expand(skb, | |
| 613 | + MACSEC_NEEDED_HEADROOM, | |
| 614 | + MACSEC_NEEDED_TAILROOM, | |
| 615 | + GFP_ATOMIC); | |
| 616 | + if (likely(nskb)) { | |
| 617 | + consume_skb(skb); | |
| 618 | + skb = nskb; | |
| 619 | + } else { | |
| 620 | + macsec_txsa_put(tx_sa); | |
| 621 | + kfree_skb(skb); | |
| 622 | + return ERR_PTR(-ENOMEM); | |
| 623 | + } | |
| 624 | + } else { | |
| 625 | + skb = skb_unshare(skb, GFP_ATOMIC); | |
| 626 | + if (!skb) { | |
| 627 | + macsec_txsa_put(tx_sa); | |
| 628 | + return ERR_PTR(-ENOMEM); | |
| 629 | + } | |
| 615 | 630 | } |
| 616 | 631 | |
| 617 | 632 | unprotected_len = skb->len; |
| @@ -835,14 +835,14 @@ static void nsim_dev_trap_report_work(struct work_struct *work) · 834 unmodified lines | ||
| 835 | 835 | trap_report_dw.work); |
| 836 | 836 | nsim_dev = nsim_trap_data->nsim_dev; |
| 837 | 837 | |
| 838 | − /* For each running port and enabled packet trap, generate a UDP | |
| 839 | − * packet with a random 5-tuple and report it. | |
| 840 | − */ | |
| 841 | 838 | if (!devl_trylock(priv_to_devlink(nsim_dev))) { |
| 842 | − schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 0); | |
| 839 | + schedule_delayed_work(&nsim_dev->trap_data->trap_report_dw, 1); | |
| 843 | 840 | return; |
| 844 | 841 | } |
| 845 | 842 | |
| 843 | + /* For each running port and enabled packet trap, generate a UDP | |
| 844 | + * packet with a random 5-tuple and report it. | |
| 845 | + */ | |
| 846 | 846 | list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) { |
| 847 | 847 | if (!netif_running(nsim_dev_port->ns->netdev)) |
| 848 | 848 | continue; |
| @@ -489,7 +489,7 @@ static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, · 488 unmodified lines | ||
| 489 | 489 | u16 reg, val; |
| 490 | 490 | |
| 491 | 491 | if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) |
| 492 | − bias = -2; | |
| 492 | + bias = -1; | |
| 493 | 493 | |
| 494 | 494 | val = clamp_val(bias + tx_r50_cal_val, 0, 63); |
| 495 | 495 | |
| @@ -705,6 +705,11 @@ restore: · 209 unmodified lines | ||
| 705 | 705 | static void mt798x_phy_common_finetune(struct phy_device *phydev) |
| 706 | 706 | { |
| 707 | 707 | phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); |
| 708 | + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ | |
| 709 | + __phy_write(phydev, 0x11, 0xc71); | |
| 710 | + __phy_write(phydev, 0x12, 0xc); | |
| 711 | + __phy_write(phydev, 0x10, 0x8fae); | |
| 712 | + | |
| 708 | 713 | /* EnabRandUpdTrig = 1 */ |
| 709 | 714 | __phy_write(phydev, 0x11, 0x2f00); |
| 710 | 715 | __phy_write(phydev, 0x12, 0xe); |
| @@ -715,15 +720,56 @@ static void mt798x_phy_common_finetune(struct phy_device *phydev) · 4 unmodified lines | ||
| 715 | 720 | __phy_write(phydev, 0x12, 0x0); |
| 716 | 721 | __phy_write(phydev, 0x10, 0x83aa); |
| 717 | 722 | |
| 718 | − /* TrFreeze = 0 */ | |
| 723 | + /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */ | |
| 724 | + __phy_write(phydev, 0x11, 0x240); | |
| 725 | + __phy_write(phydev, 0x12, 0x0); | |
| 726 | + __phy_write(phydev, 0x10, 0x9680); | |
| 727 | + | |
| 728 | + /* TrFreeze = 0 (mt7988 default) */ | |
| 719 | 729 | __phy_write(phydev, 0x11, 0x0); |
| 720 | 730 | __phy_write(phydev, 0x12, 0x0); |
| 721 | 731 | __phy_write(phydev, 0x10, 0x9686); |
| 722 | 732 | |
| 733 | + /* SSTrKp100 = 5 */ | |
| 734 | + /* SSTrKf100 = 6 */ | |
| 735 | + /* SSTrKp1000Mas = 5 */ | |
| 736 | + /* SSTrKf1000Mas = 6 */ | |
| 723 | 737 | /* SSTrKp1000Slv = 5 */ |
| 738 | + /* SSTrKf1000Slv = 6 */ | |
| 724 | 739 | __phy_write(phydev, 0x11, 0xbaef); |
| 725 | 740 | __phy_write(phydev, 0x12, 0x2e); |
| 726 | 741 | __phy_write(phydev, 0x10, 0x968c); |
| 742 | + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); | |
| 743 | +} | |
| 744 | + | |
| 745 | +static void mt7981_phy_finetune(struct phy_device *phydev) | |
| 746 | +{ | |
| 747 | + u16 val[8] = { 0x01ce, 0x01c1, | |
| 748 | + 0x020f, 0x0202, | |
| 749 | + 0x03d0, 0x03c0, | |
| 750 | + 0x0013, 0x0005 }; | |
| 751 | + int i, k; | |
| 752 | + | |
| 753 | + /* 100M eye finetune: | |
| 754 | + * Keep middle level of TX MLT3 shapper as default. | |
| 755 | + * Only change TX MLT3 overshoot level here. | |
| 756 | + */ | |
| 757 | + for (k = 0, i = 1; i < 12; i++) { | |
| 758 | + if (i % 3 == 0) | |
| 759 | + continue; | |
| 760 | + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); | |
| 761 | + } | |
| 762 | + | |
| 763 | + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); | |
| 764 | + /* ResetSyncOffset = 6 */ | |
| 765 | + __phy_write(phydev, 0x11, 0x600); | |
| 766 | + __phy_write(phydev, 0x12, 0x0); | |
| 767 | + __phy_write(phydev, 0x10, 0x8fc0); | |
| 768 | + | |
| 769 | + /* VgaDecRate = 1 */ | |
| 770 | + __phy_write(phydev, 0x11, 0x4c2a); | |
| 771 | + __phy_write(phydev, 0x12, 0x3e); | |
| 772 | + __phy_write(phydev, 0x10, 0x8fa4); | |
| 727 | 773 | |
| 728 | 774 | /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, |
| 729 | 775 | * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 |
| @@ -738,7 +784,7 @@ static void mt798x_phy_common_finetune(struct phy_device *phydev) · 8 unmodified lines | ||
| 738 | 784 | __phy_write(phydev, 0x10, 0x8ec0); |
| 739 | 785 | phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); |
| 740 | 786 | |
| 741 | − /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ | |
| 787 | + /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */ | |
| 742 | 788 | phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, |
| 743 | 789 | MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, |
| 744 | 790 | BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); |
| @@ -771,48 +817,6 @@ static void mt798x_phy_common_finetune(struct phy_device *phydev) · 26 unmodified lines | ||
| 771 | 817 | phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); |
| 772 | 818 | } |
| 773 | 819 | |
| 774 | −static void mt7981_phy_finetune(struct phy_device *phydev) | |
| 775 | −{ | |
| 776 | − u16 val[8] = { 0x01ce, 0x01c1, | |
| 777 | − 0x020f, 0x0202, | |
| 778 | − 0x03d0, 0x03c0, | |
| 779 | − 0x0013, 0x0005 }; | |
| 780 | − int i, k; | |
| 781 | − | |
| 782 | − /* 100M eye finetune: | |
| 783 | − * Keep middle level of TX MLT3 shapper as default. | |
| 784 | − * Only change TX MLT3 overshoot level here. | |
| 785 | − */ | |
| 786 | − for (k = 0, i = 1; i < 12; i++) { | |
| 787 | − if (i % 3 == 0) | |
| 788 | − continue; | |
| 789 | − phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); | |
| 790 | − } | |
| 791 | − | |
| 792 | − phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); | |
| 793 | − /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ | |
| 794 | − __phy_write(phydev, 0x11, 0xc71); | |
| 795 | − __phy_write(phydev, 0x12, 0xc); | |
| 796 | − __phy_write(phydev, 0x10, 0x8fae); | |
| 797 | − | |
| 798 | − /* ResetSyncOffset = 6 */ | |
| 799 | − __phy_write(phydev, 0x11, 0x600); | |
| 800 | − __phy_write(phydev, 0x12, 0x0); | |
| 801 | − __phy_write(phydev, 0x10, 0x8fc0); | |
| 802 | − | |
| 803 | − /* VgaDecRate = 1 */ | |
| 804 | − __phy_write(phydev, 0x11, 0x4c2a); | |
| 805 | − __phy_write(phydev, 0x12, 0x3e); | |
| 806 | − __phy_write(phydev, 0x10, 0x8fa4); | |
| 807 | − | |
| 808 | − /* FfeUpdGainForce = 4 */ | |
| 809 | − __phy_write(phydev, 0x11, 0x240); | |
| 810 | − __phy_write(phydev, 0x12, 0x0); | |
| 811 | − __phy_write(phydev, 0x10, 0x9680); | |
| 812 | − | |
| 813 | − phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); | |
| 814 | −} | |
| 815 | − | |
| 816 | 820 | static void mt7988_phy_finetune(struct phy_device *phydev) |
| 817 | 821 | { |
| 818 | 822 | u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, |
| @@ -827,17 +831,7 @@ static void mt7988_phy_finetune(struct phy_device *phydev) · 8 unmodified lines | ||
| 827 | 831 | /* TCT finetune */ |
| 828 | 832 | phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); |
| 829 | 833 | |
| 830 | − /* Disable TX power saving */ | |
| 831 | − phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, | |
| 832 | − MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); | |
| 833 | − | |
| 834 | 834 | phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); |
| 835 | − | |
| 836 | − /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */ | |
| 837 | − __phy_write(phydev, 0x11, 0x671); | |
| 838 | − __phy_write(phydev, 0x12, 0xc); | |
| 839 | − __phy_write(phydev, 0x10, 0x8fae); | |
| 840 | − | |
| 841 | 835 | /* ResetSyncOffset = 5 */ |
| 842 | 836 | __phy_write(phydev, 0x11, 0x500); |
| 843 | 837 | __phy_write(phydev, 0x12, 0x0); |
| @@ -845,13 +839,27 @@ static void mt7988_phy_finetune(struct phy_device *phydev) · 1 unmodified line | ||
| 845 | 839 | |
| 846 | 840 | /* VgaDecRate is 1 at default on mt7988 */ |
| 847 | 841 | |
| 848 | − phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); | |
| 842 | + /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7, | |
| 843 | + * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7 | |
| 844 | + */ | |
| 845 | + __phy_write(phydev, 0x11, 0xb90a); | |
| 846 | + __phy_write(phydev, 0x12, 0x6f); | |
| 847 | + __phy_write(phydev, 0x10, 0x8f82); | |
| 848 | + | |
| 849 | + /* RemAckCntLimitCtrl = 1 */ | |
| 850 | + __phy_write(phydev, 0x11, 0xfbba); | |
| 851 | + __phy_write(phydev, 0x12, 0xc3); | |
| 852 | + __phy_write(phydev, 0x10, 0x87f8); | |
| 849 | 853 | |
| 850 | − phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); | |
| 851 | − /* TxClkOffset = 2 */ | |
| 852 | − __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, | |
| 853 | − FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); | |
| 854 | 854 | phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); |
| 855 | + | |
| 856 | + /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */ | |
| 857 | + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, | |
| 858 | + MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, | |
| 859 | + BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa)); | |
| 860 | + | |
| 861 | + /* rg_tr_lpf_cnt_val = 1023 */ | |
| 862 | + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x3ff); | |
| 855 | 863 | } |
| 856 | 864 | |
| 857 | 865 | static void mt798x_phy_eee(struct phy_device *phydev) |
| @@ -884,11 +892,11 @@ static void mt798x_phy_eee(struct phy_device *phydev) · 26 unmodified lines | ||
| 884 | 892 | MTK_PHY_LPI_SLV_SEND_TX_EN, |
| 885 | 893 | FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); |
| 886 | 894 | |
| 887 | − phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, | |
| 888 | − MTK_PHY_LPI_SEND_LOC_TIMER_MASK | | |
| 889 | − MTK_PHY_LPI_TXPCS_LOC_RCV, | |
| 890 | − FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117)); | |
| 895 | + /* Keep MTK_PHY_LPI_SEND_LOC_TIMER as 375 */ | |
| 896 | + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, | |
| 897 | + MTK_PHY_LPI_TXPCS_LOC_RCV); | |
| 891 | 898 | |
| 899 | + /* This also fixes some IoT issues, such as CH340 */ | |
| 892 | 900 | phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, |
| 893 | 901 | MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, |
| 894 | 902 | FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | |
| @@ -922,7 +930,7 @@ static void mt798x_phy_eee(struct phy_device *phydev) · 27 unmodified lines | ||
| 922 | 930 | __phy_write(phydev, 0x12, 0x0); |
| 923 | 931 | __phy_write(phydev, 0x10, 0x9690); |
| 924 | 932 | |
| 925 | − /* REG_EEE_st2TrKf1000 = 3 */ | |
| 933 | + /* REG_EEE_st2TrKf1000 = 2 */ | |
| 926 | 934 | __phy_write(phydev, 0x11, 0x114f); |
| 927 | 935 | __phy_write(phydev, 0x12, 0x2); |
| 928 | 936 | __phy_write(phydev, 0x10, 0x969a); |
| @@ -947,7 +955,7 @@ static void mt798x_phy_eee(struct phy_device *phydev) · 18 unmodified lines | ||
| 947 | 955 | __phy_write(phydev, 0x12, 0x0); |
| 948 | 956 | __phy_write(phydev, 0x10, 0x96b8); |
| 949 | 957 | |
| 950 | − /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */ | |
| 958 | + /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */ | |
| 951 | 959 | __phy_write(phydev, 0x11, 0x1463); |
| 952 | 960 | __phy_write(phydev, 0x12, 0x0); |
| 953 | 961 | __phy_write(phydev, 0x10, 0x96ca); |
| @@ -1459,6 +1467,13 @@ static int mt7988_phy_probe(struct phy_device *phydev) · 505 unmodified lines | ||
| 1459 | 1467 | if (err) |
| 1460 | 1468 | return err; |
| 1461 | 1469 | |
| 1470 | + /* Disable TX power saving at probing to: | |
| 1471 | + * 1. Meet common mode compliance test criteria | |
| 1472 | + * 2. Make sure that TX-VCM calibration works fine | |
| 1473 | + */ | |
| 1474 | + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, | |
| 1475 | + MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); | |
| 1476 | + | |
| 1462 | 1477 | return mt798x_phy_calibration(phydev); |
| 1463 | 1478 | } |
| 1464 | 1479 | |
| @@ -120,6 +120,11 @@ · 119 unmodified lines | ||
| 120 | 120 | */ |
| 121 | 121 | #define LAN8814_1PPM_FORMAT 17179 |
| 122 | 122 | |
| 123 | +#define PTP_RX_VERSION 0x0248 | |
| 124 | +#define PTP_TX_VERSION 0x0288 | |
| 125 | +#define PTP_MAX_VERSION(x) (((x) & GENMASK(7, 0)) << 8) | |
| 126 | +#define PTP_MIN_VERSION(x) ((x) & GENMASK(7, 0)) | |
| 127 | + | |
| 123 | 128 | #define PTP_RX_MOD 0x024F |
| 124 | 129 | #define PTP_RX_MOD_BAD_UDPV4_CHKSUM_FORCE_FCS_DIS_ BIT(3) |
| 125 | 130 | #define PTP_RX_TIMESTAMP_EN 0x024D |
| @@ -3150,6 +3155,12 @@ static void lan8814_ptp_init(struct phy_device *phydev) · 3024 unmodified lines | ||
| 3150 | 3155 | lanphy_write_page_reg(phydev, 5, PTP_TX_PARSE_IP_ADDR_EN, 0); |
| 3151 | 3156 | lanphy_write_page_reg(phydev, 5, PTP_RX_PARSE_IP_ADDR_EN, 0); |
| 3152 | 3157 | |
| 3158 | + /* Disable checking for minorVersionPTP field */ | |
| 3159 | + lanphy_write_page_reg(phydev, 5, PTP_RX_VERSION, | |
| 3160 | + PTP_MAX_VERSION(0xff) | PTP_MIN_VERSION(0x0)); | |
| 3161 | + lanphy_write_page_reg(phydev, 5, PTP_TX_VERSION, | |
| 3162 | + PTP_MAX_VERSION(0xff) | PTP_MIN_VERSION(0x0)); | |
| 3163 | + | |
| 3153 | 3164 | skb_queue_head_init(&ptp_priv->tx_queue); |
| 3154 | 3165 | skb_queue_head_init(&ptp_priv->rx_queue); |
| 3155 | 3166 | INIT_LIST_HEAD(&ptp_priv->rx_ts_list); |
| @@ -460,6 +460,10 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg) · 459 unmodified lines | ||
| 460 | 460 | case PPPIOCSMRU: |
| 461 | 461 | if (get_user(val, p)) |
| 462 | 462 | break; |
| 463 | + if (val > U16_MAX) { | |
| 464 | + err = -EINVAL; | |
| 465 | + break; | |
| 466 | + } | |
| 463 | 467 | if (val < PPP_MRU) |
| 464 | 468 | val = PPP_MRU; |
| 465 | 469 | ap->mru = val; |
| @@ -1630,13 +1630,19 @@ static int tun_xdp_act(struct tun_struct *tun, struct bpf_prog *xdp_prog, · 1629 unmodified lines | ||
| 1630 | 1630 | switch (act) { |
| 1631 | 1631 | case XDP_REDIRECT: |
| 1632 | 1632 | err = xdp_do_redirect(tun->dev, xdp, xdp_prog); |
| 1633 | − if (err) | |
| 1633 | + if (err) { | |
| 1634 | + dev_core_stats_rx_dropped_inc(tun->dev); | |
| 1634 | 1635 | return err; |
| 1636 | + } | |
| 1637 | + dev_sw_netstats_rx_add(tun->dev, xdp->data_end - xdp->data); | |
| 1635 | 1638 | break; |
| 1636 | 1639 | case XDP_TX: |
| 1637 | 1640 | err = tun_xdp_tx(tun->dev, xdp); |
| 1638 | − if (err < 0) | |
| 1641 | + if (err < 0) { | |
| 1642 | + dev_core_stats_rx_dropped_inc(tun->dev); | |
| 1639 | 1643 | return err; |
| 1644 | + } | |
| 1645 | + dev_sw_netstats_rx_add(tun->dev, xdp->data_end - xdp->data); | |
| 1640 | 1646 | break; |
| 1641 | 1647 | case XDP_PASS: |
| 1642 | 1648 | break; |
| @@ -1803,5 +1803,6 @@ static struct usb_driver ar5523_driver = { · 1802 unmodified lines | ||
| 1803 | 1803 | |
| 1804 | 1804 | module_usb_driver(ar5523_driver); |
| 1805 | 1805 | |
| 1806 | +MODULE_DESCRIPTION("Atheros AR5523 wireless driver"); | |
| 1806 | 1807 | MODULE_LICENSE("Dual BSD/GPL"); |
| 1807 | 1808 | MODULE_FIRMWARE(AR5523_FIRMWARE_FILE); |
| @@ -368,10 +368,6 @@ struct ath11k_vif { · 367 unmodified lines | ||
| 368 | 368 | struct ieee80211_chanctx_conf chanctx; |
| 369 | 369 | struct ath11k_arp_ns_offload arp_ns_offload; |
| 370 | 370 | struct ath11k_rekey_data rekey_data; |
| 371 | − | |
| 372 | −#ifdef CONFIG_ATH11K_DEBUGFS | |
| 373 | − struct dentry *debugfs_twt; | |
| 374 | −#endif /* CONFIG_ATH11K_DEBUGFS */ | |
| 375 | 371 | }; |
| 376 | 372 | |
| 377 | 373 | struct ath11k_vif_iter { |
| @@ -1894,35 +1894,30 @@ static const struct file_operations ath11k_fops_twt_resume_dialog = { · 1893 unmodified lines | ||
| 1894 | 1894 | .open = simple_open |
| 1895 | 1895 | }; |
| 1896 | 1896 | |
| 1897 | −void ath11k_debugfs_add_interface(struct ath11k_vif *arvif) | |
| 1897 | +void ath11k_debugfs_op_vif_add(struct ieee80211_hw *hw, | |
| 1898 | + struct ieee80211_vif *vif) | |
| 1898 | 1899 | { |
| 1900 | + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); | |
| 1899 | 1901 | struct ath11k_base *ab = arvif->ar->ab; |
| 1902 | + struct dentry *debugfs_twt; | |
| 1900 | 1903 | |
| 1901 | 1904 | if (arvif->vif->type != NL80211_IFTYPE_AP && |
| 1902 | 1905 | !(arvif->vif->type == NL80211_IFTYPE_STATION && |
| 1903 | 1906 | test_bit(WMI_TLV_SERVICE_STA_TWT, ab->wmi_ab.svc_map))) |
| 1904 | 1907 | return; |
| 1905 | 1908 | |
| 1906 | − arvif->debugfs_twt = debugfs_create_dir("twt", | |
| 1907 | − arvif->vif->debugfs_dir); | |
| 1908 | − debugfs_create_file("add_dialog", 0200, arvif->debugfs_twt, | |
| 1909 | + debugfs_twt = debugfs_create_dir("twt", | |
| 1910 | + arvif->vif->debugfs_dir); | |
| 1911 | + debugfs_create_file("add_dialog", 0200, debugfs_twt, | |
| 1909 | 1912 | arvif, &ath11k_fops_twt_add_dialog); |
| 1910 | 1913 | |
| 1911 | − debugfs_create_file("del_dialog", 0200, arvif->debugfs_twt, | |
| 1914 | + debugfs_create_file("del_dialog", 0200, debugfs_twt, | |
| 1912 | 1915 | arvif, &ath11k_fops_twt_del_dialog); |
| 1913 | 1916 | |
| 1914 | − debugfs_create_file("pause_dialog", 0200, arvif->debugfs_twt, | |
| 1917 | + debugfs_create_file("pause_dialog", 0200, debugfs_twt, | |
| 1915 | 1918 | arvif, &ath11k_fops_twt_pause_dialog); |
| 1916 | 1919 | |
| 1917 | − debugfs_create_file("resume_dialog", 0200, arvif->debugfs_twt, | |
| 1920 | + debugfs_create_file("resume_dialog", 0200, debugfs_twt, | |
| 1918 | 1921 | arvif, &ath11k_fops_twt_resume_dialog); |
| 1919 | 1922 | } |
| 1920 | 1923 | |
| 1921 | −void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif) | |
| 1922 | −{ | |
| 1923 | − if (!arvif->debugfs_twt) | |
| 1924 | − return; | |
| 1925 | − | |
| 1926 | − debugfs_remove_recursive(arvif->debugfs_twt); | |
| 1927 | − arvif->debugfs_twt = NULL; | |
| 1928 | −} | |
| @@ -307,8 +307,8 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar) · 306 unmodified lines | ||
| 307 | 307 | return ar->debug.rx_filter; |
| 308 | 308 | } |
| 309 | 309 | |
| 310 | −void ath11k_debugfs_add_interface(struct ath11k_vif *arvif); | |
| 311 | −void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif); | |
| 310 | +void ath11k_debugfs_op_vif_add(struct ieee80211_hw *hw, | |
| 311 | + struct ieee80211_vif *vif); | |
| 312 | 312 | void ath11k_debugfs_add_dbring_entry(struct ath11k *ar, |
| 313 | 313 | enum wmi_direct_buffer_module id, |
| 314 | 314 | enum ath11k_dbg_dbr_event event, |
| @@ -387,14 +387,6 @@ static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar, · 72 unmodified lines | ||
| 387 | 387 | return 0; |
| 388 | 388 | } |
| 389 | 389 | |
| 390 | −static inline void ath11k_debugfs_add_interface(struct ath11k_vif *arvif) | |
| 391 | −{ | |
| 392 | −} | |
| 393 | − | |
| 394 | −static inline void ath11k_debugfs_remove_interface(struct ath11k_vif *arvif) | |
| 395 | −{ | |
| 396 | −} | |
| 397 | − | |
| 398 | 390 | static inline void |
| 399 | 391 | ath11k_debugfs_add_dbring_entry(struct ath11k *ar, |
| 400 | 392 | enum wmi_direct_buffer_module id, |
| @@ -6756,13 +6756,6 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, · 6755 unmodified lines | ||
| 6756 | 6756 | goto err; |
| 6757 | 6757 | } |
| 6758 | 6758 | |
| 6759 | − /* In the case of hardware recovery, debugfs files are | |
| 6760 | − * not deleted since ieee80211_ops.remove_interface() is | |
| 6761 | − * not invoked. In such cases, try to delete the files. | |
| 6762 | − * These will be re-created later. | |
| 6763 | − */ | |
| 6764 | − ath11k_debugfs_remove_interface(arvif); | |
| 6765 | − | |
| 6766 | 6759 | memset(arvif, 0, sizeof(*arvif)); |
| 6767 | 6760 | |
| 6768 | 6761 | arvif->ar = ar; |
| @@ -6939,8 +6932,6 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, · 170 unmodified lines | ||
| 6939 | 6932 | |
| 6940 | 6933 | ath11k_dp_vdev_tx_attach(ar, arvif); |
| 6941 | 6934 | |
| 6942 | − ath11k_debugfs_add_interface(arvif); | |
| 6943 | − | |
| 6944 | 6935 | if (vif->type != NL80211_IFTYPE_MONITOR && |
| 6945 | 6936 | test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) { |
| 6946 | 6937 | ret = ath11k_mac_monitor_vdev_create(ar); |
| @@ -7056,8 +7047,6 @@ err_vdev_del: · 109 unmodified lines | ||
| 7056 | 7047 | /* Recalc txpower for remaining vdev */ |
| 7057 | 7048 | ath11k_mac_txpower_recalc(ar); |
| 7058 | 7049 | |
| 7059 | − ath11k_debugfs_remove_interface(arvif); | |
| 7060 | − | |
| 7061 | 7050 | /* TODO: recal traffic pause state based on the available vdevs */ |
| 7062 | 7051 | |
| 7063 | 7052 | mutex_unlock(&ar->conf_mutex); |
| @@ -9153,6 +9142,7 @@ static const struct ieee80211_ops ath11k_ops = { · 2089 unmodified lines | ||
| 9153 | 9142 | #endif |
| 9154 | 9143 | |
| 9155 | 9144 | #ifdef CONFIG_ATH11K_DEBUGFS |
| 9145 | + .vif_add_debugfs = ath11k_debugfs_op_vif_add, | |
| 9156 | 9146 | .sta_add_debugfs = ath11k_debugfs_sta_op_add, |
| 9157 | 9147 | #endif |
| 9158 | 9148 | |
| @@ -1685,6 +1685,7 @@ static struct platform_driver wcn36xx_driver = { · 1684 unmodified lines | ||
| 1685 | 1685 | |
| 1686 | 1686 | module_platform_driver(wcn36xx_driver); |
| 1687 | 1687 | |
| 1688 | +MODULE_DESCRIPTION("Qualcomm Atheros WCN3660/3680 wireless driver"); | |
| 1688 | 1689 | MODULE_LICENSE("Dual BSD/GPL"); |
| 1689 | 1690 | MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); |
| 1690 | 1691 | MODULE_FIRMWARE(WLAN_NV_FILE); |
| @@ -20,6 +20,7 @@ static void __exit brcmf_bca_exit(void) · 19 unmodified lines | ||
| 20 | 20 | brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom AP chipsets"); | |
| 23 | 24 | MODULE_LICENSE("Dual BSD/GPL"); |
| 24 | 25 | MODULE_IMPORT_NS(BRCMFMAC); |
| 25 | 26 | |
| @@ -3779,8 +3779,10 @@ static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req, · 3778 unmodified lines | ||
| 3779 | 3779 | if (req->channels[i] == chan) |
| 3780 | 3780 | break; |
| 3781 | 3781 | } |
| 3782 | − if (i == req->n_channels) | |
| 3783 | − req->channels[req->n_channels++] = chan; | |
| 3782 | + if (i == req->n_channels) { | |
| 3783 | + req->n_channels++; | |
| 3784 | + req->channels[i] = chan; | |
| 3785 | + } | |
| 3784 | 3786 | |
| 3785 | 3787 | for (i = 0; i < req->n_ssids; i++) { |
| 3786 | 3788 | if (req->ssids[i].ssid_len == ssid_len && |
| @@ -20,6 +20,7 @@ static void __exit brcmf_cyw_exit(void) · 19 unmodified lines | ||
| 20 | 20 | brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_CYW, THIS_MODULE); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Cypress/Infineon chipsets"); | |
| 23 | 24 | MODULE_LICENSE("Dual BSD/GPL"); |
| 24 | 25 | MODULE_IMPORT_NS(BRCMFMAC); |
| 25 | 26 | |
| @@ -20,6 +20,7 @@ static void __exit brcmf_wcc_exit(void) · 19 unmodified lines | ||
| 20 | 20 | brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | +MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom mobility chipsets"); | |
| 23 | 24 | MODULE_LICENSE("Dual BSD/GPL"); |
| 24 | 25 | MODULE_IMPORT_NS(BRCMFMAC); |
| 25 | 26 | |
| @@ -537,7 +537,7 @@ enum iwl_fw_dbg_config_cmd_type { · 536 unmodified lines | ||
| 537 | 537 | }; /* LDBG_CFG_CMD_TYPE_API_E_VER_1 */ |
| 538 | 538 | |
| 539 | 539 | /* this token disables debug asserts in the firmware */ |
| 540 | −#define IWL_FW_DBG_CONFIG_TOKEN 0x00011301 | |
| 540 | +#define IWL_FW_DBG_CONFIG_TOKEN 0x00010001 | |
| 541 | 541 | |
| 542 | 542 | /** |
| 543 | 543 | * struct iwl_fw_dbg_config_cmd - configure FW debug |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
| 2 | 2 | /* |
| 3 | − * Copyright (C) 2005-2014, 2018-2023 Intel Corporation | |
| 3 | + * Copyright (C) 2005-2014, 2018-2024 Intel Corporation | |
| 4 | 4 | * Copyright (C) 2013-2015 Intel Mobile Communications GmbH |
| 5 | 5 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
| 6 | 6 | */ |
| @@ -19,7 +19,6 @@ · 12 unmodified lines | ||
| 19 | 19 | * @fwrt_ptr: pointer to the buffer coming from fwrt |
| 20 | 20 | * @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the |
| 21 | 21 | * transport's data. |
| 22 | − * @trans_len: length of the valid data in trans_ptr | |
| 23 | 22 | * @fwrt_len: length of the valid data in fwrt_ptr |
| 24 | 23 | */ |
| 25 | 24 | struct iwl_fw_dump_ptrs { |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
| 2 | 2 | /* |
| 3 | − * Copyright (C) 2018-2023 Intel Corporation | |
| 3 | + * Copyright (C) 2018-2024 Intel Corporation | |
| 4 | 4 | */ |
| 5 | 5 | #include <linux/firmware.h> |
| 6 | 6 | #include "iwl-drv.h" |
| @@ -1096,7 +1096,7 @@ static int iwl_dbg_tlv_override_trig_node(struct iwl_fw_runtime *fwrt, · 1089 unmodified lines | ||
| 1096 | 1096 | node_trig = (void *)node_tlv->data; |
| 1097 | 1097 | } |
| 1098 | 1098 | |
| 1099 | − memcpy(node_trig->data + offset, trig->data, trig_data_len); | |
| 1099 | + memcpy((u8 *)node_trig->data + offset, trig->data, trig_data_len); | |
| 1100 | 1100 | node_tlv->length = cpu_to_le32(size); |
| 1101 | 1101 | |
| 1102 | 1102 | if (policy & IWL_FW_INI_APPLY_POLICY_OVERRIDE_CFG) { |
| @@ -128,6 +128,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv) · 127 unmodified lines | ||
| 128 | 128 | kfree(drv->fw.ucode_capa.cmd_versions); |
| 129 | 129 | kfree(drv->fw.phy_integration_ver); |
| 130 | 130 | kfree(drv->trans->dbg.pc_data); |
| 131 | + drv->trans->dbg.pc_data = NULL; | |
| 131 | 132 | |
| 132 | 133 | for (i = 0; i < IWL_UCODE_TYPE_MAX; i++) |
| 133 | 134 | iwl_free_fw_img(drv, drv->fw.img + i); |
| @@ -668,7 +668,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { · 667 unmodified lines | ||
| 668 | 668 | .has_eht = true, |
| 669 | 669 | .eht_cap_elem = { |
| 670 | 670 | .mac_cap_info[0] = |
| 671 | − IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
| 672 | 671 | IEEE80211_EHT_MAC_CAP0_OM_CONTROL | |
| 673 | 672 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | |
| 674 | 673 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2 | |
| @@ -793,7 +792,6 @@ static const struct ieee80211_sband_iftype_data iwl_he_eht_capa[] = { · 118 unmodified lines | ||
| 793 | 792 | .has_eht = true, |
| 794 | 793 | .eht_cap_elem = { |
| 795 | 794 | .mac_cap_info[0] = |
| 796 | − IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
| 797 | 795 | IEEE80211_EHT_MAC_CAP0_OM_CONTROL | |
| 798 | 796 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | |
| 799 | 797 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2, |
| @@ -1020,8 +1018,7 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, · 220 unmodified lines | ||
| 1020 | 1018 | if (CSR_HW_REV_TYPE(trans->hw_rev) == IWL_CFG_MAC_TYPE_GL && |
| 1021 | 1019 | iftype_data->eht_cap.has_eht) { |
| 1022 | 1020 | iftype_data->eht_cap.eht_cap_elem.mac_cap_info[0] &= |
| 1023 | − ~(IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS | | |
| 1024 | − IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | | |
| 1021 | + ~(IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1 | | |
| 1025 | 1022 | IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE2); |
| 1026 | 1023 | iftype_data->eht_cap.eht_cap_elem.phy_cap_info[3] &= |
| 1027 | 1024 | ~(IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO | |
| @@ -1600,7 +1600,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, · 1599 unmodified lines | ||
| 1600 | 1600 | */ |
| 1601 | 1601 | if (vif->type == NL80211_IFTYPE_AP || |
| 1602 | 1602 | vif->type == NL80211_IFTYPE_ADHOC) { |
| 1603 | − iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1603 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | |
| 1604 | + iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1604 | 1605 | ret = 0; |
| 1605 | 1606 | goto out; |
| 1606 | 1607 | } |
| @@ -1640,7 +1641,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, · 33 unmodified lines | ||
| 1640 | 1641 | iwl_mvm_chandef_get_primary_80(&vif->bss_conf.chandef); |
| 1641 | 1642 | } |
| 1642 | 1643 | |
| 1643 | − iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1644 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | |
| 1645 | + iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 1644 | 1646 | |
| 1645 | 1647 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 1646 | 1648 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
| @@ -81,7 +81,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, · 80 unmodified lines | ||
| 81 | 81 | ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS); |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | − iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 84 | + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) | |
| 85 | + iwl_mvm_vif_dbgfs_add_link(mvm, vif); | |
| 85 | 86 | |
| 86 | 87 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 87 | 88 | vif->type == NL80211_IFTYPE_STATION && !vif->p2p && |
| @@ -437,6 +438,9 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, · 349 unmodified lines | ||
| 437 | 438 | mvmvif->ap_ibss_active = false; |
| 438 | 439 | } |
| 439 | 440 | |
| 441 | + iwl_mvm_link_changed(mvm, vif, link_conf, | |
| 442 | + LINK_CONTEXT_MODIFY_ACTIVE, false); | |
| 443 | + | |
| 440 | 444 | if (iwl_mvm_is_esr_supported(mvm->fwrt.trans) && n_active > 1) { |
| 441 | 445 | int ret = iwl_mvm_esr_mode_inactive(mvm, vif); |
| 442 | 446 | |
| @@ -448,9 +452,6 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm, · 5 unmodified lines | ||
| 448 | 452 | if (vif->type == NL80211_IFTYPE_MONITOR) |
| 449 | 453 | iwl_mvm_mld_rm_snif_sta(mvm, vif); |
| 450 | 454 | |
| 451 | − iwl_mvm_link_changed(mvm, vif, link_conf, | |
| 452 | − LINK_CONTEXT_MODIFY_ACTIVE, false); | |
| 453 | − | |
| 454 | 455 | if (switching_chanctx) |
| 455 | 456 | return; |
| 456 | 457 | mvmvif->link[link_id]->phy_ctxt = NULL; |
| @@ -125,7 +125,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) · 124 unmodified lines | ||
| 125 | 125 | "FW rev %s - Softmac protocol %x.%x\n", |
| 126 | 126 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); |
| 127 | 127 | snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version), |
| 128 | − "%s - %x.%x", fw_version, | |
| 128 | + "%.19s - %x.%x", fw_version, | |
| 129 | 129 | priv->fw_var >> 8, priv->fw_var & 0xff); |
| 130 | 130 | } |
| 131 | 131 | |
| @@ -700,6 +700,7 @@ static struct spi_driver p54spi_driver = { · 699 unmodified lines | ||
| 700 | 700 | |
| 701 | 701 | module_spi_driver(p54spi_driver); |
| 702 | 702 | |
| 703 | +MODULE_DESCRIPTION("Prism54 SPI wireless driver"); | |
| 703 | 704 | MODULE_LICENSE("GPL"); |
| 704 | 705 | MODULE_AUTHOR("Christian Lamparter <chunkeey@web.de>"); |
| 705 | 706 | MODULE_ALIAS("spi:cx3110x"); |
| @@ -728,6 +728,7 @@ const struct ieee80211_ops mt7603_ops = { · 727 unmodified lines | ||
| 728 | 728 | .set_sar_specs = mt7603_set_sar_specs, |
| 729 | 729 | }; |
| 730 | 730 | |
| 731 | +MODULE_DESCRIPTION("MediaTek MT7603E and MT76x8 wireless driver"); | |
| 731 | 732 | MODULE_LICENSE("Dual BSD/GPL"); |
| 732 | 733 | |
| 733 | 734 | static int __init mt7603_init(void) |
| @@ -1375,4 +1375,5 @@ const struct ieee80211_ops mt7615_ops = { · 1374 unmodified lines | ||
| 1375 | 1375 | }; |
| 1376 | 1376 | EXPORT_SYMBOL_GPL(mt7615_ops); |
| 1377 | 1377 | |
| 1378 | +MODULE_DESCRIPTION("MediaTek MT7615E and MT7663E wireless driver"); | |
| 1378 | 1379 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -270,4 +270,5 @@ static void __exit mt7615_exit(void) · 269 unmodified lines | ||
| 270 | 270 | |
| 271 | 271 | module_init(mt7615_init); |
| 272 | 272 | module_exit(mt7615_exit); |
| 273 | +MODULE_DESCRIPTION("MediaTek MT7615E MMIO helpers"); | |
| 273 | 274 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -253,4 +253,5 @@ module_sdio_driver(mt7663s_driver); · 252 unmodified lines | ||
| 253 | 253 | |
| 254 | 254 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 255 | 255 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 256 | +MODULE_DESCRIPTION("MediaTek MT7663S (SDIO) wireless driver"); | |
| 256 | 257 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -281,4 +281,5 @@ module_usb_driver(mt7663u_driver); · 280 unmodified lines | ||
| 281 | 281 | |
| 282 | 282 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 283 | 283 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 284 | +MODULE_DESCRIPTION("MediaTek MT7663U (USB) wireless driver"); | |
| 284 | 285 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -349,4 +349,5 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_register_device); · 348 unmodified lines | ||
| 349 | 349 | |
| 350 | 350 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 351 | 351 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 352 | +MODULE_DESCRIPTION("MediaTek MT7663 SDIO/USB helpers"); | |
| 352 | 353 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -3160,4 +3160,5 @@ exit: · 3159 unmodified lines | ||
| 3160 | 3160 | EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message); |
| 3161 | 3161 | |
| 3162 | 3162 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 3163 | +MODULE_DESCRIPTION("MediaTek MT76x connac layer helpers"); | |
| 3163 | 3164 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -342,4 +342,5 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev) · 341 unmodified lines | ||
| 342 | 342 | return 0; |
| 343 | 343 | } |
| 344 | 344 | |
| 345 | +MODULE_DESCRIPTION("MediaTek MT76x EEPROM helpers"); | |
| 345 | 346 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -302,6 +302,7 @@ static const struct pci_device_id mt76x0e_device_table[] = { · 301 unmodified lines | ||
| 302 | 302 | MODULE_DEVICE_TABLE(pci, mt76x0e_device_table); |
| 303 | 303 | MODULE_FIRMWARE(MT7610E_FIRMWARE); |
| 304 | 304 | MODULE_FIRMWARE(MT7650E_FIRMWARE); |
| 305 | +MODULE_DESCRIPTION("MediaTek MT76x0E (PCIe) wireless driver"); | |
| 305 | 306 | MODULE_LICENSE("Dual BSD/GPL"); |
| 306 | 307 | |
| 307 | 308 | static struct pci_driver mt76x0e_driver = { |
| @@ -336,6 +336,7 @@ err: · 335 unmodified lines | ||
| 336 | 336 | MODULE_DEVICE_TABLE(usb, mt76x0_device_table); |
| 337 | 337 | MODULE_FIRMWARE(MT7610E_FIRMWARE); |
| 338 | 338 | MODULE_FIRMWARE(MT7610U_FIRMWARE); |
| 339 | +MODULE_DESCRIPTION("MediaTek MT76x0U (USB) wireless driver"); | |
| 339 | 340 | MODULE_LICENSE("GPL"); |
| 340 | 341 | |
| 341 | 342 | static struct usb_driver mt76x0_driver = { |
| @@ -293,4 +293,5 @@ void mt76x02u_init_mcu(struct mt76_dev *dev) · 292 unmodified lines | ||
| 293 | 293 | EXPORT_SYMBOL_GPL(mt76x02u_init_mcu); |
| 294 | 294 | |
| 295 | 295 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |
| 296 | +MODULE_DESCRIPTION("MediaTek MT76x02 MCU helpers"); | |
| 296 | 297 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -696,4 +696,5 @@ void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev) · 695 unmodified lines | ||
| 696 | 696 | } |
| 697 | 697 | EXPORT_SYMBOL_GPL(mt76x02_config_mac_addr_list); |
| 698 | 698 | |
| 699 | +MODULE_DESCRIPTION("MediaTek MT76x02 helpers"); | |
| 699 | 700 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -506,4 +506,5 @@ int mt76x2_eeprom_init(struct mt76x02_dev *dev) · 505 unmodified lines | ||
| 506 | 506 | } |
| 507 | 507 | EXPORT_SYMBOL_GPL(mt76x2_eeprom_init); |
| 508 | 508 | |
| 509 | +MODULE_DESCRIPTION("MediaTek MT76x2 EEPROM helpers"); | |
| 509 | 510 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -165,6 +165,7 @@ mt76x2e_resume(struct pci_dev *pdev) · 164 unmodified lines | ||
| 165 | 165 | MODULE_DEVICE_TABLE(pci, mt76x2e_device_table); |
| 166 | 166 | MODULE_FIRMWARE(MT7662_FIRMWARE); |
| 167 | 167 | MODULE_FIRMWARE(MT7662_ROM_PATCH); |
| 168 | +MODULE_DESCRIPTION("MediaTek MT76x2E (PCIe) wireless driver"); | |
| 168 | 169 | MODULE_LICENSE("Dual BSD/GPL"); |
| 169 | 170 | |
| 170 | 171 | static struct pci_driver mt76pci_driver = { |
| @@ -147,4 +147,5 @@ static struct usb_driver mt76x2u_driver = { · 146 unmodified lines | ||
| 147 | 147 | module_usb_driver(mt76x2u_driver); |
| 148 | 148 | |
| 149 | 149 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |
| 150 | +MODULE_DESCRIPTION("MediaTek MT76x2U (USB) wireless driver"); | |
| 150 | 151 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -958,4 +958,5 @@ static void __exit mt7915_exit(void) · 957 unmodified lines | ||
| 958 | 958 | |
| 959 | 959 | module_init(mt7915_init); |
| 960 | 960 | module_exit(mt7915_exit); |
| 961 | +MODULE_DESCRIPTION("MediaTek MT7915E MMIO helpers"); | |
| 961 | 962 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1418,5 +1418,6 @@ const struct ieee80211_ops mt7921_ops = { · 1417 unmodified lines | ||
| 1418 | 1418 | }; |
| 1419 | 1419 | EXPORT_SYMBOL_GPL(mt7921_ops); |
| 1420 | 1420 | |
| 1421 | +MODULE_DESCRIPTION("MediaTek MT7921 core driver"); | |
| 1421 | 1422 | MODULE_LICENSE("Dual BSD/GPL"); |
| 1422 | 1423 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| @@ -544,4 +544,5 @@ MODULE_FIRMWARE(MT7922_FIRMWARE_WM); · 543 unmodified lines | ||
| 544 | 544 | MODULE_FIRMWARE(MT7922_ROM_PATCH); |
| 545 | 545 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 546 | 546 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 547 | +MODULE_DESCRIPTION("MediaTek MT7921E (PCIe) wireless driver"); | |
| 547 | 548 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -323,5 +323,6 @@ static struct sdio_driver mt7921s_driver = { · 322 unmodified lines | ||
| 323 | 323 | .drv.pm = pm_sleep_ptr(&mt7921s_pm_ops), |
| 324 | 324 | }; |
| 325 | 325 | module_sdio_driver(mt7921s_driver); |
| 326 | +MODULE_DESCRIPTION("MediaTek MT7921S (SDIO) wireless driver"); | |
| 326 | 327 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 327 | 328 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -336,5 +336,6 @@ static struct usb_driver mt7921u_driver = { · 335 unmodified lines | ||
| 336 | 336 | }; |
| 337 | 337 | module_usb_driver(mt7921u_driver); |
| 338 | 338 | |
| 339 | +MODULE_DESCRIPTION("MediaTek MT7921U (USB) wireless driver"); | |
| 339 | 340 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 340 | 341 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1450,4 +1450,5 @@ const struct ieee80211_ops mt7925_ops = { · 1449 unmodified lines | ||
| 1450 | 1450 | EXPORT_SYMBOL_GPL(mt7925_ops); |
| 1451 | 1451 | |
| 1452 | 1452 | MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); |
| 1453 | +MODULE_DESCRIPTION("MediaTek MT7925 core driver"); | |
| 1453 | 1454 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -583,4 +583,5 @@ MODULE_FIRMWARE(MT7925_FIRMWARE_WM); · 582 unmodified lines | ||
| 583 | 583 | MODULE_FIRMWARE(MT7925_ROM_PATCH); |
| 584 | 584 | MODULE_AUTHOR("Deren Wu <deren.wu@mediatek.com>"); |
| 585 | 585 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 586 | +MODULE_DESCRIPTION("MediaTek MT7925E (PCIe) wireless driver"); | |
| 586 | 587 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -329,4 +329,5 @@ static struct usb_driver mt7925u_driver = { · 328 unmodified lines | ||
| 329 | 329 | module_usb_driver(mt7925u_driver); |
| 330 | 330 | |
| 331 | 331 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 332 | +MODULE_DESCRIPTION("MediaTek MT7925U (USB) wireless driver"); | |
| 332 | 333 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -862,5 +862,6 @@ int mt792x_load_firmware(struct mt792x_dev *dev) · 861 unmodified lines | ||
| 862 | 862 | } |
| 863 | 863 | EXPORT_SYMBOL_GPL(mt792x_load_firmware); |
| 864 | 864 | |
| 865 | +MODULE_DESCRIPTION("MediaTek MT792x core driver"); | |
| 865 | 866 | MODULE_LICENSE("Dual BSD/GPL"); |
| 866 | 867 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| @@ -314,5 +314,6 @@ void mt792xu_disconnect(struct usb_interface *usb_intf) · 313 unmodified lines | ||
| 314 | 314 | } |
| 315 | 315 | EXPORT_SYMBOL_GPL(mt792xu_disconnect); |
| 316 | 316 | |
| 317 | +MODULE_DESCRIPTION("MediaTek MT792x USB helpers"); | |
| 317 | 318 | MODULE_LICENSE("Dual BSD/GPL"); |
| 318 | 319 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| @@ -4477,7 +4477,8 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy) · 4476 unmodified lines | ||
| 4477 | 4477 | |
| 4478 | 4478 | skb_put_data(skb, &req, sizeof(req)); |
| 4479 | 4479 | /* cck and ofdm */ |
| 4480 | − skb_put_data(skb, &la.cck, sizeof(la.cck) + sizeof(la.ofdm)); | |
| 4480 | + skb_put_data(skb, &la.cck, sizeof(la.cck)); | |
| 4481 | + skb_put_data(skb, &la.ofdm, sizeof(la.ofdm)); | |
| 4481 | 4482 | /* ht20 */ |
| 4482 | 4483 | skb_put_data(skb, &la.mcs[0], 8); |
| 4483 | 4484 | /* ht40 */ |
| @@ -650,4 +650,5 @@ static void __exit mt7996_exit(void) · 649 unmodified lines | ||
| 650 | 650 | |
| 651 | 651 | module_init(mt7996_init); |
| 652 | 652 | module_exit(mt7996_exit); |
| 653 | +MODULE_DESCRIPTION("MediaTek MT7996 MMIO helpers"); | |
| 653 | 654 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -672,4 +672,5 @@ EXPORT_SYMBOL_GPL(mt76s_init); · 671 unmodified lines | ||
| 672 | 672 | |
| 673 | 673 | MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>"); |
| 674 | 674 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); |
| 675 | +MODULE_DESCRIPTION("MediaTek MT76x SDIO helpers"); | |
| 675 | 676 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1128,4 +1128,5 @@ int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf) · 1127 unmodified lines | ||
| 1128 | 1128 | EXPORT_SYMBOL_GPL(mt76u_init); |
| 1129 | 1129 | |
| 1130 | 1130 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>"); |
| 1131 | +MODULE_DESCRIPTION("MediaTek MT76x USB helpers"); | |
| 1131 | 1132 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -138,4 +138,5 @@ int __mt76_worker_fn(void *ptr) · 137 unmodified lines | ||
| 138 | 138 | } |
| 139 | 139 | EXPORT_SYMBOL_GPL(__mt76_worker_fn); |
| 140 | 140 | |
| 141 | +MODULE_DESCRIPTION("MediaTek MT76x helpers"); | |
| 141 | 142 | MODULE_LICENSE("Dual BSD/GPL"); |
| @@ -1018,5 +1018,6 @@ unregister_netdev: · 1017 unmodified lines | ||
| 1018 | 1018 | return ERR_PTR(ret); |
| 1019 | 1019 | } |
| 1020 | 1020 | |
| 1021 | +MODULE_DESCRIPTION("Atmel WILC1000 core wireless driver"); | |
| 1021 | 1022 | MODULE_LICENSE("GPL"); |
| 1022 | 1023 | MODULE_FIRMWARE(WILC1000_FW(WILC1000_API_VER)); |
| @@ -984,4 +984,5 @@ static struct sdio_driver wilc_sdio_driver = { · 983 unmodified lines | ||
| 984 | 984 | module_driver(wilc_sdio_driver, |
| 985 | 985 | sdio_register_driver, |
| 986 | 986 | sdio_unregister_driver); |
| 987 | +MODULE_DESCRIPTION("Atmel WILC1000 SDIO wireless driver"); | |
| 987 | 988 | MODULE_LICENSE("GPL"); |
| @@ -273,6 +273,7 @@ static struct spi_driver wilc_spi_driver = { · 272 unmodified lines | ||
| 273 | 273 | .remove = wilc_bus_remove, |
| 274 | 274 | }; |
| 275 | 275 | module_spi_driver(wilc_spi_driver); |
| 276 | +MODULE_DESCRIPTION("Atmel WILC1000 SPI wireless driver"); | |
| 276 | 277 | MODULE_LICENSE("GPL"); |
| 277 | 278 | |
| 278 | 279 | static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) |
| @@ -343,5 +343,6 @@ static void __exit wl1251_sdio_exit(void) · 342 unmodified lines | ||
| 343 | 343 | module_init(wl1251_sdio_init); |
| 344 | 344 | module_exit(wl1251_sdio_exit); |
| 345 | 345 | |
| 346 | +MODULE_DESCRIPTION("TI WL1251 SDIO helpers"); | |
| 346 | 347 | MODULE_LICENSE("GPL"); |
| 347 | 348 | MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>"); |
| @@ -342,6 +342,7 @@ static struct spi_driver wl1251_spi_driver = { · 341 unmodified lines | ||
| 342 | 342 | |
| 343 | 343 | module_spi_driver(wl1251_spi_driver); |
| 344 | 344 | |
| 345 | +MODULE_DESCRIPTION("TI WL1251 SPI helpers"); | |
| 345 | 346 | MODULE_LICENSE("GPL"); |
| 346 | 347 | MODULE_AUTHOR("Kalle Valo <kvalo@adurom.com>"); |
| 347 | 348 | MODULE_ALIAS("spi:wl1251"); |
| @@ -1955,6 +1955,7 @@ module_param_named(tcxo, tcxo_param, charp, 0); · 1954 unmodified lines | ||
| 1955 | 1955 | MODULE_PARM_DESC(tcxo, |
| 1956 | 1956 | "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6"); |
| 1957 | 1957 | |
| 1958 | +MODULE_DESCRIPTION("TI WL12xx wireless driver"); | |
| 1958 | 1959 | MODULE_LICENSE("GPL v2"); |
| 1959 | 1960 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 1960 | 1961 | MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); |
| @@ -2086,6 +2086,7 @@ module_param_named(num_rx_desc, num_rx_desc_param, int, 0400); · 2085 unmodified lines | ||
| 2086 | 2086 | MODULE_PARM_DESC(num_rx_desc_param, |
| 2087 | 2087 | "Number of Rx descriptors: u8 (default is 32)"); |
| 2088 | 2088 | |
| 2089 | +MODULE_DESCRIPTION("TI WiLink 8 wireless driver"); | |
| 2089 | 2090 | MODULE_LICENSE("GPL v2"); |
| 2090 | 2091 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 2091 | 2092 | MODULE_FIRMWARE(WL18XX_FW_NAME); |
| @@ -6793,6 +6793,7 @@ MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery"); · 6792 unmodified lines | ||
| 6793 | 6793 | module_param(no_recovery, int, 0600); |
| 6794 | 6794 | MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); |
| 6795 | 6795 | |
| 6796 | +MODULE_DESCRIPTION("TI WLAN core driver"); | |
| 6796 | 6797 | MODULE_LICENSE("GPL"); |
| 6797 | 6798 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 6798 | 6799 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
| @@ -447,6 +447,7 @@ module_sdio_driver(wl1271_sdio_driver); · 446 unmodified lines | ||
| 447 | 447 | module_param(dump, bool, 0600); |
| 448 | 448 | MODULE_PARM_DESC(dump, "Enable sdio read/write dumps."); |
| 449 | 449 | |
| 450 | +MODULE_DESCRIPTION("TI WLAN SDIO helpers"); | |
| 450 | 451 | MODULE_LICENSE("GPL"); |
| 451 | 452 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 452 | 453 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
| @@ -562,6 +562,7 @@ static struct spi_driver wl1271_spi_driver = { · 561 unmodified lines | ||
| 562 | 562 | }; |
| 563 | 563 | |
| 564 | 564 | module_spi_driver(wl1271_spi_driver); |
| 565 | +MODULE_DESCRIPTION("TI WLAN SPI helpers"); | |
| 565 | 566 | MODULE_LICENSE("GPL"); |
| 566 | 567 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
| 567 | 568 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |
| @@ -104,13 +104,12 @@ bool provides_xdp_headroom = true; · 103 unmodified lines | ||
| 104 | 104 | module_param(provides_xdp_headroom, bool, 0644); |
| 105 | 105 | |
| 106 | 106 | static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, |
| 107 | − u8 status); | |
| 107 | + s8 status); | |
| 108 | 108 | |
| 109 | 109 | static void make_tx_response(struct xenvif_queue *queue, |
| 110 | − struct xen_netif_tx_request *txp, | |
| 110 | + const struct xen_netif_tx_request *txp, | |
| 111 | 111 | unsigned int extra_count, |
| 112 | − s8 st); | |
| 113 | −static void push_tx_responses(struct xenvif_queue *queue); | |
| 112 | + s8 status); | |
| 114 | 113 | |
| 115 | 114 | static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx); |
| 116 | 115 | |
| @@ -208,13 +207,9 @@ static void xenvif_tx_err(struct xenvif_queue *queue, · 91 unmodified lines | ||
| 208 | 207 | unsigned int extra_count, RING_IDX end) |
| 209 | 208 | { |
| 210 | 209 | RING_IDX cons = queue->tx.req_cons; |
| 211 | − unsigned long flags; | |
| 212 | 210 | |
| 213 | 211 | do { |
| 214 | − spin_lock_irqsave(&queue->response_lock, flags); | |
| 215 | 212 | make_tx_response(queue, txp, extra_count, XEN_NETIF_RSP_ERROR); |
| 216 | − push_tx_responses(queue); | |
| 217 | − spin_unlock_irqrestore(&queue->response_lock, flags); | |
| 218 | 213 | if (cons == end) |
| 219 | 214 | break; |
| 220 | 215 | RING_COPY_REQUEST(&queue->tx, cons++, txp); |
| @@ -463,12 +458,20 @@ static void xenvif_get_requests(struct xenvif_queue *queue, · 242 unmodified lines | ||
| 463 | 458 | } |
| 464 | 459 | |
| 465 | 460 | for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS; |
| 466 | − shinfo->nr_frags++, gop++, nr_slots--) { | |
| 461 | + nr_slots--) { | |
| 462 | + if (unlikely(!txp->size)) { | |
| 463 | + make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY); | |
| 464 | + ++txp; | |
| 465 | + continue; | |
| 466 | + } | |
| 467 | + | |
| 467 | 468 | index = pending_index(queue->pending_cons++); |
| 468 | 469 | pending_idx = queue->pending_ring[index]; |
| 469 | 470 | xenvif_tx_create_map_op(queue, pending_idx, txp, |
| 470 | 471 | txp == first ? extra_count : 0, gop); |
| 471 | 472 | frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx); |
| 473 | + ++shinfo->nr_frags; | |
| 474 | + ++gop; | |
| 472 | 475 | |
| 473 | 476 | if (txp == first) |
| 474 | 477 | txp = txfrags; |
| @@ -481,20 +484,33 @@ static void xenvif_get_requests(struct xenvif_queue *queue, · 6 unmodified lines | ||
| 481 | 484 | shinfo = skb_shinfo(nskb); |
| 482 | 485 | frags = shinfo->frags; |
| 483 | 486 | |
| 484 | − for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; | |
| 485 | − shinfo->nr_frags++, txp++, gop++) { | |
| 487 | + for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; ++txp) { | |
| 488 | + if (unlikely(!txp->size)) { | |
| 489 | + make_tx_response(queue, txp, 0, | |
| 490 | + XEN_NETIF_RSP_OKAY); | |
| 491 | + continue; | |
| 492 | + } | |
| 493 | + | |
| 486 | 494 | index = pending_index(queue->pending_cons++); |
| 487 | 495 | pending_idx = queue->pending_ring[index]; |
| 488 | 496 | xenvif_tx_create_map_op(queue, pending_idx, txp, 0, |
| 489 | 497 | gop); |
| 490 | 498 | frag_set_pending_idx(&frags[shinfo->nr_frags], |
| 491 | 499 | pending_idx); |
| 500 | + ++shinfo->nr_frags; | |
| 501 | + ++gop; | |
| 502 | + } | |
| 503 | + | |
| 504 | + if (shinfo->nr_frags) { | |
| 505 | + skb_shinfo(skb)->frag_list = nskb; | |
| 506 | + nskb = NULL; | |
| 492 | 507 | } |
| 508 | + } | |
| 493 | 509 | |
| 494 | − skb_shinfo(skb)->frag_list = nskb; | |
| 495 | − } else if (nskb) { | |
| 510 | + if (nskb) { | |
| 496 | 511 | /* A frag_list skb was allocated but it is no longer needed |
| 497 | − * because enough slots were converted to copy ops above. | |
| 512 | + * because enough slots were converted to copy ops above or some | |
| 513 | + * were empty. | |
| 498 | 514 | */ |
| 499 | 515 | kfree_skb(nskb); |
| 500 | 516 | } |
| @@ -963,7 +979,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, · 462 unmodified lines | ||
| 963 | 979 | (ret == 0) ? |
| 964 | 980 | XEN_NETIF_RSP_OKAY : |
| 965 | 981 | XEN_NETIF_RSP_ERROR); |
| 966 | − push_tx_responses(queue); | |
| 967 | 982 | continue; |
| 968 | 983 | } |
| 969 | 984 | |
| @@ -975,7 +990,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue, · 5 unmodified lines | ||
| 975 | 990 | |
| 976 | 991 | make_tx_response(queue, &txreq, extra_count, |
| 977 | 992 | XEN_NETIF_RSP_OKAY); |
| 978 | − push_tx_responses(queue); | |
| 979 | 993 | continue; |
| 980 | 994 | } |
| 981 | 995 | |
| @@ -1401,8 +1415,35 @@ int xenvif_tx_action(struct xenvif_queue *queue, int budget) · 419 unmodified lines | ||
| 1401 | 1415 | return work_done; |
| 1402 | 1416 | } |
| 1403 | 1417 | |
| 1418 | +static void _make_tx_response(struct xenvif_queue *queue, | |
| 1419 | + const struct xen_netif_tx_request *txp, | |
| 1420 | + unsigned int extra_count, | |
| 1421 | + s8 status) | |
| 1422 | +{ | |
| 1423 | + RING_IDX i = queue->tx.rsp_prod_pvt; | |
| 1424 | + struct xen_netif_tx_response *resp; | |
| 1425 | + | |
| 1426 | + resp = RING_GET_RESPONSE(&queue->tx, i); | |
| 1427 | + resp->id = txp->id; | |
| 1428 | + resp->status = status; | |
| 1429 | + | |
| 1430 | + while (extra_count-- != 0) | |
| 1431 | + RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL; | |
| 1432 | + | |
| 1433 | + queue->tx.rsp_prod_pvt = ++i; | |
| 1434 | +} | |
| 1435 | + | |
| 1436 | +static void push_tx_responses(struct xenvif_queue *queue) | |
| 1437 | +{ | |
| 1438 | + int notify; | |
| 1439 | + | |
| 1440 | + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify); | |
| 1441 | + if (notify) | |
| 1442 | + notify_remote_via_irq(queue->tx_irq); | |
| 1443 | +} | |
| 1444 | + | |
| 1404 | 1445 | static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, |
| 1405 | − u8 status) | |
| 1446 | + s8 status) | |
| 1406 | 1447 | { |
| 1407 | 1448 | struct pending_tx_info *pending_tx_info; |
| 1408 | 1449 | pending_ring_idx_t index; |
| @@ -1412,8 +1453,8 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, · 3 unmodified lines | ||
| 1412 | 1453 | |
| 1413 | 1454 | spin_lock_irqsave(&queue->response_lock, flags); |
| 1414 | 1455 | |
| 1415 | − make_tx_response(queue, &pending_tx_info->req, | |
| 1416 | − pending_tx_info->extra_count, status); | |
| 1456 | + _make_tx_response(queue, &pending_tx_info->req, | |
| 1457 | + pending_tx_info->extra_count, status); | |
| 1417 | 1458 | |
| 1418 | 1459 | /* Release the pending index before pusing the Tx response so |
| 1419 | 1460 | * its available before a new Tx request is pushed by the |
| @@ -1427,32 +1468,19 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx, · 7 unmodified lines | ||
| 1427 | 1468 | spin_unlock_irqrestore(&queue->response_lock, flags); |
| 1428 | 1469 | } |
| 1429 | 1470 | |
| 1430 | − | |
| 1431 | 1471 | static void make_tx_response(struct xenvif_queue *queue, |
| 1432 | − struct xen_netif_tx_request *txp, | |
| 1472 | + const struct xen_netif_tx_request *txp, | |
| 1433 | 1473 | unsigned int extra_count, |
| 1434 | − s8 st) | |
| 1474 | + s8 status) | |
| 1435 | 1475 | { |
| 1436 | − RING_IDX i = queue->tx.rsp_prod_pvt; | |
| 1437 | − struct xen_netif_tx_response *resp; | |
| 1438 | − | |
| 1439 | − resp = RING_GET_RESPONSE(&queue->tx, i); | |
| 1440 | − resp->id = txp->id; | |
| 1441 | − resp->status = st; | |
| 1442 | − | |
| 1443 | − while (extra_count-- != 0) | |
| 1444 | − RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL; | |
| 1476 | + unsigned long flags; | |
| 1445 | 1477 | |
| 1446 | − queue->tx.rsp_prod_pvt = ++i; | |
| 1447 | −} | |
| 1478 | + spin_lock_irqsave(&queue->response_lock, flags); | |
| 1448 | 1479 | |
| 1449 | −static void push_tx_responses(struct xenvif_queue *queue) | |
| 1450 | −{ | |
| 1451 | − int notify; | |
| 1480 | + _make_tx_response(queue, txp, extra_count, status); | |
| 1481 | + push_tx_responses(queue); | |
| 1452 | 1482 | |
| 1453 | − RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify); | |
| 1454 | − if (notify) | |
| 1455 | − notify_remote_via_irq(queue->tx_irq); | |
| 1483 | + spin_unlock_irqrestore(&queue->response_lock, flags); | |
| 1456 | 1484 | } |
| 1457 | 1485 | |
| 1458 | 1486 | static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx) |
| @@ -471,4 +471,5 @@ int nvme_auth_generate_key(u8 *secret, struct nvme_dhchap_key **ret_key) · 470 unmodified lines | ||
| 471 | 471 | } |
| 472 | 472 | EXPORT_SYMBOL_GPL(nvme_auth_generate_key); |
| 473 | 473 | |
| 474 | +MODULE_DESCRIPTION("NVMe Authentication framework"); | |
| 474 | 475 | MODULE_LICENSE("GPL v2"); |
| @@ -181,5 +181,6 @@ static void __exit nvme_keyring_exit(void) · 180 unmodified lines | ||
| 181 | 181 | |
| 182 | 182 | MODULE_LICENSE("GPL v2"); |
| 183 | 183 | MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>"); |
| 184 | +MODULE_DESCRIPTION("NVMe Keyring implementation"); | |
| 184 | 185 | module_init(nvme_keyring_init); |
| 185 | 186 | module_exit(nvme_keyring_exit); |
| @@ -797,6 +797,7 @@ static int apple_nvme_init_request(struct blk_mq_tag_set *set, · 796 unmodified lines | ||
| 797 | 797 | |
| 798 | 798 | static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) |
| 799 | 799 | { |
| 800 | + enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl); | |
| 800 | 801 | u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS); |
| 801 | 802 | bool dead = false, freeze = false; |
| 802 | 803 | unsigned long flags; |
| @@ -808,8 +809,8 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) · 5 unmodified lines | ||
| 808 | 809 | if (csts & NVME_CSTS_CFS) |
| 809 | 810 | dead = true; |
| 810 | 811 | |
| 811 | − if (anv->ctrl.state == NVME_CTRL_LIVE || | |
| 812 | − anv->ctrl.state == NVME_CTRL_RESETTING) { | |
| 812 | + if (state == NVME_CTRL_LIVE || | |
| 813 | + state == NVME_CTRL_RESETTING) { | |
| 813 | 814 | freeze = true; |
| 814 | 815 | nvme_start_freeze(&anv->ctrl); |
| 815 | 816 | } |
| @@ -881,7 +882,7 @@ static enum blk_eh_timer_return apple_nvme_timeout(struct request *req) · 65 unmodified lines | ||
| 881 | 882 | unsigned long flags; |
| 882 | 883 | u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS); |
| 883 | 884 | |
| 884 | − if (anv->ctrl.state != NVME_CTRL_LIVE) { | |
| 885 | + if (nvme_ctrl_state(&anv->ctrl) != NVME_CTRL_LIVE) { | |
| 885 | 886 | /* |
| 886 | 887 | * From rdma.c: |
| 887 | 888 | * If we are resetting, connecting or deleting we should |
| @@ -985,10 +986,10 @@ static void apple_nvme_reset_work(struct work_struct *work) · 97 unmodified lines | ||
| 985 | 986 | u32 boot_status, aqa; |
| 986 | 987 | struct apple_nvme *anv = |
| 987 | 988 | container_of(work, struct apple_nvme, ctrl.reset_work); |
| 989 | + enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl); | |
| 988 | 990 | |
| 989 | − if (anv->ctrl.state != NVME_CTRL_RESETTING) { | |
| 990 | − dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", | |
| 991 | − anv->ctrl.state); | |
| 991 | + if (state != NVME_CTRL_RESETTING) { | |
| 992 | + dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", state); | |
| 992 | 993 | ret = -ENODEV; |
| 993 | 994 | goto out; |
| 994 | 995 | } |
| @@ -48,11 +48,6 @@ struct nvme_dhchap_queue_context { · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | static struct workqueue_struct *nvme_auth_wq; |
| 50 | 50 | |
| 51 | −#define nvme_auth_flags_from_qid(qid) \ | |
| 52 | − (qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED | |
| 53 | −#define nvme_auth_queue_from_qid(ctrl, qid) \ | |
| 54 | − (qid == 0) ? (ctrl)->fabrics_q : (ctrl)->connect_q | |
| 55 | − | |
| 56 | 51 | static inline int ctrl_max_dhchaps(struct nvme_ctrl *ctrl) |
| 57 | 52 | { |
| 58 | 53 | return ctrl->opts->nr_io_queues + ctrl->opts->nr_write_queues + |
| @@ -63,10 +58,15 @@ static int nvme_auth_submit(struct nvme_ctrl *ctrl, int qid, · 4 unmodified lines | ||
| 63 | 58 | void *data, size_t data_len, bool auth_send) |
| 64 | 59 | { |
| 65 | 60 | struct nvme_command cmd = {}; |
| 66 | − blk_mq_req_flags_t flags = nvme_auth_flags_from_qid(qid); | |
| 67 | − struct request_queue *q = nvme_auth_queue_from_qid(ctrl, qid); | |
| 61 | + nvme_submit_flags_t flags = NVME_SUBMIT_RETRY; | |
| 62 | + struct request_queue *q = ctrl->fabrics_q; | |
| 68 | 63 | int ret; |
| 69 | 64 | |
| 65 | + if (qid != 0) { | |
| 66 | + flags |= NVME_SUBMIT_NOWAIT | NVME_SUBMIT_RESERVED; | |
| 67 | + q = ctrl->connect_q; | |
| 68 | + } | |
| 69 | + | |
| 70 | 70 | cmd.auth_common.opcode = nvme_fabrics_command; |
| 71 | 71 | cmd.auth_common.secp = NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER; |
| 72 | 72 | cmd.auth_common.spsp0 = 0x01; |
| @@ -80,8 +80,7 @@ static int nvme_auth_submit(struct nvme_ctrl *ctrl, int qid, · 7 unmodified lines | ||
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | ret = __nvme_submit_sync_cmd(q, &cmd, NULL, data, data_len, |
| 83 | − qid == 0 ? NVME_QID_ANY : qid, | |
| 84 | − 0, flags); | |
| 83 | + qid == 0 ? NVME_QID_ANY : qid, flags); | |
| 85 | 84 | if (ret > 0) |
| 86 | 85 | dev_warn(ctrl->device, |
| 87 | 86 | "qid %d auth_send failed with status %d\n", qid, ret); |
| @@ -897,7 +896,7 @@ static void nvme_ctrl_auth_work(struct work_struct *work) · 809 unmodified lines | ||
| 897 | 896 | * If the ctrl is no connected, bail as reconnect will handle |
| 898 | 897 | * authentication. |
| 899 | 898 | */ |
| 900 | − if (ctrl->state != NVME_CTRL_LIVE) | |
| 899 | + if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) | |
| 901 | 900 | return; |
| 902 | 901 | |
| 903 | 902 | /* Authenticate admin queue first */ |
| @@ -171,15 +171,15 @@ static const char * const nvme_statuses[] = { · 170 unmodified lines | ||
| 171 | 171 | [NVME_SC_HOST_ABORTED_CMD] = "Host Aborted Command", |
| 172 | 172 | }; |
| 173 | 173 | |
| 174 | −const unsigned char *nvme_get_error_status_str(u16 status) | |
| 174 | +const char *nvme_get_error_status_str(u16 status) | |
| 175 | 175 | { |
| 176 | 176 | status &= 0x7ff; |
| 177 | 177 | if (status < ARRAY_SIZE(nvme_statuses) && nvme_statuses[status]) |
| 178 | − return nvme_statuses[status & 0x7ff]; | |
| 178 | + return nvme_statuses[status]; | |
| 179 | 179 | return "Unknown"; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | −const unsigned char *nvme_get_opcode_str(u8 opcode) | |
| 182 | +const char *nvme_get_opcode_str(u8 opcode) | |
| 183 | 183 | { |
| 184 | 184 | if (opcode < ARRAY_SIZE(nvme_ops) && nvme_ops[opcode]) |
| 185 | 185 | return nvme_ops[opcode]; |
| @@ -187,7 +187,7 @@ const unsigned char *nvme_get_opcode_str(u8 opcode) · 1 unmodified line | ||
| 187 | 187 | } |
| 188 | 188 | EXPORT_SYMBOL_GPL(nvme_get_opcode_str); |
| 189 | 189 | |
| 190 | −const unsigned char *nvme_get_admin_opcode_str(u8 opcode) | |
| 190 | +const char *nvme_get_admin_opcode_str(u8 opcode) | |
| 191 | 191 | { |
| 192 | 192 | if (opcode < ARRAY_SIZE(nvme_admin_ops) && nvme_admin_ops[opcode]) |
| 193 | 193 | return nvme_admin_ops[opcode]; |
| @@ -195,7 +195,7 @@ const unsigned char *nvme_get_admin_opcode_str(u8 opcode) · 1 unmodified line | ||
| 195 | 195 | } |
| 196 | 196 | EXPORT_SYMBOL_GPL(nvme_get_admin_opcode_str); |
| 197 | 197 | |
| 198 | −const unsigned char *nvme_get_fabrics_opcode_str(u8 opcode) { | |
| 198 | +const char *nvme_get_fabrics_opcode_str(u8 opcode) { | |
| 199 | 199 | if (opcode < ARRAY_SIZE(nvme_fabrics_ops) && nvme_fabrics_ops[opcode]) |
| 200 | 200 | return nvme_fabrics_ops[opcode]; |
| 201 | 201 | return "Unknown"; |
| @@ -338,6 +338,30 @@ static void nvme_log_error(struct request *req) · 337 unmodified lines | ||
| 338 | 338 | nr->status & NVME_SC_DNR ? "DNR " : ""); |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | +static void nvme_log_err_passthru(struct request *req) | |
| 342 | +{ | |
| 343 | + struct nvme_ns *ns = req->q->queuedata; | |
| 344 | + struct nvme_request *nr = nvme_req(req); | |
| 345 | + | |
| 346 | + pr_err_ratelimited("%s: %s(0x%x), %s (sct 0x%x / sc 0x%x) %s%s" | |
| 347 | + "cdw10=0x%x cdw11=0x%x cdw12=0x%x cdw13=0x%x cdw14=0x%x cdw15=0x%x\n", | |
| 348 | + ns ? ns->disk->disk_name : dev_name(nr->ctrl->device), | |
| 349 | + ns ? nvme_get_opcode_str(nr->cmd->common.opcode) : | |
| 350 | + nvme_get_admin_opcode_str(nr->cmd->common.opcode), | |
| 351 | + nr->cmd->common.opcode, | |
| 352 | + nvme_get_error_status_str(nr->status), | |
| 353 | + nr->status >> 8 & 7, /* Status Code Type */ | |
| 354 | + nr->status & 0xff, /* Status Code */ | |
| 355 | + nr->status & NVME_SC_MORE ? "MORE " : "", | |
| 356 | + nr->status & NVME_SC_DNR ? "DNR " : "", | |
| 357 | + nr->cmd->common.cdw10, | |
| 358 | + nr->cmd->common.cdw11, | |
| 359 | + nr->cmd->common.cdw12, | |
| 360 | + nr->cmd->common.cdw13, | |
| 361 | + nr->cmd->common.cdw14, | |
| 362 | + nr->cmd->common.cdw14); | |
| 363 | +} | |
| 364 | + | |
| 341 | 365 | enum nvme_disposition { |
| 342 | 366 | COMPLETE, |
| 343 | 367 | RETRY, |
| @@ -385,8 +409,12 @@ static inline void nvme_end_req(struct request *req) · 41 unmodified lines | ||
| 385 | 409 | { |
| 386 | 410 | blk_status_t status = nvme_error_status(nvme_req(req)->status); |
| 387 | 411 | |
| 388 | − if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) | |
| 389 | − nvme_log_error(req); | |
| 412 | + if (unlikely(nvme_req(req)->status && !(req->rq_flags & RQF_QUIET))) { | |
| 413 | + if (blk_rq_is_passthrough(req)) | |
| 414 | + nvme_log_err_passthru(req); | |
| 415 | + else | |
| 416 | + nvme_log_error(req); | |
| 417 | + } | |
| 390 | 418 | nvme_end_req_zoned(req); |
| 391 | 419 | nvme_trace_bio_complete(req); |
| 392 | 420 | if (req->cmd_flags & REQ_NVME_MPATH) |
| @@ -679,10 +707,21 @@ static inline void nvme_clear_nvme_request(struct request *req) · 286 unmodified lines | ||
| 679 | 707 | /* initialize a passthrough request */ |
| 680 | 708 | void nvme_init_request(struct request *req, struct nvme_command *cmd) |
| 681 | 709 | { |
| 682 | − if (req->q->queuedata) | |
| 710 | + struct nvme_request *nr = nvme_req(req); | |
| 711 | + bool logging_enabled; | |
| 712 | + | |
| 713 | + if (req->q->queuedata) { | |
| 714 | + struct nvme_ns *ns = req->q->disk->private_data; | |
| 715 | + | |
| 716 | + logging_enabled = ns->head->passthru_err_log_enabled; | |
| 683 | 717 | req->timeout = NVME_IO_TIMEOUT; |
| 684 | − else /* no queuedata implies admin queue */ | |
| 718 | + } else { /* no queuedata implies admin queue */ | |
| 719 | + logging_enabled = nr->ctrl->passthru_err_log_enabled; | |
| 685 | 720 | req->timeout = NVME_ADMIN_TIMEOUT; |
| 721 | + } | |
| 722 | + | |
| 723 | + if (!logging_enabled) | |
| 724 | + req->rq_flags |= RQF_QUIET; | |
| 686 | 725 | |
| 687 | 726 | /* passthru commands should let the driver set the SGL flags */ |
| 688 | 727 | cmd->common.flags &= ~NVME_CMD_SGL_ALL; |
| @@ -691,8 +730,7 @@ void nvme_init_request(struct request *req, struct nvme_command *cmd) · 2 unmodified lines | ||
| 691 | 730 | if (req->mq_hctx->type == HCTX_TYPE_POLL) |
| 692 | 731 | req->cmd_flags |= REQ_POLLED; |
| 693 | 732 | nvme_clear_nvme_request(req); |
| 694 | − req->rq_flags |= RQF_QUIET; | |
| 695 | − memcpy(nvme_req(req)->cmd, cmd, sizeof(*cmd)); | |
| 733 | + memcpy(nr->cmd, cmd, sizeof(*cmd)); | |
| 696 | 734 | } |
| 697 | 735 | EXPORT_SYMBOL_GPL(nvme_init_request); |
| 698 | 736 | |
| @@ -721,7 +759,7 @@ blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, · 22 unmodified lines | ||
| 721 | 759 | EXPORT_SYMBOL_GPL(nvme_fail_nonready_command); |
| 722 | 760 | |
| 723 | 761 | bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, |
| 724 | − bool queue_live) | |
| 762 | + bool queue_live, enum nvme_ctrl_state state) | |
| 725 | 763 | { |
| 726 | 764 | struct nvme_request *req = nvme_req(rq); |
| 727 | 765 | |
| @@ -742,7 +780,7 @@ bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, · 14 unmodified lines | ||
| 742 | 780 | * command, which is require to set the queue live in the |
| 743 | 781 | * appropinquate states. |
| 744 | 782 | */ |
| 745 | − switch (nvme_ctrl_state(ctrl)) { | |
| 783 | + switch (state) { | |
| 746 | 784 | case NVME_CTRL_CONNECTING: |
| 747 | 785 | if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) && |
| 748 | 786 | (req->cmd->fabrics.fctype == nvme_fabrics_type_connect || |
| @@ -1051,20 +1089,27 @@ EXPORT_SYMBOL_NS_GPL(nvme_execute_rq, NVME_TARGET_PASSTHRU); · 302 unmodified lines | ||
| 1051 | 1089 | */ |
| 1052 | 1090 | int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| 1053 | 1091 | union nvme_result *result, void *buffer, unsigned bufflen, |
| 1054 | − int qid, int at_head, blk_mq_req_flags_t flags) | |
| 1092 | + int qid, nvme_submit_flags_t flags) | |
| 1055 | 1093 | { |
| 1056 | 1094 | struct request *req; |
| 1057 | 1095 | int ret; |
| 1096 | + blk_mq_req_flags_t blk_flags = 0; | |
| 1058 | 1097 | |
| 1098 | + if (flags & NVME_SUBMIT_NOWAIT) | |
| 1099 | + blk_flags |= BLK_MQ_REQ_NOWAIT; | |
| 1100 | + if (flags & NVME_SUBMIT_RESERVED) | |
| 1101 | + blk_flags |= BLK_MQ_REQ_RESERVED; | |
| 1059 | 1102 | if (qid == NVME_QID_ANY) |
| 1060 | − req = blk_mq_alloc_request(q, nvme_req_op(cmd), flags); | |
| 1103 | + req = blk_mq_alloc_request(q, nvme_req_op(cmd), blk_flags); | |
| 1061 | 1104 | else |
| 1062 | − req = blk_mq_alloc_request_hctx(q, nvme_req_op(cmd), flags, | |
| 1105 | + req = blk_mq_alloc_request_hctx(q, nvme_req_op(cmd), blk_flags, | |
| 1063 | 1106 | qid - 1); |
| 1064 | 1107 | |
| 1065 | 1108 | if (IS_ERR(req)) |
| 1066 | 1109 | return PTR_ERR(req); |
| 1067 | 1110 | nvme_init_request(req, cmd); |
| 1111 | + if (flags & NVME_SUBMIT_RETRY) | |
| 1112 | + req->cmd_flags &= ~REQ_FAILFAST_DRIVER; | |
| 1068 | 1113 | |
| 1069 | 1114 | if (buffer && bufflen) { |
| 1070 | 1115 | ret = blk_rq_map_kern(q, req, buffer, bufflen, GFP_KERNEL); |
| @@ -1072,7 +1117,7 @@ int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, · 1 unmodified line | ||
| 1072 | 1117 | goto out; |
| 1073 | 1118 | } |
| 1074 | 1119 | |
| 1075 | − ret = nvme_execute_rq(req, at_head); | |
| 1120 | + ret = nvme_execute_rq(req, flags & NVME_SUBMIT_AT_HEAD); | |
| 1076 | 1121 | if (result && ret >= 0) |
| 1077 | 1122 | *result = nvme_req(req)->result; |
| 1078 | 1123 | out: |
| @@ -1085,7 +1130,7 @@ int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, · 6 unmodified lines | ||
| 1085 | 1130 | void *buffer, unsigned bufflen) |
| 1086 | 1131 | { |
| 1087 | 1132 | return __nvme_submit_sync_cmd(q, cmd, NULL, buffer, bufflen, |
| 1088 | − NVME_QID_ANY, 0, 0); | |
| 1133 | + NVME_QID_ANY, 0); | |
| 1089 | 1134 | } |
| 1090 | 1135 | EXPORT_SYMBOL_GPL(nvme_submit_sync_cmd); |
| 1091 | 1136 | |
| @@ -1560,7 +1605,7 @@ static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid, · 468 unmodified lines | ||
| 1560 | 1605 | c.features.dword11 = cpu_to_le32(dword11); |
| 1561 | 1606 | |
| 1562 | 1607 | ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &res, |
| 1563 | − buffer, buflen, NVME_QID_ANY, 0, 0); | |
| 1608 | + buffer, buflen, NVME_QID_ANY, 0); | |
| 1564 | 1609 | if (ret >= 0 && result) |
| 1565 | 1610 | *result = le32_to_cpu(res.u32); |
| 1566 | 1611 | return ret; |
| @@ -2172,7 +2217,7 @@ static int nvme_sec_submit(void *data, u16 spsp, u8 secp, void *buffer, size_t l · 605 unmodified lines | ||
| 2172 | 2217 | cmd.common.cdw11 = cpu_to_le32(len); |
| 2173 | 2218 | |
| 2174 | 2219 | return __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, NULL, buffer, len, |
| 2175 | − NVME_QID_ANY, 1, 0); | |
| 2220 | + NVME_QID_ANY, NVME_SUBMIT_AT_HEAD); | |
| 2176 | 2221 | } |
| 2177 | 2222 | |
| 2178 | 2223 | static void nvme_configure_opal(struct nvme_ctrl *ctrl, bool was_suspended) |
| @@ -3714,6 +3759,13 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info) · 1535 unmodified lines | ||
| 3714 | 3759 | nvme_mpath_add_disk(ns, info->anagrpid); |
| 3715 | 3760 | nvme_fault_inject_init(&ns->fault_inject, ns->disk->disk_name); |
| 3716 | 3761 | |
| 3762 | + /* | |
| 3763 | + * Set ns->disk->device->driver_data to ns so we can access | |
| 3764 | + * ns->head->passthru_err_log_enabled in | |
| 3765 | + * nvme_io_passthru_err_log_enabled_[store | show](). | |
| 3766 | + */ | |
| 3767 | + dev_set_drvdata(disk_to_dev(ns->disk), ns); | |
| 3768 | + | |
| 3717 | 3769 | return; |
| 3718 | 3770 | |
| 3719 | 3771 | out_cleanup_ns_from_list: |
| @@ -4138,6 +4190,7 @@ static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl) · 418 unmodified lines | ||
| 4138 | 4190 | static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl) |
| 4139 | 4191 | { |
| 4140 | 4192 | struct nvme_fw_slot_info_log *log; |
| 4193 | + u8 next_fw_slot, cur_fw_slot; | |
| 4141 | 4194 | |
| 4142 | 4195 | log = kmalloc(sizeof(*log), GFP_KERNEL); |
| 4143 | 4196 | if (!log) |
| @@ -4149,13 +4202,15 @@ static void nvme_get_fw_slot_info(struct nvme_ctrl *ctrl) · 5 unmodified lines | ||
| 4149 | 4202 | goto out_free_log; |
| 4150 | 4203 | } |
| 4151 | 4204 | |
| 4152 | − if (log->afi & 0x70 || !(log->afi & 0x7)) { | |
| 4205 | + cur_fw_slot = log->afi & 0x7; | |
| 4206 | + next_fw_slot = (log->afi & 0x70) >> 4; | |
| 4207 | + if (!cur_fw_slot || (next_fw_slot && (cur_fw_slot != next_fw_slot))) { | |
| 4153 | 4208 | dev_info(ctrl->device, |
| 4154 | 4209 | "Firmware is activated after next Controller Level Reset\n"); |
| 4155 | 4210 | goto out_free_log; |
| 4156 | 4211 | } |
| 4157 | 4212 | |
| 4158 | − memcpy(ctrl->subsys->firmware_rev, &log->frs[(log->afi & 0x7) - 1], | |
| 4213 | + memcpy(ctrl->subsys->firmware_rev, &log->frs[cur_fw_slot - 1], | |
| 4159 | 4214 | sizeof(ctrl->subsys->firmware_rev)); |
| 4160 | 4215 | |
| 4161 | 4216 | out_free_log: |
| @@ -4514,6 +4569,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, · 352 unmodified lines | ||
| 4514 | 4569 | int ret; |
| 4515 | 4570 | |
| 4516 | 4571 | WRITE_ONCE(ctrl->state, NVME_CTRL_NEW); |
| 4572 | + ctrl->passthru_err_log_enabled = false; | |
| 4517 | 4573 | clear_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags); |
| 4518 | 4574 | spin_lock_init(&ctrl->lock); |
| 4519 | 4575 | mutex_init(&ctrl->scan_lock); |
| @@ -4851,5 +4907,6 @@ static void __exit nvme_core_exit(void) · 331 unmodified lines | ||
| 4851 | 4907 | |
| 4852 | 4908 | MODULE_LICENSE("GPL"); |
| 4853 | 4909 | MODULE_VERSION("1.0"); |
| 4910 | +MODULE_DESCRIPTION("NVMe host core framework"); | |
| 4854 | 4911 | module_init(nvme_core_init); |
| 4855 | 4912 | module_exit(nvme_core_exit); |
| @@ -180,7 +180,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val) · 179 unmodified lines | ||
| 180 | 180 | cmd.prop_get.offset = cpu_to_le32(off); |
| 181 | 181 | |
| 182 | 182 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, |
| 183 | − NVME_QID_ANY, 0, 0); | |
| 183 | + NVME_QID_ANY, 0); | |
| 184 | 184 | |
| 185 | 185 | if (ret >= 0) |
| 186 | 186 | *val = le64_to_cpu(res.u64); |
| @@ -226,7 +226,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val) · 39 unmodified lines | ||
| 226 | 226 | cmd.prop_get.offset = cpu_to_le32(off); |
| 227 | 227 | |
| 228 | 228 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0, |
| 229 | − NVME_QID_ANY, 0, 0); | |
| 229 | + NVME_QID_ANY, 0); | |
| 230 | 230 | |
| 231 | 231 | if (ret >= 0) |
| 232 | 232 | *val = le64_to_cpu(res.u64); |
| @@ -271,7 +271,7 @@ int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val) · 38 unmodified lines | ||
| 271 | 271 | cmd.prop_set.value = cpu_to_le64(val); |
| 272 | 272 | |
| 273 | 273 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, NULL, NULL, 0, |
| 274 | − NVME_QID_ANY, 0, 0); | |
| 274 | + NVME_QID_ANY, 0); | |
| 275 | 275 | if (unlikely(ret)) |
| 276 | 276 | dev_err(ctrl->device, |
| 277 | 277 | "Property Set error: %d, offset %#x\n", |
| @@ -450,8 +450,10 @@ int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl) · 172 unmodified lines | ||
| 450 | 450 | return -ENOMEM; |
| 451 | 451 | |
| 452 | 452 | ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, |
| 453 | − data, sizeof(*data), NVME_QID_ANY, 1, | |
| 454 | − BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); | |
| 453 | + data, sizeof(*data), NVME_QID_ANY, | |
| 454 | + NVME_SUBMIT_AT_HEAD | | |
| 455 | + NVME_SUBMIT_NOWAIT | | |
| 456 | + NVME_SUBMIT_RESERVED); | |
| 455 | 457 | if (ret) { |
| 456 | 458 | nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32), |
| 457 | 459 | &cmd, data); |
| @@ -525,8 +527,10 @@ int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid) · 67 unmodified lines | ||
| 525 | 527 | return -ENOMEM; |
| 526 | 528 | |
| 527 | 529 | ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res, |
| 528 | − data, sizeof(*data), qid, 1, | |
| 529 | − BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); | |
| 530 | + data, sizeof(*data), qid, | |
| 531 | + NVME_SUBMIT_AT_HEAD | | |
| 532 | + NVME_SUBMIT_RESERVED | | |
| 533 | + NVME_SUBMIT_NOWAIT); | |
| 530 | 534 | if (ret) { |
| 531 | 535 | nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32), |
| 532 | 536 | &cmd, data); |
| @@ -1488,6 +1492,7 @@ static void __exit nvmf_exit(void) · 955 unmodified lines | ||
| 1488 | 1492 | } |
| 1489 | 1493 | |
| 1490 | 1494 | MODULE_LICENSE("GPL v2"); |
| 1495 | +MODULE_DESCRIPTION("NVMe host fabrics library"); | |
| 1491 | 1496 | |
| 1492 | 1497 | module_init(nvmf_init); |
| 1493 | 1498 | module_exit(nvmf_exit); |
| @@ -185,9 +185,11 @@ static inline bool · 184 unmodified lines | ||
| 185 | 185 | nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl, |
| 186 | 186 | struct nvmf_ctrl_options *opts) |
| 187 | 187 | { |
| 188 | − if (ctrl->state == NVME_CTRL_DELETING || | |
| 189 | − ctrl->state == NVME_CTRL_DELETING_NOIO || | |
| 190 | − ctrl->state == NVME_CTRL_DEAD || | |
| 188 | + enum nvme_ctrl_state state = nvme_ctrl_state(ctrl); | |
| 189 | + | |
| 190 | + if (state == NVME_CTRL_DELETING || | |
| 191 | + state == NVME_CTRL_DELETING_NOIO || | |
| 192 | + state == NVME_CTRL_DEAD || | |
| 191 | 193 | strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || |
| 192 | 194 | strcmp(opts->host->nqn, ctrl->opts->host->nqn) || |
| 193 | 195 | !uuid_equal(&opts->host->id, &ctrl->opts->host->id)) |
| @@ -221,11 +221,6 @@ static LIST_HEAD(nvme_fc_lport_list); · 220 unmodified lines | ||
| 221 | 221 | static DEFINE_IDA(nvme_fc_local_port_cnt); |
| 222 | 222 | static DEFINE_IDA(nvme_fc_ctrl_cnt); |
| 223 | 223 | |
| 224 | −static struct workqueue_struct *nvme_fc_wq; | |
| 225 | − | |
| 226 | −static bool nvme_fc_waiting_to_unload; | |
| 227 | −static DECLARE_COMPLETION(nvme_fc_unload_proceed); | |
| 228 | − | |
| 229 | 224 | /* |
| 230 | 225 | * These items are short-term. They will eventually be moved into |
| 231 | 226 | * a generic FC class. See comments in module init. |
| @@ -255,8 +250,6 @@ nvme_fc_free_lport(struct kref *ref) · 23 unmodified lines | ||
| 255 | 250 | /* remove from transport list */ |
| 256 | 251 | spin_lock_irqsave(&nvme_fc_lock, flags); |
| 257 | 252 | list_del(&lport->port_list); |
| 258 | − if (nvme_fc_waiting_to_unload && list_empty(&nvme_fc_lport_list)) | |
| 259 | − complete(&nvme_fc_unload_proceed); | |
| 260 | 253 | spin_unlock_irqrestore(&nvme_fc_lock, flags); |
| 261 | 254 | |
| 262 | 255 | ida_free(&nvme_fc_local_port_cnt, lport->localport.port_num); |
| @@ -2574,6 +2567,7 @@ static enum blk_eh_timer_return nvme_fc_timeout(struct request *rq) · 2311 unmodified lines | ||
| 2574 | 2567 | { |
| 2575 | 2568 | struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq); |
| 2576 | 2569 | struct nvme_fc_ctrl *ctrl = op->ctrl; |
| 2570 | + u16 qnum = op->queue->qnum; | |
| 2577 | 2571 | struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu; |
| 2578 | 2572 | struct nvme_command *sqe = &cmdiu->sqe; |
| 2579 | 2573 | |
| @@ -2582,10 +2576,11 @@ static enum blk_eh_timer_return nvme_fc_timeout(struct request *rq) · 2 unmodified lines | ||
| 2582 | 2576 | * will detect the aborted io and will fail the connection. |
| 2583 | 2577 | */ |
| 2584 | 2578 | dev_info(ctrl->ctrl.device, |
| 2585 | − "NVME-FC{%d.%d}: io timeout: opcode %d fctype %d w10/11: " | |
| 2579 | + "NVME-FC{%d.%d}: io timeout: opcode %d fctype %d (%s) w10/11: " | |
| 2586 | 2580 | "x%08x/x%08x\n", |
| 2587 | − ctrl->cnum, op->queue->qnum, sqe->common.opcode, | |
| 2588 | − sqe->connect.fctype, sqe->common.cdw10, sqe->common.cdw11); | |
| 2581 | + ctrl->cnum, qnum, sqe->common.opcode, sqe->fabrics.fctype, | |
| 2582 | + nvme_fabrics_opcode_str(qnum, sqe), | |
| 2583 | + sqe->common.cdw10, sqe->common.cdw11); | |
| 2589 | 2584 | if (__nvme_fc_abort_op(ctrl, op)) |
| 2590 | 2585 | nvme_fc_error_recovery(ctrl, "io timeout abort failed"); |
| 2591 | 2586 | |
| @@ -3575,8 +3570,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, · 983 unmodified lines | ||
| 3575 | 3570 | flush_delayed_work(&ctrl->connect_work); |
| 3576 | 3571 | |
| 3577 | 3572 | dev_info(ctrl->ctrl.device, |
| 3578 | − "NVME-FC{%d}: new ctrl: NQN \"%s\"\n", | |
| 3579 | − ctrl->cnum, nvmf_ctrl_subsysnqn(&ctrl->ctrl)); | |
| 3573 | + "NVME-FC{%d}: new ctrl: NQN \"%s\", hostnqn: %s\n", | |
| 3574 | + ctrl->cnum, nvmf_ctrl_subsysnqn(&ctrl->ctrl), opts->host->nqn); | |
| 3580 | 3575 | |
| 3581 | 3576 | return &ctrl->ctrl; |
| 3582 | 3577 | |
| @@ -3894,10 +3889,6 @@ static int __init nvme_fc_init_module(void) · 311 unmodified lines | ||
| 3894 | 3889 | { |
| 3895 | 3890 | int ret; |
| 3896 | 3891 | |
| 3897 | − nvme_fc_wq = alloc_workqueue("nvme_fc_wq", WQ_MEM_RECLAIM, 0); | |
| 3898 | − if (!nvme_fc_wq) | |
| 3899 | − return -ENOMEM; | |
| 3900 | − | |
| 3901 | 3892 | /* |
| 3902 | 3893 | * NOTE: |
| 3903 | 3894 | * It is expected that in the future the kernel will combine |
| @@ -3915,7 +3906,7 @@ static int __init nvme_fc_init_module(void) · 11 unmodified lines | ||
| 3915 | 3906 | ret = class_register(&fc_class); |
| 3916 | 3907 | if (ret) { |
| 3917 | 3908 | pr_err("couldn't register class fc\n"); |
| 3918 | − goto out_destroy_wq; | |
| 3909 | + return ret; | |
| 3919 | 3910 | } |
| 3920 | 3911 | |
| 3921 | 3912 | /* |
| @@ -3939,8 +3930,6 @@ out_destroy_device: · 17 unmodified lines | ||
| 3939 | 3930 | device_destroy(&fc_class, MKDEV(0, 0)); |
| 3940 | 3931 | out_destroy_class: |
| 3941 | 3932 | class_unregister(&fc_class); |
| 3942 | −out_destroy_wq: | |
| 3943 | − destroy_workqueue(nvme_fc_wq); | |
| 3944 | 3933 | |
| 3945 | 3934 | return ret; |
| 3946 | 3935 | } |
| @@ -3960,48 +3949,27 @@ nvme_fc_delete_controllers(struct nvme_fc_rport *rport) · 13 unmodified lines | ||
| 3960 | 3949 | spin_unlock(&rport->lock); |
| 3961 | 3950 | } |
| 3962 | 3951 | |
| 3963 | −static void | |
| 3964 | −nvme_fc_cleanup_for_unload(void) | |
| 3952 | +static void __exit nvme_fc_exit_module(void) | |
| 3965 | 3953 | { |
| 3966 | 3954 | struct nvme_fc_lport *lport; |
| 3967 | 3955 | struct nvme_fc_rport *rport; |
| 3968 | − | |
| 3969 | − list_for_each_entry(lport, &nvme_fc_lport_list, port_list) { | |
| 3970 | − list_for_each_entry(rport, &lport->endp_list, endp_list) { | |
| 3971 | − nvme_fc_delete_controllers(rport); | |
| 3972 | − } | |
| 3973 | − } | |
| 3974 | −} | |
| 3975 | − | |
| 3976 | −static void __exit nvme_fc_exit_module(void) | |
| 3977 | −{ | |
| 3978 | 3956 | unsigned long flags; |
| 3979 | − bool need_cleanup = false; | |
| 3980 | 3957 | |
| 3981 | 3958 | spin_lock_irqsave(&nvme_fc_lock, flags); |
| 3982 | − nvme_fc_waiting_to_unload = true; | |
| 3983 | − if (!list_empty(&nvme_fc_lport_list)) { | |
| 3984 | − need_cleanup = true; | |
| 3985 | − nvme_fc_cleanup_for_unload(); | |
| 3986 | − } | |
| 3959 | + list_for_each_entry(lport, &nvme_fc_lport_list, port_list) | |
| 3960 | + list_for_each_entry(rport, &lport->endp_list, endp_list) | |
| 3961 | + nvme_fc_delete_controllers(rport); | |
| 3987 | 3962 | spin_unlock_irqrestore(&nvme_fc_lock, flags); |
| 3988 | − if (need_cleanup) { | |
| 3989 | − pr_info("%s: waiting for ctlr deletes\n", __func__); | |
| 3990 | − wait_for_completion(&nvme_fc_unload_proceed); | |
| 3991 | − pr_info("%s: ctrl deletes complete\n", __func__); | |
| 3992 | − } | |
| 3963 | + flush_workqueue(nvme_delete_wq); | |
| 3993 | 3964 | |
| 3994 | 3965 | nvmf_unregister_transport(&nvme_fc_transport); |
| 3995 | 3966 | |
| 3996 | − ida_destroy(&nvme_fc_local_port_cnt); | |
| 3997 | − ida_destroy(&nvme_fc_ctrl_cnt); | |
| 3998 | − | |
| 3999 | 3967 | device_destroy(&fc_class, MKDEV(0, 0)); |
| 4000 | 3968 | class_unregister(&fc_class); |
| 4001 | − destroy_workqueue(nvme_fc_wq); | |
| 4002 | 3969 | } |
| 4003 | 3970 | |
| 4004 | 3971 | module_init(nvme_fc_init_module); |
| 4005 | 3972 | module_exit(nvme_fc_exit_module); |
| 4006 | 3973 | |
| 3974 | +MODULE_DESCRIPTION("NVMe host FC transport driver"); | |
| 4007 | 3975 | MODULE_LICENSE("GPL v2"); |
| @@ -228,7 +228,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) · 227 unmodified lines | ||
| 228 | 228 | length = (io.nblocks + 1) << ns->head->lba_shift; |
| 229 | 229 | |
| 230 | 230 | if ((io.control & NVME_RW_PRINFO_PRACT) && |
| 231 | − ns->head->ms == sizeof(struct t10_pi_tuple)) { | |
| 231 | + (ns->head->ms == ns->head->pi_size)) { | |
| 232 | 232 | /* |
| 233 | 233 | * Protection information is stripped/inserted by the |
| 234 | 234 | * controller. |
| @@ -156,7 +156,7 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl) · 155 unmodified lines | ||
| 156 | 156 | if (!ns->head->disk) |
| 157 | 157 | continue; |
| 158 | 158 | kblockd_schedule_work(&ns->head->requeue_work); |
| 159 | − if (ctrl->state == NVME_CTRL_LIVE) | |
| 159 | + if (nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE) | |
| 160 | 160 | disk_uevent(ns->head->disk, KOBJ_CHANGE); |
| 161 | 161 | } |
| 162 | 162 | up_read(&ctrl->namespaces_rwsem); |
| @@ -223,13 +223,14 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns) · 60 unmodified lines | ||
| 223 | 223 | |
| 224 | 224 | static bool nvme_path_is_disabled(struct nvme_ns *ns) |
| 225 | 225 | { |
| 226 | + enum nvme_ctrl_state state = nvme_ctrl_state(ns->ctrl); | |
| 227 | + | |
| 226 | 228 | /* |
| 227 | 229 | * We don't treat NVME_CTRL_DELETING as a disabled path as I/O should |
| 228 | 230 | * still be able to complete assuming that the controller is connected. |
| 229 | 231 | * Otherwise it will fail immediately and return to the requeue list. |
| 230 | 232 | */ |
| 231 | − if (ns->ctrl->state != NVME_CTRL_LIVE && | |
| 232 | − ns->ctrl->state != NVME_CTRL_DELETING) | |
| 233 | + if (state != NVME_CTRL_LIVE && state != NVME_CTRL_DELETING) | |
| 233 | 234 | return true; |
| 234 | 235 | if (test_bit(NVME_NS_ANA_PENDING, &ns->flags) || |
| 235 | 236 | !test_bit(NVME_NS_READY, &ns->flags)) |
| @@ -331,7 +332,7 @@ out: · 95 unmodified lines | ||
| 331 | 332 | |
| 332 | 333 | static inline bool nvme_path_is_optimized(struct nvme_ns *ns) |
| 333 | 334 | { |
| 334 | − return ns->ctrl->state == NVME_CTRL_LIVE && | |
| 335 | + return nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE && | |
| 335 | 336 | ns->ana_state == NVME_ANA_OPTIMIZED; |
| 336 | 337 | } |
| 337 | 338 | |
| @@ -358,7 +359,7 @@ static bool nvme_available_path(struct nvme_ns_head *head) · 20 unmodified lines | ||
| 358 | 359 | list_for_each_entry_rcu(ns, &head->list, siblings) { |
| 359 | 360 | if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags)) |
| 360 | 361 | continue; |
| 361 | − switch (ns->ctrl->state) { | |
| 362 | + switch (nvme_ctrl_state(ns->ctrl)) { | |
| 362 | 363 | case NVME_CTRL_LIVE: |
| 363 | 364 | case NVME_CTRL_RESETTING: |
| 364 | 365 | case NVME_CTRL_CONNECTING: |
| @@ -667,7 +668,7 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc, · 302 unmodified lines | ||
| 667 | 668 | * controller is ready. |
| 668 | 669 | */ |
| 669 | 670 | if (nvme_state_is_live(ns->ana_state) && |
| 670 | − ns->ctrl->state == NVME_CTRL_LIVE) | |
| 671 | + nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE) | |
| 671 | 672 | nvme_mpath_set_live(ns); |
| 672 | 673 | } |
| 673 | 674 | |
| @@ -748,7 +749,7 @@ static void nvme_ana_work(struct work_struct *work) · 74 unmodified lines | ||
| 748 | 749 | { |
| 749 | 750 | struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work); |
| 750 | 751 | |
| 751 | − if (ctrl->state != NVME_CTRL_LIVE) | |
| 752 | + if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) | |
| 752 | 753 | return; |
| 753 | 754 | |
| 754 | 755 | nvme_read_ana_log(ctrl); |
| @@ -263,6 +263,7 @@ enum nvme_ctrl_flags { · 262 unmodified lines | ||
| 263 | 263 | struct nvme_ctrl { |
| 264 | 264 | bool comp_seen; |
| 265 | 265 | bool identified; |
| 266 | + bool passthru_err_log_enabled; | |
| 266 | 267 | enum nvme_ctrl_state state; |
| 267 | 268 | spinlock_t lock; |
| 268 | 269 | struct mutex scan_lock; |
| @@ -454,6 +455,7 @@ struct nvme_ns_head { · 185 unmodified lines | ||
| 454 | 455 | struct list_head entry; |
| 455 | 456 | struct kref ref; |
| 456 | 457 | bool shared; |
| 458 | + bool passthru_err_log_enabled; | |
| 457 | 459 | int instance; |
| 458 | 460 | struct nvme_effects_log *effects; |
| 459 | 461 | u64 nuse; |
| @@ -522,7 +524,6 @@ struct nvme_ns { · 62 unmodified lines | ||
| 522 | 524 | struct device cdev_device; |
| 523 | 525 | |
| 524 | 526 | struct nvme_fault_inject fault_inject; |
| 525 | − | |
| 526 | 527 | }; |
| 527 | 528 | |
| 528 | 529 | /* NVMe ns supports metadata actions by the controller (generate/strip) */ |
| @@ -805,17 +806,18 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req); · 276 unmodified lines | ||
| 805 | 806 | blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, |
| 806 | 807 | struct request *req); |
| 807 | 808 | bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, |
| 808 | − bool queue_live); | |
| 809 | + bool queue_live, enum nvme_ctrl_state state); | |
| 809 | 810 | |
| 810 | 811 | static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, |
| 811 | 812 | bool queue_live) |
| 812 | 813 | { |
| 813 | − if (likely(ctrl->state == NVME_CTRL_LIVE)) | |
| 814 | + enum nvme_ctrl_state state = nvme_ctrl_state(ctrl); | |
| 815 | + | |
| 816 | + if (likely(state == NVME_CTRL_LIVE)) | |
| 814 | 817 | return true; |
| 815 | − if (ctrl->ops->flags & NVME_F_FABRICS && | |
| 816 | − ctrl->state == NVME_CTRL_DELETING) | |
| 818 | + if (ctrl->ops->flags & NVME_F_FABRICS && state == NVME_CTRL_DELETING) | |
| 817 | 819 | return queue_live; |
| 818 | − return __nvme_check_ready(ctrl, rq, queue_live); | |
| 820 | + return __nvme_check_ready(ctrl, rq, queue_live, state); | |
| 819 | 821 | } |
| 820 | 822 | |
| 821 | 823 | /* |
| @@ -836,12 +838,27 @@ static inline bool nvme_is_unique_nsid(struct nvme_ctrl *ctrl, · 14 unmodified lines | ||
| 836 | 838 | (ctrl->ctratt & NVME_CTRL_CTRATT_NVM_SETS); |
| 837 | 839 | } |
| 838 | 840 | |
| 841 | +/* | |
| 842 | + * Flags for __nvme_submit_sync_cmd() | |
| 843 | + */ | |
| 844 | +typedef __u32 __bitwise nvme_submit_flags_t; | |
| 845 | + | |
| 846 | +enum { | |
| 847 | + /* Insert request at the head of the queue */ | |
| 848 | + NVME_SUBMIT_AT_HEAD = (__force nvme_submit_flags_t)(1 << 0), | |
| 849 | + /* Set BLK_MQ_REQ_NOWAIT when allocating request */ | |
| 850 | + NVME_SUBMIT_NOWAIT = (__force nvme_submit_flags_t)(1 << 1), | |
| 851 | + /* Set BLK_MQ_REQ_RESERVED when allocating request */ | |
| 852 | + NVME_SUBMIT_RESERVED = (__force nvme_submit_flags_t)(1 << 2), | |
| 853 | + /* Retry command when NVME_SC_DNR is not set in the result */ | |
| 854 | + NVME_SUBMIT_RETRY = (__force nvme_submit_flags_t)(1 << 3), | |
| 855 | +}; | |
| 856 | + | |
| 839 | 857 | int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| 840 | 858 | void *buf, unsigned bufflen); |
| 841 | 859 | int __nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| 842 | 860 | union nvme_result *result, void *buffer, unsigned bufflen, |
| 843 | − int qid, int at_head, | |
| 844 | − blk_mq_req_flags_t flags); | |
| 861 | + int qid, nvme_submit_flags_t flags); | |
| 845 | 862 | int nvme_set_features(struct nvme_ctrl *dev, unsigned int fid, |
| 846 | 863 | unsigned int dword11, void *buffer, size_t buflen, |
| 847 | 864 | u32 *result); |
| @@ -1124,35 +1141,42 @@ static inline bool nvme_multi_css(struct nvme_ctrl *ctrl) · 276 unmodified lines | ||
| 1124 | 1141 | } |
| 1125 | 1142 | |
| 1126 | 1143 | #ifdef CONFIG_NVME_VERBOSE_ERRORS |
| 1127 | −const unsigned char *nvme_get_error_status_str(u16 status); | |
| 1128 | −const unsigned char *nvme_get_opcode_str(u8 opcode); | |
| 1129 | −const unsigned char *nvme_get_admin_opcode_str(u8 opcode); | |
| 1130 | −const unsigned char *nvme_get_fabrics_opcode_str(u8 opcode); | |
| 1144 | +const char *nvme_get_error_status_str(u16 status); | |
| 1145 | +const char *nvme_get_opcode_str(u8 opcode); | |
| 1146 | +const char *nvme_get_admin_opcode_str(u8 opcode); | |
| 1147 | +const char *nvme_get_fabrics_opcode_str(u8 opcode); | |
| 1131 | 1148 | #else /* CONFIG_NVME_VERBOSE_ERRORS */ |
| 1132 | −static inline const unsigned char *nvme_get_error_status_str(u16 status) | |
| 1149 | +static inline const char *nvme_get_error_status_str(u16 status) | |
| 1133 | 1150 | { |
| 1134 | 1151 | return "I/O Error"; |
| 1135 | 1152 | } |
| 1136 | −static inline const unsigned char *nvme_get_opcode_str(u8 opcode) | |
| 1153 | +static inline const char *nvme_get_opcode_str(u8 opcode) | |
| 1137 | 1154 | { |
| 1138 | 1155 | return "I/O Cmd"; |
| 1139 | 1156 | } |
| 1140 | −static inline const unsigned char *nvme_get_admin_opcode_str(u8 opcode) | |
| 1157 | +static inline const char *nvme_get_admin_opcode_str(u8 opcode) | |
| 1141 | 1158 | { |
| 1142 | 1159 | return "Admin Cmd"; |
| 1143 | 1160 | } |
| 1144 | 1161 | |
| 1145 | −static inline const unsigned char *nvme_get_fabrics_opcode_str(u8 opcode) | |
| 1162 | +static inline const char *nvme_get_fabrics_opcode_str(u8 opcode) | |
| 1146 | 1163 | { |
| 1147 | 1164 | return "Fabrics Cmd"; |
| 1148 | 1165 | } |
| 1149 | 1166 | #endif /* CONFIG_NVME_VERBOSE_ERRORS */ |
| 1150 | 1167 | |
| 1151 | −static inline const unsigned char *nvme_opcode_str(int qid, u8 opcode, u8 fctype) | |
| 1168 | +static inline const char *nvme_opcode_str(int qid, u8 opcode) | |
| 1152 | 1169 | { |
| 1153 | − if (opcode == nvme_fabrics_command) | |
| 1154 | − return nvme_get_fabrics_opcode_str(fctype); | |
| 1155 | 1170 | return qid ? nvme_get_opcode_str(opcode) : |
| 1156 | 1171 | nvme_get_admin_opcode_str(opcode); |
| 1157 | 1172 | } |
| 1173 | + | |
| 1174 | +static inline const char *nvme_fabrics_opcode_str( | |
| 1175 | + int qid, const struct nvme_command *cmd) | |
| 1176 | +{ | |
| 1177 | + if (nvme_is_fabrics(cmd)) | |
| 1178 | + return nvme_get_fabrics_opcode_str(cmd->fabrics.fctype); | |
| 1179 | + | |
| 1180 | + return nvme_opcode_str(qid, cmd->common.opcode); | |
| 1181 | +} | |
| 1158 | 1182 | #endif /* _NVME_H */ |
| @@ -1349,7 +1349,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req) · 1348 unmodified lines | ||
| 1349 | 1349 | dev_warn(dev->ctrl.device, |
| 1350 | 1350 | "I/O tag %d (%04x) opcode %#x (%s) QID %d timeout, reset controller\n", |
| 1351 | 1351 | req->tag, nvme_cid(req), opcode, |
| 1352 | − nvme_opcode_str(nvmeq->qid, opcode, 0), nvmeq->qid); | |
| 1352 | + nvme_opcode_str(nvmeq->qid, opcode), nvmeq->qid); | |
| 1353 | 1353 | nvme_req(req)->flags |= NVME_REQ_CANCELLED; |
| 1354 | 1354 | goto disable; |
| 1355 | 1355 | } |
| @@ -3543,5 +3543,6 @@ static void __exit nvme_exit(void) · 2187 unmodified lines | ||
| 3543 | 3543 | MODULE_AUTHOR("Matthew Wilcox <willy@linux.intel.com>"); |
| 3544 | 3544 | MODULE_LICENSE("GPL"); |
| 3545 | 3545 | MODULE_VERSION("1.0"); |
| 3546 | +MODULE_DESCRIPTION("NVMe host PCIe transport driver"); | |
| 3546 | 3547 | module_init(nvme_init); |
| 3547 | 3548 | module_exit(nvme_exit); |
| @@ -1410,6 +1410,8 @@ static int nvme_rdma_map_sg_pi(struct nvme_rdma_queue *queue, · 1409 unmodified lines | ||
| 1410 | 1410 | struct nvme_ns *ns = rq->q->queuedata; |
| 1411 | 1411 | struct bio *bio = rq->bio; |
| 1412 | 1412 | struct nvme_keyed_sgl_desc *sg = &c->common.dptr.ksgl; |
| 1413 | + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); | |
| 1414 | + u32 xfer_len; | |
| 1413 | 1415 | int nr; |
| 1414 | 1416 | |
| 1415 | 1417 | req->mr = ib_mr_pool_get(queue->qp, &queue->qp->sig_mrs); |
| @@ -1422,8 +1424,7 @@ static int nvme_rdma_map_sg_pi(struct nvme_rdma_queue *queue, · 6 unmodified lines | ||
| 1422 | 1424 | if (unlikely(nr)) |
| 1423 | 1425 | goto mr_put; |
| 1424 | 1426 | |
| 1425 | − nvme_rdma_set_sig_attrs(blk_get_integrity(bio->bi_bdev->bd_disk), c, | |
| 1426 | − req->mr->sig_attrs, ns->head->pi_type); | |
| 1427 | + nvme_rdma_set_sig_attrs(bi, c, req->mr->sig_attrs, ns->head->pi_type); | |
| 1427 | 1428 | nvme_rdma_set_prot_checks(c, &req->mr->sig_attrs->check_mask); |
| 1428 | 1429 | |
| 1429 | 1430 | ib_update_fast_reg_key(req->mr, ib_inc_rkey(req->mr->rkey)); |
| @@ -1441,7 +1442,11 @@ static int nvme_rdma_map_sg_pi(struct nvme_rdma_queue *queue, · 11 unmodified lines | ||
| 1441 | 1442 | IB_ACCESS_REMOTE_WRITE; |
| 1442 | 1443 | |
| 1443 | 1444 | sg->addr = cpu_to_le64(req->mr->iova); |
| 1444 | − put_unaligned_le24(req->mr->length, sg->length); | |
| 1445 | + xfer_len = req->mr->length; | |
| 1446 | + /* Check if PI is added by the HW */ | |
| 1447 | + if (!pi_count) | |
| 1448 | + xfer_len += (xfer_len >> bi->interval_exp) * ns->head->pi_size; | |
| 1449 | + put_unaligned_le24(xfer_len, sg->length); | |
| 1445 | 1450 | put_unaligned_le32(req->mr->rkey, sg->key); |
| 1446 | 1451 | sg->type = NVME_KEY_SGL_FMT_DATA_DESC << 4; |
| 1447 | 1452 | |
| @@ -1946,14 +1951,13 @@ static enum blk_eh_timer_return nvme_rdma_timeout(struct request *rq) · 498 unmodified lines | ||
| 1946 | 1951 | struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq); |
| 1947 | 1952 | struct nvme_rdma_queue *queue = req->queue; |
| 1948 | 1953 | struct nvme_rdma_ctrl *ctrl = queue->ctrl; |
| 1949 | − u8 opcode = req->req.cmd->common.opcode; | |
| 1950 | − u8 fctype = req->req.cmd->fabrics.fctype; | |
| 1954 | + struct nvme_command *cmd = req->req.cmd; | |
| 1951 | 1955 | int qid = nvme_rdma_queue_idx(queue); |
| 1952 | 1956 | |
| 1953 | 1957 | dev_warn(ctrl->ctrl.device, |
| 1954 | 1958 | "I/O tag %d (%04x) opcode %#x (%s) QID %d timeout\n", |
| 1955 | − rq->tag, nvme_cid(rq), opcode, | |
| 1956 | − nvme_opcode_str(qid, opcode, fctype), qid); | |
| 1959 | + rq->tag, nvme_cid(rq), cmd->common.opcode, | |
| 1960 | + nvme_fabrics_opcode_str(qid, cmd), qid); | |
| 1957 | 1961 | |
| 1958 | 1962 | if (nvme_ctrl_state(&ctrl->ctrl) != NVME_CTRL_LIVE) { |
| 1959 | 1963 | /* |
| @@ -2296,8 +2300,8 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, · 336 unmodified lines | ||
| 2296 | 2300 | if (ret) |
| 2297 | 2301 | goto out_uninit_ctrl; |
| 2298 | 2302 | |
| 2299 | − dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs\n", | |
| 2300 | − nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr); | |
| 2303 | + dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs, hostnqn: %s\n", | |
| 2304 | + nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr, opts->host->nqn); | |
| 2301 | 2305 | |
| 2302 | 2306 | mutex_lock(&nvme_rdma_ctrl_mutex); |
| 2303 | 2307 | list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list); |
| @@ -2400,4 +2404,5 @@ static void __exit nvme_rdma_cleanup_module(void) · 96 unmodified lines | ||
| 2400 | 2404 | module_init(nvme_rdma_init_module); |
| 2401 | 2405 | module_exit(nvme_rdma_cleanup_module); |
| 2402 | 2406 | |
| 2407 | +MODULE_DESCRIPTION("NVMe host RDMA transport driver"); | |
| 2403 | 2408 | MODULE_LICENSE("GPL v2"); |
| @@ -35,6 +35,31 @@ static ssize_t nvme_sysfs_rescan(struct device *dev, · 34 unmodified lines | ||
| 35 | 35 | } |
| 36 | 36 | static DEVICE_ATTR(rescan_controller, S_IWUSR, NULL, nvme_sysfs_rescan); |
| 37 | 37 | |
| 38 | +static ssize_t nvme_adm_passthru_err_log_enabled_show(struct device *dev, | |
| 39 | + struct device_attribute *attr, char *buf) | |
| 40 | +{ | |
| 41 | + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); | |
| 42 | + | |
| 43 | + return sysfs_emit(buf, | |
| 44 | + ctrl->passthru_err_log_enabled ? "on\n" : "off\n"); | |
| 45 | +} | |
| 46 | + | |
| 47 | +static ssize_t nvme_adm_passthru_err_log_enabled_store(struct device *dev, | |
| 48 | + struct device_attribute *attr, const char *buf, size_t count) | |
| 49 | +{ | |
| 50 | + struct nvme_ctrl *ctrl = dev_get_drvdata(dev); | |
| 51 | + bool passthru_err_log_enabled; | |
| 52 | + int err; | |
| 53 | + | |
| 54 | + err = kstrtobool(buf, &passthru_err_log_enabled); | |
| 55 | + if (err) | |
| 56 | + return -EINVAL; | |
| 57 | + | |
| 58 | + ctrl->passthru_err_log_enabled = passthru_err_log_enabled; | |
| 59 | + | |
| 60 | + return count; | |
| 61 | +} | |
| 62 | + | |
| 38 | 63 | static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev) |
| 39 | 64 | { |
| 40 | 65 | struct gendisk *disk = dev_to_disk(dev); |
| @@ -44,6 +69,37 @@ static inline struct nvme_ns_head *dev_to_ns_head(struct device *dev) · 3 unmodified lines | ||
| 44 | 69 | return nvme_get_ns_from_dev(dev)->head; |
| 45 | 70 | } |
| 46 | 71 | |
| 72 | +static ssize_t nvme_io_passthru_err_log_enabled_show(struct device *dev, | |
| 73 | + struct device_attribute *attr, char *buf) | |
| 74 | +{ | |
| 75 | + struct nvme_ns_head *head = dev_to_ns_head(dev); | |
| 76 | + | |
| 77 | + return sysfs_emit(buf, head->passthru_err_log_enabled ? "on\n" : "off\n"); | |
| 78 | +} | |
| 79 | + | |
| 80 | +static ssize_t nvme_io_passthru_err_log_enabled_store(struct device *dev, | |
| 81 | + struct device_attribute *attr, const char *buf, size_t count) | |
| 82 | +{ | |
| 83 | + struct nvme_ns_head *head = dev_to_ns_head(dev); | |
| 84 | + bool passthru_err_log_enabled; | |
| 85 | + int err; | |
| 86 | + | |
| 87 | + err = kstrtobool(buf, &passthru_err_log_enabled); | |
| 88 | + if (err) | |
| 89 | + return -EINVAL; | |
| 90 | + head->passthru_err_log_enabled = passthru_err_log_enabled; | |
| 91 | + | |
| 92 | + return count; | |
| 93 | +} | |
| 94 | + | |
| 95 | +static struct device_attribute dev_attr_adm_passthru_err_log_enabled = \ | |
| 96 | + __ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \ | |
| 97 | + nvme_adm_passthru_err_log_enabled_show, nvme_adm_passthru_err_log_enabled_store); | |
| 98 | + | |
| 99 | +static struct device_attribute dev_attr_io_passthru_err_log_enabled = \ | |
| 100 | + __ATTR(passthru_err_log_enabled, S_IRUGO | S_IWUSR, \ | |
| 101 | + nvme_io_passthru_err_log_enabled_show, nvme_io_passthru_err_log_enabled_store); | |
| 102 | + | |
| 47 | 103 | static ssize_t wwid_show(struct device *dev, struct device_attribute *attr, |
| 48 | 104 | char *buf) |
| 49 | 105 | { |
| @@ -208,6 +264,7 @@ static struct attribute *nvme_ns_attrs[] = { · 158 unmodified lines | ||
| 208 | 264 | &dev_attr_ana_grpid.attr, |
| 209 | 265 | &dev_attr_ana_state.attr, |
| 210 | 266 | #endif |
| 267 | + &dev_attr_io_passthru_err_log_enabled.attr, | |
| 211 | 268 | NULL, |
| 212 | 269 | }; |
| 213 | 270 | |
| @@ -311,6 +368,7 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, · 97 unmodified lines | ||
| 311 | 368 | char *buf) |
| 312 | 369 | { |
| 313 | 370 | struct nvme_ctrl *ctrl = dev_get_drvdata(dev); |
| 371 | + unsigned state = (unsigned)nvme_ctrl_state(ctrl); | |
| 314 | 372 | static const char *const state_name[] = { |
| 315 | 373 | [NVME_CTRL_NEW] = "new", |
| 316 | 374 | [NVME_CTRL_LIVE] = "live", |
| @@ -321,9 +379,8 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, · 4 unmodified lines | ||
| 321 | 379 | [NVME_CTRL_DEAD] = "dead", |
| 322 | 380 | }; |
| 323 | 381 | |
| 324 | − if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) && | |
| 325 | − state_name[ctrl->state]) | |
| 326 | − return sysfs_emit(buf, "%s\n", state_name[ctrl->state]); | |
| 382 | + if (state < ARRAY_SIZE(state_name) && state_name[state]) | |
| 383 | + return sysfs_emit(buf, "%s\n", state_name[state]); | |
| 327 | 384 | |
| 328 | 385 | return sysfs_emit(buf, "unknown state\n"); |
| 329 | 386 | } |
| @@ -655,6 +712,7 @@ static struct attribute *nvme_dev_attrs[] = { · 325 unmodified lines | ||
| 655 | 712 | #ifdef CONFIG_NVME_TCP_TLS |
| 656 | 713 | &dev_attr_tls_key.attr, |
| 657 | 714 | #endif |
| 715 | + &dev_attr_adm_passthru_err_log_enabled.attr, | |
| 658 | 716 | NULL |
| 659 | 717 | }; |
| 660 | 718 | |
| @@ -2428,13 +2428,13 @@ static enum blk_eh_timer_return nvme_tcp_timeout(struct request *rq) · 2427 unmodified lines | ||
| 2428 | 2428 | struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq); |
| 2429 | 2429 | struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl; |
| 2430 | 2430 | struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req); |
| 2431 | − u8 opc = pdu->cmd.common.opcode, fctype = pdu->cmd.fabrics.fctype; | |
| 2431 | + struct nvme_command *cmd = &pdu->cmd; | |
| 2432 | 2432 | int qid = nvme_tcp_queue_id(req->queue); |
| 2433 | 2433 | |
| 2434 | 2434 | dev_warn(ctrl->device, |
| 2435 | 2435 | "I/O tag %d (%04x) type %d opcode %#x (%s) QID %d timeout\n", |
| 2436 | − rq->tag, nvme_cid(rq), pdu->hdr.type, opc, | |
| 2437 | − nvme_opcode_str(qid, opc, fctype), qid); | |
| 2436 | + rq->tag, nvme_cid(rq), pdu->hdr.type, cmd->common.opcode, | |
| 2437 | + nvme_fabrics_opcode_str(qid, cmd), qid); | |
| 2438 | 2438 | |
| 2439 | 2439 | if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE) { |
| 2440 | 2440 | /* |
| @@ -2753,8 +2753,8 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev, · 312 unmodified lines | ||
| 2753 | 2753 | if (ret) |
| 2754 | 2754 | goto out_uninit_ctrl; |
| 2755 | 2755 | |
| 2756 | − dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp\n", | |
| 2757 | − nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr); | |
| 2756 | + dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp, hostnqn: %s\n", | |
| 2757 | + nvmf_ctrl_subsysnqn(&ctrl->ctrl), &ctrl->addr, opts->host->nqn); | |
| 2758 | 2758 | |
| 2759 | 2759 | mutex_lock(&nvme_tcp_ctrl_mutex); |
| 2760 | 2760 | list_add_tail(&ctrl->list, &nvme_tcp_ctrl_list); |
| @@ -2826,4 +2826,5 @@ static void __exit nvme_tcp_cleanup_module(void) · 65 unmodified lines | ||
| 2826 | 2826 | module_init(nvme_tcp_init_module); |
| 2827 | 2827 | module_exit(nvme_tcp_cleanup_module); |
| 2828 | 2828 | |
| 2829 | +MODULE_DESCRIPTION("NVMe host TCP transport driver"); | |
| 2829 | 2830 | MODULE_LICENSE("GPL v2"); |
| @@ -248,7 +248,7 @@ void nvmet_ns_changed(struct nvmet_subsys *subsys, u32 nsid) · 247 unmodified lines | ||
| 248 | 248 | nvmet_add_to_changed_ns_log(ctrl, cpu_to_le32(nsid)); |
| 249 | 249 | if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_NS_ATTR)) |
| 250 | 250 | continue; |
| 251 | − nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, | |
| 251 | + nvmet_add_async_event(ctrl, NVME_AER_NOTICE, | |
| 252 | 252 | NVME_AER_NOTICE_NS_CHANGED, |
| 253 | 253 | NVME_LOG_CHANGED_NS); |
| 254 | 254 | } |
| @@ -265,7 +265,7 @@ void nvmet_send_ana_event(struct nvmet_subsys *subsys, · 10 unmodified lines | ||
| 265 | 265 | continue; |
| 266 | 266 | if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_ANA_CHANGE)) |
| 267 | 267 | continue; |
| 268 | − nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, | |
| 268 | + nvmet_add_async_event(ctrl, NVME_AER_NOTICE, | |
| 269 | 269 | NVME_AER_NOTICE_ANA, NVME_LOG_ANA); |
| 270 | 270 | } |
| 271 | 271 | mutex_unlock(&subsys->lock); |
| @@ -1705,4 +1705,5 @@ static void __exit nvmet_exit(void) · 1433 unmodified lines | ||
| 1705 | 1705 | module_init(nvmet_init); |
| 1706 | 1706 | module_exit(nvmet_exit); |
| 1707 | 1707 | |
| 1708 | +MODULE_DESCRIPTION("NVMe target core framework"); | |
| 1708 | 1709 | MODULE_LICENSE("GPL v2"); |
| @@ -21,7 +21,7 @@ static void __nvmet_disc_changed(struct nvmet_port *port, · 20 unmodified lines | ||
| 21 | 21 | if (nvmet_aen_bit_disabled(ctrl, NVME_AEN_BIT_DISC_CHANGE)) |
| 22 | 22 | return; |
| 23 | 23 | |
| 24 | − nvmet_add_async_event(ctrl, NVME_AER_TYPE_NOTICE, | |
| 24 | + nvmet_add_async_event(ctrl, NVME_AER_NOTICE, | |
| 25 | 25 | NVME_AER_NOTICE_DISC_CHANGED, NVME_LOG_DISC); |
| 26 | 26 | } |
| 27 | 27 | |
| @@ -111,6 +111,8 @@ struct nvmet_fc_tgtport { · 110 unmodified lines | ||
| 111 | 111 | struct nvmet_fc_port_entry *pe; |
| 112 | 112 | struct kref ref; |
| 113 | 113 | u32 max_sg_cnt; |
| 114 | + | |
| 115 | + struct work_struct put_work; | |
| 114 | 116 | }; |
| 115 | 117 | |
| 116 | 118 | struct nvmet_fc_port_entry { |
| @@ -145,7 +147,6 @@ struct nvmet_fc_tgt_queue { · 28 unmodified lines | ||
| 145 | 147 | struct list_head avail_defer_list; |
| 146 | 148 | struct workqueue_struct *work_q; |
| 147 | 149 | struct kref ref; |
| 148 | − struct rcu_head rcu; | |
| 149 | 150 | /* array of fcp_iods */ |
| 150 | 151 | struct nvmet_fc_fcp_iod fod[] __counted_by(sqsize); |
| 151 | 152 | } __aligned(sizeof(unsigned long long)); |
| @@ -166,10 +167,9 @@ struct nvmet_fc_tgt_assoc { · 14 unmodified lines | ||
| 166 | 167 | struct nvmet_fc_hostport *hostport; |
| 167 | 168 | struct nvmet_fc_ls_iod *rcv_disconn; |
| 168 | 169 | struct list_head a_list; |
| 169 | − struct nvmet_fc_tgt_queue __rcu *queues[NVMET_NR_QUEUES + 1]; | |
| 170 | + struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES + 1]; | |
| 170 | 171 | struct kref ref; |
| 171 | 172 | struct work_struct del_work; |
| 172 | − struct rcu_head rcu; | |
| 173 | 173 | }; |
| 174 | 174 | |
| 175 | 175 | |
| @@ -249,6 +249,13 @@ static int nvmet_fc_tgt_a_get(struct nvmet_fc_tgt_assoc *assoc); · 73 unmodified lines | ||
| 249 | 249 | static void nvmet_fc_tgt_q_put(struct nvmet_fc_tgt_queue *queue); |
| 250 | 250 | static int nvmet_fc_tgt_q_get(struct nvmet_fc_tgt_queue *queue); |
| 251 | 251 | static void nvmet_fc_tgtport_put(struct nvmet_fc_tgtport *tgtport); |
| 252 | +static void nvmet_fc_put_tgtport_work(struct work_struct *work) | |
| 253 | +{ | |
| 254 | + struct nvmet_fc_tgtport *tgtport = | |
| 255 | + container_of(work, struct nvmet_fc_tgtport, put_work); | |
| 256 | + | |
| 257 | + nvmet_fc_tgtport_put(tgtport); | |
| 258 | +} | |
| 252 | 259 | static int nvmet_fc_tgtport_get(struct nvmet_fc_tgtport *tgtport); |
| 253 | 260 | static void nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, |
| 254 | 261 | struct nvmet_fc_fcp_iod *fod); |
| @@ -360,7 +367,7 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop) · 105 unmodified lines | ||
| 360 | 367 | |
| 361 | 368 | if (!lsop->req_queued) { |
| 362 | 369 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 363 | − return; | |
| 370 | + goto out_putwork; | |
| 364 | 371 | } |
| 365 | 372 | |
| 366 | 373 | list_del(&lsop->lsreq_list); |
| @@ -373,7 +380,8 @@ __nvmet_fc_finish_ls_req(struct nvmet_fc_ls_req_op *lsop) · 6 unmodified lines | ||
| 373 | 380 | (lsreq->rqstlen + lsreq->rsplen), |
| 374 | 381 | DMA_BIDIRECTIONAL); |
| 375 | 382 | |
| 376 | − nvmet_fc_tgtport_put(tgtport); | |
| 383 | +out_putwork: | |
| 384 | + queue_work(nvmet_wq, &tgtport->put_work); | |
| 377 | 385 | } |
| 378 | 386 | |
| 379 | 387 | static int |
| @@ -489,8 +497,7 @@ nvmet_fc_xmt_disconnect_assoc(struct nvmet_fc_tgt_assoc *assoc) · 109 unmodified lines | ||
| 489 | 497 | * message is normal. Otherwise, send unless the hostport has |
| 490 | 498 | * already been invalidated by the lldd. |
| 491 | 499 | */ |
| 492 | − if (!tgtport->ops->ls_req || !assoc->hostport || | |
| 493 | − assoc->hostport->invalid) | |
| 500 | + if (!tgtport->ops->ls_req || assoc->hostport->invalid) | |
| 494 | 501 | return; |
| 495 | 502 | |
| 496 | 503 | lsop = kzalloc((sizeof(*lsop) + |
| @@ -802,14 +809,11 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, · 305 unmodified lines | ||
| 802 | 809 | if (!queue) |
| 803 | 810 | return NULL; |
| 804 | 811 | |
| 805 | − if (!nvmet_fc_tgt_a_get(assoc)) | |
| 806 | − goto out_free_queue; | |
| 807 | − | |
| 808 | 812 | queue->work_q = alloc_workqueue("ntfc%d.%d.%d", 0, 0, |
| 809 | 813 | assoc->tgtport->fc_target_port.port_num, |
| 810 | 814 | assoc->a_id, qid); |
| 811 | 815 | if (!queue->work_q) |
| 812 | − goto out_a_put; | |
| 816 | + goto out_free_queue; | |
| 813 | 817 | |
| 814 | 818 | queue->qid = qid; |
| 815 | 819 | queue->sqsize = sqsize; |
| @@ -831,15 +835,13 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, · 15 unmodified lines | ||
| 831 | 835 | goto out_fail_iodlist; |
| 832 | 836 | |
| 833 | 837 | WARN_ON(assoc->queues[qid]); |
| 834 | − rcu_assign_pointer(assoc->queues[qid], queue); | |
| 838 | + assoc->queues[qid] = queue; | |
| 835 | 839 | |
| 836 | 840 | return queue; |
| 837 | 841 | |
| 838 | 842 | out_fail_iodlist: |
| 839 | 843 | nvmet_fc_destroy_fcp_iodlist(assoc->tgtport, queue); |
| 840 | 844 | destroy_workqueue(queue->work_q); |
| 841 | −out_a_put: | |
| 842 | − nvmet_fc_tgt_a_put(assoc); | |
| 843 | 845 | out_free_queue: |
| 844 | 846 | kfree(queue); |
| 845 | 847 | return NULL; |
| @@ -852,15 +854,11 @@ nvmet_fc_tgt_queue_free(struct kref *ref) · 6 unmodified lines | ||
| 852 | 854 | struct nvmet_fc_tgt_queue *queue = |
| 853 | 855 | container_of(ref, struct nvmet_fc_tgt_queue, ref); |
| 854 | 856 | |
| 855 | − rcu_assign_pointer(queue->assoc->queues[queue->qid], NULL); | |
| 856 | − | |
| 857 | 857 | nvmet_fc_destroy_fcp_iodlist(queue->assoc->tgtport, queue); |
| 858 | 858 | |
| 859 | − nvmet_fc_tgt_a_put(queue->assoc); | |
| 860 | − | |
| 861 | 859 | destroy_workqueue(queue->work_q); |
| 862 | 860 | |
| 863 | − kfree_rcu(queue, rcu); | |
| 861 | + kfree(queue); | |
| 864 | 862 | } |
| 865 | 863 | |
| 866 | 864 | static void |
| @@ -969,7 +967,7 @@ nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport, · 102 unmodified lines | ||
| 969 | 967 | rcu_read_lock(); |
| 970 | 968 | list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { |
| 971 | 969 | if (association_id == assoc->association_id) { |
| 972 | − queue = rcu_dereference(assoc->queues[qid]); | |
| 970 | + queue = assoc->queues[qid]; | |
| 973 | 971 | if (queue && |
| 974 | 972 | (!atomic_read(&queue->connected) || |
| 975 | 973 | !nvmet_fc_tgt_q_get(queue))) |
| @@ -1078,8 +1076,6 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) · 102 unmodified lines | ||
| 1078 | 1076 | /* new allocation not needed */ |
| 1079 | 1077 | kfree(newhost); |
| 1080 | 1078 | newhost = match; |
| 1081 | − /* no new allocation - release reference */ | |
| 1082 | − nvmet_fc_tgtport_put(tgtport); | |
| 1083 | 1079 | } else { |
| 1084 | 1080 | newhost->tgtport = tgtport; |
| 1085 | 1081 | newhost->hosthandle = hosthandle; |
| @@ -1094,23 +1090,54 @@ nvmet_fc_alloc_hostport(struct nvmet_fc_tgtport *tgtport, void *hosthandle) · 8 unmodified lines | ||
| 1094 | 1090 | } |
| 1095 | 1091 | |
| 1096 | 1092 | static void |
| 1097 | −nvmet_fc_delete_assoc(struct work_struct *work) | |
| 1093 | +nvmet_fc_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) | |
| 1094 | +{ | |
| 1095 | + nvmet_fc_delete_target_assoc(assoc); | |
| 1096 | + nvmet_fc_tgt_a_put(assoc); | |
| 1097 | +} | |
| 1098 | + | |
| 1099 | +static void | |
| 1100 | +nvmet_fc_delete_assoc_work(struct work_struct *work) | |
| 1098 | 1101 | { |
| 1099 | 1102 | struct nvmet_fc_tgt_assoc *assoc = |
| 1100 | 1103 | container_of(work, struct nvmet_fc_tgt_assoc, del_work); |
| 1104 | + struct nvmet_fc_tgtport *tgtport = assoc->tgtport; | |
| 1101 | 1105 | |
| 1102 | − nvmet_fc_delete_target_assoc(assoc); | |
| 1103 | − nvmet_fc_tgt_a_put(assoc); | |
| 1106 | + nvmet_fc_delete_assoc(assoc); | |
| 1107 | + nvmet_fc_tgtport_put(tgtport); | |
| 1108 | +} | |
| 1109 | + | |
| 1110 | +static void | |
| 1111 | +nvmet_fc_schedule_delete_assoc(struct nvmet_fc_tgt_assoc *assoc) | |
| 1112 | +{ | |
| 1113 | + nvmet_fc_tgtport_get(assoc->tgtport); | |
| 1114 | + queue_work(nvmet_wq, &assoc->del_work); | |
| 1115 | +} | |
| 1116 | + | |
| 1117 | +static bool | |
| 1118 | +nvmet_fc_assoc_exits(struct nvmet_fc_tgtport *tgtport, u64 association_id) | |
| 1119 | +{ | |
| 1120 | + struct nvmet_fc_tgt_assoc *a; | |
| 1121 | + | |
| 1122 | + list_for_each_entry_rcu(a, &tgtport->assoc_list, a_list) { | |
| 1123 | + if (association_id == a->association_id) | |
| 1124 | + return true; | |
| 1125 | + } | |
| 1126 | + | |
| 1127 | + return false; | |
| 1104 | 1128 | } |
| 1105 | 1129 | |
| 1106 | 1130 | static struct nvmet_fc_tgt_assoc * |
| 1107 | 1131 | nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle) |
| 1108 | 1132 | { |
| 1109 | − struct nvmet_fc_tgt_assoc *assoc, *tmpassoc; | |
| 1133 | + struct nvmet_fc_tgt_assoc *assoc; | |
| 1110 | 1134 | unsigned long flags; |
| 1135 | + bool done; | |
| 1111 | 1136 | u64 ran; |
| 1112 | 1137 | int idx; |
| 1113 | − bool needrandom = true; | |
| 1138 | + | |
| 1139 | + if (!tgtport->pe) | |
| 1140 | + return NULL; | |
| 1114 | 1141 | |
| 1115 | 1142 | assoc = kzalloc(sizeof(*assoc), GFP_KERNEL); |
| 1116 | 1143 | if (!assoc) |
| @@ -1120,43 +1147,35 @@ nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport, void *hosthandle) · 3 unmodified lines | ||
| 1120 | 1147 | if (idx < 0) |
| 1121 | 1148 | goto out_free_assoc; |
| 1122 | 1149 | |
| 1123 | − if (!nvmet_fc_tgtport_get(tgtport)) | |
| 1124 | − goto out_ida; | |
| 1125 | − | |
| 1126 | 1150 | assoc->hostport = nvmet_fc_alloc_hostport(tgtport, hosthandle); |
| 1127 | 1151 | if (IS_ERR(assoc->hostport)) |
| 1128 | − goto out_put; | |
| 1152 | + goto out_ida; | |
| 1129 | 1153 | |
| 1130 | 1154 | assoc->tgtport = tgtport; |
| 1131 | 1155 | assoc->a_id = idx; |
| 1132 | 1156 | INIT_LIST_HEAD(&assoc->a_list); |
| 1133 | 1157 | kref_init(&assoc->ref); |
| 1134 | − INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc); | |
| 1158 | + INIT_WORK(&assoc->del_work, nvmet_fc_delete_assoc_work); | |
| 1135 | 1159 | atomic_set(&assoc->terminating, 0); |
| 1136 | 1160 | |
| 1137 | − while (needrandom) { | |
| 1161 | + done = false; | |
| 1162 | + do { | |
| 1138 | 1163 | get_random_bytes(&ran, sizeof(ran) - BYTES_FOR_QID); |
| 1139 | 1164 | ran = ran << BYTES_FOR_QID_SHIFT; |
| 1140 | 1165 | |
| 1141 | 1166 | spin_lock_irqsave(&tgtport->lock, flags); |
| 1142 | − needrandom = false; | |
| 1143 | − list_for_each_entry(tmpassoc, &tgtport->assoc_list, a_list) { | |
| 1144 | − if (ran == tmpassoc->association_id) { | |
| 1145 | − needrandom = true; | |
| 1146 | − break; | |
| 1147 | − } | |
| 1148 | − } | |
| 1149 | − if (!needrandom) { | |
| 1167 | + rcu_read_lock(); | |
| 1168 | + if (!nvmet_fc_assoc_exits(tgtport, ran)) { | |
| 1150 | 1169 | assoc->association_id = ran; |
| 1151 | 1170 | list_add_tail_rcu(&assoc->a_list, &tgtport->assoc_list); |
| 1171 | + done = true; | |
| 1152 | 1172 | } |
| 1173 | + rcu_read_unlock(); | |
| 1153 | 1174 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1154 | − } | |
| 1175 | + } while (!done); | |
| 1155 | 1176 | |
| 1156 | 1177 | return assoc; |
| 1157 | 1178 | |
| 1158 | −out_put: | |
| 1159 | − nvmet_fc_tgtport_put(tgtport); | |
| 1160 | 1179 | out_ida: |
| 1161 | 1180 | ida_free(&tgtport->assoc_cnt, idx); |
| 1162 | 1181 | out_free_assoc: |
| @@ -1172,13 +1191,18 @@ nvmet_fc_target_assoc_free(struct kref *ref) · 9 unmodified lines | ||
| 1172 | 1191 | struct nvmet_fc_tgtport *tgtport = assoc->tgtport; |
| 1173 | 1192 | struct nvmet_fc_ls_iod *oldls; |
| 1174 | 1193 | unsigned long flags; |
| 1194 | + int i; | |
| 1195 | + | |
| 1196 | + for (i = NVMET_NR_QUEUES; i >= 0; i--) { | |
| 1197 | + if (assoc->queues[i]) | |
| 1198 | + nvmet_fc_delete_target_queue(assoc->queues[i]); | |
| 1199 | + } | |
| 1175 | 1200 | |
| 1176 | 1201 | /* Send Disconnect now that all i/o has completed */ |
| 1177 | 1202 | nvmet_fc_xmt_disconnect_assoc(assoc); |
| 1178 | 1203 | |
| 1179 | 1204 | nvmet_fc_free_hostport(assoc->hostport); |
| 1180 | 1205 | spin_lock_irqsave(&tgtport->lock, flags); |
| 1181 | − list_del_rcu(&assoc->a_list); | |
| 1182 | 1206 | oldls = assoc->rcv_disconn; |
| 1183 | 1207 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1184 | 1208 | /* if pending Rcv Disconnect Association LS, send rsp now */ |
| @@ -1188,8 +1212,7 @@ nvmet_fc_target_assoc_free(struct kref *ref) · 3 unmodified lines | ||
| 1188 | 1212 | dev_info(tgtport->dev, |
| 1189 | 1213 | "{%d:%d} Association freed\n", |
| 1190 | 1214 | tgtport->fc_target_port.port_num, assoc->a_id); |
| 1191 | − kfree_rcu(assoc, rcu); | |
| 1192 | − nvmet_fc_tgtport_put(tgtport); | |
| 1215 | + kfree(assoc); | |
| 1193 | 1216 | } |
| 1194 | 1217 | |
| 1195 | 1218 | static void |
| @@ -1208,7 +1231,7 @@ static void · 12 unmodified lines | ||
| 1208 | 1231 | nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) |
| 1209 | 1232 | { |
| 1210 | 1233 | struct nvmet_fc_tgtport *tgtport = assoc->tgtport; |
| 1211 | − struct nvmet_fc_tgt_queue *queue; | |
| 1234 | + unsigned long flags; | |
| 1212 | 1235 | int i, terminating; |
| 1213 | 1236 | |
| 1214 | 1237 | terminating = atomic_xchg(&assoc->terminating, 1); |
| @@ -1217,29 +1240,21 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) · 2 unmodified lines | ||
| 1217 | 1240 | if (terminating) |
| 1218 | 1241 | return; |
| 1219 | 1242 | |
| 1243 | + spin_lock_irqsave(&tgtport->lock, flags); | |
| 1244 | + list_del_rcu(&assoc->a_list); | |
| 1245 | + spin_unlock_irqrestore(&tgtport->lock, flags); | |
| 1220 | 1246 | |
| 1221 | − for (i = NVMET_NR_QUEUES; i >= 0; i--) { | |
| 1222 | − rcu_read_lock(); | |
| 1223 | − queue = rcu_dereference(assoc->queues[i]); | |
| 1224 | − if (!queue) { | |
| 1225 | − rcu_read_unlock(); | |
| 1226 | − continue; | |
| 1227 | − } | |
| 1247 | + synchronize_rcu(); | |
| 1228 | 1248 | |
| 1229 | − if (!nvmet_fc_tgt_q_get(queue)) { | |
| 1230 | − rcu_read_unlock(); | |
| 1231 | − continue; | |
| 1232 | − } | |
| 1233 | − rcu_read_unlock(); | |
| 1234 | − nvmet_fc_delete_target_queue(queue); | |
| 1235 | − nvmet_fc_tgt_q_put(queue); | |
| 1249 | + /* ensure all in-flight I/Os have been processed */ | |
| 1250 | + for (i = NVMET_NR_QUEUES; i >= 0; i--) { | |
| 1251 | + if (assoc->queues[i]) | |
| 1252 | + flush_workqueue(assoc->queues[i]->work_q); | |
| 1236 | 1253 | } |
| 1237 | 1254 | |
| 1238 | 1255 | dev_info(tgtport->dev, |
| 1239 | 1256 | "{%d:%d} Association deleted\n", |
| 1240 | 1257 | tgtport->fc_target_port.port_num, assoc->a_id); |
| 1241 | − | |
| 1242 | − nvmet_fc_tgt_a_put(assoc); | |
| 1243 | 1258 | } |
| 1244 | 1259 | |
| 1245 | 1260 | static struct nvmet_fc_tgt_assoc * |
| @@ -1415,6 +1430,7 @@ nvmet_fc_register_targetport(struct nvmet_fc_port_info *pinfo, · 169 unmodified lines | ||
| 1415 | 1430 | kref_init(&newrec->ref); |
| 1416 | 1431 | ida_init(&newrec->assoc_cnt); |
| 1417 | 1432 | newrec->max_sg_cnt = template->max_sgl_segments; |
| 1433 | + INIT_WORK(&newrec->put_work, nvmet_fc_put_tgtport_work); | |
| 1418 | 1434 | |
| 1419 | 1435 | ret = nvmet_fc_alloc_ls_iodlist(newrec); |
| 1420 | 1436 | if (ret) { |
| @@ -1492,9 +1508,8 @@ __nvmet_fc_free_assocs(struct nvmet_fc_tgtport *tgtport) · 71 unmodified lines | ||
| 1492 | 1508 | list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { |
| 1493 | 1509 | if (!nvmet_fc_tgt_a_get(assoc)) |
| 1494 | 1510 | continue; |
| 1495 | − if (!queue_work(nvmet_wq, &assoc->del_work)) | |
| 1496 | − /* already deleting - release local reference */ | |
| 1497 | − nvmet_fc_tgt_a_put(assoc); | |
| 1511 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1512 | + nvmet_fc_tgt_a_put(assoc); | |
| 1498 | 1513 | } |
| 1499 | 1514 | rcu_read_unlock(); |
| 1500 | 1515 | } |
| @@ -1540,16 +1555,14 @@ nvmet_fc_invalidate_host(struct nvmet_fc_target_port *target_port, · 39 unmodified lines | ||
| 1540 | 1555 | spin_lock_irqsave(&tgtport->lock, flags); |
| 1541 | 1556 | list_for_each_entry_safe(assoc, next, |
| 1542 | 1557 | &tgtport->assoc_list, a_list) { |
| 1543 | − if (!assoc->hostport || | |
| 1544 | − assoc->hostport->hosthandle != hosthandle) | |
| 1558 | + if (assoc->hostport->hosthandle != hosthandle) | |
| 1545 | 1559 | continue; |
| 1546 | 1560 | if (!nvmet_fc_tgt_a_get(assoc)) |
| 1547 | 1561 | continue; |
| 1548 | 1562 | assoc->hostport->invalid = 1; |
| 1549 | 1563 | noassoc = false; |
| 1550 | − if (!queue_work(nvmet_wq, &assoc->del_work)) | |
| 1551 | − /* already deleting - release local reference */ | |
| 1552 | − nvmet_fc_tgt_a_put(assoc); | |
| 1564 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1565 | + nvmet_fc_tgt_a_put(assoc); | |
| 1553 | 1566 | } |
| 1554 | 1567 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1555 | 1568 | |
| @@ -1581,7 +1594,7 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) · 25 unmodified lines | ||
| 1581 | 1594 | |
| 1582 | 1595 | rcu_read_lock(); |
| 1583 | 1596 | list_for_each_entry_rcu(assoc, &tgtport->assoc_list, a_list) { |
| 1584 | − queue = rcu_dereference(assoc->queues[0]); | |
| 1597 | + queue = assoc->queues[0]; | |
| 1585 | 1598 | if (queue && queue->nvme_sq.ctrl == ctrl) { |
| 1586 | 1599 | if (nvmet_fc_tgt_a_get(assoc)) |
| 1587 | 1600 | found_ctrl = true; |
| @@ -1593,9 +1606,8 @@ nvmet_fc_delete_ctrl(struct nvmet_ctrl *ctrl) · 5 unmodified lines | ||
| 1593 | 1606 | nvmet_fc_tgtport_put(tgtport); |
| 1594 | 1607 | |
| 1595 | 1608 | if (found_ctrl) { |
| 1596 | − if (!queue_work(nvmet_wq, &assoc->del_work)) | |
| 1597 | − /* already deleting - release local reference */ | |
| 1598 | − nvmet_fc_tgt_a_put(assoc); | |
| 1609 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1610 | + nvmet_fc_tgt_a_put(assoc); | |
| 1599 | 1611 | return; |
| 1600 | 1612 | } |
| 1601 | 1613 | |
| @@ -1625,6 +1637,8 @@ nvmet_fc_unregister_targetport(struct nvmet_fc_target_port *target_port) · 23 unmodified lines | ||
| 1625 | 1637 | /* terminate any outstanding associations */ |
| 1626 | 1638 | __nvmet_fc_free_assocs(tgtport); |
| 1627 | 1639 | |
| 1640 | + flush_workqueue(nvmet_wq); | |
| 1641 | + | |
| 1628 | 1642 | /* |
| 1629 | 1643 | * should terminate LS's as well. However, LS's will be generated |
| 1630 | 1644 | * at the tail end of association termination, so they likely don't |
| @@ -1870,9 +1884,6 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, · 239 unmodified lines | ||
| 1870 | 1884 | sizeof(struct fcnvme_ls_disconnect_assoc_acc)), |
| 1871 | 1885 | FCNVME_LS_DISCONNECT_ASSOC); |
| 1872 | 1886 | |
| 1873 | − /* release get taken in nvmet_fc_find_target_assoc */ | |
| 1874 | − nvmet_fc_tgt_a_put(assoc); | |
| 1875 | − | |
| 1876 | 1887 | /* |
| 1877 | 1888 | * The rules for LS response says the response cannot |
| 1878 | 1889 | * go back until ABTS's have been sent for all outstanding |
| @@ -1887,8 +1898,6 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, · 8 unmodified lines | ||
| 1887 | 1898 | assoc->rcv_disconn = iod; |
| 1888 | 1899 | spin_unlock_irqrestore(&tgtport->lock, flags); |
| 1889 | 1900 | |
| 1890 | − nvmet_fc_delete_target_assoc(assoc); | |
| 1891 | − | |
| 1892 | 1901 | if (oldls) { |
| 1893 | 1902 | dev_info(tgtport->dev, |
| 1894 | 1903 | "{%d:%d} Multiple Disconnect Association LS's " |
| @@ -1904,6 +1913,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, · 9 unmodified lines | ||
| 1904 | 1913 | nvmet_fc_xmt_ls_rsp(tgtport, oldls); |
| 1905 | 1914 | } |
| 1906 | 1915 | |
| 1916 | + nvmet_fc_schedule_delete_assoc(assoc); | |
| 1917 | + nvmet_fc_tgt_a_put(assoc); | |
| 1918 | + | |
| 1907 | 1919 | return false; |
| 1908 | 1920 | } |
| 1909 | 1921 | |
| @@ -2540,8 +2552,9 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, · 630 unmodified lines | ||
| 2540 | 2552 | |
| 2541 | 2553 | fod->req.cmd = &fod->cmdiubuf.sqe; |
| 2542 | 2554 | fod->req.cqe = &fod->rspiubuf.cqe; |
| 2543 | − if (tgtport->pe) | |
| 2544 | − fod->req.port = tgtport->pe->port; | |
| 2555 | + if (!tgtport->pe) | |
| 2556 | + goto transport_error; | |
| 2557 | + fod->req.port = tgtport->pe->port; | |
| 2545 | 2558 | |
| 2546 | 2559 | /* clear any response payload */ |
| 2547 | 2560 | memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf)); |
| @@ -2902,6 +2915,9 @@ nvmet_fc_remove_port(struct nvmet_port *port) · 354 unmodified lines | ||
| 2902 | 2915 | |
| 2903 | 2916 | nvmet_fc_portentry_unbind(pe); |
| 2904 | 2917 | |
| 2918 | + /* terminate any outstanding associations */ | |
| 2919 | + __nvmet_fc_free_assocs(pe->tgtport); | |
| 2920 | + | |
| 2905 | 2921 | kfree(pe); |
| 2906 | 2922 | } |
| 2907 | 2923 | |
| @@ -2933,6 +2949,9 @@ static int __init nvmet_fc_init_module(void) · 25 unmodified lines | ||
| 2933 | 2949 | |
| 2934 | 2950 | static void __exit nvmet_fc_exit_module(void) |
| 2935 | 2951 | { |
| 2952 | + /* ensure any shutdown operation, e.g. delete ctrls have finished */ | |
| 2953 | + flush_workqueue(nvmet_wq); | |
| 2954 | + | |
| 2936 | 2955 | /* sanity check - all lports should be removed */ |
| 2937 | 2956 | if (!list_empty(&nvmet_fc_target_list)) |
| 2938 | 2957 | pr_warn("%s: targetport list not empty\n", __func__); |
| @@ -2945,4 +2964,5 @@ static void __exit nvmet_fc_exit_module(void) · 6 unmodified lines | ||
| 2945 | 2964 | module_init(nvmet_fc_init_module); |
| 2946 | 2965 | module_exit(nvmet_fc_exit_module); |
| 2947 | 2966 | |
| 2967 | +MODULE_DESCRIPTION("NVMe target FC transport driver"); | |
| 2948 | 2968 | MODULE_LICENSE("GPL v2"); |
| @@ -358,7 +358,7 @@ fcloop_h2t_ls_req(struct nvme_fc_local_port *localport, · 357 unmodified lines | ||
| 358 | 358 | if (!rport->targetport) { |
| 359 | 359 | tls_req->status = -ECONNREFUSED; |
| 360 | 360 | spin_lock(&rport->lock); |
| 361 | − list_add_tail(&rport->ls_list, &tls_req->ls_list); | |
| 361 | + list_add_tail(&tls_req->ls_list, &rport->ls_list); | |
| 362 | 362 | spin_unlock(&rport->lock); |
| 363 | 363 | queue_work(nvmet_wq, &rport->ls_work); |
| 364 | 364 | return ret; |
| @@ -391,7 +391,7 @@ fcloop_h2t_xmt_ls_rsp(struct nvmet_fc_target_port *targetport, · 26 unmodified lines | ||
| 391 | 391 | if (remoteport) { |
| 392 | 392 | rport = remoteport->private; |
| 393 | 393 | spin_lock(&rport->lock); |
| 394 | − list_add_tail(&rport->ls_list, &tls_req->ls_list); | |
| 394 | + list_add_tail(&tls_req->ls_list, &rport->ls_list); | |
| 395 | 395 | spin_unlock(&rport->lock); |
| 396 | 396 | queue_work(nvmet_wq, &rport->ls_work); |
| 397 | 397 | } |
| @@ -446,7 +446,7 @@ fcloop_t2h_ls_req(struct nvmet_fc_target_port *targetport, void *hosthandle, · 48 unmodified lines | ||
| 446 | 446 | if (!tport->remoteport) { |
| 447 | 447 | tls_req->status = -ECONNREFUSED; |
| 448 | 448 | spin_lock(&tport->lock); |
| 449 | − list_add_tail(&tport->ls_list, &tls_req->ls_list); | |
| 449 | + list_add_tail(&tls_req->ls_list, &tport->ls_list); | |
| 450 | 450 | spin_unlock(&tport->lock); |
| 451 | 451 | queue_work(nvmet_wq, &tport->ls_work); |
| 452 | 452 | return ret; |
| @@ -1650,4 +1650,5 @@ static void __exit fcloop_exit(void) · 1197 unmodified lines | ||
| 1650 | 1650 | module_init(fcloop_init); |
| 1651 | 1651 | module_exit(fcloop_exit); |
| 1652 | 1652 | |
| 1653 | +MODULE_DESCRIPTION("NVMe target FC loop transport driver"); | |
| 1653 | 1654 | MODULE_LICENSE("GPL v2"); |
| @@ -400,7 +400,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl) · 399 unmodified lines | ||
| 400 | 400 | } |
| 401 | 401 | |
| 402 | 402 | nvme_quiesce_admin_queue(&ctrl->ctrl); |
| 403 | − if (ctrl->ctrl.state == NVME_CTRL_LIVE) | |
| 403 | + if (nvme_ctrl_state(&ctrl->ctrl) == NVME_CTRL_LIVE) | |
| 404 | 404 | nvme_disable_ctrl(&ctrl->ctrl, true); |
| 405 | 405 | |
| 406 | 406 | nvme_cancel_admin_tagset(&ctrl->ctrl); |
| @@ -434,8 +434,10 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work) · 27 unmodified lines | ||
| 434 | 434 | nvme_loop_shutdown_ctrl(ctrl); |
| 435 | 435 | |
| 436 | 436 | if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { |
| 437 | − if (ctrl->ctrl.state != NVME_CTRL_DELETING && | |
| 438 | − ctrl->ctrl.state != NVME_CTRL_DELETING_NOIO) | |
| 437 | + enum nvme_ctrl_state state = nvme_ctrl_state(&ctrl->ctrl); | |
| 438 | + | |
| 439 | + if (state != NVME_CTRL_DELETING && | |
| 440 | + state != NVME_CTRL_DELETING_NOIO) | |
| 439 | 441 | /* state change failure for non-deleted ctrl? */ |
| 440 | 442 | WARN_ON_ONCE(1); |
| 441 | 443 | return; |
| @@ -688,5 +690,6 @@ static void __exit nvme_loop_cleanup_module(void) · 246 unmodified lines | ||
| 688 | 690 | module_init(nvme_loop_init_module); |
| 689 | 691 | module_exit(nvme_loop_cleanup_module); |
| 690 | 692 | |
| 693 | +MODULE_DESCRIPTION("NVMe target loop transport driver"); | |
| 691 | 694 | MODULE_LICENSE("GPL v2"); |
| 692 | 695 | MODULE_ALIAS("nvmet-transport-254"); /* 254 == NVMF_TRTYPE_LOOP */ |
| @@ -2104,5 +2104,6 @@ static void __exit nvmet_rdma_exit(void) · 2103 unmodified lines | ||
| 2104 | 2104 | module_init(nvmet_rdma_init); |
| 2105 | 2105 | module_exit(nvmet_rdma_exit); |
| 2106 | 2106 | |
| 2107 | +MODULE_DESCRIPTION("NVMe target RDMA transport driver"); | |
| 2107 | 2108 | MODULE_LICENSE("GPL v2"); |
| 2108 | 2109 | MODULE_ALIAS("nvmet-transport-1"); /* 1 == NVMF_TRTYPE_RDMA */ |
| @@ -2216,10 +2216,12 @@ static void __exit nvmet_tcp_exit(void) · 2215 unmodified lines | ||
| 2216 | 2216 | flush_workqueue(nvmet_wq); |
| 2217 | 2217 | |
| 2218 | 2218 | destroy_workqueue(nvmet_tcp_wq); |
| 2219 | + ida_destroy(&nvmet_tcp_queue_ida); | |
| 2219 | 2220 | } |
| 2220 | 2221 | |
| 2221 | 2222 | module_init(nvmet_tcp_init); |
| 2222 | 2223 | module_exit(nvmet_tcp_exit); |
| 2223 | 2224 | |
| 2225 | +MODULE_DESCRIPTION("NVMe target TCP transport driver"); | |
| 2224 | 2226 | MODULE_LICENSE("GPL v2"); |
| 2225 | 2227 | MODULE_ALIAS("nvmet-transport-3"); /* 3 == NVMF_TRTYPE_TCP */ |
| @@ -386,21 +386,8 @@ void pci_bus_add_devices(const struct pci_bus *bus) · 385 unmodified lines | ||
| 386 | 386 | } |
| 387 | 387 | EXPORT_SYMBOL(pci_bus_add_devices); |
| 388 | 388 | |
| 389 | −/** pci_walk_bus - walk devices on/under bus, calling callback. | |
| 390 | − * @top bus whose devices should be walked | |
| 391 | − * @cb callback to be called for each device found | |
| 392 | − * @userdata arbitrary pointer to be passed to callback. | |
| 393 | − * | |
| 394 | − * Walk the given bus, including any bridged devices | |
| 395 | − * on buses under this bus. Call the provided callback | |
| 396 | − * on each device found. | |
| 397 | − * | |
| 398 | − * We check the return of @cb each time. If it returns anything | |
| 399 | − * other than 0, we break out. | |
| 400 | − * | |
| 401 | − */ | |
| 402 | −void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |
| 403 | − void *userdata) | |
| 389 | +static void __pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), | |
| 390 | + void *userdata, bool locked) | |
| 404 | 391 | { |
| 405 | 392 | struct pci_dev *dev; |
| 406 | 393 | struct pci_bus *bus; |
| @@ -408,7 +395,8 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), · 1 unmodified line | ||
| 408 | 395 | int retval; |
| 409 | 396 | |
| 410 | 397 | bus = top; |
| 411 | − down_read(&pci_bus_sem); | |
| 398 | + if (!locked) | |
| 399 | + down_read(&pci_bus_sem); | |
| 412 | 400 | next = top->devices.next; |
| 413 | 401 | for (;;) { |
| 414 | 402 | if (next == &bus->devices) { |
| @@ -431,10 +419,37 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), · 16 unmodified lines | ||
| 431 | 419 | if (retval) |
| 432 | 420 | break; |
| 433 | 421 | } |
| 434 | − up_read(&pci_bus_sem); | |
| 422 | + if (!locked) | |
| 423 | + up_read(&pci_bus_sem); | |
| 424 | +} | |
| 425 | + | |
| 426 | +/** | |
| 427 | + * pci_walk_bus - walk devices on/under bus, calling callback. | |
| 428 | + * @top: bus whose devices should be walked | |
| 429 | + * @cb: callback to be called for each device found | |
| 430 | + * @userdata: arbitrary pointer to be passed to callback | |
| 431 | + * | |
| 432 | + * Walk the given bus, including any bridged devices | |
| 433 | + * on buses under this bus. Call the provided callback | |
| 434 | + * on each device found. | |
| 435 | + * | |
| 436 | + * We check the return of @cb each time. If it returns anything | |
| 437 | + * other than 0, we break out. | |
| 438 | + */ | |
| 439 | +void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) | |
| 440 | +{ | |
| 441 | + __pci_walk_bus(top, cb, userdata, false); | |
| 435 | 442 | } |
| 436 | 443 | EXPORT_SYMBOL_GPL(pci_walk_bus); |
| 437 | 444 | |
| 445 | +void pci_walk_bus_locked(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) | |
| 446 | +{ | |
| 447 | + lockdep_assert_held(&pci_bus_sem); | |
| 448 | + | |
| 449 | + __pci_walk_bus(top, cb, userdata, true); | |
| 450 | +} | |
| 451 | +EXPORT_SYMBOL_GPL(pci_walk_bus_locked); | |
| 452 | + | |
| 438 | 453 | struct pci_bus *pci_bus_get(struct pci_bus *bus) |
| 439 | 454 | { |
| 440 | 455 | if (bus) |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> |
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | +#include <linux/align.h> | |
| 9 | 10 | #include <linux/bitfield.h> |
| 10 | 11 | #include <linux/of.h> |
| 11 | 12 | #include <linux/platform_device.h> |
| @@ -482,9 +483,10 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, · 470 unmodified lines | ||
| 482 | 483 | reg = ep_func->msi_cap + PCI_MSI_DATA_32; |
| 483 | 484 | msg_data = dw_pcie_ep_readw_dbi(ep, func_no, reg); |
| 484 | 485 | } |
| 485 | − aligned_offset = msg_addr_lower & (epc->mem->window.page_size - 1); | |
| 486 | − msg_addr = ((u64)msg_addr_upper) << 32 | | |
| 487 | − (msg_addr_lower & ~aligned_offset); | |
| 486 | + msg_addr = ((u64)msg_addr_upper) << 32 | msg_addr_lower; | |
| 487 | + | |
| 488 | + aligned_offset = msg_addr & (epc->mem->window.page_size - 1); | |
| 489 | + msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size); | |
| 488 | 490 | ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr, |
| 489 | 491 | epc->mem->window.page_size); |
| 490 | 492 | if (ret) |
| @@ -551,7 +553,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no, · 60 unmodified lines | ||
| 551 | 553 | } |
| 552 | 554 | |
| 553 | 555 | aligned_offset = msg_addr & (epc->mem->window.page_size - 1); |
| 554 | − msg_addr &= ~aligned_offset; | |
| 556 | + msg_addr = ALIGN_DOWN(msg_addr, epc->mem->window.page_size); | |
| 555 | 557 | ret = dw_pcie_ep_map_addr(epc, func_no, 0, ep->msi_mem_phys, msg_addr, |
| 556 | 558 | epc->mem->window.page_size); |
| 557 | 559 | if (ret) |
| @@ -972,7 +972,7 @@ static int qcom_pcie_enable_aspm(struct pci_dev *pdev, void *userdata) · 971 unmodified lines | ||
| 972 | 972 | * Downstream devices need to be in D0 state before enabling PCI PM |
| 973 | 973 | * substates. |
| 974 | 974 | */ |
| 975 | − pci_set_power_state(pdev, PCI_D0); | |
| 975 | + pci_set_power_state_locked(pdev, PCI_D0); | |
| 976 | 976 | pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); |
| 977 | 977 | |
| 978 | 978 | return 0; |
| @@ -1354,6 +1354,7 @@ end: · 1353 unmodified lines | ||
| 1354 | 1354 | /** |
| 1355 | 1355 | * pci_set_full_power_state - Put a PCI device into D0 and update its state |
| 1356 | 1356 | * @dev: PCI device to power up |
| 1357 | + * @locked: whether pci_bus_sem is held | |
| 1357 | 1358 | * |
| 1358 | 1359 | * Call pci_power_up() to put @dev into D0, read from its PCI_PM_CTRL register |
| 1359 | 1360 | * to confirm the state change, restore its BARs if they might be lost and |
| @@ -1363,7 +1364,7 @@ end: · 3 unmodified lines | ||
| 1363 | 1364 | * to D0, it is more efficient to use pci_power_up() directly instead of this |
| 1364 | 1365 | * function. |
| 1365 | 1366 | */ |
| 1366 | −static int pci_set_full_power_state(struct pci_dev *dev) | |
| 1367 | +static int pci_set_full_power_state(struct pci_dev *dev, bool locked) | |
| 1367 | 1368 | { |
| 1368 | 1369 | u16 pmcsr; |
| 1369 | 1370 | int ret; |
| @@ -1399,7 +1400,7 @@ static int pci_set_full_power_state(struct pci_dev *dev) · 29 unmodified lines | ||
| 1399 | 1400 | } |
| 1400 | 1401 | |
| 1401 | 1402 | if (dev->bus->self) |
| 1402 | − pcie_aspm_pm_state_change(dev->bus->self); | |
| 1403 | + pcie_aspm_pm_state_change(dev->bus->self, locked); | |
| 1403 | 1404 | |
| 1404 | 1405 | return 0; |
| 1405 | 1406 | } |
| @@ -1428,10 +1429,22 @@ void pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state) · 22 unmodified lines | ||
| 1428 | 1429 | pci_walk_bus(bus, __pci_dev_set_current_state, &state); |
| 1429 | 1430 | } |
| 1430 | 1431 | |
| 1432 | +static void __pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state, bool locked) | |
| 1433 | +{ | |
| 1434 | + if (!bus) | |
| 1435 | + return; | |
| 1436 | + | |
| 1437 | + if (locked) | |
| 1438 | + pci_walk_bus_locked(bus, __pci_dev_set_current_state, &state); | |
| 1439 | + else | |
| 1440 | + pci_walk_bus(bus, __pci_dev_set_current_state, &state); | |
| 1441 | +} | |
| 1442 | + | |
| 1431 | 1443 | /** |
| 1432 | 1444 | * pci_set_low_power_state - Put a PCI device into a low-power state. |
| 1433 | 1445 | * @dev: PCI device to handle. |
| 1434 | 1446 | * @state: PCI power state (D1, D2, D3hot) to put the device into. |
| 1447 | + * @locked: whether pci_bus_sem is held | |
| 1435 | 1448 | * |
| 1436 | 1449 | * Use the device's PCI_PM_CTRL register to put it into a low-power state. |
| 1437 | 1450 | * |
| @@ -1442,7 +1455,7 @@ void pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state) · 4 unmodified lines | ||
| 1442 | 1455 | * 0 if device already is in the requested state. |
| 1443 | 1456 | * 0 if device's power state has been successfully changed. |
| 1444 | 1457 | */ |
| 1445 | −static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) | |
| 1458 | +static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state, bool locked) | |
| 1446 | 1459 | { |
| 1447 | 1460 | u16 pmcsr; |
| 1448 | 1461 | |
| @@ -1496,29 +1509,12 @@ static int pci_set_low_power_state(struct pci_dev *dev, pci_power_t state) · 47 unmodified lines | ||
| 1496 | 1509 | pci_power_name(state)); |
| 1497 | 1510 | |
| 1498 | 1511 | if (dev->bus->self) |
| 1499 | − pcie_aspm_pm_state_change(dev->bus->self); | |
| 1512 | + pcie_aspm_pm_state_change(dev->bus->self, locked); | |
| 1500 | 1513 | |
| 1501 | 1514 | return 0; |
| 1502 | 1515 | } |
| 1503 | 1516 | |
| 1504 | −/** | |
| 1505 | − * pci_set_power_state - Set the power state of a PCI device | |
| 1506 | − * @dev: PCI device to handle. | |
| 1507 | − * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | |
| 1508 | − * | |
| 1509 | − * Transition a device to a new power state, using the platform firmware and/or | |
| 1510 | − * the device's PCI PM registers. | |
| 1511 | − * | |
| 1512 | − * RETURN VALUE: | |
| 1513 | − * -EINVAL if the requested state is invalid. | |
| 1514 | − * -EIO if device does not support PCI PM or its PM capabilities register has a | |
| 1515 | − * wrong version, or device doesn't support the requested state. | |
| 1516 | − * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. | |
| 1517 | − * 0 if device already is in the requested state. | |
| 1518 | − * 0 if the transition is to D3 but D3 is not supported. | |
| 1519 | − * 0 if device's power state has been successfully changed. | |
| 1520 | − */ | |
| 1521 | −int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |
| 1517 | +static int __pci_set_power_state(struct pci_dev *dev, pci_power_t state, bool locked) | |
| 1522 | 1518 | { |
| 1523 | 1519 | int error; |
| 1524 | 1520 | |
| @@ -1542,7 +1538,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) · 17 unmodified lines | ||
| 1542 | 1538 | return 0; |
| 1543 | 1539 | |
| 1544 | 1540 | if (state == PCI_D0) |
| 1545 | − return pci_set_full_power_state(dev); | |
| 1541 | + return pci_set_full_power_state(dev, locked); | |
| 1546 | 1542 | |
| 1547 | 1543 | /* |
| 1548 | 1544 | * This device is quirked not to be put into D3, so don't put it in |
| @@ -1556,16 +1552,16 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) · 7 unmodified lines | ||
| 1556 | 1552 | * To put the device in D3cold, put it into D3hot in the native |
| 1557 | 1553 | * way, then put it into D3cold using platform ops. |
| 1558 | 1554 | */ |
| 1559 | − error = pci_set_low_power_state(dev, PCI_D3hot); | |
| 1555 | + error = pci_set_low_power_state(dev, PCI_D3hot, locked); | |
| 1560 | 1556 | |
| 1561 | 1557 | if (pci_platform_power_transition(dev, PCI_D3cold)) |
| 1562 | 1558 | return error; |
| 1563 | 1559 | |
| 1564 | 1560 | /* Powering off a bridge may power off the whole hierarchy */ |
| 1565 | 1561 | if (dev->current_state == PCI_D3cold) |
| 1566 | − pci_bus_set_current_state(dev->subordinate, PCI_D3cold); | |
| 1562 | + __pci_bus_set_current_state(dev->subordinate, PCI_D3cold, locked); | |
| 1567 | 1563 | } else { |
| 1568 | − error = pci_set_low_power_state(dev, state); | |
| 1564 | + error = pci_set_low_power_state(dev, state, locked); | |
| 1569 | 1565 | |
| 1570 | 1566 | if (pci_platform_power_transition(dev, state)) |
| 1571 | 1567 | return error; |
| @@ -1573,8 +1569,38 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) · 1 unmodified line | ||
| 1573 | 1569 | |
| 1574 | 1570 | return 0; |
| 1575 | 1571 | } |
| 1572 | + | |
| 1573 | +/** | |
| 1574 | + * pci_set_power_state - Set the power state of a PCI device | |
| 1575 | + * @dev: PCI device to handle. | |
| 1576 | + * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | |
| 1577 | + * | |
| 1578 | + * Transition a device to a new power state, using the platform firmware and/or | |
| 1579 | + * the device's PCI PM registers. | |
| 1580 | + * | |
| 1581 | + * RETURN VALUE: | |
| 1582 | + * -EINVAL if the requested state is invalid. | |
| 1583 | + * -EIO if device does not support PCI PM or its PM capabilities register has a | |
| 1584 | + * wrong version, or device doesn't support the requested state. | |
| 1585 | + * 0 if the transition is to D1 or D2 but D1 and D2 are not supported. | |
| 1586 | + * 0 if device already is in the requested state. | |
| 1587 | + * 0 if the transition is to D3 but D3 is not supported. | |
| 1588 | + * 0 if device's power state has been successfully changed. | |
| 1589 | + */ | |
| 1590 | +int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |
| 1591 | +{ | |
| 1592 | + return __pci_set_power_state(dev, state, false); | |
| 1593 | +} | |
| 1576 | 1594 | EXPORT_SYMBOL(pci_set_power_state); |
| 1577 | 1595 | |
11 more lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 160 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 248 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 297 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 276 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 197 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 409 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 239 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 466 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 314 lines aren’t shown here.
This diff is large: its 747 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 897 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 233 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 587 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 192 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 198 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 326 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 203 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 4 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 66 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 268 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 199 lines aren’t shown here.
This diff is large: its 456 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 345 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 231 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 460 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1178 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 200 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 171 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
File mode changed from 100755 to 100644.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
File mode changed from 100755 to 100644.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 214 lines aren’t shown here.
This diff is large: its 2 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 71 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.