We need the fixes in here as well, and also resolve some merge conflicts in: drivers/misc/eeprom/at25.c
Unified · Split
| @@ -126,6 +126,8 @@ Greg Kroah-Hartman <gregkh@suse.de> · 125 unmodified lines | ||
| 126 | 126 | Greg Kroah-Hartman <greg@kroah.com> |
| 127 | 127 | Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com> |
| 128 | 128 | Gregory CLEMENT <gregory.clement@bootlin.com> <gregory.clement@free-electrons.com> |
| 129 | +Guo Ren <guoren@kernel.org> <guoren@linux.alibaba.com> | |
| 130 | +Guo Ren <guoren@kernel.org> <ren_guo@c-sky.com> | |
| 129 | 131 | Gustavo Padovan <gustavo@las.ic.unicamp.br> |
| 130 | 132 | Gustavo Padovan <padovan@profusion.mobi> |
| 131 | 133 | Hanjun Guo <guohanjun@huawei.com> <hanjun.guo@linaro.org> |
| @@ -25,6 +25,6 @@ Sub graphs of DRBD's state transitions · 24 unmodified lines | ||
| 25 | 25 | :alt: disk-states-8.dot |
| 26 | 26 | :align: center |
| 27 | 27 | |
| 28 | −.. kernel-figure:: node-states-8.dot | |
| 29 | − :alt: node-states-8.dot | |
| 28 | +.. kernel-figure:: peer-states-8.dot | |
| 29 | + :alt: peer-states-8.dot | |
| 30 | 30 | :align: center |
| @@ -1,8 +1,3 @@ | ||
| 1 | −digraph node_states { | |
| 2 | − Secondary -> Primary [ label = "ioctl_set_state()" ] | |
| 3 | − Primary -> Secondary [ label = "ioctl_set_state()" ] | |
| 4 | −} | |
| 5 | − | |
| 6 | 1 | digraph peer_states { |
| 7 | 2 | Secondary -> Primary [ label = "recv state packet" ] |
| 8 | 3 | Primary -> Secondary [ label = "recv state packet" ] |
| @@ -53,11 +53,10 @@ The number of bits that the PAC occupies in a pointer is 55 minus the · 52 unmodified lines | ||
| 53 | 53 | virtual address size configured by the kernel. For example, with a |
| 54 | 54 | virtual address size of 48, the PAC is 7 bits wide. |
| 55 | 55 | |
| 56 | −Recent versions of GCC can compile code with APIAKey-based return | |
| 57 | −address protection when passed the -msign-return-address option. This | |
| 58 | −uses instructions in the HINT space (unless -march=armv8.3-a or higher | |
| 59 | −is also passed), and such code can run on systems without the pointer | |
| 60 | −authentication extension. | |
| 56 | +When ARM64_PTR_AUTH_KERNEL is selected, the kernel will be compiled | |
| 57 | +with HINT space pointer authentication instructions protecting | |
| 58 | +function returns. Kernels built with this option will work on hardware | |
| 59 | +with or without pointer authentication support. | |
| 61 | 60 | |
| 62 | 61 | In addition to exec(), keys can also be reinitialized to random values |
| 63 | 62 | using the PR_PAC_RESET_KEYS prctl. A bitmask of PR_PAC_APIAKEY, |
| @@ -249,11 +249,16 @@ except ImportError: · 248 unmodified lines | ||
| 249 | 249 | |
| 250 | 250 | html_static_path = ['sphinx-static'] |
| 251 | 251 | |
| 252 | −html_context = { | |
| 253 | − 'css_files': [ | |
| 254 | − '_static/theme_overrides.css', | |
| 255 | − ], | |
| 256 | −} | |
| 252 | +html_css_files = [ | |
| 253 | + 'theme_overrides.css', | |
| 254 | +] | |
| 255 | + | |
| 256 | +if major <= 1 and minor < 8: | |
| 257 | + html_context = { | |
| 258 | + 'css_files': [ | |
| 259 | + '_static/theme_overrides.css', | |
| 260 | + ], | |
| 261 | + } | |
| 257 | 262 | |
| 258 | 263 | # Add any extra paths that contain custom files (such as robots.txt or |
| 259 | 264 | # .htaccess) here, relative to this directory. These files are copied |
| @@ -73,12 +73,12 @@ CPUFREQ_POSTCHANGE. · 72 unmodified lines | ||
| 73 | 73 | The third argument is a struct cpufreq_freqs with the following |
| 74 | 74 | values: |
| 75 | 75 | |
| 76 | −===== =========================== | |
| 77 | −cpu number of the affected CPU | |
| 76 | +====== ====================================== | |
| 77 | +policy a pointer to the struct cpufreq_policy | |
| 78 | 78 | old old frequency |
| 79 | 79 | new new frequency |
| 80 | 80 | flags flags of the cpufreq driver |
| 81 | −===== =========================== | |
| 81 | +====== ====================================== | |
| 82 | 82 | |
| 83 | 83 | 3. CPUFreq Table Generation with Operating Performance Point (OPP) |
| 84 | 84 | ================================================================== |
| @@ -136,7 +136,7 @@ examples: · 135 unmodified lines | ||
| 136 | 136 | samsung,syscon-phandle = <&pmu_system_controller>; |
| 137 | 137 | |
| 138 | 138 | /* NTC thermistor is a hwmon device */ |
| 139 | − ncp15wb473 { | |
| 139 | + thermistor { | |
| 140 | 140 | compatible = "murata,ncp15wb473"; |
| 141 | 141 | pullup-uv = <1800000>; |
| 142 | 142 | pullup-ohm = <47000>; |
| @@ -142,7 +142,7 @@ examples: · 141 unmodified lines | ||
| 142 | 142 | down { |
| 143 | 143 | label = "GPIO Key DOWN"; |
| 144 | 144 | linux,code = <108>; |
| 145 | − interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>; | |
| 145 | + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; | |
| 146 | 146 | }; |
| 147 | 147 | }; |
| 148 | 148 | |
| @@ -79,6 +79,8 @@ properties: · 78 unmodified lines | ||
| 79 | 79 | |
| 80 | 80 | properties: |
| 81 | 81 | data-lanes: |
| 82 | + description: | |
| 83 | + Note that 'fsl,imx7-mipi-csi2' only supports up to 2 data lines. | |
| 82 | 84 | items: |
| 83 | 85 | minItems: 1 |
| 84 | 86 | maxItems: 4 |
| @@ -91,18 +93,6 @@ properties: · 6 unmodified lines | ||
| 91 | 93 | required: |
| 92 | 94 | - data-lanes |
| 93 | 95 | |
| 94 | − allOf: | |
| 95 | − - if: | |
| 96 | − properties: | |
| 97 | − compatible: | |
| 98 | − contains: | |
| 99 | − const: fsl,imx7-mipi-csi2 | |
| 100 | − then: | |
| 101 | − properties: | |
| 102 | − data-lanes: | |
| 103 | − items: | |
| 104 | − maxItems: 2 | |
| 105 | − | |
| 106 | 96 | port@1: |
| 107 | 97 | $ref: /schemas/graph.yaml#/properties/port |
| 108 | 98 | description: |
| @@ -91,6 +91,14 @@ properties: · 90 unmodified lines | ||
| 91 | 91 | compensate for the board being designed with the lanes |
| 92 | 92 | swapped. |
| 93 | 93 | |
| 94 | + enet-phy-lane-no-swap: | |
| 95 | + $ref: /schemas/types.yaml#/definitions/flag | |
| 96 | + description: | |
| 97 | + If set, indicates that PHY will disable swap of the | |
| 98 | + TX/RX lanes. This property allows the PHY to work correcly after | |
| 99 | + e.g. wrong bootstrap configuration caused by issues in PCB | |
| 100 | + layout design. | |
| 101 | + | |
| 94 | 102 | eee-broken-100tx: |
| 95 | 103 | $ref: /schemas/types.yaml#/definitions/flag |
| 96 | 104 | description: |
| @@ -29,7 +29,7 @@ properties: · 28 unmodified lines | ||
| 29 | 29 | - PHY_TYPE_PCIE |
| 30 | 30 | - PHY_TYPE_SATA |
| 31 | 31 | - PHY_TYPE_SGMII |
| 32 | − - PHY_TYPE_USB | |
| 32 | + - PHY_TYPE_USB3 | |
| 33 | 33 | - description: The PHY instance |
| 34 | 34 | minimum: 0 |
| 35 | 35 | maximum: 1 # for DP, SATA or USB |
| @@ -105,7 +105,7 @@ examples: · 104 unmodified lines | ||
| 105 | 105 | reg = <0x65>; |
| 106 | 106 | interrupt-parent = <&gpio1>; |
| 107 | 107 | interrupts = <16 IRQ_TYPE_EDGE_FALLING>; |
| 108 | − ti,watchdog-timer = <0>; | |
| 108 | + ti,watchdog-timeout-ms = <0>; | |
| 109 | 109 | ti,sc-ocp-limit-microamp = <2000000>; |
| 110 | 110 | ti,sc-ovp-limit-microvolt = <17800000>; |
| 111 | 111 | monitored-battery = <&bat>; |
| @@ -19,6 +19,9 @@ properties: · 18 unmodified lines | ||
| 19 | 19 | clocks: |
| 20 | 20 | maxItems: 1 |
| 21 | 21 | |
| 22 | + interrupts: | |
| 23 | + maxItems: 1 | |
| 24 | + | |
| 22 | 25 | "#sound-dai-cells": |
| 23 | 26 | const: 0 |
| 24 | 27 | |
| @@ -33,6 +33,7 @@ properties: · 32 unmodified lines | ||
| 33 | 33 | - rockchip,rk3328-spi |
| 34 | 34 | - rockchip,rk3368-spi |
| 35 | 35 | - rockchip,rk3399-spi |
| 36 | + - rockchip,rk3568-spi | |
| 36 | 37 | - rockchip,rv1126-spi |
| 37 | 38 | - const: rockchip,rk3066-spi |
| 38 | 39 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | .. SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | 3 | ================================= |
| 4 | −NETWORK FILESYSTEM HELPER LIBRARY | |
| 4 | +Network Filesystem Helper Library | |
| 5 | 5 | ================================= |
| 6 | 6 | |
| 7 | 7 | .. Contents: |
| @@ -37,22 +37,22 @@ into a common call framework. · 29 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | The following services are provided: |
| 39 | 39 | |
| 40 | − * Handles transparent huge pages (THPs). | |
| 40 | + * Handle folios that span multiple pages. | |
| 41 | 41 | |
| 42 | − * Insulates the netfs from VM interface changes. | |
| 42 | + * Insulate the netfs from VM interface changes. | |
| 43 | 43 | |
| 44 | − * Allows the netfs to arbitrarily split reads up into pieces, even ones that | |
| 45 | − don't match page sizes or page alignments and that may cross pages. | |
| 44 | + * Allow the netfs to arbitrarily split reads up into pieces, even ones that | |
| 45 | + don't match folio sizes or folio alignments and that may cross folios. | |
| 46 | 46 | |
| 47 | − * Allows the netfs to expand a readahead request in both directions to meet | |
| 48 | − its needs. | |
| 47 | + * Allow the netfs to expand a readahead request in both directions to meet its | |
| 48 | + needs. | |
| 49 | 49 | |
| 50 | − * Allows the netfs to partially fulfil a read, which will then be resubmitted. | |
| 50 | + * Allow the netfs to partially fulfil a read, which will then be resubmitted. | |
| 51 | 51 | |
| 52 | − * Handles local caching, allowing cached data and server-read data to be | |
| 52 | + * Handle local caching, allowing cached data and server-read data to be | |
| 53 | 53 | interleaved for a single request. |
| 54 | 54 | |
| 55 | − * Handles clearing of bufferage that aren't on the server. | |
| 55 | + * Handle clearing of bufferage that aren't on the server. | |
| 56 | 56 | |
| 57 | 57 | * Handle retrying of reads that failed, switching reads from the cache to the |
| 58 | 58 | server as necessary. |
| @@ -70,22 +70,22 @@ Read Helper Functions · 11 unmodified lines | ||
| 70 | 70 | |
| 71 | 71 | Three read helpers are provided:: |
| 72 | 72 | |
| 73 | − * void netfs_readahead(struct readahead_control *ractl, | |
| 74 | − const struct netfs_read_request_ops *ops, | |
| 75 | − void *netfs_priv);`` | |
| 76 | − * int netfs_readpage(struct file *file, | |
| 77 | − struct page *page, | |
| 78 | − const struct netfs_read_request_ops *ops, | |
| 79 | − void *netfs_priv); | |
| 80 | − * int netfs_write_begin(struct file *file, | |
| 81 | − struct address_space *mapping, | |
| 82 | − loff_t pos, | |
| 83 | − unsigned int len, | |
| 84 | − unsigned int flags, | |
| 85 | − struct page **_page, | |
| 86 | − void **_fsdata, | |
| 87 | − const struct netfs_read_request_ops *ops, | |
| 88 | − void *netfs_priv); | |
| 73 | + void netfs_readahead(struct readahead_control *ractl, | |
| 74 | + const struct netfs_read_request_ops *ops, | |
| 75 | + void *netfs_priv); | |
| 76 | + int netfs_readpage(struct file *file, | |
| 77 | + struct folio *folio, | |
| 78 | + const struct netfs_read_request_ops *ops, | |
| 79 | + void *netfs_priv); | |
| 80 | + int netfs_write_begin(struct file *file, | |
| 81 | + struct address_space *mapping, | |
| 82 | + loff_t pos, | |
| 83 | + unsigned int len, | |
| 84 | + unsigned int flags, | |
| 85 | + struct folio **_folio, | |
| 86 | + void **_fsdata, | |
| 87 | + const struct netfs_read_request_ops *ops, | |
| 88 | + void *netfs_priv); | |
| 89 | 89 | |
| 90 | 90 | Each corresponds to a VM operation, with the addition of a couple of parameters |
| 91 | 91 | for the use of the read helpers: |
| @@ -103,8 +103,8 @@ Both of these values will be stored into the read request structure. · 11 unmodified lines | ||
| 103 | 103 | For ->readahead() and ->readpage(), the network filesystem should just jump |
| 104 | 104 | into the corresponding read helper; whereas for ->write_begin(), it may be a |
| 105 | 105 | little more complicated as the network filesystem might want to flush |
| 106 | −conflicting writes or track dirty data and needs to put the acquired page if an | |
| 107 | −error occurs after calling the helper. | |
| 106 | +conflicting writes or track dirty data and needs to put the acquired folio if | |
| 107 | +an error occurs after calling the helper. | |
| 108 | 108 | |
| 109 | 109 | The helpers manage the read request, calling back into the network filesystem |
| 110 | 110 | through the suppplied table of operations. Waits will be performed as |
| @@ -253,7 +253,7 @@ through which it can issue requests and negotiate:: · 142 unmodified lines | ||
| 253 | 253 | void (*issue_op)(struct netfs_read_subrequest *subreq); |
| 254 | 254 | bool (*is_still_valid)(struct netfs_read_request *rreq); |
| 255 | 255 | int (*check_write_begin)(struct file *file, loff_t pos, unsigned len, |
| 256 | − struct page *page, void **_fsdata); | |
| 256 | + struct folio *folio, void **_fsdata); | |
| 257 | 257 | void (*done)(struct netfs_read_request *rreq); |
| 258 | 258 | void (*cleanup)(struct address_space *mapping, void *netfs_priv); |
| 259 | 259 | }; |
| @@ -313,13 +313,14 @@ The operations are as follows: · 53 unmodified lines | ||
| 313 | 313 | |
| 314 | 314 | There is no return value; the netfs_subreq_terminated() function should be |
| 315 | 315 | called to indicate whether or not the operation succeeded and how much data |
| 316 | − it transferred. The filesystem also should not deal with setting pages | |
| 316 | + it transferred. The filesystem also should not deal with setting folios | |
| 317 | 317 | uptodate, unlocking them or dropping their refs - the helpers need to deal |
| 318 | 318 | with this as they have to coordinate with copying to the local cache. |
| 319 | 319 | |
| 320 | − Note that the helpers have the pages locked, but not pinned. It is possible | |
| 321 | − to use the ITER_XARRAY iov iterator to refer to the range of the inode that | |
| 322 | − is being operated upon without the need to allocate large bvec tables. | |
| 320 | + Note that the helpers have the folios locked, but not pinned. It is | |
| 321 | + possible to use the ITER_XARRAY iov iterator to refer to the range of the | |
| 322 | + inode that is being operated upon without the need to allocate large bvec | |
| 323 | + tables. | |
| 323 | 324 | |
| 324 | 325 | * ``is_still_valid()`` |
| 325 | 326 | |
| @@ -330,15 +331,15 @@ The operations are as follows: · 4 unmodified lines | ||
| 330 | 331 | * ``check_write_begin()`` |
| 331 | 332 | |
| 332 | 333 | [Optional] This is called from the netfs_write_begin() helper once it has |
| 333 | − allocated/grabbed the page to be modified to allow the filesystem to flush | |
| 334 | + allocated/grabbed the folio to be modified to allow the filesystem to flush | |
| 334 | 335 | conflicting state before allowing it to be modified. |
| 335 | 336 | |
| 336 | − It should return 0 if everything is now fine, -EAGAIN if the page should be | |
| 337 | + It should return 0 if everything is now fine, -EAGAIN if the folio should be | |
| 337 | 338 | regrabbed and any other error code to abort the operation. |
| 338 | 339 | |
| 339 | 340 | * ``done`` |
| 340 | 341 | |
| 341 | − [Optional] This is called after the pages in the request have all been | |
| 342 | + [Optional] This is called after the folios in the request have all been | |
| 342 | 343 | unlocked (and marked uptodate if applicable). |
| 343 | 344 | |
| 344 | 345 | * ``cleanup`` |
| @@ -390,7 +391,7 @@ The read helpers work by the following general procedure: · 45 unmodified lines | ||
| 390 | 391 | * If NETFS_SREQ_CLEAR_TAIL was set, a short read will be cleared to the |
| 391 | 392 | end of the slice instead of reissuing. |
| 392 | 393 | |
| 393 | − * Once the data is read, the pages that have been fully read/cleared: | |
| 394 | + * Once the data is read, the folios that have been fully read/cleared: | |
| 394 | 395 | |
| 395 | 396 | * Will be marked uptodate. |
| 396 | 397 | |
| @@ -398,11 +399,11 @@ The read helpers work by the following general procedure: · 1 unmodified line | ||
| 398 | 399 | |
| 399 | 400 | * Unlocked |
| 400 | 401 | |
| 401 | − * Any pages that need writing to the cache will then have DIO writes issued. | |
| 402 | + * Any folios that need writing to the cache will then have DIO writes issued. | |
| 402 | 403 | |
| 403 | 404 | * Synchronous operations will wait for reading to be complete. |
| 404 | 405 | |
| 405 | − * Writes to the cache will proceed asynchronously and the pages will have the | |
| 406 | + * Writes to the cache will proceed asynchronously and the folios will have the | |
| 406 | 407 | PG_fscache mark removed when that completes. |
| 407 | 408 | |
| 408 | 409 | * The request structures will be cleaned up when everything has completed. |
| @@ -452,6 +453,9 @@ operation table looks like the following:: · 43 unmodified lines | ||
| 452 | 453 | netfs_io_terminated_t term_func, |
| 453 | 454 | void *term_func_priv); |
| 454 | 455 | |
| 456 | + int (*prepare_write)(struct netfs_cache_resources *cres, | |
| 457 | + loff_t *_start, size_t *_len, loff_t i_size); | |
| 458 | + | |
| 455 | 459 | int (*write)(struct netfs_cache_resources *cres, |
| 456 | 460 | loff_t start_pos, |
| 457 | 461 | struct iov_iter *iter, |
| @@ -509,6 +513,14 @@ The methods defined in the table are: · 51 unmodified lines | ||
| 509 | 513 | indicating whether the termination is definitely happening in the caller's |
| 510 | 514 | context. |
| 511 | 515 | |
| 516 | + * ``prepare_write()`` | |
| 517 | + | |
| 518 | + [Required] Called to adjust a write to the cache and check that there is | |
| 519 | + sufficient space in the cache. The start and length values indicate the | |
| 520 | + size of the write that netfslib is proposing, and this can be adjusted by | |
| 521 | + the cache to respect DIO boundaries. The file size is passed for | |
| 522 | + information. | |
| 523 | + | |
| 512 | 524 | * ``write()`` |
| 513 | 525 | |
| 514 | 526 | [Required] Called to write to the cache. The start file offset is given |
| @@ -525,4 +537,9 @@ not the read request structure as they could be used in other situations where · 10 unmodified lines | ||
| 525 | 537 | there isn't a read request structure as well, such as writing dirty data to the |
| 526 | 538 | cache. |
| 527 | 539 | |
| 540 | + | |
| 541 | +API Function Reference | |
| 542 | +====================== | |
| 543 | + | |
| 528 | 544 | .. kernel-doc:: include/linux/netfs.h |
| 545 | +.. kernel-doc:: fs/netfs/read_helper.c | |
| @@ -439,11 +439,9 @@ preemption. The following substitution works on both kernels:: · 438 unmodified lines | ||
| 439 | 439 | spin_lock(&p->lock); |
| 440 | 440 | p->count += this_cpu_read(var2); |
| 441 | 441 | |
| 442 | −On a non-PREEMPT_RT kernel migrate_disable() maps to preempt_disable() | |
| 443 | −which makes the above code fully equivalent. On a PREEMPT_RT kernel | |
| 444 | 442 | migrate_disable() ensures that the task is pinned on the current CPU which |
| 445 | 443 | in turn guarantees that the per-CPU access to var1 and var2 are staying on |
| 446 | −the same CPU. | |
| 444 | +the same CPU while the task remains preemptible. | |
| 447 | 445 | |
| 448 | 446 | The migrate_disable() substitution is not valid for the following |
| 449 | 447 | scenario:: |
| @@ -456,9 +454,8 @@ scenario:: · 6 unmodified lines | ||
| 456 | 454 | p = this_cpu_ptr(&var1); |
| 457 | 455 | p->val = func2(); |
| 458 | 456 | |
| 459 | −While correct on a non-PREEMPT_RT kernel, this breaks on PREEMPT_RT because | |
| 460 | −here migrate_disable() does not protect against reentrancy from a | |
| 461 | −preempting task. A correct substitution for this case is:: | |
| 457 | +This breaks because migrate_disable() does not protect against reentrancy from | |
| 458 | +a preempting task. A correct substitution for this case is:: | |
| 462 | 459 | |
| 463 | 460 | func() |
| 464 | 461 | { |
| @@ -35,6 +35,7 @@ GNU make 3.81 make --version · 34 unmodified lines | ||
| 35 | 35 | binutils 2.23 ld -v |
| 36 | 36 | flex 2.5.35 flex --version |
| 37 | 37 | bison 2.0 bison --version |
| 38 | +pahole 1.16 pahole --version | |
| 38 | 39 | util-linux 2.10o fdformat --version |
| 39 | 40 | kmod 13 depmod -V |
| 40 | 41 | e2fsprogs 1.41.4 e2fsck -V |
| @@ -108,6 +109,16 @@ Bison · 67 unmodified lines | ||
| 108 | 109 | Since Linux 4.16, the build system generates parsers |
| 109 | 110 | during build. This requires bison 2.0 or later. |
| 110 | 111 | |
| 112 | +pahole: | |
| 113 | +------- | |
| 114 | + | |
| 115 | +Since Linux 5.2, if CONFIG_DEBUG_INFO_BTF is selected, the build system | |
| 116 | +generates BTF (BPF Type Format) from DWARF in vmlinux, a bit later from kernel | |
| 117 | +modules as well. This requires pahole v1.16 or later. | |
| 118 | + | |
| 119 | +It is found in the 'dwarves' or 'pahole' distro packages or from | |
| 120 | +https://fedorapeople.org/~acme/dwarves/. | |
| 121 | + | |
| 111 | 122 | Perl |
| 112 | 123 | ---- |
| 113 | 124 | |
| @@ -14,7 +14,8 @@ works, see Documentation/process/development-process.rst. Also, read · 13 unmodified lines | ||
| 14 | 14 | Documentation/process/submit-checklist.rst |
| 15 | 15 | for a list of items to check before submitting code. If you are submitting |
| 16 | 16 | a driver, also read Documentation/process/submitting-drivers.rst; for device |
| 17 | −tree binding patches, read Documentation/process/submitting-patches.rst. | |
| 17 | +tree binding patches, read | |
| 18 | +Documentation/devicetree/bindings/submitting-patches.rst. | |
| 18 | 19 | |
| 19 | 20 | This documentation assumes that you're using ``git`` to prepare your patches. |
| 20 | 21 | If you're unfamiliar with ``git``, you would be well-advised to learn how to |
| @@ -9331,7 +9331,6 @@ S: Maintained · 9330 unmodified lines | ||
| 9331 | 9331 | F: drivers/iio/pressure/dps310.c |
| 9332 | 9332 | |
| 9333 | 9333 | INFINIBAND SUBSYSTEM |
| 9334 | −M: Doug Ledford <dledford@redhat.com> | |
| 9335 | 9334 | M: Jason Gunthorpe <jgg@nvidia.com> |
| 9336 | 9335 | L: linux-rdma@vger.kernel.org |
| 9337 | 9336 | S: Supported |
| @@ -10282,9 +10281,9 @@ F: lib/Kconfig.kcsan · 944 unmodified lines | ||
| 10282 | 10281 | F: scripts/Makefile.kcsan |
| 10283 | 10282 | |
| 10284 | 10283 | KDUMP |
| 10285 | −M: Dave Young <dyoung@redhat.com> | |
| 10286 | 10284 | M: Baoquan He <bhe@redhat.com> |
| 10287 | 10285 | R: Vivek Goyal <vgoyal@redhat.com> |
| 10286 | +R: Dave Young <dyoung@redhat.com> | |
| 10288 | 10287 | L: kexec@lists.infradead.org |
| 10289 | 10288 | S: Maintained |
| 10290 | 10289 | W: http://lse.sourceforge.net/kdump/ |
| @@ -12182,8 +12181,8 @@ F: drivers/net/ethernet/mellanox/mlx5/core/fpga/* · 1891 unmodified lines | ||
| 12182 | 12181 | F: include/linux/mlx5/mlx5_ifc_fpga.h |
| 12183 | 12182 | |
| 12184 | 12183 | MELLANOX ETHERNET SWITCH DRIVERS |
| 12185 | −M: Jiri Pirko <jiri@nvidia.com> | |
| 12186 | 12184 | M: Ido Schimmel <idosch@nvidia.com> |
| 12185 | +M: Petr Machata <petrm@nvidia.com> | |
| 12187 | 12186 | L: netdev@vger.kernel.org |
| 12188 | 12187 | S: Supported |
| 12189 | 12188 | W: http://www.mellanox.com |
| @@ -15773,6 +15772,15 @@ S: Maintained · 3583 unmodified lines | ||
| 15773 | 15772 | F: Documentation/devicetree/bindings/net/qcom,ethqos.txt |
| 15774 | 15773 | F: drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c |
| 15775 | 15774 | |
| 15775 | +QUALCOMM FASTRPC DRIVER | |
| 15776 | +M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> | |
| 15777 | +M: Amol Maheshwari <amahesh@qti.qualcomm.com> | |
| 15778 | +L: linux-arm-msm@vger.kernel.org | |
| 15779 | +S: Maintained | |
| 15780 | +F: Documentation/devicetree/bindings/misc/qcom,fastrpc.txt | |
| 15781 | +F: drivers/misc/fastrpc.c | |
| 15782 | +F: include/uapi/misc/fastrpc.h | |
| 15783 | + | |
| 15776 | 15784 | QUALCOMM GENERIC INTERFACE I2C DRIVER |
| 15777 | 15785 | M: Akash Asthana <akashast@codeaurora.org> |
| 15778 | 15786 | M: Mukesh Savaliya <msavaliy@codeaurora.org> |
| @@ -15981,6 +15989,7 @@ F: arch/mips/generic/board-ranchu.c · 202 unmodified lines | ||
| 15981 | 15989 | |
| 15982 | 15990 | RANDOM NUMBER DRIVER |
| 15983 | 15991 | M: "Theodore Ts'o" <tytso@mit.edu> |
| 15992 | +M: Jason A. Donenfeld <Jason@zx2c4.com> | |
| 15984 | 15993 | S: Maintained |
| 15985 | 15994 | F: drivers/char/random.c |
| 15986 | 15995 | |
| @@ -16503,6 +16512,12 @@ T: git git://linuxtv.org/media_tree.git · 516 unmodified lines | ||
| 16503 | 16512 | F: Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml |
| 16504 | 16513 | F: drivers/media/platform/sunxi/sun8i-rotate/ |
| 16505 | 16514 | |
| 16515 | +RPMSG TTY DRIVER | |
| 16516 | +M: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com> | |
| 16517 | +L: linux-remoteproc@vger.kernel.org | |
| 16518 | +S: Maintained | |
| 16519 | +F: drivers/tty/rpmsg_tty.c | |
| 16520 | + | |
| 16506 | 16521 | RTL2830 MEDIA DRIVER |
| 16507 | 16522 | M: Antti Palosaari <crope@iki.fi> |
| 16508 | 16523 | L: linux-media@vger.kernel.org |
| @@ -16624,8 +16639,8 @@ W: http://www.ibm.com/developerworks/linux/linux390/ · 115 unmodified lines | ||
| 16624 | 16639 | F: drivers/iommu/s390-iommu.c |
| 16625 | 16640 | |
| 16626 | 16641 | S390 IUCV NETWORK LAYER |
| 16627 | −M: Julian Wiedmann <jwi@linux.ibm.com> | |
| 16628 | −M: Karsten Graul <kgraul@linux.ibm.com> | |
| 16642 | +M: Alexandra Winter <wintera@linux.ibm.com> | |
| 16643 | +M: Wenjia Zhang <wenjia@linux.ibm.com> | |
| 16629 | 16644 | L: linux-s390@vger.kernel.org |
| 16630 | 16645 | L: netdev@vger.kernel.org |
| 16631 | 16646 | S: Supported |
| @@ -16635,8 +16650,8 @@ F: include/net/iucv/ · 3 unmodified lines | ||
| 16635 | 16650 | F: net/iucv/ |
| 16636 | 16651 | |
| 16637 | 16652 | S390 NETWORK DRIVERS |
| 16638 | −M: Julian Wiedmann <jwi@linux.ibm.com> | |
| 16639 | −M: Karsten Graul <kgraul@linux.ibm.com> | |
| 16653 | +M: Alexandra Winter <wintera@linux.ibm.com> | |
| 16654 | +M: Wenjia Zhang <wenjia@linux.ibm.com> | |
| 16640 | 16655 | L: linux-s390@vger.kernel.org |
| 16641 | 16656 | L: netdev@vger.kernel.org |
| 16642 | 16657 | S: Supported |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 5 |
| 3 | 3 | PATCHLEVEL = 16 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc3 | |
| 5 | +EXTRAVERSION = -rc5 | |
| 6 | 6 | NAME = Gobble Gobble |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -789,7 +789,7 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong · 780 unmodified lines | ||
| 789 | 789 | KBUILD_CFLAGS += $(stackp-flags-y) |
| 790 | 790 | |
| 791 | 791 | KBUILD_CFLAGS-$(CONFIG_WERROR) += -Werror |
| 792 | −KBUILD_CFLAGS += $(KBUILD_CFLAGS-y) $(CONFIG_CC_IMPLICIT_FALLTHROUGH) | |
| 792 | +KBUILD_CFLAGS += $(KBUILD_CFLAGS-y) $(CONFIG_CC_IMPLICIT_FALLTHROUGH:"%"=%) | |
| 793 | 793 | |
| 794 | 794 | ifdef CONFIG_CC_IS_CLANG |
| 795 | 795 | KBUILD_CPPFLAGS += -Qunused-arguments |
| @@ -1374,17 +1374,17 @@ endif · 578 unmodified lines | ||
| 1374 | 1374 | |
| 1375 | 1375 | ifneq ($(dtstree),) |
| 1376 | 1376 | |
| 1377 | −%.dtb: dt_binding_check include/config/kernel.release scripts_dtc | |
| 1378 | − $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ $(dtstree)/$*.dt.yaml | |
| 1377 | +%.dtb: include/config/kernel.release scripts_dtc | |
| 1378 | + $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ | |
| 1379 | 1379 | |
| 1380 | −%.dtbo: dt_binding_check include/config/kernel.release scripts_dtc | |
| 1381 | − $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ $(dtstree)/$*.dt.yaml | |
| 1380 | +%.dtbo: include/config/kernel.release scripts_dtc | |
| 1381 | + $(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@ | |
| 1382 | 1382 | |
| 1383 | 1383 | PHONY += dtbs dtbs_install dtbs_check |
| 1384 | 1384 | dtbs: include/config/kernel.release scripts_dtc |
| 1385 | 1385 | $(Q)$(MAKE) $(build)=$(dtstree) |
| 1386 | 1386 | |
| 1387 | −ifneq ($(filter dtbs_check %.dtb %.dtbo, $(MAKECMDGOALS)),) | |
| 1387 | +ifneq ($(filter dtbs_check, $(MAKECMDGOALS)),) | |
| 1388 | 1388 | export CHECK_DTBS=y |
| 1389 | 1389 | dtbs: dt_binding_check |
| 1390 | 1390 | endif |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | * Copyright The Asahi Linux Contributors |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | +#include <dt-bindings/gpio/gpio.h> | |
| 10 | 11 | #include <dt-bindings/interrupt-controller/apple-aic.h> |
| 11 | 12 | #include <dt-bindings/interrupt-controller/irq.h> |
| 12 | 13 | #include <dt-bindings/pinctrl/apple.h> |
| @@ -281,7 +282,7 @@ · 268 unmodified lines | ||
| 281 | 282 | port00: pci@0,0 { |
| 282 | 283 | device_type = "pci"; |
| 283 | 284 | reg = <0x0 0x0 0x0 0x0 0x0>; |
| 284 | − reset-gpios = <&pinctrl_ap 152 0>; | |
| 285 | + reset-gpios = <&pinctrl_ap 152 GPIO_ACTIVE_LOW>; | |
| 285 | 286 | max-link-speed = <2>; |
| 286 | 287 | |
| 287 | 288 | #address-cells = <3>; |
| @@ -301,7 +302,7 @@ · 13 unmodified lines | ||
| 301 | 302 | port01: pci@1,0 { |
| 302 | 303 | device_type = "pci"; |
| 303 | 304 | reg = <0x800 0x0 0x0 0x0 0x0>; |
| 304 | − reset-gpios = <&pinctrl_ap 153 0>; | |
| 305 | + reset-gpios = <&pinctrl_ap 153 GPIO_ACTIVE_LOW>; | |
| 305 | 306 | max-link-speed = <2>; |
| 306 | 307 | |
| 307 | 308 | #address-cells = <3>; |
| @@ -321,7 +322,7 @@ · 13 unmodified lines | ||
| 321 | 322 | port02: pci@2,0 { |
| 322 | 323 | device_type = "pci"; |
| 323 | 324 | reg = <0x1000 0x0 0x0 0x0 0x0>; |
| 324 | − reset-gpios = <&pinctrl_ap 33 0>; | |
| 325 | + reset-gpios = <&pinctrl_ap 33 GPIO_ACTIVE_LOW>; | |
| 325 | 326 | max-link-speed = <1>; |
| 326 | 327 | |
| 327 | 328 | #address-cells = <3>; |
| @@ -91,7 +91,7 @@ · 90 unmodified lines | ||
| 91 | 91 | #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) |
| 92 | 92 | |
| 93 | 93 | /* TCR_EL2 Registers bits */ |
| 94 | −#define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) | |
| 94 | +#define TCR_EL2_RES1 ((1U << 31) | (1 << 23)) | |
| 95 | 95 | #define TCR_EL2_TBI (1 << 20) |
| 96 | 96 | #define TCR_EL2_PS_SHIFT 16 |
| 97 | 97 | #define TCR_EL2_PS_MASK (7 << TCR_EL2_PS_SHIFT) |
| @@ -276,7 +276,7 @@ · 178 unmodified lines | ||
| 276 | 276 | #define CPTR_EL2_TFP_SHIFT 10 |
| 277 | 277 | |
| 278 | 278 | /* Hyp Coprocessor Trap Register */ |
| 279 | −#define CPTR_EL2_TCPAC (1 << 31) | |
| 279 | +#define CPTR_EL2_TCPAC (1U << 31) | |
| 280 | 280 | #define CPTR_EL2_TAM (1 << 30) |
| 281 | 281 | #define CPTR_EL2_TTA (1 << 20) |
| 282 | 282 | #define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT) |
| @@ -77,11 +77,17 @@ · 76 unmodified lines | ||
| 77 | 77 | .endm |
| 78 | 78 | |
| 79 | 79 | SYM_CODE_START(ftrace_regs_caller) |
| 80 | +#ifdef BTI_C | |
| 81 | + BTI_C | |
| 82 | +#endif | |
| 80 | 83 | ftrace_regs_entry 1 |
| 81 | 84 | b ftrace_common |
| 82 | 85 | SYM_CODE_END(ftrace_regs_caller) |
| 83 | 86 | |
| 84 | 87 | SYM_CODE_START(ftrace_caller) |
| 88 | +#ifdef BTI_C | |
| 89 | + BTI_C | |
| 90 | +#endif | |
| 85 | 91 | ftrace_regs_entry 0 |
| 86 | 92 | b ftrace_common |
| 87 | 93 | SYM_CODE_END(ftrace_caller) |
| @@ -147,7 +147,7 @@ int machine_kexec_post_load(struct kimage *kimage) · 146 unmodified lines | ||
| 147 | 147 | if (rc) |
| 148 | 148 | return rc; |
| 149 | 149 | kimage->arch.ttbr1 = __pa(trans_pgd); |
| 150 | − kimage->arch.zero_page = __pa(empty_zero_page); | |
| 150 | + kimage->arch.zero_page = __pa_symbol(empty_zero_page); | |
| 151 | 151 | |
| 152 | 152 | reloc_size = __relocate_new_kernel_end - __relocate_new_kernel_start; |
| 153 | 153 | memcpy(reloc_code, __relocate_new_kernel_start, reloc_size); |
| @@ -403,6 +403,8 @@ typedef bool (*exit_handler_fn)(struct kvm_vcpu *, u64 *); · 402 unmodified lines | ||
| 403 | 403 | |
| 404 | 404 | static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu); |
| 405 | 405 | |
| 406 | +static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code); | |
| 407 | + | |
| 406 | 408 | /* |
| 407 | 409 | * Allow the hypervisor to handle the exit with an exit handler if it has one. |
| 408 | 410 | * |
| @@ -429,6 +431,18 @@ static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code) · 20 unmodified lines | ||
| 429 | 431 | */ |
| 430 | 432 | static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) |
| 431 | 433 | { |
| 434 | + /* | |
| 435 | + * Save PSTATE early so that we can evaluate the vcpu mode | |
| 436 | + * early on. | |
| 437 | + */ | |
| 438 | + vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR); | |
| 439 | + | |
| 440 | + /* | |
| 441 | + * Check whether we want to repaint the state one way or | |
| 442 | + * another. | |
| 443 | + */ | |
| 444 | + early_exit_filter(vcpu, exit_code); | |
| 445 | + | |
| 432 | 446 | if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) |
| 433 | 447 | vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR); |
| 434 | 448 | |
| @@ -70,7 +70,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) · 69 unmodified lines | ||
| 70 | 70 | static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) |
| 71 | 71 | { |
| 72 | 72 | ctxt->regs.pc = read_sysreg_el2(SYS_ELR); |
| 73 | − ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); | |
| 73 | + /* | |
| 74 | + * Guest PSTATE gets saved at guest fixup time in all | |
| 75 | + * cases. We still need to handle the nVHE host side here. | |
| 76 | + */ | |
| 77 | + if (!has_vhe() && ctxt->__hyp_running_vcpu) | |
| 78 | + ctxt->regs.pstate = read_sysreg_el2(SYS_SPSR); | |
| 74 | 79 | |
| 75 | 80 | if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN)) |
| 76 | 81 | ctxt_sys_reg(ctxt, DISR_EL1) = read_sysreg_s(SYS_VDISR_EL2); |
| @@ -233,7 +233,7 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu) · 232 unmodified lines | ||
| 233 | 233 | * Returns false if the guest ran in AArch32 when it shouldn't have, and |
| 234 | 234 | * thus should exit to the host, or true if a the guest run loop can continue. |
| 235 | 235 | */ |
| 236 | −static bool handle_aarch32_guest(struct kvm_vcpu *vcpu, u64 *exit_code) | |
| 236 | +static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) | |
| 237 | 237 | { |
| 238 | 238 | struct kvm *kvm = kern_hyp_va(vcpu->kvm); |
| 239 | 239 | |
| @@ -248,10 +248,7 @@ static bool handle_aarch32_guest(struct kvm_vcpu *vcpu, u64 *exit_code) · 8 unmodified lines | ||
| 248 | 248 | vcpu->arch.target = -1; |
| 249 | 249 | *exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT); |
| 250 | 250 | *exit_code |= ARM_EXCEPTION_IL; |
| 251 | − return false; | |
| 252 | 251 | } |
| 253 | − | |
| 254 | − return true; | |
| 255 | 252 | } |
| 256 | 253 | |
| 257 | 254 | /* Switch to the guest for legacy non-VHE systems */ |
| @@ -316,9 +313,6 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) · 58 unmodified lines | ||
| 316 | 313 | /* Jump in the fire! */ |
| 317 | 314 | exit_code = __guest_enter(vcpu); |
| 318 | 315 | |
| 319 | − if (unlikely(!handle_aarch32_guest(vcpu, &exit_code))) | |
| 320 | − break; | |
| 321 | − | |
| 322 | 316 | /* And we're baaack! */ |
| 323 | 317 | } while (fixup_guest_exit(vcpu, &exit_code)); |
| 324 | 318 | |
| @@ -112,6 +112,10 @@ static const exit_handler_fn *kvm_get_exit_handler_array(struct kvm_vcpu *vcpu) · 111 unmodified lines | ||
| 112 | 112 | return hyp_exit_handlers; |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | +static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) | |
| 116 | +{ | |
| 117 | +} | |
| 118 | + | |
| 115 | 119 | /* Switch to the guest for VHE systems running in EL2 */ |
| 116 | 120 | static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) |
| 117 | 121 | { |
| @@ -209,7 +209,7 @@ asmlinkage void do_trap_illinsn(struct pt_regs *regs) · 208 unmodified lines | ||
| 209 | 209 | |
| 210 | 210 | asmlinkage void do_trap_fpe(struct pt_regs *regs) |
| 211 | 211 | { |
| 212 | −#ifdef CONFIG_CPU_HAS_FP | |
| 212 | +#ifdef CONFIG_CPU_HAS_FPU | |
| 213 | 213 | return fpu_fpe(regs); |
| 214 | 214 | #else |
| 215 | 215 | do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc, |
| @@ -219,7 +219,7 @@ asmlinkage void do_trap_fpe(struct pt_regs *regs) · 3 unmodified lines | ||
| 219 | 219 | |
| 220 | 220 | asmlinkage void do_trap_priv(struct pt_regs *regs) |
| 221 | 221 | { |
| 222 | −#ifdef CONFIG_CPU_HAS_FP | |
| 222 | +#ifdef CONFIG_CPU_HAS_FPU | |
| 223 | 223 | if (user_mode(regs) && fpu_libc_helper(regs)) |
| 224 | 224 | return; |
| 225 | 225 | #endif |
| @@ -98,7 +98,7 @@ do { \ · 97 unmodified lines | ||
| 98 | 98 | #define emit(...) __emit(__VA_ARGS__) |
| 99 | 99 | |
| 100 | 100 | /* Workaround for R10000 ll/sc errata */ |
| 101 | −#ifdef CONFIG_WAR_R10000 | |
| 101 | +#ifdef CONFIG_WAR_R10000_LLSC | |
| 102 | 102 | #define LLSC_beqz beqzl |
| 103 | 103 | #else |
| 104 | 104 | #define LLSC_beqz beqz |
| @@ -15,7 +15,12 @@ · 14 unmodified lines | ||
| 15 | 15 | # Mike Shaver, Helge Deller and Martin K. Petersen |
| 16 | 16 | # |
| 17 | 17 | |
| 18 | +ifdef CONFIG_PARISC_SELF_EXTRACT | |
| 19 | +boot := arch/parisc/boot | |
| 20 | +KBUILD_IMAGE := $(boot)/bzImage | |
| 21 | +else | |
| 18 | 22 | KBUILD_IMAGE := vmlinuz |
| 23 | +endif | |
| 19 | 24 | |
| 20 | 25 | NM = sh $(srctree)/arch/parisc/nm |
| 21 | 26 | CHECKFLAGS += -D__hppa__=1 |
| @@ -1,7 +1,9 @@ | ||
| 1 | 1 | CONFIG_LOCALVERSION="-64bit" |
| 2 | 2 | # CONFIG_LOCALVERSION_AUTO is not set |
| 3 | +CONFIG_KERNEL_LZ4=y | |
| 3 | 4 | CONFIG_SYSVIPC=y |
| 4 | 5 | CONFIG_POSIX_MQUEUE=y |
| 6 | +CONFIG_AUDIT=y | |
| 5 | 7 | CONFIG_BSD_PROCESS_ACCT=y |
| 6 | 8 | CONFIG_BSD_PROCESS_ACCT_V3=y |
| 7 | 9 | CONFIG_TASKSTATS=y |
| @@ -35,6 +37,7 @@ CONFIG_MODVERSIONS=y · 27 unmodified lines | ||
| 35 | 37 | CONFIG_BLK_DEV_INTEGRITY=y |
| 36 | 38 | CONFIG_BINFMT_MISC=m |
| 37 | 39 | # CONFIG_COMPACTION is not set |
| 40 | +CONFIG_MEMORY_FAILURE=y | |
| 38 | 41 | CONFIG_NET=y |
| 39 | 42 | CONFIG_PACKET=y |
| 40 | 43 | CONFIG_UNIX=y |
| @@ -65,12 +68,15 @@ CONFIG_SCSI_ISCSI_ATTRS=y · 24 unmodified lines | ||
| 65 | 68 | CONFIG_SCSI_SRP_ATTRS=y |
| 66 | 69 | CONFIG_ISCSI_BOOT_SYSFS=y |
| 67 | 70 | CONFIG_SCSI_MPT2SAS=y |
| 68 | −CONFIG_SCSI_LASI700=m | |
| 71 | +CONFIG_SCSI_LASI700=y | |
| 69 | 72 | CONFIG_SCSI_SYM53C8XX_2=y |
| 70 | 73 | CONFIG_SCSI_ZALON=y |
| 71 | 74 | CONFIG_SCSI_QLA_ISCSI=m |
| 72 | 75 | CONFIG_SCSI_DH=y |
| 73 | 76 | CONFIG_ATA=y |
| 77 | +CONFIG_SATA_SIL=y | |
| 78 | +CONFIG_SATA_SIS=y | |
| 79 | +CONFIG_SATA_VIA=y | |
| 74 | 80 | CONFIG_PATA_NS87415=y |
| 75 | 81 | CONFIG_PATA_SIL680=y |
| 76 | 82 | CONFIG_ATA_GENERIC=y |
| @@ -79,6 +85,7 @@ CONFIG_MD_LINEAR=m · 2 unmodified lines | ||
| 79 | 85 | CONFIG_BLK_DEV_DM=m |
| 80 | 86 | CONFIG_DM_RAID=m |
| 81 | 87 | CONFIG_DM_UEVENT=y |
| 88 | +CONFIG_DM_AUDIT=y | |
| 82 | 89 | CONFIG_FUSION=y |
| 83 | 90 | CONFIG_FUSION_SPI=y |
| 84 | 91 | CONFIG_FUSION_SAS=y |
| @@ -196,10 +203,15 @@ CONFIG_FB_MATROX_G=y · 111 unmodified lines | ||
| 196 | 203 | CONFIG_FB_MATROX_I2C=y |
| 197 | 204 | CONFIG_FB_MATROX_MAVEN=y |
| 198 | 205 | CONFIG_FB_RADEON=y |
| 206 | +CONFIG_LOGO=y | |
| 207 | +# CONFIG_LOGO_LINUX_CLUT224 is not set | |
| 199 | 208 | CONFIG_HIDRAW=y |
| 200 | 209 | CONFIG_HID_PID=y |
| 201 | 210 | CONFIG_USB_HIDDEV=y |
| 202 | 211 | CONFIG_USB=y |
| 212 | +CONFIG_USB_EHCI_HCD=y | |
| 213 | +CONFIG_USB_OHCI_HCD=y | |
| 214 | +CONFIG_USB_OHCI_HCD_PLATFORM=y | |
| 203 | 215 | CONFIG_UIO=y |
| 204 | 216 | CONFIG_UIO_PDRV_GENIRQ=m |
| 205 | 217 | CONFIG_UIO_AEC=m |
| @@ -39,6 +39,7 @@ verify "$3" · 38 unmodified lines | ||
| 39 | 39 | if [ -n "${INSTALLKERNEL}" ]; then |
| 40 | 40 | if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi |
| 41 | 41 | if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi |
| 42 | + if [ -x /usr/sbin/${INSTALLKERNEL} ]; then exec /usr/sbin/${INSTALLKERNEL} "$@"; fi | |
| 42 | 43 | fi |
| 43 | 44 | |
| 44 | 45 | # Default install |
| @@ -249,30 +249,16 @@ void __init time_init(void) · 248 unmodified lines | ||
| 249 | 249 | static int __init init_cr16_clocksource(void) |
| 250 | 250 | { |
| 251 | 251 | /* |
| 252 | − * The cr16 interval timers are not syncronized across CPUs on | |
| 253 | − * different sockets, so mark them unstable and lower rating on | |
| 254 | − * multi-socket SMP systems. | |
| 252 | + * The cr16 interval timers are not syncronized across CPUs, even if | |
| 253 | + * they share the same socket. | |
| 255 | 254 | */ |
| 256 | 255 | if (num_online_cpus() > 1 && !running_on_qemu) { |
| 257 | − int cpu; | |
| 258 | − unsigned long cpu0_loc; | |
| 259 | − cpu0_loc = per_cpu(cpu_data, 0).cpu_loc; | |
| 260 | − | |
| 261 | − for_each_online_cpu(cpu) { | |
| 262 | − if (cpu == 0) | |
| 263 | − continue; | |
| 264 | − if ((cpu0_loc != 0) && | |
| 265 | − (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc)) | |
| 266 | − continue; | |
| 267 | − | |
| 268 | − /* mark sched_clock unstable */ | |
| 269 | − clear_sched_clock_stable(); | |
| 270 | − | |
| 271 | − clocksource_cr16.name = "cr16_unstable"; | |
| 272 | − clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; | |
| 273 | − clocksource_cr16.rating = 0; | |
| 274 | − break; | |
| 275 | − } | |
| 256 | + /* mark sched_clock unstable */ | |
| 257 | + clear_sched_clock_stable(); | |
| 258 | + | |
| 259 | + clocksource_cr16.name = "cr16_unstable"; | |
| 260 | + clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE; | |
| 261 | + clocksource_cr16.rating = 0; | |
| 276 | 262 | } |
| 277 | 263 | |
| 278 | 264 | /* register at clocksource framework */ |
| @@ -12,14 +12,12 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/types.h> |
| 13 | 13 | #include <linux/kvm.h> |
| 14 | 14 | #include <linux/kvm_types.h> |
| 15 | +#include <asm/csr.h> | |
| 15 | 16 | #include <asm/kvm_vcpu_fp.h> |
| 16 | 17 | #include <asm/kvm_vcpu_timer.h> |
| 17 | 18 | |
| 18 | −#ifdef CONFIG_64BIT | |
| 19 | −#define KVM_MAX_VCPUS (1U << 16) | |
| 20 | −#else | |
| 21 | −#define KVM_MAX_VCPUS (1U << 9) | |
| 22 | −#endif | |
| 19 | +#define KVM_MAX_VCPUS \ | |
| 20 | + ((HGATP_VMID_MASK >> HGATP_VMID_SHIFT) + 1) | |
| 23 | 21 | |
| 24 | 22 | #define KVM_HALT_POLL_NS_DEFAULT 500000 |
| 25 | 23 | |
| @@ -453,6 +453,12 @@ void kvm_arch_flush_shadow_all(struct kvm *kvm) · 452 unmodified lines | ||
| 453 | 453 | void kvm_arch_flush_shadow_memslot(struct kvm *kvm, |
| 454 | 454 | struct kvm_memory_slot *slot) |
| 455 | 455 | { |
| 456 | + gpa_t gpa = slot->base_gfn << PAGE_SHIFT; | |
| 457 | + phys_addr_t size = slot->npages << PAGE_SHIFT; | |
| 458 | + | |
| 459 | + spin_lock(&kvm->mmu_lock); | |
| 460 | + stage2_unmap_range(kvm, gpa, size, false); | |
| 461 | + spin_unlock(&kvm->mmu_lock); | |
| 456 | 462 | } |
| 457 | 463 | |
| 458 | 464 | void kvm_arch_commit_memory_region(struct kvm *kvm, |
| @@ -403,7 +403,6 @@ CONFIG_DEVTMPFS=y · 402 unmodified lines | ||
| 403 | 403 | CONFIG_CONNECTOR=y |
| 404 | 404 | CONFIG_ZRAM=y |
| 405 | 405 | CONFIG_BLK_DEV_LOOP=m |
| 406 | −CONFIG_BLK_DEV_CRYPTOLOOP=m | |
| 407 | 406 | CONFIG_BLK_DEV_DRBD=m |
| 408 | 407 | CONFIG_BLK_DEV_NBD=m |
| 409 | 408 | CONFIG_BLK_DEV_RAM=y |
| @@ -476,6 +475,7 @@ CONFIG_MACVLAN=m · 66 unmodified lines | ||
| 476 | 475 | CONFIG_MACVTAP=m |
| 477 | 476 | CONFIG_VXLAN=m |
| 478 | 477 | CONFIG_BAREUDP=m |
| 478 | +CONFIG_AMT=m | |
| 479 | 479 | CONFIG_TUN=m |
| 480 | 480 | CONFIG_VETH=m |
| 481 | 481 | CONFIG_VIRTIO_NET=m |
| @@ -489,6 +489,7 @@ CONFIG_NLMON=m · 7 unmodified lines | ||
| 489 | 489 | # CONFIG_NET_VENDOR_AMD is not set |
| 490 | 490 | # CONFIG_NET_VENDOR_AQUANTIA is not set |
| 491 | 491 | # CONFIG_NET_VENDOR_ARC is not set |
| 492 | +# CONFIG_NET_VENDOR_ASIX is not set | |
| 492 | 493 | # CONFIG_NET_VENDOR_ATHEROS is not set |
| 493 | 494 | # CONFIG_NET_VENDOR_BROADCOM is not set |
| 494 | 495 | # CONFIG_NET_VENDOR_BROCADE is not set |
| @@ -571,6 +572,7 @@ CONFIG_WATCHDOG=y · 76 unmodified lines | ||
| 571 | 572 | CONFIG_WATCHDOG_NOWAYOUT=y |
| 572 | 573 | CONFIG_SOFT_WATCHDOG=m |
| 573 | 574 | CONFIG_DIAG288_WATCHDOG=m |
| 575 | +# CONFIG_DRM_DEBUG_MODESET_LOCK is not set | |
| 574 | 576 | CONFIG_FB=y |
| 575 | 577 | CONFIG_FRAMEBUFFER_CONSOLE=y |
| 576 | 578 | CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y |
| @@ -775,12 +777,14 @@ CONFIG_CRC4=m · 198 unmodified lines | ||
| 775 | 777 | CONFIG_CRC7=m |
| 776 | 778 | CONFIG_CRC8=m |
| 777 | 779 | CONFIG_RANDOM32_SELFTEST=y |
| 780 | +CONFIG_XZ_DEC_MICROLZMA=y | |
| 778 | 781 | CONFIG_DMA_CMA=y |
| 779 | 782 | CONFIG_CMA_SIZE_MBYTES=0 |
| 780 | 783 | CONFIG_PRINTK_TIME=y |
| 781 | 784 | CONFIG_DYNAMIC_DEBUG=y |
| 782 | 785 | CONFIG_DEBUG_INFO=y |
| 783 | 786 | CONFIG_DEBUG_INFO_DWARF4=y |
| 787 | +CONFIG_DEBUG_INFO_BTF=y | |
| 784 | 788 | CONFIG_GDB_SCRIPTS=y |
| 785 | 789 | CONFIG_HEADERS_INSTALL=y |
| 786 | 790 | CONFIG_DEBUG_SECTION_MISMATCH=y |
| @@ -807,6 +811,7 @@ CONFIG_DEBUG_MEMORY_INIT=y · 20 unmodified lines | ||
| 807 | 811 | CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m |
| 808 | 812 | CONFIG_DEBUG_PER_CPU_MAPS=y |
| 809 | 813 | CONFIG_KFENCE=y |
| 814 | +CONFIG_KFENCE_STATIC_KEYS=y | |
| 810 | 815 | CONFIG_DEBUG_SHIRQ=y |
| 811 | 816 | CONFIG_PANIC_ON_OOPS=y |
| 812 | 817 | CONFIG_DETECT_HUNG_TASK=y |
| @@ -842,6 +847,7 @@ CONFIG_FTRACE_STARTUP_TEST=y · 29 unmodified lines | ||
| 842 | 847 | CONFIG_SAMPLES=y |
| 843 | 848 | CONFIG_SAMPLE_TRACE_PRINTK=m |
| 844 | 849 | CONFIG_SAMPLE_FTRACE_DIRECT=m |
| 850 | +CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m | |
| 845 | 851 | CONFIG_DEBUG_ENTRY=y |
| 846 | 852 | CONFIG_CIO_INJECT=y |
| 847 | 853 | CONFIG_KUNIT=m |
| @@ -860,7 +866,7 @@ CONFIG_FAIL_FUNCTION=y · 12 unmodified lines | ||
| 860 | 866 | CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y |
| 861 | 867 | CONFIG_LKDTM=m |
| 862 | 868 | CONFIG_TEST_MIN_HEAP=y |
| 863 | −CONFIG_KPROBES_SANITY_TEST=y | |
| 869 | +CONFIG_KPROBES_SANITY_TEST=m | |
| 864 | 870 | CONFIG_RBTREE_TEST=y |
| 865 | 871 | CONFIG_INTERVAL_TREE_TEST=m |
| 866 | 872 | CONFIG_PERCPU_TEST=m |
| @@ -394,7 +394,6 @@ CONFIG_DEVTMPFS=y · 393 unmodified lines | ||
| 394 | 394 | CONFIG_CONNECTOR=y |
| 395 | 395 | CONFIG_ZRAM=y |
| 396 | 396 | CONFIG_BLK_DEV_LOOP=m |
| 397 | −CONFIG_BLK_DEV_CRYPTOLOOP=m | |
| 398 | 397 | CONFIG_BLK_DEV_DRBD=m |
| 399 | 398 | CONFIG_BLK_DEV_NBD=m |
| 400 | 399 | CONFIG_BLK_DEV_RAM=y |
| @@ -467,6 +466,7 @@ CONFIG_MACVLAN=m · 66 unmodified lines | ||
| 467 | 466 | CONFIG_MACVTAP=m |
| 468 | 467 | CONFIG_VXLAN=m |
| 469 | 468 | CONFIG_BAREUDP=m |
| 469 | +CONFIG_AMT=m | |
| 470 | 470 | CONFIG_TUN=m |
| 471 | 471 | CONFIG_VETH=m |
| 472 | 472 | CONFIG_VIRTIO_NET=m |
| @@ -480,6 +480,7 @@ CONFIG_NLMON=m · 7 unmodified lines | ||
| 480 | 480 | # CONFIG_NET_VENDOR_AMD is not set |
| 481 | 481 | # CONFIG_NET_VENDOR_AQUANTIA is not set |
| 482 | 482 | # CONFIG_NET_VENDOR_ARC is not set |
| 483 | +# CONFIG_NET_VENDOR_ASIX is not set | |
| 483 | 484 | # CONFIG_NET_VENDOR_ATHEROS is not set |
| 484 | 485 | # CONFIG_NET_VENDOR_BROADCOM is not set |
| 485 | 486 | # CONFIG_NET_VENDOR_BROCADE is not set |
| @@ -762,12 +763,14 @@ CONFIG_PRIME_NUMBERS=m · 276 unmodified lines | ||
| 762 | 763 | CONFIG_CRC4=m |
| 763 | 764 | CONFIG_CRC7=m |
| 764 | 765 | CONFIG_CRC8=m |
| 766 | +CONFIG_XZ_DEC_MICROLZMA=y | |
| 765 | 767 | CONFIG_DMA_CMA=y |
| 766 | 768 | CONFIG_CMA_SIZE_MBYTES=0 |
| 767 | 769 | CONFIG_PRINTK_TIME=y |
| 768 | 770 | CONFIG_DYNAMIC_DEBUG=y |
| 769 | 771 | CONFIG_DEBUG_INFO=y |
| 770 | 772 | CONFIG_DEBUG_INFO_DWARF4=y |
| 773 | +CONFIG_DEBUG_INFO_BTF=y | |
| 771 | 774 | CONFIG_GDB_SCRIPTS=y |
| 772 | 775 | CONFIG_DEBUG_SECTION_MISMATCH=y |
| 773 | 776 | CONFIG_MAGIC_SYSRQ=y |
| @@ -792,9 +795,11 @@ CONFIG_HIST_TRIGGERS=y · 18 unmodified lines | ||
| 792 | 795 | CONFIG_SAMPLES=y |
| 793 | 796 | CONFIG_SAMPLE_TRACE_PRINTK=m |
| 794 | 797 | CONFIG_SAMPLE_FTRACE_DIRECT=m |
| 798 | +CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m | |
| 795 | 799 | CONFIG_KUNIT=m |
| 796 | 800 | CONFIG_KUNIT_DEBUGFS=y |
| 797 | 801 | CONFIG_LKDTM=m |
| 802 | +CONFIG_KPROBES_SANITY_TEST=m | |
| 798 | 803 | CONFIG_PERCPU_TEST=m |
| 799 | 804 | CONFIG_ATOMIC64_SELFTEST=y |
| 800 | 805 | CONFIG_TEST_BPF=m |
| @@ -65,9 +65,11 @@ CONFIG_ZFCP=y · 64 unmodified lines | ||
| 65 | 65 | # CONFIG_NETWORK_FILESYSTEMS is not set |
| 66 | 66 | CONFIG_LSM="yama,loadpin,safesetid,integrity" |
| 67 | 67 | # CONFIG_ZLIB_DFLTCC is not set |
| 68 | +CONFIG_XZ_DEC_MICROLZMA=y | |
| 68 | 69 | CONFIG_PRINTK_TIME=y |
| 69 | 70 | # CONFIG_SYMBOLIC_ERRNAME is not set |
| 70 | 71 | CONFIG_DEBUG_INFO=y |
| 72 | +CONFIG_DEBUG_INFO_BTF=y | |
| 71 | 73 | CONFIG_DEBUG_FS=y |
| 72 | 74 | CONFIG_DEBUG_KERNEL=y |
| 73 | 75 | CONFIG_PANIC_ON_OOPS=y |
| @@ -14,12 +14,13 @@ · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | /* I/O Map */ |
| 16 | 16 | #define ZPCI_IOMAP_SHIFT 48 |
| 17 | −#define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000UL | |
| 17 | +#define ZPCI_IOMAP_ADDR_SHIFT 62 | |
| 18 | +#define ZPCI_IOMAP_ADDR_BASE (1UL << ZPCI_IOMAP_ADDR_SHIFT) | |
| 18 | 19 | #define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1) |
| 19 | 20 | #define ZPCI_IOMAP_MAX_ENTRIES \ |
| 20 | − ((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT)) | |
| 21 | + (1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT)) | |
| 21 | 22 | #define ZPCI_IOMAP_ADDR_IDX_MASK \ |
| 22 | − (~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE) | |
| 23 | + ((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK) | |
| 23 | 24 | |
| 24 | 25 | struct zpci_iomap_entry { |
| 25 | 26 | u32 fh; |
| @@ -173,10 +173,11 @@ static noinline int unwindme_func4(struct unwindme *u) · 172 unmodified lines | ||
| 173 | 173 | } |
| 174 | 174 | |
| 175 | 175 | /* |
| 176 | − * trigger specification exception | |
| 176 | + * Trigger operation exception; use insn notation to bypass | |
| 177 | + * llvm's integrated assembler sanity checks. | |
| 177 | 178 | */ |
| 178 | 179 | asm volatile( |
| 179 | − " mvcl %%r1,%%r1\n" | |
| 180 | + " .insn e,0x0000\n" /* illegal opcode */ | |
| 180 | 181 | "0: nopr %%r7\n" |
| 181 | 182 | EX_TABLE(0b, 0b) |
| 182 | 183 | :); |
| @@ -1932,6 +1932,7 @@ config EFI · 1931 unmodified lines | ||
| 1932 | 1932 | depends on ACPI |
| 1933 | 1933 | select UCS2_STRING |
| 1934 | 1934 | select EFI_RUNTIME_WRAPPERS |
| 1935 | + select ARCH_USE_MEMREMAP_PROT | |
| 1935 | 1936 | help |
| 1936 | 1937 | This enables the kernel to use EFI runtime services that are |
| 1937 | 1938 | available (such as the EFI variable services). |
| @@ -574,6 +574,10 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) · 573 unmodified lines | ||
| 574 | 574 | ud2 |
| 575 | 575 | 1: |
| 576 | 576 | #endif |
| 577 | +#ifdef CONFIG_XEN_PV | |
| 578 | + ALTERNATIVE "", "jmp xenpv_restore_regs_and_return_to_usermode", X86_FEATURE_XENPV | |
| 579 | +#endif | |
| 580 | + | |
| 577 | 581 | POP_REGS pop_rdi=0 |
| 578 | 582 | |
| 579 | 583 | /* |
| @@ -890,6 +894,7 @@ SYM_CODE_START_LOCAL(paranoid_entry) · 310 unmodified lines | ||
| 890 | 894 | .Lparanoid_entry_checkgs: |
| 891 | 895 | /* EBX = 1 -> kernel GSBASE active, no restore required */ |
| 892 | 896 | movl $1, %ebx |
| 897 | + | |
| 893 | 898 | /* |
| 894 | 899 | * The kernel-enforced convention is a negative GSBASE indicates |
| 895 | 900 | * a kernel value. No SWAPGS needed on entry and exit. |
| @@ -897,21 +902,14 @@ SYM_CODE_START_LOCAL(paranoid_entry) · 1 unmodified line | ||
| 897 | 902 | movl $MSR_GS_BASE, %ecx |
| 898 | 903 | rdmsr |
| 899 | 904 | testl %edx, %edx |
| 900 | − jns .Lparanoid_entry_swapgs | |
| 901 | − ret | |
| 905 | + js .Lparanoid_kernel_gsbase | |
| 902 | 906 | |
| 903 | −.Lparanoid_entry_swapgs: | |
| 907 | + /* EBX = 0 -> SWAPGS required on exit */ | |
| 908 | + xorl %ebx, %ebx | |
| 904 | 909 | swapgs |
| 910 | +.Lparanoid_kernel_gsbase: | |
| 905 | 911 | |
| 906 | − /* | |
| 907 | − * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an | |
| 908 | − * unconditional CR3 write, even in the PTI case. So do an lfence | |
| 909 | − * to prevent GS speculation, regardless of whether PTI is enabled. | |
| 910 | − */ | |
| 911 | 912 | FENCE_SWAPGS_KERNEL_ENTRY |
| 912 | − | |
| 913 | − /* EBX = 0 -> SWAPGS required on exit */ | |
| 914 | − xorl %ebx, %ebx | |
| 915 | 913 | ret |
| 916 | 914 | SYM_CODE_END(paranoid_entry) |
| 917 | 915 | |
| @@ -993,11 +991,6 @@ SYM_CODE_START_LOCAL(error_entry) · 75 unmodified lines | ||
| 993 | 991 | pushq %r12 |
| 994 | 992 | ret |
| 995 | 993 | |
| 996 | −.Lerror_entry_done_lfence: | |
| 997 | − FENCE_SWAPGS_KERNEL_ENTRY | |
| 998 | −.Lerror_entry_done: | |
| 999 | − ret | |
| 1000 | − | |
| 1001 | 994 | /* |
| 1002 | 995 | * There are two places in the kernel that can potentially fault with |
| 1003 | 996 | * usergs. Handle them here. B stepping K8s sometimes report a |
| @@ -1020,8 +1013,14 @@ SYM_CODE_START_LOCAL(error_entry) · 16 unmodified lines | ||
| 1020 | 1013 | * .Lgs_change's error handler with kernel gsbase. |
| 1021 | 1014 | */ |
| 1022 | 1015 | SWAPGS |
| 1023 | − FENCE_SWAPGS_USER_ENTRY | |
| 1024 | − jmp .Lerror_entry_done | |
| 1016 | + | |
| 1017 | + /* | |
| 1018 | + * Issue an LFENCE to prevent GS speculation, regardless of whether it is a | |
| 1019 | + * kernel or user gsbase. | |
| 1020 | + */ | |
| 1021 | +.Lerror_entry_done_lfence: | |
| 1022 | + FENCE_SWAPGS_KERNEL_ENTRY | |
| 1023 | + ret | |
| 1025 | 1024 | |
| 1026 | 1025 | .Lbstep_iret: |
| 1027 | 1026 | /* Fix truncated RIP */ |
| @@ -108,7 +108,7 @@ · 107 unmodified lines | ||
| 108 | 108 | #define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */ |
| 109 | 109 | #define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */ |
| 110 | 110 | |
| 111 | −#define INTEL_FAM6_RAPTOR_LAKE 0xB7 | |
| 111 | +#define INTEL_FAM6_RAPTORLAKE 0xB7 | |
| 112 | 112 | |
| 113 | 113 | /* "Small Core" Processors (Atom) */ |
| 114 | 114 | |
| @@ -97,7 +97,7 @@ · 96 unmodified lines | ||
| 97 | 97 | KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) |
| 98 | 98 | #define KVM_REQ_TLB_FLUSH_CURRENT KVM_ARCH_REQ(26) |
| 99 | 99 | #define KVM_REQ_TLB_FLUSH_GUEST \ |
| 100 | − KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_NO_WAKEUP) | |
| 100 | + KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) | |
| 101 | 101 | #define KVM_REQ_APF_READY KVM_ARCH_REQ(28) |
| 102 | 102 | #define KVM_REQ_MSR_FILTER_CHANGED KVM_ARCH_REQ(29) |
| 103 | 103 | #define KVM_REQ_UPDATE_CPU_DIRTY_LOGGING \ |
| @@ -1036,6 +1036,7 @@ struct kvm_x86_msr_filter { · 932 unmodified lines | ||
| 1036 | 1036 | #define APICV_INHIBIT_REASON_PIT_REINJ 4 |
| 1037 | 1037 | #define APICV_INHIBIT_REASON_X2APIC 5 |
| 1038 | 1038 | #define APICV_INHIBIT_REASON_BLOCKIRQ 6 |
| 1039 | +#define APICV_INHIBIT_REASON_ABSENT 7 | |
| 1039 | 1040 | |
| 1040 | 1041 | struct kvm_arch { |
| 1041 | 1042 | unsigned long n_used_mmu_pages; |
| @@ -73,4 +73,15 @@ · 72 unmodified lines | ||
| 73 | 73 | |
| 74 | 74 | #define GHCB_RESP_CODE(v) ((v) & GHCB_MSR_INFO_MASK) |
| 75 | 75 | |
| 76 | +/* | |
| 77 | + * Error codes related to GHCB input that can be communicated back to the guest | |
| 78 | + * by setting the lower 32-bits of the GHCB SW_EXITINFO1 field to 2. | |
| 79 | + */ | |
| 80 | +#define GHCB_ERR_NOT_REGISTERED 1 | |
| 81 | +#define GHCB_ERR_INVALID_USAGE 2 | |
| 82 | +#define GHCB_ERR_INVALID_SCRATCH_AREA 3 | |
| 83 | +#define GHCB_ERR_MISSING_INPUT 4 | |
| 84 | +#define GHCB_ERR_INVALID_INPUT 5 | |
| 85 | +#define GHCB_ERR_INVALID_EVENT 6 | |
| 86 | + | |
| 76 | 87 | #endif |
| @@ -118,7 +118,7 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame, · 117 unmodified lines | ||
| 118 | 118 | struct fpstate *fpstate) |
| 119 | 119 | { |
| 120 | 120 | struct xregs_state __user *x = buf; |
| 121 | − struct _fpx_sw_bytes sw_bytes; | |
| 121 | + struct _fpx_sw_bytes sw_bytes = {}; | |
| 122 | 122 | u32 xfeatures; |
| 123 | 123 | int err; |
| 124 | 124 | |
| @@ -294,11 +294,6 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt, · 293 unmodified lines | ||
| 294 | 294 | char *dst, char *buf, size_t size) |
| 295 | 295 | { |
| 296 | 296 | unsigned long error_code = X86_PF_PROT | X86_PF_WRITE; |
| 297 | − char __user *target = (char __user *)dst; | |
| 298 | − u64 d8; | |
| 299 | − u32 d4; | |
| 300 | − u16 d2; | |
| 301 | − u8 d1; | |
| 302 | 297 | |
| 303 | 298 | /* |
| 304 | 299 | * This function uses __put_user() independent of whether kernel or user |
| @@ -320,26 +315,42 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt, · 15 unmodified lines | ||
| 320 | 315 | * instructions here would cause infinite nesting. |
| 321 | 316 | */ |
| 322 | 317 | switch (size) { |
| 323 | − case 1: | |
| 318 | + case 1: { | |
| 319 | + u8 d1; | |
| 320 | + u8 __user *target = (u8 __user *)dst; | |
| 321 | + | |
| 324 | 322 | memcpy(&d1, buf, 1); |
| 325 | 323 | if (__put_user(d1, target)) |
| 326 | 324 | goto fault; |
| 327 | 325 | break; |
| 328 | − case 2: | |
| 326 | + } | |
| 327 | + case 2: { | |
| 328 | + u16 d2; | |
| 329 | + u16 __user *target = (u16 __user *)dst; | |
| 330 | + | |
| 329 | 331 | memcpy(&d2, buf, 2); |
| 330 | 332 | if (__put_user(d2, target)) |
| 331 | 333 | goto fault; |
| 332 | 334 | break; |
| 333 | − case 4: | |
| 335 | + } | |
| 336 | + case 4: { | |
| 337 | + u32 d4; | |
| 338 | + u32 __user *target = (u32 __user *)dst; | |
| 339 | + | |
| 334 | 340 | memcpy(&d4, buf, 4); |
| 335 | 341 | if (__put_user(d4, target)) |
| 336 | 342 | goto fault; |
| 337 | 343 | break; |
| 338 | − case 8: | |
| 344 | + } | |
| 345 | + case 8: { | |
| 346 | + u64 d8; | |
| 347 | + u64 __user *target = (u64 __user *)dst; | |
| 348 | + | |
| 339 | 349 | memcpy(&d8, buf, 8); |
| 340 | 350 | if (__put_user(d8, target)) |
| 341 | 351 | goto fault; |
| 342 | 352 | break; |
| 353 | + } | |
| 343 | 354 | default: |
| 344 | 355 | WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); |
| 345 | 356 | return ES_UNSUPPORTED; |
| @@ -362,11 +373,6 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, · 16 unmodified lines | ||
| 362 | 373 | char *src, char *buf, size_t size) |
| 363 | 374 | { |
| 364 | 375 | unsigned long error_code = X86_PF_PROT; |
| 365 | − char __user *s = (char __user *)src; | |
| 366 | − u64 d8; | |
| 367 | − u32 d4; | |
| 368 | − u16 d2; | |
| 369 | − u8 d1; | |
| 370 | 376 | |
| 371 | 377 | /* |
| 372 | 378 | * This function uses __get_user() independent of whether kernel or user |
| @@ -388,26 +394,41 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, · 15 unmodified lines | ||
| 388 | 394 | * instructions here would cause infinite nesting. |
| 389 | 395 | */ |
| 390 | 396 | switch (size) { |
| 391 | − case 1: | |
| 397 | + case 1: { | |
| 398 | + u8 d1; | |
| 399 | + u8 __user *s = (u8 __user *)src; | |
| 400 | + | |
| 392 | 401 | if (__get_user(d1, s)) |
| 393 | 402 | goto fault; |
| 394 | 403 | memcpy(buf, &d1, 1); |
| 395 | 404 | break; |
| 396 | − case 2: | |
| 405 | + } | |
| 406 | + case 2: { | |
| 407 | + u16 d2; | |
| 408 | + u16 __user *s = (u16 __user *)src; | |
| 409 | + | |
| 397 | 410 | if (__get_user(d2, s)) |
| 398 | 411 | goto fault; |
| 399 | 412 | memcpy(buf, &d2, 2); |
| 400 | 413 | break; |
| 401 | − case 4: | |
| 414 | + } | |
| 415 | + case 4: { | |
| 416 | + u32 d4; | |
| 417 | + u32 __user *s = (u32 __user *)src; | |
| 418 | + | |
| 402 | 419 | if (__get_user(d4, s)) |
| 403 | 420 | goto fault; |
| 404 | 421 | memcpy(buf, &d4, 4); |
| 405 | 422 | break; |
| 406 | − case 8: | |
| 423 | + } | |
| 424 | + case 8: { | |
| 425 | + u64 d8; | |
| 426 | + u64 __user *s = (u64 __user *)src; | |
| 407 | 427 | if (__get_user(d8, s)) |
| 408 | 428 | goto fault; |
| 409 | 429 | memcpy(buf, &d8, 8); |
| 410 | 430 | break; |
| 431 | + } | |
| 411 | 432 | default: |
| 412 | 433 | WARN_ONCE(1, "%s: Invalid size: %zu\n", __func__, size); |
| 413 | 434 | return ES_UNSUPPORTED; |
| @@ -579,6 +579,17 @@ static struct sched_domain_topology_level x86_numa_in_package_topology[] = { · 578 unmodified lines | ||
| 579 | 579 | { NULL, }, |
| 580 | 580 | }; |
| 581 | 581 | |
| 582 | +static struct sched_domain_topology_level x86_hybrid_topology[] = { | |
| 583 | +#ifdef CONFIG_SCHED_SMT | |
| 584 | + { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) }, | |
| 585 | +#endif | |
| 586 | +#ifdef CONFIG_SCHED_MC | |
| 587 | + { cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) }, | |
| 588 | +#endif | |
| 589 | + { cpu_cpu_mask, SD_INIT_NAME(DIE) }, | |
| 590 | + { NULL, }, | |
| 591 | +}; | |
| 592 | + | |
| 582 | 593 | static struct sched_domain_topology_level x86_topology[] = { |
| 583 | 594 | #ifdef CONFIG_SCHED_SMT |
| 584 | 595 | { cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) }, |
| @@ -1469,8 +1480,11 @@ void __init native_smp_cpus_done(unsigned int max_cpus) · 884 unmodified lines | ||
| 1469 | 1480 | |
| 1470 | 1481 | calculate_max_logical_packages(); |
| 1471 | 1482 | |
| 1483 | + /* XXX for now assume numa-in-package and hybrid don't overlap */ | |
| 1472 | 1484 | if (x86_has_numa_in_package) |
| 1473 | 1485 | set_sched_topology(x86_numa_in_package_topology); |
| 1486 | + if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) | |
| 1487 | + set_sched_topology(x86_hybrid_topology); | |
| 1474 | 1488 | |
| 1475 | 1489 | nmi_selftest(); |
| 1476 | 1490 | impress_friends(); |
| @@ -1180,6 +1180,12 @@ void mark_tsc_unstable(char *reason) · 1179 unmodified lines | ||
| 1180 | 1180 | |
| 1181 | 1181 | EXPORT_SYMBOL_GPL(mark_tsc_unstable); |
| 1182 | 1182 | |
| 1183 | +static void __init tsc_disable_clocksource_watchdog(void) | |
| 1184 | +{ | |
| 1185 | + clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | |
| 1186 | + clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | |
| 1187 | +} | |
| 1188 | + | |
| 1183 | 1189 | static void __init check_system_tsc_reliable(void) |
| 1184 | 1190 | { |
| 1185 | 1191 | #if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC) |
| @@ -1196,6 +1202,23 @@ static void __init check_system_tsc_reliable(void) · 10 unmodified lines | ||
| 1196 | 1202 | #endif |
| 1197 | 1203 | if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) |
| 1198 | 1204 | tsc_clocksource_reliable = 1; |
| 1205 | + | |
| 1206 | + /* | |
| 1207 | + * Disable the clocksource watchdog when the system has: | |
| 1208 | + * - TSC running at constant frequency | |
| 1209 | + * - TSC which does not stop in C-States | |
| 1210 | + * - the TSC_ADJUST register which allows to detect even minimal | |
| 1211 | + * modifications | |
| 1212 | + * - not more than two sockets. As the number of sockets cannot be | |
| 1213 | + * evaluated at the early boot stage where this has to be | |
| 1214 | + * invoked, check the number of online memory nodes as a | |
| 1215 | + * fallback solution which is an reasonable estimate. | |
| 1216 | + */ | |
| 1217 | + if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && | |
| 1218 | + boot_cpu_has(X86_FEATURE_NONSTOP_TSC) && | |
| 1219 | + boot_cpu_has(X86_FEATURE_TSC_ADJUST) && | |
| 1220 | + nr_online_nodes <= 2) | |
| 1221 | + tsc_disable_clocksource_watchdog(); | |
| 1199 | 1222 | } |
| 1200 | 1223 | |
| 1201 | 1224 | /* |
| @@ -1387,9 +1410,6 @@ static int __init init_tsc_clocksource(void) · 185 unmodified lines | ||
| 1387 | 1410 | if (tsc_unstable) |
| 1388 | 1411 | goto unreg; |
| 1389 | 1412 | |
| 1390 | − if (tsc_clocksource_reliable || no_tsc_watchdog) | |
| 1391 | − clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | |
| 1392 | − | |
| 1393 | 1413 | if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3)) |
| 1394 | 1414 | clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP; |
| 1395 | 1415 | |
| @@ -1527,7 +1547,7 @@ void __init tsc_init(void) · 131 unmodified lines | ||
| 1527 | 1547 | } |
| 1528 | 1548 | |
| 1529 | 1549 | if (tsc_clocksource_reliable || no_tsc_watchdog) |
| 1530 | − clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | |
| 1550 | + tsc_disable_clocksource_watchdog(); | |
| 1531 | 1551 | |
| 1532 | 1552 | clocksource_register_khz(&clocksource_tsc_early, tsc_khz); |
| 1533 | 1553 | detect_art(); |
| @@ -30,6 +30,7 @@ struct tsc_adjust { · 29 unmodified lines | ||
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | 32 | static DEFINE_PER_CPU(struct tsc_adjust, tsc_adjust); |
| 33 | +static struct timer_list tsc_sync_check_timer; | |
| 33 | 34 | |
| 34 | 35 | /* |
| 35 | 36 | * TSC's on different sockets may be reset asynchronously. |
| @@ -77,6 +78,46 @@ void tsc_verify_tsc_adjust(bool resume) · 41 unmodified lines | ||
| 77 | 78 | } |
| 78 | 79 | } |
| 79 | 80 | |
| 81 | +/* | |
| 82 | + * Normally the tsc_sync will be checked every time system enters idle | |
| 83 | + * state, but there is still caveat that a system won't enter idle, | |
| 84 | + * either because it's too busy or configured purposely to not enter | |
| 85 | + * idle. | |
| 86 | + * | |
| 87 | + * So setup a periodic timer (every 10 minutes) to make sure the check | |
| 88 | + * is always on. | |
| 89 | + */ | |
| 90 | + | |
| 91 | +#define SYNC_CHECK_INTERVAL (HZ * 600) | |
| 92 | + | |
| 93 | +static void tsc_sync_check_timer_fn(struct timer_list *unused) | |
| 94 | +{ | |
| 95 | + int next_cpu; | |
| 96 | + | |
| 97 | + tsc_verify_tsc_adjust(false); | |
| 98 | + | |
| 99 | + /* Run the check for all onlined CPUs in turn */ | |
| 100 | + next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask); | |
| 101 | + if (next_cpu >= nr_cpu_ids) | |
| 102 | + next_cpu = cpumask_first(cpu_online_mask); | |
| 103 | + | |
| 104 | + tsc_sync_check_timer.expires += SYNC_CHECK_INTERVAL; | |
| 105 | + add_timer_on(&tsc_sync_check_timer, next_cpu); | |
| 106 | +} | |
| 107 | + | |
| 108 | +static int __init start_sync_check_timer(void) | |
| 109 | +{ | |
| 110 | + if (!cpu_feature_enabled(X86_FEATURE_TSC_ADJUST) || tsc_clocksource_reliable) | |
| 111 | + return 0; | |
| 112 | + | |
| 113 | + timer_setup(&tsc_sync_check_timer, tsc_sync_check_timer_fn, 0); | |
| 114 | + tsc_sync_check_timer.expires = jiffies + SYNC_CHECK_INTERVAL; | |
| 115 | + add_timer(&tsc_sync_check_timer); | |
| 116 | + | |
| 117 | + return 0; | |
| 118 | +} | |
| 119 | +late_initcall(start_sync_check_timer); | |
| 120 | + | |
| 80 | 121 | static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval, |
| 81 | 122 | unsigned int cpu, bool bootcpu) |
| 82 | 123 | { |
| @@ -1922,11 +1922,13 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool · 1921 unmodified lines | ||
| 1922 | 1922 | |
| 1923 | 1923 | all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL; |
| 1924 | 1924 | |
| 1925 | + if (all_cpus) | |
| 1926 | + goto check_and_send_ipi; | |
| 1927 | + | |
| 1925 | 1928 | if (!sparse_banks_len) |
| 1926 | 1929 | goto ret_success; |
| 1927 | 1930 | |
| 1928 | − if (!all_cpus && | |
| 1929 | − kvm_read_guest(kvm, | |
| 1931 | + if (kvm_read_guest(kvm, | |
| 1930 | 1932 | hc->ingpa + offsetof(struct hv_send_ipi_ex, |
| 1931 | 1933 | vp_set.bank_contents), |
| 1932 | 1934 | sparse_banks, |
| @@ -1934,6 +1936,7 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc, bool · 1 unmodified line | ||
| 1934 | 1936 | return HV_STATUS_INVALID_HYPERCALL_INPUT; |
| 1935 | 1937 | } |
| 1936 | 1938 | |
| 1939 | +check_and_send_ipi: | |
| 1937 | 1940 | if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) |
| 1938 | 1941 | return HV_STATUS_INVALID_HYPERCALL_INPUT; |
| 1939 | 1942 | |
| @@ -81,7 +81,6 @@ struct kvm_ioapic { · 80 unmodified lines | ||
| 81 | 81 | unsigned long irq_states[IOAPIC_NUM_PINS]; |
| 82 | 82 | struct kvm_io_device dev; |
| 83 | 83 | struct kvm *kvm; |
| 84 | − void (*ack_notifier)(void *opaque, int irq); | |
| 85 | 84 | spinlock_t lock; |
| 86 | 85 | struct rtc_status rtc_status; |
| 87 | 86 | struct delayed_work eoi_inject; |
| @@ -56,7 +56,6 @@ struct kvm_pic { · 55 unmodified lines | ||
| 56 | 56 | struct kvm_io_device dev_master; |
| 57 | 57 | struct kvm_io_device dev_slave; |
| 58 | 58 | struct kvm_io_device dev_elcr; |
| 59 | − void (*ack_notifier)(void *opaque, int irq); | |
| 60 | 59 | unsigned long irq_states[PIC_NUM_PINS]; |
| 61 | 60 | }; |
| 62 | 61 | |
| @@ -707,7 +707,7 @@ static void pv_eoi_clr_pending(struct kvm_vcpu *vcpu) · 706 unmodified lines | ||
| 707 | 707 | static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr) |
| 708 | 708 | { |
| 709 | 709 | int highest_irr; |
| 710 | − if (apic->vcpu->arch.apicv_active) | |
| 710 | + if (kvm_x86_ops.sync_pir_to_irr) | |
| 711 | 711 | highest_irr = static_call(kvm_x86_sync_pir_to_irr)(apic->vcpu); |
| 712 | 712 | else |
| 713 | 713 | highest_irr = apic_find_highest_irr(apic); |
| @@ -1582,7 +1582,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) · 1581 unmodified lines | ||
| 1582 | 1582 | flush = kvm_handle_gfn_range(kvm, range, kvm_unmap_rmapp); |
| 1583 | 1583 | |
| 1584 | 1584 | if (is_tdp_mmu_enabled(kvm)) |
| 1585 | − flush |= kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); | |
| 1585 | + flush = kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush); | |
| 1586 | 1586 | |
| 1587 | 1587 | return flush; |
| 1588 | 1588 | } |
| @@ -1936,7 +1936,11 @@ static void mmu_audit_disable(void) { } · 347 unmodified lines | ||
| 1936 | 1936 | |
| 1937 | 1937 | static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp) |
| 1938 | 1938 | { |
| 1939 | − return sp->role.invalid || | |
| 1939 | + if (sp->role.invalid) | |
| 1940 | + return true; | |
| 1941 | + | |
| 1942 | + /* TDP MMU pages due not use the MMU generation. */ | |
| 1943 | + return !sp->tdp_mmu_page && | |
| 1940 | 1944 | unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen); |
| 1941 | 1945 | } |
| 1942 | 1946 | |
| @@ -2173,10 +2177,10 @@ static void shadow_walk_init_using_root(struct kvm_shadow_walk_iterator *iterato · 230 unmodified lines | ||
| 2173 | 2177 | iterator->shadow_addr = root; |
| 2174 | 2178 | iterator->level = vcpu->arch.mmu->shadow_root_level; |
| 2175 | 2179 | |
| 2176 | − if (iterator->level == PT64_ROOT_4LEVEL && | |
| 2180 | + if (iterator->level >= PT64_ROOT_4LEVEL && | |
| 2177 | 2181 | vcpu->arch.mmu->root_level < PT64_ROOT_4LEVEL && |
| 2178 | 2182 | !vcpu->arch.mmu->direct_map) |
| 2179 | − --iterator->level; | |
| 2183 | + iterator->level = PT32E_ROOT_LEVEL; | |
| 2180 | 2184 | |
| 2181 | 2185 | if (iterator->level == PT32E_ROOT_LEVEL) { |
| 2182 | 2186 | /* |
| @@ -3976,6 +3980,20 @@ out_retry: · 1793 unmodified lines | ||
| 3976 | 3980 | return true; |
| 3977 | 3981 | } |
| 3978 | 3982 | |
| 3983 | +/* | |
| 3984 | + * Returns true if the page fault is stale and needs to be retried, i.e. if the | |
| 3985 | + * root was invalidated by a memslot update or a relevant mmu_notifier fired. | |
| 3986 | + */ | |
| 3987 | +static bool is_page_fault_stale(struct kvm_vcpu *vcpu, | |
| 3988 | + struct kvm_page_fault *fault, int mmu_seq) | |
| 3989 | +{ | |
| 3990 | + if (is_obsolete_sp(vcpu->kvm, to_shadow_page(vcpu->arch.mmu->root_hpa))) | |
| 3991 | + return true; | |
| 3992 | + | |
| 3993 | + return fault->slot && | |
| 3994 | + mmu_notifier_retry_hva(vcpu->kvm, mmu_seq, fault->hva); | |
| 3995 | +} | |
| 3996 | + | |
| 3979 | 3997 | static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault) |
| 3980 | 3998 | { |
| 3981 | 3999 | bool is_tdp_mmu_fault = is_tdp_mmu(vcpu->arch.mmu); |
| @@ -4013,8 +4031,9 @@ static int direct_page_fault(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault · 31 unmodified lines | ||
| 4013 | 4031 | else |
| 4014 | 4032 | write_lock(&vcpu->kvm->mmu_lock); |
| 4015 | 4033 | |
| 4016 | − if (fault->slot && mmu_notifier_retry_hva(vcpu->kvm, mmu_seq, fault->hva)) | |
| 4034 | + if (is_page_fault_stale(vcpu, fault, mmu_seq)) | |
| 4017 | 4035 | goto out_unlock; |
| 4036 | + | |
| 4018 | 4037 | r = make_mmu_pages_available(vcpu); |
| 4019 | 4038 | if (r) |
| 4020 | 4039 | goto out_unlock; |
| @@ -4855,7 +4874,7 @@ void kvm_init_shadow_npt_mmu(struct kvm_vcpu *vcpu, unsigned long cr0, · 834 unmodified lines | ||
| 4855 | 4874 | struct kvm_mmu *context = &vcpu->arch.guest_mmu; |
| 4856 | 4875 | struct kvm_mmu_role_regs regs = { |
| 4857 | 4876 | .cr0 = cr0, |
| 4858 | − .cr4 = cr4, | |
| 4877 | + .cr4 = cr4 & ~X86_CR4_PKE, | |
| 4859 | 4878 | .efer = efer, |
| 4860 | 4879 | }; |
| 4861 | 4880 | union kvm_mmu_role new_role; |
| @@ -4919,7 +4938,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly, · 57 unmodified lines | ||
| 4919 | 4938 | context->direct_map = false; |
| 4920 | 4939 | |
| 4921 | 4940 | update_permission_bitmask(context, true); |
| 4922 | − update_pkru_bitmask(context); | |
| 4941 | + context->pkru_mask = 0; | |
| 4923 | 4942 | reset_rsvds_bits_mask_ept(vcpu, context, execonly); |
| 4924 | 4943 | reset_ept_shadow_zero_bits_mask(vcpu, context, execonly); |
| 4925 | 4944 | } |
| @@ -5025,6 +5044,14 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu) · 99 unmodified lines | ||
| 5025 | 5044 | /* |
| 5026 | 5045 | * Invalidate all MMU roles to force them to reinitialize as CPUID |
| 5027 | 5046 | * information is factored into reserved bit calculations. |
| 5047 | + * | |
| 5048 | + * Correctly handling multiple vCPU models with respect to paging and | |
| 5049 | + * physical address properties) in a single VM would require tracking | |
| 5050 | + * all relevant CPUID information in kvm_mmu_page_role. That is very | |
| 5051 | + * undesirable as it would increase the memory requirements for | |
| 5052 | + * gfn_track (see struct kvm_mmu_page_role comments). For now that | |
| 5053 | + * problem is swept under the rug; KVM's CPUID API is horrific and | |
| 5054 | + * it's all but impossible to solve it without introducing a new API. | |
| 5028 | 5055 | */ |
| 5029 | 5056 | vcpu->arch.root_mmu.mmu_role.ext.valid = 0; |
| 5030 | 5057 | vcpu->arch.guest_mmu.mmu_role.ext.valid = 0; |
| @@ -5032,24 +5059,10 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu) · 1 unmodified line | ||
| 5032 | 5059 | kvm_mmu_reset_context(vcpu); |
| 5033 | 5060 | |
| 5034 | 5061 | /* |
| 5035 | − * KVM does not correctly handle changing guest CPUID after KVM_RUN, as | |
| 5036 | − * MAXPHYADDR, GBPAGES support, AMD reserved bit behavior, etc.. aren't | |
| 5037 | − * tracked in kvm_mmu_page_role. As a result, KVM may miss guest page | |
| 5038 | − * faults due to reusing SPs/SPTEs. Alert userspace, but otherwise | |
| 5039 | − * sweep the problem under the rug. | |
| 5040 | − * | |
| 5041 | − * KVM's horrific CPUID ABI makes the problem all but impossible to | |
| 5042 | − * solve, as correctly handling multiple vCPU models (with respect to | |
| 5043 | − * paging and physical address properties) in a single VM would require | |
| 5044 | − * tracking all relevant CPUID information in kvm_mmu_page_role. That | |
| 5045 | − * is very undesirable as it would double the memory requirements for | |
| 5046 | − * gfn_track (see struct kvm_mmu_page_role comments), and in practice | |
| 5047 | − * no sane VMM mucks with the core vCPU model on the fly. | |
| 5062 | + * Changing guest CPUID after KVM_RUN is forbidden, see the comment in | |
| 5063 | + * kvm_arch_vcpu_ioctl(). | |
| 5048 | 5064 | */ |
| 5049 | − if (vcpu->arch.last_vmentry_cpu != -1) { | |
| 5050 | − pr_warn_ratelimited("KVM: KVM_SET_CPUID{,2} after KVM_RUN may cause guest instability\n"); | |
| 5051 | − pr_warn_ratelimited("KVM: KVM_SET_CPUID{,2} will fail after KVM_RUN starting with Linux 5.16\n"); | |
| 5052 | − } | |
| 5065 | + KVM_BUG_ON(vcpu->arch.last_vmentry_cpu != -1, vcpu->kvm); | |
| 5053 | 5066 | } |
| 5054 | 5067 | |
| 5055 | 5068 | void kvm_mmu_reset_context(struct kvm_vcpu *vcpu) |
| @@ -5369,7 +5382,7 @@ void kvm_mmu_invalidate_gva(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, · 313 unmodified lines | ||
| 5369 | 5382 | |
| 5370 | 5383 | void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva) |
| 5371 | 5384 | { |
| 5372 | − kvm_mmu_invalidate_gva(vcpu, vcpu->arch.mmu, gva, INVALID_PAGE); | |
| 5385 | + kvm_mmu_invalidate_gva(vcpu, vcpu->arch.walk_mmu, gva, INVALID_PAGE); | |
| 5373 | 5386 | ++vcpu->stat.invlpg; |
| 5374 | 5387 | } |
| 5375 | 5388 | EXPORT_SYMBOL_GPL(kvm_mmu_invlpg); |
| @@ -5854,8 +5867,6 @@ restart: · 478 unmodified lines | ||
| 5854 | 5867 | void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm, |
| 5855 | 5868 | const struct kvm_memory_slot *slot) |
| 5856 | 5869 | { |
| 5857 | − bool flush = false; | |
| 5858 | − | |
| 5859 | 5870 | if (kvm_memslots_have_rmaps(kvm)) { |
| 5860 | 5871 | write_lock(&kvm->mmu_lock); |
| 5861 | 5872 | /* |
| @@ -5863,17 +5874,14 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm, · 1 unmodified line | ||
| 5863 | 5874 | * logging at a 4k granularity and never creates collapsible |
| 5864 | 5875 | * 2m SPTEs during dirty logging. |
| 5865 | 5876 | */ |
| 5866 | − flush = slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true); | |
| 5867 | − if (flush) | |
| 5877 | + if (slot_handle_level_4k(kvm, slot, kvm_mmu_zap_collapsible_spte, true)) | |
| 5868 | 5878 | kvm_arch_flush_remote_tlbs_memslot(kvm, slot); |
| 5869 | 5879 | write_unlock(&kvm->mmu_lock); |
| 5870 | 5880 | } |
| 5871 | 5881 | |
| 5872 | 5882 | if (is_tdp_mmu_enabled(kvm)) { |
| 5873 | 5883 | read_lock(&kvm->mmu_lock); |
| 5874 | − flush = kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot, flush); | |
| 5875 | − if (flush) | |
| 5876 | − kvm_arch_flush_remote_tlbs_memslot(kvm, slot); | |
| 5884 | + kvm_tdp_mmu_zap_collapsible_sptes(kvm, slot); | |
| 5877 | 5885 | read_unlock(&kvm->mmu_lock); |
| 5878 | 5886 | } |
| 5879 | 5887 | } |
| @@ -6182,23 +6190,46 @@ void kvm_mmu_module_exit(void) · 302 unmodified lines | ||
| 6182 | 6190 | mmu_audit_disable(); |
| 6183 | 6191 | } |
| 6184 | 6192 | |
| 6193 | +/* | |
| 6194 | + * Calculate the effective recovery period, accounting for '0' meaning "let KVM | |
| 6195 | + * select a halving time of 1 hour". Returns true if recovery is enabled. | |
| 6196 | + */ | |
| 6197 | +static bool calc_nx_huge_pages_recovery_period(uint *period) | |
| 6198 | +{ | |
| 6199 | + /* | |
| 6200 | + * Use READ_ONCE to get the params, this may be called outside of the | |
| 6201 | + * param setters, e.g. by the kthread to compute its next timeout. | |
| 6202 | + */ | |
| 6203 | + bool enabled = READ_ONCE(nx_huge_pages); | |
| 6204 | + uint ratio = READ_ONCE(nx_huge_pages_recovery_ratio); | |
| 6205 | + | |
| 6206 | + if (!enabled || !ratio) | |
| 6207 | + return false; | |
| 6208 | + | |
| 6209 | + *period = READ_ONCE(nx_huge_pages_recovery_period_ms); | |
| 6210 | + if (!*period) { | |
| 6211 | + /* Make sure the period is not less than one second. */ | |
| 6212 | + ratio = min(ratio, 3600u); | |
| 6213 | + *period = 60 * 60 * 1000 / ratio; | |
| 6214 | + } | |
| 6215 | + return true; | |
| 6216 | +} | |
| 6217 | + | |
| 6185 | 6218 | static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel_param *kp) |
| 6186 | 6219 | { |
| 6187 | 6220 | bool was_recovery_enabled, is_recovery_enabled; |
| 6188 | 6221 | uint old_period, new_period; |
| 6189 | 6222 | int err; |
| 6190 | 6223 | |
| 6191 | − was_recovery_enabled = nx_huge_pages_recovery_ratio; | |
| 6192 | − old_period = nx_huge_pages_recovery_period_ms; | |
| 6224 | + was_recovery_enabled = calc_nx_huge_pages_recovery_period(&old_period); | |
| 6193 | 6225 | |
| 6194 | 6226 | err = param_set_uint(val, kp); |
| 6195 | 6227 | if (err) |
| 6196 | 6228 | return err; |
| 6197 | 6229 | |
| 6198 | − is_recovery_enabled = nx_huge_pages_recovery_ratio; | |
| 6199 | − new_period = nx_huge_pages_recovery_period_ms; | |
| 6230 | + is_recovery_enabled = calc_nx_huge_pages_recovery_period(&new_period); | |
| 6200 | 6231 | |
| 6201 | − if (READ_ONCE(nx_huge_pages) && is_recovery_enabled && | |
| 6232 | + if (is_recovery_enabled && | |
| 6202 | 6233 | (!was_recovery_enabled || old_period > new_period)) { |
| 6203 | 6234 | struct kvm *kvm; |
| 6204 | 6235 | |
| @@ -6262,18 +6293,13 @@ static void kvm_recover_nx_lpages(struct kvm *kvm) · 57 unmodified lines | ||
| 6262 | 6293 | |
| 6263 | 6294 | static long get_nx_lpage_recovery_timeout(u64 start_time) |
| 6264 | 6295 | { |
| 6265 | − uint ratio = READ_ONCE(nx_huge_pages_recovery_ratio); | |
| 6266 | − uint period = READ_ONCE(nx_huge_pages_recovery_period_ms); | |
| 6296 | + bool enabled; | |
| 6297 | + uint period; | |
| 6267 | 6298 | |
| 6268 | − if (!period && ratio) { | |
| 6269 | − /* Make sure the period is not less than one second. */ | |
| 6270 | − ratio = min(ratio, 3600u); | |
| 6271 | − period = 60 * 60 * 1000 / ratio; | |
| 6272 | − } | |
| 6299 | + enabled = calc_nx_huge_pages_recovery_period(&period); | |
| 6273 | 6300 | |
| 6274 | − return READ_ONCE(nx_huge_pages) && ratio | |
| 6275 | − ? start_time + msecs_to_jiffies(period) - get_jiffies_64() | |
| 6276 | − : MAX_SCHEDULE_TIMEOUT; | |
| 6301 | + return enabled ? start_time + msecs_to_jiffies(period) - get_jiffies_64() | |
| 6302 | + : MAX_SCHEDULE_TIMEOUT; | |
| 6277 | 6303 | } |
| 6278 | 6304 | |
| 6279 | 6305 | static int kvm_nx_lpage_recovery_worker(struct kvm *kvm, uintptr_t data) |
| @@ -911,7 +911,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault · 910 unmodified lines | ||
| 911 | 911 | |
| 912 | 912 | r = RET_PF_RETRY; |
| 913 | 913 | write_lock(&vcpu->kvm->mmu_lock); |
| 914 | − if (fault->slot && mmu_notifier_retry_hva(vcpu->kvm, mmu_seq, fault->hva)) | |
| 914 | + | |
| 915 | + if (is_page_fault_stale(vcpu, fault, mmu_seq)) | |
| 915 | 916 | goto out_unlock; |
| 916 | 917 | |
| 917 | 918 | kvm_mmu_audit(vcpu, AUDIT_PRE_PAGE_FAULT); |
| @@ -317,9 +317,6 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, · 316 unmodified lines | ||
| 317 | 317 | struct kvm_mmu_page *sp = sptep_to_sp(rcu_dereference(pt)); |
| 318 | 318 | int level = sp->role.level; |
| 319 | 319 | gfn_t base_gfn = sp->gfn; |
| 320 | − u64 old_child_spte; | |
| 321 | − u64 *sptep; | |
| 322 | − gfn_t gfn; | |
| 323 | 320 | int i; |
| 324 | 321 | |
| 325 | 322 | trace_kvm_mmu_prepare_zap_page(sp); |
| @@ -327,8 +324,9 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, · 1 unmodified line | ||
| 327 | 324 | tdp_mmu_unlink_page(kvm, sp, shared); |
| 328 | 325 | |
| 329 | 326 | for (i = 0; i < PT64_ENT_PER_PAGE; i++) { |
| 330 | − sptep = rcu_dereference(pt) + i; | |
| 331 | − gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); | |
| 327 | + u64 *sptep = rcu_dereference(pt) + i; | |
| 328 | + gfn_t gfn = base_gfn + i * KVM_PAGES_PER_HPAGE(level); | |
| 329 | + u64 old_child_spte; | |
| 332 | 330 | |
| 333 | 331 | if (shared) { |
| 334 | 332 | /* |
| @@ -374,7 +372,7 @@ static void handle_removed_tdp_mmu_page(struct kvm *kvm, tdp_ptep_t pt, · 39 unmodified lines | ||
| 374 | 372 | shared); |
| 375 | 373 | } |
| 376 | 374 | |
| 377 | − kvm_flush_remote_tlbs_with_address(kvm, gfn, | |
| 375 | + kvm_flush_remote_tlbs_with_address(kvm, base_gfn, | |
| 378 | 376 | KVM_PAGES_PER_HPAGE(level + 1)); |
| 379 | 377 | |
| 380 | 378 | call_rcu(&sp->rcu_head, tdp_mmu_free_sp_rcu_callback); |
| @@ -1033,9 +1031,9 @@ bool kvm_tdp_mmu_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range, · 652 unmodified lines | ||
| 1033 | 1031 | { |
| 1034 | 1032 | struct kvm_mmu_page *root; |
| 1035 | 1033 | |
| 1036 | − for_each_tdp_mmu_root(kvm, root, range->slot->as_id) | |
| 1037 | − flush |= zap_gfn_range(kvm, root, range->start, range->end, | |
| 1038 | − range->may_block, flush, false); | |
| 1034 | + for_each_tdp_mmu_root_yield_safe(kvm, root, range->slot->as_id, false) | |
| 1035 | + flush = zap_gfn_range(kvm, root, range->start, range->end, | |
| 1036 | + range->may_block, flush, false); | |
| 1039 | 1037 | |
| 1040 | 1038 | return flush; |
| 1041 | 1039 | } |
| @@ -1364,10 +1362,9 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, · 322 unmodified lines | ||
| 1364 | 1362 | * Clear leaf entries which could be replaced by large mappings, for |
| 1365 | 1363 | * GFNs within the slot. |
| 1366 | 1364 | */ |
| 1367 | −static bool zap_collapsible_spte_range(struct kvm *kvm, | |
| 1365 | +static void zap_collapsible_spte_range(struct kvm *kvm, | |
| 1368 | 1366 | struct kvm_mmu_page *root, |
| 1369 | − const struct kvm_memory_slot *slot, | |
| 1370 | − bool flush) | |
| 1367 | + const struct kvm_memory_slot *slot) | |
| 1371 | 1368 | { |
| 1372 | 1369 | gfn_t start = slot->base_gfn; |
| 1373 | 1370 | gfn_t end = start + slot->npages; |
| @@ -1378,10 +1375,8 @@ static bool zap_collapsible_spte_range(struct kvm *kvm, · 4 unmodified lines | ||
| 1378 | 1375 | |
| 1379 | 1376 | tdp_root_for_each_pte(iter, root, start, end) { |
| 1380 | 1377 | retry: |
| 1381 | − if (tdp_mmu_iter_cond_resched(kvm, &iter, flush, true)) { | |
| 1382 | − flush = false; | |
| 1378 | + if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true)) | |
| 1383 | 1379 | continue; |
| 1384 | − } | |
| 1385 | 1380 | |
| 1386 | 1381 | if (!is_shadow_present_pte(iter.old_spte) || |
| 1387 | 1382 | !is_last_spte(iter.old_spte, iter.level)) |
| @@ -1393,6 +1388,7 @@ retry: · 5 unmodified lines | ||
| 1393 | 1388 | pfn, PG_LEVEL_NUM)) |
| 1394 | 1389 | continue; |
| 1395 | 1390 | |
| 1391 | + /* Note, a successful atomic zap also does a remote TLB flush. */ | |
| 1396 | 1392 | if (!tdp_mmu_zap_spte_atomic(kvm, &iter)) { |
| 1397 | 1393 | /* |
| 1398 | 1394 | * The iter must explicitly re-read the SPTE because |
| @@ -1401,30 +1397,24 @@ retry: · 2 unmodified lines | ||
| 1401 | 1397 | iter.old_spte = READ_ONCE(*rcu_dereference(iter.sptep)); |
| 1402 | 1398 | goto retry; |
| 1403 | 1399 | } |
| 1404 | − flush = true; | |
| 1405 | 1400 | } |
| 1406 | 1401 | |
| 1407 | 1402 | rcu_read_unlock(); |
| 1408 | − | |
| 1409 | − return flush; | |
| 1410 | 1403 | } |
| 1411 | 1404 | |
| 1412 | 1405 | /* |
| 1413 | 1406 | * Clear non-leaf entries (and free associated page tables) which could |
| 1414 | 1407 | * be replaced by large mappings, for GFNs within the slot. |
| 1415 | 1408 | */ |
| 1416 | −bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, | |
| 1417 | − const struct kvm_memory_slot *slot, | |
| 1418 | − bool flush) | |
| 1409 | +void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, | |
| 1410 | + const struct kvm_memory_slot *slot) | |
| 1419 | 1411 | { |
| 1420 | 1412 | struct kvm_mmu_page *root; |
| 1421 | 1413 | |
| 1422 | 1414 | lockdep_assert_held_read(&kvm->mmu_lock); |
| 1423 | 1415 | |
| 1424 | 1416 | for_each_tdp_mmu_root_yield_safe(kvm, root, slot->as_id, true) |
| 1425 | − flush = zap_collapsible_spte_range(kvm, root, slot, flush); | |
| 1426 | − | |
| 1427 | − return flush; | |
| 1417 | + zap_collapsible_spte_range(kvm, root, slot); | |
| 1428 | 1418 | } |
| 1429 | 1419 | |
| 1430 | 1420 | /* |
| @@ -64,9 +64,8 @@ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, · 63 unmodified lines | ||
| 64 | 64 | struct kvm_memory_slot *slot, |
| 65 | 65 | gfn_t gfn, unsigned long mask, |
| 66 | 66 | bool wrprot); |
| 67 | −bool kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, | |
| 68 | − const struct kvm_memory_slot *slot, | |
| 69 | − bool flush); | |
| 67 | +void kvm_tdp_mmu_zap_collapsible_sptes(struct kvm *kvm, | |
| 68 | + const struct kvm_memory_slot *slot); | |
| 70 | 69 | |
| 71 | 70 | bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm, |
| 72 | 71 | struct kvm_memory_slot *slot, gfn_t gfn, |
| @@ -900,6 +900,7 @@ out: · 899 unmodified lines | ||
| 900 | 900 | bool svm_check_apicv_inhibit_reasons(ulong bit) |
| 901 | 901 | { |
| 902 | 902 | ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) | |
| 903 | + BIT(APICV_INHIBIT_REASON_ABSENT) | | |
| 903 | 904 | BIT(APICV_INHIBIT_REASON_HYPERV) | |
| 904 | 905 | BIT(APICV_INHIBIT_REASON_NESTED) | |
| 905 | 906 | BIT(APICV_INHIBIT_REASON_IRQWIN) | |
| @@ -989,16 +990,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu) · 83 unmodified lines | ||
| 989 | 990 | static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run) |
| 990 | 991 | { |
| 991 | 992 | struct vcpu_svm *svm = to_svm(vcpu); |
| 993 | + int cpu = get_cpu(); | |
| 992 | 994 | |
| 995 | + WARN_ON(cpu != vcpu->cpu); | |
| 993 | 996 | svm->avic_is_running = is_run; |
| 994 | 997 | |
| 995 | − if (!kvm_vcpu_apicv_active(vcpu)) | |
| 996 | − return; | |
| 997 | − | |
| 998 | − if (is_run) | |
| 999 | − avic_vcpu_load(vcpu, vcpu->cpu); | |
| 1000 | − else | |
| 1001 | − avic_vcpu_put(vcpu); | |
| 998 | + if (kvm_vcpu_apicv_active(vcpu)) { | |
| 999 | + if (is_run) | |
| 1000 | + avic_vcpu_load(vcpu, cpu); | |
| 1001 | + else | |
| 1002 | + avic_vcpu_put(vcpu); | |
| 1003 | + } | |
| 1004 | + put_cpu(); | |
| 1002 | 1005 | } |
| 1003 | 1006 | |
| 1004 | 1007 | void svm_vcpu_blocking(struct kvm_vcpu *vcpu) |
| @@ -281,7 +281,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu) · 280 unmodified lines | ||
| 281 | 281 | pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS; |
| 282 | 282 | |
| 283 | 283 | pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1; |
| 284 | − pmu->reserved_bits = 0xffffffff00200000ull; | |
| 284 | + pmu->reserved_bits = 0xfffffff000280000ull; | |
| 285 | 285 | pmu->version = 1; |
| 286 | 286 | /* not applicable to AMD; but clean them to prevent any fall out */ |
| 287 | 287 | pmu->counter_bitmask[KVM_PMC_FIXED] = 0; |
| @@ -1543,28 +1543,50 @@ static bool is_cmd_allowed_from_mirror(u32 cmd_id) · 1542 unmodified lines | ||
| 1543 | 1543 | return false; |
| 1544 | 1544 | } |
| 1545 | 1545 | |
| 1546 | −static int sev_lock_for_migration(struct kvm *kvm) | |
| 1546 | +static int sev_lock_two_vms(struct kvm *dst_kvm, struct kvm *src_kvm) | |
| 1547 | 1547 | { |
| 1548 | − struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; | |
| 1548 | + struct kvm_sev_info *dst_sev = &to_kvm_svm(dst_kvm)->sev_info; | |
| 1549 | + struct kvm_sev_info *src_sev = &to_kvm_svm(src_kvm)->sev_info; | |
| 1550 | + int r = -EBUSY; | |
| 1551 | + | |
| 1552 | + if (dst_kvm == src_kvm) | |
| 1553 | + return -EINVAL; | |
| 1549 | 1554 | |
| 1550 | 1555 | /* |
| 1551 | − * Bail if this VM is already involved in a migration to avoid deadlock | |
| 1552 | − * between two VMs trying to migrate to/from each other. | |
| 1556 | + * Bail if these VMs are already involved in a migration to avoid | |
| 1557 | + * deadlock between two VMs trying to migrate to/from each other. | |
| 1553 | 1558 | */ |
| 1554 | − if (atomic_cmpxchg_acquire(&sev->migration_in_progress, 0, 1)) | |
| 1559 | + if (atomic_cmpxchg_acquire(&dst_sev->migration_in_progress, 0, 1)) | |
| 1555 | 1560 | return -EBUSY; |
| 1556 | 1561 | |
| 1557 | − mutex_lock(&kvm->lock); | |
| 1562 | + if (atomic_cmpxchg_acquire(&src_sev->migration_in_progress, 0, 1)) | |
| 1563 | + goto release_dst; | |
| 1558 | 1564 | |
| 1565 | + r = -EINTR; | |
| 1566 | + if (mutex_lock_killable(&dst_kvm->lock)) | |
| 1567 | + goto release_src; | |
| 1568 | + if (mutex_lock_killable(&src_kvm->lock)) | |
| 1569 | + goto unlock_dst; | |
| 1559 | 1570 | return 0; |
| 1571 | + | |
| 1572 | +unlock_dst: | |
| 1573 | + mutex_unlock(&dst_kvm->lock); | |
| 1574 | +release_src: | |
| 1575 | + atomic_set_release(&src_sev->migration_in_progress, 0); | |
| 1576 | +release_dst: | |
| 1577 | + atomic_set_release(&dst_sev->migration_in_progress, 0); | |
| 1578 | + return r; | |
| 1560 | 1579 | } |
| 1561 | 1580 | |
| 1562 | −static void sev_unlock_after_migration(struct kvm *kvm) | |
| 1581 | +static void sev_unlock_two_vms(struct kvm *dst_kvm, struct kvm *src_kvm) | |
| 1563 | 1582 | { |
| 1564 | − struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; | |
| 1583 | + struct kvm_sev_info *dst_sev = &to_kvm_svm(dst_kvm)->sev_info; | |
| 1584 | + struct kvm_sev_info *src_sev = &to_kvm_svm(src_kvm)->sev_info; | |
| 1565 | 1585 | |
| 1566 | − mutex_unlock(&kvm->lock); | |
| 1567 | − atomic_set_release(&sev->migration_in_progress, 0); | |
| 1586 | + mutex_unlock(&dst_kvm->lock); | |
| 1587 | + mutex_unlock(&src_kvm->lock); | |
| 1588 | + atomic_set_release(&dst_sev->migration_in_progress, 0); | |
| 1589 | + atomic_set_release(&src_sev->migration_in_progress, 0); | |
| 1568 | 1590 | } |
| 1569 | 1591 | |
| 1570 | 1592 | |
| @@ -1607,14 +1629,15 @@ static void sev_migrate_from(struct kvm_sev_info *dst, · 36 unmodified lines | ||
| 1607 | 1629 | dst->asid = src->asid; |
| 1608 | 1630 | dst->handle = src->handle; |
| 1609 | 1631 | dst->pages_locked = src->pages_locked; |
| 1632 | + dst->enc_context_owner = src->enc_context_owner; | |
| 1610 | 1633 | |
| 1611 | 1634 | src->asid = 0; |
| 1612 | 1635 | src->active = false; |
| 1613 | 1636 | src->handle = 0; |
| 1614 | 1637 | src->pages_locked = 0; |
| 1638 | + src->enc_context_owner = NULL; | |
| 1615 | 1639 | |
| 1616 | − INIT_LIST_HEAD(&dst->regions_list); | |
| 1617 | − list_replace_init(&src->regions_list, &dst->regions_list); | |
| 1640 | + list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list); | |
| 1618 | 1641 | } |
| 1619 | 1642 | |
| 1620 | 1643 | static int sev_es_migrate_from(struct kvm *dst, struct kvm *src) |
| @@ -1666,15 +1689,6 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd) · 45 unmodified lines | ||
| 1666 | 1689 | bool charged = false; |
| 1667 | 1690 | int ret; |
| 1668 | 1691 | |
| 1669 | − ret = sev_lock_for_migration(kvm); | |
| 1670 | − if (ret) | |
| 1671 | − return ret; | |
| 1672 | − | |
| 1673 | − if (sev_guest(kvm)) { | |
| 1674 | − ret = -EINVAL; | |
| 1675 | − goto out_unlock; | |
| 1676 | − } | |
| 1677 | − | |
| 1678 | 1692 | source_kvm_file = fget(source_fd); |
| 1679 | 1693 | if (!file_is_kvm(source_kvm_file)) { |
| 1680 | 1694 | ret = -EBADF; |
| @@ -1682,16 +1696,26 @@ int svm_vm_migrate_from(struct kvm *kvm, unsigned int source_fd) · 1 unmodified line | ||
| 1682 | 1696 | } |
| 1683 | 1697 | |
| 1684 | 1698 | source_kvm = source_kvm_file->private_data; |
| 1685 | − ret = sev_lock_for_migration(source_kvm); | |
| 1699 | + ret = sev_lock_two_vms(kvm, source_kvm); | |
| 1686 | 1700 | if (ret) |
| 1687 | 1701 | goto out_fput; |
| 1688 | 1702 | |
| 1689 | − if (!sev_guest(source_kvm)) { | |
| 1703 | + if (sev_guest(kvm) || !sev_guest(source_kvm)) { | |
| 1690 | 1704 | ret = -EINVAL; |
| 1691 | − goto out_source; | |
| 1705 | + goto out_unlock; | |
| 1692 | 1706 | } |
| 1693 | 1707 | |
| 1694 | 1708 | src_sev = &to_kvm_svm(source_kvm)->sev_info; |
| 1709 | + | |
| 1710 | + /* | |
| 1711 | + * VMs mirroring src's encryption context rely on it to keep the | |
| 1712 | + * ASID allocated, but below we are clearing src_sev->asid. | |
| 1713 | + */ | |
| 1714 | + if (src_sev->num_mirrored_vms) { | |
| 1715 | + ret = -EBUSY; | |
| 1716 | + goto out_unlock; | |
| 1717 | + } | |
| 1718 | + | |
| 1695 | 1719 | dst_sev->misc_cg = get_current_misc_cg(); |
| 1696 | 1720 | cg_cleanup_sev = dst_sev; |
| 1697 | 1721 | if (dst_sev->misc_cg != src_sev->misc_cg) { |
| @@ -1728,13 +1752,11 @@ out_dst_cgroup: · 30 unmodified lines | ||
| 1728 | 1752 | sev_misc_cg_uncharge(cg_cleanup_sev); |
| 1729 | 1753 | put_misc_cg(cg_cleanup_sev->misc_cg); |
| 1730 | 1754 | cg_cleanup_sev->misc_cg = NULL; |
| 1731 | −out_source: | |
| 1732 | − sev_unlock_after_migration(source_kvm); | |
| 1755 | +out_unlock: | |
| 1756 | + sev_unlock_two_vms(kvm, source_kvm); | |
| 1733 | 1757 | out_fput: |
| 1734 | 1758 | if (source_kvm_file) |
| 1735 | 1759 | fput(source_kvm_file); |
| 1736 | −out_unlock: | |
| 1737 | − sev_unlock_after_migration(kvm); | |
| 1738 | 1760 | return ret; |
| 1739 | 1761 | } |
| 1740 | 1762 | |
| @@ -1953,76 +1975,60 @@ int svm_vm_copy_asid_from(struct kvm *kvm, unsigned int source_fd) · 212 unmodified lines | ||
| 1953 | 1975 | { |
| 1954 | 1976 | struct file *source_kvm_file; |
| 1955 | 1977 | struct kvm *source_kvm; |
| 1956 | − struct kvm_sev_info source_sev, *mirror_sev; | |
| 1978 | + struct kvm_sev_info *source_sev, *mirror_sev; | |
| 1957 | 1979 | int ret; |
| 1958 | 1980 | |
| 1959 | 1981 | source_kvm_file = fget(source_fd); |
| 1960 | 1982 | if (!file_is_kvm(source_kvm_file)) { |
| 1961 | 1983 | ret = -EBADF; |
| 1962 | − goto e_source_put; | |
| 1984 | + goto e_source_fput; | |
| 1963 | 1985 | } |
| 1964 | 1986 | |
| 1965 | 1987 | source_kvm = source_kvm_file->private_data; |
| 1966 | − mutex_lock(&source_kvm->lock); | |
| 1967 | − | |
| 1968 | − if (!sev_guest(source_kvm)) { | |
| 1969 | − ret = -EINVAL; | |
| 1970 | − goto e_source_unlock; | |
| 1971 | − } | |
| 1988 | + ret = sev_lock_two_vms(kvm, source_kvm); | |
| 1989 | + if (ret) | |
| 1990 | + goto e_source_fput; | |
| 1972 | 1991 | |
| 1973 | − /* Mirrors of mirrors should work, but let's not get silly */ | |
| 1974 | − if (is_mirroring_enc_context(source_kvm) || source_kvm == kvm) { | |
| 1992 | + /* | |
| 1993 | + * Mirrors of mirrors should work, but let's not get silly. Also | |
| 1994 | + * disallow out-of-band SEV/SEV-ES init if the target is already an | |
| 1995 | + * SEV guest, or if vCPUs have been created. KVM relies on vCPUs being | |
| 1996 | + * created after SEV/SEV-ES initialization, e.g. to init intercepts. | |
| 1997 | + */ | |
| 1998 | + if (sev_guest(kvm) || !sev_guest(source_kvm) || | |
| 1999 | + is_mirroring_enc_context(source_kvm) || kvm->created_vcpus) { | |
| 1975 | 2000 | ret = -EINVAL; |
| 1976 | − goto e_source_unlock; | |
| 2001 | + goto e_unlock; | |
| 1977 | 2002 | } |
| 1978 | 2003 | |
| 1979 | − memcpy(&source_sev, &to_kvm_svm(source_kvm)->sev_info, | |
| 1980 | − sizeof(source_sev)); | |
| 1981 | − | |
| 1982 | 2004 | /* |
| 1983 | 2005 | * The mirror kvm holds an enc_context_owner ref so its asid can't |
| 1984 | 2006 | * disappear until we're done with it |
| 1985 | 2007 | */ |
| 2008 | + source_sev = &to_kvm_svm(source_kvm)->sev_info; | |
| 1986 | 2009 | kvm_get_kvm(source_kvm); |
| 1987 | − | |
| 1988 | − fput(source_kvm_file); | |
| 1989 | − mutex_unlock(&source_kvm->lock); | |
| 1990 | − mutex_lock(&kvm->lock); | |
| 1991 | − | |
| 1992 | − /* | |
| 1993 | − * Disallow out-of-band SEV/SEV-ES init if the target is already an | |
| 1994 | − * SEV guest, or if vCPUs have been created. KVM relies on vCPUs being | |
| 1995 | − * created after SEV/SEV-ES initialization, e.g. to init intercepts. | |
| 1996 | − */ | |
| 1997 | − if (sev_guest(kvm) || kvm->created_vcpus) { | |
| 1998 | − ret = -EINVAL; | |
| 1999 | − goto e_mirror_unlock; | |
| 2000 | − } | |
| 2010 | + source_sev->num_mirrored_vms++; | |
| 2001 | 2011 | |
| 2002 | 2012 | /* Set enc_context_owner and copy its encryption context over */ |
| 2003 | 2013 | mirror_sev = &to_kvm_svm(kvm)->sev_info; |
| 2004 | 2014 | mirror_sev->enc_context_owner = source_kvm; |
| 2005 | 2015 | mirror_sev->active = true; |
| 2006 | − mirror_sev->asid = source_sev.asid; | |
| 2007 | − mirror_sev->fd = source_sev.fd; | |
| 2008 | − mirror_sev->es_active = source_sev.es_active; | |
| 2009 | − mirror_sev->handle = source_sev.handle; | |
| 2016 | + mirror_sev->asid = source_sev->asid; | |
| 2017 | + mirror_sev->fd = source_sev->fd; | |
| 2018 | + mirror_sev->es_active = source_sev->es_active; | |
| 2019 | + mirror_sev->handle = source_sev->handle; | |
| 2020 | + INIT_LIST_HEAD(&mirror_sev->regions_list); | |
| 2021 | + ret = 0; | |
| 2022 | + | |
| 2010 | 2023 | /* |
| 2011 | 2024 | * Do not copy ap_jump_table. Since the mirror does not share the same |
| 2012 | 2025 | * KVM contexts as the original, and they may have different |
| 2013 | 2026 | * memory-views. |
| 2014 | 2027 | */ |
| 2015 | 2028 | |
| 2016 | − mutex_unlock(&kvm->lock); | |
| 2017 | − return 0; | |
| 2018 | − | |
| 2019 | −e_mirror_unlock: | |
| 2020 | − mutex_unlock(&kvm->lock); | |
| 2021 | − kvm_put_kvm(source_kvm); | |
| 2022 | − return ret; | |
| 2023 | −e_source_unlock: | |
| 2024 | − mutex_unlock(&source_kvm->lock); | |
| 2025 | −e_source_put: | |
| 2029 | +e_unlock: | |
| 2030 | + sev_unlock_two_vms(kvm, source_kvm); | |
| 2031 | +e_source_fput: | |
| 2026 | 2032 | if (source_kvm_file) |
| 2027 | 2033 | fput(source_kvm_file); |
| 2028 | 2034 | return ret; |
| @@ -2034,17 +2040,24 @@ void sev_vm_destroy(struct kvm *kvm) · 5 unmodified lines | ||
| 2034 | 2040 | struct list_head *head = &sev->regions_list; |
| 2035 | 2041 | struct list_head *pos, *q; |
| 2036 | 2042 | |
| 2043 | + WARN_ON(sev->num_mirrored_vms); | |
| 2044 | + | |
| 2037 | 2045 | if (!sev_guest(kvm)) |
| 2038 | 2046 | return; |
| 2039 | 2047 | |
| 2040 | 2048 | /* If this is a mirror_kvm release the enc_context_owner and skip sev cleanup */ |
| 2041 | 2049 | if (is_mirroring_enc_context(kvm)) { |
| 2042 | − kvm_put_kvm(sev->enc_context_owner); | |
| 2050 | + struct kvm *owner_kvm = sev->enc_context_owner; | |
| 2051 | + struct kvm_sev_info *owner_sev = &to_kvm_svm(owner_kvm)->sev_info; | |
| 2052 | + | |
| 2053 | + mutex_lock(&owner_kvm->lock); | |
| 2054 | + if (!WARN_ON(!owner_sev->num_mirrored_vms)) | |
| 2055 | + owner_sev->num_mirrored_vms--; | |
| 2056 | + mutex_unlock(&owner_kvm->lock); | |
| 2057 | + kvm_put_kvm(owner_kvm); | |
| 2043 | 2058 | return; |
| 2044 | 2059 | } |
| 2045 | 2060 | |
| 2046 | − mutex_lock(&kvm->lock); | |
| 2047 | − | |
| 2048 | 2061 | /* |
| 2049 | 2062 | * Ensure that all guest tagged cache entries are flushed before |
| 2050 | 2063 | * releasing the pages back to the system for use. CLFLUSH will |
| @@ -2064,8 +2077,6 @@ void sev_vm_destroy(struct kvm *kvm) · 13 unmodified lines | ||
| 2064 | 2077 | } |
| 2065 | 2078 | } |
| 2066 | 2079 | |
| 2067 | − mutex_unlock(&kvm->lock); | |
| 2068 | − | |
| 2069 | 2080 | sev_unbind_asid(kvm, sev->handle); |
| 2070 | 2081 | sev_asid_free(sev); |
| 2071 | 2082 | } |
| @@ -2249,7 +2260,7 @@ void sev_free_vcpu(struct kvm_vcpu *vcpu) · 177 unmodified lines | ||
| 2249 | 2260 | __free_page(virt_to_page(svm->sev_es.vmsa)); |
| 2250 | 2261 | |
| 2251 | 2262 | if (svm->sev_es.ghcb_sa_free) |
| 2252 | − kfree(svm->sev_es.ghcb_sa); | |
| 2263 | + kvfree(svm->sev_es.ghcb_sa); | |
| 2253 | 2264 | } |
| 2254 | 2265 | |
| 2255 | 2266 | static void dump_ghcb(struct vcpu_svm *svm) |
| @@ -2341,24 +2352,29 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm) · 85 unmodified lines | ||
| 2341 | 2352 | memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); |
| 2342 | 2353 | } |
| 2343 | 2354 | |
| 2344 | −static int sev_es_validate_vmgexit(struct vcpu_svm *svm) | |
| 2355 | +static bool sev_es_validate_vmgexit(struct vcpu_svm *svm) | |
| 2345 | 2356 | { |
| 2346 | 2357 | struct kvm_vcpu *vcpu; |
| 2347 | 2358 | struct ghcb *ghcb; |
| 2348 | − u64 exit_code = 0; | |
| 2359 | + u64 exit_code; | |
| 2360 | + u64 reason; | |
| 2349 | 2361 | |
| 2350 | 2362 | ghcb = svm->sev_es.ghcb; |
| 2351 | 2363 | |
| 2352 | − /* Only GHCB Usage code 0 is supported */ | |
| 2353 | − if (ghcb->ghcb_usage) | |
| 2354 | − goto vmgexit_err; | |
| 2355 | − | |
| 2356 | 2364 | /* |
| 2357 | − * Retrieve the exit code now even though is may not be marked valid | |
| 2365 | + * Retrieve the exit code now even though it may not be marked valid | |
| 2358 | 2366 | * as it could help with debugging. |
| 2359 | 2367 | */ |
| 2360 | 2368 | exit_code = ghcb_get_sw_exit_code(ghcb); |
| 2361 | 2369 | |
| 2370 | + /* Only GHCB Usage code 0 is supported */ | |
| 2371 | + if (ghcb->ghcb_usage) { | |
| 2372 | + reason = GHCB_ERR_INVALID_USAGE; | |
| 2373 | + goto vmgexit_err; | |
| 2374 | + } | |
| 2375 | + | |
| 2376 | + reason = GHCB_ERR_MISSING_INPUT; | |
| 2377 | + | |
| 2362 | 2378 | if (!ghcb_sw_exit_code_is_valid(ghcb) || |
| 2363 | 2379 | !ghcb_sw_exit_info_1_is_valid(ghcb) || |
| 2364 | 2380 | !ghcb_sw_exit_info_2_is_valid(ghcb)) |
| @@ -2437,30 +2453,34 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) · 72 unmodified lines | ||
| 2437 | 2453 | case SVM_VMGEXIT_UNSUPPORTED_EVENT: |
| 2438 | 2454 | break; |
| 2439 | 2455 | default: |
| 2456 | + reason = GHCB_ERR_INVALID_EVENT; | |
| 2440 | 2457 | goto vmgexit_err; |
| 2441 | 2458 | } |
| 2442 | 2459 | |
| 2443 | − return 0; | |
| 2460 | + return true; | |
| 2444 | 2461 | |
| 2445 | 2462 | vmgexit_err: |
| 2446 | 2463 | vcpu = &svm->vcpu; |
| 2447 | 2464 | |
| 2448 | − if (ghcb->ghcb_usage) { | |
| 2465 | + if (reason == GHCB_ERR_INVALID_USAGE) { | |
| 2449 | 2466 | vcpu_unimpl(vcpu, "vmgexit: ghcb usage %#x is not valid\n", |
| 2450 | 2467 | ghcb->ghcb_usage); |
| 2468 | + } else if (reason == GHCB_ERR_INVALID_EVENT) { | |
| 2469 | + vcpu_unimpl(vcpu, "vmgexit: exit code %#llx is not valid\n", | |
| 2470 | + exit_code); | |
| 2451 | 2471 | } else { |
| 2452 | − vcpu_unimpl(vcpu, "vmgexit: exit reason %#llx is not valid\n", | |
| 2472 | + vcpu_unimpl(vcpu, "vmgexit: exit code %#llx input is not valid\n", | |
| 2453 | 2473 | exit_code); |
| 2454 | 2474 | dump_ghcb(svm); |
| 2455 | 2475 | } |
| 2456 | 2476 | |
| 2457 | − vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; | |
| 2458 | − vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON; | |
| 2459 | − vcpu->run->internal.ndata = 2; | |
| 2460 | − vcpu->run->internal.data[0] = exit_code; | |
| 2461 | − vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu; | |
| 2477 | + /* Clear the valid entries fields */ | |
| 2478 | + memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap)); | |
| 2479 | + | |
| 2480 | + ghcb_set_sw_exit_info_1(ghcb, 2); | |
| 2481 | + ghcb_set_sw_exit_info_2(ghcb, reason); | |
| 2462 | 2482 | |
| 2463 | − return -EINVAL; | |
| 2483 | + return false; | |
| 2464 | 2484 | } |
| 2465 | 2485 | |
| 2466 | 2486 | void sev_es_unmap_ghcb(struct vcpu_svm *svm) |
| @@ -2482,7 +2502,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm) · 15 unmodified lines | ||
| 2482 | 2502 | svm->sev_es.ghcb_sa_sync = false; |
| 2483 | 2503 | } |
| 2484 | 2504 | |
| 2485 | − kfree(svm->sev_es.ghcb_sa); | |
| 2505 | + kvfree(svm->sev_es.ghcb_sa); | |
| 2486 | 2506 | svm->sev_es.ghcb_sa = NULL; |
| 2487 | 2507 | svm->sev_es.ghcb_sa_free = false; |
| 2488 | 2508 | } |
| @@ -2530,14 +2550,14 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) · 41 unmodified lines | ||
| 2530 | 2550 | scratch_gpa_beg = ghcb_get_sw_scratch(ghcb); |
| 2531 | 2551 | if (!scratch_gpa_beg) { |
| 2532 | 2552 | pr_err("vmgexit: scratch gpa not provided\n"); |
| 2533 | − return false; | |
| 2553 | + goto e_scratch; | |
| 2534 | 2554 | } |
| 2535 | 2555 | |
| 2536 | 2556 | scratch_gpa_end = scratch_gpa_beg + len; |
| 2537 | 2557 | if (scratch_gpa_end < scratch_gpa_beg) { |
| 2538 | 2558 | pr_err("vmgexit: scratch length (%#llx) not valid for scratch address (%#llx)\n", |
| 2539 | 2559 | len, scratch_gpa_beg); |
| 2540 | − return false; | |
| 2560 | + goto e_scratch; | |
| 2541 | 2561 | } |
| 2542 | 2562 | |
| 2543 | 2563 | if ((scratch_gpa_beg & PAGE_MASK) == control->ghcb_gpa) { |
| @@ -2555,7 +2575,7 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) · 11 unmodified lines | ||
| 2555 | 2575 | scratch_gpa_end > ghcb_scratch_end) { |
| 2556 | 2576 | pr_err("vmgexit: scratch area is outside of GHCB shared buffer area (%#llx - %#llx)\n", |
| 2557 | 2577 | scratch_gpa_beg, scratch_gpa_end); |
| 2558 | − return false; | |
| 2578 | + goto e_scratch; | |
| 2559 | 2579 | } |
| 2560 | 2580 | |
| 2561 | 2581 | scratch_va = (void *)svm->sev_es.ghcb; |
| @@ -2568,18 +2588,18 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) · 6 unmodified lines | ||
| 2568 | 2588 | if (len > GHCB_SCRATCH_AREA_LIMIT) { |
| 2569 | 2589 | pr_err("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n", |
| 2570 | 2590 | len, GHCB_SCRATCH_AREA_LIMIT); |
| 2571 | − return false; | |
| 2591 | + goto e_scratch; | |
| 2572 | 2592 | } |
| 2573 | − scratch_va = kzalloc(len, GFP_KERNEL_ACCOUNT); | |
| 2593 | + scratch_va = kvzalloc(len, GFP_KERNEL_ACCOUNT); | |
| 2574 | 2594 | if (!scratch_va) |
| 2575 | − return false; | |
| 2595 | + goto e_scratch; | |
| 2576 | 2596 | |
| 2577 | 2597 | if (kvm_read_guest(svm->vcpu.kvm, scratch_gpa_beg, scratch_va, len)) { |
| 2578 | 2598 | /* Unable to copy scratch area from guest */ |
| 2579 | 2599 | pr_err("vmgexit: kvm_read_guest for scratch area failed\n"); |
| 2580 | 2600 | |
| 2581 | − kfree(scratch_va); | |
| 2582 | − return false; | |
| 2601 | + kvfree(scratch_va); | |
| 2602 | + goto e_scratch; | |
| 2583 | 2603 | } |
| 2584 | 2604 | |
| 2585 | 2605 | /* |
| @@ -2596,6 +2616,12 @@ static bool setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len) · 10 unmodified lines | ||
| 2596 | 2616 | svm->sev_es.ghcb_sa_len = len; |
| 2597 | 2617 | |
| 2598 | 2618 | return true; |
| 2619 | + | |
| 2620 | +e_scratch: | |
| 2621 | + ghcb_set_sw_exit_info_1(ghcb, 2); | |
| 2622 | + ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_SCRATCH_AREA); | |
| 2623 | + | |
| 2624 | + return false; | |
| 2599 | 2625 | } |
| 2600 | 2626 | |
| 2601 | 2627 | static void set_ghcb_msr_bits(struct vcpu_svm *svm, u64 value, u64 mask, |
| @@ -2646,7 +2672,7 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm) · 44 unmodified lines | ||
| 2646 | 2672 | |
| 2647 | 2673 | ret = svm_invoke_exit_handler(vcpu, SVM_EXIT_CPUID); |
| 2648 | 2674 | if (!ret) { |
| 2649 | − ret = -EINVAL; | |
| 2675 | + /* Error, keep GHCB MSR value as-is */ | |
| 2650 | 2676 | break; |
| 2651 | 2677 | } |
| 2652 | 2678 | |
| @@ -2682,10 +2708,13 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm) · 29 unmodified lines | ||
| 2682 | 2708 | GHCB_MSR_TERM_REASON_POS); |
| 2683 | 2709 | pr_info("SEV-ES guest requested termination: %#llx:%#llx\n", |
| 2684 | 2710 | reason_set, reason_code); |
| 2685 | − fallthrough; | |
| 2711 | + | |
| 2712 | + ret = -EINVAL; | |
| 2713 | + break; | |
| 2686 | 2714 | } |
| 2687 | 2715 | default: |
| 2688 | − ret = -EINVAL; | |
| 2716 | + /* Error, keep GHCB MSR value as-is */ | |
| 2717 | + break; | |
| 2689 | 2718 | } |
| 2690 | 2719 | |
| 2691 | 2720 | trace_kvm_vmgexit_msr_protocol_exit(svm->vcpu.vcpu_id, |
| @@ -2709,14 +2738,18 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 17 unmodified lines | ||
| 2709 | 2738 | |
| 2710 | 2739 | if (!ghcb_gpa) { |
| 2711 | 2740 | vcpu_unimpl(vcpu, "vmgexit: GHCB gpa is not set\n"); |
| 2712 | − return -EINVAL; | |
| 2741 | + | |
| 2742 | + /* Without a GHCB, just return right back to the guest */ | |
| 2743 | + return 1; | |
| 2713 | 2744 | } |
| 2714 | 2745 | |
| 2715 | 2746 | if (kvm_vcpu_map(vcpu, ghcb_gpa >> PAGE_SHIFT, &svm->sev_es.ghcb_map)) { |
| 2716 | 2747 | /* Unable to map GHCB from guest */ |
| 2717 | 2748 | vcpu_unimpl(vcpu, "vmgexit: error mapping GHCB [%#llx] from guest\n", |
| 2718 | 2749 | ghcb_gpa); |
| 2719 | − return -EINVAL; | |
| 2750 | + | |
| 2751 | + /* Without a GHCB, just return right back to the guest */ | |
| 2752 | + return 1; | |
| 2720 | 2753 | } |
| 2721 | 2754 | |
| 2722 | 2755 | svm->sev_es.ghcb = svm->sev_es.ghcb_map.hva; |
| @@ -2726,15 +2759,14 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 3 unmodified lines | ||
| 2726 | 2759 | |
| 2727 | 2760 | exit_code = ghcb_get_sw_exit_code(ghcb); |
| 2728 | 2761 | |
| 2729 | − ret = sev_es_validate_vmgexit(svm); | |
| 2730 | − if (ret) | |
| 2731 | − return ret; | |
| 2762 | + if (!sev_es_validate_vmgexit(svm)) | |
| 2763 | + return 1; | |
| 2732 | 2764 | |
| 2733 | 2765 | sev_es_sync_from_ghcb(svm); |
| 2734 | 2766 | ghcb_set_sw_exit_info_1(ghcb, 0); |
| 2735 | 2767 | ghcb_set_sw_exit_info_2(ghcb, 0); |
| 2736 | 2768 | |
| 2737 | − ret = -EINVAL; | |
| 2769 | + ret = 1; | |
| 2738 | 2770 | switch (exit_code) { |
| 2739 | 2771 | case SVM_VMGEXIT_MMIO_READ: |
| 2740 | 2772 | if (!setup_vmgexit_scratch(svm, true, control->exit_info_2)) |
| @@ -2775,20 +2807,17 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu) · 34 unmodified lines | ||
| 2775 | 2807 | default: |
| 2776 | 2808 | pr_err("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n", |
| 2777 | 2809 | control->exit_info_1); |
| 2778 | − ghcb_set_sw_exit_info_1(ghcb, 1); | |
| 2779 | − ghcb_set_sw_exit_info_2(ghcb, | |
| 2780 | − X86_TRAP_UD | | |
| 2781 | − SVM_EVTINJ_TYPE_EXEPT | | |
| 2782 | − SVM_EVTINJ_VALID); | |
| 2810 | + ghcb_set_sw_exit_info_1(ghcb, 2); | |
| 2811 | + ghcb_set_sw_exit_info_2(ghcb, GHCB_ERR_INVALID_INPUT); | |
| 2783 | 2812 | } |
| 2784 | 2813 | |
| 2785 | − ret = 1; | |
| 2786 | 2814 | break; |
| 2787 | 2815 | } |
| 2788 | 2816 | case SVM_VMGEXIT_UNSUPPORTED_EVENT: |
| 2789 | 2817 | vcpu_unimpl(vcpu, |
| 2790 | 2818 | "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n", |
| 2791 | 2819 | control->exit_info_1, control->exit_info_2); |
| 2820 | + ret = -EINVAL; | |
| 2792 | 2821 | break; |
| 2793 | 2822 | default: |
| 2794 | 2823 | ret = svm_invoke_exit_handler(vcpu, exit_code); |
| @@ -2810,7 +2839,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in) · 15 unmodified lines | ||
| 2810 | 2839 | return -EINVAL; |
| 2811 | 2840 | |
| 2812 | 2841 | if (!setup_vmgexit_scratch(svm, in, bytes)) |
| 2813 | − return -EINVAL; | |
| 2842 | + return 1; | |
| 2814 | 2843 | |
| 2815 | 2844 | return kvm_sev_es_string_io(&svm->vcpu, size, port, svm->sev_es.ghcb_sa, |
| 2816 | 2845 | count, in); |
| @@ -4651,7 +4651,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = { · 4650 unmodified lines | ||
| 4651 | 4651 | .load_eoi_exitmap = svm_load_eoi_exitmap, |
| 4652 | 4652 | .hwapic_irr_update = svm_hwapic_irr_update, |
| 4653 | 4653 | .hwapic_isr_update = svm_hwapic_isr_update, |
| 4654 | − .sync_pir_to_irr = kvm_lapic_find_highest_irr, | |
| 4655 | 4654 | .apicv_post_state_restore = avic_post_state_restore, |
| 4656 | 4655 | |
| 4657 | 4656 | .set_tss_addr = svm_set_tss_addr, |
| @@ -79,6 +79,7 @@ struct kvm_sev_info { · 78 unmodified lines | ||
| 79 | 79 | struct list_head regions_list; /* List of registered regions */ |
| 80 | 80 | u64 ap_jump_table; /* SEV-ES AP Jump Table address */ |
| 81 | 81 | struct kvm *enc_context_owner; /* Owner of copied encryption context */ |
| 82 | + unsigned long num_mirrored_vms; /* Number of VMs sharing this ASID */ | |
| 82 | 83 | struct misc_cg *misc_cg; /* For misc cgroup accounting */ |
| 83 | 84 | atomic_t migration_in_progress; |
| 84 | 85 | }; |
| @@ -1162,29 +1162,26 @@ static void nested_vmx_transition_tlb_flush(struct kvm_vcpu *vcpu, · 1161 unmodified lines | ||
| 1162 | 1162 | WARN_ON(!enable_vpid); |
| 1163 | 1163 | |
| 1164 | 1164 | /* |
| 1165 | − * If VPID is enabled and used by vmc12, but L2 does not have a unique | |
| 1166 | − * TLB tag (ASID), i.e. EPT is disabled and KVM was unable to allocate | |
| 1167 | − * a VPID for L2, flush the current context as the effective ASID is | |
| 1168 | − * common to both L1 and L2. | |
| 1169 | − * | |
| 1170 | − * Defer the flush so that it runs after vmcs02.EPTP has been set by | |
| 1171 | − * KVM_REQ_LOAD_MMU_PGD (if nested EPT is enabled) and to avoid | |
| 1172 | − * redundant flushes further down the nested pipeline. | |
| 1173 | − * | |
| 1174 | − * If a TLB flush isn't required due to any of the above, and vpid12 is | |
| 1175 | − * changing then the new "virtual" VPID (vpid12) will reuse the same | |
| 1176 | − * "real" VPID (vpid02), and so needs to be flushed. There's no direct | |
| 1177 | − * mapping between vpid02 and vpid12, vpid02 is per-vCPU and reused for | |
| 1178 | − * all nested vCPUs. Remember, a flush on VM-Enter does not invalidate | |
| 1179 | − * guest-physical mappings, so there is no need to sync the nEPT MMU. | |
| 1165 | + * VPID is enabled and in use by vmcs12. If vpid12 is changing, then | |
| 1166 | + * emulate a guest TLB flush as KVM does not track vpid12 history nor | |
| 1167 | + * is the VPID incorporated into the MMU context. I.e. KVM must assume | |
| 1168 | + * that the new vpid12 has never been used and thus represents a new | |
| 1169 | + * guest ASID that cannot have entries in the TLB. | |
| 1180 | 1170 | */ |
| 1181 | − if (!nested_has_guest_tlb_tag(vcpu)) { | |
| 1182 | − kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); | |
| 1183 | − } else if (is_vmenter && | |
| 1184 | − vmcs12->virtual_processor_id != vmx->nested.last_vpid) { | |
| 1171 | + if (is_vmenter && vmcs12->virtual_processor_id != vmx->nested.last_vpid) { | |
| 1185 | 1172 | vmx->nested.last_vpid = vmcs12->virtual_processor_id; |
| 1186 | − vpid_sync_context(nested_get_vpid02(vcpu)); | |
| 1173 | + kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); | |
| 1174 | + return; | |
| 1187 | 1175 | } |
| 1176 | + | |
| 1177 | + /* | |
| 1178 | + * If VPID is enabled, used by vmc12, and vpid12 is not changing but | |
| 1179 | + * does not have a unique TLB tag (ASID), i.e. EPT is disabled and | |
| 1180 | + * KVM was unable to allocate a VPID for L2, flush the current context | |
| 1181 | + * as the effective ASID is common to both L1 and L2. | |
| 1182 | + */ | |
| 1183 | + if (!nested_has_guest_tlb_tag(vcpu)) | |
| 1184 | + kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); | |
| 1188 | 1185 | } |
| 1189 | 1186 | |
| 1190 | 1187 | static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask) |
| @@ -2594,8 +2591,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, · 1403 unmodified lines | ||
| 2594 | 2591 | |
| 2595 | 2592 | if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && |
| 2596 | 2593 | WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL, |
| 2597 | − vmcs12->guest_ia32_perf_global_ctrl))) | |
| 2594 | + vmcs12->guest_ia32_perf_global_ctrl))) { | |
| 2595 | + *entry_failure_code = ENTRY_FAIL_DEFAULT; | |
| 2598 | 2596 | return -EINVAL; |
| 2597 | + } | |
| 2599 | 2598 | |
| 2600 | 2599 | kvm_rsp_write(vcpu, vmcs12->guest_rsp); |
| 2601 | 2600 | kvm_rip_write(vcpu, vmcs12->guest_rip); |
| @@ -3344,8 +3343,7 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, · 742 unmodified lines | ||
| 3344 | 3343 | }; |
| 3345 | 3344 | u32 failed_index; |
| 3346 | 3345 | |
| 3347 | − if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) | |
| 3348 | − kvm_vcpu_flush_tlb_current(vcpu); | |
| 3346 | + kvm_service_local_tlb_flush_requests(vcpu); | |
| 3349 | 3347 | |
| 3350 | 3348 | evaluate_pending_interrupts = exec_controls_get(vmx) & |
| 3351 | 3349 | (CPU_BASED_INTR_WINDOW_EXITING | CPU_BASED_NMI_WINDOW_EXITING); |
| @@ -4502,9 +4500,8 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, · 1150 unmodified lines | ||
| 4502 | 4500 | (void)nested_get_evmcs_page(vcpu); |
| 4503 | 4501 | } |
| 4504 | 4502 | |
| 4505 | − /* Service the TLB flush request for L2 before switching to L1. */ | |
| 4506 | − if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) | |
| 4507 | − kvm_vcpu_flush_tlb_current(vcpu); | |
| 4503 | + /* Service pending TLB flush requests for L2 before switching to L1. */ | |
| 4504 | + kvm_service_local_tlb_flush_requests(vcpu); | |
| 4508 | 4505 | |
| 4509 | 4506 | /* |
| 4510 | 4507 | * VCPU_EXREG_PDPTR will be clobbered in arch/x86/kvm/vmx/vmx.h between |
| @@ -4857,6 +4854,7 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu) · 346 unmodified lines | ||
| 4857 | 4854 | if (!vmx->nested.cached_vmcs12) |
| 4858 | 4855 | goto out_cached_vmcs12; |
| 4859 | 4856 | |
| 4857 | + vmx->nested.shadow_vmcs12_cache.gpa = INVALID_GPA; | |
| 4860 | 4858 | vmx->nested.cached_shadow_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL_ACCOUNT); |
| 4861 | 4859 | if (!vmx->nested.cached_shadow_vmcs12) |
| 4862 | 4860 | goto out_cached_shadow_vmcs12; |
| @@ -5289,8 +5287,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu) · 426 unmodified lines | ||
| 5289 | 5287 | struct gfn_to_hva_cache *ghc = &vmx->nested.vmcs12_cache; |
| 5290 | 5288 | struct vmcs_hdr hdr; |
| 5291 | 5289 | |
| 5292 | − if (ghc->gpa != vmptr && | |
| 5293 | − kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, vmptr, VMCS12_SIZE)) { | |
| 5290 | + if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ghc, vmptr, VMCS12_SIZE)) { | |
| 5294 | 5291 | /* |
| 5295 | 5292 | * Reads from an unbacked page return all 1s, |
| 5296 | 5293 | * which means that the 32 bits located at the |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <asm/cpu.h> |
| 6 | 6 | |
| 7 | 7 | #include "lapic.h" |
| 8 | +#include "irq.h" | |
| 8 | 9 | #include "posted_intr.h" |
| 9 | 10 | #include "trace.h" |
| 10 | 11 | #include "vmx.h" |
| @@ -77,13 +78,18 @@ after_clear_sn: · 66 unmodified lines | ||
| 77 | 78 | pi_set_on(pi_desc); |
| 78 | 79 | } |
| 79 | 80 | |
| 81 | +static bool vmx_can_use_vtd_pi(struct kvm *kvm) | |
| 82 | +{ | |
| 83 | + return irqchip_in_kernel(kvm) && enable_apicv && | |
| 84 | + kvm_arch_has_assigned_device(kvm) && | |
| 85 | + irq_remapping_cap(IRQ_POSTING_CAP); | |
| 86 | +} | |
| 87 | + | |
| 80 | 88 | void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu) |
| 81 | 89 | { |
| 82 | 90 | struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); |
| 83 | 91 | |
| 84 | − if (!kvm_arch_has_assigned_device(vcpu->kvm) || | |
| 85 | − !irq_remapping_cap(IRQ_POSTING_CAP) || | |
| 86 | − !kvm_vcpu_apicv_active(vcpu)) | |
| 92 | + if (!vmx_can_use_vtd_pi(vcpu->kvm)) | |
| 87 | 93 | return; |
| 88 | 94 | |
| 89 | 95 | /* Set SN when the vCPU is preempted */ |
| @@ -141,9 +147,7 @@ int pi_pre_block(struct kvm_vcpu *vcpu) · 51 unmodified lines | ||
| 141 | 147 | struct pi_desc old, new; |
| 142 | 148 | struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu); |
| 143 | 149 | |
| 144 | − if (!kvm_arch_has_assigned_device(vcpu->kvm) || | |
| 145 | − !irq_remapping_cap(IRQ_POSTING_CAP) || | |
| 146 | − !kvm_vcpu_apicv_active(vcpu)) | |
| 150 | + if (!vmx_can_use_vtd_pi(vcpu->kvm)) | |
| 147 | 151 | return 0; |
| 148 | 152 | |
| 149 | 153 | WARN_ON(irqs_disabled()); |
| @@ -270,9 +274,7 @@ int pi_update_irte(struct kvm *kvm, unsigned int host_irq, uint32_t guest_irq, · 120 unmodified lines | ||
| 270 | 274 | struct vcpu_data vcpu_info; |
| 271 | 275 | int idx, ret = 0; |
| 272 | 276 | |
| 273 | − if (!kvm_arch_has_assigned_device(kvm) || | |
| 274 | − !irq_remapping_cap(IRQ_POSTING_CAP) || | |
| 275 | − !kvm_vcpu_apicv_active(kvm->vcpus[0])) | |
| 277 | + if (!vmx_can_use_vtd_pi(kvm)) | |
| 276 | 278 | return 0; |
| 277 | 279 | |
| 278 | 280 | idx = srcu_read_lock(&kvm->irq_srcu); |
| @@ -2646,15 +2646,6 @@ int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs) · 2645 unmodified lines | ||
| 2646 | 2646 | if (!loaded_vmcs->msr_bitmap) |
| 2647 | 2647 | goto out_vmcs; |
| 2648 | 2648 | memset(loaded_vmcs->msr_bitmap, 0xff, PAGE_SIZE); |
| 2649 | − | |
| 2650 | − if (IS_ENABLED(CONFIG_HYPERV) && | |
| 2651 | − static_branch_unlikely(&enable_evmcs) && | |
| 2652 | − (ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP)) { | |
| 2653 | − struct hv_enlightened_vmcs *evmcs = | |
| 2654 | − (struct hv_enlightened_vmcs *)loaded_vmcs->vmcs; | |
| 2655 | − | |
| 2656 | − evmcs->hv_enlightenments_control.msr_bitmap = 1; | |
| 2657 | − } | |
| 2658 | 2649 | } |
| 2659 | 2650 | |
| 2660 | 2651 | memset(&loaded_vmcs->host_state, 0, sizeof(struct vmcs_host_state)); |
| @@ -2918,6 +2909,13 @@ static void vmx_flush_tlb_all(struct kvm_vcpu *vcpu) · 257 unmodified lines | ||
| 2918 | 2909 | } |
| 2919 | 2910 | } |
| 2920 | 2911 | |
| 2912 | +static inline int vmx_get_current_vpid(struct kvm_vcpu *vcpu) | |
| 2913 | +{ | |
| 2914 | + if (is_guest_mode(vcpu)) | |
| 2915 | + return nested_get_vpid02(vcpu); | |
| 2916 | + return to_vmx(vcpu)->vpid; | |
| 2917 | +} | |
| 2918 | + | |
| 2921 | 2919 | static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) |
| 2922 | 2920 | { |
| 2923 | 2921 | struct kvm_mmu *mmu = vcpu->arch.mmu; |
| @@ -2930,31 +2928,29 @@ static void vmx_flush_tlb_current(struct kvm_vcpu *vcpu) · 6 unmodified lines | ||
| 2930 | 2928 | if (enable_ept) |
| 2931 | 2929 | ept_sync_context(construct_eptp(vcpu, root_hpa, |
| 2932 | 2930 | mmu->shadow_root_level)); |
| 2933 | − else if (!is_guest_mode(vcpu)) | |
| 2934 | − vpid_sync_context(to_vmx(vcpu)->vpid); | |
| 2935 | 2931 | else |
| 2936 | − vpid_sync_context(nested_get_vpid02(vcpu)); | |
| 2932 | + vpid_sync_context(vmx_get_current_vpid(vcpu)); | |
| 2937 | 2933 | } |
| 2938 | 2934 | |
| 2939 | 2935 | static void vmx_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t addr) |
| 2940 | 2936 | { |
| 2941 | 2937 | /* |
| 2942 | − * vpid_sync_vcpu_addr() is a nop if vmx->vpid==0, see the comment in | |
| 2938 | + * vpid_sync_vcpu_addr() is a nop if vpid==0, see the comment in | |
| 2943 | 2939 | * vmx_flush_tlb_guest() for an explanation of why this is ok. |
| 2944 | 2940 | */ |
| 2945 | − vpid_sync_vcpu_addr(to_vmx(vcpu)->vpid, addr); | |
| 2941 | + vpid_sync_vcpu_addr(vmx_get_current_vpid(vcpu), addr); | |
| 2946 | 2942 | } |
| 2947 | 2943 | |
| 2948 | 2944 | static void vmx_flush_tlb_guest(struct kvm_vcpu *vcpu) |
| 2949 | 2945 | { |
| 2950 | 2946 | /* |
| 2951 | − * vpid_sync_context() is a nop if vmx->vpid==0, e.g. if enable_vpid==0 | |
| 2952 | − * or a vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit | |
| 2953 | − * are required to flush GVA->{G,H}PA mappings from the TLB if vpid is | |
| 2947 | + * vpid_sync_context() is a nop if vpid==0, e.g. if enable_vpid==0 or a | |
| 2948 | + * vpid couldn't be allocated for this vCPU. VM-Enter and VM-Exit are | |
| 2949 | + * required to flush GVA->{G,H}PA mappings from the TLB if vpid is | |
| 2954 | 2950 | * disabled (VM-Enter with vpid enabled and vpid==0 is disallowed), |
| 2955 | 2951 | * i.e. no explicit INVVPID is necessary. |
| 2956 | 2952 | */ |
| 2957 | − vpid_sync_context(to_vmx(vcpu)->vpid); | |
| 2953 | + vpid_sync_context(vmx_get_current_vpid(vcpu)); | |
| 2958 | 2954 | } |
| 2959 | 2955 | |
| 2960 | 2956 | void vmx_ept_load_pdptrs(struct kvm_vcpu *vcpu) |
| @@ -6262,9 +6258,9 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu) · 3301 unmodified lines | ||
| 6262 | 6258 | { |
| 6263 | 6259 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
| 6264 | 6260 | int max_irr; |
| 6265 | − bool max_irr_updated; | |
| 6261 | + bool got_posted_interrupt; | |
| 6266 | 6262 | |
| 6267 | − if (KVM_BUG_ON(!vcpu->arch.apicv_active, vcpu->kvm)) | |
| 6263 | + if (KVM_BUG_ON(!enable_apicv, vcpu->kvm)) | |
| 6268 | 6264 | return -EIO; |
| 6269 | 6265 | |
| 6270 | 6266 | if (pi_test_on(&vmx->pi_desc)) { |
| @@ -6274,22 +6270,33 @@ static int vmx_sync_pir_to_irr(struct kvm_vcpu *vcpu) · 3 unmodified lines | ||
| 6274 | 6270 | * But on x86 this is just a compiler barrier anyway. |
| 6275 | 6271 | */ |
| 6276 | 6272 | smp_mb__after_atomic(); |
| 6277 | − max_irr_updated = | |
| 6273 | + got_posted_interrupt = | |
| 6278 | 6274 | kvm_apic_update_irr(vcpu, vmx->pi_desc.pir, &max_irr); |
| 6279 | − | |
| 6280 | − /* | |
| 6281 | − * If we are running L2 and L1 has a new pending interrupt | |
| 6282 | − * which can be injected, this may cause a vmexit or it may | |
| 6283 | − * be injected into L2. Either way, this interrupt will be | |
| 6284 | − * processed via KVM_REQ_EVENT, not RVI, because we do not use | |
| 6285 | − * virtual interrupt delivery to inject L1 interrupts into L2. | |
| 6286 | − */ | |
| 6287 | − if (is_guest_mode(vcpu) && max_irr_updated) | |
| 6288 | − kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| 6289 | 6275 | } else { |
| 6290 | 6276 | max_irr = kvm_lapic_find_highest_irr(vcpu); |
| 6277 | + got_posted_interrupt = false; | |
| 6291 | 6278 | } |
| 6292 | − vmx_hwapic_irr_update(vcpu, max_irr); | |
| 6279 | + | |
| 6280 | + /* | |
| 6281 | + * Newly recognized interrupts are injected via either virtual interrupt | |
| 6282 | + * delivery (RVI) or KVM_REQ_EVENT. Virtual interrupt delivery is | |
| 6283 | + * disabled in two cases: | |
| 6284 | + * | |
| 6285 | + * 1) If L2 is running and the vCPU has a new pending interrupt. If L1 | |
| 6286 | + * wants to exit on interrupts, KVM_REQ_EVENT is needed to synthesize a | |
| 6287 | + * VM-Exit to L1. If L1 doesn't want to exit, the interrupt is injected | |
| 6288 | + * into L2, but KVM doesn't use virtual interrupt delivery to inject | |
| 6289 | + * interrupts into L2, and so KVM_REQ_EVENT is again needed. | |
| 6290 | + * | |
| 6291 | + * 2) If APICv is disabled for this vCPU, assigned devices may still | |
| 6292 | + * attempt to post interrupts. The posted interrupt vector will cause | |
| 6293 | + * a VM-Exit and the subsequent entry will call sync_pir_to_irr. | |
| 6294 | + */ | |
| 6295 | + if (!is_guest_mode(vcpu) && kvm_vcpu_apicv_active(vcpu)) | |
| 6296 | + vmx_set_rvi(max_irr); | |
| 6297 | + else if (got_posted_interrupt) | |
| 6298 | + kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| 6299 | + | |
| 6293 | 6300 | return max_irr; |
| 6294 | 6301 | } |
| 6295 | 6302 | |
| @@ -6826,6 +6833,19 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu) · 530 unmodified lines | ||
| 6826 | 6833 | if (err < 0) |
| 6827 | 6834 | goto free_pml; |
| 6828 | 6835 | |
| 6836 | + /* | |
| 6837 | + * Use Hyper-V 'Enlightened MSR Bitmap' feature when KVM runs as a | |
| 6838 | + * nested (L1) hypervisor and Hyper-V in L0 supports it. Enable the | |
| 6839 | + * feature only for vmcs01, KVM currently isn't equipped to realize any | |
| 6840 | + * performance benefits from enabling it for vmcs02. | |
| 6841 | + */ | |
| 6842 | + if (IS_ENABLED(CONFIG_HYPERV) && static_branch_unlikely(&enable_evmcs) && | |
| 6843 | + (ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP)) { | |
| 6844 | + struct hv_enlightened_vmcs *evmcs = (void *)vmx->vmcs01.vmcs; | |
| 6845 | + | |
| 6846 | + evmcs->hv_enlightenments_control.msr_bitmap = 1; | |
| 6847 | + } | |
| 6848 | + | |
| 6829 | 6849 | /* The MSR bitmap starts with all ones */ |
| 6830 | 6850 | bitmap_fill(vmx->shadow_msr_intercept.read, MAX_POSSIBLE_PASSTHROUGH_MSRS); |
| 6831 | 6851 | bitmap_fill(vmx->shadow_msr_intercept.write, MAX_POSSIBLE_PASSTHROUGH_MSRS); |
| @@ -7509,6 +7529,7 @@ static void hardware_unsetup(void) · 677 unmodified lines | ||
| 7509 | 7529 | static bool vmx_check_apicv_inhibit_reasons(ulong bit) |
| 7510 | 7530 | { |
| 7511 | 7531 | ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) | |
| 7532 | + BIT(APICV_INHIBIT_REASON_ABSENT) | | |
| 7512 | 7533 | BIT(APICV_INHIBIT_REASON_HYPERV) | |
| 7513 | 7534 | BIT(APICV_INHIBIT_REASON_BLOCKIRQ); |
| 7514 | 7535 | |
| @@ -7761,10 +7782,10 @@ static __init int hardware_setup(void) · 246 unmodified lines | ||
| 7761 | 7782 | ple_window_shrink = 0; |
| 7762 | 7783 | } |
| 7763 | 7784 | |
| 7764 | − if (!cpu_has_vmx_apicv()) { | |
| 7785 | + if (!cpu_has_vmx_apicv()) | |
| 7765 | 7786 | enable_apicv = 0; |
| 7787 | + if (!enable_apicv) | |
| 7766 | 7788 | vmx_x86_ops.sync_pir_to_irr = NULL; |
| 7767 | − } | |
| 7768 | 7789 | |
| 7769 | 7790 | if (cpu_has_vmx_tsc_scaling()) { |
| 7770 | 7791 | kvm_has_tsc_control = true; |
| @@ -890,7 +890,8 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) · 889 unmodified lines | ||
| 890 | 890 | !load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu))) |
| 891 | 891 | return 1; |
| 892 | 892 | |
| 893 | − if (!(cr0 & X86_CR0_PG) && kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE)) | |
| 893 | + if (!(cr0 & X86_CR0_PG) && | |
| 894 | + (is_64_bit_mode(vcpu) || kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE))) | |
| 894 | 895 | return 1; |
| 895 | 896 | |
| 896 | 897 | static_call(kvm_x86_set_cr0)(vcpu, cr0); |
| @@ -3258,6 +3259,29 @@ static void kvm_vcpu_flush_tlb_guest(struct kvm_vcpu *vcpu) · 2361 unmodified lines | ||
| 3258 | 3259 | static_call(kvm_x86_tlb_flush_guest)(vcpu); |
| 3259 | 3260 | } |
| 3260 | 3261 | |
| 3262 | + | |
| 3263 | +static inline void kvm_vcpu_flush_tlb_current(struct kvm_vcpu *vcpu) | |
| 3264 | +{ | |
| 3265 | + ++vcpu->stat.tlb_flush; | |
| 3266 | + static_call(kvm_x86_tlb_flush_current)(vcpu); | |
| 3267 | +} | |
| 3268 | + | |
| 3269 | +/* | |
| 3270 | + * Service "local" TLB flush requests, which are specific to the current MMU | |
| 3271 | + * context. In addition to the generic event handling in vcpu_enter_guest(), | |
| 3272 | + * TLB flushes that are targeted at an MMU context also need to be serviced | |
| 3273 | + * prior before nested VM-Enter/VM-Exit. | |
| 3274 | + */ | |
| 3275 | +void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu) | |
| 3276 | +{ | |
| 3277 | + if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) | |
| 3278 | + kvm_vcpu_flush_tlb_current(vcpu); | |
| 3279 | + | |
| 3280 | + if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) | |
| 3281 | + kvm_vcpu_flush_tlb_guest(vcpu); | |
| 3282 | +} | |
| 3283 | +EXPORT_SYMBOL_GPL(kvm_service_local_tlb_flush_requests); | |
| 3284 | + | |
| 3261 | 3285 | static void record_steal_time(struct kvm_vcpu *vcpu) |
| 3262 | 3286 | { |
| 3263 | 3287 | struct gfn_to_hva_cache *ghc = &vcpu->arch.st.cache; |
| @@ -4133,6 +4157,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 869 unmodified lines | ||
| 4133 | 4157 | case KVM_CAP_SGX_ATTRIBUTE: |
| 4134 | 4158 | #endif |
| 4135 | 4159 | case KVM_CAP_VM_COPY_ENC_CONTEXT_FROM: |
| 4160 | + case KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM: | |
| 4136 | 4161 | case KVM_CAP_SREGS2: |
| 4137 | 4162 | case KVM_CAP_EXIT_ON_EMULATION_FAILURE: |
| 4138 | 4163 | case KVM_CAP_VCPU_ATTRIBUTES: |
| @@ -4448,8 +4473,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) · 309 unmodified lines | ||
| 4448 | 4473 | static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu, |
| 4449 | 4474 | struct kvm_lapic_state *s) |
| 4450 | 4475 | { |
| 4451 | − if (vcpu->arch.apicv_active) | |
| 4452 | − static_call(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 4476 | + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 4453 | 4477 | |
| 4454 | 4478 | return kvm_apic_get_state(vcpu, s); |
| 4455 | 4479 | } |
| @@ -5124,6 +5148,17 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 668 unmodified lines | ||
| 5124 | 5148 | struct kvm_cpuid __user *cpuid_arg = argp; |
| 5125 | 5149 | struct kvm_cpuid cpuid; |
| 5126 | 5150 | |
| 5151 | + /* | |
| 5152 | + * KVM does not correctly handle changing guest CPUID after KVM_RUN, as | |
| 5153 | + * MAXPHYADDR, GBPAGES support, AMD reserved bit behavior, etc.. aren't | |
| 5154 | + * tracked in kvm_mmu_page_role. As a result, KVM may miss guest page | |
| 5155 | + * faults due to reusing SPs/SPTEs. In practice no sane VMM mucks with | |
| 5156 | + * the core vCPU model on the fly, so fail. | |
| 5157 | + */ | |
| 5158 | + r = -EINVAL; | |
| 5159 | + if (vcpu->arch.last_vmentry_cpu != -1) | |
| 5160 | + goto out; | |
| 5161 | + | |
| 5127 | 5162 | r = -EFAULT; |
| 5128 | 5163 | if (copy_from_user(&cpuid, cpuid_arg, sizeof(cpuid))) |
| 5129 | 5164 | goto out; |
| @@ -5134,6 +5169,14 @@ long kvm_arch_vcpu_ioctl(struct file *filp, · 4 unmodified lines | ||
| 5134 | 5169 | struct kvm_cpuid2 __user *cpuid_arg = argp; |
| 5135 | 5170 | struct kvm_cpuid2 cpuid; |
| 5136 | 5171 | |
| 5172 | + /* | |
| 5173 | + * KVM_SET_CPUID{,2} after KVM_RUN is forbidded, see the comment in | |
| 5174 | + * KVM_SET_CPUID case above. | |
| 5175 | + */ | |
| 5176 | + r = -EINVAL; | |
| 5177 | + if (vcpu->arch.last_vmentry_cpu != -1) | |
| 5178 | + goto out; | |
| 5179 | + | |
| 5137 | 5180 | r = -EFAULT; |
| 5138 | 5181 | if (copy_from_user(&cpuid, cpuid_arg, sizeof(cpuid))) |
| 5139 | 5182 | goto out; |
| @@ -5698,6 +5741,7 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, · 558 unmodified lines | ||
| 5698 | 5741 | smp_wmb(); |
| 5699 | 5742 | kvm->arch.irqchip_mode = KVM_IRQCHIP_SPLIT; |
| 5700 | 5743 | kvm->arch.nr_reserved_ioapic_pins = cap->args[0]; |
| 5744 | + kvm_request_apicv_update(kvm, true, APICV_INHIBIT_REASON_ABSENT); | |
| 5701 | 5745 | r = 0; |
| 5702 | 5746 | split_irqchip_unlock: |
| 5703 | 5747 | mutex_unlock(&kvm->lock); |
| @@ -6078,6 +6122,7 @@ set_identity_unlock: · 374 unmodified lines | ||
| 6078 | 6122 | /* Write kvm->irq_routing before enabling irqchip_in_kernel. */ |
| 6079 | 6123 | smp_wmb(); |
| 6080 | 6124 | kvm->arch.irqchip_mode = KVM_IRQCHIP_KERNEL; |
| 6125 | + kvm_request_apicv_update(kvm, true, APICV_INHIBIT_REASON_ABSENT); | |
| 6081 | 6126 | create_irqchip_unlock: |
| 6082 | 6127 | mutex_unlock(&kvm->lock); |
| 6083 | 6128 | break; |
| @@ -7077,7 +7122,13 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, · 993 unmodified lines | ||
| 7077 | 7122 | unsigned short port, void *val, unsigned int count) |
| 7078 | 7123 | { |
| 7079 | 7124 | if (vcpu->arch.pio.count) { |
| 7080 | − /* Complete previous iteration. */ | |
| 7125 | + /* | |
| 7126 | + * Complete a previous iteration that required userspace I/O. | |
| 7127 | + * Note, @count isn't guaranteed to match pio.count as userspace | |
| 7128 | + * can modify ECX before rerunning the vCPU. Ignore any such | |
| 7129 | + * shenanigans as KVM doesn't support modifying the rep count, | |
| 7130 | + * and the emulator ensures @count doesn't overflow the buffer. | |
| 7131 | + */ | |
| 7081 | 7132 | } else { |
| 7082 | 7133 | int r = __emulator_pio_in(vcpu, size, port, count); |
| 7083 | 7134 | if (!r) |
| @@ -7086,7 +7137,6 @@ static int emulator_pio_in(struct kvm_vcpu *vcpu, int size, · 2 unmodified lines | ||
| 7086 | 7137 | /* Results already available, fall through. */ |
| 7087 | 7138 | } |
| 7088 | 7139 | |
| 7089 | − WARN_ON(count != vcpu->arch.pio.count); | |
| 7090 | 7140 | complete_emulator_pio_in(vcpu, val); |
| 7091 | 7141 | return 1; |
| 7092 | 7142 | } |
| @@ -8776,10 +8826,9 @@ static void kvm_apicv_init(struct kvm *kvm) · 1683 unmodified lines | ||
| 8776 | 8826 | { |
| 8777 | 8827 | init_rwsem(&kvm->arch.apicv_update_lock); |
| 8778 | 8828 | |
| 8779 | − if (enable_apicv) | |
| 8780 | − clear_bit(APICV_INHIBIT_REASON_DISABLE, | |
| 8781 | − &kvm->arch.apicv_inhibit_reasons); | |
| 8782 | − else | |
| 8829 | + set_bit(APICV_INHIBIT_REASON_ABSENT, | |
| 8830 | + &kvm->arch.apicv_inhibit_reasons); | |
| 8831 | + if (!enable_apicv) | |
| 8783 | 8832 | set_bit(APICV_INHIBIT_REASON_DISABLE, |
| 8784 | 8833 | &kvm->arch.apicv_inhibit_reasons); |
| 8785 | 8834 | } |
| @@ -9528,8 +9577,7 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu) · 742 unmodified lines | ||
| 9528 | 9577 | if (irqchip_split(vcpu->kvm)) |
| 9529 | 9578 | kvm_scan_ioapic_routes(vcpu, vcpu->arch.ioapic_handled_vectors); |
| 9530 | 9579 | else { |
| 9531 | − if (vcpu->arch.apicv_active) | |
| 9532 | − static_call(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 9580 | + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 9533 | 9581 | if (ioapic_in_kernel(vcpu->kvm)) |
| 9534 | 9582 | kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors); |
| 9535 | 9583 | } |
| @@ -9648,10 +9696,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 112 unmodified lines | ||
| 9648 | 9696 | /* Flushing all ASIDs flushes the current ASID... */ |
| 9649 | 9697 | kvm_clear_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); |
| 9650 | 9698 | } |
| 9651 | − if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) | |
| 9652 | − kvm_vcpu_flush_tlb_current(vcpu); | |
| 9653 | − if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) | |
| 9654 | − kvm_vcpu_flush_tlb_guest(vcpu); | |
| 9699 | + kvm_service_local_tlb_flush_requests(vcpu); | |
| 9655 | 9700 | |
| 9656 | 9701 | if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) { |
| 9657 | 9702 | vcpu->run->exit_reason = KVM_EXIT_TPR_ACCESS; |
| @@ -9802,10 +9847,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 144 unmodified lines | ||
| 9802 | 9847 | |
| 9803 | 9848 | /* |
| 9804 | 9849 | * This handles the case where a posted interrupt was |
| 9805 | − * notified with kvm_vcpu_kick. | |
| 9850 | + * notified with kvm_vcpu_kick. Assigned devices can | |
| 9851 | + * use the POSTED_INTR_VECTOR even if APICv is disabled, | |
| 9852 | + * so do it even if APICv is disabled on this vCPU. | |
| 9806 | 9853 | */ |
| 9807 | − if (kvm_lapic_enabled(vcpu) && vcpu->arch.apicv_active) | |
| 9808 | − static_call(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 9854 | + if (kvm_lapic_enabled(vcpu)) | |
| 9855 | + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 9809 | 9856 | |
| 9810 | 9857 | if (kvm_vcpu_exit_request(vcpu)) { |
| 9811 | 9858 | vcpu->mode = OUTSIDE_GUEST_MODE; |
| @@ -9849,8 +9896,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 37 unmodified lines | ||
| 9849 | 9896 | if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST)) |
| 9850 | 9897 | break; |
| 9851 | 9898 | |
| 9852 | − if (vcpu->arch.apicv_active) | |
| 9853 | − static_call(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 9899 | + if (kvm_lapic_enabled(vcpu)) | |
| 9900 | + static_call_cond(kvm_x86_sync_pir_to_irr)(vcpu); | |
| 9854 | 9901 | |
| 9855 | 9902 | if (unlikely(kvm_vcpu_exit_request(vcpu))) { |
| 9856 | 9903 | exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED; |
| @@ -103,6 +103,7 @@ static inline unsigned int __shrink_ple_window(unsigned int val, · 102 unmodified lines | ||
| 103 | 103 | |
| 104 | 104 | #define MSR_IA32_CR_PAT_DEFAULT 0x0007040600070406ULL |
| 105 | 105 | |
| 106 | +void kvm_service_local_tlb_flush_requests(struct kvm_vcpu *vcpu); | |
| 106 | 107 | int kvm_check_nested_events(struct kvm_vcpu *vcpu); |
| 107 | 108 | |
| 108 | 109 | static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu) |
| @@ -185,12 +186,6 @@ static inline bool mmu_is_nested(struct kvm_vcpu *vcpu) · 76 unmodified lines | ||
| 185 | 186 | return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu; |
| 186 | 187 | } |
| 187 | 188 | |
| 188 | −static inline void kvm_vcpu_flush_tlb_current(struct kvm_vcpu *vcpu) | |
| 189 | −{ | |
| 190 | − ++vcpu->stat.tlb_flush; | |
| 191 | − static_call(kvm_x86_tlb_flush_current)(vcpu); | |
| 192 | −} | |
| 193 | − | |
| 194 | 189 | static inline int is_pae(struct kvm_vcpu *vcpu) |
| 195 | 190 | { |
| 196 | 191 | return kvm_read_cr4_bits(vcpu, X86_CR4_PAE); |
| @@ -277,7 +277,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size) · 276 unmodified lines | ||
| 277 | 277 | return; |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | − new = early_memremap(data.phys_map, data.size); | |
| 280 | + new = early_memremap_prot(data.phys_map, data.size, | |
| 281 | + pgprot_val(pgprot_encrypted(FIXMAP_PAGE_NORMAL))); | |
| 281 | 282 | if (!new) { |
| 282 | 283 | pr_err("Failed to map new boot services memmap\n"); |
| 283 | 284 | return; |
| @@ -72,6 +72,7 @@ static void __init setup_real_mode(void) · 71 unmodified lines | ||
| 72 | 72 | #ifdef CONFIG_X86_64 |
| 73 | 73 | u64 *trampoline_pgd; |
| 74 | 74 | u64 efer; |
| 75 | + int i; | |
| 75 | 76 | #endif |
| 76 | 77 | |
| 77 | 78 | base = (unsigned char *)real_mode_header; |
| @@ -128,8 +129,17 @@ static void __init setup_real_mode(void) · 50 unmodified lines | ||
| 128 | 129 | trampoline_header->flags = 0; |
| 129 | 130 | |
| 130 | 131 | trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); |
| 132 | + | |
| 133 | + /* Map the real mode stub as virtual == physical */ | |
| 131 | 134 | trampoline_pgd[0] = trampoline_pgd_entry.pgd; |
| 132 | − trampoline_pgd[511] = init_top_pgt[511].pgd; | |
| 135 | + | |
| 136 | + /* | |
| 137 | + * Include the entirety of the kernel mapping into the trampoline | |
| 138 | + * PGD. This way, all mappings present in the normal kernel page | |
| 139 | + * tables are usable while running on trampoline_pgd. | |
| 140 | + */ | |
| 141 | + for (i = pgd_index(__PAGE_OFFSET); i < PTRS_PER_PGD; i++) | |
| 142 | + trampoline_pgd[i] = init_top_pgt[i].pgd; | |
| 133 | 143 | #endif |
| 134 | 144 | |
| 135 | 145 | sme_sev_setup_real_mode(trampoline_header); |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | #include <linux/init.h> |
| 22 | 22 | #include <linux/linkage.h> |
| 23 | +#include <../entry/calling.h> | |
| 23 | 24 | |
| 24 | 25 | .pushsection .noinstr.text, "ax" |
| 25 | 26 | /* |
| @@ -192,6 +193,25 @@ SYM_CODE_START(xen_iret) · 166 unmodified lines | ||
| 192 | 193 | jmp hypercall_iret |
| 193 | 194 | SYM_CODE_END(xen_iret) |
| 194 | 195 | |
| 196 | +/* | |
| 197 | + * XEN pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is | |
| 198 | + * also the kernel stack. Reusing swapgs_restore_regs_and_return_to_usermode() | |
| 199 | + * in XEN pv would cause %rsp to move up to the top of the kernel stack and | |
| 200 | + * leave the IRET frame below %rsp, which is dangerous to be corrupted if #NMI | |
| 201 | + * interrupts. And swapgs_restore_regs_and_return_to_usermode() pushing the IRET | |
| 202 | + * frame at the same address is useless. | |
| 203 | + */ | |
| 204 | +SYM_CODE_START(xenpv_restore_regs_and_return_to_usermode) | |
| 205 | + UNWIND_HINT_REGS | |
| 206 | + POP_REGS | |
| 207 | + | |
| 208 | + /* stackleak_erase() can work safely on the kernel stack. */ | |
| 209 | + STACKLEAK_ERASE_NOCLOBBER | |
| 210 | + | |
| 211 | + addq $8, %rsp /* skip regs->orig_ax */ | |
| 212 | + jmp xen_iret | |
| 213 | +SYM_CODE_END(xenpv_restore_regs_and_return_to_usermode) | |
| 214 | + | |
| 195 | 215 | /* |
| 196 | 216 | * Xen handles syscall callbacks much like ordinary exceptions, which |
| 197 | 217 | * means we have: |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/falloc.h> |
| 16 | 16 | #include <linux/suspend.h> |
| 17 | 17 | #include <linux/fs.h> |
| 18 | +#include <linux/module.h> | |
| 18 | 19 | #include "blk.h" |
| 19 | 20 | |
| 20 | 21 | static inline struct inode *bdev_file_inode(struct file *file) |
| @@ -340,8 +341,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb, · 319 unmodified lines | ||
| 340 | 341 | } else { |
| 341 | 342 | ret = bio_iov_iter_get_pages(bio, iter); |
| 342 | 343 | if (unlikely(ret)) { |
| 343 | − bio->bi_status = BLK_STS_IOERR; | |
| 344 | − bio_endio(bio); | |
| 344 | + bio_put(bio); | |
| 345 | 345 | return ret; |
| 346 | 346 | } |
| 347 | 347 | } |
| @@ -220,6 +220,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) · 219 unmodified lines | ||
| 220 | 220 | pgrp = task_pgrp(current); |
| 221 | 221 | else |
| 222 | 222 | pgrp = find_vpid(who); |
| 223 | + read_lock(&tasklist_lock); | |
| 223 | 224 | do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { |
| 224 | 225 | tmpio = get_task_ioprio(p); |
| 225 | 226 | if (tmpio < 0) |
| @@ -229,6 +230,8 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) · 3 unmodified lines | ||
| 229 | 230 | else |
| 230 | 231 | ret = ioprio_best(ret, tmpio); |
| 231 | 232 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
| 233 | + read_unlock(&tasklist_lock); | |
| 234 | + | |
| 232 | 235 | break; |
| 233 | 236 | case IOPRIO_WHO_USER: |
| 234 | 237 | uid = make_kuid(current_user_ns(), who); |
| @@ -4743,23 +4743,20 @@ static int binder_thread_release(struct binder_proc *proc, · 4742 unmodified lines | ||
| 4743 | 4743 | __release(&t->lock); |
| 4744 | 4744 | |
| 4745 | 4745 | /* |
| 4746 | − * If this thread used poll, make sure we remove the waitqueue | |
| 4747 | − * from any epoll data structures holding it with POLLFREE. | |
| 4748 | − * waitqueue_active() is safe to use here because we're holding | |
| 4749 | − * the inner lock. | |
| 4746 | + * If this thread used poll, make sure we remove the waitqueue from any | |
| 4747 | + * poll data structures holding it. | |
| 4750 | 4748 | */ |
| 4751 | − if ((thread->looper & BINDER_LOOPER_STATE_POLL) && | |
| 4752 | − waitqueue_active(&thread->wait)) { | |
| 4753 | − wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE); | |
| 4754 | − } | |
| 4749 | + if (thread->looper & BINDER_LOOPER_STATE_POLL) | |
| 4750 | + wake_up_pollfree(&thread->wait); | |
| 4755 | 4751 | |
| 4756 | 4752 | binder_inner_proc_unlock(thread->proc); |
| 4757 | 4753 | |
| 4758 | 4754 | /* |
| 4759 | − * This is needed to avoid races between wake_up_poll() above and | |
| 4760 | − * and ep_remove_waitqueue() called for other reasons (eg the epoll file | |
| 4761 | − * descriptor being closed); ep_remove_waitqueue() holds an RCU read | |
| 4762 | − * lock, so we can be sure it's done after calling synchronize_rcu(). | |
| 4755 | + * This is needed to avoid races between wake_up_pollfree() above and | |
| 4756 | + * someone else removing the last entry from the queue for other reasons | |
| 4757 | + * (e.g. ep_remove_wait_queue() being called due to an epoll file | |
| 4758 | + * descriptor being closed). Such other users hold an RCU read lock, so | |
| 4759 | + * we can be sure they're done after we call synchronize_rcu(). | |
| 4763 | 4760 | */ |
| 4764 | 4761 | if (thread->looper & BINDER_LOOPER_STATE_POLL) |
| 4765 | 4762 | synchronize_rcu(); |
| @@ -94,6 +94,7 @@ struct ceva_ahci_priv { · 93 unmodified lines | ||
| 94 | 94 | static unsigned int ceva_ahci_read_id(struct ata_device *dev, |
| 95 | 95 | struct ata_taskfile *tf, u16 *id) |
| 96 | 96 | { |
| 97 | + __le16 *__id = (__le16 *)id; | |
| 97 | 98 | u32 err_mask; |
| 98 | 99 | |
| 99 | 100 | err_mask = ata_do_dev_read_id(dev, tf, id); |
| @@ -103,7 +104,7 @@ static unsigned int ceva_ahci_read_id(struct ata_device *dev, · 3 unmodified lines | ||
| 103 | 104 | * Since CEVA controller does not support device sleep feature, we |
| 104 | 105 | * need to clear DEVSLP (bit 8) in word78 of the IDENTIFY DEVICE data. |
| 105 | 106 | */ |
| 106 | − id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8)); | |
| 107 | + __id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8)); | |
| 107 | 108 | |
| 108 | 109 | return 0; |
| 109 | 110 | } |
| @@ -3920,6 +3920,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { · 3919 unmodified lines | ||
| 3920 | 3920 | { "VRFDFC22048UCHC-TE*", NULL, ATA_HORKAGE_NODMA }, |
| 3921 | 3921 | /* Odd clown on sil3726/4726 PMPs */ |
| 3922 | 3922 | { "Config Disk", NULL, ATA_HORKAGE_DISABLE }, |
| 3923 | + /* Similar story with ASMedia 1092 */ | |
| 3924 | + { "ASMT109x- Config", NULL, ATA_HORKAGE_DISABLE }, | |
| 3923 | 3925 | |
| 3924 | 3926 | /* Weird ATAPI devices */ |
| 3925 | 3927 | { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, |
| @@ -827,7 +827,7 @@ static ssize_t ata_scsi_lpm_show(struct device *dev, · 826 unmodified lines | ||
| 827 | 827 | if (ap->target_lpm_policy >= ARRAY_SIZE(ata_lpm_policy_names)) |
| 828 | 828 | return -EINVAL; |
| 829 | 829 | |
| 830 | − return snprintf(buf, PAGE_SIZE, "%s\n", | |
| 830 | + return sysfs_emit(buf, "%s\n", | |
| 831 | 831 | ata_lpm_policy_names[ap->target_lpm_policy]); |
| 832 | 832 | } |
| 833 | 833 | DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR, |
| @@ -55,14 +55,14 @@ static unsigned int pata_falcon_data_xfer(struct ata_queued_cmd *qc, · 54 unmodified lines | ||
| 55 | 55 | /* Transfer multiple of 2 bytes */ |
| 56 | 56 | if (rw == READ) { |
| 57 | 57 | if (swap) |
| 58 | − raw_insw_swapw((u16 *)data_addr, (u16 *)buf, words); | |
| 58 | + raw_insw_swapw(data_addr, (u16 *)buf, words); | |
| 59 | 59 | else |
| 60 | − raw_insw((u16 *)data_addr, (u16 *)buf, words); | |
| 60 | + raw_insw(data_addr, (u16 *)buf, words); | |
| 61 | 61 | } else { |
| 62 | 62 | if (swap) |
| 63 | − raw_outsw_swapw((u16 *)data_addr, (u16 *)buf, words); | |
| 63 | + raw_outsw_swapw(data_addr, (u16 *)buf, words); | |
| 64 | 64 | else |
| 65 | − raw_outsw((u16 *)data_addr, (u16 *)buf, words); | |
| 65 | + raw_outsw(data_addr, (u16 *)buf, words); | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | /* Transfer trailing byte, if any. */ |
| @@ -74,16 +74,16 @@ static unsigned int pata_falcon_data_xfer(struct ata_queued_cmd *qc, · 5 unmodified lines | ||
| 74 | 74 | |
| 75 | 75 | if (rw == READ) { |
| 76 | 76 | if (swap) |
| 77 | − raw_insw_swapw((u16 *)data_addr, (u16 *)pad, 1); | |
| 77 | + raw_insw_swapw(data_addr, (u16 *)pad, 1); | |
| 78 | 78 | else |
| 79 | − raw_insw((u16 *)data_addr, (u16 *)pad, 1); | |
| 79 | + raw_insw(data_addr, (u16 *)pad, 1); | |
| 80 | 80 | *buf = pad[0]; |
| 81 | 81 | } else { |
| 82 | 82 | pad[0] = *buf; |
| 83 | 83 | if (swap) |
| 84 | − raw_outsw_swapw((u16 *)data_addr, (u16 *)pad, 1); | |
| 84 | + raw_outsw_swapw(data_addr, (u16 *)pad, 1); | |
| 85 | 85 | else |
| 86 | − raw_outsw((u16 *)data_addr, (u16 *)pad, 1); | |
| 86 | + raw_outsw(data_addr, (u16 *)pad, 1); | |
| 87 | 87 | } |
| 88 | 88 | words++; |
| 89 | 89 | } |
| @@ -1394,6 +1394,14 @@ static int sata_fsl_init_controller(struct ata_host *host) · 1393 unmodified lines | ||
| 1394 | 1394 | return 0; |
| 1395 | 1395 | } |
| 1396 | 1396 | |
| 1397 | +static void sata_fsl_host_stop(struct ata_host *host) | |
| 1398 | +{ | |
| 1399 | + struct sata_fsl_host_priv *host_priv = host->private_data; | |
| 1400 | + | |
| 1401 | + iounmap(host_priv->hcr_base); | |
| 1402 | + kfree(host_priv); | |
| 1403 | +} | |
| 1404 | + | |
| 1397 | 1405 | /* |
| 1398 | 1406 | * scsi mid-layer and libata interface structures |
| 1399 | 1407 | */ |
| @@ -1426,6 +1434,8 @@ static struct ata_port_operations sata_fsl_ops = { · 26 unmodified lines | ||
| 1426 | 1434 | .port_start = sata_fsl_port_start, |
| 1427 | 1435 | .port_stop = sata_fsl_port_stop, |
| 1428 | 1436 | |
| 1437 | + .host_stop = sata_fsl_host_stop, | |
| 1438 | + | |
| 1429 | 1439 | .pmp_attach = sata_fsl_pmp_attach, |
| 1430 | 1440 | .pmp_detach = sata_fsl_pmp_detach, |
| 1431 | 1441 | }; |
| @@ -1480,9 +1490,9 @@ static int sata_fsl_probe(struct platform_device *ofdev) · 48 unmodified lines | ||
| 1480 | 1490 | host_priv->ssr_base = ssr_base; |
| 1481 | 1491 | host_priv->csr_base = csr_base; |
| 1482 | 1492 | |
| 1483 | − irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); | |
| 1484 | − if (!irq) { | |
| 1485 | − dev_err(&ofdev->dev, "invalid irq from platform\n"); | |
| 1493 | + irq = platform_get_irq(ofdev, 0); | |
| 1494 | + if (irq < 0) { | |
| 1495 | + retval = irq; | |
| 1486 | 1496 | goto error_exit_with_cleanup; |
| 1487 | 1497 | } |
| 1488 | 1498 | host_priv->irq = irq; |
| @@ -1557,10 +1567,6 @@ static int sata_fsl_remove(struct platform_device *ofdev) · 68 unmodified lines | ||
| 1557 | 1567 | |
| 1558 | 1568 | ata_host_detach(host); |
| 1559 | 1569 | |
| 1560 | − irq_dispose_mapping(host_priv->irq); | |
| 1561 | − iounmap(host_priv->hcr_base); | |
| 1562 | − kfree(host_priv); | |
| 1563 | − | |
| 1564 | 1570 | return 0; |
| 1565 | 1571 | } |
| 1566 | 1572 | |
| @@ -2103,7 +2103,7 @@ static int loop_control_remove(int idx) · 2102 unmodified lines | ||
| 2103 | 2103 | int ret; |
| 2104 | 2104 | |
| 2105 | 2105 | if (idx < 0) { |
| 2106 | − pr_warn("deleting an unspecified loop device is not supported.\n"); | |
| 2106 | + pr_warn_once("deleting an unspecified loop device is not supported.\n"); | |
| 2107 | 2107 | return -EINVAL; |
| 2108 | 2108 | } |
| 2109 | 2109 | |
| @@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) · 880 unmodified lines | ||
| 881 | 881 | } |
| 882 | 882 | EXPORT_SYMBOL_GPL(mhi_pm_suspend); |
| 883 | 883 | |
| 884 | −int mhi_pm_resume(struct mhi_controller *mhi_cntrl) | |
| 884 | +static int __mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force) | |
| 885 | 885 | { |
| 886 | 886 | struct mhi_chan *itr, *tmp; |
| 887 | 887 | struct device *dev = &mhi_cntrl->mhi_dev->dev; |
| @@ -898,8 +898,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) · 10 unmodified lines | ||
| 898 | 898 | if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) |
| 899 | 899 | return -EIO; |
| 900 | 900 | |
| 901 | − if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) | |
| 902 | − return -EINVAL; | |
| 901 | + if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) { | |
| 902 | + dev_warn(dev, "Resuming from non M3 state (%s)\n", | |
| 903 | + TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); | |
| 904 | + if (!force) | |
| 905 | + return -EINVAL; | |
| 906 | + } | |
| 903 | 907 | |
| 904 | 908 | /* Notify clients about exiting LPM */ |
| 905 | 909 | list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { |
| @@ -940,8 +944,19 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) · 34 unmodified lines | ||
| 940 | 944 | |
| 941 | 945 | return 0; |
| 942 | 946 | } |
| 947 | + | |
| 948 | +int mhi_pm_resume(struct mhi_controller *mhi_cntrl) | |
| 949 | +{ | |
| 950 | + return __mhi_pm_resume(mhi_cntrl, false); | |
| 951 | +} | |
| 943 | 952 | EXPORT_SYMBOL_GPL(mhi_pm_resume); |
| 944 | 953 | |
| 954 | +int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl) | |
| 955 | +{ | |
| 956 | + return __mhi_pm_resume(mhi_cntrl, true); | |
| 957 | +} | |
| 958 | +EXPORT_SYMBOL_GPL(mhi_pm_resume_force); | |
| 959 | + | |
| 945 | 960 | int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) |
| 946 | 961 | { |
| 947 | 962 | int ret; |
| @@ -20,7 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | #define MHI_PCI_DEFAULT_BAR_NUM 0 |
| 22 | 22 | |
| 23 | −#define MHI_POST_RESET_DELAY_MS 500 | |
| 23 | +#define MHI_POST_RESET_DELAY_MS 2000 | |
| 24 | 24 | |
| 25 | 25 | #define HEALTH_CHECK_PERIOD (HZ * 2) |
| 26 | 26 | |
| @@ -281,7 +281,7 @@ agp_ioc_init(void __iomem *ioc_regs) · 280 unmodified lines | ||
| 281 | 281 | return 0; |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | −static int | |
| 284 | +static int __init | |
| 285 | 285 | lba_find_capability(int cap) |
| 286 | 286 | { |
| 287 | 287 | struct _parisc_agp_info *info = &parisc_agp_info; |
| @@ -366,7 +366,7 @@ fail: · 78 unmodified lines | ||
| 366 | 366 | return error; |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | −static int | |
| 369 | +static int __init | |
| 370 | 370 | find_quicksilver(struct device *dev, void *data) |
| 371 | 371 | { |
| 372 | 372 | struct parisc_device **lba = data; |
| @@ -378,7 +378,7 @@ find_quicksilver(struct device *dev, void *data) · 5 unmodified lines | ||
| 378 | 378 | return 0; |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | −static int | |
| 381 | +static int __init | |
| 382 | 382 | parisc_agp_init(void) |
| 383 | 383 | { |
| 384 | 384 | extern struct sba_device *sba_list; |
| @@ -191,6 +191,8 @@ struct ipmi_user { · 190 unmodified lines | ||
| 191 | 191 | struct work_struct remove_work; |
| 192 | 192 | }; |
| 193 | 193 | |
| 194 | +static struct workqueue_struct *remove_work_wq; | |
| 195 | + | |
| 194 | 196 | static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user, int *index) |
| 195 | 197 | __acquires(user->release_barrier) |
| 196 | 198 | { |
| @@ -1297,7 +1299,7 @@ static void free_user(struct kref *ref) · 1100 unmodified lines | ||
| 1297 | 1299 | struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount); |
| 1298 | 1300 | |
| 1299 | 1301 | /* SRCU cleanup must happen in task context. */ |
| 1300 | − schedule_work(&user->remove_work); | |
| 1302 | + queue_work(remove_work_wq, &user->remove_work); | |
| 1301 | 1303 | } |
| 1302 | 1304 | |
| 1303 | 1305 | static void _ipmi_destroy_user(struct ipmi_user *user) |
| @@ -3918,9 +3920,11 @@ static int handle_ipmb_direct_rcv_cmd(struct ipmi_smi *intf, · 2614 unmodified lines | ||
| 3918 | 3920 | /* We didn't find a user, deliver an error response. */ |
| 3919 | 3921 | ipmi_inc_stat(intf, unhandled_commands); |
| 3920 | 3922 | |
| 3921 | − msg->data[0] = ((netfn + 1) << 2) | (msg->rsp[4] & 0x3); | |
| 3922 | − msg->data[1] = msg->rsp[2]; | |
| 3923 | − msg->data[2] = msg->rsp[4] & ~0x3; | |
| 3923 | + msg->data[0] = (netfn + 1) << 2; | |
| 3924 | + msg->data[0] |= msg->rsp[2] & 0x3; /* rqLUN */ | |
| 3925 | + msg->data[1] = msg->rsp[1]; /* Addr */ | |
| 3926 | + msg->data[2] = msg->rsp[2] & ~0x3; /* rqSeq */ | |
| 3927 | + msg->data[2] |= msg->rsp[0] & 0x3; /* rsLUN */ | |
| 3924 | 3928 | msg->data[3] = cmd; |
| 3925 | 3929 | msg->data[4] = IPMI_INVALID_CMD_COMPLETION_CODE; |
| 3926 | 3930 | msg->data_size = 5; |
| @@ -4455,13 +4459,24 @@ return_unspecified: · 528 unmodified lines | ||
| 4455 | 4459 | msg->rsp[2] = IPMI_ERR_UNSPECIFIED; |
| 4456 | 4460 | msg->rsp_size = 3; |
| 4457 | 4461 | } else if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) { |
| 4458 | − /* commands must have at least 3 bytes, responses 4. */ | |
| 4459 | − if (is_cmd && (msg->rsp_size < 3)) { | |
| 4462 | + /* commands must have at least 4 bytes, responses 5. */ | |
| 4463 | + if (is_cmd && (msg->rsp_size < 4)) { | |
| 4460 | 4464 | ipmi_inc_stat(intf, invalid_commands); |
| 4461 | 4465 | goto out; |
| 4462 | 4466 | } |
| 4463 | − if (!is_cmd && (msg->rsp_size < 4)) | |
| 4464 | − goto return_unspecified; | |
| 4467 | + if (!is_cmd && (msg->rsp_size < 5)) { | |
| 4468 | + ipmi_inc_stat(intf, invalid_ipmb_responses); | |
| 4469 | + /* Construct a valid error response. */ | |
| 4470 | + msg->rsp[0] = msg->data[0] & 0xfc; /* NetFN */ | |
| 4471 | + msg->rsp[0] |= (1 << 2); /* Make it a response */ | |
| 4472 | + msg->rsp[0] |= msg->data[2] & 3; /* rqLUN */ | |
| 4473 | + msg->rsp[1] = msg->data[1]; /* Addr */ | |
| 4474 | + msg->rsp[2] = msg->data[2] & 0xfc; /* rqSeq */ | |
| 4475 | + msg->rsp[2] |= msg->data[0] & 0x3; /* rsLUN */ | |
| 4476 | + msg->rsp[3] = msg->data[3]; /* Cmd */ | |
| 4477 | + msg->rsp[4] = IPMI_ERR_UNSPECIFIED; | |
| 4478 | + msg->rsp_size = 5; | |
| 4479 | + } | |
| 4465 | 4480 | } else if ((msg->data_size >= 2) |
| 4466 | 4481 | && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) |
| 4467 | 4482 | && (msg->data[1] == IPMI_SEND_MSG_CMD) |
| @@ -5031,6 +5046,7 @@ struct ipmi_smi_msg *ipmi_alloc_smi_msg(void) · 563 unmodified lines | ||
| 5031 | 5046 | if (rv) { |
| 5032 | 5047 | rv->done = free_smi_msg; |
| 5033 | 5048 | rv->user_data = NULL; |
| 5049 | + rv->type = IPMI_SMI_MSG_TYPE_NORMAL; | |
| 5034 | 5050 | atomic_inc(&smi_msg_inuse_count); |
| 5035 | 5051 | } |
| 5036 | 5052 | return rv; |
| @@ -5383,6 +5399,13 @@ static int ipmi_init_msghandler(void) · 346 unmodified lines | ||
| 5383 | 5399 | |
| 5384 | 5400 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 5385 | 5401 | |
| 5402 | + remove_work_wq = create_singlethread_workqueue("ipmi-msghandler-remove-wq"); | |
| 5403 | + if (!remove_work_wq) { | |
| 5404 | + pr_err("unable to create ipmi-msghandler-remove-wq workqueue"); | |
| 5405 | + rv = -ENOMEM; | |
| 5406 | + goto out; | |
| 5407 | + } | |
| 5408 | + | |
| 5386 | 5409 | initialized = true; |
| 5387 | 5410 | |
| 5388 | 5411 | out: |
| @@ -5408,6 +5431,8 @@ static void __exit cleanup_ipmi(void) · 19 unmodified lines | ||
| 5408 | 5431 | int count; |
| 5409 | 5432 | |
| 5410 | 5433 | if (initialized) { |
| 5434 | + destroy_workqueue(remove_work_wq); | |
| 5435 | + | |
| 5411 | 5436 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 5412 | 5437 | &panic_block); |
| 5413 | 5438 | |
| @@ -370,7 +370,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = { · 369 unmodified lines | ||
| 370 | 370 | .probe = imx8qxp_lpcg_clk_probe, |
| 371 | 371 | }; |
| 372 | 372 | |
| 373 | −builtin_platform_driver(imx8qxp_lpcg_clk_driver); | |
| 373 | +module_platform_driver(imx8qxp_lpcg_clk_driver); | |
| 374 | 374 | |
| 375 | 375 | MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); |
| 376 | 376 | MODULE_DESCRIPTION("NXP i.MX8QXP LPCG clock driver"); |
| @@ -308,7 +308,7 @@ static struct platform_driver imx8qxp_clk_driver = { · 307 unmodified lines | ||
| 308 | 308 | }, |
| 309 | 309 | .probe = imx8qxp_clk_probe, |
| 310 | 310 | }; |
| 311 | −builtin_platform_driver(imx8qxp_clk_driver); | |
| 311 | +module_platform_driver(imx8qxp_clk_driver); | |
| 312 | 312 | |
| 313 | 313 | MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>"); |
| 314 | 314 | MODULE_DESCRIPTION("NXP i.MX8QXP clock driver"); |
| @@ -1429,6 +1429,15 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); · 1428 unmodified lines | ||
| 1429 | 1429 | void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, |
| 1430 | 1430 | const struct alpha_pll_config *config) |
| 1431 | 1431 | { |
| 1432 | + /* | |
| 1433 | + * If the bootloader left the PLL enabled it's likely that there are | |
| 1434 | + * RCGs that will lock up if we disable the PLL below. | |
| 1435 | + */ | |
| 1436 | + if (trion_pll_is_enabled(pll, regmap)) { | |
| 1437 | + pr_debug("Trion PLL is already enabled, skipping configuration\n"); | |
| 1438 | + return; | |
| 1439 | + } | |
| 1440 | + | |
| 1432 | 1441 | clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); |
| 1433 | 1442 | regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL); |
| 1434 | 1443 | clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); |
| @@ -28,7 +28,7 @@ static u8 mux_get_parent(struct clk_hw *hw) · 27 unmodified lines | ||
| 28 | 28 | val &= mask; |
| 29 | 29 | |
| 30 | 30 | if (mux->parent_map) |
| 31 | − return qcom_find_src_index(hw, mux->parent_map, val); | |
| 31 | + return qcom_find_cfg_index(hw, mux->parent_map, val); | |
| 32 | 32 | |
| 33 | 33 | return val; |
| 34 | 34 | } |
| @@ -69,6 +69,18 @@ int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src) · 68 unmodified lines | ||
| 69 | 69 | } |
| 70 | 70 | EXPORT_SYMBOL_GPL(qcom_find_src_index); |
| 71 | 71 | |
| 72 | +int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, u8 cfg) | |
| 73 | +{ | |
| 74 | + int i, num_parents = clk_hw_get_num_parents(hw); | |
| 75 | + | |
| 76 | + for (i = 0; i < num_parents; i++) | |
| 77 | + if (cfg == map[i].cfg) | |
| 78 | + return i; | |
| 79 | + | |
| 80 | + return -ENOENT; | |
| 81 | +} | |
| 82 | +EXPORT_SYMBOL_GPL(qcom_find_cfg_index); | |
| 83 | + | |
| 72 | 84 | struct regmap * |
| 73 | 85 | qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc) |
| 74 | 86 | { |
| @@ -49,6 +49,8 @@ extern void · 48 unmodified lines | ||
| 49 | 49 | qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count); |
| 50 | 50 | extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, |
| 51 | 51 | u8 src); |
| 52 | +extern int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, | |
| 53 | + u8 cfg); | |
| 52 | 54 | |
| 53 | 55 | extern int qcom_cc_register_board_clk(struct device *dev, const char *path, |
| 54 | 56 | const char *name, unsigned long rate); |
| @@ -1121,7 +1121,7 @@ static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { · 1120 unmodified lines | ||
| 1121 | 1121 | .name = "gcc_sdcc1_apps_clk_src", |
| 1122 | 1122 | .parent_data = gcc_parent_data_1, |
| 1123 | 1123 | .num_parents = ARRAY_SIZE(gcc_parent_data_1), |
| 1124 | − .ops = &clk_rcg2_ops, | |
| 1124 | + .ops = &clk_rcg2_floor_ops, | |
| 1125 | 1125 | }, |
| 1126 | 1126 | }; |
| 1127 | 1127 | |
| @@ -1143,7 +1143,7 @@ static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { · 15 unmodified lines | ||
| 1143 | 1143 | .name = "gcc_sdcc1_ice_core_clk_src", |
| 1144 | 1144 | .parent_data = gcc_parent_data_0, |
| 1145 | 1145 | .num_parents = ARRAY_SIZE(gcc_parent_data_0), |
| 1146 | − .ops = &clk_rcg2_floor_ops, | |
| 1146 | + .ops = &clk_rcg2_ops, | |
| 1147 | 1147 | }, |
| 1148 | 1148 | }; |
| 1149 | 1149 | |
| @@ -543,8 +543,8 @@ static void __init of_syscon_icst_setup(struct device_node *np) · 542 unmodified lines | ||
| 543 | 543 | |
| 544 | 544 | regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map, ctype); |
| 545 | 545 | if (IS_ERR(regclk)) { |
| 546 | − kfree(name); | |
| 547 | 546 | pr_err("error setting up syscon ICST clock %s\n", name); |
| 547 | + kfree(name); | |
| 548 | 548 | return; |
| 549 | 549 | } |
| 550 | 550 | of_clk_add_provider(np, of_clk_src_simple_get, regclk); |
| @@ -394,8 +394,13 @@ EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); · 393 unmodified lines | ||
| 394 | 394 | |
| 395 | 395 | static atomic_t timer_unstable_counter_workaround_in_use = ATOMIC_INIT(0); |
| 396 | 396 | |
| 397 | −static void erratum_set_next_event_generic(const int access, unsigned long evt, | |
| 398 | − struct clock_event_device *clk) | |
| 397 | +/* | |
| 398 | + * Force the inlining of this function so that the register accesses | |
| 399 | + * can be themselves correctly inlined. | |
| 400 | + */ | |
| 401 | +static __always_inline | |
| 402 | +void erratum_set_next_event_generic(const int access, unsigned long evt, | |
| 403 | + struct clock_event_device *clk) | |
| 399 | 404 | { |
| 400 | 405 | unsigned long ctrl; |
| 401 | 406 | u64 cval; |
| @@ -47,7 +47,7 @@ static int __init timer_get_base_and_rate(struct device_node *np, · 46 unmodified lines | ||
| 47 | 47 | pr_warn("pclk for %pOFn is present, but could not be activated\n", |
| 48 | 48 | np); |
| 49 | 49 | |
| 50 | − if (!of_property_read_u32(np, "clock-freq", rate) && | |
| 50 | + if (!of_property_read_u32(np, "clock-freq", rate) || | |
| 51 | 51 | !of_property_read_u32(np, "clock-frequency", rate)) |
| 52 | 52 | return 0; |
| 53 | 53 | |
| @@ -1004,10 +1004,9 @@ static struct kobj_type ktype_cpufreq = { · 1003 unmodified lines | ||
| 1004 | 1004 | .release = cpufreq_sysfs_release, |
| 1005 | 1005 | }; |
| 1006 | 1006 | |
| 1007 | −static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu) | |
| 1007 | +static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu, | |
| 1008 | + struct device *dev) | |
| 1008 | 1009 | { |
| 1009 | − struct device *dev = get_cpu_device(cpu); | |
| 1010 | − | |
| 1011 | 1010 | if (unlikely(!dev)) |
| 1012 | 1011 | return; |
| 1013 | 1012 | |
| @@ -1296,8 +1295,9 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) · 282 unmodified lines | ||
| 1296 | 1295 | |
| 1297 | 1296 | if (policy->max_freq_req) { |
| 1298 | 1297 | /* |
| 1299 | − * CPUFREQ_CREATE_POLICY notification is sent only after | |
| 1300 | − * successfully adding max_freq_req request. | |
| 1298 | + * Remove max_freq_req after sending CPUFREQ_REMOVE_POLICY | |
| 1299 | + * notification, since CPUFREQ_CREATE_POLICY notification was | |
| 1300 | + * sent after adding max_freq_req earlier. | |
| 1301 | 1301 | */ |
| 1302 | 1302 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
| 1303 | 1303 | CPUFREQ_REMOVE_POLICY, policy); |
| @@ -1391,7 +1391,7 @@ static int cpufreq_online(unsigned int cpu) · 87 unmodified lines | ||
| 1391 | 1391 | if (new_policy) { |
| 1392 | 1392 | for_each_cpu(j, policy->related_cpus) { |
| 1393 | 1393 | per_cpu(cpufreq_cpu_data, j) = policy; |
| 1394 | − add_cpu_dev_symlink(policy, j); | |
| 1394 | + add_cpu_dev_symlink(policy, j, get_cpu_device(j)); | |
| 1395 | 1395 | } |
| 1396 | 1396 | |
| 1397 | 1397 | policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req), |
| @@ -1565,7 +1565,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) · 167 unmodified lines | ||
| 1565 | 1565 | /* Create sysfs link on CPU registration */ |
| 1566 | 1566 | policy = per_cpu(cpufreq_cpu_data, cpu); |
| 1567 | 1567 | if (policy) |
| 1568 | − add_cpu_dev_symlink(policy, cpu); | |
| 1568 | + add_cpu_dev_symlink(policy, cpu, dev); | |
| 1569 | 1569 | |
| 1570 | 1570 | return 0; |
| 1571 | 1571 | } |
| @@ -290,7 +290,7 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) · 289 unmodified lines | ||
| 290 | 290 | int i; |
| 291 | 291 | |
| 292 | 292 | table = &buffer->sg_table; |
| 293 | − for_each_sg(table->sgl, sg, table->nents, i) { | |
| 293 | + for_each_sgtable_sg(table, sg, i) { | |
| 294 | 294 | struct page *page = sg_page(sg); |
| 295 | 295 | |
| 296 | 296 | __free_pages(page, compound_order(page)); |
| @@ -1396,7 +1396,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( · 1395 unmodified lines | ||
| 1396 | 1396 | struct sg_table *sg = NULL; |
| 1397 | 1397 | uint64_t user_addr = 0; |
| 1398 | 1398 | struct amdgpu_bo *bo; |
| 1399 | − struct drm_gem_object *gobj; | |
| 1399 | + struct drm_gem_object *gobj = NULL; | |
| 1400 | 1400 | u32 domain, alloc_domain; |
| 1401 | 1401 | u64 alloc_flags; |
| 1402 | 1402 | int ret; |
| @@ -1506,14 +1506,16 @@ allocate_init_user_pages_failed: · 103 unmodified lines | ||
| 1506 | 1506 | remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info); |
| 1507 | 1507 | drm_vma_node_revoke(&gobj->vma_node, drm_priv); |
| 1508 | 1508 | err_node_allow: |
| 1509 | − drm_gem_object_put(gobj); | |
| 1510 | 1509 | /* Don't unreserve system mem limit twice */ |
| 1511 | 1510 | goto err_reserve_limit; |
| 1512 | 1511 | err_bo_create: |
| 1513 | 1512 | unreserve_mem_limit(adev, size, alloc_domain, !!sg); |
| 1514 | 1513 | err_reserve_limit: |
| 1515 | 1514 | mutex_destroy(&(*mem)->lock); |
| 1516 | − kfree(*mem); | |
| 1515 | + if (gobj) | |
| 1516 | + drm_gem_object_put(gobj); | |
| 1517 | + else | |
| 1518 | + kfree(*mem); | |
| 1517 | 1519 | err: |
| 1518 | 1520 | if (sg) { |
| 1519 | 1521 | sg_free_table(sg); |
| @@ -3833,7 +3833,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) · 3832 unmodified lines | ||
| 3833 | 3833 | /* disable all interrupts */ |
| 3834 | 3834 | amdgpu_irq_disable_all(adev); |
| 3835 | 3835 | if (adev->mode_info.mode_config_initialized){ |
| 3836 | − if (!amdgpu_device_has_dc_support(adev)) | |
| 3836 | + if (!drm_drv_uses_atomic_modeset(adev_to_drm(adev))) | |
| 3837 | 3837 | drm_helper_force_disable_all(adev_to_drm(adev)); |
| 3838 | 3838 | else |
| 3839 | 3839 | drm_atomic_helper_shutdown(adev_to_drm(adev)); |
| @@ -4289,6 +4289,8 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, · 449 unmodified lines | ||
| 4289 | 4289 | { |
| 4290 | 4290 | int r; |
| 4291 | 4291 | |
| 4292 | + amdgpu_amdkfd_pre_reset(adev); | |
| 4293 | + | |
| 4292 | 4294 | if (from_hypervisor) |
| 4293 | 4295 | r = amdgpu_virt_request_full_gpu(adev, true); |
| 4294 | 4296 | else |
| @@ -4316,6 +4318,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, · 21 unmodified lines | ||
| 4316 | 4318 | |
| 4317 | 4319 | amdgpu_irq_gpu_reset_resume_helper(adev); |
| 4318 | 4320 | r = amdgpu_ib_ring_tests(adev); |
| 4321 | + amdgpu_amdkfd_post_reset(adev); | |
| 4319 | 4322 | |
| 4320 | 4323 | error: |
| 4321 | 4324 | if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) { |
| @@ -5030,7 +5033,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, · 708 unmodified lines | ||
| 5030 | 5033 | |
| 5031 | 5034 | cancel_delayed_work_sync(&tmp_adev->delayed_init_work); |
| 5032 | 5035 | |
| 5033 | − amdgpu_amdkfd_pre_reset(tmp_adev); | |
| 5036 | + if (!amdgpu_sriov_vf(tmp_adev)) | |
| 5037 | + amdgpu_amdkfd_pre_reset(tmp_adev); | |
| 5034 | 5038 | |
| 5035 | 5039 | /* |
| 5036 | 5040 | * Mark these ASICs to be reseted as untracked first |
| @@ -5129,7 +5133,7 @@ skip_hw_reset: · 92 unmodified lines | ||
| 5129 | 5133 | drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res); |
| 5130 | 5134 | } |
| 5131 | 5135 | |
| 5132 | − if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { | |
| 5136 | + if (!drm_drv_uses_atomic_modeset(adev_to_drm(tmp_adev)) && !job_signaled) { | |
| 5133 | 5137 | drm_helper_resume_force_mode(adev_to_drm(tmp_adev)); |
| 5134 | 5138 | } |
| 5135 | 5139 | |
| @@ -5148,9 +5152,9 @@ skip_hw_reset: · 12 unmodified lines | ||
| 5148 | 5152 | |
| 5149 | 5153 | skip_sched_resume: |
| 5150 | 5154 | list_for_each_entry(tmp_adev, device_list_handle, reset_list) { |
| 5151 | − /* unlock kfd */ | |
| 5152 | − if (!need_emergency_restart) | |
| 5153 | − amdgpu_amdkfd_post_reset(tmp_adev); | |
| 5155 | + /* unlock kfd: SRIOV would do it separately */ | |
| 5156 | + if (!need_emergency_restart && !amdgpu_sriov_vf(tmp_adev)) | |
| 5157 | + amdgpu_amdkfd_post_reset(tmp_adev); | |
| 5154 | 5158 | |
| 5155 | 5159 | /* kfd_post_reset will do nothing if kfd device is not initialized, |
| 5156 | 5160 | * need to bring up kfd here if it's not be initialized before |
| @@ -157,6 +157,8 @@ static int hw_id_map[MAX_HWIP] = { · 156 unmodified lines | ||
| 157 | 157 | [HDP_HWIP] = HDP_HWID, |
| 158 | 158 | [SDMA0_HWIP] = SDMA0_HWID, |
| 159 | 159 | [SDMA1_HWIP] = SDMA1_HWID, |
| 160 | + [SDMA2_HWIP] = SDMA2_HWID, | |
| 161 | + [SDMA3_HWIP] = SDMA3_HWID, | |
| 160 | 162 | [MMHUB_HWIP] = MMHUB_HWID, |
| 161 | 163 | [ATHUB_HWIP] = ATHUB_HWID, |
| 162 | 164 | [NBIO_HWIP] = NBIF_HWID, |
| @@ -918,6 +920,7 @@ static int amdgpu_discovery_set_mm_ip_blocks(struct amdgpu_device *adev) · 755 unmodified lines | ||
| 918 | 920 | case IP_VERSION(3, 0, 64): |
| 919 | 921 | case IP_VERSION(3, 1, 1): |
| 920 | 922 | case IP_VERSION(3, 0, 2): |
| 923 | + case IP_VERSION(3, 0, 192): | |
| 921 | 924 | amdgpu_device_ip_block_add(adev, &vcn_v3_0_ip_block); |
| 922 | 925 | if (!amdgpu_sriov_vf(adev)) |
| 923 | 926 | amdgpu_device_ip_block_add(adev, &jpeg_v3_0_ip_block); |
| @@ -135,6 +135,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) · 134 unmodified lines | ||
| 135 | 135 | break; |
| 136 | 136 | case IP_VERSION(3, 0, 0): |
| 137 | 137 | case IP_VERSION(3, 0, 64): |
| 138 | + case IP_VERSION(3, 0, 192): | |
| 138 | 139 | if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 0)) |
| 139 | 140 | fw_name = FIRMWARE_SIENNA_CICHLID; |
| 140 | 141 | else |
| @@ -504,8 +504,8 @@ static int amdgpu_vkms_sw_fini(void *handle) · 503 unmodified lines | ||
| 504 | 504 | int i = 0; |
| 505 | 505 | |
| 506 | 506 | for (i = 0; i < adev->mode_info.num_crtc; i++) |
| 507 | − if (adev->mode_info.crtcs[i]) | |
| 508 | − hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); | |
| 507 | + if (adev->amdgpu_vkms_output[i].vblank_hrtimer.function) | |
| 508 | + hrtimer_cancel(&adev->amdgpu_vkms_output[i].vblank_hrtimer); | |
| 509 | 509 | |
| 510 | 510 | kfree(adev->mode_info.bios_hardcoded_edid); |
| 511 | 511 | kfree(adev->amdgpu_vkms_output); |
| @@ -4060,9 +4060,10 @@ static int gfx_v9_0_hw_fini(void *handle) · 4059 unmodified lines | ||
| 4060 | 4060 | |
| 4061 | 4061 | gfx_v9_0_cp_enable(adev, false); |
| 4062 | 4062 | |
| 4063 | − /* Skip suspend with A+A reset */ | |
| 4064 | − if (adev->gmc.xgmi.connected_to_cpu && amdgpu_in_reset(adev)) { | |
| 4065 | − dev_dbg(adev->dev, "Device in reset. Skipping RLC halt\n"); | |
| 4063 | + /* Skip stopping RLC with A+A reset or when RLC controls GFX clock */ | |
| 4064 | + if ((adev->gmc.xgmi.connected_to_cpu && amdgpu_in_reset(adev)) || | |
| 4065 | + (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2))) { | |
| 4066 | + dev_dbg(adev->dev, "Skipping RLC halt\n"); | |
| 4066 | 4067 | return 0; |
| 4067 | 4068 | } |
| 4068 | 4069 | |
| @@ -183,6 +183,7 @@ static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode, · 182 unmodified lines | ||
| 183 | 183 | switch (adev->ip_versions[UVD_HWIP][0]) { |
| 184 | 184 | case IP_VERSION(3, 0, 0): |
| 185 | 185 | case IP_VERSION(3, 0, 64): |
| 186 | + case IP_VERSION(3, 0, 192): | |
| 186 | 187 | if (amdgpu_sriov_vf(adev)) { |
| 187 | 188 | if (encode) |
| 188 | 189 | *codecs = &sriov_sc_video_codecs_encode; |
| @@ -1574,7 +1574,6 @@ retry_flush_work: · 1573 unmodified lines | ||
| 1574 | 1574 | static void svm_range_restore_work(struct work_struct *work) |
| 1575 | 1575 | { |
| 1576 | 1576 | struct delayed_work *dwork = to_delayed_work(work); |
| 1577 | − struct amdkfd_process_info *process_info; | |
| 1578 | 1577 | struct svm_range_list *svms; |
| 1579 | 1578 | struct svm_range *prange; |
| 1580 | 1579 | struct kfd_process *p; |
| @@ -1594,12 +1593,10 @@ static void svm_range_restore_work(struct work_struct *work) · 13 unmodified lines | ||
| 1594 | 1593 | * the lifetime of this thread, kfd_process and mm will be valid. |
| 1595 | 1594 | */ |
| 1596 | 1595 | p = container_of(svms, struct kfd_process, svms); |
| 1597 | − process_info = p->kgd_process_info; | |
| 1598 | 1596 | mm = p->mm; |
| 1599 | 1597 | if (!mm) |
| 1600 | 1598 | return; |
| 1601 | 1599 | |
| 1602 | − mutex_lock(&process_info->lock); | |
| 1603 | 1600 | svm_range_list_lock_and_flush_work(svms, mm); |
| 1604 | 1601 | mutex_lock(&svms->lock); |
| 1605 | 1602 | |
| @@ -1652,7 +1649,6 @@ static void svm_range_restore_work(struct work_struct *work) · 46 unmodified lines | ||
| 1652 | 1649 | out_reschedule: |
| 1653 | 1650 | mutex_unlock(&svms->lock); |
| 1654 | 1651 | mmap_write_unlock(mm); |
| 1655 | − mutex_unlock(&process_info->lock); | |
| 1656 | 1652 | |
| 1657 | 1653 | /* If validation failed, reschedule another attempt */ |
| 1658 | 1654 | if (evicted_ranges) { |
| @@ -2614,6 +2610,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, · 955 unmodified lines | ||
| 2614 | 2610 | |
| 2615 | 2611 | if (atomic_read(&svms->drain_pagefaults)) { |
| 2616 | 2612 | pr_debug("draining retry fault, drop fault 0x%llx\n", addr); |
| 2613 | + r = 0; | |
| 2617 | 2614 | goto out; |
| 2618 | 2615 | } |
| 2619 | 2616 | |
| @@ -2623,6 +2620,7 @@ svm_range_restore_pages(struct amdgpu_device *adev, unsigned int pasid, · 3 unmodified lines | ||
| 2623 | 2620 | mm = get_task_mm(p->lead_thread); |
| 2624 | 2621 | if (!mm) { |
| 2625 | 2622 | pr_debug("svms 0x%p failed to get mm\n", svms); |
| 2623 | + r = 0; | |
| 2626 | 2624 | goto out; |
| 2627 | 2625 | } |
| 2628 | 2626 | |
| @@ -2660,6 +2658,7 @@ retry_write_locked: · 31 unmodified lines | ||
| 2660 | 2658 | |
| 2661 | 2659 | if (svm_range_skip_recover(prange)) { |
| 2662 | 2660 | amdgpu_gmc_filter_faults_remove(adev, addr, pasid); |
| 2661 | + r = 0; | |
| 2663 | 2662 | goto out_unlock_range; |
| 2664 | 2663 | } |
| 2665 | 2664 | |
| @@ -2668,6 +2667,7 @@ retry_write_locked: · 2 unmodified lines | ||
| 2668 | 2667 | if (timestamp < AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING) { |
| 2669 | 2668 | pr_debug("svms 0x%p [0x%lx %lx] already restored\n", |
| 2670 | 2669 | svms, prange->start, prange->last); |
| 2670 | + r = 0; | |
| 2671 | 2671 | goto out_unlock_range; |
| 2672 | 2672 | } |
| 2673 | 2673 | |
| @@ -3177,7 +3177,6 @@ static int · 503 unmodified lines | ||
| 3177 | 3177 | svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, |
| 3178 | 3178 | uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) |
| 3179 | 3179 | { |
| 3180 | − struct amdkfd_process_info *process_info = p->kgd_process_info; | |
| 3181 | 3180 | struct mm_struct *mm = current->mm; |
| 3182 | 3181 | struct list_head update_list; |
| 3183 | 3182 | struct list_head insert_list; |
| @@ -3196,8 +3195,6 @@ svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, · 12 unmodified lines | ||
| 3196 | 3195 | |
| 3197 | 3196 | svms = &p->svms; |
| 3198 | 3197 | |
| 3199 | − mutex_lock(&process_info->lock); | |
| 3200 | − | |
| 3201 | 3198 | svm_range_list_lock_and_flush_work(svms, mm); |
| 3202 | 3199 | |
| 3203 | 3200 | r = svm_range_is_valid(p, start, size); |
| @@ -3273,8 +3270,6 @@ out_unlock_range: · 69 unmodified lines | ||
| 3273 | 3270 | mutex_unlock(&svms->lock); |
| 3274 | 3271 | mmap_read_unlock(mm); |
| 3275 | 3272 | out: |
| 3276 | − mutex_unlock(&process_info->lock); | |
| 3277 | − | |
| 3278 | 3273 | pr_debug("pasid 0x%x svms 0x%p [0x%llx 0x%llx] done, r=%d\n", p->pasid, |
| 3279 | 3274 | &p->svms, start, start + size - 1, r); |
| 3280 | 3275 | |
| @@ -2576,7 +2576,8 @@ static int dm_resume(void *handle) · 2575 unmodified lines | ||
| 2576 | 2576 | */ |
| 2577 | 2577 | link_enc_cfg_init(dm->dc, dc_state); |
| 2578 | 2578 | |
| 2579 | − amdgpu_dm_outbox_init(adev); | |
| 2579 | + if (dc_enable_dmub_notifications(adev->dm.dc)) | |
| 2580 | + amdgpu_dm_outbox_init(adev); | |
| 2580 | 2581 | |
| 2581 | 2582 | r = dm_dmub_hw_init(adev); |
| 2582 | 2583 | if (r) |
| @@ -2625,6 +2626,10 @@ static int dm_resume(void *handle) · 42 unmodified lines | ||
| 2625 | 2626 | /* TODO: Remove dc_state->dccg, use dc->dccg directly. */ |
| 2626 | 2627 | dc_resource_state_construct(dm->dc, dm_state->context); |
| 2627 | 2628 | |
| 2629 | + /* Re-enable outbox interrupts for DPIA. */ | |
| 2630 | + if (dc_enable_dmub_notifications(adev->dm.dc)) | |
| 2631 | + amdgpu_dm_outbox_init(adev); | |
| 2632 | + | |
| 2628 | 2633 | /* Before powering on DC we need to re-initialize DMUB. */ |
| 2629 | 2634 | r = dm_dmub_hw_init(adev); |
| 2630 | 2635 | if (r) |
| @@ -314,6 +314,14 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name) · 313 unmodified lines | ||
| 314 | 314 | ret = -EINVAL; |
| 315 | 315 | goto cleanup; |
| 316 | 316 | } |
| 317 | + | |
| 318 | + if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) && | |
| 319 | + (aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) { | |
| 320 | + DRM_DEBUG_DRIVER("No DP connector available for CRC source\n"); | |
| 321 | + ret = -EINVAL; | |
| 322 | + goto cleanup; | |
| 323 | + } | |
| 324 | + | |
| 317 | 325 | } |
| 318 | 326 | |
| 319 | 327 | #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) |
| @@ -36,6 +36,8 @@ · 35 unmodified lines | ||
| 36 | 36 | #include "dm_helpers.h" |
| 37 | 37 | |
| 38 | 38 | #include "dc_link_ddc.h" |
| 39 | +#include "ddc_service_types.h" | |
| 40 | +#include "dpcd_defs.h" | |
| 39 | 41 | |
| 40 | 42 | #include "i2caux_interface.h" |
| 41 | 43 | #include "dmub_cmd.h" |
| @@ -157,6 +159,16 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { · 115 unmodified lines | ||
| 157 | 159 | }; |
| 158 | 160 | |
| 159 | 161 | #if defined(CONFIG_DRM_AMD_DC_DCN) |
| 162 | +static bool needs_dsc_aux_workaround(struct dc_link *link) | |
| 163 | +{ | |
| 164 | + if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && | |
| 165 | + (link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) && | |
| 166 | + link->dpcd_caps.sink_count.bits.SINK_COUNT >= 2) | |
| 167 | + return true; | |
| 168 | + | |
| 169 | + return false; | |
| 170 | +} | |
| 171 | + | |
| 160 | 172 | static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector) |
| 161 | 173 | { |
| 162 | 174 | struct dc_sink *dc_sink = aconnector->dc_sink; |
| @@ -166,7 +178,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto · 3 unmodified lines | ||
| 166 | 178 | u8 *dsc_branch_dec_caps = NULL; |
| 167 | 179 | |
| 168 | 180 | aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port); |
| 169 | −#if defined(CONFIG_HP_HOOK_WORKAROUND) | |
| 181 | + | |
| 170 | 182 | /* |
| 171 | 183 | * drm_dp_mst_dsc_aux_for_port() will return NULL for certain configs |
| 172 | 184 | * because it only check the dsc/fec caps of the "port variable" and not the dock |
| @@ -176,10 +188,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto · 3 unmodified lines | ||
| 176 | 188 | * Workaround: explicitly check the use case above and use the mst dock's aux as dsc_aux |
| 177 | 189 | * |
| 178 | 190 | */ |
| 179 | − | |
| 180 | − if (!aconnector->dsc_aux && !port->parent->port_parent) | |
| 191 | + if (!aconnector->dsc_aux && !port->parent->port_parent && | |
| 192 | + needs_dsc_aux_workaround(aconnector->dc_link)) | |
| 181 | 193 | aconnector->dsc_aux = &aconnector->mst_port->dm_dp_aux.aux; |
| 182 | −#endif | |
| 194 | + | |
| 183 | 195 | if (!aconnector->dsc_aux) |
| 184 | 196 | return false; |
| 185 | 197 | |
| @@ -758,6 +758,18 @@ static bool detect_dp(struct dc_link *link, · 757 unmodified lines | ||
| 758 | 758 | dal_ddc_service_set_transaction_type(link->ddc, |
| 759 | 759 | sink_caps->transaction_type); |
| 760 | 760 | |
| 761 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 762 | + /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock | |
| 763 | + * reports DSC support. | |
| 764 | + */ | |
| 765 | + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && | |
| 766 | + link->type == dc_connection_mst_branch && | |
| 767 | + link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && | |
| 768 | + link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && | |
| 769 | + !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) | |
| 770 | + link->wa_flags.dpia_mst_dsc_always_on = true; | |
| 771 | +#endif | |
| 772 | + | |
| 761 | 773 | #if defined(CONFIG_DRM_AMD_DC_HDCP) |
| 762 | 774 | /* In case of fallback to SST when topology discovery below fails |
| 763 | 775 | * HDCP caps will be querried again later by the upper layer (caller |
| @@ -1203,6 +1215,10 @@ static bool dc_link_detect_helper(struct dc_link *link, · 439 unmodified lines | ||
| 1203 | 1215 | LINK_INFO("link=%d, mst branch is now Disconnected\n", |
| 1204 | 1216 | link->link_index); |
| 1205 | 1217 | |
| 1218 | + /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */ | |
| 1219 | + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) | |
| 1220 | + link->wa_flags.dpia_mst_dsc_always_on = false; | |
| 1221 | + | |
| 1206 | 1222 | dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); |
| 1207 | 1223 | |
| 1208 | 1224 | link->mst_stream_alloc_table.stream_count = 0; |
| @@ -2138,7 +2138,7 @@ static enum link_training_result dp_perform_8b_10b_link_training( · 2137 unmodified lines | ||
| 2138 | 2138 | } |
| 2139 | 2139 | |
| 2140 | 2140 | for (lane = 0; lane < (uint8_t)lt_settings->link_settings.lane_count; lane++) |
| 2141 | − lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET = VOLTAGE_SWING_LEVEL0; | |
| 2141 | + lt_settings->dpcd_lane_settings[lane].raw = 0; | |
| 2142 | 2142 | } |
| 2143 | 2143 | |
| 2144 | 2144 | if (status == LINK_TRAINING_SUCCESS) { |
| @@ -1664,6 +1664,10 @@ bool dc_is_stream_unchanged( · 1663 unmodified lines | ||
| 1664 | 1664 | if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param) |
| 1665 | 1665 | return false; |
| 1666 | 1666 | |
| 1667 | + // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks | |
| 1668 | + if (old_stream->audio_info.mode_count != stream->audio_info.mode_count) | |
| 1669 | + return false; | |
| 1670 | + | |
| 1667 | 1671 | return true; |
| 1668 | 1672 | } |
| 1669 | 1673 | |
| @@ -2252,16 +2256,6 @@ enum dc_status dc_validate_global_state( · 582 unmodified lines | ||
| 2252 | 2256 | |
| 2253 | 2257 | if (!new_ctx) |
| 2254 | 2258 | return DC_ERROR_UNEXPECTED; |
| 2255 | −#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 2256 | − | |
| 2257 | − /* | |
| 2258 | − * Update link encoder to stream assignment. | |
| 2259 | − * TODO: Split out reason allocation from validation. | |
| 2260 | − */ | |
| 2261 | − if (dc->res_pool->funcs->link_encs_assign && fast_validate == false) | |
| 2262 | − dc->res_pool->funcs->link_encs_assign( | |
| 2263 | − dc, new_ctx, new_ctx->streams, new_ctx->stream_count); | |
| 2264 | −#endif | |
| 2265 | 2259 | |
| 2266 | 2260 | if (dc->res_pool->funcs->validate_global) { |
| 2267 | 2261 | result = dc->res_pool->funcs->validate_global(dc, new_ctx); |
| @@ -2313,6 +2307,16 @@ enum dc_status dc_validate_global_state( · 45 unmodified lines | ||
| 2313 | 2307 | if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate)) |
| 2314 | 2308 | result = DC_FAIL_BANDWIDTH_VALIDATE; |
| 2315 | 2309 | |
| 2310 | +#if defined(CONFIG_DRM_AMD_DC_DCN) | |
| 2311 | + /* | |
| 2312 | + * Only update link encoder to stream assignment after bandwidth validation passed. | |
| 2313 | + * TODO: Split out assignment and validation. | |
| 2314 | + */ | |
| 2315 | + if (result == DC_OK && dc->res_pool->funcs->link_encs_assign && fast_validate == false) | |
| 2316 | + dc->res_pool->funcs->link_encs_assign( | |
| 2317 | + dc, new_ctx, new_ctx->streams, new_ctx->stream_count); | |
| 2318 | +#endif | |
| 2319 | + | |
| 2316 | 2320 | return result; |
| 2317 | 2321 | } |
| 2318 | 2322 | |
| @@ -508,7 +508,8 @@ union dpia_debug_options { · 507 unmodified lines | ||
| 508 | 508 | uint32_t disable_dpia:1; |
| 509 | 509 | uint32_t force_non_lttpr:1; |
| 510 | 510 | uint32_t extend_aux_rd_interval:1; |
| 511 | − uint32_t reserved:29; | |
| 511 | + uint32_t disable_mst_dsc_work_around:1; | |
| 512 | + uint32_t reserved:28; | |
| 512 | 513 | } bits; |
| 513 | 514 | uint32_t raw; |
| 514 | 515 | }; |
| @@ -191,6 +191,8 @@ struct dc_link { · 190 unmodified lines | ||
| 191 | 191 | bool dp_skip_DID2; |
| 192 | 192 | bool dp_skip_reset_segment; |
| 193 | 193 | bool dp_mot_reset_segment; |
| 194 | + /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */ | |
| 195 | + bool dpia_mst_dsc_always_on; | |
| 194 | 196 | } wa_flags; |
| 195 | 197 | struct link_mst_stream_allocation_table mst_stream_alloc_table; |
| 196 | 198 | |
| @@ -224,6 +226,8 @@ static inline void get_edp_links(const struct dc *dc, · 27 unmodified lines | ||
| 224 | 226 | *edp_num = 0; |
| 225 | 227 | for (i = 0; i < dc->link_count; i++) { |
| 226 | 228 | // report any eDP links, even unconnected DDI's |
| 229 | + if (!dc->links[i]) | |
| 230 | + continue; | |
| 227 | 231 | if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) { |
| 228 | 232 | edp_links[*edp_num] = dc->links[i]; |
| 229 | 233 | if (++(*edp_num) == MAX_NUM_EDP) |
| @@ -1468,7 +1468,7 @@ static int smu_disable_dpms(struct smu_context *smu) · 1467 unmodified lines | ||
| 1468 | 1468 | dev_err(adev->dev, "Failed to disable smu features.\n"); |
| 1469 | 1469 | } |
| 1470 | 1470 | |
| 1471 | − if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 0, 0) && | |
| 1471 | + if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) && | |
| 1472 | 1472 | adev->gfx.rlc.funcs->stop) |
| 1473 | 1473 | adev->gfx.rlc.funcs->stop(adev); |
| 1474 | 1474 | |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/shmem_fs.h> |
| 10 | 10 | #include <linux/slab.h> |
| 11 | 11 | #include <linux/vmalloc.h> |
| 12 | +#include <linux/module.h> | |
| 12 | 13 | |
| 13 | 14 | #ifdef CONFIG_X86 |
| 14 | 15 | #include <asm/set_memory.h> |
| @@ -404,8 +404,17 @@ int drm_syncobj_find_fence(struct drm_file *file_private, · 403 unmodified lines | ||
| 404 | 404 | |
| 405 | 405 | if (*fence) { |
| 406 | 406 | ret = dma_fence_chain_find_seqno(fence, point); |
| 407 | − if (!ret) | |
| 407 | + if (!ret) { | |
| 408 | + /* If the requested seqno is already signaled | |
| 409 | + * drm_syncobj_find_fence may return a NULL | |
| 410 | + * fence. To make sure the recipient gets | |
| 411 | + * signalled, use a new fence instead. | |
| 412 | + */ | |
| 413 | + if (!*fence) | |
| 414 | + *fence = dma_fence_get_stub(); | |
| 415 | + | |
| 408 | 416 | goto out; |
| 417 | + } | |
| 409 | 418 | dma_fence_put(*fence); |
| 410 | 419 | } else { |
| 411 | 420 | ret = -EINVAL; |
| @@ -1640,6 +1640,9 @@ struct intel_dp { · 1639 unmodified lines | ||
| 1640 | 1640 | struct intel_dp_pcon_frl frl; |
| 1641 | 1641 | |
| 1642 | 1642 | struct intel_psr psr; |
| 1643 | + | |
| 1644 | + /* When we last wrote the OUI for eDP */ | |
| 1645 | + unsigned long last_oui_write; | |
| 1643 | 1646 | }; |
| 1644 | 1647 | |
| 1645 | 1648 | enum lspcon_vendor { |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/i2c.h> |
| 30 | 30 | #include <linux/notifier.h> |
| 31 | 31 | #include <linux/slab.h> |
| 32 | +#include <linux/timekeeping.h> | |
| 32 | 33 | #include <linux/types.h> |
| 33 | 34 | |
| 34 | 35 | #include <asm/byteorder.h> |
| @@ -1955,6 +1956,16 @@ intel_edp_init_source_oui(struct intel_dp *intel_dp, bool careful) · 1920 unmodified lines | ||
| 1955 | 1956 | |
| 1956 | 1957 | if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) |
| 1957 | 1958 | drm_err(&i915->drm, "Failed to write source OUI\n"); |
| 1959 | + | |
| 1960 | + intel_dp->last_oui_write = jiffies; | |
| 1961 | +} | |
| 1962 | + | |
| 1963 | +void intel_dp_wait_source_oui(struct intel_dp *intel_dp) | |
| 1964 | +{ | |
| 1965 | + struct drm_i915_private *i915 = dp_to_i915(intel_dp); | |
| 1966 | + | |
| 1967 | + drm_dbg_kms(&i915->drm, "Performing OUI wait\n"); | |
| 1968 | + wait_remaining_ms_from_jiffies(intel_dp->last_oui_write, 30); | |
| 1958 | 1969 | } |
| 1959 | 1970 | |
| 1960 | 1971 | /* If the device supports it, try to set the power state appropriately */ |
| @@ -119,4 +119,6 @@ void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp, · 118 unmodified lines | ||
| 119 | 119 | const struct intel_crtc_state *crtc_state); |
| 120 | 120 | void intel_dp_phy_test(struct intel_encoder *encoder); |
| 121 | 121 | |
| 122 | +void intel_dp_wait_source_oui(struct intel_dp *intel_dp); | |
| 123 | + | |
| 122 | 124 | #endif /* __INTEL_DP_H__ */ |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | #include "intel_backlight.h" |
| 38 | 38 | #include "intel_display_types.h" |
| 39 | +#include "intel_dp.h" | |
| 39 | 40 | #include "intel_dp_aux_backlight.h" |
| 40 | 41 | |
| 41 | 42 | /* TODO: |
| @@ -106,6 +107,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) · 64 unmodified lines | ||
| 106 | 107 | int ret; |
| 107 | 108 | u8 tcon_cap[4]; |
| 108 | 109 | |
| 110 | + intel_dp_wait_source_oui(intel_dp); | |
| 111 | + | |
| 109 | 112 | ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); |
| 110 | 113 | if (ret != sizeof(tcon_cap)) |
| 111 | 114 | return false; |
| @@ -204,6 +207,8 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, · 92 unmodified lines | ||
| 204 | 207 | int ret; |
| 205 | 208 | u8 old_ctrl, ctrl; |
| 206 | 209 | |
| 210 | + intel_dp_wait_source_oui(intel_dp); | |
| 211 | + | |
| 207 | 212 | ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); |
| 208 | 213 | if (ret != 1) { |
| 209 | 214 | drm_err(&i915->drm, "Failed to read current backlight control mode: %d\n", ret); |
| @@ -293,6 +298,13 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, · 83 unmodified lines | ||
| 293 | 298 | struct intel_panel *panel = &connector->panel; |
| 294 | 299 | struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
| 295 | 300 | |
| 301 | + if (!panel->backlight.edp.vesa.info.aux_enable) { | |
| 302 | + u32 pwm_level = intel_backlight_invert_pwm_level(connector, | |
| 303 | + panel->backlight.pwm_level_max); | |
| 304 | + | |
| 305 | + panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level); | |
| 306 | + } | |
| 307 | + | |
| 296 | 308 | drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level); |
| 297 | 309 | } |
| 298 | 310 | |
| @@ -304,6 +316,10 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state · 5 unmodified lines | ||
| 304 | 316 | struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
| 305 | 317 | |
| 306 | 318 | drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info); |
| 319 | + | |
| 320 | + if (!panel->backlight.edp.vesa.info.aux_enable) | |
| 321 | + panel->backlight.pwm_funcs->disable(old_conn_state, | |
| 322 | + intel_backlight_invert_pwm_level(connector, 0)); | |
| 307 | 323 | } |
| 308 | 324 | |
| 309 | 325 | static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe) |
| @@ -321,6 +337,15 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, · 11 unmodified lines | ||
| 321 | 337 | if (ret < 0) |
| 322 | 338 | return ret; |
| 323 | 339 | |
| 340 | + if (!panel->backlight.edp.vesa.info.aux_enable) { | |
| 341 | + ret = panel->backlight.pwm_funcs->setup(connector, pipe); | |
| 342 | + if (ret < 0) { | |
| 343 | + drm_err(&i915->drm, | |
| 344 | + "Failed to setup PWM backlight controls for eDP backlight: %d\n", | |
| 345 | + ret); | |
| 346 | + return ret; | |
| 347 | + } | |
| 348 | + } | |
| 324 | 349 | panel->backlight.max = panel->backlight.edp.vesa.info.max; |
| 325 | 350 | panel->backlight.min = 0; |
| 326 | 351 | if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
| @@ -340,12 +365,7 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector) · 13 unmodified lines | ||
| 340 | 365 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
| 341 | 366 | struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
| 342 | 367 | |
| 343 | − /* TODO: We currently only support AUX only backlight configurations, not backlights which | |
| 344 | − * require a mix of PWM and AUX controls to work. In the mean time, these machines typically | |
| 345 | − * work just fine using normal PWM controls anyway. | |
| 346 | − */ | |
| 347 | − if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && | |
| 348 | − drm_edp_backlight_supported(intel_dp->edp_dpcd)) { | |
| 368 | + if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) { | |
| 349 | 369 | drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n"); |
| 350 | 370 | return true; |
| 351 | 371 | } |
| @@ -3277,6 +3277,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, · 3276 unmodified lines | ||
| 3277 | 3277 | out_fence = eb_requests_create(&eb, in_fence, out_fence_fd); |
| 3278 | 3278 | if (IS_ERR(out_fence)) { |
| 3279 | 3279 | err = PTR_ERR(out_fence); |
| 3280 | + out_fence = NULL; | |
| 3280 | 3281 | if (eb.requests[0]) |
| 3281 | 3282 | goto err_request; |
| 3282 | 3283 | else |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #include <linux/slab.h> /* fault-inject.h is not standalone! */ |
| 7 | 7 | |
| 8 | 8 | #include <linux/fault-inject.h> |
| 9 | +#include <linux/sched/mm.h> | |
| 9 | 10 | |
| 10 | 11 | #include "gem/i915_gem_lmem.h" |
| 11 | 12 | #include "i915_trace.h" |
| @@ -621,13 +621,6 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, · 620 unmodified lines | ||
| 621 | 621 | FF_MODE2_GS_TIMER_MASK, |
| 622 | 622 | FF_MODE2_GS_TIMER_224, |
| 623 | 623 | 0, false); |
| 624 | − | |
| 625 | − /* | |
| 626 | − * Wa_14012131227:dg1 | |
| 627 | − * Wa_1508744258:tgl,rkl,dg1,adl-s,adl-p | |
| 628 | − */ | |
| 629 | − wa_masked_en(wal, GEN7_COMMON_SLICE_CHICKEN1, | |
| 630 | − GEN9_RHWO_OPTIMIZATION_DISABLE); | |
| 631 | 624 | } |
| 632 | 625 | |
| 633 | 626 | static void dg1_ctx_workarounds_init(struct intel_engine_cs *engine, |
| @@ -1134,6 +1127,15 @@ icl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) · 500 unmodified lines | ||
| 1134 | 1127 | GAMT_CHKN_BIT_REG, |
| 1135 | 1128 | GAMT_CHKN_DISABLE_L3_COH_PIPE); |
| 1136 | 1129 | |
| 1130 | + /* Wa_1407352427:icl,ehl */ | |
| 1131 | + wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2, | |
| 1132 | + PSDUNIT_CLKGATE_DIS); | |
| 1133 | + | |
| 1134 | + /* Wa_1406680159:icl,ehl */ | |
| 1135 | + wa_write_or(wal, | |
| 1136 | + SUBSLICE_UNIT_LEVEL_CLKGATE, | |
| 1137 | + GWUNIT_CLKGATE_DIS); | |
| 1138 | + | |
| 1137 | 1139 | /* Wa_1607087056:icl,ehl,jsl */ |
| 1138 | 1140 | if (IS_ICELAKE(i915) || |
| 1139 | 1141 | IS_JSL_EHL_GT_STEP(i915, STEP_A0, STEP_B0)) |
| @@ -1859,15 +1861,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) · 719 unmodified lines | ||
| 1859 | 1861 | wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE, |
| 1860 | 1862 | VSUNIT_CLKGATE_DIS | HSUNIT_CLKGATE_DIS); |
| 1861 | 1863 | |
| 1862 | − /* Wa_1407352427:icl,ehl */ | |
| 1863 | − wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2, | |
| 1864 | − PSDUNIT_CLKGATE_DIS); | |
| 1865 | − | |
| 1866 | − /* Wa_1406680159:icl,ehl */ | |
| 1867 | − wa_write_or(wal, | |
| 1868 | − SUBSLICE_UNIT_LEVEL_CLKGATE, | |
| 1869 | − GWUNIT_CLKGATE_DIS); | |
| 1870 | − | |
| 1871 | 1864 | /* |
| 1872 | 1865 | * Wa_1408767742:icl[a2..forever],ehl[all] |
| 1873 | 1866 | * Wa_1605460711:icl[a0..c0] |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/sched.h> |
| 30 | 30 | #include <linux/sched/clock.h> |
| 31 | 31 | #include <linux/sched/signal.h> |
| 32 | +#include <linux/sched/mm.h> | |
| 32 | 33 | |
| 33 | 34 | #include "gem/i915_gem_context.h" |
| 34 | 35 | #include "gt/intel_breadcrumbs.h" |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | ||
| 4 | 4 | #include <linux/regulator/consumer.h> |
| 5 | 5 | #include <linux/reset.h> |
| 6 | 6 | #include <linux/clk.h> |
| 7 | +#include <linux/slab.h> | |
| 7 | 8 | #include <linux/dma-mapping.h> |
| 8 | 9 | #include <linux/platform_device.h> |
| 9 | 10 | |
| @@ -4,8 +4,8 @@ config DRM_MSM · 3 unmodified lines | ||
| 4 | 4 | tristate "MSM DRM" |
| 5 | 5 | depends on DRM |
| 6 | 6 | depends on ARCH_QCOM || SOC_IMX5 || COMPILE_TEST |
| 7 | + depends on COMMON_CLK | |
| 7 | 8 | depends on IOMMU_SUPPORT |
| 8 | − depends on (OF && COMMON_CLK) || COMPILE_TEST | |
| 9 | 9 | depends on QCOM_OCMEM || QCOM_OCMEM=n |
| 10 | 10 | depends on QCOM_LLCC || QCOM_LLCC=n |
| 11 | 11 | depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n |
| @@ -23,8 +23,10 @@ msm-y := \ · 22 unmodified lines | ||
| 23 | 23 | hdmi/hdmi_i2c.o \ |
| 24 | 24 | hdmi/hdmi_phy.o \ |
| 25 | 25 | hdmi/hdmi_phy_8960.o \ |
| 26 | + hdmi/hdmi_phy_8996.o \ | |
| 26 | 27 | hdmi/hdmi_phy_8x60.o \ |
| 27 | 28 | hdmi/hdmi_phy_8x74.o \ |
| 29 | + hdmi/hdmi_pll_8960.o \ | |
| 28 | 30 | edp/edp.o \ |
| 29 | 31 | edp/edp_aux.o \ |
| 30 | 32 | edp/edp_bridge.o \ |
| @@ -37,6 +39,7 @@ msm-y := \ · 6 unmodified lines | ||
| 37 | 39 | disp/mdp4/mdp4_dtv_encoder.o \ |
| 38 | 40 | disp/mdp4/mdp4_lcdc_encoder.o \ |
| 39 | 41 | disp/mdp4/mdp4_lvds_connector.o \ |
| 42 | + disp/mdp4/mdp4_lvds_pll.o \ | |
| 40 | 43 | disp/mdp4/mdp4_irq.o \ |
| 41 | 44 | disp/mdp4/mdp4_kms.o \ |
| 42 | 45 | disp/mdp4/mdp4_plane.o \ |
| @@ -116,9 +119,6 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ · 73 unmodified lines | ||
| 116 | 119 | dp/dp_audio.o |
| 117 | 120 | |
| 118 | 121 | msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o |
| 119 | −msm-$(CONFIG_COMMON_CLK) += disp/mdp4/mdp4_lvds_pll.o | |
| 120 | −msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o | |
| 121 | −msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o | |
| 122 | 122 | |
| 123 | 123 | msm-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o |
| 124 | 124 | |
| @@ -1424,17 +1424,24 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) · 1423 unmodified lines | ||
| 1424 | 1424 | { |
| 1425 | 1425 | struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; |
| 1426 | 1426 | struct msm_gpu *gpu = &adreno_gpu->base; |
| 1427 | − u32 gpu_scid, cntl1_regval = 0; | |
| 1427 | + u32 cntl1_regval = 0; | |
| 1428 | 1428 | |
| 1429 | 1429 | if (IS_ERR(a6xx_gpu->llc_mmio)) |
| 1430 | 1430 | return; |
| 1431 | 1431 | |
| 1432 | 1432 | if (!llcc_slice_activate(a6xx_gpu->llc_slice)) { |
| 1433 | − gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); | |
| 1433 | + u32 gpu_scid = llcc_get_slice_id(a6xx_gpu->llc_slice); | |
| 1434 | 1434 | |
| 1435 | 1435 | gpu_scid &= 0x1f; |
| 1436 | 1436 | cntl1_regval = (gpu_scid << 0) | (gpu_scid << 5) | (gpu_scid << 10) | |
| 1437 | 1437 | (gpu_scid << 15) | (gpu_scid << 20); |
| 1438 | + | |
| 1439 | + /* On A660, the SCID programming for UCHE traffic is done in | |
| 1440 | + * A6XX_GBIF_SCACHE_CNTL0[14:10] | |
| 1441 | + */ | |
| 1442 | + if (adreno_is_a660_family(adreno_gpu)) | |
| 1443 | + gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | | |
| 1444 | + (1 << 8), (gpu_scid << 10) | (1 << 8)); | |
| 1438 | 1445 | } |
| 1439 | 1446 | |
| 1440 | 1447 | /* |
| @@ -1471,13 +1478,6 @@ static void a6xx_llc_activate(struct a6xx_gpu *a6xx_gpu) · 30 unmodified lines | ||
| 1471 | 1478 | } |
| 1472 | 1479 | |
| 1473 | 1480 | gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL1, GENMASK(24, 0), cntl1_regval); |
| 1474 | − | |
| 1475 | − /* On A660, the SCID programming for UCHE traffic is done in | |
| 1476 | − * A6XX_GBIF_SCACHE_CNTL0[14:10] | |
| 1477 | − */ | |
| 1478 | − if (adreno_is_a660_family(adreno_gpu)) | |
| 1479 | − gpu_rmw(gpu, REG_A6XX_GBIF_SCACHE_CNTL0, (0x1f << 10) | | |
| 1480 | − (1 << 8), (gpu_scid << 10) | (1 << 8)); | |
| 1481 | 1481 | } |
| 1482 | 1482 | |
| 1483 | 1483 | static void a6xx_llc_slices_destroy(struct a6xx_gpu *a6xx_gpu) |
| @@ -1640,7 +1640,7 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) · 156 unmodified lines | ||
| 1640 | 1640 | return (unsigned long)busy_time; |
| 1641 | 1641 | } |
| 1642 | 1642 | |
| 1643 | −void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) | |
| 1643 | +static void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) | |
| 1644 | 1644 | { |
| 1645 | 1645 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
| 1646 | 1646 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); |
| @@ -777,12 +777,12 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, · 776 unmodified lines | ||
| 777 | 777 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); |
| 778 | 778 | |
| 779 | 779 | a6xx_state->gmu_registers = state_kcalloc(a6xx_state, |
| 780 | − 2, sizeof(*a6xx_state->gmu_registers)); | |
| 780 | + 3, sizeof(*a6xx_state->gmu_registers)); | |
| 781 | 781 | |
| 782 | 782 | if (!a6xx_state->gmu_registers) |
| 783 | 783 | return; |
| 784 | 784 | |
| 785 | − a6xx_state->nr_gmu_registers = 2; | |
| 785 | + a6xx_state->nr_gmu_registers = 3; | |
| 786 | 786 | |
| 787 | 787 | /* Get the CX GMU registers from AHB */ |
| 788 | 788 | _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], |
| @@ -33,6 +33,7 @@ struct dp_aux_private { · 32 unmodified lines | ||
| 33 | 33 | bool read; |
| 34 | 34 | bool no_send_addr; |
| 35 | 35 | bool no_send_stop; |
| 36 | + bool initted; | |
| 36 | 37 | u32 offset; |
| 37 | 38 | u32 segment; |
| 38 | 39 | |
| @@ -331,6 +332,10 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, · 292 unmodified lines | ||
| 331 | 332 | } |
| 332 | 333 | |
| 333 | 334 | mutex_lock(&aux->mutex); |
| 335 | + if (!aux->initted) { | |
| 336 | + ret = -EIO; | |
| 337 | + goto exit; | |
| 338 | + } | |
| 334 | 339 | |
| 335 | 340 | dp_aux_update_offset_and_segment(aux, msg); |
| 336 | 341 | dp_aux_transfer_helper(aux, msg, true); |
| @@ -380,6 +385,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux, · 43 unmodified lines | ||
| 380 | 385 | } |
| 381 | 386 | |
| 382 | 387 | aux->cmd_busy = false; |
| 388 | + | |
| 389 | +exit: | |
| 383 | 390 | mutex_unlock(&aux->mutex); |
| 384 | 391 | |
| 385 | 392 | return ret; |
| @@ -431,8 +438,13 @@ void dp_aux_init(struct drm_dp_aux *dp_aux) · 45 unmodified lines | ||
| 431 | 438 | |
| 432 | 439 | aux = container_of(dp_aux, struct dp_aux_private, dp_aux); |
| 433 | 440 | |
| 441 | + mutex_lock(&aux->mutex); | |
| 442 | + | |
| 434 | 443 | dp_catalog_aux_enable(aux->catalog, true); |
| 435 | 444 | aux->retry_cnt = 0; |
| 445 | + aux->initted = true; | |
| 446 | + | |
| 447 | + mutex_unlock(&aux->mutex); | |
| 436 | 448 | } |
| 437 | 449 | |
| 438 | 450 | void dp_aux_deinit(struct drm_dp_aux *dp_aux) |
| @@ -441,7 +453,12 @@ void dp_aux_deinit(struct drm_dp_aux *dp_aux) · 2 unmodified lines | ||
| 441 | 453 | |
| 442 | 454 | aux = container_of(dp_aux, struct dp_aux_private, dp_aux); |
| 443 | 455 | |
| 456 | + mutex_lock(&aux->mutex); | |
| 457 | + | |
| 458 | + aux->initted = false; | |
| 444 | 459 | dp_catalog_aux_enable(aux->catalog, false); |
| 460 | + | |
| 461 | + mutex_unlock(&aux->mutex); | |
| 445 | 462 | } |
| 446 | 463 | |
| 447 | 464 | int dp_aux_register(struct drm_dp_aux *dp_aux) |
| @@ -1658,6 +1658,8 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host, · 1657 unmodified lines | ||
| 1658 | 1658 | if (!prop) { |
| 1659 | 1659 | DRM_DEV_DEBUG(dev, |
| 1660 | 1660 | "failed to find data lane mapping, using default\n"); |
| 1661 | + /* Set the number of date lanes to 4 by default. */ | |
| 1662 | + msm_host->num_data_lanes = 4; | |
| 1661 | 1663 | return 0; |
| 1662 | 1664 | } |
| 1663 | 1665 | |
| @@ -77,6 +77,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file) · 76 unmodified lines | ||
| 77 | 77 | goto free_priv; |
| 78 | 78 | |
| 79 | 79 | pm_runtime_get_sync(&gpu->pdev->dev); |
| 80 | + msm_gpu_hw_init(gpu); | |
| 80 | 81 | show_priv->state = gpu->funcs->gpu_state_get(gpu); |
| 81 | 82 | pm_runtime_put_sync(&gpu->pdev->dev); |
| 82 | 83 | |
| @@ -967,29 +967,18 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, · 966 unmodified lines | ||
| 967 | 967 | return ret; |
| 968 | 968 | } |
| 969 | 969 | |
| 970 | −static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, | |
| 971 | − struct drm_file *file) | |
| 970 | +static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, | |
| 971 | + ktime_t timeout) | |
| 972 | 972 | { |
| 973 | − struct msm_drm_private *priv = dev->dev_private; | |
| 974 | − struct drm_msm_wait_fence *args = data; | |
| 975 | − ktime_t timeout = to_ktime(args->timeout); | |
| 976 | − struct msm_gpu_submitqueue *queue; | |
| 977 | − struct msm_gpu *gpu = priv->gpu; | |
| 978 | 973 | struct dma_fence *fence; |
| 979 | 974 | int ret; |
| 980 | 975 | |
| 981 | − if (args->pad) { | |
| 982 | − DRM_ERROR("invalid pad: %08x\n", args->pad); | |
| 976 | + if (fence_id > queue->last_fence) { | |
| 977 | + DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n", | |
| 978 | + fence_id, queue->last_fence); | |
| 983 | 979 | return -EINVAL; |
| 984 | 980 | } |
| 985 | 981 | |
| 986 | − if (!gpu) | |
| 987 | − return 0; | |
| 988 | − | |
| 989 | − queue = msm_submitqueue_get(file->driver_priv, args->queueid); | |
| 990 | − if (!queue) | |
| 991 | − return -ENOENT; | |
| 992 | − | |
| 993 | 982 | /* |
| 994 | 983 | * Map submitqueue scoped "seqno" (which is actually an idr key) |
| 995 | 984 | * back to underlying dma-fence |
| @@ -1001,7 +990,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, · 5 unmodified lines | ||
| 1001 | 990 | ret = mutex_lock_interruptible(&queue->lock); |
| 1002 | 991 | if (ret) |
| 1003 | 992 | return ret; |
| 1004 | − fence = idr_find(&queue->fence_idr, args->fence); | |
| 993 | + fence = idr_find(&queue->fence_idr, fence_id); | |
| 1005 | 994 | if (fence) |
| 1006 | 995 | fence = dma_fence_get_rcu(fence); |
| 1007 | 996 | mutex_unlock(&queue->lock); |
| @@ -1017,6 +1006,32 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, · 9 unmodified lines | ||
| 1017 | 1006 | } |
| 1018 | 1007 | |
| 1019 | 1008 | dma_fence_put(fence); |
| 1009 | + | |
| 1010 | + return ret; | |
| 1011 | +} | |
| 1012 | + | |
| 1013 | +static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, | |
| 1014 | + struct drm_file *file) | |
| 1015 | +{ | |
| 1016 | + struct msm_drm_private *priv = dev->dev_private; | |
| 1017 | + struct drm_msm_wait_fence *args = data; | |
| 1018 | + struct msm_gpu_submitqueue *queue; | |
| 1019 | + int ret; | |
| 1020 | + | |
| 1021 | + if (args->pad) { | |
| 1022 | + DRM_ERROR("invalid pad: %08x\n", args->pad); | |
| 1023 | + return -EINVAL; | |
| 1024 | + } | |
| 1025 | + | |
| 1026 | + if (!priv->gpu) | |
| 1027 | + return 0; | |
| 1028 | + | |
| 1029 | + queue = msm_submitqueue_get(file->driver_priv, args->queueid); | |
| 1030 | + if (!queue) | |
| 1031 | + return -ENOENT; | |
| 1032 | + | |
| 1033 | + ret = wait_fence(queue, args->fence, to_ktime(args->timeout)); | |
| 1034 | + | |
| 1020 | 1035 | msm_submitqueue_put(queue); |
| 1021 | 1036 | |
| 1022 | 1037 | return ret; |
| @@ -1056,8 +1056,7 @@ static int msm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct · 1055 unmodified lines | ||
| 1056 | 1056 | { |
| 1057 | 1057 | struct msm_gem_object *msm_obj = to_msm_bo(obj); |
| 1058 | 1058 | |
| 1059 | − vma->vm_flags &= ~VM_PFNMAP; | |
| 1060 | − vma->vm_flags |= VM_MIXEDMAP | VM_DONTEXPAND; | |
| 1059 | + vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP; | |
| 1061 | 1060 | vma->vm_page_prot = msm_gem_pgprot(msm_obj, vm_get_page_prot(vma->vm_flags)); |
| 1062 | 1061 | |
| 1063 | 1062 | return 0; |
| @@ -1121,7 +1120,7 @@ static int msm_gem_new_impl(struct drm_device *dev, · 57 unmodified lines | ||
| 1121 | 1120 | break; |
| 1122 | 1121 | fallthrough; |
| 1123 | 1122 | default: |
| 1124 | − DRM_DEV_ERROR(dev->dev, "invalid cache flag: %x\n", | |
| 1123 | + DRM_DEV_DEBUG(dev->dev, "invalid cache flag: %x\n", | |
| 1125 | 1124 | (flags & MSM_BO_CACHE_MASK)); |
| 1126 | 1125 | return -EINVAL; |
| 1127 | 1126 | } |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | */ |
| 6 | 6 | |
| 7 | 7 | #include <linux/vmalloc.h> |
| 8 | +#include <linux/sched/mm.h> | |
| 8 | 9 | |
| 9 | 10 | #include "msm_drv.h" |
| 10 | 11 | #include "msm_gem.h" |
| @@ -772,6 +772,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 771 unmodified lines | ||
| 772 | 772 | args->nr_cmds); |
| 773 | 773 | if (IS_ERR(submit)) { |
| 774 | 774 | ret = PTR_ERR(submit); |
| 775 | + submit = NULL; | |
| 775 | 776 | goto out_unlock; |
| 776 | 777 | } |
| 777 | 778 | |
| @@ -904,6 +905,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, · 126 unmodified lines | ||
| 904 | 905 | drm_sched_entity_push_job(&submit->base); |
| 905 | 906 | |
| 906 | 907 | args->fence = submit->fence_id; |
| 908 | + queue->last_fence = submit->fence_id; | |
| 907 | 909 | |
| 908 | 910 | msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs); |
| 909 | 911 | msm_process_post_deps(post_deps, args->nr_out_syncobjs, |
| @@ -359,6 +359,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, · 358 unmodified lines | ||
| 359 | 359 | * @ring_nr: the ringbuffer used by this submitqueue, which is determined |
| 360 | 360 | * by the submitqueue's priority |
| 361 | 361 | * @faults: the number of GPU hangs associated with this submitqueue |
| 362 | + * @last_fence: the sequence number of the last allocated fence (for error | |
| 363 | + * checking) | |
| 362 | 364 | * @ctx: the per-drm_file context associated with the submitqueue (ie. |
| 363 | 365 | * which set of pgtables do submits jobs associated with the |
| 364 | 366 | * submitqueue use) |
| @@ -374,6 +376,7 @@ struct msm_gpu_submitqueue { · 9 unmodified lines | ||
| 374 | 376 | u32 flags; |
| 375 | 377 | u32 ring_nr; |
| 376 | 378 | int faults; |
| 379 | + uint32_t last_fence; | |
| 377 | 380 | struct msm_file_private *ctx; |
| 378 | 381 | struct list_head node; |
| 379 | 382 | struct idr fence_idr; |
| @@ -20,6 +20,10 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, · 19 unmodified lines | ||
| 20 | 20 | struct msm_gpu *gpu = dev_to_gpu(dev); |
| 21 | 21 | struct dev_pm_opp *opp; |
| 22 | 22 | |
| 23 | + /* | |
| 24 | + * Note that devfreq_recommended_opp() can modify the freq | |
| 25 | + * to something that actually is in the opp table: | |
| 26 | + */ | |
| 23 | 27 | opp = devfreq_recommended_opp(dev, freq, flags); |
| 24 | 28 | |
| 25 | 29 | /* |
| @@ -28,6 +32,7 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq, · 2 unmodified lines | ||
| 28 | 32 | */ |
| 29 | 33 | if (gpu->devfreq.idle_freq) { |
| 30 | 34 | gpu->devfreq.idle_freq = *freq; |
| 35 | + dev_pm_opp_put(opp); | |
| 31 | 36 | return 0; |
| 32 | 37 | } |
| 33 | 38 | |
| @@ -203,9 +208,6 @@ static void msm_devfreq_idle_work(struct kthread_work *work) · 169 unmodified lines | ||
| 203 | 208 | struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq); |
| 204 | 209 | unsigned long idle_freq, target_freq = 0; |
| 205 | 210 | |
| 206 | − if (!df->devfreq) | |
| 207 | − return; | |
| 208 | − | |
| 209 | 211 | /* |
| 210 | 212 | * Hold devfreq lock to synchronize with get_dev_status()/ |
| 211 | 213 | * target() callbacks |
| @@ -227,6 +229,9 @@ void msm_devfreq_idle(struct msm_gpu *gpu) · 15 unmodified lines | ||
| 227 | 229 | { |
| 228 | 230 | struct msm_gpu_devfreq *df = &gpu->devfreq; |
| 229 | 231 | |
| 232 | + if (!df->devfreq) | |
| 233 | + return; | |
| 234 | + | |
| 230 | 235 | msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1), |
| 231 | − HRTIMER_MODE_ABS); | |
| 236 | + HRTIMER_MODE_REL); | |
| 232 | 237 | } |
| @@ -1103,7 +1103,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, · 1102 unmodified lines | ||
| 1103 | 1103 | * as an indication that we're about to swap out. |
| 1104 | 1104 | */ |
| 1105 | 1105 | memset(&place, 0, sizeof(place)); |
| 1106 | − place.mem_type = TTM_PL_SYSTEM; | |
| 1106 | + place.mem_type = bo->resource->mem_type; | |
| 1107 | 1107 | if (!ttm_bo_evict_swapout_allowable(bo, ctx, &place, &locked, NULL)) |
| 1108 | 1108 | return -EBUSY; |
| 1109 | 1109 | |
| @@ -1135,6 +1135,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, · 25 unmodified lines | ||
| 1135 | 1135 | struct ttm_place hop; |
| 1136 | 1136 | |
| 1137 | 1137 | memset(&hop, 0, sizeof(hop)); |
| 1138 | + place.mem_type = TTM_PL_SYSTEM; | |
| 1138 | 1139 | ret = ttm_resource_alloc(bo, &place, &evict_mem); |
| 1139 | 1140 | if (unlikely(ret)) |
| 1140 | 1141 | goto out; |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | #include <linux/sched.h> |
| 35 | 35 | #include <linux/shmem_fs.h> |
| 36 | 36 | #include <linux/file.h> |
| 37 | +#include <linux/module.h> | |
| 37 | 38 | #include <drm/drm_cache.h> |
| 38 | 39 | #include <drm/ttm/ttm_bo_driver.h> |
| 39 | 40 | |
| @@ -337,10 +337,10 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) · 336 unmodified lines | ||
| 337 | 337 | struct drm_device *dev = state->dev; |
| 338 | 338 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
| 339 | 339 | struct vc4_hvs *hvs = vc4->hvs; |
| 340 | − struct drm_crtc_state *old_crtc_state; | |
| 341 | 340 | struct drm_crtc_state *new_crtc_state; |
| 342 | 341 | struct drm_crtc *crtc; |
| 343 | 342 | struct vc4_hvs_state *old_hvs_state; |
| 343 | + unsigned int channel; | |
| 344 | 344 | int i; |
| 345 | 345 | |
| 346 | 346 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { |
| @@ -353,30 +353,32 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) · 6 unmodified lines | ||
| 353 | 353 | vc4_hvs_mask_underrun(dev, vc4_crtc_state->assigned_channel); |
| 354 | 354 | } |
| 355 | 355 | |
| 356 | − if (vc4->hvs->hvs5) | |
| 357 | − clk_set_min_rate(hvs->core_clk, 500000000); | |
| 358 | − | |
| 359 | 356 | old_hvs_state = vc4_hvs_get_old_global_state(state); |
| 360 | − if (!old_hvs_state) | |
| 357 | + if (IS_ERR(old_hvs_state)) | |
| 361 | 358 | return; |
| 362 | 359 | |
| 363 | − for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { | |
| 364 | − struct vc4_crtc_state *vc4_crtc_state = | |
| 365 | − to_vc4_crtc_state(old_crtc_state); | |
| 366 | − unsigned int channel = vc4_crtc_state->assigned_channel; | |
| 360 | + for (channel = 0; channel < HVS_NUM_CHANNELS; channel++) { | |
| 361 | + struct drm_crtc_commit *commit; | |
| 367 | 362 | int ret; |
| 368 | 363 | |
| 369 | − if (channel == VC4_HVS_CHANNEL_DISABLED) | |
| 364 | + if (!old_hvs_state->fifo_state[channel].in_use) | |
| 370 | 365 | continue; |
| 371 | 366 | |
| 372 | − if (!old_hvs_state->fifo_state[channel].in_use) | |
| 367 | + commit = old_hvs_state->fifo_state[channel].pending_commit; | |
| 368 | + if (!commit) | |
| 373 | 369 | continue; |
| 374 | 370 | |
| 375 | − ret = drm_crtc_commit_wait(old_hvs_state->fifo_state[channel].pending_commit); | |
| 371 | + ret = drm_crtc_commit_wait(commit); | |
| 376 | 372 | if (ret) |
| 377 | 373 | drm_err(dev, "Timed out waiting for commit\n"); |
| 374 | + | |
| 375 | + drm_crtc_commit_put(commit); | |
| 376 | + old_hvs_state->fifo_state[channel].pending_commit = NULL; | |
| 378 | 377 | } |
| 379 | 378 | |
| 379 | + if (vc4->hvs->hvs5) | |
| 380 | + clk_set_min_rate(hvs->core_clk, 500000000); | |
| 381 | + | |
| 380 | 382 | drm_atomic_helper_commit_modeset_disables(dev, state); |
| 381 | 383 | |
| 382 | 384 | vc4_ctm_commit(vc4, state); |
| @@ -410,8 +412,8 @@ static int vc4_atomic_commit_setup(struct drm_atomic_state *state) · 27 unmodified lines | ||
| 410 | 412 | unsigned int i; |
| 411 | 413 | |
| 412 | 414 | hvs_state = vc4_hvs_get_new_global_state(state); |
| 413 | − if (!hvs_state) | |
| 414 | − return -EINVAL; | |
| 415 | + if (WARN_ON(IS_ERR(hvs_state))) | |
| 416 | + return PTR_ERR(hvs_state); | |
| 415 | 417 | |
| 416 | 418 | for_each_new_crtc_in_state(state, crtc, crtc_state, i) { |
| 417 | 419 | struct vc4_crtc_state *vc4_crtc_state = |
| @@ -668,12 +670,6 @@ vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) · 250 unmodified lines | ||
| 668 | 670 | |
| 669 | 671 | for (i = 0; i < HVS_NUM_CHANNELS; i++) { |
| 670 | 672 | state->fifo_state[i].in_use = old_state->fifo_state[i].in_use; |
| 671 | − | |
| 672 | − if (!old_state->fifo_state[i].pending_commit) | |
| 673 | − continue; | |
| 674 | − | |
| 675 | − state->fifo_state[i].pending_commit = | |
| 676 | − drm_crtc_commit_get(old_state->fifo_state[i].pending_commit); | |
| 677 | 673 | } |
| 678 | 674 | |
| 679 | 675 | return &state->base; |
| @@ -762,8 +758,8 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, · 82 unmodified lines | ||
| 762 | 758 | unsigned int i; |
| 763 | 759 | |
| 764 | 760 | hvs_new_state = vc4_hvs_get_global_state(state); |
| 765 | − if (!hvs_new_state) | |
| 766 | − return -EINVAL; | |
| 761 | + if (IS_ERR(hvs_new_state)) | |
| 762 | + return PTR_ERR(hvs_new_state); | |
| 767 | 763 | |
| 768 | 764 | for (i = 0; i < ARRAY_SIZE(hvs_new_state->fifo_state); i++) |
| 769 | 765 | if (!hvs_new_state->fifo_state[i].in_use) |
| @@ -157,36 +157,6 @@ static void virtio_gpu_config_changed(struct virtio_device *vdev) · 156 unmodified lines | ||
| 157 | 157 | schedule_work(&vgdev->config_changed_work); |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | −static __poll_t virtio_gpu_poll(struct file *filp, | |
| 161 | − struct poll_table_struct *wait) | |
| 162 | −{ | |
| 163 | − struct drm_file *drm_file = filp->private_data; | |
| 164 | − struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv; | |
| 165 | − struct drm_device *dev = drm_file->minor->dev; | |
| 166 | − struct virtio_gpu_device *vgdev = dev->dev_private; | |
| 167 | − struct drm_pending_event *e = NULL; | |
| 168 | − __poll_t mask = 0; | |
| 169 | − | |
| 170 | − if (!vgdev->has_virgl_3d || !vfpriv || !vfpriv->ring_idx_mask) | |
| 171 | − return drm_poll(filp, wait); | |
| 172 | − | |
| 173 | − poll_wait(filp, &drm_file->event_wait, wait); | |
| 174 | − | |
| 175 | − if (!list_empty(&drm_file->event_list)) { | |
| 176 | − spin_lock_irq(&dev->event_lock); | |
| 177 | − e = list_first_entry(&drm_file->event_list, | |
| 178 | − struct drm_pending_event, link); | |
| 179 | − drm_file->event_space += e->event->length; | |
| 180 | − list_del(&e->link); | |
| 181 | − spin_unlock_irq(&dev->event_lock); | |
| 182 | − | |
| 183 | − kfree(e); | |
| 184 | − mask |= EPOLLIN | EPOLLRDNORM; | |
| 185 | − } | |
| 186 | − | |
| 187 | − return mask; | |
| 188 | −} | |
| 189 | − | |
| 190 | 160 | static struct virtio_device_id id_table[] = { |
| 191 | 161 | { VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID }, |
| 192 | 162 | { 0 }, |
| @@ -226,17 +196,7 @@ MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>"); · 33 unmodified lines | ||
| 226 | 196 | MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>"); |
| 227 | 197 | MODULE_AUTHOR("Alon Levy"); |
| 228 | 198 | |
| 229 | −static const struct file_operations virtio_gpu_driver_fops = { | |
| 230 | − .owner = THIS_MODULE, | |
| 231 | − .open = drm_open, | |
| 232 | − .release = drm_release, | |
| 233 | − .unlocked_ioctl = drm_ioctl, | |
| 234 | − .compat_ioctl = drm_compat_ioctl, | |
| 235 | − .poll = virtio_gpu_poll, | |
| 236 | − .read = drm_read, | |
| 237 | − .llseek = noop_llseek, | |
| 238 | − .mmap = drm_gem_mmap | |
| 239 | −}; | |
| 199 | +DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops); | |
| 240 | 200 | |
| 241 | 201 | static const struct drm_driver driver = { |
| 242 | 202 | .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, |
| @@ -138,7 +138,6 @@ struct virtio_gpu_fence_driver { · 137 unmodified lines | ||
| 138 | 138 | spinlock_t lock; |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | −#define VIRTGPU_EVENT_FENCE_SIGNALED_INTERNAL 0x10000000 | |
| 142 | 141 | struct virtio_gpu_fence_event { |
| 143 | 142 | struct drm_pending_event base; |
| 144 | 143 | struct drm_event event; |
| @@ -54,7 +54,7 @@ static int virtio_gpu_fence_event_create(struct drm_device *dev, · 53 unmodified lines | ||
| 54 | 54 | if (!e) |
| 55 | 55 | return -ENOMEM; |
| 56 | 56 | |
| 57 | − e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED_INTERNAL; | |
| 57 | + e->event.type = VIRTGPU_EVENT_FENCE_SIGNALED; | |
| 58 | 58 | e->event.length = sizeof(e->event); |
| 59 | 59 | |
| 60 | 60 | ret = drm_event_reserve_init(dev, file, &e->base, &e->event); |
| @@ -207,14 +207,14 @@ config HID_CHERRY · 206 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | config HID_CHICONY |
| 209 | 209 | tristate "Chicony devices" |
| 210 | − depends on HID | |
| 210 | + depends on USB_HID | |
| 211 | 211 | default !EXPERT |
| 212 | 212 | help |
| 213 | 213 | Support for Chicony Tactical pad and special keys on Chicony keyboards. |
| 214 | 214 | |
| 215 | 215 | config HID_CORSAIR |
| 216 | 216 | tristate "Corsair devices" |
| 217 | − depends on HID && USB && LEDS_CLASS | |
| 217 | + depends on USB_HID && LEDS_CLASS | |
| 218 | 218 | help |
| 219 | 219 | Support for Corsair devices that are not fully compliant with the |
| 220 | 220 | HID standard. |
| @@ -245,7 +245,7 @@ config HID_MACALLY · 24 unmodified lines | ||
| 245 | 245 | |
| 246 | 246 | config HID_PRODIKEYS |
| 247 | 247 | tristate "Prodikeys PC-MIDI Keyboard support" |
| 248 | − depends on HID && SND | |
| 248 | + depends on USB_HID && SND | |
| 249 | 249 | select SND_RAWMIDI |
| 250 | 250 | help |
| 251 | 251 | Support for Prodikeys PC-MIDI Keyboard device support. |
| @@ -560,7 +560,7 @@ config HID_LENOVO · 308 unmodified lines | ||
| 560 | 560 | |
| 561 | 561 | config HID_LOGITECH |
| 562 | 562 | tristate "Logitech devices" |
| 563 | − depends on HID | |
| 563 | + depends on USB_HID | |
| 564 | 564 | depends on LEDS_CLASS |
| 565 | 565 | default !EXPERT |
| 566 | 566 | help |
| @@ -951,7 +951,7 @@ config HID_SAITEK · 384 unmodified lines | ||
| 951 | 951 | |
| 952 | 952 | config HID_SAMSUNG |
| 953 | 953 | tristate "Samsung InfraRed remote control or keyboards" |
| 954 | − depends on HID | |
| 954 | + depends on USB_HID | |
| 955 | 955 | help |
| 956 | 956 | Support for Samsung InfraRed remote control or keyboards. |
| 957 | 957 | |
| @@ -1028,8 +1028,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) · 1027 unmodified lines | ||
| 1028 | 1028 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) |
| 1029 | 1029 | drvdata->tp = &asus_i2c_tp; |
| 1030 | 1030 | |
| 1031 | − if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && | |
| 1032 | − hid_is_using_ll_driver(hdev, &usb_hid_driver)) { | |
| 1031 | + if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) { | |
| 1033 | 1032 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
| 1034 | 1033 | |
| 1035 | 1034 | if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { |
| @@ -1057,8 +1056,7 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) · 21 unmodified lines | ||
| 1057 | 1056 | drvdata->tp = &asus_t100chi_tp; |
| 1058 | 1057 | } |
| 1059 | 1058 | |
| 1060 | − if ((drvdata->quirks & QUIRK_MEDION_E1239T) && | |
| 1061 | − hid_is_using_ll_driver(hdev, &usb_hid_driver)) { | |
| 1059 | + if ((drvdata->quirks & QUIRK_MEDION_E1239T) && hid_is_usb(hdev)) { | |
| 1062 | 1060 | struct usb_host_interface *alt = |
| 1063 | 1061 | to_usb_interface(hdev->dev.parent)->altsetting; |
| 1064 | 1062 | |
| @@ -191,7 +191,7 @@ static void bigben_worker(struct work_struct *work) · 190 unmodified lines | ||
| 191 | 191 | struct bigben_device, worker); |
| 192 | 192 | struct hid_field *report_field = bigben->report->field[0]; |
| 193 | 193 | |
| 194 | − if (bigben->removed) | |
| 194 | + if (bigben->removed || !report_field) | |
| 195 | 195 | return; |
| 196 | 196 | |
| 197 | 197 | if (bigben->work_led) { |
| @@ -114,6 +114,9 @@ static int ch_probe(struct hid_device *hdev, const struct hid_device_id *id) · 113 unmodified lines | ||
| 114 | 114 | { |
| 115 | 115 | int ret; |
| 116 | 116 | |
| 117 | + if (!hid_is_usb(hdev)) | |
| 118 | + return -EINVAL; | |
| 119 | + | |
| 117 | 120 | hdev->quirks |= HID_QUIRK_INPUT_PER_APP; |
| 118 | 121 | ret = hid_parse(hdev); |
| 119 | 122 | if (ret) { |
| @@ -553,7 +553,12 @@ static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id) · 552 unmodified lines | ||
| 553 | 553 | int ret; |
| 554 | 554 | unsigned long quirks = id->driver_data; |
| 555 | 555 | struct corsair_drvdata *drvdata; |
| 556 | − struct usb_interface *usbif = to_usb_interface(dev->dev.parent); | |
| 556 | + struct usb_interface *usbif; | |
| 557 | + | |
| 558 | + if (!hid_is_usb(dev)) | |
| 559 | + return -EINVAL; | |
| 560 | + | |
| 561 | + usbif = to_usb_interface(dev->dev.parent); | |
| 557 | 562 | |
| 558 | 563 | drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata), |
| 559 | 564 | GFP_KERNEL); |
| @@ -50,7 +50,7 @@ struct elan_drvdata { · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | static int is_not_elan_touchpad(struct hid_device *hdev) |
| 52 | 52 | { |
| 53 | − if (hdev->bus == BUS_USB) { | |
| 53 | + if (hid_is_usb(hdev)) { | |
| 54 | 54 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
| 55 | 55 | |
| 56 | 56 | return (intf->altsetting->desc.bInterfaceNumber != |
| @@ -230,6 +230,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id) · 229 unmodified lines | ||
| 230 | 230 | int ret; |
| 231 | 231 | struct usb_device *udev; |
| 232 | 232 | |
| 233 | + if (!hid_is_usb(hdev)) | |
| 234 | + return -EINVAL; | |
| 235 | + | |
| 233 | 236 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 234 | 237 | if (!priv) |
| 235 | 238 | return -ENOMEM; |
| @@ -915,6 +915,9 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id) · 914 unmodified lines | ||
| 915 | 915 | struct ft260_get_chip_version_report version; |
| 916 | 916 | int ret; |
| 917 | 917 | |
| 918 | + if (!hid_is_usb(hdev)) | |
| 919 | + return -EINVAL; | |
| 920 | + | |
| 918 | 921 | dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); |
| 919 | 922 | if (!dev) |
| 920 | 923 | return -ENOMEM; |
| @@ -585,6 +585,8 @@ static void hammer_remove(struct hid_device *hdev) · 584 unmodified lines | ||
| 585 | 585 | static const struct hid_device_id hammer_devices[] = { |
| 586 | 586 | { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, |
| 587 | 587 | USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) }, |
| 588 | + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, | |
| 589 | + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) }, | |
| 588 | 590 | { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, |
| 589 | 591 | USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, |
| 590 | 592 | { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, |
| @@ -140,12 +140,17 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, · 139 unmodified lines | ||
| 140 | 140 | static int holtek_kbd_probe(struct hid_device *hdev, |
| 141 | 141 | const struct hid_device_id *id) |
| 142 | 142 | { |
| 143 | − struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 144 | − int ret = hid_parse(hdev); | |
| 143 | + struct usb_interface *intf; | |
| 144 | + int ret; | |
| 145 | + | |
| 146 | + if (!hid_is_usb(hdev)) | |
| 147 | + return -EINVAL; | |
| 145 | 148 | |
| 149 | + ret = hid_parse(hdev); | |
| 146 | 150 | if (!ret) |
| 147 | 151 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
| 148 | 152 | |
| 153 | + intf = to_usb_interface(hdev->dev.parent); | |
| 149 | 154 | if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) { |
| 150 | 155 | struct hid_input *hidinput; |
| 151 | 156 | list_for_each_entry(hidinput, &hdev->inputs, list) { |
| @@ -62,6 +62,14 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 61 unmodified lines | ||
| 62 | 62 | return rdesc; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | +static int holtek_mouse_probe(struct hid_device *hdev, | |
| 66 | + const struct hid_device_id *id) | |
| 67 | +{ | |
| 68 | + if (!hid_is_usb(hdev)) | |
| 69 | + return -EINVAL; | |
| 70 | + return 0; | |
| 71 | +} | |
| 72 | + | |
| 65 | 73 | static const struct hid_device_id holtek_mouse_devices[] = { |
| 66 | 74 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, |
| 67 | 75 | USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, |
| @@ -83,6 +91,7 @@ static struct hid_driver holtek_mouse_driver = { · 15 unmodified lines | ||
| 83 | 91 | .name = "holtek_mouse", |
| 84 | 92 | .id_table = holtek_mouse_devices, |
| 85 | 93 | .report_fixup = holtek_mouse_report_fixup, |
| 94 | + .probe = holtek_mouse_probe, | |
| 86 | 95 | }; |
| 87 | 96 | |
| 88 | 97 | module_hid_driver(holtek_mouse_driver); |
| @@ -399,6 +399,7 @@ · 398 unmodified lines | ||
| 399 | 399 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 |
| 400 | 400 | #define I2C_DEVICE_ID_HP_ENVY_X360_15 0x2d05 |
| 401 | 401 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 |
| 402 | +#define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 | |
| 402 | 403 | #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 |
| 403 | 404 | #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A |
| 404 | 405 | |
| @@ -501,6 +502,7 @@ · 96 unmodified lines | ||
| 501 | 502 | #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d |
| 502 | 503 | #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 |
| 503 | 504 | #define USB_DEVICE_ID_GOOGLE_DON 0x5050 |
| 505 | +#define USB_DEVICE_ID_GOOGLE_EEL 0x5057 | |
| 504 | 506 | |
| 505 | 507 | #define USB_VENDOR_ID_GOTOP 0x08f2 |
| 506 | 508 | #define USB_DEVICE_ID_SUPER_Q2 0x007f |
| @@ -886,6 +888,7 @@ · 379 unmodified lines | ||
| 886 | 888 | #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 |
| 887 | 889 | #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 |
| 888 | 890 | #define USB_DEVICE_ID_MS_POWER_COVER 0x07da |
| 891 | +#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de | |
| 889 | 892 | #define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd |
| 890 | 893 | #define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb |
| 891 | 894 | #define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0 |
| @@ -325,6 +325,8 @@ static const struct hid_device_id hid_battery_quirks[] = { · 324 unmodified lines | ||
| 325 | 325 | HID_BATTERY_QUIRK_IGNORE }, |
| 326 | 326 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), |
| 327 | 327 | HID_BATTERY_QUIRK_IGNORE }, |
| 328 | + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), | |
| 329 | + HID_BATTERY_QUIRK_IGNORE }, | |
| 328 | 330 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15), |
| 329 | 331 | HID_BATTERY_QUIRK_IGNORE }, |
| 330 | 332 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), |
| @@ -749,12 +749,18 @@ static int lg_raw_event(struct hid_device *hdev, struct hid_report *report, · 748 unmodified lines | ||
| 749 | 749 | |
| 750 | 750 | static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 751 | 751 | { |
| 752 | − struct usb_interface *iface = to_usb_interface(hdev->dev.parent); | |
| 753 | − __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; | |
| 752 | + struct usb_interface *iface; | |
| 753 | + __u8 iface_num; | |
| 754 | 754 | unsigned int connect_mask = HID_CONNECT_DEFAULT; |
| 755 | 755 | struct lg_drv_data *drv_data; |
| 756 | 756 | int ret; |
| 757 | 757 | |
| 758 | + if (!hid_is_usb(hdev)) | |
| 759 | + return -EINVAL; | |
| 760 | + | |
| 761 | + iface = to_usb_interface(hdev->dev.parent); | |
| 762 | + iface_num = iface->cur_altsetting->desc.bInterfaceNumber; | |
| 763 | + | |
| 758 | 764 | /* G29 only work with the 1st interface */ |
| 759 | 765 | if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) && |
| 760 | 766 | (iface_num != 0)) { |
| @@ -1777,7 +1777,7 @@ static int logi_dj_probe(struct hid_device *hdev, · 1776 unmodified lines | ||
| 1777 | 1777 | case recvr_type_bluetooth: no_dj_interfaces = 2; break; |
| 1778 | 1778 | case recvr_type_dinovo: no_dj_interfaces = 2; break; |
| 1779 | 1779 | } |
| 1780 | − if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) { | |
| 1780 | + if (hid_is_usb(hdev)) { | |
| 1781 | 1781 | intf = to_usb_interface(hdev->dev.parent); |
| 1782 | 1782 | if (intf && intf->altsetting->desc.bInterfaceNumber >= |
| 1783 | 1783 | no_dj_interfaces) { |
| @@ -798,12 +798,18 @@ static int pk_raw_event(struct hid_device *hdev, struct hid_report *report, · 797 unmodified lines | ||
| 798 | 798 | static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 799 | 799 | { |
| 800 | 800 | int ret; |
| 801 | − struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 802 | − unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | |
| 801 | + struct usb_interface *intf; | |
| 802 | + unsigned short ifnum; | |
| 803 | 803 | unsigned long quirks = id->driver_data; |
| 804 | 804 | struct pk_device *pk; |
| 805 | 805 | struct pcmidi_snd *pm = NULL; |
| 806 | 806 | |
| 807 | + if (!hid_is_usb(hdev)) | |
| 808 | + return -EINVAL; | |
| 809 | + | |
| 810 | + intf = to_usb_interface(hdev->dev.parent); | |
| 811 | + ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | |
| 812 | + | |
| 807 | 813 | pk = kzalloc(sizeof(*pk), GFP_KERNEL); |
| 808 | 814 | if (pk == NULL) { |
| 809 | 815 | hid_err(hdev, "can't alloc descriptor\n"); |
| @@ -124,6 +124,7 @@ static const struct hid_device_id hid_quirks[] = { · 123 unmodified lines | ||
| 124 | 124 | { HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT }, |
| 125 | 125 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL }, |
| 126 | 126 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS }, |
| 127 | + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER), HID_QUIRK_NO_INIT_REPORTS }, | |
| 127 | 128 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS }, |
| 128 | 129 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, |
| 129 | 130 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, |
| @@ -344,6 +344,9 @@ static int arvo_probe(struct hid_device *hdev, · 343 unmodified lines | ||
| 344 | 344 | { |
| 345 | 345 | int retval; |
| 346 | 346 | |
| 347 | + if (!hid_is_usb(hdev)) | |
| 348 | + return -EINVAL; | |
| 349 | + | |
| 347 | 350 | retval = hid_parse(hdev); |
| 348 | 351 | if (retval) { |
| 349 | 352 | hid_err(hdev, "parse failed\n"); |
| @@ -324,6 +324,9 @@ static int isku_probe(struct hid_device *hdev, · 323 unmodified lines | ||
| 324 | 324 | { |
| 325 | 325 | int retval; |
| 326 | 326 | |
| 327 | + if (!hid_is_usb(hdev)) | |
| 328 | + return -EINVAL; | |
| 329 | + | |
| 327 | 330 | retval = hid_parse(hdev); |
| 328 | 331 | if (retval) { |
| 329 | 332 | hid_err(hdev, "parse failed\n"); |
| @@ -749,6 +749,9 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) · 748 unmodified lines | ||
| 749 | 749 | { |
| 750 | 750 | int retval; |
| 751 | 751 | |
| 752 | + if (!hid_is_usb(hdev)) | |
| 753 | + return -EINVAL; | |
| 754 | + | |
| 752 | 755 | retval = hid_parse(hdev); |
| 753 | 756 | if (retval) { |
| 754 | 757 | hid_err(hdev, "parse failed\n"); |
| @@ -431,6 +431,9 @@ static int koneplus_probe(struct hid_device *hdev, · 430 unmodified lines | ||
| 431 | 431 | { |
| 432 | 432 | int retval; |
| 433 | 433 | |
| 434 | + if (!hid_is_usb(hdev)) | |
| 435 | + return -EINVAL; | |
| 436 | + | |
| 434 | 437 | retval = hid_parse(hdev); |
| 435 | 438 | if (retval) { |
| 436 | 439 | hid_err(hdev, "parse failed\n"); |
| @@ -133,6 +133,9 @@ static int konepure_probe(struct hid_device *hdev, · 132 unmodified lines | ||
| 133 | 133 | { |
| 134 | 134 | int retval; |
| 135 | 135 | |
| 136 | + if (!hid_is_usb(hdev)) | |
| 137 | + return -EINVAL; | |
| 138 | + | |
| 136 | 139 | retval = hid_parse(hdev); |
| 137 | 140 | if (retval) { |
| 138 | 141 | hid_err(hdev, "parse failed\n"); |
| @@ -501,6 +501,9 @@ static int kovaplus_probe(struct hid_device *hdev, · 500 unmodified lines | ||
| 501 | 501 | { |
| 502 | 502 | int retval; |
| 503 | 503 | |
| 504 | + if (!hid_is_usb(hdev)) | |
| 505 | + return -EINVAL; | |
| 506 | + | |
| 504 | 507 | retval = hid_parse(hdev); |
| 505 | 508 | if (retval) { |
| 506 | 509 | hid_err(hdev, "parse failed\n"); |
| @@ -160,6 +160,9 @@ static int lua_probe(struct hid_device *hdev, · 159 unmodified lines | ||
| 160 | 160 | { |
| 161 | 161 | int retval; |
| 162 | 162 | |
| 163 | + if (!hid_is_usb(hdev)) | |
| 164 | + return -EINVAL; | |
| 165 | + | |
| 163 | 166 | retval = hid_parse(hdev); |
| 164 | 167 | if (retval) { |
| 165 | 168 | hid_err(hdev, "parse failed\n"); |
| @@ -449,6 +449,9 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) · 448 unmodified lines | ||
| 449 | 449 | { |
| 450 | 450 | int retval; |
| 451 | 451 | |
| 452 | + if (!hid_is_usb(hdev)) | |
| 453 | + return -EINVAL; | |
| 454 | + | |
| 452 | 455 | retval = hid_parse(hdev); |
| 453 | 456 | if (retval) { |
| 454 | 457 | hid_err(hdev, "parse failed\n"); |
| @@ -141,6 +141,9 @@ static int ryos_probe(struct hid_device *hdev, · 140 unmodified lines | ||
| 141 | 141 | { |
| 142 | 142 | int retval; |
| 143 | 143 | |
| 144 | + if (!hid_is_usb(hdev)) | |
| 145 | + return -EINVAL; | |
| 146 | + | |
| 144 | 147 | retval = hid_parse(hdev); |
| 145 | 148 | if (retval) { |
| 146 | 149 | hid_err(hdev, "parse failed\n"); |
| @@ -113,6 +113,9 @@ static int savu_probe(struct hid_device *hdev, · 112 unmodified lines | ||
| 113 | 113 | { |
| 114 | 114 | int retval; |
| 115 | 115 | |
| 116 | + if (!hid_is_usb(hdev)) | |
| 117 | + return -EINVAL; | |
| 118 | + | |
| 116 | 119 | retval = hid_parse(hdev); |
| 117 | 120 | if (retval) { |
| 118 | 121 | hid_err(hdev, "parse failed\n"); |
| @@ -152,6 +152,9 @@ static int samsung_probe(struct hid_device *hdev, · 151 unmodified lines | ||
| 152 | 152 | int ret; |
| 153 | 153 | unsigned int cmask = HID_CONNECT_DEFAULT; |
| 154 | 154 | |
| 155 | + if (!hid_is_usb(hdev)) | |
| 156 | + return -EINVAL; | |
| 157 | + | |
| 155 | 158 | ret = hid_parse(hdev); |
| 156 | 159 | if (ret) { |
| 157 | 160 | hid_err(hdev, "parse failed\n"); |
| @@ -3000,7 +3000,6 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 2999 unmodified lines | ||
| 3000 | 3000 | sc->quirks = quirks; |
| 3001 | 3001 | hid_set_drvdata(hdev, sc); |
| 3002 | 3002 | sc->hdev = hdev; |
| 3003 | − usbdev = to_usb_device(sc->hdev->dev.parent->parent); | |
| 3004 | 3003 | |
| 3005 | 3004 | ret = hid_parse(hdev); |
| 3006 | 3005 | if (ret) { |
| @@ -3038,14 +3037,23 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 31 unmodified lines | ||
| 3038 | 3037 | */ |
| 3039 | 3038 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) { |
| 3040 | 3039 | hid_err(hdev, "failed to claim input\n"); |
| 3041 | − hid_hw_stop(hdev); | |
| 3042 | − return -ENODEV; | |
| 3040 | + ret = -ENODEV; | |
| 3041 | + goto err; | |
| 3043 | 3042 | } |
| 3044 | 3043 | |
| 3045 | 3044 | if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { |
| 3045 | + if (!hid_is_usb(hdev)) { | |
| 3046 | + ret = -EINVAL; | |
| 3047 | + goto err; | |
| 3048 | + } | |
| 3049 | + | |
| 3050 | + usbdev = to_usb_device(sc->hdev->dev.parent->parent); | |
| 3051 | + | |
| 3046 | 3052 | sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC); |
| 3047 | − if (!sc->ghl_urb) | |
| 3048 | − return -ENOMEM; | |
| 3053 | + if (!sc->ghl_urb) { | |
| 3054 | + ret = -ENOMEM; | |
| 3055 | + goto err; | |
| 3056 | + } | |
| 3049 | 3057 | |
| 3050 | 3058 | if (sc->quirks & GHL_GUITAR_PS3WIIU) |
| 3051 | 3059 | ret = ghl_init_urb(sc, usbdev, ghl_ps3wiiu_magic_data, |
| @@ -3055,7 +3063,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 3 unmodified lines | ||
| 3055 | 3063 | ARRAY_SIZE(ghl_ps4_magic_data)); |
| 3056 | 3064 | if (ret) { |
| 3057 | 3065 | hid_err(hdev, "error preparing URB\n"); |
| 3058 | − return ret; | |
| 3066 | + goto err; | |
| 3059 | 3067 | } |
| 3060 | 3068 | |
| 3061 | 3069 | timer_setup(&sc->ghl_poke_timer, ghl_magic_poke, 0); |
| @@ -3064,6 +3072,10 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 2 unmodified lines | ||
| 3064 | 3072 | } |
| 3065 | 3073 | |
| 3066 | 3074 | return ret; |
| 3075 | + | |
| 3076 | +err: | |
| 3077 | + hid_hw_stop(hdev); | |
| 3078 | + return ret; | |
| 3067 | 3079 | } |
| 3068 | 3080 | |
| 3069 | 3081 | static void sony_remove(struct hid_device *hdev) |
| @@ -274,6 +274,9 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i · 273 unmodified lines | ||
| 274 | 274 | int ret = 0; |
| 275 | 275 | struct tm_wheel *tm_wheel = NULL; |
| 276 | 276 | |
| 277 | + if (!hid_is_usb(hdev)) | |
| 278 | + return -EINVAL; | |
| 279 | + | |
| 277 | 280 | ret = hid_parse(hdev); |
| 278 | 281 | if (ret) { |
| 279 | 282 | hid_err(hdev, "parse failed with error %d\n", ret); |
| @@ -311,7 +311,7 @@ static int u2fzero_probe(struct hid_device *hdev, · 310 unmodified lines | ||
| 311 | 311 | unsigned int minor; |
| 312 | 312 | int ret; |
| 313 | 313 | |
| 314 | − if (!hid_is_using_ll_driver(hdev, &usb_hid_driver)) | |
| 314 | + if (!hid_is_usb(hdev)) | |
| 315 | 315 | return -EINVAL; |
| 316 | 316 | |
| 317 | 317 | dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); |
| @@ -164,6 +164,9 @@ static int uclogic_probe(struct hid_device *hdev, · 163 unmodified lines | ||
| 164 | 164 | struct uclogic_drvdata *drvdata = NULL; |
| 165 | 165 | bool params_initialized = false; |
| 166 | 166 | |
| 167 | + if (!hid_is_usb(hdev)) | |
| 168 | + return -EINVAL; | |
| 169 | + | |
| 167 | 170 | /* |
| 168 | 171 | * libinput requires the pad interface to be on a different node |
| 169 | 172 | * than the pen, so use QUIRK_MULTI_INPUT for all tablets. |
| @@ -843,8 +843,7 @@ int uclogic_params_init(struct uclogic_params *params, · 842 unmodified lines | ||
| 843 | 843 | struct uclogic_params p = {0, }; |
| 844 | 844 | |
| 845 | 845 | /* Check arguments */ |
| 846 | − if (params == NULL || hdev == NULL || | |
| 847 | − !hid_is_using_ll_driver(hdev, &usb_hid_driver)) { | |
| 846 | + if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) { | |
| 848 | 847 | rc = -EINVAL; |
| 849 | 848 | goto cleanup; |
| 850 | 849 | } |
| @@ -266,7 +266,8 @@ static void __maybe_unused ish_resume_handler(struct work_struct *work) · 265 unmodified lines | ||
| 266 | 266 | |
| 267 | 267 | if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag |
| 268 | 268 | && IPC_IS_ISH_ILUP(fwsts)) { |
| 269 | − disable_irq_wake(pdev->irq); | |
| 269 | + if (device_may_wakeup(&pdev->dev)) | |
| 270 | + disable_irq_wake(pdev->irq); | |
| 270 | 271 | |
| 271 | 272 | ish_set_host_ready(dev); |
| 272 | 273 | |
| @@ -337,7 +338,8 @@ static int __maybe_unused ish_suspend(struct device *device) · 64 unmodified lines | ||
| 337 | 338 | */ |
| 338 | 339 | pci_save_state(pdev); |
| 339 | 340 | |
| 340 | − enable_irq_wake(pdev->irq); | |
| 341 | + if (device_may_wakeup(&pdev->dev)) | |
| 342 | + enable_irq_wake(pdev->irq); | |
| 341 | 343 | } |
| 342 | 344 | } else { |
| 343 | 345 | /* |
| @@ -726,7 +726,7 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, · 725 unmodified lines | ||
| 726 | 726 | * Skip the query for this type and modify defaults based on |
| 727 | 727 | * interface number. |
| 728 | 728 | */ |
| 729 | − if (features->type == WIRELESS) { | |
| 729 | + if (features->type == WIRELESS && intf) { | |
| 730 | 730 | if (intf->cur_altsetting->desc.bInterfaceNumber == 0) |
| 731 | 731 | features->device_type = WACOM_DEVICETYPE_WL_MONITOR; |
| 732 | 732 | else |
| @@ -2214,7 +2214,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) · 1481 unmodified lines | ||
| 2214 | 2214 | if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) { |
| 2215 | 2215 | char *product_name = wacom->hdev->name; |
| 2216 | 2216 | |
| 2217 | − if (hid_is_using_ll_driver(wacom->hdev, &usb_hid_driver)) { | |
| 2217 | + if (hid_is_usb(wacom->hdev)) { | |
| 2218 | 2218 | struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent); |
| 2219 | 2219 | struct usb_device *dev = interface_to_usbdev(intf); |
| 2220 | 2220 | product_name = dev->product; |
| @@ -2451,6 +2451,9 @@ static void wacom_wireless_work(struct work_struct *work) · 230 unmodified lines | ||
| 2451 | 2451 | |
| 2452 | 2452 | wacom_destroy_battery(wacom); |
| 2453 | 2453 | |
| 2454 | + if (!usbdev) | |
| 2455 | + return; | |
| 2456 | + | |
| 2454 | 2457 | /* Stylus interface */ |
| 2455 | 2458 | hdev1 = usb_get_intfdata(usbdev->config->interface[1]); |
| 2456 | 2459 | wacom1 = hid_get_drvdata(hdev1); |
| @@ -2730,8 +2733,6 @@ static void wacom_mode_change_work(struct work_struct *work) · 273 unmodified lines | ||
| 2730 | 2733 | static int wacom_probe(struct hid_device *hdev, |
| 2731 | 2734 | const struct hid_device_id *id) |
| 2732 | 2735 | { |
| 2733 | − struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 2734 | − struct usb_device *dev = interface_to_usbdev(intf); | |
| 2735 | 2736 | struct wacom *wacom; |
| 2736 | 2737 | struct wacom_wac *wacom_wac; |
| 2737 | 2738 | struct wacom_features *features; |
| @@ -2766,8 +2767,14 @@ static int wacom_probe(struct hid_device *hdev, · 28 unmodified lines | ||
| 2766 | 2767 | wacom_wac->hid_data.inputmode = -1; |
| 2767 | 2768 | wacom_wac->mode_report = -1; |
| 2768 | 2769 | |
| 2769 | − wacom->usbdev = dev; | |
| 2770 | − wacom->intf = intf; | |
| 2770 | + if (hid_is_usb(hdev)) { | |
| 2771 | + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 2772 | + struct usb_device *dev = interface_to_usbdev(intf); | |
| 2773 | + | |
| 2774 | + wacom->usbdev = dev; | |
| 2775 | + wacom->intf = intf; | |
| 2776 | + } | |
| 2777 | + | |
| 2771 | 2778 | mutex_init(&wacom->lock); |
| 2772 | 2779 | INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work); |
| 2773 | 2780 | INIT_WORK(&wacom->wireless_work, wacom_wireless_work); |
| @@ -729,7 +729,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id · 728 unmodified lines | ||
| 729 | 729 | corsairpsu_check_cmd_support(priv); |
| 730 | 730 | |
| 731 | 731 | priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsairpsu", priv, |
| 732 | − &corsairpsu_chip_info, 0); | |
| 732 | + &corsairpsu_chip_info, NULL); | |
| 733 | 733 | |
| 734 | 734 | if (IS_ERR(priv->hwmon_dev)) { |
| 735 | 735 | ret = PTR_ERR(priv->hwmon_dev); |
| @@ -627,10 +627,9 @@ static void __init i8k_init_procfs(struct device *dev) · 626 unmodified lines | ||
| 627 | 627 | { |
| 628 | 628 | struct dell_smm_data *data = dev_get_drvdata(dev); |
| 629 | 629 | |
| 630 | − /* Register the proc entry */ | |
| 631 | − proc_create_data("i8k", 0, NULL, &i8k_proc_ops, data); | |
| 632 | − | |
| 633 | − devm_add_action_or_reset(dev, i8k_exit_procfs, NULL); | |
| 630 | + /* Only register exit function if creation was successful */ | |
| 631 | + if (proc_create_data("i8k", 0, NULL, &i8k_proc_ops, data)) | |
| 632 | + devm_add_action_or_reset(dev, i8k_exit_procfs, NULL); | |
| 634 | 633 | } |
| 635 | 634 | |
| 636 | 635 | #else |
| @@ -1527,7 +1527,7 @@ static u16 nct6775_wmi_read_value(struct nct6775_data *data, u16 reg) · 1526 unmodified lines | ||
| 1527 | 1527 | |
| 1528 | 1528 | nct6775_wmi_set_bank(data, reg); |
| 1529 | 1529 | |
| 1530 | − err = nct6775_asuswmi_read(data->bank, reg, &tmp); | |
| 1530 | + err = nct6775_asuswmi_read(data->bank, reg & 0xff, &tmp); | |
| 1531 | 1531 | if (err) |
| 1532 | 1532 | return 0; |
| 1533 | 1533 | |
| @@ -336,8 +336,6 @@ static int pwm_fan_probe(struct platform_device *pdev) · 335 unmodified lines | ||
| 336 | 336 | return ret; |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | − ctx->pwm_value = MAX_PWM; | |
| 340 | − | |
| 341 | 339 | pwm_init_state(ctx->pwm, &ctx->pwm_state); |
| 342 | 340 | |
| 343 | 341 | /* |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | /* |
| 24 | 24 | * I2C command delays (in microseconds) |
| 25 | 25 | */ |
| 26 | −#define SHT4X_MEAS_DELAY 1000 | |
| 26 | +#define SHT4X_MEAS_DELAY_HPM 8200 /* see t_MEAS,h in datasheet */ | |
| 27 | 27 | #define SHT4X_DELAY_EXTRA 10000 |
| 28 | 28 | |
| 29 | 29 | /* |
| @@ -90,7 +90,7 @@ static int sht4x_read_values(struct sht4x_data *data) · 60 unmodified lines | ||
| 90 | 90 | if (ret < 0) |
| 91 | 91 | goto unlock; |
| 92 | 92 | |
| 93 | − usleep_range(SHT4X_MEAS_DELAY, SHT4X_MEAS_DELAY + SHT4X_DELAY_EXTRA); | |
| 93 | + usleep_range(SHT4X_MEAS_DELAY_HPM, SHT4X_MEAS_DELAY_HPM + SHT4X_DELAY_EXTRA); | |
| 94 | 94 | |
| 95 | 95 | ret = i2c_master_recv(client, raw_data, SHT4X_RESPONSE_LENGTH); |
| 96 | 96 | if (ret != SHT4X_RESPONSE_LENGTH) { |
| @@ -195,8 +195,9 @@ static u32 cbus_i2c_func(struct i2c_adapter *adapter) · 194 unmodified lines | ||
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | static const struct i2c_algorithm cbus_i2c_algo = { |
| 198 | − .smbus_xfer = cbus_i2c_smbus_xfer, | |
| 199 | − .functionality = cbus_i2c_func, | |
| 198 | + .smbus_xfer = cbus_i2c_smbus_xfer, | |
| 199 | + .smbus_xfer_atomic = cbus_i2c_smbus_xfer, | |
| 200 | + .functionality = cbus_i2c_func, | |
| 200 | 201 | }; |
| 201 | 202 | |
| 202 | 203 | static int cbus_i2c_remove(struct platform_device *pdev) |
| @@ -636,7 +636,7 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) · 635 unmodified lines | ||
| 636 | 636 | status = readb(i2c->base + MPC_I2C_SR); |
| 637 | 637 | if (status & CSR_MIF) { |
| 638 | 638 | /* Wait up to 100us for transfer to properly complete */ |
| 639 | − readb_poll_timeout(i2c->base + MPC_I2C_SR, status, !(status & CSR_MCF), 0, 100); | |
| 639 | + readb_poll_timeout_atomic(i2c->base + MPC_I2C_SR, status, status & CSR_MCF, 0, 100); | |
| 640 | 640 | writeb(0, i2c->base + MPC_I2C_SR); |
| 641 | 641 | mpc_i2c_do_intr(i2c, status); |
| 642 | 642 | return IRQ_HANDLED; |
| @@ -423,8 +423,8 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) · 422 unmodified lines | ||
| 423 | 423 | if (!(ipd & REG_INT_MBRF)) |
| 424 | 424 | return; |
| 425 | 425 | |
| 426 | − /* ack interrupt */ | |
| 427 | − i2c_writel(i2c, REG_INT_MBRF, REG_IPD); | |
| 426 | + /* ack interrupt (read also produces a spurious START flag, clear it too) */ | |
| 427 | + i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD); | |
| 428 | 428 | |
| 429 | 429 | /* Can only handle a maximum of 32 bytes at a time */ |
| 430 | 430 | if (len > 32) |
| @@ -1493,6 +1493,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) · 1492 unmodified lines | ||
| 1493 | 1493 | { |
| 1494 | 1494 | struct stm32f7_i2c_dev *i2c_dev = data; |
| 1495 | 1495 | struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; |
| 1496 | + struct stm32_i2c_dma *dma = i2c_dev->dma; | |
| 1496 | 1497 | void __iomem *base = i2c_dev->base; |
| 1497 | 1498 | u32 status, mask; |
| 1498 | 1499 | int ret = IRQ_HANDLED; |
| @@ -1518,6 +1519,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) · 19 unmodified lines | ||
| 1518 | 1519 | dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", |
| 1519 | 1520 | __func__, f7_msg->addr); |
| 1520 | 1521 | writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); |
| 1522 | + if (i2c_dev->use_dma) { | |
| 1523 | + stm32f7_i2c_disable_dma_req(i2c_dev); | |
| 1524 | + dmaengine_terminate_async(dma->chan_using); | |
| 1525 | + } | |
| 1521 | 1526 | f7_msg->result = -ENXIO; |
| 1522 | 1527 | } |
| 1523 | 1528 | |
| @@ -1533,7 +1538,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) · 9 unmodified lines | ||
| 1533 | 1538 | /* Clear STOP flag */ |
| 1534 | 1539 | writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); |
| 1535 | 1540 | |
| 1536 | − if (i2c_dev->use_dma) { | |
| 1541 | + if (i2c_dev->use_dma && !f7_msg->result) { | |
| 1537 | 1542 | ret = IRQ_WAKE_THREAD; |
| 1538 | 1543 | } else { |
| 1539 | 1544 | i2c_dev->master_mode = false; |
| @@ -1546,7 +1551,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) · 6 unmodified lines | ||
| 1546 | 1551 | if (f7_msg->stop) { |
| 1547 | 1552 | mask = STM32F7_I2C_CR2_STOP; |
| 1548 | 1553 | stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask); |
| 1549 | − } else if (i2c_dev->use_dma) { | |
| 1554 | + } else if (i2c_dev->use_dma && !f7_msg->result) { | |
| 1550 | 1555 | ret = IRQ_WAKE_THREAD; |
| 1551 | 1556 | } else if (f7_msg->smbus) { |
| 1552 | 1557 | stm32f7_i2c_smbus_rep_start(i2c_dev); |
| @@ -1583,7 +1588,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data) · 30 unmodified lines | ||
| 1583 | 1588 | if (!ret) { |
| 1584 | 1589 | dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); |
| 1585 | 1590 | stm32f7_i2c_disable_dma_req(i2c_dev); |
| 1586 | − dmaengine_terminate_all(dma->chan_using); | |
| 1591 | + dmaengine_terminate_async(dma->chan_using); | |
| 1587 | 1592 | f7_msg->result = -ETIMEDOUT; |
| 1588 | 1593 | } |
| 1589 | 1594 | |
| @@ -1660,7 +1665,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) · 70 unmodified lines | ||
| 1660 | 1665 | /* Disable dma */ |
| 1661 | 1666 | if (i2c_dev->use_dma) { |
| 1662 | 1667 | stm32f7_i2c_disable_dma_req(i2c_dev); |
| 1663 | − dmaengine_terminate_all(dma->chan_using); | |
| 1668 | + dmaengine_terminate_async(dma->chan_using); | |
| 1664 | 1669 | } |
| 1665 | 1670 | |
| 1666 | 1671 | i2c_dev->master_mode = false; |
| @@ -1696,12 +1701,26 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, · 29 unmodified lines | ||
| 1696 | 1701 | time_left = wait_for_completion_timeout(&i2c_dev->complete, |
| 1697 | 1702 | i2c_dev->adap.timeout); |
| 1698 | 1703 | ret = f7_msg->result; |
| 1704 | + if (ret) { | |
| 1705 | + if (i2c_dev->use_dma) | |
| 1706 | + dmaengine_synchronize(dma->chan_using); | |
| 1707 | + | |
| 1708 | + /* | |
| 1709 | + * It is possible that some unsent data have already been | |
| 1710 | + * written into TXDR. To avoid sending old data in a | |
| 1711 | + * further transfer, flush TXDR in case of any error | |
| 1712 | + */ | |
| 1713 | + writel_relaxed(STM32F7_I2C_ISR_TXE, | |
| 1714 | + i2c_dev->base + STM32F7_I2C_ISR); | |
| 1715 | + goto pm_free; | |
| 1716 | + } | |
| 1699 | 1717 | |
| 1700 | 1718 | if (!time_left) { |
| 1701 | 1719 | dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n", |
| 1702 | 1720 | i2c_dev->msg->addr); |
| 1703 | 1721 | if (i2c_dev->use_dma) |
| 1704 | − dmaengine_terminate_all(dma->chan_using); | |
| 1722 | + dmaengine_terminate_sync(dma->chan_using); | |
| 1723 | + stm32f7_i2c_wait_free_bus(i2c_dev); | |
| 1705 | 1724 | ret = -ETIMEDOUT; |
| 1706 | 1725 | } |
| 1707 | 1726 | |
| @@ -1744,13 +1763,25 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, · 36 unmodified lines | ||
| 1744 | 1763 | timeout = wait_for_completion_timeout(&i2c_dev->complete, |
| 1745 | 1764 | i2c_dev->adap.timeout); |
| 1746 | 1765 | ret = f7_msg->result; |
| 1747 | − if (ret) | |
| 1766 | + if (ret) { | |
| 1767 | + if (i2c_dev->use_dma) | |
| 1768 | + dmaengine_synchronize(dma->chan_using); | |
| 1769 | + | |
| 1770 | + /* | |
| 1771 | + * It is possible that some unsent data have already been | |
| 1772 | + * written into TXDR. To avoid sending old data in a | |
| 1773 | + * further transfer, flush TXDR in case of any error | |
| 1774 | + */ | |
| 1775 | + writel_relaxed(STM32F7_I2C_ISR_TXE, | |
| 1776 | + i2c_dev->base + STM32F7_I2C_ISR); | |
| 1748 | 1777 | goto pm_free; |
| 1778 | + } | |
| 1749 | 1779 | |
| 1750 | 1780 | if (!timeout) { |
| 1751 | 1781 | dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr); |
| 1752 | 1782 | if (i2c_dev->use_dma) |
| 1753 | − dmaengine_terminate_all(dma->chan_using); | |
| 1783 | + dmaengine_terminate_sync(dma->chan_using); | |
| 1784 | + stm32f7_i2c_wait_free_bus(i2c_dev); | |
| 1754 | 1785 | ret = -ETIMEDOUT; |
| 1755 | 1786 | goto pm_free; |
| 1756 | 1787 | } |
| @@ -22,24 +22,24 @@ · 21 unmodified lines | ||
| 22 | 22 | /** |
| 23 | 23 | * struct virtio_i2c - virtio I2C data |
| 24 | 24 | * @vdev: virtio device for this controller |
| 25 | − * @completion: completion of virtio I2C message | |
| 26 | 25 | * @adap: I2C adapter for this controller |
| 27 | 26 | * @vq: the virtio virtqueue for communication |
| 28 | 27 | */ |
| 29 | 28 | struct virtio_i2c { |
| 30 | 29 | struct virtio_device *vdev; |
| 31 | − struct completion completion; | |
| 32 | 30 | struct i2c_adapter adap; |
| 33 | 31 | struct virtqueue *vq; |
| 34 | 32 | }; |
| 35 | 33 | |
| 36 | 34 | /** |
| 37 | 35 | * struct virtio_i2c_req - the virtio I2C request structure |
| 36 | + * @completion: completion of virtio I2C message | |
| 38 | 37 | * @out_hdr: the OUT header of the virtio I2C message |
| 39 | 38 | * @buf: the buffer into which data is read, or from which it's written |
| 40 | 39 | * @in_hdr: the IN header of the virtio I2C message |
| 41 | 40 | */ |
| 42 | 41 | struct virtio_i2c_req { |
| 42 | + struct completion completion; | |
| 43 | 43 | struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned; |
| 44 | 44 | uint8_t *buf ____cacheline_aligned; |
| 45 | 45 | struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned; |
| @@ -47,9 +47,11 @@ struct virtio_i2c_req { · 1 unmodified line | ||
| 47 | 47 | |
| 48 | 48 | static void virtio_i2c_msg_done(struct virtqueue *vq) |
| 49 | 49 | { |
| 50 | − struct virtio_i2c *vi = vq->vdev->priv; | |
| 50 | + struct virtio_i2c_req *req; | |
| 51 | + unsigned int len; | |
| 51 | 52 | |
| 52 | − complete(&vi->completion); | |
| 53 | + while ((req = virtqueue_get_buf(vq, &len))) | |
| 54 | + complete(&req->completion); | |
| 53 | 55 | } |
| 54 | 56 | |
| 55 | 57 | static int virtio_i2c_prepare_reqs(struct virtqueue *vq, |
| @@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, · 6 unmodified lines | ||
| 62 | 64 | for (i = 0; i < num; i++) { |
| 63 | 65 | int outcnt = 0, incnt = 0; |
| 64 | 66 | |
| 67 | + init_completion(&reqs[i].completion); | |
| 68 | + | |
| 65 | 69 | /* |
| 66 | 70 | * Only 7-bit mode supported for this moment. For the address |
| 67 | 71 | * format, Please check the Virtio I2C Specification. |
| @@ -106,21 +110,15 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, · 38 unmodified lines | ||
| 106 | 110 | struct virtio_i2c_req *reqs, |
| 107 | 111 | struct i2c_msg *msgs, int num) |
| 108 | 112 | { |
| 109 | − struct virtio_i2c_req *req; | |
| 110 | 113 | bool failed = false; |
| 111 | − unsigned int len; | |
| 112 | 114 | int i, j = 0; |
| 113 | 115 | |
| 114 | 116 | for (i = 0; i < num; i++) { |
| 115 | − /* Detach the ith request from the vq */ | |
| 116 | − req = virtqueue_get_buf(vq, &len); | |
| 117 | + struct virtio_i2c_req *req = &reqs[i]; | |
| 117 | 118 | |
| 118 | − /* | |
| 119 | − * Condition req == &reqs[i] should always meet since we have | |
| 120 | − * total num requests in the vq. reqs[i] can never be NULL here. | |
| 121 | − */ | |
| 122 | − if (!failed && (WARN_ON(req != &reqs[i]) || | |
| 123 | − req->in_hdr.status != VIRTIO_I2C_MSG_OK)) | |
| 119 | + wait_for_completion(&req->completion); | |
| 120 | + | |
| 121 | + if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) | |
| 124 | 122 | failed = true; |
| 125 | 123 | |
| 126 | 124 | i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); |
| @@ -156,12 +154,8 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, · 29 unmodified lines | ||
| 156 | 154 | * remote here to clear the virtqueue, so we can try another set of |
| 157 | 155 | * messages later on. |
| 158 | 156 | */ |
| 159 | − | |
| 160 | − reinit_completion(&vi->completion); | |
| 161 | 157 | virtqueue_kick(vq); |
| 162 | 158 | |
| 163 | − wait_for_completion(&vi->completion); | |
| 164 | − | |
| 165 | 159 | count = virtio_i2c_complete_reqs(vq, reqs, msgs, count); |
| 166 | 160 | |
| 167 | 161 | err_free: |
| @@ -210,8 +204,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev) · 42 unmodified lines | ||
| 210 | 204 | vdev->priv = vi; |
| 211 | 205 | vi->vdev = vdev; |
| 212 | 206 | |
| 213 | − init_completion(&vi->completion); | |
| 214 | − | |
| 215 | 207 | ret = virtio_i2c_setup_vqs(vi); |
| 216 | 208 | if (ret) |
| 217 | 209 | return ret; |
| @@ -1595,8 +1595,7 @@ static int kxcjk1013_probe(struct i2c_client *client, · 1594 unmodified lines | ||
| 1595 | 1595 | return 0; |
| 1596 | 1596 | |
| 1597 | 1597 | err_buffer_cleanup: |
| 1598 | − if (data->dready_trig) | |
| 1599 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1598 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1600 | 1599 | err_trigger_unregister: |
| 1601 | 1600 | if (data->dready_trig) |
| 1602 | 1601 | iio_trigger_unregister(data->dready_trig); |
| @@ -1618,8 +1617,8 @@ static int kxcjk1013_remove(struct i2c_client *client) · 15 unmodified lines | ||
| 1618 | 1617 | pm_runtime_disable(&client->dev); |
| 1619 | 1618 | pm_runtime_set_suspended(&client->dev); |
| 1620 | 1619 | |
| 1620 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1621 | 1621 | if (data->dready_trig) { |
| 1622 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1623 | 1622 | iio_trigger_unregister(data->dready_trig); |
| 1624 | 1623 | iio_trigger_unregister(data->motion_trig); |
| 1625 | 1624 | } |
| @@ -224,14 +224,14 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p) · 223 unmodified lines | ||
| 224 | 224 | hw_values.chan, |
| 225 | 225 | sizeof(hw_values.chan)); |
| 226 | 226 | if (ret) { |
| 227 | − dev_err(st->dev, | |
| 228 | − "error reading data\n"); | |
| 229 | − return ret; | |
| 227 | + dev_err(st->dev, "error reading data: %d\n", ret); | |
| 228 | + goto out; | |
| 230 | 229 | } |
| 231 | 230 | |
| 232 | 231 | iio_push_to_buffers_with_timestamp(indio_dev, |
| 233 | 232 | &hw_values, |
| 234 | 233 | iio_get_time_ns(indio_dev)); |
| 234 | +out: | |
| 235 | 235 | iio_trigger_notify_done(indio_dev->trig); |
| 236 | 236 | |
| 237 | 237 | return IRQ_HANDLED; |
| @@ -1470,7 +1470,7 @@ static int mma8452_trigger_setup(struct iio_dev *indio_dev) · 1469 unmodified lines | ||
| 1470 | 1470 | if (ret) |
| 1471 | 1471 | return ret; |
| 1472 | 1472 | |
| 1473 | − indio_dev->trig = trig; | |
| 1473 | + indio_dev->trig = iio_trigger_get(trig); | |
| 1474 | 1474 | |
| 1475 | 1475 | return 0; |
| 1476 | 1476 | } |
| @@ -532,7 +532,7 @@ config IMX7D_ADC · 531 unmodified lines | ||
| 532 | 532 | |
| 533 | 533 | config IMX8QXP_ADC |
| 534 | 534 | tristate "NXP IMX8QXP ADC driver" |
| 535 | − depends on ARCH_MXC_ARM64 || COMPILE_TEST | |
| 535 | + depends on ARCH_MXC || COMPILE_TEST | |
| 536 | 536 | depends on HAS_IOMEM |
| 537 | 537 | help |
| 538 | 538 | Say yes here to build support for IMX8QXP ADC. |
| @@ -480,8 +480,8 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p) · 479 unmodified lines | ||
| 480 | 480 | iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan, |
| 481 | 481 | iio_get_time_ns(indio_dev)); |
| 482 | 482 | |
| 483 | − iio_trigger_notify_done(indio_dev->trig); | |
| 484 | 483 | err_unlock: |
| 484 | + iio_trigger_notify_done(indio_dev->trig); | |
| 485 | 485 | mutex_unlock(&st->lock); |
| 486 | 486 | |
| 487 | 487 | return IRQ_HANDLED; |
| @@ -1586,7 +1586,8 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, · 1585 unmodified lines | ||
| 1586 | 1586 | *val = st->conversion_value; |
| 1587 | 1587 | ret = at91_adc_adjust_val_osr(st, val); |
| 1588 | 1588 | if (chan->scan_type.sign == 's') |
| 1589 | − *val = sign_extend32(*val, 11); | |
| 1589 | + *val = sign_extend32(*val, | |
| 1590 | + chan->scan_type.realbits - 1); | |
| 1590 | 1591 | st->conversion_done = false; |
| 1591 | 1592 | } |
| 1592 | 1593 | |
| @@ -251,19 +251,8 @@ static int axp22x_adc_raw(struct iio_dev *indio_dev, · 250 unmodified lines | ||
| 251 | 251 | struct iio_chan_spec const *chan, int *val) |
| 252 | 252 | { |
| 253 | 253 | struct axp20x_adc_iio *info = iio_priv(indio_dev); |
| 254 | − int size; | |
| 255 | 254 | |
| 256 | − /* | |
| 257 | − * N.B.: Unlike the Chinese datasheets tell, the charging current is | |
| 258 | − * stored on 12 bits, not 13 bits. Only discharging current is on 13 | |
| 259 | − * bits. | |
| 260 | − */ | |
| 261 | − if (chan->type == IIO_CURRENT && chan->channel == AXP22X_BATT_DISCHRG_I) | |
| 262 | − size = 13; | |
| 263 | − else | |
| 264 | − size = 12; | |
| 265 | − | |
| 266 | − *val = axp20x_read_variable_width(info->regmap, chan->address, size); | |
| 255 | + *val = axp20x_read_variable_width(info->regmap, chan->address, 12); | |
| 267 | 256 | if (*val < 0) |
| 268 | 257 | return *val; |
| 269 | 258 | |
| @@ -386,9 +375,8 @@ static int axp22x_adc_scale(struct iio_chan_spec const *chan, int *val, · 116 unmodified lines | ||
| 386 | 375 | return IIO_VAL_INT_PLUS_MICRO; |
| 387 | 376 | |
| 388 | 377 | case IIO_CURRENT: |
| 389 | − *val = 0; | |
| 390 | − *val2 = 500000; | |
| 391 | − return IIO_VAL_INT_PLUS_MICRO; | |
| 378 | + *val = 1; | |
| 379 | + return IIO_VAL_INT; | |
| 392 | 380 | |
| 393 | 381 | case IIO_TEMP: |
| 394 | 382 | *val = 100; |
| @@ -248,7 +248,6 @@ static int dln2_adc_set_chan_period(struct dln2_adc *dln2, · 247 unmodified lines | ||
| 248 | 248 | static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) |
| 249 | 249 | { |
| 250 | 250 | int ret, i; |
| 251 | − struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev); | |
| 252 | 251 | u16 conflict; |
| 253 | 252 | __le16 value; |
| 254 | 253 | int olen = sizeof(value); |
| @@ -257,13 +256,9 @@ static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel) · 2 unmodified lines | ||
| 257 | 256 | .chan = channel, |
| 258 | 257 | }; |
| 259 | 258 | |
| 260 | − ret = iio_device_claim_direct_mode(indio_dev); | |
| 261 | − if (ret < 0) | |
| 262 | − return ret; | |
| 263 | − | |
| 264 | 259 | ret = dln2_adc_set_chan_enabled(dln2, channel, true); |
| 265 | 260 | if (ret < 0) |
| 266 | − goto release_direct; | |
| 261 | + return ret; | |
| 267 | 262 | |
| 268 | 263 | ret = dln2_adc_set_port_enabled(dln2, true, &conflict); |
| 269 | 264 | if (ret < 0) { |
| @@ -300,8 +295,6 @@ disable_port: · 30 unmodified lines | ||
| 300 | 295 | dln2_adc_set_port_enabled(dln2, false, NULL); |
| 301 | 296 | disable_chan: |
| 302 | 297 | dln2_adc_set_chan_enabled(dln2, channel, false); |
| 303 | −release_direct: | |
| 304 | − iio_device_release_direct_mode(indio_dev); | |
| 305 | 298 | |
| 306 | 299 | return ret; |
| 307 | 300 | } |
| @@ -337,10 +330,16 @@ static int dln2_adc_read_raw(struct iio_dev *indio_dev, · 29 unmodified lines | ||
| 337 | 330 | |
| 338 | 331 | switch (mask) { |
| 339 | 332 | case IIO_CHAN_INFO_RAW: |
| 333 | + ret = iio_device_claim_direct_mode(indio_dev); | |
| 334 | + if (ret < 0) | |
| 335 | + return ret; | |
| 336 | + | |
| 340 | 337 | mutex_lock(&dln2->mutex); |
| 341 | 338 | ret = dln2_adc_read(dln2, chan->channel); |
| 342 | 339 | mutex_unlock(&dln2->mutex); |
| 343 | 340 | |
| 341 | + iio_device_release_direct_mode(indio_dev); | |
| 342 | + | |
| 344 | 343 | if (ret < 0) |
| 345 | 344 | return ret; |
| 346 | 345 | |
| @@ -656,7 +655,11 @@ static int dln2_adc_probe(struct platform_device *pdev) · 309 unmodified lines | ||
| 656 | 655 | return -ENOMEM; |
| 657 | 656 | } |
| 658 | 657 | iio_trigger_set_drvdata(dln2->trig, dln2); |
| 659 | − devm_iio_trigger_register(dev, dln2->trig); | |
| 658 | + ret = devm_iio_trigger_register(dev, dln2->trig); | |
| 659 | + if (ret) { | |
| 660 | + dev_err(dev, "failed to register trigger: %d\n", ret); | |
| 661 | + return ret; | |
| 662 | + } | |
| 660 | 663 | iio_trigger_set_immutable(indio_dev, dln2->trig); |
| 661 | 664 | |
| 662 | 665 | ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, |
| @@ -1117,6 +1117,7 @@ static void stm32h7_adc_unprepare(struct iio_dev *indio_dev) · 1116 unmodified lines | ||
| 1117 | 1117 | { |
| 1118 | 1118 | struct stm32_adc *adc = iio_priv(indio_dev); |
| 1119 | 1119 | |
| 1120 | + stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0); | |
| 1120 | 1121 | stm32h7_adc_disable(indio_dev); |
| 1121 | 1122 | stm32_adc_int_ch_disable(adc); |
| 1122 | 1123 | stm32h7_adc_enter_pwr_down(adc); |
| @@ -1986,7 +1987,7 @@ static int stm32_adc_populate_int_ch(struct iio_dev *indio_dev, const char *ch_n · 863 unmodified lines | ||
| 1986 | 1987 | /* Get calibration data for vrefint channel */ |
| 1987 | 1988 | ret = nvmem_cell_read_u16(&indio_dev->dev, "vrefint", &vrefint); |
| 1988 | 1989 | if (ret && ret != -ENOENT) { |
| 1989 | − return dev_err_probe(&indio_dev->dev, ret, | |
| 1990 | + return dev_err_probe(indio_dev->dev.parent, ret, | |
| 1990 | 1991 | "nvmem access error\n"); |
| 1991 | 1992 | } |
| 1992 | 1993 | if (ret == -ENOENT) |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | #include <linux/bitfield.h> |
| 10 | +#include <linux/bitops.h> | |
| 10 | 11 | #include <linux/delay.h> |
| 11 | 12 | #include <linux/device.h> |
| 12 | 13 | #include <linux/kernel.h> |
| @@ -124,7 +125,7 @@ static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int * · 111 unmodified lines | ||
| 124 | 125 | goto err_unlock; |
| 125 | 126 | } |
| 126 | 127 | |
| 127 | − *val = temp; | |
| 128 | + *val = sign_extend32(temp, 15); | |
| 128 | 129 | |
| 129 | 130 | err_unlock: |
| 130 | 131 | mutex_unlock(&st->lock); |
| @@ -146,7 +147,7 @@ static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val) · 15 unmodified lines | ||
| 146 | 147 | } |
| 147 | 148 | |
| 148 | 149 | /* extract lower 12 bits temperature reading */ |
| 149 | − *val = temp & 0x0FFF; | |
| 150 | + *val = sign_extend32(temp, 11); | |
| 150 | 151 | |
| 151 | 152 | err_unlock: |
| 152 | 153 | mutex_unlock(&st->lock); |
| @@ -61,9 +61,9 @@ static irqreturn_t itg3200_trigger_handler(int irq, void *p) · 60 unmodified lines | ||
| 61 | 61 | |
| 62 | 62 | iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); |
| 63 | 63 | |
| 64 | +error_ret: | |
| 64 | 65 | iio_trigger_notify_done(indio_dev->trig); |
| 65 | 66 | |
| 66 | −error_ret: | |
| 67 | 67 | return IRQ_HANDLED; |
| 68 | 68 | } |
| 69 | 69 | |
| @@ -556,7 +556,6 @@ struct iio_trigger *viio_trigger_alloc(struct device *parent, · 555 unmodified lines | ||
| 556 | 556 | irq_modify_status(trig->subirq_base + i, |
| 557 | 557 | IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); |
| 558 | 558 | } |
| 559 | − get_device(&trig->dev); | |
| 560 | 559 | |
| 561 | 560 | return trig; |
| 562 | 561 | |
| @@ -1275,7 +1275,7 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) · 1274 unmodified lines | ||
| 1275 | 1275 | ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, |
| 1276 | 1276 | als_buf, sizeof(als_buf)); |
| 1277 | 1277 | if (ret < 0) |
| 1278 | − return ret; | |
| 1278 | + goto done; | |
| 1279 | 1279 | if (test_bit(0, indio_dev->active_scan_mask)) |
| 1280 | 1280 | scan.channels[j++] = le16_to_cpu(als_buf[1]); |
| 1281 | 1281 | if (test_bit(1, indio_dev->active_scan_mask)) |
| @@ -546,9 +546,8 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) · 545 unmodified lines | ||
| 546 | 546 | mutex_lock(&data->lock); |
| 547 | 547 | ret = regmap_field_read(data->reg_flag_nf, &dir); |
| 548 | 548 | if (ret < 0) { |
| 549 | − dev_err(&data->client->dev, "register read failed\n"); | |
| 550 | − mutex_unlock(&data->lock); | |
| 551 | − return ret; | |
| 549 | + dev_err(&data->client->dev, "register read failed: %d\n", ret); | |
| 550 | + goto out; | |
| 552 | 551 | } |
| 553 | 552 | event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, |
| 554 | 553 | IIO_EV_TYPE_THRESH, |
| @@ -560,6 +559,7 @@ static irqreturn_t stk3310_irq_event_handler(int irq, void *private) · 5 unmodified lines | ||
| 560 | 559 | ret = regmap_field_write(data->reg_flag_psint, 0); |
| 561 | 560 | if (ret < 0) |
| 562 | 561 | dev_err(&data->client->dev, "failed to reset interrupts\n"); |
| 562 | +out: | |
| 563 | 563 | mutex_unlock(&data->lock); |
| 564 | 564 | |
| 565 | 565 | return IRQ_HANDLED; |
| @@ -912,6 +912,6 @@ static struct platform_driver stm32_timer_trigger_driver = { · 911 unmodified lines | ||
| 912 | 912 | }; |
| 913 | 913 | module_platform_driver(stm32_timer_trigger_driver); |
| 914 | 914 | |
| 915 | −MODULE_ALIAS("platform: stm32-timer-trigger"); | |
| 915 | +MODULE_ALIAS("platform:stm32-timer-trigger"); | |
| 916 | 916 | MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver"); |
| 917 | 917 | MODULE_LICENSE("GPL v2"); |
| @@ -8415,6 +8415,8 @@ static void receive_interrupt_common(struct hfi1_ctxtdata *rcd) · 8414 unmodified lines | ||
| 8415 | 8415 | */ |
| 8416 | 8416 | static void __hfi1_rcd_eoi_intr(struct hfi1_ctxtdata *rcd) |
| 8417 | 8417 | { |
| 8418 | + if (!rcd->rcvhdrq) | |
| 8419 | + return; | |
| 8418 | 8420 | clear_recv_intr(rcd); |
| 8419 | 8421 | if (check_packet_present(rcd)) |
| 8420 | 8422 | force_recv_intr(rcd); |
| @@ -1012,6 +1012,8 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread) · 1011 unmodified lines | ||
| 1012 | 1012 | struct hfi1_packet packet; |
| 1013 | 1013 | int skip_pkt = 0; |
| 1014 | 1014 | |
| 1015 | + if (!rcd->rcvhdrq) | |
| 1016 | + return RCV_PKT_OK; | |
| 1015 | 1017 | /* Control context will always use the slow path interrupt handler */ |
| 1016 | 1018 | needset = (rcd->ctxt == HFI1_CTRL_CTXT) ? 0 : 1; |
| 1017 | 1019 | |
| @@ -113,7 +113,6 @@ static int hfi1_create_kctxt(struct hfi1_devdata *dd, · 112 unmodified lines | ||
| 113 | 113 | rcd->fast_handler = get_dma_rtail_setting(rcd) ? |
| 114 | 114 | handle_receive_interrupt_dma_rtail : |
| 115 | 115 | handle_receive_interrupt_nodma_rtail; |
| 116 | − rcd->slow_handler = handle_receive_interrupt; | |
| 117 | 116 | |
| 118 | 117 | hfi1_set_seq_cnt(rcd, 1); |
| 119 | 118 | |
| @@ -334,6 +333,8 @@ int hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, int numa, · 214 unmodified lines | ||
| 334 | 333 | rcd->numa_id = numa; |
| 335 | 334 | rcd->rcv_array_groups = dd->rcv_entries.ngroups; |
| 336 | 335 | rcd->rhf_rcv_function_map = normal_rhf_rcv_functions; |
| 336 | + rcd->slow_handler = handle_receive_interrupt; | |
| 337 | + rcd->do_interrupt = rcd->slow_handler; | |
| 337 | 338 | rcd->msix_intr = CCE_NUM_MSIX_VECTORS; |
| 338 | 339 | |
| 339 | 340 | mutex_init(&rcd->exp_mutex); |
| @@ -874,18 +875,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) · 534 unmodified lines | ||
| 874 | 875 | if (ret) |
| 875 | 876 | goto done; |
| 876 | 877 | |
| 877 | − /* allocate dummy tail memory for all receive contexts */ | |
| 878 | − dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev, | |
| 879 | − sizeof(u64), | |
| 880 | − &dd->rcvhdrtail_dummy_dma, | |
| 881 | − GFP_KERNEL); | |
| 882 | − | |
| 883 | − if (!dd->rcvhdrtail_dummy_kvaddr) { | |
| 884 | − dd_dev_err(dd, "cannot allocate dummy tail memory\n"); | |
| 885 | − ret = -ENOMEM; | |
| 886 | − goto done; | |
| 887 | − } | |
| 888 | − | |
| 889 | 878 | /* dd->rcd can be NULL if early initialization failed */ |
| 890 | 879 | for (i = 0; dd->rcd && i < dd->first_dyn_alloc_ctxt; ++i) { |
| 891 | 880 | /* |
| @@ -898,8 +887,6 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit) · 6 unmodified lines | ||
| 898 | 887 | if (!rcd) |
| 899 | 888 | continue; |
| 900 | 889 | |
| 901 | − rcd->do_interrupt = &handle_receive_interrupt; | |
| 902 | − | |
| 903 | 890 | lastfail = hfi1_create_rcvhdrq(dd, rcd); |
| 904 | 891 | if (!lastfail) |
| 905 | 892 | lastfail = hfi1_setup_eagerbufs(rcd); |
| @@ -1120,7 +1107,7 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd) · 214 unmodified lines | ||
| 1120 | 1107 | rcd->egrbufs.rcvtids = NULL; |
| 1121 | 1108 | |
| 1122 | 1109 | for (e = 0; e < rcd->egrbufs.alloced; e++) { |
| 1123 | − if (rcd->egrbufs.buffers[e].dma) | |
| 1110 | + if (rcd->egrbufs.buffers[e].addr) | |
| 1124 | 1111 | dma_free_coherent(&dd->pcidev->dev, |
| 1125 | 1112 | rcd->egrbufs.buffers[e].len, |
| 1126 | 1113 | rcd->egrbufs.buffers[e].addr, |
| @@ -1201,6 +1188,11 @@ void hfi1_free_devdata(struct hfi1_devdata *dd) · 74 unmodified lines | ||
| 1201 | 1188 | dd->tx_opstats = NULL; |
| 1202 | 1189 | kfree(dd->comp_vect); |
| 1203 | 1190 | dd->comp_vect = NULL; |
| 1191 | + if (dd->rcvhdrtail_dummy_kvaddr) | |
| 1192 | + dma_free_coherent(&dd->pcidev->dev, sizeof(u64), | |
| 1193 | + (void *)dd->rcvhdrtail_dummy_kvaddr, | |
| 1194 | + dd->rcvhdrtail_dummy_dma); | |
| 1195 | + dd->rcvhdrtail_dummy_kvaddr = NULL; | |
| 1204 | 1196 | sdma_clean(dd, dd->num_sdma); |
| 1205 | 1197 | rvt_dealloc_device(&dd->verbs_dev.rdi); |
| 1206 | 1198 | } |
| @@ -1298,6 +1290,15 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, · 91 unmodified lines | ||
| 1298 | 1290 | goto bail; |
| 1299 | 1291 | } |
| 1300 | 1292 | |
| 1293 | + /* allocate dummy tail memory for all receive contexts */ | |
| 1294 | + dd->rcvhdrtail_dummy_kvaddr = | |
| 1295 | + dma_alloc_coherent(&dd->pcidev->dev, sizeof(u64), | |
| 1296 | + &dd->rcvhdrtail_dummy_dma, GFP_KERNEL); | |
| 1297 | + if (!dd->rcvhdrtail_dummy_kvaddr) { | |
| 1298 | + ret = -ENOMEM; | |
| 1299 | + goto bail; | |
| 1300 | + } | |
| 1301 | + | |
| 1301 | 1302 | atomic_set(&dd->ipoib_rsm_usr_num, 0); |
| 1302 | 1303 | return dd; |
| 1303 | 1304 | |
| @@ -1505,13 +1506,6 @@ static void cleanup_device_data(struct hfi1_devdata *dd) · 201 unmodified lines | ||
| 1505 | 1506 | |
| 1506 | 1507 | free_credit_return(dd); |
| 1507 | 1508 | |
| 1508 | − if (dd->rcvhdrtail_dummy_kvaddr) { | |
| 1509 | − dma_free_coherent(&dd->pcidev->dev, sizeof(u64), | |
| 1510 | − (void *)dd->rcvhdrtail_dummy_kvaddr, | |
| 1511 | − dd->rcvhdrtail_dummy_dma); | |
| 1512 | − dd->rcvhdrtail_dummy_kvaddr = NULL; | |
| 1513 | − } | |
| 1514 | − | |
| 1515 | 1509 | /* |
| 1516 | 1510 | * Free any resources still in use (usually just kernel contexts) |
| 1517 | 1511 | * at unload; we do for ctxtcnt, because that's what we allocate. |
| @@ -838,8 +838,8 @@ struct sdma_engine *sdma_select_user_engine(struct hfi1_devdata *dd, · 837 unmodified lines | ||
| 838 | 838 | if (current->nr_cpus_allowed != 1) |
| 839 | 839 | goto out; |
| 840 | 840 | |
| 841 | − cpu_id = smp_processor_id(); | |
| 842 | 841 | rcu_read_lock(); |
| 842 | + cpu_id = smp_processor_id(); | |
| 843 | 843 | rht_node = rhashtable_lookup(dd->sdma_rht, &cpu_id, |
| 844 | 844 | sdma_rht_params); |
| 845 | 845 | |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/acpi.h> |
| 34 | 34 | #include <linux/etherdevice.h> |
| 35 | 35 | #include <linux/interrupt.h> |
| 36 | +#include <linux/iopoll.h> | |
| 36 | 37 | #include <linux/kernel.h> |
| 37 | 38 | #include <linux/types.h> |
| 38 | 39 | #include <net/addrconf.h> |
| @@ -1050,9 +1051,14 @@ static u32 hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, · 1011 unmodified lines | ||
| 1050 | 1051 | unsigned long instance_stage, |
| 1051 | 1052 | unsigned long reset_stage) |
| 1052 | 1053 | { |
| 1054 | +#define HW_RESET_TIMEOUT_US 1000000 | |
| 1055 | +#define HW_RESET_SLEEP_US 1000 | |
| 1056 | + | |
| 1053 | 1057 | struct hns_roce_v2_priv *priv = hr_dev->priv; |
| 1054 | 1058 | struct hnae3_handle *handle = priv->handle; |
| 1055 | 1059 | const struct hnae3_ae_ops *ops = handle->ae_algo->ops; |
| 1060 | + unsigned long val; | |
| 1061 | + int ret; | |
| 1056 | 1062 | |
| 1057 | 1063 | /* When hardware reset is detected, we should stop sending mailbox&cmq& |
| 1058 | 1064 | * doorbell to hardware. If now in .init_instance() function, we should |
| @@ -1064,7 +1070,11 @@ static u32 hns_roce_v2_cmd_hw_resetting(struct hns_roce_dev *hr_dev, · 5 unmodified lines | ||
| 1064 | 1070 | * again. |
| 1065 | 1071 | */ |
| 1066 | 1072 | hr_dev->dis_db = true; |
| 1067 | − if (!ops->get_hw_reset_stat(handle)) | |
| 1073 | + | |
| 1074 | + ret = read_poll_timeout(ops->ae_dev_reset_cnt, val, | |
| 1075 | + val > hr_dev->reset_cnt, HW_RESET_SLEEP_US, | |
| 1076 | + HW_RESET_TIMEOUT_US, false, handle); | |
| 1077 | + if (!ret) | |
| 1068 | 1078 | hr_dev->is_reset = true; |
| 1069 | 1079 | |
| 1070 | 1080 | if (!hr_dev->is_reset || reset_stage == HNS_ROCE_STATE_RST_INIT || |
| @@ -6387,10 +6397,8 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) · 5316 unmodified lines | ||
| 6387 | 6397 | if (!hr_dev) |
| 6388 | 6398 | return 0; |
| 6389 | 6399 | |
| 6390 | − hr_dev->is_reset = true; | |
| 6391 | 6400 | hr_dev->active = false; |
| 6392 | 6401 | hr_dev->dis_db = true; |
| 6393 | − | |
| 6394 | 6402 | hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN; |
| 6395 | 6403 | |
| 6396 | 6404 | return 0; |
| @@ -60,6 +60,8 @@ static void irdma_iwarp_ce_handler(struct irdma_sc_cq *iwcq) · 59 unmodified lines | ||
| 60 | 60 | { |
| 61 | 61 | struct irdma_cq *cq = iwcq->back_cq; |
| 62 | 62 | |
| 63 | + if (!cq->user_mode) | |
| 64 | + cq->armed = false; | |
| 63 | 65 | if (cq->ibcq.comp_handler) |
| 64 | 66 | cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); |
| 65 | 67 | } |
| @@ -146,6 +148,7 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, · 80 unmodified lines | ||
| 146 | 148 | qp->flush_code = FLUSH_PROT_ERR; |
| 147 | 149 | break; |
| 148 | 150 | case IRDMA_AE_AMP_BAD_QP: |
| 151 | + case IRDMA_AE_WQE_UNEXPECTED_OPCODE: | |
| 149 | 152 | qp->flush_code = FLUSH_LOC_QP_OP_ERR; |
| 150 | 153 | break; |
| 151 | 154 | case IRDMA_AE_AMP_BAD_STAG_KEY: |
| @@ -156,7 +159,6 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, · 4 unmodified lines | ||
| 156 | 159 | case IRDMA_AE_PRIV_OPERATION_DENIED: |
| 157 | 160 | case IRDMA_AE_IB_INVALID_REQUEST: |
| 158 | 161 | case IRDMA_AE_IB_REMOTE_ACCESS_ERROR: |
| 159 | − case IRDMA_AE_IB_REMOTE_OP_ERROR: | |
| 160 | 162 | qp->flush_code = FLUSH_REM_ACCESS_ERR; |
| 161 | 163 | qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; |
| 162 | 164 | break; |
| @@ -184,6 +186,9 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, · 21 unmodified lines | ||
| 184 | 186 | case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS: |
| 185 | 187 | qp->flush_code = FLUSH_MW_BIND_ERR; |
| 186 | 188 | break; |
| 189 | + case IRDMA_AE_IB_REMOTE_OP_ERROR: | |
| 190 | + qp->flush_code = FLUSH_REM_OP_ERR; | |
| 191 | + break; | |
| 187 | 192 | default: |
| 188 | 193 | qp->flush_code = FLUSH_FATAL_ERR; |
| 189 | 194 | break; |
| @@ -542,6 +542,7 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, · 541 unmodified lines | ||
| 542 | 542 | void (*callback_fcn)(struct irdma_cqp_request *cqp_request), |
| 543 | 543 | void *cb_param); |
| 544 | 544 | void irdma_gsi_ud_qp_ah_cb(struct irdma_cqp_request *cqp_request); |
| 545 | +bool irdma_cq_empty(struct irdma_cq *iwcq); | |
| 545 | 546 | int irdma_inetaddr_event(struct notifier_block *notifier, unsigned long event, |
| 546 | 547 | void *ptr); |
| 547 | 548 | int irdma_inet6addr_event(struct notifier_block *notifier, unsigned long event, |
| @@ -25,8 +25,7 @@ void irdma_destroy_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) · 24 unmodified lines | ||
| 25 | 25 | list_del(&chunk->list); |
| 26 | 26 | if (chunk->type == PBLE_SD_PAGED) |
| 27 | 27 | irdma_pble_free_paged_mem(chunk); |
| 28 | − if (chunk->bitmapbuf) | |
| 29 | − kfree(chunk->bitmapmem.va); | |
| 28 | + bitmap_free(chunk->bitmapbuf); | |
| 30 | 29 | kfree(chunk->chunkmem.va); |
| 31 | 30 | } |
| 32 | 31 | } |
| @@ -283,7 +282,6 @@ add_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) · 250 unmodified lines | ||
| 283 | 282 | "PBLE: next_fpm_addr = %llx chunk_size[%llu] = 0x%llx\n", |
| 284 | 283 | pble_rsrc->next_fpm_addr, chunk->size, chunk->size); |
| 285 | 284 | pble_rsrc->unallocated_pble -= (u32)(chunk->size >> 3); |
| 286 | − list_add(&chunk->list, &pble_rsrc->pinfo.clist); | |
| 287 | 285 | sd_reg_val = (sd_entry_type == IRDMA_SD_TYPE_PAGED) ? |
| 288 | 286 | sd_entry->u.pd_table.pd_page_addr.pa : |
| 289 | 287 | sd_entry->u.bp.addr.pa; |
| @@ -295,12 +293,12 @@ add_pble_prm(struct irdma_hmc_pble_rsrc *pble_rsrc) · 5 unmodified lines | ||
| 295 | 293 | goto error; |
| 296 | 294 | } |
| 297 | 295 | |
| 296 | + list_add(&chunk->list, &pble_rsrc->pinfo.clist); | |
| 298 | 297 | sd_entry->valid = true; |
| 299 | 298 | return 0; |
| 300 | 299 | |
| 301 | 300 | error: |
| 302 | − if (chunk->bitmapbuf) | |
| 303 | − kfree(chunk->bitmapmem.va); | |
| 301 | + bitmap_free(chunk->bitmapbuf); | |
| 304 | 302 | kfree(chunk->chunkmem.va); |
| 305 | 303 | |
| 306 | 304 | return ret_code; |
| @@ -78,7 +78,6 @@ struct irdma_chunk { · 77 unmodified lines | ||
| 78 | 78 | u32 pg_cnt; |
| 79 | 79 | enum irdma_alloc_type type; |
| 80 | 80 | struct irdma_sc_dev *dev; |
| 81 | − struct irdma_virt_mem bitmapmem; | |
| 82 | 81 | struct irdma_virt_mem chunkmem; |
| 83 | 82 | }; |
| 84 | 83 | |
| @@ -2239,15 +2239,10 @@ enum irdma_status_code irdma_prm_add_pble_mem(struct irdma_pble_prm *pprm, · 2238 unmodified lines | ||
| 2239 | 2239 | |
| 2240 | 2240 | sizeofbitmap = (u64)pchunk->size >> pprm->pble_shift; |
| 2241 | 2241 | |
| 2242 | − pchunk->bitmapmem.size = sizeofbitmap >> 3; | |
| 2243 | − pchunk->bitmapmem.va = kzalloc(pchunk->bitmapmem.size, GFP_KERNEL); | |
| 2244 | − | |
| 2245 | − if (!pchunk->bitmapmem.va) | |
| 2242 | + pchunk->bitmapbuf = bitmap_zalloc(sizeofbitmap, GFP_KERNEL); | |
| 2243 | + if (!pchunk->bitmapbuf) | |
| 2246 | 2244 | return IRDMA_ERR_NO_MEMORY; |
| 2247 | 2245 | |
| 2248 | − pchunk->bitmapbuf = pchunk->bitmapmem.va; | |
| 2249 | − bitmap_zero(pchunk->bitmapbuf, sizeofbitmap); | |
| 2250 | − | |
| 2251 | 2246 | pchunk->sizeofbitmap = sizeofbitmap; |
| 2252 | 2247 | /* each pble is 8 bytes hence shift by 3 */ |
| 2253 | 2248 | pprm->total_pble_alloc += pchunk->size >> 3; |
| @@ -2491,3 +2486,18 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event) · 237 unmodified lines | ||
| 2491 | 2486 | ibevent.element.qp = &iwqp->ibqp; |
| 2492 | 2487 | iwqp->ibqp.event_handler(&ibevent, iwqp->ibqp.qp_context); |
| 2493 | 2488 | } |
| 2489 | + | |
| 2490 | +bool irdma_cq_empty(struct irdma_cq *iwcq) | |
| 2491 | +{ | |
| 2492 | + struct irdma_cq_uk *ukcq; | |
| 2493 | + u64 qword3; | |
| 2494 | + __le64 *cqe; | |
| 2495 | + u8 polarity; | |
| 2496 | + | |
| 2497 | + ukcq = &iwcq->sc_cq.cq_uk; | |
| 2498 | + cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq); | |
| 2499 | + get_64bit_val(cqe, 24, &qword3); | |
| 2500 | + polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); | |
| 2501 | + | |
| 2502 | + return polarity != ukcq->polarity; | |
| 2503 | +} | |
| @@ -3584,18 +3584,31 @@ static int irdma_req_notify_cq(struct ib_cq *ibcq, · 3583 unmodified lines | ||
| 3584 | 3584 | struct irdma_cq *iwcq; |
| 3585 | 3585 | struct irdma_cq_uk *ukcq; |
| 3586 | 3586 | unsigned long flags; |
| 3587 | − enum irdma_cmpl_notify cq_notify = IRDMA_CQ_COMPL_EVENT; | |
| 3587 | + enum irdma_cmpl_notify cq_notify; | |
| 3588 | + bool promo_event = false; | |
| 3589 | + int ret = 0; | |
| 3588 | 3590 | |
| 3591 | + cq_notify = notify_flags == IB_CQ_SOLICITED ? | |
| 3592 | + IRDMA_CQ_COMPL_SOLICITED : IRDMA_CQ_COMPL_EVENT; | |
| 3589 | 3593 | iwcq = to_iwcq(ibcq); |
| 3590 | 3594 | ukcq = &iwcq->sc_cq.cq_uk; |
| 3591 | − if (notify_flags == IB_CQ_SOLICITED) | |
| 3592 | − cq_notify = IRDMA_CQ_COMPL_SOLICITED; | |
| 3593 | 3595 | |
| 3594 | 3596 | spin_lock_irqsave(&iwcq->lock, flags); |
| 3595 | − irdma_uk_cq_request_notification(ukcq, cq_notify); | |
| 3597 | + /* Only promote to arm the CQ for any event if the last arm event was solicited. */ | |
| 3598 | + if (iwcq->last_notify == IRDMA_CQ_COMPL_SOLICITED && notify_flags != IB_CQ_SOLICITED) | |
| 3599 | + promo_event = true; | |
| 3600 | + | |
| 3601 | + if (!iwcq->armed || promo_event) { | |
| 3602 | + iwcq->armed = true; | |
| 3603 | + iwcq->last_notify = cq_notify; | |
| 3604 | + irdma_uk_cq_request_notification(ukcq, cq_notify); | |
| 3605 | + } | |
| 3606 | + | |
| 3607 | + if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && !irdma_cq_empty(iwcq)) | |
| 3608 | + ret = 1; | |
| 3596 | 3609 | spin_unlock_irqrestore(&iwcq->lock, flags); |
| 3597 | 3610 | |
| 3598 | − return 0; | |
| 3611 | + return ret; | |
| 3599 | 3612 | } |
| 3600 | 3613 | |
| 3601 | 3614 | static int irdma_roce_port_immutable(struct ib_device *ibdev, u32 port_num, |
| @@ -110,6 +110,8 @@ struct irdma_cq { · 109 unmodified lines | ||
| 110 | 110 | u16 cq_size; |
| 111 | 111 | u16 cq_num; |
| 112 | 112 | bool user_mode; |
| 113 | + bool armed; | |
| 114 | + enum irdma_cmpl_notify last_notify; | |
| 113 | 115 | u32 polled_cmpls; |
| 114 | 116 | u32 cq_mem_size; |
| 115 | 117 | struct irdma_dma_mem kmem; |
| @@ -664,7 +664,6 @@ struct mlx5_ib_mr { · 663 unmodified lines | ||
| 664 | 664 | |
| 665 | 665 | /* User MR data */ |
| 666 | 666 | struct mlx5_cache_ent *cache_ent; |
| 667 | − struct ib_umem *umem; | |
| 668 | 667 | |
| 669 | 668 | /* This is zero'd when the MR is allocated */ |
| 670 | 669 | union { |
| @@ -676,7 +675,7 @@ struct mlx5_ib_mr { · 5 unmodified lines | ||
| 676 | 675 | struct list_head list; |
| 677 | 676 | }; |
| 678 | 677 | |
| 679 | − /* Used only by kernel MRs (umem == NULL) */ | |
| 678 | + /* Used only by kernel MRs */ | |
| 680 | 679 | struct { |
| 681 | 680 | void *descs; |
| 682 | 681 | void *descs_alloc; |
| @@ -697,8 +696,9 @@ struct mlx5_ib_mr { · 14 unmodified lines | ||
| 697 | 696 | int data_length; |
| 698 | 697 | }; |
| 699 | 698 | |
| 700 | − /* Used only by User MRs (umem != NULL) */ | |
| 699 | + /* Used only by User MRs */ | |
| 701 | 700 | struct { |
| 701 | + struct ib_umem *umem; | |
| 702 | 702 | unsigned int page_shift; |
| 703 | 703 | /* Current access_flags */ |
| 704 | 704 | int access_flags; |
| @@ -1904,19 +1904,18 @@ err: · 1903 unmodified lines | ||
| 1904 | 1904 | return ret; |
| 1905 | 1905 | } |
| 1906 | 1906 | |
| 1907 | −static void | |
| 1908 | −mlx5_free_priv_descs(struct mlx5_ib_mr *mr) | |
| 1907 | +static void mlx5_free_priv_descs(struct mlx5_ib_mr *mr) | |
| 1909 | 1908 | { |
| 1910 | − if (!mr->umem && mr->descs) { | |
| 1911 | − struct ib_device *device = mr->ibmr.device; | |
| 1912 | − int size = mr->max_descs * mr->desc_size; | |
| 1913 | − struct mlx5_ib_dev *dev = to_mdev(device); | |
| 1909 | + struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device); | |
| 1910 | + int size = mr->max_descs * mr->desc_size; | |
| 1914 | 1911 | |
| 1915 | − dma_unmap_single(&dev->mdev->pdev->dev, mr->desc_map, size, | |
| 1916 | − DMA_TO_DEVICE); | |
| 1917 | − kfree(mr->descs_alloc); | |
| 1918 | − mr->descs = NULL; | |
| 1919 | − } | |
| 1912 | + if (!mr->descs) | |
| 1913 | + return; | |
| 1914 | + | |
| 1915 | + dma_unmap_single(&dev->mdev->pdev->dev, mr->desc_map, size, | |
| 1916 | + DMA_TO_DEVICE); | |
| 1917 | + kfree(mr->descs_alloc); | |
| 1918 | + mr->descs = NULL; | |
| 1920 | 1919 | } |
| 1921 | 1920 | |
| 1922 | 1921 | int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) |
| @@ -1992,7 +1991,8 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) · 69 unmodified lines | ||
| 1992 | 1991 | if (mr->cache_ent) { |
| 1993 | 1992 | mlx5_mr_cache_free(dev, mr); |
| 1994 | 1993 | } else { |
| 1995 | − mlx5_free_priv_descs(mr); | |
| 1994 | + if (!udata) | |
| 1995 | + mlx5_free_priv_descs(mr); | |
| 1996 | 1996 | kfree(mr); |
| 1997 | 1997 | } |
| 1998 | 1998 | return 0; |
| @@ -2079,7 +2079,6 @@ static struct mlx5_ib_mr *mlx5_ib_alloc_pi_mr(struct ib_pd *pd, · 80 unmodified lines | ||
| 2079 | 2079 | if (err) |
| 2080 | 2080 | goto err_free_in; |
| 2081 | 2081 | |
| 2082 | − mr->umem = NULL; | |
| 2083 | 2082 | kfree(in); |
| 2084 | 2083 | |
| 2085 | 2084 | return mr; |
| @@ -2206,7 +2205,6 @@ static struct ib_mr *__mlx5_ib_alloc_mr(struct ib_pd *pd, · 120 unmodified lines | ||
| 2206 | 2205 | } |
| 2207 | 2206 | |
| 2208 | 2207 | mr->ibmr.device = pd->device; |
| 2209 | − mr->umem = NULL; | |
| 2210 | 2208 | |
| 2211 | 2209 | switch (mr_type) { |
| 2212 | 2210 | case IB_MR_TYPE_MEM_REG: |
| @@ -359,6 +359,7 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd, · 358 unmodified lines | ||
| 359 | 359 | |
| 360 | 360 | err2: |
| 361 | 361 | rxe_queue_cleanup(qp->sq.queue); |
| 362 | + qp->sq.queue = NULL; | |
| 362 | 363 | err1: |
| 363 | 364 | qp->pd = NULL; |
| 364 | 365 | qp->rcq = NULL; |
| @@ -19,7 +19,7 @@ void rtrs_clt_update_wc_stats(struct rtrs_clt_con *con) · 18 unmodified lines | ||
| 19 | 19 | int cpu; |
| 20 | 20 | |
| 21 | 21 | cpu = raw_smp_processor_id(); |
| 22 | − s = this_cpu_ptr(stats->pcpu_stats); | |
| 22 | + s = get_cpu_ptr(stats->pcpu_stats); | |
| 23 | 23 | if (con->cpu != cpu) { |
| 24 | 24 | s->cpu_migr.to++; |
| 25 | 25 | |
| @@ -27,14 +27,16 @@ void rtrs_clt_update_wc_stats(struct rtrs_clt_con *con) · 1 unmodified line | ||
| 27 | 27 | s = per_cpu_ptr(stats->pcpu_stats, con->cpu); |
| 28 | 28 | atomic_inc(&s->cpu_migr.from); |
| 29 | 29 | } |
| 30 | + put_cpu_ptr(stats->pcpu_stats); | |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | 33 | void rtrs_clt_inc_failover_cnt(struct rtrs_clt_stats *stats) |
| 33 | 34 | { |
| 34 | 35 | struct rtrs_clt_stats_pcpu *s; |
| 35 | 36 | |
| 36 | − s = this_cpu_ptr(stats->pcpu_stats); | |
| 37 | + s = get_cpu_ptr(stats->pcpu_stats); | |
| 37 | 38 | s->rdma.failover_cnt++; |
| 39 | + put_cpu_ptr(stats->pcpu_stats); | |
| 38 | 40 | } |
| 39 | 41 | |
| 40 | 42 | int rtrs_clt_stats_migration_from_cnt_to_str(struct rtrs_clt_stats *stats, char *buf) |
| @@ -169,9 +171,10 @@ static inline void rtrs_clt_update_rdma_stats(struct rtrs_clt_stats *stats, · 128 unmodified lines | ||
| 169 | 171 | { |
| 170 | 172 | struct rtrs_clt_stats_pcpu *s; |
| 171 | 173 | |
| 172 | − s = this_cpu_ptr(stats->pcpu_stats); | |
| 174 | + s = get_cpu_ptr(stats->pcpu_stats); | |
| 173 | 175 | s->rdma.dir[d].cnt++; |
| 174 | 176 | s->rdma.dir[d].size_total += size; |
| 177 | + put_cpu_ptr(stats->pcpu_stats); | |
| 175 | 178 | } |
| 176 | 179 | |
| 177 | 180 | void rtrs_clt_update_all_stats(struct rtrs_clt_io_req *req, int dir) |
| @@ -707,7 +707,7 @@ static const struct irq_domain_ops aic_ipi_domain_ops = { · 706 unmodified lines | ||
| 707 | 707 | .free = aic_ipi_free, |
| 708 | 708 | }; |
| 709 | 709 | |
| 710 | −static int aic_init_smp(struct aic_irq_chip *irqc, struct device_node *node) | |
| 710 | +static int __init aic_init_smp(struct aic_irq_chip *irqc, struct device_node *node) | |
| 711 | 711 | { |
| 712 | 712 | struct irq_domain *ipi_domain; |
| 713 | 713 | int base_ipi; |
| @@ -232,16 +232,12 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, · 231 unmodified lines | ||
| 232 | 232 | int hwirq, i; |
| 233 | 233 | |
| 234 | 234 | mutex_lock(&msi_used_lock); |
| 235 | + hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR, | |
| 236 | + order_base_2(nr_irqs)); | |
| 237 | + mutex_unlock(&msi_used_lock); | |
| 235 | 238 | |
| 236 | − hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR, | |
| 237 | − 0, nr_irqs, 0); | |
| 238 | − if (hwirq >= PCI_MSI_DOORBELL_NR) { | |
| 239 | − mutex_unlock(&msi_used_lock); | |
| 239 | + if (hwirq < 0) | |
| 240 | 240 | return -ENOSPC; |
| 241 | − } | |
| 242 | − | |
| 243 | − bitmap_set(msi_used, hwirq, nr_irqs); | |
| 244 | − mutex_unlock(&msi_used_lock); | |
| 245 | 241 | |
| 246 | 242 | for (i = 0; i < nr_irqs; i++) { |
| 247 | 243 | irq_domain_set_info(domain, virq + i, hwirq + i, |
| @@ -250,7 +246,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, · 2 unmodified lines | ||
| 250 | 246 | NULL, NULL); |
| 251 | 247 | } |
| 252 | 248 | |
| 253 | − return hwirq; | |
| 249 | + return 0; | |
| 254 | 250 | } |
| 255 | 251 | |
| 256 | 252 | static void armada_370_xp_msi_free(struct irq_domain *domain, |
| @@ -259,7 +255,7 @@ static void armada_370_xp_msi_free(struct irq_domain *domain, · 2 unmodified lines | ||
| 259 | 255 | struct irq_data *d = irq_domain_get_irq_data(domain, virq); |
| 260 | 256 | |
| 261 | 257 | mutex_lock(&msi_used_lock); |
| 262 | − bitmap_clear(msi_used, d->hwirq, nr_irqs); | |
| 258 | + bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs)); | |
| 263 | 259 | mutex_unlock(&msi_used_lock); |
| 264 | 260 | } |
| 265 | 261 | |
| @@ -76,8 +76,8 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc) · 75 unmodified lines | ||
| 76 | 76 | generic_handle_domain_irq(scu_ic->irq_domain, |
| 77 | 77 | bit - scu_ic->irq_shift); |
| 78 | 78 | |
| 79 | − regmap_update_bits(scu_ic->scu, scu_ic->reg, mask, | |
| 80 | − BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); | |
| 79 | + regmap_write_bits(scu_ic->scu, scu_ic->reg, mask, | |
| 80 | + BIT(bit + ASPEED_SCU_IC_STATUS_SHIFT)); | |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | 83 | chained_irq_exit(chip, desc); |
| @@ -238,6 +238,7 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, · 237 unmodified lines | ||
| 238 | 238 | } |
| 239 | 239 | |
| 240 | 240 | data->num_parent_irqs = platform_irq_count(pdev); |
| 241 | + put_device(&pdev->dev); | |
| 241 | 242 | if (data->num_parent_irqs <= 0) { |
| 242 | 243 | pr_err("invalid number of parent interrupts\n"); |
| 243 | 244 | ret = -ENOMEM; |
| @@ -742,7 +742,7 @@ static struct its_collection *its_build_invall_cmd(struct its_node *its, · 741 unmodified lines | ||
| 742 | 742 | |
| 743 | 743 | its_fixup_cmd(cmd); |
| 744 | 744 | |
| 745 | − return NULL; | |
| 745 | + return desc->its_invall_cmd.col; | |
| 746 | 746 | } |
| 747 | 747 | |
| 748 | 748 | static struct its_vpe *its_build_vinvall_cmd(struct its_node *its, |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | |
| 10 | 10 | #define pr_fmt(fmt) "irq-mips-gic: " fmt |
| 11 | 11 | |
| 12 | +#include <linux/bitfield.h> | |
| 12 | 13 | #include <linux/bitmap.h> |
| 13 | 14 | #include <linux/clocksource.h> |
| 14 | 15 | #include <linux/cpuhotplug.h> |
| @@ -735,8 +736,7 @@ static int __init gic_of_init(struct device_node *node, · 720 unmodified lines | ||
| 735 | 736 | mips_gic_base = ioremap(gic_base, gic_len); |
| 736 | 737 | |
| 737 | 738 | gicconfig = read_gic_config(); |
| 738 | − gic_shared_intrs = gicconfig & GIC_CONFIG_NUMINTERRUPTS; | |
| 739 | − gic_shared_intrs >>= __ffs(GIC_CONFIG_NUMINTERRUPTS); | |
| 739 | + gic_shared_intrs = FIELD_GET(GIC_CONFIG_NUMINTERRUPTS, gicconfig); | |
| 740 | 740 | gic_shared_intrs = (gic_shared_intrs + 1) * 8; |
| 741 | 741 | |
| 742 | 742 | if (cpu_has_veic) { |
| @@ -26,7 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | |
| 27 | 27 | #define NVIC_ISER 0x000 |
| 28 | 28 | #define NVIC_ICER 0x080 |
| 29 | −#define NVIC_IPR 0x300 | |
| 29 | +#define NVIC_IPR 0x400 | |
| 30 | 30 | |
| 31 | 31 | #define NVIC_MAX_BANKS 16 |
| 32 | 32 | /* |
| @@ -2189,6 +2189,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) · 2188 unmodified lines | ||
| 2189 | 2189 | |
| 2190 | 2190 | if (!num_sectors || num_sectors > max_sectors) |
| 2191 | 2191 | num_sectors = max_sectors; |
| 2192 | + rdev->sb_start = sb_start; | |
| 2192 | 2193 | } |
| 2193 | 2194 | sb = page_address(rdev->sb_page); |
| 2194 | 2195 | sb->data_size = cpu_to_le64(num_sectors); |
| @@ -6270,7 +6271,8 @@ static void __md_stop(struct mddev *mddev) · 4075 unmodified lines | ||
| 6270 | 6271 | spin_lock(&mddev->lock); |
| 6271 | 6272 | mddev->pers = NULL; |
| 6272 | 6273 | spin_unlock(&mddev->lock); |
| 6273 | − pers->free(mddev, mddev->private); | |
| 6274 | + if (mddev->private) | |
| 6275 | + pers->free(mddev, mddev->private); | |
| 6274 | 6276 | mddev->private = NULL; |
| 6275 | 6277 | if (pers->sync_request && mddev->to_remove == NULL) |
| 6276 | 6278 | mddev->to_remove = &md_redundancy_group; |
| @@ -1803,8 +1803,6 @@ static int rtsx_pci_runtime_suspend(struct device *device) · 1802 unmodified lines | ||
| 1803 | 1803 | mutex_lock(&pcr->pcr_mutex); |
| 1804 | 1804 | rtsx_pci_power_off(pcr, HOST_ENTER_S3); |
| 1805 | 1805 | |
| 1806 | − free_irq(pcr->irq, (void *)pcr); | |
| 1807 | − | |
| 1808 | 1806 | mutex_unlock(&pcr->pcr_mutex); |
| 1809 | 1807 | |
| 1810 | 1808 | pcr->is_runtime_suspended = true; |
| @@ -1825,8 +1823,6 @@ static int rtsx_pci_runtime_resume(struct device *device) · 14 unmodified lines | ||
| 1825 | 1823 | mutex_lock(&pcr->pcr_mutex); |
| 1826 | 1824 | |
| 1827 | 1825 | rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00); |
| 1828 | − rtsx_pci_acquire_irq(pcr); | |
| 1829 | − synchronize_irq(pcr->irq); | |
| 1830 | 1826 | |
| 1831 | 1827 | if (pcr->ops->fetch_vendor_settings) |
| 1832 | 1828 | pcr->ops->fetch_vendor_settings(pcr); |
| @@ -440,10 +440,6 @@ static int at25_probe(struct spi_device *spi) · 439 unmodified lines | ||
| 440 | 440 | return -ENXIO; |
| 441 | 441 | } |
| 442 | 442 | |
| 443 | − at25 = devm_kzalloc(&spi->dev, sizeof(struct at25_data), GFP_KERNEL); | |
| 444 | − if (!at25) | |
| 445 | − return -ENOMEM; | |
| 446 | − | |
| 447 | 443 | mutex_init(&at25->lock); |
| 448 | 444 | at25->spi = spi; |
| 449 | 445 | spi_set_drvdata(spi, at25); |
| @@ -493,7 +489,8 @@ static int at25_probe(struct spi_device *spi) · 43 unmodified lines | ||
| 493 | 489 | return PTR_ERR(at25->nvmem); |
| 494 | 490 | |
| 495 | 491 | dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n", |
| 496 | − (at25->chip.byte_len < 1024) ? at25->chip.byte_len : (at25->chip.byte_len / 1024), | |
| 492 | + (at25->chip.byte_len < 1024) ? | |
| 493 | + at25->chip.byte_len : (at25->chip.byte_len / 1024), | |
| 497 | 494 | (at25->chip.byte_len < 1024) ? "Byte" : "KByte", |
| 498 | 495 | at25->chip.name, is_fram ? "fram" : "eeprom", |
| 499 | 496 | (at25->chip.flags & EE_READONLY) ? " (readonly)" : "", |
| @@ -719,16 +719,18 @@ static int fastrpc_get_meta_size(struct fastrpc_invoke_ctx *ctx) · 718 unmodified lines | ||
| 719 | 719 | static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen) |
| 720 | 720 | { |
| 721 | 721 | u64 size = 0; |
| 722 | − int i; | |
| 722 | + int oix; | |
| 723 | 723 | |
| 724 | 724 | size = ALIGN(metalen, FASTRPC_ALIGN); |
| 725 | − for (i = 0; i < ctx->nscalars; i++) { | |
| 725 | + for (oix = 0; oix < ctx->nbufs; oix++) { | |
| 726 | + int i = ctx->olaps[oix].raix; | |
| 727 | + | |
| 726 | 728 | if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) { |
| 727 | 729 | |
| 728 | − if (ctx->olaps[i].offset == 0) | |
| 730 | + if (ctx->olaps[oix].offset == 0) | |
| 729 | 731 | size = ALIGN(size, FASTRPC_ALIGN); |
| 730 | 732 | |
| 731 | − size += (ctx->olaps[i].mend - ctx->olaps[i].mstart); | |
| 733 | + size += (ctx->olaps[oix].mend - ctx->olaps[oix].mstart); | |
| 732 | 734 | } |
| 733 | 735 | } |
| 734 | 736 | |
| @@ -2291,8 +2291,10 @@ static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card · 2290 unmodified lines | ||
| 2291 | 2291 | sdr_set_field(host->base + PAD_DS_TUNE, |
| 2292 | 2292 | PAD_DS_TUNE_DLY1, i); |
| 2293 | 2293 | ret = mmc_get_ext_csd(card, &ext_csd); |
| 2294 | − if (!ret) | |
| 2294 | + if (!ret) { | |
| 2295 | 2295 | result_dly1 |= (1 << i); |
| 2296 | + kfree(ext_csd); | |
| 2297 | + } | |
| 2296 | 2298 | } |
| 2297 | 2299 | host->hs400_tuning = false; |
| 2298 | 2300 | |
| @@ -673,7 +673,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) · 672 unmodified lines | ||
| 673 | 673 | |
| 674 | 674 | /* Issue CMD19 twice for each tap */ |
| 675 | 675 | for (i = 0; i < 2 * priv->tap_num; i++) { |
| 676 | − int cmd_error; | |
| 676 | + int cmd_error = 0; | |
| 677 | 677 | |
| 678 | 678 | /* Set sampling clock position */ |
| 679 | 679 | sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, i % priv->tap_num); |
| @@ -96,6 +96,13 @@ struct dataflash { · 95 unmodified lines | ||
| 96 | 96 | struct mtd_info mtd; |
| 97 | 97 | }; |
| 98 | 98 | |
| 99 | +static const struct spi_device_id dataflash_dev_ids[] = { | |
| 100 | + { "at45" }, | |
| 101 | + { "dataflash" }, | |
| 102 | + { }, | |
| 103 | +}; | |
| 104 | +MODULE_DEVICE_TABLE(spi, dataflash_dev_ids); | |
| 105 | + | |
| 99 | 106 | #ifdef CONFIG_OF |
| 100 | 107 | static const struct of_device_id dataflash_dt_ids[] = { |
| 101 | 108 | { .compatible = "atmel,at45", }, |
| @@ -927,6 +934,7 @@ static struct spi_driver dataflash_driver = { · 825 unmodified lines | ||
| 927 | 934 | .name = "mtd_dataflash", |
| 928 | 935 | .of_match_table = of_match_ptr(dataflash_dt_ids), |
| 929 | 936 | }, |
| 937 | + .id_table = dataflash_dev_ids, | |
| 930 | 938 | |
| 931 | 939 | .probe = dataflash_probe, |
| 932 | 940 | .remove = dataflash_remove, |
| @@ -26,7 +26,7 @@ config MTD_NAND_DENALI_PCI · 25 unmodified lines | ||
| 26 | 26 | config MTD_NAND_DENALI_DT |
| 27 | 27 | tristate "Denali NAND controller as a DT device" |
| 28 | 28 | select MTD_NAND_DENALI |
| 29 | − depends on HAS_DMA && HAVE_CLK && OF | |
| 29 | + depends on HAS_DMA && HAVE_CLK && OF && HAS_IOMEM | |
| 30 | 30 | help |
| 31 | 31 | Enable the driver for NAND flash on platforms using a Denali NAND |
| 32 | 32 | controller as a DT device. |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | #include <linux/clk.h> |
| 17 | 17 | #include <linux/completion.h> |
| 18 | +#include <linux/delay.h> | |
| 18 | 19 | #include <linux/dmaengine.h> |
| 19 | 20 | #include <linux/dma-direction.h> |
| 20 | 21 | #include <linux/dma-mapping.h> |
| @@ -93,6 +94,14 @@ · 72 unmodified lines | ||
| 93 | 94 | |
| 94 | 95 | #define FSMC_BUSY_WAIT_TIMEOUT (1 * HZ) |
| 95 | 96 | |
| 97 | +/* | |
| 98 | + * According to SPEAr300 Reference Manual (RM0082) | |
| 99 | + * TOUDEL = 7ns (Output delay from the flip-flops to the board) | |
| 100 | + * TINDEL = 5ns (Input delay from the board to the flipflop) | |
| 101 | + */ | |
| 102 | +#define TOUTDEL 7000 | |
| 103 | +#define TINDEL 5000 | |
| 104 | + | |
| 96 | 105 | struct fsmc_nand_timings { |
| 97 | 106 | u8 tclr; |
| 98 | 107 | u8 tar; |
| @@ -277,7 +286,7 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, · 178 unmodified lines | ||
| 277 | 286 | { |
| 278 | 287 | unsigned long hclk = clk_get_rate(host->clk); |
| 279 | 288 | unsigned long hclkn = NSEC_PER_SEC / hclk; |
| 280 | − u32 thiz, thold, twait, tset; | |
| 289 | + u32 thiz, thold, twait, tset, twait_min; | |
| 281 | 290 | |
| 282 | 291 | if (sdrt->tRC_min < 30000) |
| 283 | 292 | return -EOPNOTSUPP; |
| @@ -309,13 +318,6 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, · 25 unmodified lines | ||
| 309 | 318 | else if (tims->thold > FSMC_THOLD_MASK) |
| 310 | 319 | tims->thold = FSMC_THOLD_MASK; |
| 311 | 320 | |
| 312 | − twait = max(sdrt->tRP_min, sdrt->tWP_min); | |
| 313 | − tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; | |
| 314 | − if (tims->twait == 0) | |
| 315 | − tims->twait = 1; | |
| 316 | − else if (tims->twait > FSMC_TWAIT_MASK) | |
| 317 | − tims->twait = FSMC_TWAIT_MASK; | |
| 318 | − | |
| 319 | 321 | tset = max(sdrt->tCS_min - sdrt->tWP_min, |
| 320 | 322 | sdrt->tCEA_max - sdrt->tREA_max); |
| 321 | 323 | tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1; |
| @@ -324,6 +326,21 @@ static int fsmc_calc_timings(struct fsmc_nand_data *host, · 2 unmodified lines | ||
| 324 | 326 | else if (tims->tset > FSMC_TSET_MASK) |
| 325 | 327 | tims->tset = FSMC_TSET_MASK; |
| 326 | 328 | |
| 329 | + /* | |
| 330 | + * According to SPEAr300 Reference Manual (RM0082) which gives more | |
| 331 | + * information related to FSMSC timings than the SPEAr600 one (RM0305), | |
| 332 | + * twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL | |
| 333 | + */ | |
| 334 | + twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000) | |
| 335 | + + TOUTDEL + TINDEL; | |
| 336 | + twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min); | |
| 337 | + | |
| 338 | + tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1; | |
| 339 | + if (tims->twait == 0) | |
| 340 | + tims->twait = 1; | |
| 341 | + else if (tims->twait > FSMC_TWAIT_MASK) | |
| 342 | + tims->twait = FSMC_TWAIT_MASK; | |
| 343 | + | |
| 327 | 344 | return 0; |
| 328 | 345 | } |
| 329 | 346 | |
| @@ -664,6 +681,9 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op, · 334 unmodified lines | ||
| 664 | 681 | instr->ctx.waitrdy.timeout_ms); |
| 665 | 682 | break; |
| 666 | 683 | } |
| 684 | + | |
| 685 | + if (instr->delay_ns) | |
| 686 | + ndelay(instr->delay_ns); | |
| 667 | 687 | } |
| 668 | 688 | |
| 669 | 689 | return ret; |
| @@ -926,7 +926,7 @@ int nand_choose_best_sdr_timings(struct nand_chip *chip, · 925 unmodified lines | ||
| 926 | 926 | struct nand_sdr_timings *spec_timings) |
| 927 | 927 | { |
| 928 | 928 | const struct nand_controller_ops *ops = chip->controller->ops; |
| 929 | − int best_mode = 0, mode, ret; | |
| 929 | + int best_mode = 0, mode, ret = -EOPNOTSUPP; | |
| 930 | 930 | |
| 931 | 931 | iface->type = NAND_SDR_IFACE; |
| 932 | 932 | |
| @@ -977,7 +977,7 @@ int nand_choose_best_nvddr_timings(struct nand_chip *chip, · 44 unmodified lines | ||
| 977 | 977 | struct nand_nvddr_timings *spec_timings) |
| 978 | 978 | { |
| 979 | 979 | const struct nand_controller_ops *ops = chip->controller->ops; |
| 980 | − int best_mode = 0, mode, ret; | |
| 980 | + int best_mode = 0, mode, ret = -EOPNOTSUPP; | |
| 981 | 981 | |
| 982 | 982 | iface->type = NAND_NVDDR_IFACE; |
| 983 | 983 | |
| @@ -1837,7 +1837,7 @@ int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock) · 853 unmodified lines | ||
| 1837 | 1837 | NAND_OP_CMD(NAND_CMD_ERASE1, 0), |
| 1838 | 1838 | NAND_OP_ADDR(2, addrs, 0), |
| 1839 | 1839 | NAND_OP_CMD(NAND_CMD_ERASE2, |
| 1840 | − NAND_COMMON_TIMING_MS(conf, tWB_max)), | |
| 1840 | + NAND_COMMON_TIMING_NS(conf, tWB_max)), | |
| 1841 | 1841 | NAND_OP_WAIT_RDY(NAND_COMMON_TIMING_MS(conf, tBERS_max), |
| 1842 | 1842 | 0), |
| 1843 | 1843 | }; |
| @@ -1501,14 +1501,14 @@ void bond_alb_monitor(struct work_struct *work) · 1500 unmodified lines | ||
| 1501 | 1501 | struct slave *slave; |
| 1502 | 1502 | |
| 1503 | 1503 | if (!bond_has_slaves(bond)) { |
| 1504 | − bond_info->tx_rebalance_counter = 0; | |
| 1504 | + atomic_set(&bond_info->tx_rebalance_counter, 0); | |
| 1505 | 1505 | bond_info->lp_counter = 0; |
| 1506 | 1506 | goto re_arm; |
| 1507 | 1507 | } |
| 1508 | 1508 | |
| 1509 | 1509 | rcu_read_lock(); |
| 1510 | 1510 | |
| 1511 | − bond_info->tx_rebalance_counter++; | |
| 1511 | + atomic_inc(&bond_info->tx_rebalance_counter); | |
| 1512 | 1512 | bond_info->lp_counter++; |
| 1513 | 1513 | |
| 1514 | 1514 | /* send learning packets */ |
| @@ -1530,7 +1530,7 @@ void bond_alb_monitor(struct work_struct *work) · 15 unmodified lines | ||
| 1530 | 1530 | } |
| 1531 | 1531 | |
| 1532 | 1532 | /* rebalance tx traffic */ |
| 1533 | − if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) { | |
| 1533 | + if (atomic_read(&bond_info->tx_rebalance_counter) >= BOND_TLB_REBALANCE_TICKS) { | |
| 1534 | 1534 | bond_for_each_slave_rcu(bond, slave, iter) { |
| 1535 | 1535 | tlb_clear_slave(bond, slave, 1); |
| 1536 | 1536 | if (slave == rcu_access_pointer(bond->curr_active_slave)) { |
| @@ -1540,7 +1540,7 @@ void bond_alb_monitor(struct work_struct *work) · 3 unmodified lines | ||
| 1540 | 1540 | bond_info->unbalanced_load = 0; |
| 1541 | 1541 | } |
| 1542 | 1542 | } |
| 1543 | − bond_info->tx_rebalance_counter = 0; | |
| 1543 | + atomic_set(&bond_info->tx_rebalance_counter, 0); | |
| 1544 | 1544 | } |
| 1545 | 1545 | |
| 1546 | 1546 | if (bond_info->rlb_enabled) { |
| @@ -1610,7 +1610,8 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave) · 63 unmodified lines | ||
| 1610 | 1610 | tlb_init_slave(slave); |
| 1611 | 1611 | |
| 1612 | 1612 | /* order a rebalance ASAP */ |
| 1613 | − bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; | |
| 1613 | + atomic_set(&bond->alb_info.tx_rebalance_counter, | |
| 1614 | + BOND_TLB_REBALANCE_TICKS); | |
| 1614 | 1615 | |
| 1615 | 1616 | if (bond->alb_info.rlb_enabled) |
| 1616 | 1617 | bond->alb_info.rlb_rebalance = 1; |
| @@ -1647,7 +1648,8 @@ void bond_alb_handle_link_change(struct bonding *bond, struct slave *slave, char · 30 unmodified lines | ||
| 1647 | 1648 | rlb_clear_slave(bond, slave); |
| 1648 | 1649 | } else if (link == BOND_LINK_UP) { |
| 1649 | 1650 | /* order a rebalance ASAP */ |
| 1650 | − bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS; | |
| 1651 | + atomic_set(&bond_info->tx_rebalance_counter, | |
| 1652 | + BOND_TLB_REBALANCE_TICKS); | |
| 1651 | 1653 | if (bond->alb_info.rlb_enabled) { |
| 1652 | 1654 | bond->alb_info.rlb_rebalance = 1; |
| 1653 | 1655 | /* If the updelay module parameter is smaller than the |
| @@ -248,6 +248,9 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); · 247 unmodified lines | ||
| 248 | 248 | #define KVASER_PCIEFD_SPACK_EWLR BIT(23) |
| 249 | 249 | #define KVASER_PCIEFD_SPACK_EPLR BIT(24) |
| 250 | 250 | |
| 251 | +/* Kvaser KCAN_EPACK second word */ | |
| 252 | +#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) | |
| 253 | + | |
| 251 | 254 | struct kvaser_pciefd; |
| 252 | 255 | |
| 253 | 256 | struct kvaser_pciefd_can { |
| @@ -1285,7 +1288,10 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, · 1031 unmodified lines | ||
| 1285 | 1288 | |
| 1286 | 1289 | can->err_rep_cnt++; |
| 1287 | 1290 | can->can.can_stats.bus_error++; |
| 1288 | − stats->rx_errors++; | |
| 1291 | + if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) | |
| 1292 | + stats->tx_errors++; | |
| 1293 | + else | |
| 1294 | + stats->rx_errors++; | |
| 1289 | 1295 | |
| 1290 | 1296 | can->bec.txerr = bec.txerr; |
| 1291 | 1297 | can->bec.rxerr = bec.rxerr; |
| @@ -204,16 +204,16 @@ enum m_can_reg { · 203 unmodified lines | ||
| 204 | 204 | |
| 205 | 205 | /* Interrupts for version 3.0.x */ |
| 206 | 206 | #define IR_ERR_LEC_30X (IR_STE | IR_FOE | IR_ACKE | IR_BE | IR_CRCE) |
| 207 | −#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_ELO | IR_BEU | \ | |
| 208 | − IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ | |
| 209 | − IR_RF1L | IR_RF0L) | |
| 207 | +#define IR_ERR_BUS_30X (IR_ERR_LEC_30X | IR_WDI | IR_BEU | IR_BEC | \ | |
| 208 | + IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ | |
| 209 | + IR_RF0L) | |
| 210 | 210 | #define IR_ERR_ALL_30X (IR_ERR_STATE | IR_ERR_BUS_30X) |
| 211 | 211 | |
| 212 | 212 | /* Interrupts for version >= 3.1.x */ |
| 213 | 213 | #define IR_ERR_LEC_31X (IR_PED | IR_PEA) |
| 214 | −#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BEU | \ | |
| 215 | − IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \ | |
| 216 | − IR_RF1L | IR_RF0L) | |
| 214 | +#define IR_ERR_BUS_31X (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \ | |
| 215 | + IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \ | |
| 216 | + IR_RF0L) | |
| 217 | 217 | #define IR_ERR_ALL_31X (IR_ERR_STATE | IR_ERR_BUS_31X) |
| 218 | 218 | |
| 219 | 219 | /* Interrupt Line Select (ILS) */ |
| @@ -517,7 +517,7 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) · 297 unmodified lines | ||
| 517 | 517 | err = m_can_fifo_read(cdev, fgi, M_CAN_FIFO_DATA, |
| 518 | 518 | cf->data, DIV_ROUND_UP(cf->len, 4)); |
| 519 | 519 | if (err) |
| 520 | − goto out_fail; | |
| 520 | + goto out_free_skb; | |
| 521 | 521 | } |
| 522 | 522 | |
| 523 | 523 | /* acknowledge rx fifo 0 */ |
| @@ -532,6 +532,8 @@ static int m_can_read_fifo(struct net_device *dev, u32 rxfs) · 8 unmodified lines | ||
| 532 | 532 | |
| 533 | 533 | return 0; |
| 534 | 534 | |
| 535 | +out_free_skb: | |
| 536 | + kfree_skb(skb); | |
| 535 | 537 | out_fail: |
| 536 | 538 | netdev_err(dev, "FIFO read returned %d\n", err); |
| 537 | 539 | return err; |
| @@ -810,8 +812,6 @@ static void m_can_handle_other_err(struct net_device *dev, u32 irqstatus) · 272 unmodified lines | ||
| 810 | 812 | { |
| 811 | 813 | if (irqstatus & IR_WDI) |
| 812 | 814 | netdev_err(dev, "Message RAM Watchdog event due to missing READY\n"); |
| 813 | − if (irqstatus & IR_ELO) | |
| 814 | − netdev_err(dev, "Error Logging Overflow\n"); | |
| 815 | 815 | if (irqstatus & IR_BEU) |
| 816 | 816 | netdev_err(dev, "Bit Error Uncorrected\n"); |
| 817 | 817 | if (irqstatus & IR_BEC) |
| @@ -1494,20 +1494,32 @@ static int m_can_dev_setup(struct m_can_classdev *cdev) · 676 unmodified lines | ||
| 1494 | 1494 | case 30: |
| 1495 | 1495 | /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ |
| 1496 | 1496 | can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); |
| 1497 | − cdev->can.bittiming_const = &m_can_bittiming_const_30X; | |
| 1498 | − cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X; | |
| 1497 | + cdev->can.bittiming_const = cdev->bit_timing ? | |
| 1498 | + cdev->bit_timing : &m_can_bittiming_const_30X; | |
| 1499 | + | |
| 1500 | + cdev->can.data_bittiming_const = cdev->data_timing ? | |
| 1501 | + cdev->data_timing : | |
| 1502 | + &m_can_data_bittiming_const_30X; | |
| 1499 | 1503 | break; |
| 1500 | 1504 | case 31: |
| 1501 | 1505 | /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ |
| 1502 | 1506 | can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); |
| 1503 | − cdev->can.bittiming_const = &m_can_bittiming_const_31X; | |
| 1504 | − cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; | |
| 1507 | + cdev->can.bittiming_const = cdev->bit_timing ? | |
| 1508 | + cdev->bit_timing : &m_can_bittiming_const_31X; | |
| 1509 | + | |
| 1510 | + cdev->can.data_bittiming_const = cdev->data_timing ? | |
| 1511 | + cdev->data_timing : | |
| 1512 | + &m_can_data_bittiming_const_31X; | |
| 1505 | 1513 | break; |
| 1506 | 1514 | case 32: |
| 1507 | 1515 | case 33: |
| 1508 | 1516 | /* Support both MCAN version v3.2.x and v3.3.0 */ |
| 1509 | − cdev->can.bittiming_const = &m_can_bittiming_const_31X; | |
| 1510 | − cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; | |
| 1517 | + cdev->can.bittiming_const = cdev->bit_timing ? | |
| 1518 | + cdev->bit_timing : &m_can_bittiming_const_31X; | |
| 1519 | + | |
| 1520 | + cdev->can.data_bittiming_const = cdev->data_timing ? | |
| 1521 | + cdev->data_timing : | |
| 1522 | + &m_can_data_bittiming_const_31X; | |
| 1511 | 1523 | |
| 1512 | 1524 | cdev->can.ctrlmode_supported |= |
| 1513 | 1525 | (m_can_niso_supported(cdev) ? |
| @@ -85,6 +85,9 @@ struct m_can_classdev { · 84 unmodified lines | ||
| 85 | 85 | struct sk_buff *tx_skb; |
| 86 | 86 | struct phy *transceiver; |
| 87 | 87 | |
| 88 | + const struct can_bittiming_const *bit_timing; | |
| 89 | + const struct can_bittiming_const *data_timing; | |
| 90 | + | |
| 88 | 91 | struct m_can_ops *ops; |
| 89 | 92 | |
| 90 | 93 | int version; |
| @@ -18,9 +18,14 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #define M_CAN_PCI_MMIO_BAR 0 |
| 20 | 20 | |
| 21 | −#define M_CAN_CLOCK_FREQ_EHL 100000000 | |
| 22 | 21 | #define CTL_CSR_INT_CTL_OFFSET 0x508 |
| 23 | 22 | |
| 23 | +struct m_can_pci_config { | |
| 24 | + const struct can_bittiming_const *bit_timing; | |
| 25 | + const struct can_bittiming_const *data_timing; | |
| 26 | + unsigned int clock_freq; | |
| 27 | +}; | |
| 28 | + | |
| 24 | 29 | struct m_can_pci_priv { |
| 25 | 30 | struct m_can_classdev cdev; |
| 26 | 31 | |
| @@ -42,8 +47,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg) · 15 unmodified lines | ||
| 42 | 47 | static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count) |
| 43 | 48 | { |
| 44 | 49 | struct m_can_pci_priv *priv = cdev_to_priv(cdev); |
| 50 | + void __iomem *src = priv->base + offset; | |
| 45 | 51 | |
| 46 | − ioread32_rep(priv->base + offset, val, val_count); | |
| 52 | + while (val_count--) { | |
| 53 | + *(unsigned int *)val = ioread32(src); | |
| 54 | + val += 4; | |
| 55 | + src += 4; | |
| 56 | + } | |
| 47 | 57 | |
| 48 | 58 | return 0; |
| 49 | 59 | } |
| @@ -61,8 +71,13 @@ static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, · 11 unmodified lines | ||
| 61 | 71 | const void *val, size_t val_count) |
| 62 | 72 | { |
| 63 | 73 | struct m_can_pci_priv *priv = cdev_to_priv(cdev); |
| 74 | + void __iomem *dst = priv->base + offset; | |
| 64 | 75 | |
| 65 | − iowrite32_rep(priv->base + offset, val, val_count); | |
| 76 | + while (val_count--) { | |
| 77 | + iowrite32(*(unsigned int *)val, dst); | |
| 78 | + val += 4; | |
| 79 | + dst += 4; | |
| 80 | + } | |
| 66 | 81 | |
| 67 | 82 | return 0; |
| 68 | 83 | } |
| @@ -74,9 +89,40 @@ static struct m_can_ops m_can_pci_ops = { · 5 unmodified lines | ||
| 74 | 89 | .read_fifo = iomap_read_fifo, |
| 75 | 90 | }; |
| 76 | 91 | |
| 92 | +static const struct can_bittiming_const m_can_bittiming_const_ehl = { | |
| 93 | + .name = KBUILD_MODNAME, | |
| 94 | + .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ | |
| 95 | + .tseg1_max = 64, | |
| 96 | + .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ | |
| 97 | + .tseg2_max = 128, | |
| 98 | + .sjw_max = 128, | |
| 99 | + .brp_min = 1, | |
| 100 | + .brp_max = 512, | |
| 101 | + .brp_inc = 1, | |
| 102 | +}; | |
| 103 | + | |
| 104 | +static const struct can_bittiming_const m_can_data_bittiming_const_ehl = { | |
| 105 | + .name = KBUILD_MODNAME, | |
| 106 | + .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ | |
| 107 | + .tseg1_max = 16, | |
| 108 | + .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ | |
| 109 | + .tseg2_max = 8, | |
| 110 | + .sjw_max = 4, | |
| 111 | + .brp_min = 1, | |
| 112 | + .brp_max = 32, | |
| 113 | + .brp_inc = 1, | |
| 114 | +}; | |
| 115 | + | |
| 116 | +static const struct m_can_pci_config m_can_pci_ehl = { | |
| 117 | + .bit_timing = &m_can_bittiming_const_ehl, | |
| 118 | + .data_timing = &m_can_data_bittiming_const_ehl, | |
| 119 | + .clock_freq = 200000000, | |
| 120 | +}; | |
| 121 | + | |
| 77 | 122 | static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) |
| 78 | 123 | { |
| 79 | 124 | struct device *dev = &pci->dev; |
| 125 | + const struct m_can_pci_config *cfg; | |
| 80 | 126 | struct m_can_classdev *mcan_class; |
| 81 | 127 | struct m_can_pci_priv *priv; |
| 82 | 128 | void __iomem *base; |
| @@ -104,6 +150,8 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) · 21 unmodified lines | ||
| 104 | 150 | if (!mcan_class) |
| 105 | 151 | return -ENOMEM; |
| 106 | 152 | |
| 153 | + cfg = (const struct m_can_pci_config *)id->driver_data; | |
| 154 | + | |
| 107 | 155 | priv = cdev_to_priv(mcan_class); |
| 108 | 156 | |
| 109 | 157 | priv->base = base; |
| @@ -115,7 +163,9 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) · 5 unmodified lines | ||
| 115 | 163 | mcan_class->dev = &pci->dev; |
| 116 | 164 | mcan_class->net->irq = pci_irq_vector(pci, 0); |
| 117 | 165 | mcan_class->pm_clock_support = 1; |
| 118 | − mcan_class->can.clock.freq = id->driver_data; | |
| 166 | + mcan_class->bit_timing = cfg->bit_timing; | |
| 167 | + mcan_class->data_timing = cfg->data_timing; | |
| 168 | + mcan_class->can.clock.freq = cfg->clock_freq; | |
| 119 | 169 | mcan_class->ops = &m_can_pci_ops; |
| 120 | 170 | |
| 121 | 171 | pci_set_drvdata(pci, mcan_class); |
| @@ -168,8 +218,8 @@ static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops, · 46 unmodified lines | ||
| 168 | 218 | m_can_pci_suspend, m_can_pci_resume); |
| 169 | 219 | |
| 170 | 220 | static const struct pci_device_id m_can_pci_id_table[] = { |
| 171 | − { PCI_VDEVICE(INTEL, 0x4bc1), M_CAN_CLOCK_FREQ_EHL, }, | |
| 172 | − { PCI_VDEVICE(INTEL, 0x4bc2), M_CAN_CLOCK_FREQ_EHL, }, | |
| 221 | + { PCI_VDEVICE(INTEL, 0x4bc1), (kernel_ulong_t)&m_can_pci_ehl, }, | |
| 222 | + { PCI_VDEVICE(INTEL, 0x4bc2), (kernel_ulong_t)&m_can_pci_ehl, }, | |
| 173 | 223 | { } /* Terminating Entry */ |
| 174 | 224 | }; |
| 175 | 225 | MODULE_DEVICE_TABLE(pci, m_can_pci_id_table); |
| @@ -692,11 +692,11 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota) · 691 unmodified lines | ||
| 692 | 692 | cf->data[i + 1] = data_reg >> 8; |
| 693 | 693 | } |
| 694 | 694 | |
| 695 | − netif_receive_skb(skb); | |
| 696 | 695 | rcv_pkts++; |
| 697 | 696 | stats->rx_packets++; |
| 698 | 697 | quota--; |
| 699 | 698 | stats->rx_bytes += cf->len; |
| 699 | + netif_receive_skb(skb); | |
| 700 | 700 | |
| 701 | 701 | pch_fifo_thresh(priv, obj_num); |
| 702 | 702 | obj_num++; |
| @@ -234,7 +234,12 @@ static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base) · 233 unmodified lines | ||
| 234 | 234 | free_sja1000dev(dev); |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | − err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, | |
| 237 | + if (!card->channels) { | |
| 238 | + err = -ENODEV; | |
| 239 | + goto failure_cleanup; | |
| 240 | + } | |
| 241 | + | |
| 242 | + err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED, | |
| 238 | 243 | DRV_NAME, card); |
| 239 | 244 | if (!err) |
| 240 | 245 | return 0; |
| @@ -28,10 +28,6 @@ · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | #include "kvaser_usb.h" |
| 30 | 30 | |
| 31 | −/* Forward declaration */ | |
| 32 | −static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; | |
| 33 | − | |
| 34 | −#define CAN_USB_CLOCK 8000000 | |
| 35 | 31 | #define MAX_USBCAN_NET_DEVICES 2 |
| 36 | 32 | |
| 37 | 33 | /* Command header size */ |
| @@ -80,6 +76,12 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg; · 42 unmodified lines | ||
| 80 | 76 | |
| 81 | 77 | #define CMD_LEAF_LOG_MESSAGE 106 |
| 82 | 78 | |
| 79 | +/* Leaf frequency options */ | |
| 80 | +#define KVASER_USB_LEAF_SWOPTION_FREQ_MASK 0x60 | |
| 81 | +#define KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK 0 | |
| 82 | +#define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) | |
| 83 | +#define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) | |
| 84 | + | |
| 83 | 85 | /* error factors */ |
| 84 | 86 | #define M16C_EF_ACKE BIT(0) |
| 85 | 87 | #define M16C_EF_CRCE BIT(1) |
| @@ -340,6 +342,50 @@ struct kvaser_usb_err_summary { · 254 unmodified lines | ||
| 340 | 342 | }; |
| 341 | 343 | }; |
| 342 | 344 | |
| 345 | +static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { | |
| 346 | + .name = "kvaser_usb", | |
| 347 | + .tseg1_min = KVASER_USB_TSEG1_MIN, | |
| 348 | + .tseg1_max = KVASER_USB_TSEG1_MAX, | |
| 349 | + .tseg2_min = KVASER_USB_TSEG2_MIN, | |
| 350 | + .tseg2_max = KVASER_USB_TSEG2_MAX, | |
| 351 | + .sjw_max = KVASER_USB_SJW_MAX, | |
| 352 | + .brp_min = KVASER_USB_BRP_MIN, | |
| 353 | + .brp_max = KVASER_USB_BRP_MAX, | |
| 354 | + .brp_inc = KVASER_USB_BRP_INC, | |
| 355 | +}; | |
| 356 | + | |
| 357 | +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_8mhz = { | |
| 358 | + .clock = { | |
| 359 | + .freq = 8000000, | |
| 360 | + }, | |
| 361 | + .timestamp_freq = 1, | |
| 362 | + .bittiming_const = &kvaser_usb_leaf_bittiming_const, | |
| 363 | +}; | |
| 364 | + | |
| 365 | +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_16mhz = { | |
| 366 | + .clock = { | |
| 367 | + .freq = 16000000, | |
| 368 | + }, | |
| 369 | + .timestamp_freq = 1, | |
| 370 | + .bittiming_const = &kvaser_usb_leaf_bittiming_const, | |
| 371 | +}; | |
| 372 | + | |
| 373 | +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_24mhz = { | |
| 374 | + .clock = { | |
| 375 | + .freq = 24000000, | |
| 376 | + }, | |
| 377 | + .timestamp_freq = 1, | |
| 378 | + .bittiming_const = &kvaser_usb_leaf_bittiming_const, | |
| 379 | +}; | |
| 380 | + | |
| 381 | +static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg_32mhz = { | |
| 382 | + .clock = { | |
| 383 | + .freq = 32000000, | |
| 384 | + }, | |
| 385 | + .timestamp_freq = 1, | |
| 386 | + .bittiming_const = &kvaser_usb_leaf_bittiming_const, | |
| 387 | +}; | |
| 388 | + | |
| 343 | 389 | static void * |
| 344 | 390 | kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, |
| 345 | 391 | const struct sk_buff *skb, int *frame_len, |
| @@ -471,6 +517,27 @@ static int kvaser_usb_leaf_send_simple_cmd(const struct kvaser_usb *dev, · 125 unmodified lines | ||
| 471 | 517 | return rc; |
| 472 | 518 | } |
| 473 | 519 | |
| 520 | +static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, | |
| 521 | + const struct leaf_cmd_softinfo *softinfo) | |
| 522 | +{ | |
| 523 | + u32 sw_options = le32_to_cpu(softinfo->sw_options); | |
| 524 | + | |
| 525 | + dev->fw_version = le32_to_cpu(softinfo->fw_version); | |
| 526 | + dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); | |
| 527 | + | |
| 528 | + switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { | |
| 529 | + case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: | |
| 530 | + dev->cfg = &kvaser_usb_leaf_dev_cfg_16mhz; | |
| 531 | + break; | |
| 532 | + case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: | |
| 533 | + dev->cfg = &kvaser_usb_leaf_dev_cfg_24mhz; | |
| 534 | + break; | |
| 535 | + case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: | |
| 536 | + dev->cfg = &kvaser_usb_leaf_dev_cfg_32mhz; | |
| 537 | + break; | |
| 538 | + } | |
| 539 | +} | |
| 540 | + | |
| 474 | 541 | static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) |
| 475 | 542 | { |
| 476 | 543 | struct kvaser_cmd cmd; |
| @@ -486,14 +553,13 @@ static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) · 9 unmodified lines | ||
| 486 | 553 | |
| 487 | 554 | switch (dev->card_data.leaf.family) { |
| 488 | 555 | case KVASER_LEAF: |
| 489 | − dev->fw_version = le32_to_cpu(cmd.u.leaf.softinfo.fw_version); | |
| 490 | − dev->max_tx_urbs = | |
| 491 | − le16_to_cpu(cmd.u.leaf.softinfo.max_outstanding_tx); | |
| 556 | + kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); | |
| 492 | 557 | break; |
| 493 | 558 | case KVASER_USBCAN: |
| 494 | 559 | dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version); |
| 495 | 560 | dev->max_tx_urbs = |
| 496 | 561 | le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); |
| 562 | + dev->cfg = &kvaser_usb_leaf_dev_cfg_8mhz; | |
| 497 | 563 | break; |
| 498 | 564 | } |
| 499 | 565 | |
| @@ -1225,24 +1291,11 @@ static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) · 725 unmodified lines | ||
| 1225 | 1291 | { |
| 1226 | 1292 | struct kvaser_usb_dev_card_data *card_data = &dev->card_data; |
| 1227 | 1293 | |
| 1228 | − dev->cfg = &kvaser_usb_leaf_dev_cfg; | |
| 1229 | 1294 | card_data->ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; |
| 1230 | 1295 | |
| 1231 | 1296 | return 0; |
| 1232 | 1297 | } |
| 1233 | 1298 | |
| 1234 | −static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = { | |
| 1235 | − .name = "kvaser_usb", | |
| 1236 | − .tseg1_min = KVASER_USB_TSEG1_MIN, | |
| 1237 | − .tseg1_max = KVASER_USB_TSEG1_MAX, | |
| 1238 | − .tseg2_min = KVASER_USB_TSEG2_MIN, | |
| 1239 | − .tseg2_max = KVASER_USB_TSEG2_MAX, | |
| 1240 | − .sjw_max = KVASER_USB_SJW_MAX, | |
| 1241 | − .brp_min = KVASER_USB_BRP_MIN, | |
| 1242 | − .brp_max = KVASER_USB_BRP_MAX, | |
| 1243 | − .brp_inc = KVASER_USB_BRP_INC, | |
| 1244 | −}; | |
| 1245 | − | |
| 1246 | 1299 | static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) |
| 1247 | 1300 | { |
| 1248 | 1301 | struct kvaser_usb_net_priv *priv = netdev_priv(netdev); |
| @@ -1348,11 +1401,3 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { · 99 unmodified lines | ||
| 1348 | 1401 | .dev_read_bulk_callback = kvaser_usb_leaf_read_bulk_callback, |
| 1349 | 1402 | .dev_frame_to_cmd = kvaser_usb_leaf_frame_to_cmd, |
| 1350 | 1403 | }; |
| 1351 | − | |
| 1352 | −static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg = { | |
| 1353 | − .clock = { | |
| 1354 | − .freq = CAN_USB_CLOCK, | |
| 1355 | − }, | |
| 1356 | − .timestamp_freq = 1, | |
| 1357 | − .bittiming_const = &kvaser_usb_leaf_bittiming_const, | |
| 1358 | −}; | |
| @@ -349,6 +349,19 @@ static const struct of_device_id b53_spi_of_match[] = { · 348 unmodified lines | ||
| 349 | 349 | }; |
| 350 | 350 | MODULE_DEVICE_TABLE(of, b53_spi_of_match); |
| 351 | 351 | |
| 352 | +static const struct spi_device_id b53_spi_ids[] = { | |
| 353 | + { .name = "bcm5325" }, | |
| 354 | + { .name = "bcm5365" }, | |
| 355 | + { .name = "bcm5395" }, | |
| 356 | + { .name = "bcm5397" }, | |
| 357 | + { .name = "bcm5398" }, | |
| 358 | + { .name = "bcm53115" }, | |
| 359 | + { .name = "bcm53125" }, | |
| 360 | + { .name = "bcm53128" }, | |
| 361 | + { /* sentinel */ } | |
| 362 | +}; | |
| 363 | +MODULE_DEVICE_TABLE(spi, b53_spi_ids); | |
| 364 | + | |
| 352 | 365 | static struct spi_driver b53_spi_driver = { |
| 353 | 366 | .driver = { |
| 354 | 367 | .name = "b53-switch", |
| @@ -357,6 +370,7 @@ static struct spi_driver b53_spi_driver = { · 2 unmodified lines | ||
| 357 | 370 | .probe = b53_spi_probe, |
| 358 | 371 | .remove = b53_spi_remove, |
| 359 | 372 | .shutdown = b53_spi_shutdown, |
| 373 | + .id_table = b53_spi_ids, | |
| 360 | 374 | }; |
| 361 | 375 | |
| 362 | 376 | module_spi_driver(b53_spi_driver); |
| @@ -471,6 +471,12 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) · 470 unmodified lines | ||
| 471 | 471 | u16 reg; |
| 472 | 472 | int err; |
| 473 | 473 | |
| 474 | + /* The 88e6250 family does not have the PHY detect bit. Instead, | |
| 475 | + * report whether the port is internal. | |
| 476 | + */ | |
| 477 | + if (chip->info->family == MV88E6XXX_FAMILY_6250) | |
| 478 | + return port < chip->info->num_internal_phys; | |
| 479 | + | |
| 474 | 480 | err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); |
| 475 | 481 | if (err) { |
| 476 | 482 | dev_err(chip->dev, |
| @@ -692,44 +698,48 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, · 215 unmodified lines | ||
| 692 | 698 | { |
| 693 | 699 | struct mv88e6xxx_chip *chip = ds->priv; |
| 694 | 700 | struct mv88e6xxx_port *p; |
| 695 | − int err; | |
| 701 | + int err = 0; | |
| 696 | 702 | |
| 697 | 703 | p = &chip->ports[port]; |
| 698 | 704 | |
| 699 | − /* FIXME: is this the correct test? If we're in fixed mode on an | |
| 700 | − * internal port, why should we process this any different from | |
| 701 | − * PHY mode? On the other hand, the port may be automedia between | |
| 702 | − * an internal PHY and the serdes... | |
| 703 | − */ | |
| 704 | − if ((mode == MLO_AN_PHY) && mv88e6xxx_phy_is_internal(ds, port)) | |
| 705 | − return; | |
| 706 | − | |
| 707 | 705 | mv88e6xxx_reg_lock(chip); |
| 708 | − /* In inband mode, the link may come up at any time while the link | |
| 709 | − * is not forced down. Force the link down while we reconfigure the | |
| 710 | − * interface mode. | |
| 711 | − */ | |
| 712 | − if (mode == MLO_AN_INBAND && p->interface != state->interface && | |
| 713 | − chip->info->ops->port_set_link) | |
| 714 | − chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN); | |
| 715 | − | |
| 716 | − err = mv88e6xxx_port_config_interface(chip, port, state->interface); | |
| 717 | − if (err && err != -EOPNOTSUPP) | |
| 718 | − goto err_unlock; | |
| 719 | 706 | |
| 720 | − err = mv88e6xxx_serdes_pcs_config(chip, port, mode, state->interface, | |
| 721 | − state->advertising); | |
| 722 | − /* FIXME: we should restart negotiation if something changed - which | |
| 723 | − * is something we get if we convert to using phylinks PCS operations. | |
| 724 | − */ | |
| 725 | − if (err > 0) | |
| 726 | − err = 0; | |
| 707 | + if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { | |
| 708 | + /* In inband mode, the link may come up at any time while the | |
| 709 | + * link is not forced down. Force the link down while we | |
| 710 | + * reconfigure the interface mode. | |
| 711 | + */ | |
| 712 | + if (mode == MLO_AN_INBAND && | |
| 713 | + p->interface != state->interface && | |
| 714 | + chip->info->ops->port_set_link) | |
| 715 | + chip->info->ops->port_set_link(chip, port, | |
| 716 | + LINK_FORCED_DOWN); | |
| 717 | + | |
| 718 | + err = mv88e6xxx_port_config_interface(chip, port, | |
| 719 | + state->interface); | |
| 720 | + if (err && err != -EOPNOTSUPP) | |
| 721 | + goto err_unlock; | |
| 722 | + | |
| 723 | + err = mv88e6xxx_serdes_pcs_config(chip, port, mode, | |
| 724 | + state->interface, | |
| 725 | + state->advertising); | |
| 726 | + /* FIXME: we should restart negotiation if something changed - | |
| 727 | + * which is something we get if we convert to using phylinks | |
| 728 | + * PCS operations. | |
| 729 | + */ | |
| 730 | + if (err > 0) | |
| 731 | + err = 0; | |
| 732 | + } | |
| 727 | 733 | |
| 728 | 734 | /* Undo the forced down state above after completing configuration |
| 729 | − * irrespective of its state on entry, which allows the link to come up. | |
| 735 | + * irrespective of its state on entry, which allows the link to come | |
| 736 | + * up in the in-band case where there is no separate SERDES. Also | |
| 737 | + * ensure that the link can come up if the PPU is in use and we are | |
| 738 | + * in PHY mode (we treat the PPU as an effective in-band mechanism.) | |
| 730 | 739 | */ |
| 731 | − if (mode == MLO_AN_INBAND && p->interface != state->interface && | |
| 732 | − chip->info->ops->port_set_link) | |
| 740 | + if (chip->info->ops->port_set_link && | |
| 741 | + ((mode == MLO_AN_INBAND && p->interface != state->interface) || | |
| 742 | + (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port)))) | |
| 733 | 743 | chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); |
| 734 | 744 | |
| 735 | 745 | p->interface = state->interface; |
| @@ -752,11 +762,10 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, · 16 unmodified lines | ||
| 752 | 762 | ops = chip->info->ops; |
| 753 | 763 | |
| 754 | 764 | mv88e6xxx_reg_lock(chip); |
| 755 | − /* Internal PHYs propagate their configuration directly to the MAC. | |
| 756 | − * External PHYs depend on whether the PPU is enabled for this port. | |
| 765 | + /* Force the link down if we know the port may not be automatically | |
| 766 | + * updated by the switch or if we are using fixed-link mode. | |
| 757 | 767 | */ |
| 758 | − if (((!mv88e6xxx_phy_is_internal(ds, port) && | |
| 759 | − !mv88e6xxx_port_ppu_updates(chip, port)) || | |
| 768 | + if ((!mv88e6xxx_port_ppu_updates(chip, port) || | |
| 760 | 769 | mode == MLO_AN_FIXED) && ops->port_sync_link) |
| 761 | 770 | err = ops->port_sync_link(chip, port, mode, false); |
| 762 | 771 | mv88e6xxx_reg_unlock(chip); |
| @@ -779,11 +788,11 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, · 16 unmodified lines | ||
| 779 | 788 | ops = chip->info->ops; |
| 780 | 789 | |
| 781 | 790 | mv88e6xxx_reg_lock(chip); |
| 782 | − /* Internal PHYs propagate their configuration directly to the MAC. | |
| 783 | − * External PHYs depend on whether the PPU is enabled for this port. | |
| 791 | + /* Configure and force the link up if we know that the port may not | |
| 792 | + * automatically updated by the switch or if we are using fixed-link | |
| 793 | + * mode. | |
| 784 | 794 | */ |
| 785 | − if ((!mv88e6xxx_phy_is_internal(ds, port) && | |
| 786 | − !mv88e6xxx_port_ppu_updates(chip, port)) || | |
| 795 | + if (!mv88e6xxx_port_ppu_updates(chip, port) || | |
| 787 | 796 | mode == MLO_AN_FIXED) { |
| 788 | 797 | /* FIXME: for an automedia port, should we force the link |
| 789 | 798 | * down here - what if the link comes up due to "other" media |
| @@ -50,11 +50,22 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, · 49 unmodified lines | ||
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, |
| 53 | − u16 status, u16 lpa, | |
| 53 | + u16 ctrl, u16 status, u16 lpa, | |
| 54 | 54 | struct phylink_link_state *state) |
| 55 | 55 | { |
| 56 | + state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); | |
| 57 | + | |
| 56 | 58 | if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { |
| 57 | − state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); | |
| 59 | + /* The Spped and Duplex Resolved register is 1 if AN is enabled | |
| 60 | + * and complete, or if AN is disabled. So with disabled AN we | |
| 61 | + * still get here on link up. But we want to set an_complete | |
| 62 | + * only if AN was enabled, thus we look at BMCR_ANENABLE. | |
| 63 | + * (According to 802.3-2008 section 22.2.4.2.10, we should be | |
| 64 | + * able to get this same value from BMSR_ANEGCAPABLE, but tests | |
| 65 | + * show that these Marvell PHYs don't conform to this part of | |
| 66 | + * the specificaion - BMSR_ANEGCAPABLE is simply always 1.) | |
| 67 | + */ | |
| 68 | + state->an_complete = !!(ctrl & BMCR_ANENABLE); | |
| 58 | 69 | state->duplex = status & |
| 59 | 70 | MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? |
| 60 | 71 | DUPLEX_FULL : DUPLEX_HALF; |
| @@ -81,6 +92,18 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, · 20 unmodified lines | ||
| 81 | 92 | dev_err(chip->dev, "invalid PHY speed\n"); |
| 82 | 93 | return -EINVAL; |
| 83 | 94 | } |
| 95 | + } else if (state->link && | |
| 96 | + state->interface != PHY_INTERFACE_MODE_SGMII) { | |
| 97 | + /* If Speed and Duplex Resolved register is 0 and link is up, it | |
| 98 | + * means that AN was enabled, but link partner had it disabled | |
| 99 | + * and the PHY invoked the Auto-Negotiation Bypass feature and | |
| 100 | + * linked anyway. | |
| 101 | + */ | |
| 102 | + state->duplex = DUPLEX_FULL; | |
| 103 | + if (state->interface == PHY_INTERFACE_MODE_2500BASEX) | |
| 104 | + state->speed = SPEED_2500; | |
| 105 | + else | |
| 106 | + state->speed = SPEED_1000; | |
| 84 | 107 | } else { |
| 85 | 108 | state->link = false; |
| 86 | 109 | } |
| @@ -168,9 +191,15 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, · 81 unmodified lines | ||
| 168 | 191 | int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, |
| 169 | 192 | int lane, struct phylink_link_state *state) |
| 170 | 193 | { |
| 171 | − u16 lpa, status; | |
| 194 | + u16 lpa, status, ctrl; | |
| 172 | 195 | int err; |
| 173 | 196 | |
| 197 | + err = mv88e6352_serdes_read(chip, MII_BMCR, &ctrl); | |
| 198 | + if (err) { | |
| 199 | + dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); | |
| 200 | + return err; | |
| 201 | + } | |
| 202 | + | |
| 174 | 203 | err = mv88e6352_serdes_read(chip, 0x11, &status); |
| 175 | 204 | if (err) { |
| 176 | 205 | dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err); |
| @@ -183,7 +212,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, · 6 unmodified lines | ||
| 183 | 212 | return err; |
| 184 | 213 | } |
| 185 | 214 | |
| 186 | − return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); | |
| 215 | + return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); | |
| 187 | 216 | } |
| 188 | 217 | |
| 189 | 218 | int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, |
| @@ -801,7 +830,7 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, · 611 unmodified lines | ||
| 801 | 830 | bool up) |
| 802 | 831 | { |
| 803 | 832 | u8 cmode = chip->ports[port].cmode; |
| 804 | − int err = 0; | |
| 833 | + int err; | |
| 805 | 834 | |
| 806 | 835 | switch (cmode) { |
| 807 | 836 | case MV88E6XXX_PORT_STS_CMODE_SGMII: |
| @@ -813,6 +842,9 @@ int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, · 5 unmodified lines | ||
| 813 | 842 | case MV88E6XXX_PORT_STS_CMODE_RXAUI: |
| 814 | 843 | err = mv88e6390_serdes_power_10g(chip, lane, up); |
| 815 | 844 | break; |
| 845 | + default: | |
| 846 | + err = -EINVAL; | |
| 847 | + break; | |
| 816 | 848 | } |
| 817 | 849 | |
| 818 | 850 | if (!err && up) |
| @@ -883,9 +915,16 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, · 64 unmodified lines | ||
| 883 | 915 | static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, |
| 884 | 916 | int port, int lane, struct phylink_link_state *state) |
| 885 | 917 | { |
| 886 | − u16 lpa, status; | |
| 918 | + u16 lpa, status, ctrl; | |
| 887 | 919 | int err; |
| 888 | 920 | |
| 921 | + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, | |
| 922 | + MV88E6390_SGMII_BMCR, &ctrl); | |
| 923 | + if (err) { | |
| 924 | + dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); | |
| 925 | + return err; | |
| 926 | + } | |
| 927 | + | |
| 889 | 928 | err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, |
| 890 | 929 | MV88E6390_SGMII_PHY_STATUS, &status); |
| 891 | 930 | if (err) { |
| @@ -900,7 +939,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, · 8 unmodified lines | ||
| 900 | 939 | return err; |
| 901 | 940 | } |
| 902 | 941 | |
| 903 | − return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state); | |
| 942 | + return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); | |
| 904 | 943 | } |
| 905 | 944 | |
| 906 | 945 | static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, |
| @@ -1271,9 +1310,31 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p) · 364 unmodified lines | ||
| 1271 | 1310 | } |
| 1272 | 1311 | } |
| 1273 | 1312 | |
| 1274 | −static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) | |
| 1313 | +static int mv88e6393x_serdes_power_lane(struct mv88e6xxx_chip *chip, int lane, | |
| 1314 | + bool on) | |
| 1275 | 1315 | { |
| 1276 | − u16 reg, pcs; | |
| 1316 | + u16 reg; | |
| 1317 | + int err; | |
| 1318 | + | |
| 1319 | + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, | |
| 1320 | + MV88E6393X_SERDES_CTRL1, ®); | |
| 1321 | + if (err) | |
| 1322 | + return err; | |
| 1323 | + | |
| 1324 | + if (on) | |
| 1325 | + reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN | | |
| 1326 | + MV88E6393X_SERDES_CTRL1_RX_PDOWN); | |
| 1327 | + else | |
| 1328 | + reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN | | |
| 1329 | + MV88E6393X_SERDES_CTRL1_RX_PDOWN; | |
| 1330 | + | |
| 1331 | + return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, | |
| 1332 | + MV88E6393X_SERDES_CTRL1, reg); | |
| 1333 | +} | |
| 1334 | + | |
| 1335 | +static int mv88e6393x_serdes_erratum_4_6(struct mv88e6xxx_chip *chip, int lane) | |
| 1336 | +{ | |
| 1337 | + u16 reg; | |
| 1277 | 1338 | int err; |
| 1278 | 1339 | |
| 1279 | 1340 | /* mv88e6393x family errata 4.6: |
| @@ -1284,26 +1345,45 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) · 4 unmodified lines | ||
| 1284 | 1345 | * It seems that after this workaround the SERDES is automatically |
| 1285 | 1346 | * powered up (the bit is cleared), so power it down. |
| 1286 | 1347 | */ |
| 1287 | − if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE || | |
| 1288 | − lane == MV88E6393X_PORT10_LANE) { | |
| 1289 | − err = mv88e6390_serdes_read(chip, lane, | |
| 1290 | − MDIO_MMD_PHYXS, | |
| 1291 | − MV88E6393X_SERDES_POC, ®); | |
| 1292 | − if (err) | |
| 1293 | − return err; | |
| 1348 | + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, | |
| 1349 | + MV88E6393X_SERDES_POC, ®); | |
| 1350 | + if (err) | |
| 1351 | + return err; | |
| 1294 | 1352 | |
| 1295 | − reg &= ~MV88E6393X_SERDES_POC_PDOWN; | |
| 1296 | − reg |= MV88E6393X_SERDES_POC_RESET; | |
| 1353 | + reg &= ~MV88E6393X_SERDES_POC_PDOWN; | |
| 1354 | + reg |= MV88E6393X_SERDES_POC_RESET; | |
| 1297 | 1355 | |
| 1298 | − err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, | |
| 1299 | − MV88E6393X_SERDES_POC, reg); | |
| 1300 | − if (err) | |
| 1301 | − return err; | |
| 1356 | + err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, | |
| 1357 | + MV88E6393X_SERDES_POC, reg); | |
| 1358 | + if (err) | |
| 1359 | + return err; | |
| 1302 | 1360 | |
| 1303 | − err = mv88e6390_serdes_power_sgmii(chip, lane, false); | |
| 1304 | − if (err) | |
| 1305 | − return err; | |
| 1306 | − } | |
| 1361 | + err = mv88e6390_serdes_power_sgmii(chip, lane, false); | |
| 1362 | + if (err) | |
| 1363 | + return err; | |
| 1364 | + | |
| 1365 | + return mv88e6393x_serdes_power_lane(chip, lane, false); | |
| 1366 | +} | |
| 1367 | + | |
| 1368 | +int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) | |
| 1369 | +{ | |
| 1370 | + int err; | |
| 1371 | + | |
| 1372 | + err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT0_LANE); | |
| 1373 | + if (err) | |
| 1374 | + return err; | |
| 1375 | + | |
| 1376 | + err = mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT9_LANE); | |
| 1377 | + if (err) | |
| 1378 | + return err; | |
| 1379 | + | |
| 1380 | + return mv88e6393x_serdes_erratum_4_6(chip, MV88E6393X_PORT10_LANE); | |
| 1381 | +} | |
| 1382 | + | |
| 1383 | +static int mv88e6393x_serdes_erratum_4_8(struct mv88e6xxx_chip *chip, int lane) | |
| 1384 | +{ | |
| 1385 | + u16 reg, pcs; | |
| 1386 | + int err; | |
| 1307 | 1387 | |
| 1308 | 1388 | /* mv88e6393x family errata 4.8: |
| 1309 | 1389 | * When a SERDES port is operating in 1000BASE-X or SGMII mode link may |
| @@ -1334,38 +1414,152 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane) · 24 unmodified lines | ||
| 1334 | 1414 | MV88E6393X_ERRATA_4_8_REG, reg); |
| 1335 | 1415 | } |
| 1336 | 1416 | |
| 1337 | −int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip) | |
| 1417 | +static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, | |
| 1418 | + u8 cmode) | |
| 1419 | +{ | |
| 1420 | + static const struct { | |
| 1421 | + u16 dev, reg, val, mask; | |
| 1422 | + } fixes[] = { | |
| 1423 | + { MDIO_MMD_VEND1, 0x8093, 0xcb5a, 0xffff }, | |
| 1424 | + { MDIO_MMD_VEND1, 0x8171, 0x7088, 0xffff }, | |
| 1425 | + { MDIO_MMD_VEND1, 0x80c9, 0x311a, 0xffff }, | |
| 1426 | + { MDIO_MMD_VEND1, 0x80a2, 0x8000, 0xff7f }, | |
| 1427 | + { MDIO_MMD_VEND1, 0x80a9, 0x0000, 0xfff0 }, | |
| 1428 | + { MDIO_MMD_VEND1, 0x80a3, 0x0000, 0xf8ff }, | |
| 1429 | + { MDIO_MMD_PHYXS, MV88E6393X_SERDES_POC, | |
| 1430 | + MV88E6393X_SERDES_POC_RESET, MV88E6393X_SERDES_POC_RESET }, | |
| 1431 | + }; | |
| 1432 | + int err, i; | |
| 1433 | + u16 reg; | |
| 1434 | + | |
| 1435 | + /* mv88e6393x family errata 5.2: | |
| 1436 | + * For optimal signal integrity the following sequence should be applied | |
| 1437 | + * to SERDES operating in 10G mode. These registers only apply to 10G | |
| 1438 | + * operation and have no effect on other speeds. | |
| 1439 | + */ | |
| 1440 | + if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER) | |
| 1441 | + return 0; | |
| 1442 | + | |
| 1443 | + for (i = 0; i < ARRAY_SIZE(fixes); ++i) { | |
| 1444 | + err = mv88e6390_serdes_read(chip, lane, fixes[i].dev, | |
| 1445 | + fixes[i].reg, ®); | |
| 1446 | + if (err) | |
| 1447 | + return err; | |
| 1448 | + | |
| 1449 | + reg &= ~fixes[i].mask; | |
| 1450 | + reg |= fixes[i].val; | |
| 1451 | + | |
| 1452 | + err = mv88e6390_serdes_write(chip, lane, fixes[i].dev, | |
| 1453 | + fixes[i].reg, reg); | |
| 1454 | + if (err) | |
| 1455 | + return err; | |
| 1456 | + } | |
| 1457 | + | |
| 1458 | + return 0; | |
| 1459 | +} | |
| 1460 | + | |
| 1461 | +static int mv88e6393x_serdes_fix_2500basex_an(struct mv88e6xxx_chip *chip, | |
| 1462 | + int lane, u8 cmode, bool on) | |
| 1338 | 1463 | { |
| 1464 | + u16 reg; | |
| 1339 | 1465 | int err; |
| 1340 | 1466 | |
| 1341 | − err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT0_LANE); | |
| 1467 | + if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX) | |
| 1468 | + return 0; | |
| 1469 | + | |
| 1470 | + /* Inband AN is broken on Amethyst in 2500base-x mode when set by | |
| 1471 | + * standard mechanism (via cmode). | |
| 1472 | + * We can get around this by configuring the PCS mode to 1000base-x | |
| 1473 | + * and then writing value 0x58 to register 1e.8000. (This must be done | |
| 1474 | + * while SerDes receiver and transmitter are disabled, which is, when | |
| 1475 | + * this function is called.) | |
| 1476 | + * It seem that when we do this configuration to 2500base-x mode (by | |
| 1477 | + * changing PCS mode to 1000base-x and frequency to 3.125 GHz from | |
| 1478 | + * 1.25 GHz) and then configure to sgmii or 1000base-x, the device | |
| 1479 | + * thinks that it already has SerDes at 1.25 GHz and does not change | |
| 1480 | + * the 1e.8000 register, leaving SerDes at 3.125 GHz. | |
| 1481 | + * To avoid this, change PCS mode back to 2500base-x when disabling | |
| 1482 | + * SerDes from 2500base-x mode. | |
| 1483 | + */ | |
| 1484 | + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, | |
| 1485 | + MV88E6393X_SERDES_POC, ®); | |
| 1486 | + if (err) | |
| 1487 | + return err; | |
| 1488 | + | |
| 1489 | + reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN); | |
| 1490 | + if (on) | |
| 1491 | + reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX | | |
| 1492 | + MV88E6393X_SERDES_POC_AN; | |
| 1493 | + else | |
| 1494 | + reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX; | |
| 1495 | + reg |= MV88E6393X_SERDES_POC_RESET; | |
| 1496 | + | |
| 1497 | + err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS, | |
| 1498 | + MV88E6393X_SERDES_POC, reg); | |
| 1342 | 1499 | if (err) |
| 1343 | 1500 | return err; |
| 1344 | 1501 | |
| 1345 | − err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT9_LANE); | |
| 1502 | + err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_VEND1, 0x8000, 0x58); | |
| 1346 | 1503 | if (err) |
| 1347 | 1504 | return err; |
| 1348 | 1505 | |
| 1349 | − return mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT10_LANE); | |
| 1506 | + return 0; | |
| 1350 | 1507 | } |
| 1351 | 1508 | |
| 1352 | 1509 | int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, |
| 1353 | 1510 | bool on) |
| 1354 | 1511 | { |
| 1355 | 1512 | u8 cmode = chip->ports[port].cmode; |
| 1513 | + int err; | |
| 1356 | 1514 | |
| 1357 | 1515 | if (port != 0 && port != 9 && port != 10) |
| 1358 | 1516 | return -EOPNOTSUPP; |
| 1359 | 1517 | |
| 1518 | + if (on) { | |
| 1519 | + err = mv88e6393x_serdes_erratum_4_8(chip, lane); | |
| 1520 | + if (err) | |
| 1521 | + return err; | |
| 1522 | + | |
| 1523 | + err = mv88e6393x_serdes_erratum_5_2(chip, lane, cmode); | |
| 1524 | + if (err) | |
| 1525 | + return err; | |
| 1526 | + | |
| 1527 | + err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, | |
| 1528 | + true); | |
| 1529 | + if (err) | |
| 1530 | + return err; | |
| 1531 | + | |
| 1532 | + err = mv88e6393x_serdes_power_lane(chip, lane, true); | |
| 1533 | + if (err) | |
| 1534 | + return err; | |
| 1535 | + } | |
| 1536 | + | |
| 1360 | 1537 | switch (cmode) { |
| 1361 | 1538 | case MV88E6XXX_PORT_STS_CMODE_SGMII: |
| 1362 | 1539 | case MV88E6XXX_PORT_STS_CMODE_1000BASEX: |
| 1363 | 1540 | case MV88E6XXX_PORT_STS_CMODE_2500BASEX: |
| 1364 | − return mv88e6390_serdes_power_sgmii(chip, lane, on); | |
| 1541 | + err = mv88e6390_serdes_power_sgmii(chip, lane, on); | |
| 1542 | + break; | |
| 1365 | 1543 | case MV88E6393X_PORT_STS_CMODE_5GBASER: |
| 1366 | 1544 | case MV88E6393X_PORT_STS_CMODE_10GBASER: |
| 1367 | − return mv88e6390_serdes_power_10g(chip, lane, on); | |
| 1545 | + err = mv88e6390_serdes_power_10g(chip, lane, on); | |
| 1546 | + break; | |
| 1547 | + default: | |
| 1548 | + err = -EINVAL; | |
| 1549 | + break; | |
| 1368 | 1550 | } |
| 1369 | 1551 | |
| 1370 | − return 0; | |
| 1552 | + if (err) | |
| 1553 | + return err; | |
| 1554 | + | |
| 1555 | + if (!on) { | |
| 1556 | + err = mv88e6393x_serdes_power_lane(chip, lane, false); | |
| 1557 | + if (err) | |
| 1558 | + return err; | |
| 1559 | + | |
| 1560 | + err = mv88e6393x_serdes_fix_2500basex_an(chip, lane, cmode, | |
| 1561 | + false); | |
| 1562 | + } | |
| 1563 | + | |
| 1564 | + return err; | |
| 1371 | 1565 | } |
| @@ -93,6 +93,10 @@ · 92 unmodified lines | ||
| 93 | 93 | #define MV88E6393X_SERDES_POC_PCS_MASK 0x0007 |
| 94 | 94 | #define MV88E6393X_SERDES_POC_RESET BIT(15) |
| 95 | 95 | #define MV88E6393X_SERDES_POC_PDOWN BIT(5) |
| 96 | +#define MV88E6393X_SERDES_POC_AN BIT(3) | |
| 97 | +#define MV88E6393X_SERDES_CTRL1 0xf003 | |
| 98 | +#define MV88E6393X_SERDES_CTRL1_TX_PDOWN BIT(9) | |
| 99 | +#define MV88E6393X_SERDES_CTRL1_RX_PDOWN BIT(8) | |
| 96 | 100 | |
| 97 | 101 | #define MV88E6393X_ERRATA_4_8_REG 0xF074 |
| 98 | 102 | #define MV88E6393X_ERRATA_4_8_BIT BIT(14) |
| @@ -290,8 +290,11 @@ static int felix_setup_mmio_filtering(struct felix *felix) · 289 unmodified lines | ||
| 290 | 290 | } |
| 291 | 291 | } |
| 292 | 292 | |
| 293 | − if (cpu < 0) | |
| 293 | + if (cpu < 0) { | |
| 294 | + kfree(tagging_rule); | |
| 295 | + kfree(redirect_rule); | |
| 294 | 296 | return -EINVAL; |
| 297 | + } | |
| 295 | 298 | |
| 296 | 299 | tagging_rule->key_type = OCELOT_VCAP_KEY_ETYPE; |
| 297 | 300 | *(__be16 *)tagging_rule->key.etype.etype.value = htons(ETH_P_1588); |
| @@ -107,6 +107,7 @@ · 106 unmodified lines | ||
| 107 | 107 | #define RTL8365MB_LEARN_LIMIT_MAX_8365MB_VC 2112 |
| 108 | 108 | |
| 109 | 109 | /* Family-specific data and limits */ |
| 110 | +#define RTL8365MB_PHYADDRMAX 7 | |
| 110 | 111 | #define RTL8365MB_NUM_PHYREGS 32 |
| 111 | 112 | #define RTL8365MB_PHYREGMAX (RTL8365MB_NUM_PHYREGS - 1) |
| 112 | 113 | #define RTL8365MB_MAX_NUM_PORTS (RTL8365MB_CPU_PORT_NUM_8365MB_VC + 1) |
| @@ -176,7 +177,7 @@ · 63 unmodified lines | ||
| 176 | 177 | #define RTL8365MB_INDIRECT_ACCESS_STATUS_REG 0x1F01 |
| 177 | 178 | #define RTL8365MB_INDIRECT_ACCESS_ADDRESS_REG 0x1F02 |
| 178 | 179 | #define RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_5_1_MASK GENMASK(4, 0) |
| 179 | −#define RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK GENMASK(6, 5) | |
| 180 | +#define RTL8365MB_INDIRECT_ACCESS_ADDRESS_PHYNUM_MASK GENMASK(7, 5) | |
| 180 | 181 | #define RTL8365MB_INDIRECT_ACCESS_ADDRESS_OCPADR_9_6_MASK GENMASK(11, 8) |
| 181 | 182 | #define RTL8365MB_PHY_BASE 0x2000 |
| 182 | 183 | #define RTL8365MB_INDIRECT_ACCESS_WRITE_DATA_REG 0x1F03 |
| @@ -679,6 +680,9 @@ static int rtl8365mb_phy_read(struct realtek_smi *smi, int phy, int regnum) · 496 unmodified lines | ||
| 679 | 680 | u16 val; |
| 680 | 681 | int ret; |
| 681 | 682 | |
| 683 | + if (phy > RTL8365MB_PHYADDRMAX) | |
| 684 | + return -EINVAL; | |
| 685 | + | |
| 682 | 686 | if (regnum > RTL8365MB_PHYREGMAX) |
| 683 | 687 | return -EINVAL; |
| 684 | 688 | |
| @@ -704,6 +708,9 @@ static int rtl8365mb_phy_write(struct realtek_smi *smi, int phy, int regnum, · 19 unmodified lines | ||
| 704 | 708 | u32 ocp_addr; |
| 705 | 709 | int ret; |
| 706 | 710 | |
| 711 | + if (phy > RTL8365MB_PHYADDRMAX) | |
| 712 | + return -EINVAL; | |
| 713 | + | |
| 707 | 714 | if (regnum > RTL8365MB_PHYREGMAX) |
| 708 | 715 | return -EINVAL; |
| 709 | 716 | |
| @@ -1430,16 +1430,19 @@ static int altera_tse_probe(struct platform_device *pdev) · 1429 unmodified lines | ||
| 1430 | 1430 | priv->rxdescmem_busaddr = dma_res->start; |
| 1431 | 1431 | |
| 1432 | 1432 | } else { |
| 1433 | + ret = -ENODEV; | |
| 1433 | 1434 | goto err_free_netdev; |
| 1434 | 1435 | } |
| 1435 | 1436 | |
| 1436 | − if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) | |
| 1437 | + if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) { | |
| 1437 | 1438 | dma_set_coherent_mask(priv->device, |
| 1438 | 1439 | DMA_BIT_MASK(priv->dmaops->dmamask)); |
| 1439 | − else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) | |
| 1440 | + } else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) { | |
| 1440 | 1441 | dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); |
| 1441 | − else | |
| 1442 | + } else { | |
| 1443 | + ret = -EIO; | |
| 1442 | 1444 | goto err_free_netdev; |
| 1445 | + } | |
| 1443 | 1446 | |
| 1444 | 1447 | /* MAC address space */ |
| 1445 | 1448 | ret = request_and_map(pdev, "control_port", &control_port, |
| @@ -40,10 +40,12 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | #define AQ_DEVICE_ID_AQC113DEV 0x00C0 |
| 42 | 42 | #define AQ_DEVICE_ID_AQC113CS 0x94C0 |
| 43 | +#define AQ_DEVICE_ID_AQC113CA 0x34C0 | |
| 43 | 44 | #define AQ_DEVICE_ID_AQC114CS 0x93C0 |
| 44 | 45 | #define AQ_DEVICE_ID_AQC113 0x04C0 |
| 45 | 46 | #define AQ_DEVICE_ID_AQC113C 0x14C0 |
| 46 | 47 | #define AQ_DEVICE_ID_AQC115C 0x12C0 |
| 48 | +#define AQ_DEVICE_ID_AQC116C 0x11C0 | |
| 47 | 49 | |
| 48 | 50 | #define HW_ATL_NIC_NAME "Marvell (aQuantia) AQtion 10Gbit Network Adapter" |
| 49 | 51 | |
| @@ -53,20 +55,19 @@ · 3 unmodified lines | ||
| 53 | 55 | |
| 54 | 56 | #define AQ_NIC_RATE_10G BIT(0) |
| 55 | 57 | #define AQ_NIC_RATE_5G BIT(1) |
| 56 | −#define AQ_NIC_RATE_5GSR BIT(2) | |
| 57 | −#define AQ_NIC_RATE_2G5 BIT(3) | |
| 58 | −#define AQ_NIC_RATE_1G BIT(4) | |
| 59 | −#define AQ_NIC_RATE_100M BIT(5) | |
| 60 | −#define AQ_NIC_RATE_10M BIT(6) | |
| 61 | −#define AQ_NIC_RATE_1G_HALF BIT(7) | |
| 62 | −#define AQ_NIC_RATE_100M_HALF BIT(8) | |
| 63 | −#define AQ_NIC_RATE_10M_HALF BIT(9) | |
| 58 | +#define AQ_NIC_RATE_2G5 BIT(2) | |
| 59 | +#define AQ_NIC_RATE_1G BIT(3) | |
| 60 | +#define AQ_NIC_RATE_100M BIT(4) | |
| 61 | +#define AQ_NIC_RATE_10M BIT(5) | |
| 62 | +#define AQ_NIC_RATE_1G_HALF BIT(6) | |
| 63 | +#define AQ_NIC_RATE_100M_HALF BIT(7) | |
| 64 | +#define AQ_NIC_RATE_10M_HALF BIT(8) | |
| 64 | 65 | |
| 65 | −#define AQ_NIC_RATE_EEE_10G BIT(10) | |
| 66 | −#define AQ_NIC_RATE_EEE_5G BIT(11) | |
| 67 | −#define AQ_NIC_RATE_EEE_2G5 BIT(12) | |
| 68 | −#define AQ_NIC_RATE_EEE_1G BIT(13) | |
| 69 | −#define AQ_NIC_RATE_EEE_100M BIT(14) | |
| 66 | +#define AQ_NIC_RATE_EEE_10G BIT(9) | |
| 67 | +#define AQ_NIC_RATE_EEE_5G BIT(10) | |
| 68 | +#define AQ_NIC_RATE_EEE_2G5 BIT(11) | |
| 69 | +#define AQ_NIC_RATE_EEE_1G BIT(12) | |
| 70 | +#define AQ_NIC_RATE_EEE_100M BIT(13) | |
| 70 | 71 | #define AQ_NIC_RATE_EEE_MSK (AQ_NIC_RATE_EEE_10G |\ |
| 71 | 72 | AQ_NIC_RATE_EEE_5G |\ |
| 72 | 73 | AQ_NIC_RATE_EEE_2G5 |\ |
| @@ -80,6 +80,8 @@ struct aq_hw_link_status_s { · 79 unmodified lines | ||
| 80 | 80 | }; |
| 81 | 81 | |
| 82 | 82 | struct aq_stats_s { |
| 83 | + u64 brc; | |
| 84 | + u64 btc; | |
| 83 | 85 | u64 uprc; |
| 84 | 86 | u64 mprc; |
| 85 | 87 | u64 bprc; |
| @@ -316,18 +316,22 @@ int aq_nic_ndev_register(struct aq_nic_s *self) · 315 unmodified lines | ||
| 316 | 316 | aq_macsec_init(self); |
| 317 | 317 | #endif |
| 318 | 318 | |
| 319 | − mutex_lock(&self->fwreq_mutex); | |
| 320 | − err = self->aq_fw_ops->get_mac_permanent(self->aq_hw, addr); | |
| 321 | − mutex_unlock(&self->fwreq_mutex); | |
| 322 | − if (err) | |
| 323 | − goto err_exit; | |
| 319 | + if (platform_get_ethdev_address(&self->pdev->dev, self->ndev) != 0) { | |
| 320 | + // If DT has none or an invalid one, ask device for MAC address | |
| 321 | + mutex_lock(&self->fwreq_mutex); | |
| 322 | + err = self->aq_fw_ops->get_mac_permanent(self->aq_hw, addr); | |
| 323 | + mutex_unlock(&self->fwreq_mutex); | |
| 324 | 324 | |
| 325 | − eth_hw_addr_set(self->ndev, addr); | |
| 325 | + if (err) | |
| 326 | + goto err_exit; | |
| 326 | 327 | |
| 327 | − if (!is_valid_ether_addr(self->ndev->dev_addr) || | |
| 328 | − !aq_nic_is_valid_ether_addr(self->ndev->dev_addr)) { | |
| 329 | − netdev_warn(self->ndev, "MAC is invalid, will use random."); | |
| 330 | − eth_hw_addr_random(self->ndev); | |
| 328 | + if (is_valid_ether_addr(addr) && | |
| 329 | + aq_nic_is_valid_ether_addr(addr)) { | |
| 330 | + eth_hw_addr_set(self->ndev, addr); | |
| 331 | + } else { | |
| 332 | + netdev_warn(self->ndev, "MAC is invalid, will use random."); | |
| 333 | + eth_hw_addr_random(self->ndev); | |
| 334 | + } | |
| 331 | 335 | } |
| 332 | 336 | |
| 333 | 337 | #if defined(AQ_CFG_MAC_ADDR_PERMANENT) |
| @@ -905,8 +909,14 @@ u64 *aq_nic_get_stats(struct aq_nic_s *self, u64 *data) · 571 unmodified lines | ||
| 905 | 909 | data[++i] = stats->mbtc; |
| 906 | 910 | data[++i] = stats->bbrc; |
| 907 | 911 | data[++i] = stats->bbtc; |
| 908 | − data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; | |
| 909 | − data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; | |
| 912 | + if (stats->brc) | |
| 913 | + data[++i] = stats->brc; | |
| 914 | + else | |
| 915 | + data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; | |
| 916 | + if (stats->btc) | |
| 917 | + data[++i] = stats->btc; | |
| 918 | + else | |
| 919 | + data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; | |
| 910 | 920 | data[++i] = stats->dma_pkt_rc; |
| 911 | 921 | data[++i] = stats->dma_pkt_tc; |
| 912 | 922 | data[++i] = stats->dma_oct_rc; |
| @@ -49,6 +49,8 @@ static const struct pci_device_id aq_pci_tbl[] = { · 48 unmodified lines | ||
| 49 | 49 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113), }, |
| 50 | 50 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113C), }, |
| 51 | 51 | { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC115C), }, |
| 52 | + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC113CA), }, | |
| 53 | + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC116C), }, | |
| 52 | 54 | |
| 53 | 55 | {} |
| 54 | 56 | }; |
| @@ -85,7 +87,10 @@ static const struct aq_board_revision_s hw_atl_boards[] = { · 30 unmodified lines | ||
| 85 | 87 | { AQ_DEVICE_ID_AQC113CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, |
| 86 | 88 | { AQ_DEVICE_ID_AQC114CS, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, |
| 87 | 89 | { AQ_DEVICE_ID_AQC113C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, |
| 88 | − { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, | |
| 90 | + { AQ_DEVICE_ID_AQC115C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc115c, }, | |
| 91 | + { AQ_DEVICE_ID_AQC113CA, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc113, }, | |
| 92 | + { AQ_DEVICE_ID_AQC116C, AQ_HWREV_ANY, &hw_atl2_ops, &hw_atl2_caps_aqc116c, }, | |
| 93 | + | |
| 89 | 94 | }; |
| 90 | 95 | |
| 91 | 96 | MODULE_DEVICE_TABLE(pci, aq_pci_tbl); |
| @@ -362,9 +362,6 @@ unsigned int aq_vec_get_sw_stats(struct aq_vec_s *self, const unsigned int tc, u · 361 unmodified lines | ||
| 362 | 362 | { |
| 363 | 363 | unsigned int count; |
| 364 | 364 | |
| 365 | − WARN_ONCE(!aq_vec_is_valid_tc(self, tc), | |
| 366 | − "Invalid tc %u (#rx=%u, #tx=%u)\n", | |
| 367 | − tc, self->rx_rings, self->tx_rings); | |
| 368 | 365 | if (!aq_vec_is_valid_tc(self, tc)) |
| 369 | 366 | return 0; |
| 370 | 367 | |
| @@ -867,12 +867,20 @@ static int hw_atl_fw1x_deinit(struct aq_hw_s *self) · 866 unmodified lines | ||
| 867 | 867 | int hw_atl_utils_update_stats(struct aq_hw_s *self) |
| 868 | 868 | { |
| 869 | 869 | struct aq_stats_s *cs = &self->curr_stats; |
| 870 | + struct aq_stats_s curr_stats = *cs; | |
| 870 | 871 | struct hw_atl_utils_mbox mbox; |
| 872 | + bool corrupted_stats = false; | |
| 871 | 873 | |
| 872 | 874 | hw_atl_utils_mpi_read_stats(self, &mbox); |
| 873 | 875 | |
| 874 | −#define AQ_SDELTA(_N_) (self->curr_stats._N_ += \ | |
| 875 | − mbox.stats._N_ - self->last_stats._N_) | |
| 876 | +#define AQ_SDELTA(_N_) \ | |
| 877 | +do { \ | |
| 878 | + if (!corrupted_stats && \ | |
| 879 | + ((s64)(mbox.stats._N_ - self->last_stats._N_)) >= 0) \ | |
| 880 | + curr_stats._N_ += mbox.stats._N_ - self->last_stats._N_; \ | |
| 881 | + else \ | |
| 882 | + corrupted_stats = true; \ | |
| 883 | +} while (0) | |
| 876 | 884 | |
| 877 | 885 | if (self->aq_link_status.mbps) { |
| 878 | 886 | AQ_SDELTA(uprc); |
| @@ -892,6 +900,9 @@ int hw_atl_utils_update_stats(struct aq_hw_s *self) · 13 unmodified lines | ||
| 892 | 900 | AQ_SDELTA(bbrc); |
| 893 | 901 | AQ_SDELTA(bbtc); |
| 894 | 902 | AQ_SDELTA(dpc); |
| 903 | + | |
| 904 | + if (!corrupted_stats) | |
| 905 | + *cs = curr_stats; | |
| 895 | 906 | } |
| 896 | 907 | #undef AQ_SDELTA |
| 897 | 908 | |
| @@ -132,9 +132,6 @@ static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) · 131 unmodified lines | ||
| 132 | 132 | if (speed & AQ_NIC_RATE_5G) |
| 133 | 133 | rate |= FW2X_RATE_5G; |
| 134 | 134 | |
| 135 | − if (speed & AQ_NIC_RATE_5GSR) | |
| 136 | − rate |= FW2X_RATE_5G; | |
| 137 | − | |
| 138 | 135 | if (speed & AQ_NIC_RATE_2G5) |
| 139 | 136 | rate |= FW2X_RATE_2G5; |
| 140 | 137 | |
| @@ -65,11 +65,25 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = { · 64 unmodified lines | ||
| 65 | 65 | AQ_NIC_RATE_5G | |
| 66 | 66 | AQ_NIC_RATE_2G5 | |
| 67 | 67 | AQ_NIC_RATE_1G | |
| 68 | − AQ_NIC_RATE_1G_HALF | | |
| 69 | 68 | AQ_NIC_RATE_100M | |
| 70 | − AQ_NIC_RATE_100M_HALF | | |
| 71 | − AQ_NIC_RATE_10M | | |
| 72 | − AQ_NIC_RATE_10M_HALF, | |
| 69 | + AQ_NIC_RATE_10M, | |
| 70 | +}; | |
| 71 | + | |
| 72 | +const struct aq_hw_caps_s hw_atl2_caps_aqc115c = { | |
| 73 | + DEFAULT_BOARD_BASIC_CAPABILITIES, | |
| 74 | + .media_type = AQ_HW_MEDIA_TYPE_TP, | |
| 75 | + .link_speed_msk = AQ_NIC_RATE_2G5 | | |
| 76 | + AQ_NIC_RATE_1G | | |
| 77 | + AQ_NIC_RATE_100M | | |
| 78 | + AQ_NIC_RATE_10M, | |
| 79 | +}; | |
| 80 | + | |
| 81 | +const struct aq_hw_caps_s hw_atl2_caps_aqc116c = { | |
| 82 | + DEFAULT_BOARD_BASIC_CAPABILITIES, | |
| 83 | + .media_type = AQ_HW_MEDIA_TYPE_TP, | |
| 84 | + .link_speed_msk = AQ_NIC_RATE_1G | | |
| 85 | + AQ_NIC_RATE_100M | | |
| 86 | + AQ_NIC_RATE_10M, | |
| 73 | 87 | }; |
| 74 | 88 | |
| 75 | 89 | static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self) |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | #include "aq_common.h" |
| 10 | 10 | |
| 11 | 11 | extern const struct aq_hw_caps_s hw_atl2_caps_aqc113; |
| 12 | +extern const struct aq_hw_caps_s hw_atl2_caps_aqc115c; | |
| 13 | +extern const struct aq_hw_caps_s hw_atl2_caps_aqc116c; | |
| 12 | 14 | extern const struct aq_hw_ops hw_atl2_ops; |
| 13 | 15 | |
| 14 | 16 | #endif /* HW_ATL2_H */ |
| @@ -239,7 +239,8 @@ struct version_s { · 238 unmodified lines | ||
| 239 | 239 | u8 minor; |
| 240 | 240 | u16 build; |
| 241 | 241 | } phy; |
| 242 | − u32 rsvd; | |
| 242 | + u32 drv_iface_ver:4; | |
| 243 | + u32 rsvd:28; | |
| 243 | 244 | }; |
| 244 | 245 | |
| 245 | 246 | struct link_status_s { |
| @@ -424,7 +425,7 @@ struct cable_diag_status_s { · 178 unmodified lines | ||
| 424 | 425 | u16 rsvd2; |
| 425 | 426 | }; |
| 426 | 427 | |
| 427 | −struct statistics_s { | |
| 428 | +struct statistics_a0_s { | |
| 428 | 429 | struct { |
| 429 | 430 | u32 link_up; |
| 430 | 431 | u32 link_down; |
| @@ -457,6 +458,33 @@ struct statistics_s { · 26 unmodified lines | ||
| 457 | 458 | u32 reserve_fw_gap; |
| 458 | 459 | }; |
| 459 | 460 | |
| 461 | +struct __packed statistics_b0_s { | |
| 462 | + u64 rx_good_octets; | |
| 463 | + u64 rx_pause_frames; | |
| 464 | + u64 rx_good_frames; | |
| 465 | + u64 rx_errors; | |
| 466 | + u64 rx_unicast_frames; | |
| 467 | + u64 rx_multicast_frames; | |
| 468 | + u64 rx_broadcast_frames; | |
| 469 | + | |
| 470 | + u64 tx_good_octets; | |
| 471 | + u64 tx_pause_frames; | |
| 472 | + u64 tx_good_frames; | |
| 473 | + u64 tx_errors; | |
| 474 | + u64 tx_unicast_frames; | |
| 475 | + u64 tx_multicast_frames; | |
| 476 | + u64 tx_broadcast_frames; | |
| 477 | + | |
| 478 | + u32 main_loop_cycles; | |
| 479 | +}; | |
| 480 | + | |
| 481 | +struct __packed statistics_s { | |
| 482 | + union __packed { | |
| 483 | + struct statistics_a0_s a0; | |
| 484 | + struct statistics_b0_s b0; | |
| 485 | + }; | |
| 486 | +}; | |
| 487 | + | |
| 460 | 488 | struct filter_caps_s { |
| 461 | 489 | u8 l2_filters_base_index:6; |
| 462 | 490 | u8 flexible_filter_mask:2; |
| @@ -545,7 +573,7 @@ struct management_status_s { · 82 unmodified lines | ||
| 545 | 573 | u32 rsvd5; |
| 546 | 574 | }; |
| 547 | 575 | |
| 548 | −struct fw_interface_out { | |
| 576 | +struct __packed fw_interface_out { | |
| 549 | 577 | struct transaction_counter_s transaction_id; |
| 550 | 578 | struct version_s version; |
| 551 | 579 | struct link_status_s link_status; |
| @@ -569,7 +597,6 @@ struct fw_interface_out { · 17 unmodified lines | ||
| 569 | 597 | struct core_dump_s core_dump; |
| 570 | 598 | u32 rsvd11; |
| 571 | 599 | struct statistics_s stats; |
| 572 | − u32 rsvd12; | |
| 573 | 600 | struct filter_caps_s filter_caps; |
| 574 | 601 | struct device_caps_s device_caps; |
| 575 | 602 | u32 rsvd13; |
| @@ -592,6 +619,9 @@ struct fw_interface_out { · 16 unmodified lines | ||
| 592 | 619 | #define AQ_HOST_MODE_LOW_POWER 3U |
| 593 | 620 | #define AQ_HOST_MODE_SHUTDOWN 4U |
| 594 | 621 | |
| 622 | +#define AQ_A2_FW_INTERFACE_A0 0 | |
| 623 | +#define AQ_A2_FW_INTERFACE_B0 1 | |
| 624 | + | |
| 595 | 625 | int hw_atl2_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops); |
| 596 | 626 | |
| 597 | 627 | int hw_atl2_utils_soft_reset(struct aq_hw_s *self); |
| @@ -84,7 +84,7 @@ static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self, · 83 unmodified lines | ||
| 84 | 84 | if (cnt > AQ_A2_FW_READ_TRY_MAX) |
| 85 | 85 | return -ETIME; |
| 86 | 86 | if (tid1.transaction_cnt_a != tid1.transaction_cnt_b) |
| 87 | − udelay(1); | |
| 87 | + mdelay(1); | |
| 88 | 88 | } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b); |
| 89 | 89 | |
| 90 | 90 | hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords); |
| @@ -154,7 +154,7 @@ static void a2_link_speed_mask2fw(u32 speed, · 63 unmodified lines | ||
| 154 | 154 | { |
| 155 | 155 | link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G); |
| 156 | 156 | link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G); |
| 157 | − link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR); | |
| 157 | + link_options->rate_N5G = link_options->rate_5G; | |
| 158 | 158 | link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5); |
| 159 | 159 | link_options->rate_N2P5G = link_options->rate_2P5G; |
| 160 | 160 | link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); |
| @@ -192,8 +192,6 @@ static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps) · 31 unmodified lines | ||
| 192 | 192 | rate |= AQ_NIC_RATE_10G; |
| 193 | 193 | if (lkp_link_caps->rate_5G) |
| 194 | 194 | rate |= AQ_NIC_RATE_5G; |
| 195 | − if (lkp_link_caps->rate_N5G) | |
| 196 | − rate |= AQ_NIC_RATE_5GSR; | |
| 197 | 195 | if (lkp_link_caps->rate_2P5G) |
| 198 | 196 | rate |= AQ_NIC_RATE_2G5; |
| 199 | 197 | if (lkp_link_caps->rate_1G) |
| @@ -335,15 +333,22 @@ static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) · 135 unmodified lines | ||
| 335 | 333 | return 0; |
| 336 | 334 | } |
| 337 | 335 | |
| 338 | −static int aq_a2_fw_update_stats(struct aq_hw_s *self) | |
| 336 | +static void aq_a2_fill_a0_stats(struct aq_hw_s *self, | |
| 337 | + struct statistics_s *stats) | |
| 339 | 338 | { |
| 340 | 339 | struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; |
| 341 | − struct statistics_s stats; | |
| 342 | − | |
| 343 | − hw_atl2_shared_buffer_read_safe(self, stats, &stats); | |
| 344 | − | |
| 345 | −#define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \ | |
| 346 | − stats.msm._F_ - priv->last_stats.msm._F_) | |
| 340 | + struct aq_stats_s *cs = &self->curr_stats; | |
| 341 | + struct aq_stats_s curr_stats = *cs; | |
| 342 | + bool corrupted_stats = false; | |
| 343 | + | |
| 344 | +#define AQ_SDELTA(_N, _F) \ | |
| 345 | +do { \ | |
| 346 | + if (!corrupted_stats && \ | |
| 347 | + ((s64)(stats->a0.msm._F - priv->last_stats.a0.msm._F)) >= 0) \ | |
| 348 | + curr_stats._N += stats->a0.msm._F - priv->last_stats.a0.msm._F;\ | |
| 349 | + else \ | |
| 350 | + corrupted_stats = true; \ | |
| 351 | +} while (0) | |
| 347 | 352 | |
| 348 | 353 | if (self->aq_link_status.mbps) { |
| 349 | 354 | AQ_SDELTA(uprc, rx_unicast_frames); |
| @@ -362,17 +367,76 @@ static int aq_a2_fw_update_stats(struct aq_hw_s *self) · 12 unmodified lines | ||
| 362 | 367 | AQ_SDELTA(mbtc, tx_multicast_octets); |
| 363 | 368 | AQ_SDELTA(bbrc, rx_broadcast_octets); |
| 364 | 369 | AQ_SDELTA(bbtc, tx_broadcast_octets); |
| 370 | + | |
| 371 | + if (!corrupted_stats) | |
| 372 | + *cs = curr_stats; | |
| 365 | 373 | } |
| 366 | 374 | #undef AQ_SDELTA |
| 367 | − self->curr_stats.dma_pkt_rc = | |
| 368 | − hw_atl_stats_rx_dma_good_pkt_counter_get(self); | |
| 369 | − self->curr_stats.dma_pkt_tc = | |
| 370 | − hw_atl_stats_tx_dma_good_pkt_counter_get(self); | |
| 371 | − self->curr_stats.dma_oct_rc = | |
| 372 | − hw_atl_stats_rx_dma_good_octet_counter_get(self); | |
| 373 | − self->curr_stats.dma_oct_tc = | |
| 374 | − hw_atl_stats_tx_dma_good_octet_counter_get(self); | |
| 375 | − self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); | |
| 375 | + | |
| 376 | +} | |
| 377 | + | |
| 378 | +static void aq_a2_fill_b0_stats(struct aq_hw_s *self, | |
| 379 | + struct statistics_s *stats) | |
| 380 | +{ | |
| 381 | + struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; | |
| 382 | + struct aq_stats_s *cs = &self->curr_stats; | |
| 383 | + struct aq_stats_s curr_stats = *cs; | |
| 384 | + bool corrupted_stats = false; | |
| 385 | + | |
| 386 | +#define AQ_SDELTA(_N, _F) \ | |
| 387 | +do { \ | |
| 388 | + if (!corrupted_stats && \ | |
| 389 | + ((s64)(stats->b0._F - priv->last_stats.b0._F)) >= 0) \ | |
| 390 | + curr_stats._N += stats->b0._F - priv->last_stats.b0._F; \ | |
| 391 | + else \ | |
| 392 | + corrupted_stats = true; \ | |
| 393 | +} while (0) | |
| 394 | + | |
| 395 | + if (self->aq_link_status.mbps) { | |
| 396 | + AQ_SDELTA(uprc, rx_unicast_frames); | |
| 397 | + AQ_SDELTA(mprc, rx_multicast_frames); | |
| 398 | + AQ_SDELTA(bprc, rx_broadcast_frames); | |
| 399 | + AQ_SDELTA(erpr, rx_errors); | |
| 400 | + AQ_SDELTA(brc, rx_good_octets); | |
| 401 | + | |
| 402 | + AQ_SDELTA(uptc, tx_unicast_frames); | |
| 403 | + AQ_SDELTA(mptc, tx_multicast_frames); | |
| 404 | + AQ_SDELTA(bptc, tx_broadcast_frames); | |
| 405 | + AQ_SDELTA(erpt, tx_errors); | |
| 406 | + AQ_SDELTA(btc, tx_good_octets); | |
| 407 | + | |
| 408 | + if (!corrupted_stats) | |
| 409 | + *cs = curr_stats; | |
| 410 | + } | |
| 411 | +#undef AQ_SDELTA | |
| 412 | +} | |
| 413 | + | |
| 414 | +static int aq_a2_fw_update_stats(struct aq_hw_s *self) | |
| 415 | +{ | |
| 416 | + struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; | |
| 417 | + struct aq_stats_s *cs = &self->curr_stats; | |
| 418 | + struct statistics_s stats; | |
| 419 | + struct version_s version; | |
| 420 | + int err; | |
| 421 | + | |
| 422 | + err = hw_atl2_shared_buffer_read_safe(self, version, &version); | |
| 423 | + if (err) | |
| 424 | + return err; | |
| 425 | + | |
| 426 | + err = hw_atl2_shared_buffer_read_safe(self, stats, &stats); | |
| 427 | + if (err) | |
| 428 | + return err; | |
| 429 | + | |
| 430 | + if (version.drv_iface_ver == AQ_A2_FW_INTERFACE_A0) | |
| 431 | + aq_a2_fill_a0_stats(self, &stats); | |
| 432 | + else | |
| 433 | + aq_a2_fill_b0_stats(self, &stats); | |
| 434 | + | |
| 435 | + cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self); | |
| 436 | + cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self); | |
| 437 | + cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self); | |
| 438 | + cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self); | |
| 439 | + cs->dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); | |
| 376 | 440 | |
| 377 | 441 | memcpy(&priv->last_stats, &stats, sizeof(stats)); |
| 378 | 442 | |
| @@ -499,9 +563,9 @@ u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) · 120 unmodified lines | ||
| 499 | 563 | hw_atl2_shared_buffer_read_safe(self, version, &version); |
| 500 | 564 | |
| 501 | 565 | /* A2 FW version is stored in reverse order */ |
| 502 | − return version.mac.major << 24 | | |
| 503 | − version.mac.minor << 16 | | |
| 504 | − version.mac.build; | |
| 566 | + return version.bundle.major << 24 | | |
| 567 | + version.bundle.minor << 16 | | |
| 568 | + version.bundle.build; | |
| 505 | 569 | } |
| 506 | 570 | |
| 507 | 571 | int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, |
| @@ -708,7 +708,9 @@ static int bcm4908_enet_probe(struct platform_device *pdev) · 707 unmodified lines | ||
| 708 | 708 | |
| 709 | 709 | enet->irq_tx = platform_get_irq_byname(pdev, "tx"); |
| 710 | 710 | |
| 711 | − dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); | |
| 711 | + err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); | |
| 712 | + if (err) | |
| 713 | + return err; | |
| 712 | 714 | |
| 713 | 715 | err = bcm4908_enet_dma_alloc(enet); |
| 714 | 716 | if (err) |
| @@ -4550,6 +4550,8 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) · 4549 unmodified lines | ||
| 4550 | 4550 | |
| 4551 | 4551 | fsl_mc_portal_free(priv->mc_io); |
| 4552 | 4552 | |
| 4553 | + destroy_workqueue(priv->dpaa2_ptp_wq); | |
| 4554 | + | |
| 4553 | 4555 | dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name); |
| 4554 | 4556 | |
| 4555 | 4557 | free_netdev(net_dev); |
| @@ -377,6 +377,9 @@ struct bufdesc_ex { · 376 unmodified lines | ||
| 377 | 377 | #define FEC_ENET_WAKEUP ((uint)0x00020000) /* Wakeup request */ |
| 378 | 378 | #define FEC_ENET_TXF (FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2) |
| 379 | 379 | #define FEC_ENET_RXF (FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2) |
| 380 | +#define FEC_ENET_RXF_GET(X) (((X) == 0) ? FEC_ENET_RXF_0 : \ | |
| 381 | + (((X) == 1) ? FEC_ENET_RXF_1 : \ | |
| 382 | + FEC_ENET_RXF_2)) | |
| 380 | 383 | #define FEC_ENET_TS_AVAIL ((uint)0x00010000) |
| 381 | 384 | #define FEC_ENET_TS_TIMER ((uint)0x00008000) |
| 382 | 385 | |
| @@ -1480,7 +1480,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) · 1479 unmodified lines | ||
| 1480 | 1480 | break; |
| 1481 | 1481 | pkt_received++; |
| 1482 | 1482 | |
| 1483 | − writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); | |
| 1483 | + writel(FEC_ENET_RXF_GET(queue_id), fep->hwp + FEC_IEVENT); | |
| 1484 | 1484 | |
| 1485 | 1485 | /* Check for errors. */ |
| 1486 | 1486 | status ^= BD_ENET_RX_LAST; |
| @@ -68,6 +68,9 @@ struct sk_buff *gve_rx_copy(struct net_device *dev, struct napi_struct *napi, · 67 unmodified lines | ||
| 68 | 68 | set_protocol = ctx->curr_frag_cnt == ctx->expected_frag_cnt - 1; |
| 69 | 69 | } else { |
| 70 | 70 | skb = napi_alloc_skb(napi, len); |
| 71 | + | |
| 72 | + if (unlikely(!skb)) | |
| 73 | + return NULL; | |
| 71 | 74 | set_protocol = true; |
| 72 | 75 | } |
| 73 | 76 | __skb_put(skb, len); |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | #include <linux/interrupt.h> |
| 9 | 9 | #include <linux/etherdevice.h> |
| 10 | 10 | #include <linux/netdevice.h> |
| 11 | +#include <linux/module.h> | |
| 11 | 12 | |
| 12 | 13 | #include "hinic_hw_dev.h" |
| 13 | 14 | #include "hinic_dev.h" |
| @@ -628,17 +628,9 @@ static bool reuse_rx_pools(struct ibmvnic_adapter *adapter) · 627 unmodified lines | ||
| 628 | 628 | old_buff_size = adapter->prev_rx_buf_sz; |
| 629 | 629 | new_buff_size = adapter->cur_rx_buf_sz; |
| 630 | 630 | |
| 631 | − /* Require buff size to be exactly same for now */ | |
| 632 | − if (old_buff_size != new_buff_size) | |
| 633 | − return false; | |
| 634 | − | |
| 635 | − if (old_num_pools == new_num_pools && old_pool_size == new_pool_size) | |
| 636 | − return true; | |
| 637 | − | |
| 638 | − if (old_num_pools < adapter->min_rx_queues || | |
| 639 | − old_num_pools > adapter->max_rx_queues || | |
| 640 | − old_pool_size < adapter->min_rx_add_entries_per_subcrq || | |
| 641 | − old_pool_size > adapter->max_rx_add_entries_per_subcrq) | |
| 631 | + if (old_buff_size != new_buff_size || | |
| 632 | + old_num_pools != new_num_pools || | |
| 633 | + old_pool_size != new_pool_size) | |
| 642 | 634 | return false; |
| 643 | 635 | |
| 644 | 636 | return true; |
| @@ -874,17 +866,9 @@ static bool reuse_tx_pools(struct ibmvnic_adapter *adapter) · 229 unmodified lines | ||
| 874 | 866 | old_mtu = adapter->prev_mtu; |
| 875 | 867 | new_mtu = adapter->req_mtu; |
| 876 | 868 | |
| 877 | − /* Require MTU to be exactly same to reuse pools for now */ | |
| 878 | − if (old_mtu != new_mtu) | |
| 879 | − return false; | |
| 880 | − | |
| 881 | − if (old_num_pools == new_num_pools && old_pool_size == new_pool_size) | |
| 882 | − return true; | |
| 883 | − | |
| 884 | − if (old_num_pools < adapter->min_tx_queues || | |
| 885 | − old_num_pools > adapter->max_tx_queues || | |
| 886 | − old_pool_size < adapter->min_tx_entries_per_subcrq || | |
| 887 | − old_pool_size > adapter->max_tx_entries_per_subcrq) | |
| 869 | + if (old_mtu != new_mtu || | |
| 870 | + old_num_pools != new_num_pools || | |
| 871 | + old_pool_size != new_pool_size) | |
| 888 | 872 | return false; |
| 889 | 873 | |
| 890 | 874 | return true; |
| @@ -553,6 +553,14 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, · 552 unmodified lines | ||
| 553 | 553 | dev_info(&pf->pdev->dev, "vsi %d not found\n", vsi_seid); |
| 554 | 554 | return; |
| 555 | 555 | } |
| 556 | + if (vsi->type != I40E_VSI_MAIN && | |
| 557 | + vsi->type != I40E_VSI_FDIR && | |
| 558 | + vsi->type != I40E_VSI_VMDQ2) { | |
| 559 | + dev_info(&pf->pdev->dev, | |
| 560 | + "vsi %d type %d descriptor rings not available\n", | |
| 561 | + vsi_seid, vsi->type); | |
| 562 | + return; | |
| 563 | + } | |
| 556 | 564 | if (type == RING_TYPE_XDP && !i40e_enabled_xdp_vsi(vsi)) { |
| 557 | 565 | dev_info(&pf->pdev->dev, "XDP not enabled on VSI %d\n", vsi_seid); |
| 558 | 566 | return; |
| @@ -1948,6 +1948,32 @@ static int i40e_vc_send_resp_to_vf(struct i40e_vf *vf, · 1947 unmodified lines | ||
| 1948 | 1948 | return i40e_vc_send_msg_to_vf(vf, opcode, retval, NULL, 0); |
| 1949 | 1949 | } |
| 1950 | 1950 | |
| 1951 | +/** | |
| 1952 | + * i40e_sync_vf_state | |
| 1953 | + * @vf: pointer to the VF info | |
| 1954 | + * @state: VF state | |
| 1955 | + * | |
| 1956 | + * Called from a VF message to synchronize the service with a potential | |
| 1957 | + * VF reset state | |
| 1958 | + **/ | |
| 1959 | +static bool i40e_sync_vf_state(struct i40e_vf *vf, enum i40e_vf_states state) | |
| 1960 | +{ | |
| 1961 | + int i; | |
| 1962 | + | |
| 1963 | + /* When handling some messages, it needs VF state to be set. | |
| 1964 | + * It is possible that this flag is cleared during VF reset, | |
| 1965 | + * so there is a need to wait until the end of the reset to | |
| 1966 | + * handle the request message correctly. | |
| 1967 | + */ | |
| 1968 | + for (i = 0; i < I40E_VF_STATE_WAIT_COUNT; i++) { | |
| 1969 | + if (test_bit(state, &vf->vf_states)) | |
| 1970 | + return true; | |
| 1971 | + usleep_range(10000, 20000); | |
| 1972 | + } | |
| 1973 | + | |
| 1974 | + return test_bit(state, &vf->vf_states); | |
| 1975 | +} | |
| 1976 | + | |
| 1951 | 1977 | /** |
| 1952 | 1978 | * i40e_vc_get_version_msg |
| 1953 | 1979 | * @vf: pointer to the VF info |
| @@ -2008,7 +2034,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) · 54 unmodified lines | ||
| 2008 | 2034 | size_t len = 0; |
| 2009 | 2035 | int ret; |
| 2010 | 2036 | |
| 2011 | − if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) { | |
| 2037 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { | |
| 2012 | 2038 | aq_ret = I40E_ERR_PARAM; |
| 2013 | 2039 | goto err; |
| 2014 | 2040 | } |
| @@ -2131,7 +2157,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, u8 *msg) · 116 unmodified lines | ||
| 2131 | 2157 | bool allmulti = false; |
| 2132 | 2158 | bool alluni = false; |
| 2133 | 2159 | |
| 2134 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 2160 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 2135 | 2161 | aq_ret = I40E_ERR_PARAM; |
| 2136 | 2162 | goto err_out; |
| 2137 | 2163 | } |
| @@ -2219,7 +2245,7 @@ static int i40e_vc_config_queues_msg(struct i40e_vf *vf, u8 *msg) · 81 unmodified lines | ||
| 2219 | 2245 | struct i40e_vsi *vsi; |
| 2220 | 2246 | u16 num_qps_all = 0; |
| 2221 | 2247 | |
| 2222 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 2248 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 2223 | 2249 | aq_ret = I40E_ERR_PARAM; |
| 2224 | 2250 | goto error_param; |
| 2225 | 2251 | } |
| @@ -2368,7 +2394,7 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg) · 142 unmodified lines | ||
| 2368 | 2394 | i40e_status aq_ret = 0; |
| 2369 | 2395 | int i; |
| 2370 | 2396 | |
| 2371 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 2397 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 2372 | 2398 | aq_ret = I40E_ERR_PARAM; |
| 2373 | 2399 | goto error_param; |
| 2374 | 2400 | } |
| @@ -2540,7 +2566,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg) · 165 unmodified lines | ||
| 2540 | 2566 | struct i40e_pf *pf = vf->pf; |
| 2541 | 2567 | i40e_status aq_ret = 0; |
| 2542 | 2568 | |
| 2543 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 2569 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 2544 | 2570 | aq_ret = I40E_ERR_PARAM; |
| 2545 | 2571 | goto error_param; |
| 2546 | 2572 | } |
| @@ -2590,7 +2616,7 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg) · 43 unmodified lines | ||
| 2590 | 2616 | u8 cur_pairs = vf->num_queue_pairs; |
| 2591 | 2617 | struct i40e_pf *pf = vf->pf; |
| 2592 | 2618 | |
| 2593 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) | |
| 2619 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) | |
| 2594 | 2620 | return -EINVAL; |
| 2595 | 2621 | |
| 2596 | 2622 | if (req_pairs > I40E_MAX_VF_QUEUES) { |
| @@ -2635,7 +2661,7 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg) · 38 unmodified lines | ||
| 2635 | 2661 | |
| 2636 | 2662 | memset(&stats, 0, sizeof(struct i40e_eth_stats)); |
| 2637 | 2663 | |
| 2638 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 2664 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 2639 | 2665 | aq_ret = I40E_ERR_PARAM; |
| 2640 | 2666 | goto error_param; |
| 2641 | 2667 | } |
| @@ -2752,7 +2778,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg) · 110 unmodified lines | ||
| 2752 | 2778 | i40e_status ret = 0; |
| 2753 | 2779 | int i; |
| 2754 | 2780 | |
| 2755 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || | |
| 2781 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || | |
| 2756 | 2782 | !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { |
| 2757 | 2783 | ret = I40E_ERR_PARAM; |
| 2758 | 2784 | goto error_param; |
| @@ -2824,7 +2850,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg) · 65 unmodified lines | ||
| 2824 | 2850 | i40e_status ret = 0; |
| 2825 | 2851 | int i; |
| 2826 | 2852 | |
| 2827 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || | |
| 2853 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || | |
| 2828 | 2854 | !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) { |
| 2829 | 2855 | ret = I40E_ERR_PARAM; |
| 2830 | 2856 | goto error_param; |
| @@ -2968,7 +2994,7 @@ static int i40e_vc_remove_vlan_msg(struct i40e_vf *vf, u8 *msg) · 137 unmodified lines | ||
| 2968 | 2994 | i40e_status aq_ret = 0; |
| 2969 | 2995 | int i; |
| 2970 | 2996 | |
| 2971 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || | |
| 2997 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || | |
| 2972 | 2998 | !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) { |
| 2973 | 2999 | aq_ret = I40E_ERR_PARAM; |
| 2974 | 3000 | goto error_param; |
| @@ -3088,9 +3114,9 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg) · 113 unmodified lines | ||
| 3088 | 3114 | struct i40e_vsi *vsi = NULL; |
| 3089 | 3115 | i40e_status aq_ret = 0; |
| 3090 | 3116 | |
| 3091 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || | |
| 3117 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || | |
| 3092 | 3118 | !i40e_vc_isvalid_vsi_id(vf, vrk->vsi_id) || |
| 3093 | − (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) { | |
| 3119 | + vrk->key_len != I40E_HKEY_ARRAY_SIZE) { | |
| 3094 | 3120 | aq_ret = I40E_ERR_PARAM; |
| 3095 | 3121 | goto err; |
| 3096 | 3122 | } |
| @@ -3119,9 +3145,9 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg) · 22 unmodified lines | ||
| 3119 | 3145 | i40e_status aq_ret = 0; |
| 3120 | 3146 | u16 i; |
| 3121 | 3147 | |
| 3122 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) || | |
| 3148 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) || | |
| 3123 | 3149 | !i40e_vc_isvalid_vsi_id(vf, vrl->vsi_id) || |
| 3124 | − (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) { | |
| 3150 | + vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) { | |
| 3125 | 3151 | aq_ret = I40E_ERR_PARAM; |
| 3126 | 3152 | goto err; |
| 3127 | 3153 | } |
| @@ -3154,7 +3180,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg) · 26 unmodified lines | ||
| 3154 | 3180 | i40e_status aq_ret = 0; |
| 3155 | 3181 | int len = 0; |
| 3156 | 3182 | |
| 3157 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3183 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3158 | 3184 | aq_ret = I40E_ERR_PARAM; |
| 3159 | 3185 | goto err; |
| 3160 | 3186 | } |
| @@ -3190,7 +3216,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg) · 29 unmodified lines | ||
| 3190 | 3216 | struct i40e_hw *hw = &pf->hw; |
| 3191 | 3217 | i40e_status aq_ret = 0; |
| 3192 | 3218 | |
| 3193 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3219 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3194 | 3220 | aq_ret = I40E_ERR_PARAM; |
| 3195 | 3221 | goto err; |
| 3196 | 3222 | } |
| @@ -3215,7 +3241,7 @@ static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg) · 18 unmodified lines | ||
| 3215 | 3241 | i40e_status aq_ret = 0; |
| 3216 | 3242 | struct i40e_vsi *vsi; |
| 3217 | 3243 | |
| 3218 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3244 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3219 | 3245 | aq_ret = I40E_ERR_PARAM; |
| 3220 | 3246 | goto err; |
| 3221 | 3247 | } |
| @@ -3241,7 +3267,7 @@ static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg) · 19 unmodified lines | ||
| 3241 | 3267 | i40e_status aq_ret = 0; |
| 3242 | 3268 | struct i40e_vsi *vsi; |
| 3243 | 3269 | |
| 3244 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3270 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3245 | 3271 | aq_ret = I40E_ERR_PARAM; |
| 3246 | 3272 | goto err; |
| 3247 | 3273 | } |
| @@ -3468,7 +3494,7 @@ static int i40e_vc_del_cloud_filter(struct i40e_vf *vf, u8 *msg) · 220 unmodified lines | ||
| 3468 | 3494 | i40e_status aq_ret = 0; |
| 3469 | 3495 | int i, ret; |
| 3470 | 3496 | |
| 3471 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3497 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3472 | 3498 | aq_ret = I40E_ERR_PARAM; |
| 3473 | 3499 | goto err; |
| 3474 | 3500 | } |
| @@ -3599,7 +3625,7 @@ static int i40e_vc_add_cloud_filter(struct i40e_vf *vf, u8 *msg) · 124 unmodified lines | ||
| 3599 | 3625 | i40e_status aq_ret = 0; |
| 3600 | 3626 | int i, ret; |
| 3601 | 3627 | |
| 3602 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3628 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3603 | 3629 | aq_ret = I40E_ERR_PARAM; |
| 3604 | 3630 | goto err_out; |
| 3605 | 3631 | } |
| @@ -3708,7 +3734,7 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) · 102 unmodified lines | ||
| 3708 | 3734 | i40e_status aq_ret = 0; |
| 3709 | 3735 | u64 speed = 0; |
| 3710 | 3736 | |
| 3711 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3737 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3712 | 3738 | aq_ret = I40E_ERR_PARAM; |
| 3713 | 3739 | goto err; |
| 3714 | 3740 | } |
| @@ -3797,11 +3823,6 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg) · 82 unmodified lines | ||
| 3797 | 3823 | |
| 3798 | 3824 | /* set this flag only after making sure all inputs are sane */ |
| 3799 | 3825 | vf->adq_enabled = true; |
| 3800 | − /* num_req_queues is set when user changes number of queues via ethtool | |
| 3801 | − * and this causes issue for default VSI(which depends on this variable) | |
| 3802 | − * when ADq is enabled, hence reset it. | |
| 3803 | − */ | |
| 3804 | − vf->num_req_queues = 0; | |
| 3805 | 3826 | |
| 3806 | 3827 | /* reset the VF in order to allocate resources */ |
| 3807 | 3828 | i40e_vc_reset_vf(vf, true); |
| @@ -3824,7 +3845,7 @@ static int i40e_vc_del_qch_msg(struct i40e_vf *vf, u8 *msg) · 16 unmodified lines | ||
| 3824 | 3845 | struct i40e_pf *pf = vf->pf; |
| 3825 | 3846 | i40e_status aq_ret = 0; |
| 3826 | 3847 | |
| 3827 | − if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) { | |
| 3848 | + if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) { | |
| 3828 | 3849 | aq_ret = I40E_ERR_PARAM; |
| 3829 | 3850 | goto err; |
| 3830 | 3851 | } |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #define I40E_MAX_VF_PROMISC_FLAGS 3 |
| 20 | 20 | |
| 21 | +#define I40E_VF_STATE_WAIT_COUNT 20 | |
| 22 | + | |
| 21 | 23 | /* Various queue ctrls */ |
| 22 | 24 | enum i40e_queue_ctrl { |
| 23 | 25 | I40E_QUEUE_CTRL_UNKNOWN = 0, |
| @@ -615,23 +615,44 @@ static int iavf_set_ringparam(struct net_device *netdev, · 614 unmodified lines | ||
| 615 | 615 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
| 616 | 616 | return -EINVAL; |
| 617 | 617 | |
| 618 | − new_tx_count = clamp_t(u32, ring->tx_pending, | |
| 619 | − IAVF_MIN_TXD, | |
| 620 | − IAVF_MAX_TXD); | |
| 621 | − new_tx_count = ALIGN(new_tx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); | |
| 618 | + if (ring->tx_pending > IAVF_MAX_TXD || | |
| 619 | + ring->tx_pending < IAVF_MIN_TXD || | |
| 620 | + ring->rx_pending > IAVF_MAX_RXD || | |
| 621 | + ring->rx_pending < IAVF_MIN_RXD) { | |
| 622 | + netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n", | |
| 623 | + ring->tx_pending, ring->rx_pending, IAVF_MIN_TXD, | |
| 624 | + IAVF_MAX_RXD, IAVF_REQ_DESCRIPTOR_MULTIPLE); | |
| 625 | + return -EINVAL; | |
| 626 | + } | |
| 622 | 627 | |
| 623 | − new_rx_count = clamp_t(u32, ring->rx_pending, | |
| 624 | − IAVF_MIN_RXD, | |
| 625 | − IAVF_MAX_RXD); | |
| 626 | − new_rx_count = ALIGN(new_rx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE); | |
| 628 | + new_tx_count = ALIGN(ring->tx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); | |
| 629 | + if (new_tx_count != ring->tx_pending) | |
| 630 | + netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n", | |
| 631 | + new_tx_count); | |
| 632 | + | |
| 633 | + new_rx_count = ALIGN(ring->rx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE); | |
| 634 | + if (new_rx_count != ring->rx_pending) | |
| 635 | + netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n", | |
| 636 | + new_rx_count); | |
| 627 | 637 | |
| 628 | 638 | /* if nothing to do return success */ |
| 629 | 639 | if ((new_tx_count == adapter->tx_desc_count) && |
| 630 | − (new_rx_count == adapter->rx_desc_count)) | |
| 640 | + (new_rx_count == adapter->rx_desc_count)) { | |
| 641 | + netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n"); | |
| 631 | 642 | return 0; |
| 643 | + } | |
| 632 | 644 | |
| 633 | − adapter->tx_desc_count = new_tx_count; | |
| 634 | − adapter->rx_desc_count = new_rx_count; | |
| 645 | + if (new_tx_count != adapter->tx_desc_count) { | |
| 646 | + netdev_dbg(netdev, "Changing Tx descriptor count from %d to %d\n", | |
| 647 | + adapter->tx_desc_count, new_tx_count); | |
| 648 | + adapter->tx_desc_count = new_tx_count; | |
| 649 | + } | |
| 650 | + | |
| 651 | + if (new_rx_count != adapter->rx_desc_count) { | |
| 652 | + netdev_dbg(netdev, "Changing Rx descriptor count from %d to %d\n", | |
| 653 | + adapter->rx_desc_count, new_rx_count); | |
| 654 | + adapter->rx_desc_count = new_rx_count; | |
| 655 | + } | |
| 635 | 656 | |
| 636 | 657 | if (netif_running(netdev)) { |
| 637 | 658 | adapter->flags |= IAVF_FLAG_RESET_NEEDED; |
| @@ -2248,6 +2248,7 @@ static void iavf_reset_task(struct work_struct *work) · 2247 unmodified lines | ||
| 2248 | 2248 | } |
| 2249 | 2249 | |
| 2250 | 2250 | pci_set_master(adapter->pdev); |
| 2251 | + pci_restore_msi_state(adapter->pdev); | |
| 2251 | 2252 | |
| 2252 | 2253 | if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) { |
| 2253 | 2254 | dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n", |
| @@ -97,6 +97,9 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets) · 96 unmodified lines | ||
| 97 | 97 | |
| 98 | 98 | new_cfg->etscfg.maxtcs = pf->hw.func_caps.common_cap.maxtc; |
| 99 | 99 | |
| 100 | + if (!bwcfg) | |
| 101 | + new_cfg->etscfg.tcbwtable[0] = 100; | |
| 102 | + | |
| 100 | 103 | if (!bwrec) |
| 101 | 104 | new_cfg->etsrec.tcbwtable[0] = 100; |
| 102 | 105 | |
| @@ -167,15 +170,18 @@ static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode) · 64 unmodified lines | ||
| 167 | 170 | if (mode == pf->dcbx_cap) |
| 168 | 171 | return ICE_DCB_NO_HW_CHG; |
| 169 | 172 | |
| 170 | − pf->dcbx_cap = mode; | |
| 171 | 173 | qos_cfg = &pf->hw.port_info->qos_cfg; |
| 172 | − if (mode & DCB_CAP_DCBX_VER_CEE) { | |
| 173 | − if (qos_cfg->local_dcbx_cfg.pfc_mode == ICE_QOS_MODE_DSCP) | |
| 174 | − return ICE_DCB_NO_HW_CHG; | |
| 174 | + | |
| 175 | + /* DSCP configuration is not DCBx negotiated */ | |
| 176 | + if (qos_cfg->local_dcbx_cfg.pfc_mode == ICE_QOS_MODE_DSCP) | |
| 177 | + return ICE_DCB_NO_HW_CHG; | |
| 178 | + | |
| 179 | + pf->dcbx_cap = mode; | |
| 180 | + | |
| 181 | + if (mode & DCB_CAP_DCBX_VER_CEE) | |
| 175 | 182 | qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE; |
| 176 | − } else { | |
| 183 | + else | |
| 177 | 184 | qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE; |
| 178 | − } | |
| 179 | 185 | |
| 180 | 186 | dev_info(ice_pf_to_dev(pf), "DCBx mode = 0x%x\n", mode); |
| 181 | 187 | return ICE_DCB_HW_CHG_RST; |
| @@ -1268,7 +1268,7 @@ ice_fdir_write_all_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input, · 1267 unmodified lines | ||
| 1268 | 1268 | bool is_tun = tun == ICE_FD_HW_SEG_TUN; |
| 1269 | 1269 | int err; |
| 1270 | 1270 | |
| 1271 | − if (is_tun && !ice_get_open_tunnel_port(&pf->hw, &port_num)) | |
| 1271 | + if (is_tun && !ice_get_open_tunnel_port(&pf->hw, &port_num, TNL_ALL)) | |
| 1272 | 1272 | continue; |
| 1273 | 1273 | err = ice_fdir_write_fltr(pf, input, add, is_tun); |
| 1274 | 1274 | if (err) |
| @@ -1652,7 +1652,7 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd) · 377 unmodified lines | ||
| 1652 | 1652 | } |
| 1653 | 1653 | |
| 1654 | 1654 | /* return error if not an update and no available filters */ |
| 1655 | − fltrs_needed = ice_get_open_tunnel_port(hw, &tunnel_port) ? 2 : 1; | |
| 1655 | + fltrs_needed = ice_get_open_tunnel_port(hw, &tunnel_port, TNL_ALL) ? 2 : 1; | |
| 1656 | 1656 | if (!ice_fdir_find_fltr_by_idx(hw, fsp->location) && |
| 1657 | 1657 | ice_fdir_num_avail_fltr(hw, pf->vsi[vsi->idx]) < fltrs_needed) { |
| 1658 | 1658 | dev_err(dev, "Failed to add filter. The maximum number of flow director filters has been reached.\n"); |
| @@ -924,7 +924,7 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input, · 923 unmodified lines | ||
| 924 | 924 | memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len); |
| 925 | 925 | loc = pkt; |
| 926 | 926 | } else { |
| 927 | − if (!ice_get_open_tunnel_port(hw, &tnl_port)) | |
| 927 | + if (!ice_get_open_tunnel_port(hw, &tnl_port, TNL_ALL)) | |
| 928 | 928 | return ICE_ERR_DOES_NOT_EXIST; |
| 929 | 929 | if (!ice_fdir_pkt[idx].tun_pkt) |
| 930 | 930 | return ICE_ERR_PARAM; |
| @@ -1899,9 +1899,11 @@ static struct ice_buf *ice_pkg_buf(struct ice_buf_build *bld) · 1898 unmodified lines | ||
| 1899 | 1899 | * ice_get_open_tunnel_port - retrieve an open tunnel port |
| 1900 | 1900 | * @hw: pointer to the HW structure |
| 1901 | 1901 | * @port: returns open port |
| 1902 | + * @type: type of tunnel, can be TNL_LAST if it doesn't matter | |
| 1902 | 1903 | */ |
| 1903 | 1904 | bool |
| 1904 | −ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port) | |
| 1905 | +ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port, | |
| 1906 | + enum ice_tunnel_type type) | |
| 1905 | 1907 | { |
| 1906 | 1908 | bool res = false; |
| 1907 | 1909 | u16 i; |
| @@ -1909,7 +1911,8 @@ ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port) · 1 unmodified line | ||
| 1909 | 1911 | mutex_lock(&hw->tnl_lock); |
| 1910 | 1912 | |
| 1911 | 1913 | for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++) |
| 1912 | − if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].port) { | |
| 1914 | + if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].port && | |
| 1915 | + (type == TNL_LAST || type == hw->tnl.tbl[i].type)) { | |
| 1913 | 1916 | *port = hw->tnl.tbl[i].port; |
| 1914 | 1917 | res = true; |
| 1915 | 1918 | break; |
| @@ -33,7 +33,8 @@ enum ice_status · 32 unmodified lines | ||
| 33 | 33 | ice_get_sw_fv_list(struct ice_hw *hw, u8 *prot_ids, u16 ids_cnt, |
| 34 | 34 | unsigned long *bm, struct list_head *fv_list); |
| 35 | 35 | bool |
| 36 | −ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port); | |
| 36 | +ice_get_open_tunnel_port(struct ice_hw *hw, u16 *port, | |
| 37 | + enum ice_tunnel_type type); | |
| 37 | 38 | int ice_udp_tunnel_set_port(struct net_device *netdev, unsigned int table, |
| 38 | 39 | unsigned int idx, struct udp_tunnel_info *ti); |
| 39 | 40 | int ice_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table, |
| @@ -5881,6 +5881,9 @@ static int ice_up_complete(struct ice_vsi *vsi) · 5880 unmodified lines | ||
| 5881 | 5881 | netif_carrier_on(vsi->netdev); |
| 5882 | 5882 | } |
| 5883 | 5883 | |
| 5884 | + /* clear this now, and the first stats read will be used as baseline */ | |
| 5885 | + vsi->stat_offsets_loaded = false; | |
| 5886 | + | |
| 5884 | 5887 | ice_service_task_schedule(pf); |
| 5885 | 5888 | |
| 5886 | 5889 | return 0; |
| @@ -5927,14 +5930,15 @@ ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp, struct ice_q_stats st · 40 unmodified lines | ||
| 5927 | 5930 | /** |
| 5928 | 5931 | * ice_update_vsi_tx_ring_stats - Update VSI Tx ring stats counters |
| 5929 | 5932 | * @vsi: the VSI to be updated |
| 5933 | + * @vsi_stats: the stats struct to be updated | |
| 5930 | 5934 | * @rings: rings to work on |
| 5931 | 5935 | * @count: number of rings |
| 5932 | 5936 | */ |
| 5933 | 5937 | static void |
| 5934 | −ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, struct ice_tx_ring **rings, | |
| 5935 | − u16 count) | |
| 5938 | +ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, | |
| 5939 | + struct rtnl_link_stats64 *vsi_stats, | |
| 5940 | + struct ice_tx_ring **rings, u16 count) | |
| 5936 | 5941 | { |
| 5937 | − struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats; | |
| 5938 | 5942 | u16 i; |
| 5939 | 5943 | |
| 5940 | 5944 | for (i = 0; i < count; i++) { |
| @@ -5958,15 +5962,13 @@ ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, struct ice_tx_ring **rings, · 17 unmodified lines | ||
| 5958 | 5962 | */ |
| 5959 | 5963 | static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) |
| 5960 | 5964 | { |
| 5961 | − struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats; | |
| 5965 | + struct rtnl_link_stats64 *vsi_stats; | |
| 5962 | 5966 | u64 pkts, bytes; |
| 5963 | 5967 | int i; |
| 5964 | 5968 | |
| 5965 | − /* reset netdev stats */ | |
| 5966 | − vsi_stats->tx_packets = 0; | |
| 5967 | − vsi_stats->tx_bytes = 0; | |
| 5968 | − vsi_stats->rx_packets = 0; | |
| 5969 | − vsi_stats->rx_bytes = 0; | |
| 5969 | + vsi_stats = kzalloc(sizeof(*vsi_stats), GFP_ATOMIC); | |
| 5970 | + if (!vsi_stats) | |
| 5971 | + return; | |
| 5970 | 5972 | |
| 5971 | 5973 | /* reset non-netdev (extended) stats */ |
| 5972 | 5974 | vsi->tx_restart = 0; |
| @@ -5978,7 +5980,8 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) · 5 unmodified lines | ||
| 5978 | 5980 | rcu_read_lock(); |
| 5979 | 5981 | |
| 5980 | 5982 | /* update Tx rings counters */ |
| 5981 | − ice_update_vsi_tx_ring_stats(vsi, vsi->tx_rings, vsi->num_txq); | |
| 5983 | + ice_update_vsi_tx_ring_stats(vsi, vsi_stats, vsi->tx_rings, | |
| 5984 | + vsi->num_txq); | |
| 5982 | 5985 | |
| 5983 | 5986 | /* update Rx rings counters */ |
| 5984 | 5987 | ice_for_each_rxq(vsi, i) { |
| @@ -5993,10 +5996,17 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi) · 8 unmodified lines | ||
| 5993 | 5996 | |
| 5994 | 5997 | /* update XDP Tx rings counters */ |
| 5995 | 5998 | if (ice_is_xdp_ena_vsi(vsi)) |
| 5996 | − ice_update_vsi_tx_ring_stats(vsi, vsi->xdp_rings, | |
| 5999 | + ice_update_vsi_tx_ring_stats(vsi, vsi_stats, vsi->xdp_rings, | |
| 5997 | 6000 | vsi->num_xdp_txq); |
| 5998 | 6001 | |
| 5999 | 6002 | rcu_read_unlock(); |
| 6003 | + | |
| 6004 | + vsi->net_stats.tx_packets = vsi_stats->tx_packets; | |
| 6005 | + vsi->net_stats.tx_bytes = vsi_stats->tx_bytes; | |
| 6006 | + vsi->net_stats.rx_packets = vsi_stats->rx_packets; | |
| 6007 | + vsi->net_stats.rx_bytes = vsi_stats->rx_bytes; | |
| 6008 | + | |
| 6009 | + kfree(vsi_stats); | |
| 6000 | 6010 | } |
| 6001 | 6011 | |
| 6002 | 6012 | /** |
| @@ -3796,10 +3796,13 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { · 3795 unmodified lines | ||
| 3796 | 3796 | * ice_find_recp - find a recipe |
| 3797 | 3797 | * @hw: pointer to the hardware structure |
| 3798 | 3798 | * @lkup_exts: extension sequence to match |
| 3799 | + * @tun_type: type of recipe tunnel | |
| 3799 | 3800 | * |
| 3800 | 3801 | * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found. |
| 3801 | 3802 | */ |
| 3802 | −static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts) | |
| 3803 | +static u16 | |
| 3804 | +ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts, | |
| 3805 | + enum ice_sw_tunnel_type tun_type) | |
| 3803 | 3806 | { |
| 3804 | 3807 | bool refresh_required = true; |
| 3805 | 3808 | struct ice_sw_recipe *recp; |
| @@ -3860,8 +3863,9 @@ static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts) · 54 unmodified lines | ||
| 3860 | 3863 | } |
| 3861 | 3864 | /* If for "i"th recipe the found was never set to false |
| 3862 | 3865 | * then it means we found our match |
| 3866 | + * Also tun type of recipe needs to be checked | |
| 3863 | 3867 | */ |
| 3864 | − if (found) | |
| 3868 | + if (found && recp[i].tun_type == tun_type) | |
| 3865 | 3869 | return i; /* Return the recipe ID */ |
| 3866 | 3870 | } |
| 3867 | 3871 | } |
| @@ -4651,11 +4655,12 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, · 783 unmodified lines | ||
| 4651 | 4655 | } |
| 4652 | 4656 | |
| 4653 | 4657 | /* Look for a recipe which matches our requested fv / mask list */ |
| 4654 | − *rid = ice_find_recp(hw, lkup_exts); | |
| 4658 | + *rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type); | |
| 4655 | 4659 | if (*rid < ICE_MAX_NUM_RECIPES) |
| 4656 | 4660 | /* Success if found a recipe that match the existing criteria */ |
| 4657 | 4661 | goto err_unroll; |
| 4658 | 4662 | |
| 4663 | + rm->tun_type = rinfo->tun_type; | |
| 4659 | 4664 | /* Recipe we need does not exist, add a recipe */ |
| 4660 | 4665 | status = ice_add_sw_recipe(hw, rm, profiles); |
| 4661 | 4666 | if (status) |
| @@ -4958,11 +4963,13 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type, · 296 unmodified lines | ||
| 4958 | 4963 | |
| 4959 | 4964 | switch (tun_type) { |
| 4960 | 4965 | case ICE_SW_TUN_VXLAN: |
| 4966 | + if (!ice_get_open_tunnel_port(hw, &open_port, TNL_VXLAN)) | |
| 4967 | + return ICE_ERR_CFG; | |
| 4968 | + break; | |
| 4961 | 4969 | case ICE_SW_TUN_GENEVE: |
| 4962 | − if (!ice_get_open_tunnel_port(hw, &open_port)) | |
| 4970 | + if (!ice_get_open_tunnel_port(hw, &open_port, TNL_GENEVE)) | |
| 4963 | 4971 | return ICE_ERR_CFG; |
| 4964 | 4972 | break; |
| 4965 | − | |
| 4966 | 4973 | default: |
| 4967 | 4974 | /* Nothing needs to be done for this tunnel type */ |
| 4968 | 4975 | return 0; |
| @@ -5555,7 +5562,7 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, · 586 unmodified lines | ||
| 5555 | 5562 | if (status) |
| 5556 | 5563 | return status; |
| 5557 | 5564 | |
| 5558 | − rid = ice_find_recp(hw, &lkup_exts); | |
| 5565 | + rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type); | |
| 5559 | 5566 | /* If did not find a recipe that match the existing criteria */ |
| 5560 | 5567 | if (rid == ICE_MAX_NUM_RECIPES) |
| 5561 | 5568 | return ICE_ERR_PARAM; |
| @@ -74,21 +74,13 @@ static enum ice_protocol_type ice_proto_type_from_ipv6(bool inner) · 73 unmodified lines | ||
| 74 | 74 | return inner ? ICE_IPV6_IL : ICE_IPV6_OFOS; |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | −static enum ice_protocol_type | |
| 78 | −ice_proto_type_from_l4_port(bool inner, u16 ip_proto) | |
| 77 | +static enum ice_protocol_type ice_proto_type_from_l4_port(u16 ip_proto) | |
| 79 | 78 | { |
| 80 | − if (inner) { | |
| 81 | − switch (ip_proto) { | |
| 82 | − case IPPROTO_UDP: | |
| 83 | − return ICE_UDP_ILOS; | |
| 84 | − } | |
| 85 | − } else { | |
| 86 | − switch (ip_proto) { | |
| 87 | − case IPPROTO_TCP: | |
| 88 | − return ICE_TCP_IL; | |
| 89 | − case IPPROTO_UDP: | |
| 90 | − return ICE_UDP_OF; | |
| 91 | − } | |
| 79 | + switch (ip_proto) { | |
| 80 | + case IPPROTO_TCP: | |
| 81 | + return ICE_TCP_IL; | |
| 82 | + case IPPROTO_UDP: | |
| 83 | + return ICE_UDP_ILOS; | |
| 92 | 84 | } |
| 93 | 85 | |
| 94 | 86 | return 0; |
| @@ -191,8 +183,9 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, · 96 unmodified lines | ||
| 191 | 183 | i++; |
| 192 | 184 | } |
| 193 | 185 | |
| 194 | − if (flags & ICE_TC_FLWR_FIELD_ENC_DEST_L4_PORT) { | |
| 195 | − list[i].type = ice_proto_type_from_l4_port(false, hdr->l3_key.ip_proto); | |
| 186 | + if ((flags & ICE_TC_FLWR_FIELD_ENC_DEST_L4_PORT) && | |
| 187 | + hdr->l3_key.ip_proto == IPPROTO_UDP) { | |
| 188 | + list[i].type = ICE_UDP_OF; | |
| 196 | 189 | list[i].h_u.l4_hdr.dst_port = hdr->l4_key.dst_port; |
| 197 | 190 | list[i].m_u.l4_hdr.dst_port = hdr->l4_mask.dst_port; |
| 198 | 191 | i++; |
| @@ -317,7 +310,7 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, · 118 unmodified lines | ||
| 317 | 310 | ICE_TC_FLWR_FIELD_SRC_L4_PORT)) { |
| 318 | 311 | struct ice_tc_l4_hdr *l4_key, *l4_mask; |
| 319 | 312 | |
| 320 | − list[i].type = ice_proto_type_from_l4_port(inner, headers->l3_key.ip_proto); | |
| 313 | + list[i].type = ice_proto_type_from_l4_port(headers->l3_key.ip_proto); | |
| 321 | 314 | l4_key = &headers->l4_key; |
| 322 | 315 | l4_mask = &headers->l4_mask; |
| 323 | 316 | |
| @@ -802,7 +795,8 @@ ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule, · 478 unmodified lines | ||
| 802 | 795 | headers->l3_mask.ttl = match.mask->ttl; |
| 803 | 796 | } |
| 804 | 797 | |
| 805 | − if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS)) { | |
| 798 | + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS) && | |
| 799 | + fltr->tunnel_type != TNL_VXLAN && fltr->tunnel_type != TNL_GENEVE) { | |
| 806 | 800 | struct flow_match_ports match; |
| 807 | 801 | |
| 808 | 802 | flow_rule_match_enc_ports(rule, &match); |
| @@ -1617,6 +1617,7 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr) · 1616 unmodified lines | ||
| 1617 | 1617 | ice_vc_set_default_allowlist(vf); |
| 1618 | 1618 | |
| 1619 | 1619 | ice_vf_fdir_exit(vf); |
| 1620 | + ice_vf_fdir_init(vf); | |
| 1620 | 1621 | /* clean VF control VSI when resetting VFs since it should be |
| 1621 | 1622 | * setup only when VF creates its first FDIR rule. |
| 1622 | 1623 | */ |
| @@ -1747,6 +1748,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) · 124 unmodified lines | ||
| 1747 | 1748 | } |
| 1748 | 1749 | |
| 1749 | 1750 | ice_vf_fdir_exit(vf); |
| 1751 | + ice_vf_fdir_init(vf); | |
| 1750 | 1752 | /* clean VF control VSI when resetting VF since it should be setup |
| 1751 | 1753 | * only when VF creates its first FDIR rule. |
| 1752 | 1754 | */ |
| @@ -2021,6 +2023,10 @@ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs) · 268 unmodified lines | ||
| 2021 | 2023 | if (ret) |
| 2022 | 2024 | goto err_unroll_sriov; |
| 2023 | 2025 | |
| 2026 | + /* rearm global interrupts */ | |
| 2027 | + if (test_and_clear_bit(ICE_OICR_INTR_DIS, pf->state)) | |
| 2028 | + ice_irq_dynamic_ena(hw, NULL, NULL); | |
| 2029 | + | |
| 2024 | 2030 | return 0; |
| 2025 | 2031 | |
| 2026 | 2032 | err_unroll_sriov: |
| @@ -383,6 +383,7 @@ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count) · 382 unmodified lines | ||
| 383 | 383 | while (i--) { |
| 384 | 384 | dma = xsk_buff_xdp_get_dma(*xdp); |
| 385 | 385 | rx_desc->read.pkt_addr = cpu_to_le64(dma); |
| 386 | + rx_desc->wb.status_error0 = 0; | |
| 386 | 387 | |
| 387 | 388 | rx_desc++; |
| 388 | 389 | xdp++; |
| @@ -2960,11 +2960,11 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, · 2959 unmodified lines | ||
| 2960 | 2960 | mvpp2_rxq_status_update(port, rxq->id, 0, rxq->size); |
| 2961 | 2961 | |
| 2962 | 2962 | if (priv->percpu_pools) { |
| 2963 | − err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->id, 0); | |
| 2963 | + err = xdp_rxq_info_reg(&rxq->xdp_rxq_short, port->dev, rxq->logic_rxq, 0); | |
| 2964 | 2964 | if (err < 0) |
| 2965 | 2965 | goto err_free_dma; |
| 2966 | 2966 | |
| 2967 | − err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->id, 0); | |
| 2967 | + err = xdp_rxq_info_reg(&rxq->xdp_rxq_long, port->dev, rxq->logic_rxq, 0); | |
| 2968 | 2968 | if (err < 0) |
| 2969 | 2969 | goto err_unregister_rxq_short; |
| 2970 | 2970 | |
| @@ -7458,7 +7458,7 @@ static int mvpp2_probe(struct platform_device *pdev) · 4487 unmodified lines | ||
| 7458 | 7458 | |
| 7459 | 7459 | shared = num_present_cpus() - priv->nthreads; |
| 7460 | 7460 | if (shared > 0) |
| 7461 | − bitmap_fill(&priv->lock_map, | |
| 7461 | + bitmap_set(&priv->lock_map, 0, | |
| 7462 | 7462 | min_t(int, shared, MVPP2_MAX_THREADS)); |
| 7463 | 7463 | |
| 7464 | 7464 | for (i = 0; i < MVPP2_MAX_THREADS; i++) { |
| @@ -2341,7 +2341,7 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw, · 2340 unmodified lines | ||
| 2341 | 2341 | goto free_regions; |
| 2342 | 2342 | break; |
| 2343 | 2343 | default: |
| 2344 | − return err; | |
| 2344 | + goto free_regions; | |
| 2345 | 2345 | } |
| 2346 | 2346 | |
| 2347 | 2347 | mw->mbox_wq = alloc_workqueue(name, |
| @@ -5,6 +5,8 @@ · 4 unmodified lines | ||
| 5 | 5 | * |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | +#include <linux/module.h> | |
| 9 | + | |
| 8 | 10 | #include "otx2_common.h" |
| 9 | 11 | #include "otx2_ptp.h" |
| 10 | 12 | |
| @@ -670,7 +670,7 @@ void __init mlx4_en_init_ptys2ethtool_map(void) · 669 unmodified lines | ||
| 670 | 670 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_T, SPEED_1000, |
| 671 | 671 | ETHTOOL_LINK_MODE_1000baseT_Full_BIT); |
| 672 | 672 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_CX_SGMII, SPEED_1000, |
| 673 | − ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); | |
| 673 | + ETHTOOL_LINK_MODE_1000baseX_Full_BIT); | |
| 674 | 674 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_KX, SPEED_1000, |
| 675 | 675 | ETHTOOL_LINK_MODE_1000baseKX_Full_BIT); |
| 676 | 676 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_T, SPEED_10000, |
| @@ -682,9 +682,9 @@ void __init mlx4_en_init_ptys2ethtool_map(void) · 5 unmodified lines | ||
| 682 | 682 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KR, SPEED_10000, |
| 683 | 683 | ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); |
| 684 | 684 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CR, SPEED_10000, |
| 685 | − ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); | |
| 685 | + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT); | |
| 686 | 686 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_SR, SPEED_10000, |
| 687 | − ETHTOOL_LINK_MODE_10000baseKR_Full_BIT); | |
| 687 | + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT); | |
| 688 | 688 | MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_20GBASE_KR2, SPEED_20000, |
| 689 | 689 | ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT, |
| 690 | 690 | ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT); |
| @@ -2286,9 +2286,14 @@ int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv, · 2285 unmodified lines | ||
| 2286 | 2286 | bool carry_xdp_prog) |
| 2287 | 2287 | { |
| 2288 | 2288 | struct bpf_prog *xdp_prog; |
| 2289 | − int i, t; | |
| 2289 | + int i, t, ret; | |
| 2290 | 2290 | |
| 2291 | − mlx4_en_copy_priv(tmp, priv, prof); | |
| 2291 | + ret = mlx4_en_copy_priv(tmp, priv, prof); | |
| 2292 | + if (ret) { | |
| 2293 | + en_warn(priv, "%s: mlx4_en_copy_priv() failed, return\n", | |
| 2294 | + __func__); | |
| 2295 | + return ret; | |
| 2296 | + } | |
| 2292 | 2297 | |
| 2293 | 2298 | if (mlx4_en_alloc_resources(tmp)) { |
| 2294 | 2299 | en_warn(priv, |
| @@ -341,6 +341,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, · 340 unmodified lines | ||
| 341 | 341 | case MLX5_CMD_OP_DEALLOC_SF: |
| 342 | 342 | case MLX5_CMD_OP_DESTROY_UCTX: |
| 343 | 343 | case MLX5_CMD_OP_DESTROY_UMEM: |
| 344 | + case MLX5_CMD_OP_MODIFY_RQT: | |
| 344 | 345 | return MLX5_CMD_STAT_OK; |
| 345 | 346 | |
| 346 | 347 | case MLX5_CMD_OP_QUERY_HCA_CAP: |
| @@ -446,7 +447,6 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op, · 99 unmodified lines | ||
| 446 | 447 | case MLX5_CMD_OP_MODIFY_TIS: |
| 447 | 448 | case MLX5_CMD_OP_QUERY_TIS: |
| 448 | 449 | case MLX5_CMD_OP_CREATE_RQT: |
| 449 | − case MLX5_CMD_OP_MODIFY_RQT: | |
| 450 | 450 | case MLX5_CMD_OP_QUERY_RQT: |
| 451 | 451 | |
| 452 | 452 | case MLX5_CMD_OP_CREATE_FLOW_TABLE: |
| @@ -13,6 +13,9 @@ struct mlx5e_rx_res { · 12 unmodified lines | ||
| 13 | 13 | unsigned int max_nch; |
| 14 | 14 | u32 drop_rqn; |
| 15 | 15 | |
| 16 | + struct mlx5e_packet_merge_param pkt_merge_param; | |
| 17 | + struct rw_semaphore pkt_merge_param_sem; | |
| 18 | + | |
| 16 | 19 | struct mlx5e_rss *rss[MLX5E_MAX_NUM_RSS]; |
| 17 | 20 | bool rss_active; |
| 18 | 21 | u32 rss_rqns[MLX5E_INDIR_RQT_SIZE]; |
| @@ -392,6 +395,7 @@ static int mlx5e_rx_res_ptp_init(struct mlx5e_rx_res *res) · 373 unmodified lines | ||
| 392 | 395 | if (err) |
| 393 | 396 | goto out; |
| 394 | 397 | |
| 398 | + /* Separated from the channels RQs, does not share pkt_merge state with them */ | |
| 395 | 399 | mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, |
| 396 | 400 | mlx5e_rqt_get_rqtn(&res->ptp.rqt), |
| 397 | 401 | inner_ft_support); |
| @@ -447,6 +451,9 @@ int mlx5e_rx_res_init(struct mlx5e_rx_res *res, struct mlx5_core_dev *mdev, · 49 unmodified lines | ||
| 447 | 451 | res->max_nch = max_nch; |
| 448 | 452 | res->drop_rqn = drop_rqn; |
| 449 | 453 | |
| 454 | + res->pkt_merge_param = *init_pkt_merge_param; | |
| 455 | + init_rwsem(&res->pkt_merge_param_sem); | |
| 456 | + | |
| 450 | 457 | err = mlx5e_rx_res_rss_init_def(res, init_pkt_merge_param, init_nch); |
| 451 | 458 | if (err) |
| 452 | 459 | goto err_out; |
| @@ -513,7 +520,7 @@ u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res) · 60 unmodified lines | ||
| 513 | 520 | return mlx5e_tir_get_tirn(&res->ptp.tir); |
| 514 | 521 | } |
| 515 | 522 | |
| 516 | −u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) | |
| 523 | +static u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix) | |
| 517 | 524 | { |
| 518 | 525 | return mlx5e_rqt_get_rqtn(&res->channels[ix].direct_rqt); |
| 519 | 526 | } |
| @@ -656,6 +663,9 @@ int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, · 136 unmodified lines | ||
| 656 | 663 | if (!builder) |
| 657 | 664 | return -ENOMEM; |
| 658 | 665 | |
| 666 | + down_write(&res->pkt_merge_param_sem); | |
| 667 | + res->pkt_merge_param = *pkt_merge_param; | |
| 668 | + | |
| 659 | 669 | mlx5e_tir_builder_build_packet_merge(builder, pkt_merge_param); |
| 660 | 670 | |
| 661 | 671 | final_err = 0; |
| @@ -681,6 +691,7 @@ int mlx5e_rx_res_packet_merge_set_param(struct mlx5e_rx_res *res, · 19 unmodified lines | ||
| 681 | 691 | } |
| 682 | 692 | } |
| 683 | 693 | |
| 694 | + up_write(&res->pkt_merge_param_sem); | |
| 684 | 695 | mlx5e_tir_builder_free(builder); |
| 685 | 696 | return final_err; |
| 686 | 697 | } |
| @@ -689,3 +700,31 @@ struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res * · 2 unmodified lines | ||
| 689 | 700 | { |
| 690 | 701 | return mlx5e_rss_get_hash(res->rss[0]); |
| 691 | 702 | } |
| 703 | + | |
| 704 | +int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, | |
| 705 | + struct mlx5e_tir *tir) | |
| 706 | +{ | |
| 707 | + bool inner_ft_support = res->features & MLX5E_RX_RES_FEATURE_INNER_FT; | |
| 708 | + struct mlx5e_tir_builder *builder; | |
| 709 | + u32 rqtn; | |
| 710 | + int err; | |
| 711 | + | |
| 712 | + builder = mlx5e_tir_builder_alloc(false); | |
| 713 | + if (!builder) | |
| 714 | + return -ENOMEM; | |
| 715 | + | |
| 716 | + rqtn = mlx5e_rx_res_get_rqtn_direct(res, rxq); | |
| 717 | + | |
| 718 | + mlx5e_tir_builder_build_rqt(builder, res->mdev->mlx5e_res.hw_objs.td.tdn, rqtn, | |
| 719 | + inner_ft_support); | |
| 720 | + mlx5e_tir_builder_build_direct(builder); | |
| 721 | + mlx5e_tir_builder_build_tls(builder); | |
| 722 | + down_read(&res->pkt_merge_param_sem); | |
| 723 | + mlx5e_tir_builder_build_packet_merge(builder, &res->pkt_merge_param); | |
| 724 | + err = mlx5e_tir_init(tir, builder, res->mdev, false); | |
| 725 | + up_read(&res->pkt_merge_param_sem); | |
| 726 | + | |
| 727 | + mlx5e_tir_builder_free(builder); | |
| 728 | + | |
| 729 | + return err; | |
| 730 | +} | |
| @@ -37,9 +37,6 @@ u32 mlx5e_rx_res_get_tirn_rss(struct mlx5e_rx_res *res, enum mlx5_traffic_types · 36 unmodified lines | ||
| 37 | 37 | u32 mlx5e_rx_res_get_tirn_rss_inner(struct mlx5e_rx_res *res, enum mlx5_traffic_types tt); |
| 38 | 38 | u32 mlx5e_rx_res_get_tirn_ptp(struct mlx5e_rx_res *res); |
| 39 | 39 | |
| 40 | −/* RQTN getters for modules that create their own TIRs */ | |
| 41 | −u32 mlx5e_rx_res_get_rqtn_direct(struct mlx5e_rx_res *res, unsigned int ix); | |
| 42 | − | |
| 43 | 40 | /* Activate/deactivate API */ |
| 44 | 41 | void mlx5e_rx_res_channels_activate(struct mlx5e_rx_res *res, struct mlx5e_channels *chs); |
| 45 | 42 | void mlx5e_rx_res_channels_deactivate(struct mlx5e_rx_res *res); |
| @@ -69,4 +66,7 @@ struct mlx5e_rss *mlx5e_rx_res_rss_get(struct mlx5e_rx_res *res, u32 rss_idx); · 23 unmodified lines | ||
| 69 | 66 | /* Workaround for hairpin */ |
| 70 | 67 | struct mlx5e_rss_params_hash mlx5e_rx_res_get_current_hash(struct mlx5e_rx_res *res); |
| 71 | 68 | |
| 69 | +/* Accel TIRs */ | |
| 70 | +int mlx5e_rx_res_tls_tir_create(struct mlx5e_rx_res *res, unsigned int rxq, | |
| 71 | + struct mlx5e_tir *tir); | |
| 72 | 72 | #endif /* __MLX5_EN_RX_RES_H__ */ |
| @@ -191,7 +191,7 @@ static void mlx5e_ipsec_set_swp(struct sk_buff *skb, · 190 unmodified lines | ||
| 191 | 191 | eseg->swp_inner_l3_offset = skb_inner_network_offset(skb) / 2; |
| 192 | 192 | eseg->swp_inner_l4_offset = |
| 193 | 193 | (skb->csum_start + skb->head - skb->data) / 2; |
| 194 | − if (skb->protocol == htons(ETH_P_IPV6)) | |
| 194 | + if (inner_ip_hdr(skb)->version == 6) | |
| 195 | 195 | eseg->swp_flags |= MLX5_ETH_WQE_SWP_INNER_L3_IPV6; |
| 196 | 196 | break; |
| 197 | 197 | default: |
| @@ -100,25 +100,6 @@ mlx5e_ktls_rx_resync_create_resp_list(void) · 99 unmodified lines | ||
| 100 | 100 | return resp_list; |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | −static int mlx5e_ktls_create_tir(struct mlx5_core_dev *mdev, struct mlx5e_tir *tir, u32 rqtn) | |
| 104 | −{ | |
| 105 | − struct mlx5e_tir_builder *builder; | |
| 106 | − int err; | |
| 107 | − | |
| 108 | − builder = mlx5e_tir_builder_alloc(false); | |
| 109 | − if (!builder) | |
| 110 | − return -ENOMEM; | |
| 111 | − | |
| 112 | − mlx5e_tir_builder_build_rqt(builder, mdev->mlx5e_res.hw_objs.td.tdn, rqtn, false); | |
| 113 | − mlx5e_tir_builder_build_direct(builder); | |
| 114 | − mlx5e_tir_builder_build_tls(builder); | |
| 115 | − err = mlx5e_tir_init(tir, builder, mdev, false); | |
| 116 | − | |
| 117 | − mlx5e_tir_builder_free(builder); | |
| 118 | − | |
| 119 | − return err; | |
| 120 | −} | |
| 121 | − | |
| 122 | 103 | static void accel_rule_handle_work(struct work_struct *work) |
| 123 | 104 | { |
| 124 | 105 | struct mlx5e_ktls_offload_context_rx *priv_rx; |
| @@ -609,7 +590,6 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, · 484 unmodified lines | ||
| 609 | 590 | struct mlx5_core_dev *mdev; |
| 610 | 591 | struct mlx5e_priv *priv; |
| 611 | 592 | int rxq, err; |
| 612 | − u32 rqtn; | |
| 613 | 593 | |
| 614 | 594 | tls_ctx = tls_get_ctx(sk); |
| 615 | 595 | priv = netdev_priv(netdev); |
| @@ -635,9 +615,7 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, · 19 unmodified lines | ||
| 635 | 615 | priv_rx->sw_stats = &priv->tls->sw_stats; |
| 636 | 616 | mlx5e_set_ktls_rx_priv_ctx(tls_ctx, priv_rx); |
| 637 | 617 | |
| 638 | − rqtn = mlx5e_rx_res_get_rqtn_direct(priv->rx_res, rxq); | |
| 639 | − | |
| 640 | − err = mlx5e_ktls_create_tir(mdev, &priv_rx->tir, rqtn); | |
| 618 | + err = mlx5e_rx_res_tls_tir_create(priv->rx_res, rxq, &priv_rx->tir); | |
| 641 | 619 | if (err) |
| 642 | 620 | goto err_create_tir; |
| 643 | 621 | |
| @@ -1080,6 +1080,10 @@ static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = { · 1079 unmodified lines | ||
| 1080 | 1080 | &MLX5E_STATS_GRP(pme), |
| 1081 | 1081 | &MLX5E_STATS_GRP(channels), |
| 1082 | 1082 | &MLX5E_STATS_GRP(per_port_buff_congest), |
| 1083 | +#ifdef CONFIG_MLX5_EN_IPSEC | |
| 1084 | + &MLX5E_STATS_GRP(ipsec_sw), | |
| 1085 | + &MLX5E_STATS_GRP(ipsec_hw), | |
| 1086 | +#endif | |
| 1083 | 1087 | }; |
| 1084 | 1088 | |
| 1085 | 1089 | static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv) |
| @@ -543,13 +543,13 @@ static int mlx5e_build_shampo_hd_umr(struct mlx5e_rq *rq, · 542 unmodified lines | ||
| 543 | 543 | u16 klm_entries, u16 index) |
| 544 | 544 | { |
| 545 | 545 | struct mlx5e_shampo_hd *shampo = rq->mpwqe.shampo; |
| 546 | − u16 entries, pi, i, header_offset, err, wqe_bbs, new_entries; | |
| 546 | + u16 entries, pi, header_offset, err, wqe_bbs, new_entries; | |
| 547 | 547 | u32 lkey = rq->mdev->mlx5e_res.hw_objs.mkey; |
| 548 | 548 | struct page *page = shampo->last_page; |
| 549 | 549 | u64 addr = shampo->last_addr; |
| 550 | 550 | struct mlx5e_dma_info *dma_info; |
| 551 | 551 | struct mlx5e_umr_wqe *umr_wqe; |
| 552 | − int headroom; | |
| 552 | + int headroom, i; | |
| 553 | 553 | |
| 554 | 554 | headroom = rq->buff.headroom; |
| 555 | 555 | new_entries = klm_entries - (shampo->pi & (MLX5_UMR_KLM_ALIGNMENT - 1)); |
| @@ -601,9 +601,7 @@ update_klm: · 45 unmodified lines | ||
| 601 | 601 | |
| 602 | 602 | err_unmap: |
| 603 | 603 | while (--i >= 0) { |
| 604 | − if (--index < 0) | |
| 605 | − index = shampo->hd_per_wq - 1; | |
| 606 | − dma_info = &shampo->info[index]; | |
| 604 | + dma_info = &shampo->info[--index]; | |
| 607 | 605 | if (!(i & (MLX5E_SHAMPO_WQ_HEADER_PER_PAGE - 1))) { |
| 608 | 606 | dma_info->addr = ALIGN_DOWN(dma_info->addr, PAGE_SIZE); |
| 609 | 607 | mlx5e_page_release(rq, dma_info, true); |
| @@ -130,7 +130,7 @@ static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw, · 129 unmodified lines | ||
| 130 | 130 | /* If vports min rate divider is 0 but their group has bw_share configured, then |
| 131 | 131 | * need to set bw_share for vports to minimal value. |
| 132 | 132 | */ |
| 133 | − if (!group_level && !max_guarantee && group->bw_share) | |
| 133 | + if (!group_level && !max_guarantee && group && group->bw_share) | |
| 134 | 134 | return 1; |
| 135 | 135 | return 0; |
| 136 | 136 | } |
| @@ -423,7 +423,7 @@ static int esw_qos_vport_update_group(struct mlx5_eswitch *esw, · 286 unmodified lines | ||
| 423 | 423 | return err; |
| 424 | 424 | |
| 425 | 425 | /* Recalculate bw share weights of old and new groups */ |
| 426 | − if (vport->qos.bw_share) { | |
| 426 | + if (vport->qos.bw_share || new_group->bw_share) { | |
| 427 | 427 | esw_qos_normalize_vports_min_rate(esw, curr_group, extack); |
| 428 | 428 | esw_qos_normalize_vports_min_rate(esw, new_group, extack); |
| 429 | 429 | } |
| @@ -329,14 +329,25 @@ static bool · 328 unmodified lines | ||
| 329 | 329 | esw_is_indir_table(struct mlx5_eswitch *esw, struct mlx5_flow_attr *attr) |
| 330 | 330 | { |
| 331 | 331 | struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr; |
| 332 | + bool result = false; | |
| 332 | 333 | int i; |
| 333 | 334 | |
| 334 | − for (i = esw_attr->split_count; i < esw_attr->out_count; i++) | |
| 335 | + /* Indirect table is supported only for flows with in_port uplink | |
| 336 | + * and the destination is vport on the same eswitch as the uplink, | |
| 337 | + * return false in case at least one of destinations doesn't meet | |
| 338 | + * this criteria. | |
| 339 | + */ | |
| 340 | + for (i = esw_attr->split_count; i < esw_attr->out_count; i++) { | |
| 335 | 341 | if (esw_attr->dests[i].rep && |
| 336 | 342 | mlx5_esw_indir_table_needed(esw, attr, esw_attr->dests[i].rep->vport, |
| 337 | − esw_attr->dests[i].mdev)) | |
| 338 | − return true; | |
| 339 | − return false; | |
| 343 | + esw_attr->dests[i].mdev)) { | |
| 344 | + result = true; | |
| 345 | + } else { | |
| 346 | + result = false; | |
| 347 | + break; | |
| 348 | + } | |
| 349 | + } | |
| 350 | + return result; | |
| 340 | 351 | } |
| 341 | 352 | |
| 342 | 353 | static int |
| @@ -2512,6 +2523,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, · 2169 unmodified lines | ||
| 2512 | 2523 | struct mlx5_eswitch *esw = master->priv.eswitch; |
| 2513 | 2524 | struct mlx5_flow_table_attr ft_attr = { |
| 2514 | 2525 | .max_fte = 1, .prio = 0, .level = 0, |
| 2526 | + .flags = MLX5_FLOW_TABLE_OTHER_VPORT, | |
| 2515 | 2527 | }; |
| 2516 | 2528 | struct mlx5_flow_namespace *egress_ns; |
| 2517 | 2529 | struct mlx5_flow_table *acl; |
| @@ -835,6 +835,9 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev) · 834 unmodified lines | ||
| 835 | 835 | |
| 836 | 836 | health->timer.expires = jiffies + msecs_to_jiffies(poll_interval_ms); |
| 837 | 837 | add_timer(&health->timer); |
| 838 | + | |
| 839 | + if (mlx5_core_is_pf(dev) && MLX5_CAP_MCAM_REG(dev, mrtc)) | |
| 840 | + queue_delayed_work(health->wq, &health->update_fw_log_ts_work, 0); | |
| 838 | 841 | } |
| 839 | 842 | |
| 840 | 843 | void mlx5_stop_health_poll(struct mlx5_core_dev *dev, bool disable_health) |
| @@ -902,8 +905,6 @@ int mlx5_health_init(struct mlx5_core_dev *dev) · 61 unmodified lines | ||
| 902 | 905 | INIT_WORK(&health->fatal_report_work, mlx5_fw_fatal_reporter_err_work); |
| 903 | 906 | INIT_WORK(&health->report_work, mlx5_fw_reporter_err_work); |
| 904 | 907 | INIT_DELAYED_WORK(&health->update_fw_log_ts_work, mlx5_health_log_ts_update); |
| 905 | − if (mlx5_core_is_pf(dev)) | |
| 906 | − queue_delayed_work(health->wq, &health->update_fw_log_ts_work, 0); | |
| 907 | 908 | |
| 908 | 909 | return 0; |
| 909 | 910 | |
| @@ -608,4 +608,5 @@ void mlx5_lag_port_sel_destroy(struct mlx5_lag *ldev) · 607 unmodified lines | ||
| 608 | 608 | if (port_sel->tunnel) |
| 609 | 609 | mlx5_destroy_ttc_table(port_sel->inner.ttc); |
| 610 | 610 | mlx5_lag_destroy_definers(ldev); |
| 611 | + memset(port_sel, 0, sizeof(*port_sel)); | |
| 611 | 612 | } |
| @@ -31,11 +31,11 @@ static void tout_set(struct mlx5_core_dev *dev, u64 val, enum mlx5_timeouts_type · 30 unmodified lines | ||
| 31 | 31 | dev->timeouts->to[type] = val; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | −static void tout_set_def_val(struct mlx5_core_dev *dev) | |
| 34 | +void mlx5_tout_set_def_val(struct mlx5_core_dev *dev) | |
| 35 | 35 | { |
| 36 | 36 | int i; |
| 37 | 37 | |
| 38 | − for (i = MLX5_TO_FW_PRE_INIT_TIMEOUT_MS; i < MAX_TIMEOUT_TYPES; i++) | |
| 38 | + for (i = 0; i < MAX_TIMEOUT_TYPES; i++) | |
| 39 | 39 | tout_set(dev, tout_def_sw_val[i], i); |
| 40 | 40 | } |
| 41 | 41 | |
| @@ -45,7 +45,6 @@ int mlx5_tout_init(struct mlx5_core_dev *dev) · 3 unmodified lines | ||
| 45 | 45 | if (!dev->timeouts) |
| 46 | 46 | return -ENOMEM; |
| 47 | 47 | |
| 48 | − tout_set_def_val(dev); | |
| 49 | 48 | return 0; |
| 50 | 49 | } |
| 51 | 50 | |
| @@ -34,6 +34,7 @@ int mlx5_tout_init(struct mlx5_core_dev *dev); · 33 unmodified lines | ||
| 34 | 34 | void mlx5_tout_cleanup(struct mlx5_core_dev *dev); |
| 35 | 35 | void mlx5_tout_query_iseg(struct mlx5_core_dev *dev); |
| 36 | 36 | int mlx5_tout_query_dtor(struct mlx5_core_dev *dev); |
| 37 | +void mlx5_tout_set_def_val(struct mlx5_core_dev *dev); | |
| 37 | 38 | u64 _mlx5_tout_ms(struct mlx5_core_dev *dev, enum mlx5_timeouts_types type); |
| 38 | 39 | |
| 39 | 40 | #define mlx5_tout_ms(dev, type) _mlx5_tout_ms(dev, MLX5_TO_##type##_MS) |
| @@ -992,11 +992,7 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) · 991 unmodified lines | ||
| 992 | 992 | if (mlx5_core_is_pf(dev)) |
| 993 | 993 | pcie_print_link_status(dev->pdev); |
| 994 | 994 | |
| 995 | − err = mlx5_tout_init(dev); | |
| 996 | − if (err) { | |
| 997 | − mlx5_core_err(dev, "Failed initializing timeouts, aborting\n"); | |
| 998 | − return err; | |
| 999 | − } | |
| 995 | + mlx5_tout_set_def_val(dev); | |
| 1000 | 996 | |
| 1001 | 997 | /* wait for firmware to accept initialization segments configurations |
| 1002 | 998 | */ |
| @@ -1005,13 +1001,13 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) · 2 unmodified lines | ||
| 1005 | 1001 | if (err) { |
| 1006 | 1002 | mlx5_core_err(dev, "Firmware over %llu MS in pre-initializing state, aborting\n", |
| 1007 | 1003 | mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT)); |
| 1008 | − goto err_tout_cleanup; | |
| 1004 | + return err; | |
| 1009 | 1005 | } |
| 1010 | 1006 | |
| 1011 | 1007 | err = mlx5_cmd_init(dev); |
| 1012 | 1008 | if (err) { |
| 1013 | 1009 | mlx5_core_err(dev, "Failed initializing command interface, aborting\n"); |
| 1014 | − goto err_tout_cleanup; | |
| 1010 | + return err; | |
| 1015 | 1011 | } |
| 1016 | 1012 | |
| 1017 | 1013 | mlx5_tout_query_iseg(dev); |
| @@ -1075,18 +1071,16 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot) · 57 unmodified lines | ||
| 1075 | 1071 | |
| 1076 | 1072 | mlx5_set_driver_version(dev); |
| 1077 | 1073 | |
| 1078 | − mlx5_start_health_poll(dev); | |
| 1079 | − | |
| 1080 | 1074 | err = mlx5_query_hca_caps(dev); |
| 1081 | 1075 | if (err) { |
| 1082 | 1076 | mlx5_core_err(dev, "query hca failed\n"); |
| 1083 | − goto stop_health; | |
| 1077 | + goto reclaim_boot_pages; | |
| 1084 | 1078 | } |
| 1085 | 1079 | |
| 1080 | + mlx5_start_health_poll(dev); | |
| 1081 | + | |
| 1086 | 1082 | return 0; |
| 1087 | 1083 | |
| 1088 | −stop_health: | |
| 1089 | − mlx5_stop_health_poll(dev, boot); | |
| 1090 | 1084 | reclaim_boot_pages: |
| 1091 | 1085 | mlx5_reclaim_startup_pages(dev); |
| 1092 | 1086 | err_disable_hca: |
| @@ -1094,8 +1088,6 @@ err_disable_hca: · 1 unmodified line | ||
| 1094 | 1088 | err_cmd_cleanup: |
| 1095 | 1089 | mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); |
| 1096 | 1090 | mlx5_cmd_cleanup(dev); |
| 1097 | −err_tout_cleanup: | |
| 1098 | − mlx5_tout_cleanup(dev); | |
| 1099 | 1091 | |
| 1100 | 1092 | return err; |
| 1101 | 1093 | } |
| @@ -1114,7 +1106,6 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) · 12 unmodified lines | ||
| 1114 | 1106 | mlx5_core_disable_hca(dev, 0); |
| 1115 | 1107 | mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); |
| 1116 | 1108 | mlx5_cmd_cleanup(dev); |
| 1117 | − mlx5_tout_cleanup(dev); | |
| 1118 | 1109 | |
| 1119 | 1110 | return 0; |
| 1120 | 1111 | } |
| @@ -1476,6 +1467,12 @@ int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx) · 355 unmodified lines | ||
| 1476 | 1467 | mlx5_debugfs_root); |
| 1477 | 1468 | INIT_LIST_HEAD(&priv->traps); |
| 1478 | 1469 | |
| 1470 | + err = mlx5_tout_init(dev); | |
| 1471 | + if (err) { | |
| 1472 | + mlx5_core_err(dev, "Failed initializing timeouts, aborting\n"); | |
| 1473 | + goto err_timeout_init; | |
| 1474 | + } | |
| 1475 | + | |
| 1479 | 1476 | err = mlx5_health_init(dev); |
| 1480 | 1477 | if (err) |
| 1481 | 1478 | goto err_health_init; |
| @@ -1501,6 +1498,8 @@ err_adev_init: · 19 unmodified lines | ||
| 1501 | 1498 | err_pagealloc_init: |
| 1502 | 1499 | mlx5_health_cleanup(dev); |
| 1503 | 1500 | err_health_init: |
| 1501 | + mlx5_tout_cleanup(dev); | |
| 1502 | +err_timeout_init: | |
| 1504 | 1503 | debugfs_remove(dev->priv.dbg_root); |
| 1505 | 1504 | mutex_destroy(&priv->pgdir_mutex); |
| 1506 | 1505 | mutex_destroy(&priv->alloc_mutex); |
| @@ -1518,6 +1517,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev) · 11 unmodified lines | ||
| 1518 | 1517 | mlx5_adev_cleanup(dev); |
| 1519 | 1518 | mlx5_pagealloc_cleanup(dev); |
| 1520 | 1519 | mlx5_health_cleanup(dev); |
| 1520 | + mlx5_tout_cleanup(dev); | |
| 1521 | 1521 | debugfs_remove_recursive(dev->priv.dbg_root); |
| 1522 | 1522 | mutex_destroy(&priv->pgdir_mutex); |
| 1523 | 1523 | mutex_destroy(&priv->alloc_mutex); |
| @@ -480,16 +480,16 @@ static int mana_hwc_create_wq(struct hw_channel_context *hwc, · 479 unmodified lines | ||
| 480 | 480 | if (err) |
| 481 | 481 | goto out; |
| 482 | 482 | |
| 483 | − err = mana_hwc_alloc_dma_buf(hwc, q_depth, max_msg_size, | |
| 484 | − &hwc_wq->msg_buf); | |
| 485 | − if (err) | |
| 486 | − goto out; | |
| 487 | − | |
| 488 | 483 | hwc_wq->hwc = hwc; |
| 489 | 484 | hwc_wq->gdma_wq = queue; |
| 490 | 485 | hwc_wq->queue_depth = q_depth; |
| 491 | 486 | hwc_wq->hwc_cq = hwc_cq; |
| 492 | 487 | |
| 488 | + err = mana_hwc_alloc_dma_buf(hwc, q_depth, max_msg_size, | |
| 489 | + &hwc_wq->msg_buf); | |
| 490 | + if (err) | |
| 491 | + goto out; | |
| 492 | + | |
| 493 | 493 | *hwc_wq_ptr = hwc_wq; |
| 494 | 494 | return 0; |
| 495 | 495 | out: |
| @@ -1563,8 +1563,10 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) · 1562 unmodified lines | ||
| 1563 | 1563 | } |
| 1564 | 1564 | |
| 1565 | 1565 | err = ocelot_setup_ptp_traps(ocelot, port, l2, l4); |
| 1566 | − if (err) | |
| 1566 | + if (err) { | |
| 1567 | + mutex_unlock(&ocelot->ptp_lock); | |
| 1567 | 1568 | return err; |
| 1569 | + } | |
| 1568 | 1570 | |
| 1569 | 1571 | if (l2 && l4) |
| 1570 | 1572 | cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; |
| @@ -120,7 +120,7 @@ static const struct net_device_ops xtsonic_netdev_ops = { · 119 unmodified lines | ||
| 120 | 120 | .ndo_set_mac_address = eth_mac_addr, |
| 121 | 121 | }; |
| 122 | 122 | |
| 123 | −static int __init sonic_probe1(struct net_device *dev) | |
| 123 | +static int sonic_probe1(struct net_device *dev) | |
| 124 | 124 | { |
| 125 | 125 | unsigned int silicon_revision; |
| 126 | 126 | struct sonic_local *lp = netdev_priv(dev); |
| @@ -803,8 +803,10 @@ int nfp_cpp_area_cache_add(struct nfp_cpp *cpp, size_t size) · 802 unmodified lines | ||
| 803 | 803 | return -ENOMEM; |
| 804 | 804 | |
| 805 | 805 | cache = kzalloc(sizeof(*cache), GFP_KERNEL); |
| 806 | − if (!cache) | |
| 806 | + if (!cache) { | |
| 807 | + nfp_cpp_area_free(area); | |
| 807 | 808 | return -ENOMEM; |
| 809 | + } | |
| 808 | 810 | |
| 809 | 811 | cache->id = 0; |
| 810 | 812 | cache->addr = 0; |
| @@ -1643,6 +1643,13 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 1642 unmodified lines | ||
| 1643 | 1643 | data_split = true; |
| 1644 | 1644 | } |
| 1645 | 1645 | } else { |
| 1646 | + if (unlikely(skb->len > ETH_TX_MAX_NON_LSO_PKT_LEN)) { | |
| 1647 | + DP_ERR(edev, "Unexpected non LSO skb length = 0x%x\n", skb->len); | |
| 1648 | + qede_free_failed_tx_pkt(txq, first_bd, 0, false); | |
| 1649 | + qede_update_tx_producer(txq); | |
| 1650 | + return NETDEV_TX_OK; | |
| 1651 | + } | |
| 1652 | + | |
| 1646 | 1653 | val |= ((skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK) << |
| 1647 | 1654 | ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT); |
| 1648 | 1655 | } |
| @@ -3480,20 +3480,19 @@ static int ql_adapter_up(struct ql3_adapter *qdev) · 3479 unmodified lines | ||
| 3480 | 3480 | |
| 3481 | 3481 | spin_lock_irqsave(&qdev->hw_lock, hw_flags); |
| 3482 | 3482 | |
| 3483 | − err = ql_wait_for_drvr_lock(qdev); | |
| 3484 | − if (err) { | |
| 3485 | − err = ql_adapter_initialize(qdev); | |
| 3486 | − if (err) { | |
| 3487 | − netdev_err(ndev, "Unable to initialize adapter\n"); | |
| 3488 | − goto err_init; | |
| 3489 | − } | |
| 3490 | − netdev_err(ndev, "Releasing driver lock\n"); | |
| 3491 | − ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); | |
| 3492 | − } else { | |
| 3483 | + if (!ql_wait_for_drvr_lock(qdev)) { | |
| 3493 | 3484 | netdev_err(ndev, "Could not acquire driver lock\n"); |
| 3485 | + err = -ENODEV; | |
| 3494 | 3486 | goto err_lock; |
| 3495 | 3487 | } |
| 3496 | 3488 | |
| 3489 | + err = ql_adapter_initialize(qdev); | |
| 3490 | + if (err) { | |
| 3491 | + netdev_err(ndev, "Unable to initialize adapter\n"); | |
| 3492 | + goto err_init; | |
| 3493 | + } | |
| 3494 | + ql_sem_unlock(qdev, QL_DRVR_SEM_MASK); | |
| 3495 | + | |
| 3497 | 3496 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); |
| 3498 | 3497 | |
| 3499 | 3498 | set_bit(QL_ADAPTER_UP, &qdev->flags); |
| @@ -1077,8 +1077,14 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter) · 1076 unmodified lines | ||
| 1077 | 1077 | sds_mbx_size = sizeof(struct qlcnic_sds_mbx); |
| 1078 | 1078 | context_id = recv_ctx->context_id; |
| 1079 | 1079 | num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS; |
| 1080 | − ahw->hw_ops->alloc_mbx_args(&cmd, adapter, | |
| 1081 | − QLCNIC_CMD_ADD_RCV_RINGS); | |
| 1080 | + err = ahw->hw_ops->alloc_mbx_args(&cmd, adapter, | |
| 1081 | + QLCNIC_CMD_ADD_RCV_RINGS); | |
| 1082 | + if (err) { | |
| 1083 | + dev_err(&adapter->pdev->dev, | |
| 1084 | + "Failed to alloc mbx args %d\n", err); | |
| 1085 | + return err; | |
| 1086 | + } | |
| 1087 | + | |
| 1082 | 1088 | cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16); |
| 1083 | 1089 | |
| 1084 | 1090 | /* set up status rings, mbx 2-81 */ |
| @@ -5540,8 +5540,6 @@ static int stmmac_set_features(struct net_device *netdev, · 5539 unmodified lines | ||
| 5540 | 5540 | netdev_features_t features) |
| 5541 | 5541 | { |
| 5542 | 5542 | struct stmmac_priv *priv = netdev_priv(netdev); |
| 5543 | − bool sph_en; | |
| 5544 | − u32 chan; | |
| 5545 | 5543 | |
| 5546 | 5544 | /* Keep the COE Type in case of csum is supporting */ |
| 5547 | 5545 | if (features & NETIF_F_RXCSUM) |
| @@ -5553,10 +5551,13 @@ static int stmmac_set_features(struct net_device *netdev, · 5 unmodified lines | ||
| 5553 | 5551 | */ |
| 5554 | 5552 | stmmac_rx_ipc(priv, priv->hw); |
| 5555 | 5553 | |
| 5556 | − sph_en = (priv->hw->rx_csum > 0) && priv->sph; | |
| 5554 | + if (priv->sph_cap) { | |
| 5555 | + bool sph_en = (priv->hw->rx_csum > 0) && priv->sph; | |
| 5556 | + u32 chan; | |
| 5557 | 5557 | |
| 5558 | − for (chan = 0; chan < priv->plat->rx_queues_to_use; chan++) | |
| 5559 | − stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); | |
| 5558 | + for (chan = 0; chan < priv->plat->rx_queues_to_use; chan++) | |
| 5559 | + stmmac_enable_sph(priv, priv->ioaddr, sph_en, chan); | |
| 5560 | + } | |
| 5560 | 5561 | |
| 5561 | 5562 | return 0; |
| 5562 | 5563 | } |
| @@ -1388,6 +1388,7 @@ EXPORT_SYMBOL_GPL(phylink_stop); · 1387 unmodified lines | ||
| 1388 | 1388 | * @mac_wol: true if the MAC needs to receive packets for Wake-on-Lan |
| 1389 | 1389 | * |
| 1390 | 1390 | * Handle a network device suspend event. There are several cases: |
| 1391 | + * | |
| 1391 | 1392 | * - If Wake-on-Lan is not active, we can bring down the link between |
| 1392 | 1393 | * the MAC and PHY by calling phylink_stop(). |
| 1393 | 1394 | * - If Wake-on-Lan is active, and being handled only by the PHY, we |
| @@ -181,6 +181,8 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx) · 180 unmodified lines | ||
| 181 | 181 | min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32); |
| 182 | 182 | |
| 183 | 183 | max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)); |
| 184 | + if (max == 0) | |
| 185 | + max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */ | |
| 184 | 186 | |
| 185 | 187 | /* some devices set dwNtbOutMaxSize too low for the above default */ |
| 186 | 188 | min = min(min, max); |
| @@ -2228,7 +2228,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) · 2227 unmodified lines | ||
| 2228 | 2228 | if (dev->domain_data.phyirq > 0) |
| 2229 | 2229 | phydev->irq = dev->domain_data.phyirq; |
| 2230 | 2230 | else |
| 2231 | − phydev->irq = 0; | |
| 2231 | + phydev->irq = PHY_POLL; | |
| 2232 | 2232 | netdev_dbg(dev->net, "phydev->irq = %d\n", phydev->irq); |
| 2233 | 2233 | |
| 2234 | 2234 | /* set to AUTOMDIX */ |
| @@ -3261,7 +3261,7 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) · 3260 unmodified lines | ||
| 3261 | 3261 | |
| 3262 | 3262 | #ifdef CONFIG_PCI_MSI |
| 3263 | 3263 | if (adapter->intr.type == VMXNET3_IT_MSIX) { |
| 3264 | − int i, nvec; | |
| 3264 | + int i, nvec, nvec_allocated; | |
| 3265 | 3265 | |
| 3266 | 3266 | nvec = adapter->share_intr == VMXNET3_INTR_TXSHARE ? |
| 3267 | 3267 | 1 : adapter->num_tx_queues; |
| @@ -3274,14 +3274,15 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) · 6 unmodified lines | ||
| 3274 | 3274 | for (i = 0; i < nvec; i++) |
| 3275 | 3275 | adapter->intr.msix_entries[i].entry = i; |
| 3276 | 3276 | |
| 3277 | − nvec = vmxnet3_acquire_msix_vectors(adapter, nvec); | |
| 3278 | − if (nvec < 0) | |
| 3277 | + nvec_allocated = vmxnet3_acquire_msix_vectors(adapter, nvec); | |
| 3278 | + if (nvec_allocated < 0) | |
| 3279 | 3279 | goto msix_err; |
| 3280 | 3280 | |
| 3281 | 3281 | /* If we cannot allocate one MSIx vector per queue |
| 3282 | 3282 | * then limit the number of rx queues to 1 |
| 3283 | 3283 | */ |
| 3284 | − if (nvec == VMXNET3_LINUX_MIN_MSIX_VECT) { | |
| 3284 | + if (nvec_allocated == VMXNET3_LINUX_MIN_MSIX_VECT && | |
| 3285 | + nvec != VMXNET3_LINUX_MIN_MSIX_VECT) { | |
| 3285 | 3286 | if (adapter->share_intr != VMXNET3_INTR_BUDDYSHARE |
| 3286 | 3287 | || adapter->num_rx_queues != 1) { |
| 3287 | 3288 | adapter->share_intr = VMXNET3_INTR_TXSHARE; |
| @@ -3291,14 +3292,14 @@ vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter) · 3 unmodified lines | ||
| 3291 | 3292 | } |
| 3292 | 3293 | } |
| 3293 | 3294 | |
| 3294 | − adapter->intr.num_intrs = nvec; | |
| 3295 | + adapter->intr.num_intrs = nvec_allocated; | |
| 3295 | 3296 | return; |
| 3296 | 3297 | |
| 3297 | 3298 | msix_err: |
| 3298 | 3299 | /* If we cannot allocate MSIx vectors use only one rx queue */ |
| 3299 | 3300 | dev_info(&adapter->pdev->dev, |
| 3300 | 3301 | "Failed to enable MSI-X, error %d. " |
| 3301 | − "Limiting #rx queues to 1, try MSI.\n", nvec); | |
| 3302 | + "Limiting #rx queues to 1, try MSI.\n", nvec_allocated); | |
| 3302 | 3303 | |
| 3303 | 3304 | adapter->intr.type = VMXNET3_IT_MSI; |
| 3304 | 3305 | } |
| @@ -497,6 +497,7 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, · 496 unmodified lines | ||
| 497 | 497 | /* strip the ethernet header added for pass through VRF device */ |
| 498 | 498 | __skb_pull(skb, skb_network_offset(skb)); |
| 499 | 499 | |
| 500 | + memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | |
| 500 | 501 | ret = vrf_ip6_local_out(net, skb->sk, skb); |
| 501 | 502 | if (unlikely(net_xmit_eval(ret))) |
| 502 | 503 | dev->stats.tx_errors++; |
| @@ -579,6 +580,7 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, · 76 unmodified lines | ||
| 579 | 580 | RT_SCOPE_LINK); |
| 580 | 581 | } |
| 581 | 582 | |
| 583 | + memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | |
| 582 | 584 | ret = vrf_ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb); |
| 583 | 585 | if (unlikely(net_xmit_eval(ret))) |
| 584 | 586 | vrf_dev->stats.tx_errors++; |
| @@ -768,8 +770,6 @@ static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev, · 183 unmodified lines | ||
| 768 | 770 | |
| 769 | 771 | skb->dev = vrf_dev; |
| 770 | 772 | |
| 771 | − vrf_nf_set_untracked(skb); | |
| 772 | − | |
| 773 | 773 | err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, |
| 774 | 774 | skb, NULL, vrf_dev, vrf_ip6_out_direct_finish); |
| 775 | 775 | |
| @@ -790,6 +790,8 @@ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev, · 14 unmodified lines | ||
| 790 | 790 | if (rt6_need_strict(&ipv6_hdr(skb)->daddr)) |
| 791 | 791 | return skb; |
| 792 | 792 | |
| 793 | + vrf_nf_set_untracked(skb); | |
| 794 | + | |
| 793 | 795 | if (qdisc_tx_is_default(vrf_dev) || |
| 794 | 796 | IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) |
| 795 | 797 | return vrf_ip6_out_direct(vrf_dev, sk, skb); |
| @@ -998,8 +1000,6 @@ static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev, · 202 unmodified lines | ||
| 998 | 1000 | |
| 999 | 1001 | skb->dev = vrf_dev; |
| 1000 | 1002 | |
| 1001 | − vrf_nf_set_untracked(skb); | |
| 1002 | − | |
| 1003 | 1003 | err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, |
| 1004 | 1004 | skb, NULL, vrf_dev, vrf_ip_out_direct_finish); |
| 1005 | 1005 | |
| @@ -1021,6 +1021,8 @@ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev, · 15 unmodified lines | ||
| 1021 | 1021 | ipv4_is_lbcast(ip_hdr(skb)->daddr)) |
| 1022 | 1022 | return skb; |
| 1023 | 1023 | |
| 1024 | + vrf_nf_set_untracked(skb); | |
| 1025 | + | |
| 1024 | 1026 | if (qdisc_tx_is_default(vrf_dev) || |
| 1025 | 1027 | IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) |
| 1026 | 1028 | return vrf_ip_out_direct(vrf_dev, sk, skb); |
| @@ -163,7 +163,7 @@ static bool node_placement(struct allowedips_node __rcu *trie, const u8 *key, · 162 unmodified lines | ||
| 163 | 163 | return exact; |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | −static inline void connect_node(struct allowedips_node **parent, u8 bit, struct allowedips_node *node) | |
| 166 | +static inline void connect_node(struct allowedips_node __rcu **parent, u8 bit, struct allowedips_node *node) | |
| 167 | 167 | { |
| 168 | 168 | node->parent_bit_packed = (unsigned long)parent | bit; |
| 169 | 169 | rcu_assign_pointer(*parent, node); |
| @@ -98,6 +98,7 @@ static int wg_stop(struct net_device *dev) · 97 unmodified lines | ||
| 98 | 98 | { |
| 99 | 99 | struct wg_device *wg = netdev_priv(dev); |
| 100 | 100 | struct wg_peer *peer; |
| 101 | + struct sk_buff *skb; | |
| 101 | 102 | |
| 102 | 103 | mutex_lock(&wg->device_update_lock); |
| 103 | 104 | list_for_each_entry(peer, &wg->peer_list, peer_list) { |
| @@ -108,7 +109,9 @@ static int wg_stop(struct net_device *dev) · 4 unmodified lines | ||
| 108 | 109 | wg_noise_reset_last_sent_handshake(&peer->last_sent_handshake); |
| 109 | 110 | } |
| 110 | 111 | mutex_unlock(&wg->device_update_lock); |
| 111 | − skb_queue_purge(&wg->incoming_handshakes); | |
| 112 | + while ((skb = ptr_ring_consume(&wg->handshake_queue.ring)) != NULL) | |
| 113 | + kfree_skb(skb); | |
| 114 | + atomic_set(&wg->handshake_queue_len, 0); | |
| 112 | 115 | wg_socket_reinit(wg, NULL, NULL); |
| 113 | 116 | return 0; |
| 114 | 117 | } |
| @@ -235,14 +238,13 @@ static void wg_destruct(struct net_device *dev) · 120 unmodified lines | ||
| 235 | 238 | destroy_workqueue(wg->handshake_receive_wq); |
| 236 | 239 | destroy_workqueue(wg->handshake_send_wq); |
| 237 | 240 | destroy_workqueue(wg->packet_crypt_wq); |
| 238 | − wg_packet_queue_free(&wg->decrypt_queue); | |
| 239 | − wg_packet_queue_free(&wg->encrypt_queue); | |
| 241 | + wg_packet_queue_free(&wg->handshake_queue, true); | |
| 242 | + wg_packet_queue_free(&wg->decrypt_queue, false); | |
| 243 | + wg_packet_queue_free(&wg->encrypt_queue, false); | |
| 240 | 244 | rcu_barrier(); /* Wait for all the peers to be actually freed. */ |
| 241 | 245 | wg_ratelimiter_uninit(); |
| 242 | 246 | memzero_explicit(&wg->static_identity, sizeof(wg->static_identity)); |
| 243 | − skb_queue_purge(&wg->incoming_handshakes); | |
| 244 | 247 | free_percpu(dev->tstats); |
| 245 | − free_percpu(wg->incoming_handshakes_worker); | |
| 246 | 248 | kvfree(wg->index_hashtable); |
| 247 | 249 | kvfree(wg->peer_hashtable); |
| 248 | 250 | mutex_unlock(&wg->device_update_lock); |
| @@ -298,7 +300,6 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, · 49 unmodified lines | ||
| 298 | 300 | init_rwsem(&wg->static_identity.lock); |
| 299 | 301 | mutex_init(&wg->socket_update_lock); |
| 300 | 302 | mutex_init(&wg->device_update_lock); |
| 301 | − skb_queue_head_init(&wg->incoming_handshakes); | |
| 302 | 303 | wg_allowedips_init(&wg->peer_allowedips); |
| 303 | 304 | wg_cookie_checker_init(&wg->cookie_checker, wg); |
| 304 | 305 | INIT_LIST_HEAD(&wg->peer_list); |
| @@ -316,16 +317,10 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, · 11 unmodified lines | ||
| 316 | 317 | if (!dev->tstats) |
| 317 | 318 | goto err_free_index_hashtable; |
| 318 | 319 | |
| 319 | − wg->incoming_handshakes_worker = | |
| 320 | − wg_packet_percpu_multicore_worker_alloc( | |
| 321 | − wg_packet_handshake_receive_worker, wg); | |
| 322 | − if (!wg->incoming_handshakes_worker) | |
| 323 | − goto err_free_tstats; | |
| 324 | − | |
| 325 | 320 | wg->handshake_receive_wq = alloc_workqueue("wg-kex-%s", |
| 326 | 321 | WQ_CPU_INTENSIVE | WQ_FREEZABLE, 0, dev->name); |
| 327 | 322 | if (!wg->handshake_receive_wq) |
| 328 | − goto err_free_incoming_handshakes; | |
| 323 | + goto err_free_tstats; | |
| 329 | 324 | |
| 330 | 325 | wg->handshake_send_wq = alloc_workqueue("wg-kex-%s", |
| 331 | 326 | WQ_UNBOUND | WQ_FREEZABLE, 0, dev->name); |
| @@ -347,10 +342,15 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, · 15 unmodified lines | ||
| 347 | 342 | if (ret < 0) |
| 348 | 343 | goto err_free_encrypt_queue; |
| 349 | 344 | |
| 350 | − ret = wg_ratelimiter_init(); | |
| 345 | + ret = wg_packet_queue_init(&wg->handshake_queue, wg_packet_handshake_receive_worker, | |
| 346 | + MAX_QUEUED_INCOMING_HANDSHAKES); | |
| 351 | 347 | if (ret < 0) |
| 352 | 348 | goto err_free_decrypt_queue; |
| 353 | 349 | |
| 350 | + ret = wg_ratelimiter_init(); | |
| 351 | + if (ret < 0) | |
| 352 | + goto err_free_handshake_queue; | |
| 353 | + | |
| 354 | 354 | ret = register_netdevice(dev); |
| 355 | 355 | if (ret < 0) |
| 356 | 356 | goto err_uninit_ratelimiter; |
| @@ -367,18 +367,18 @@ static int wg_newlink(struct net *src_net, struct net_device *dev, · 10 unmodified lines | ||
| 367 | 367 | |
| 368 | 368 | err_uninit_ratelimiter: |
| 369 | 369 | wg_ratelimiter_uninit(); |
| 370 | +err_free_handshake_queue: | |
| 371 | + wg_packet_queue_free(&wg->handshake_queue, false); | |
| 370 | 372 | err_free_decrypt_queue: |
| 371 | − wg_packet_queue_free(&wg->decrypt_queue); | |
| 373 | + wg_packet_queue_free(&wg->decrypt_queue, false); | |
| 372 | 374 | err_free_encrypt_queue: |
| 373 | − wg_packet_queue_free(&wg->encrypt_queue); | |
| 375 | + wg_packet_queue_free(&wg->encrypt_queue, false); | |
| 374 | 376 | err_destroy_packet_crypt: |
| 375 | 377 | destroy_workqueue(wg->packet_crypt_wq); |
| 376 | 378 | err_destroy_handshake_send: |
| 377 | 379 | destroy_workqueue(wg->handshake_send_wq); |
| 378 | 380 | err_destroy_handshake_receive: |
| 379 | 381 | destroy_workqueue(wg->handshake_receive_wq); |
| 380 | −err_free_incoming_handshakes: | |
| 381 | − free_percpu(wg->incoming_handshakes_worker); | |
| 382 | 382 | err_free_tstats: |
| 383 | 383 | free_percpu(dev->tstats); |
| 384 | 384 | err_free_index_hashtable: |
| @@ -398,6 +398,7 @@ static struct rtnl_link_ops link_ops __read_mostly = { · 13 unmodified lines | ||
| 398 | 398 | static void wg_netns_pre_exit(struct net *net) |
| 399 | 399 | { |
| 400 | 400 | struct wg_device *wg; |
| 401 | + struct wg_peer *peer; | |
| 401 | 402 | |
| 402 | 403 | rtnl_lock(); |
| 403 | 404 | list_for_each_entry(wg, &device_list, device_list) { |
| @@ -407,6 +408,8 @@ static void wg_netns_pre_exit(struct net *net) · 3 unmodified lines | ||
| 407 | 408 | mutex_lock(&wg->device_update_lock); |
| 408 | 409 | rcu_assign_pointer(wg->creating_net, NULL); |
| 409 | 410 | wg_socket_reinit(wg, NULL, NULL); |
| 411 | + list_for_each_entry(peer, &wg->peer_list, peer_list) | |
| 412 | + wg_socket_clear_peer_endpoint_src(peer); | |
| 410 | 413 | mutex_unlock(&wg->device_update_lock); |
| 411 | 414 | } |
| 412 | 415 | } |
| @@ -39,21 +39,18 @@ struct prev_queue { · 38 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | struct wg_device { |
| 41 | 41 | struct net_device *dev; |
| 42 | − struct crypt_queue encrypt_queue, decrypt_queue; | |
| 42 | + struct crypt_queue encrypt_queue, decrypt_queue, handshake_queue; | |
| 43 | 43 | struct sock __rcu *sock4, *sock6; |
| 44 | 44 | struct net __rcu *creating_net; |
| 45 | 45 | struct noise_static_identity static_identity; |
| 46 | − struct workqueue_struct *handshake_receive_wq, *handshake_send_wq; | |
| 47 | − struct workqueue_struct *packet_crypt_wq; | |
| 48 | − struct sk_buff_head incoming_handshakes; | |
| 49 | − int incoming_handshake_cpu; | |
| 50 | − struct multicore_worker __percpu *incoming_handshakes_worker; | |
| 46 | + struct workqueue_struct *packet_crypt_wq,*handshake_receive_wq, *handshake_send_wq; | |
| 51 | 47 | struct cookie_checker cookie_checker; |
| 52 | 48 | struct pubkey_hashtable *peer_hashtable; |
| 53 | 49 | struct index_hashtable *index_hashtable; |
| 54 | 50 | struct allowedips peer_allowedips; |
| 55 | 51 | struct mutex device_update_lock, socket_update_lock; |
| 56 | 52 | struct list_head device_list, peer_list; |
| 53 | + atomic_t handshake_queue_len; | |
| 57 | 54 | unsigned int num_peers, device_update_gen; |
| 58 | 55 | u32 fwmark; |
| 59 | 56 | u16 incoming_port; |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/genetlink.h> |
| 18 | 18 | #include <net/rtnetlink.h> |
| 19 | 19 | |
| 20 | −static int __init mod_init(void) | |
| 20 | +static int __init wg_mod_init(void) | |
| 21 | 21 | { |
| 22 | 22 | int ret; |
| 23 | 23 | |
| @@ -60,7 +60,7 @@ err_allowedips: · 36 unmodified lines | ||
| 60 | 60 | return ret; |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | −static void __exit mod_exit(void) | |
| 63 | +static void __exit wg_mod_exit(void) | |
| 64 | 64 | { |
| 65 | 65 | wg_genetlink_uninit(); |
| 66 | 66 | wg_device_uninit(); |
| @@ -68,8 +68,8 @@ static void __exit mod_exit(void) · 1 unmodified line | ||
| 68 | 68 | wg_allowedips_slab_uninit(); |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | −module_init(mod_init); | |
| 72 | −module_exit(mod_exit); | |
| 71 | +module_init(wg_mod_init); | |
| 72 | +module_exit(wg_mod_exit); | |
| 73 | 73 | MODULE_LICENSE("GPL v2"); |
| 74 | 74 | MODULE_DESCRIPTION("WireGuard secure network tunnel"); |
| 75 | 75 | MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>"); |
| @@ -38,11 +38,11 @@ int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, · 37 unmodified lines | ||
| 38 | 38 | return 0; |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | −void wg_packet_queue_free(struct crypt_queue *queue) | |
| 41 | +void wg_packet_queue_free(struct crypt_queue *queue, bool purge) | |
| 42 | 42 | { |
| 43 | 43 | free_percpu(queue->worker); |
| 44 | − WARN_ON(!__ptr_ring_empty(&queue->ring)); | |
| 45 | − ptr_ring_cleanup(&queue->ring, NULL); | |
| 44 | + WARN_ON(!purge && !__ptr_ring_empty(&queue->ring)); | |
| 45 | + ptr_ring_cleanup(&queue->ring, purge ? (void(*)(void*))kfree_skb : NULL); | |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | #define NEXT(skb) ((skb)->prev) |
| @@ -23,7 +23,7 @@ struct sk_buff; · 22 unmodified lines | ||
| 23 | 23 | /* queueing.c APIs: */ |
| 24 | 24 | int wg_packet_queue_init(struct crypt_queue *queue, work_func_t function, |
| 25 | 25 | unsigned int len); |
| 26 | −void wg_packet_queue_free(struct crypt_queue *queue); | |
| 26 | +void wg_packet_queue_free(struct crypt_queue *queue, bool purge); | |
| 27 | 27 | struct multicore_worker __percpu * |
| 28 | 28 | wg_packet_percpu_multicore_worker_alloc(work_func_t function, void *ptr); |
| 29 | 29 | |
| @@ -176,12 +176,12 @@ int wg_ratelimiter_init(void) · 175 unmodified lines | ||
| 176 | 176 | (1U << 14) / sizeof(struct hlist_head))); |
| 177 | 177 | max_entries = table_size * 8; |
| 178 | 178 | |
| 179 | − table_v4 = kvzalloc(table_size * sizeof(*table_v4), GFP_KERNEL); | |
| 179 | + table_v4 = kvcalloc(table_size, sizeof(*table_v4), GFP_KERNEL); | |
| 180 | 180 | if (unlikely(!table_v4)) |
| 181 | 181 | goto err_kmemcache; |
| 182 | 182 | |
| 183 | 183 | #if IS_ENABLED(CONFIG_IPV6) |
| 184 | − table_v6 = kvzalloc(table_size * sizeof(*table_v6), GFP_KERNEL); | |
| 184 | + table_v6 = kvcalloc(table_size, sizeof(*table_v6), GFP_KERNEL); | |
| 185 | 185 | if (unlikely(!table_v6)) { |
| 186 | 186 | kvfree(table_v4); |
| 187 | 187 | goto err_kmemcache; |
| @@ -116,8 +116,8 @@ static void wg_receive_handshake_packet(struct wg_device *wg, · 115 unmodified lines | ||
| 116 | 116 | return; |
| 117 | 117 | } |
| 118 | 118 | |
| 119 | − under_load = skb_queue_len(&wg->incoming_handshakes) >= | |
| 120 | − MAX_QUEUED_INCOMING_HANDSHAKES / 8; | |
| 119 | + under_load = atomic_read(&wg->handshake_queue_len) >= | |
| 120 | + MAX_QUEUED_INCOMING_HANDSHAKES / 8; | |
| 121 | 121 | if (under_load) { |
| 122 | 122 | last_under_load = ktime_get_coarse_boottime_ns(); |
| 123 | 123 | } else if (last_under_load) { |
| @@ -212,13 +212,14 @@ static void wg_receive_handshake_packet(struct wg_device *wg, · 88 unmodified lines | ||
| 212 | 212 | |
| 213 | 213 | void wg_packet_handshake_receive_worker(struct work_struct *work) |
| 214 | 214 | { |
| 215 | − struct wg_device *wg = container_of(work, struct multicore_worker, | |
| 216 | − work)->ptr; | |
| 215 | + struct crypt_queue *queue = container_of(work, struct multicore_worker, work)->ptr; | |
| 216 | + struct wg_device *wg = container_of(queue, struct wg_device, handshake_queue); | |
| 217 | 217 | struct sk_buff *skb; |
| 218 | 218 | |
| 219 | − while ((skb = skb_dequeue(&wg->incoming_handshakes)) != NULL) { | |
| 219 | + while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) { | |
| 220 | 220 | wg_receive_handshake_packet(wg, skb); |
| 221 | 221 | dev_kfree_skb(skb); |
| 222 | + atomic_dec(&wg->handshake_queue_len); | |
| 222 | 223 | cond_resched(); |
| 223 | 224 | } |
| 224 | 225 | } |
| @@ -553,22 +554,28 @@ void wg_packet_receive(struct wg_device *wg, struct sk_buff *skb) · 328 unmodified lines | ||
| 553 | 554 | case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION): |
| 554 | 555 | case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): |
| 555 | 556 | case cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE): { |
| 556 | − int cpu; | |
| 557 | − | |
| 558 | − if (skb_queue_len(&wg->incoming_handshakes) > | |
| 559 | − MAX_QUEUED_INCOMING_HANDSHAKES || | |
| 560 | − unlikely(!rng_is_initialized())) { | |
| 557 | + int cpu, ret = -EBUSY; | |
| 558 | + | |
| 559 | + if (unlikely(!rng_is_initialized())) | |
| 560 | + goto drop; | |
| 561 | + if (atomic_read(&wg->handshake_queue_len) > MAX_QUEUED_INCOMING_HANDSHAKES / 2) { | |
| 562 | + if (spin_trylock_bh(&wg->handshake_queue.ring.producer_lock)) { | |
| 563 | + ret = __ptr_ring_produce(&wg->handshake_queue.ring, skb); | |
| 564 | + spin_unlock_bh(&wg->handshake_queue.ring.producer_lock); | |
| 565 | + } | |
| 566 | + } else | |
| 567 | + ret = ptr_ring_produce_bh(&wg->handshake_queue.ring, skb); | |
| 568 | + if (ret) { | |
| 569 | + drop: | |
| 561 | 570 | net_dbg_skb_ratelimited("%s: Dropping handshake packet from %pISpfsc\n", |
| 562 | 571 | wg->dev->name, skb); |
| 563 | 572 | goto err; |
| 564 | 573 | } |
| 565 | − skb_queue_tail(&wg->incoming_handshakes, skb); | |
| 566 | − /* Queues up a call to packet_process_queued_handshake_ | |
| 567 | − * packets(skb): | |
| 568 | − */ | |
| 569 | − cpu = wg_cpumask_next_online(&wg->incoming_handshake_cpu); | |
| 574 | + atomic_inc(&wg->handshake_queue_len); | |
| 575 | + cpu = wg_cpumask_next_online(&wg->handshake_queue.last_cpu); | |
| 576 | + /* Queues up a call to packet_process_queued_handshake_packets(skb): */ | |
| 570 | 577 | queue_work_on(cpu, wg->handshake_receive_wq, |
| 571 | − &per_cpu_ptr(wg->incoming_handshakes_worker, cpu)->work); | |
| 578 | + &per_cpu_ptr(wg->handshake_queue.worker, cpu)->work); | |
| 572 | 579 | break; |
| 573 | 580 | } |
| 574 | 581 | case cpu_to_le32(MESSAGE_DATA): |
| @@ -308,7 +308,7 @@ void wg_socket_clear_peer_endpoint_src(struct wg_peer *peer) · 307 unmodified lines | ||
| 308 | 308 | { |
| 309 | 309 | write_lock_bh(&peer->endpoint_lock); |
| 310 | 310 | memset(&peer->endpoint.src6, 0, sizeof(peer->endpoint.src6)); |
| 311 | − dst_cache_reset(&peer->endpoint_cache); | |
| 311 | + dst_cache_reset_now(&peer->endpoint_cache); | |
| 312 | 312 | write_unlock_bh(&peer->endpoint_lock); |
| 313 | 313 | } |
| 314 | 314 | |
| @@ -533,7 +533,11 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, · 532 unmodified lines | ||
| 533 | 533 | ret = mhi_pm_suspend(ab_pci->mhi_ctrl); |
| 534 | 534 | break; |
| 535 | 535 | case ATH11K_MHI_RESUME: |
| 536 | − ret = mhi_pm_resume(ab_pci->mhi_ctrl); | |
| 536 | + /* Do force MHI resume as some devices like QCA6390, WCN6855 | |
| 537 | + * are not in M3 state but they are functional. So just ignore | |
| 538 | + * the MHI state while resuming. | |
| 539 | + */ | |
| 540 | + ret = mhi_pm_resume_force(ab_pci->mhi_ctrl); | |
| 537 | 541 | break; |
| 538 | 542 | case ATH11K_MHI_TRIGGER_RDDM: |
| 539 | 543 | ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); |
| @@ -86,6 +86,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, · 85 unmodified lines | ||
| 86 | 86 | if (len < tlv_len) { |
| 87 | 87 | IWL_ERR(trans, "invalid TLV len: %zd/%u\n", |
| 88 | 88 | len, tlv_len); |
| 89 | + kfree(reduce_power_data); | |
| 89 | 90 | reduce_power_data = ERR_PTR(-EINVAL); |
| 90 | 91 | goto out; |
| 91 | 92 | } |
| @@ -105,6 +106,7 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, · 13 unmodified lines | ||
| 105 | 106 | IWL_DEBUG_FW(trans, |
| 106 | 107 | "Couldn't allocate (more) reduce_power_data\n"); |
| 107 | 108 | |
| 109 | + kfree(reduce_power_data); | |
| 108 | 110 | reduce_power_data = ERR_PTR(-ENOMEM); |
| 109 | 111 | goto out; |
| 110 | 112 | } |
| @@ -134,6 +136,10 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, · 23 unmodified lines | ||
| 134 | 136 | done: |
| 135 | 137 | if (!size) { |
| 136 | 138 | IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); |
| 139 | + /* Better safe than sorry, but 'reduce_power_data' should | |
| 140 | + * always be NULL if !size. | |
| 141 | + */ | |
| 142 | + kfree(reduce_power_data); | |
| 137 | 143 | reduce_power_data = ERR_PTR(-ENOENT); |
| 138 | 144 | goto out; |
| 139 | 145 | } |
| @@ -1313,23 +1313,31 @@ _iwl_op_mode_start(struct iwl_drv *drv, struct iwlwifi_opmode_table *op) · 1312 unmodified lines | ||
| 1313 | 1313 | const struct iwl_op_mode_ops *ops = op->ops; |
| 1314 | 1314 | struct dentry *dbgfs_dir = NULL; |
| 1315 | 1315 | struct iwl_op_mode *op_mode = NULL; |
| 1316 | + int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY; | |
| 1317 | + | |
| 1318 | + for (retry = 0; retry <= max_retry; retry++) { | |
| 1316 | 1319 | |
| 1317 | 1320 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 1318 | − drv->dbgfs_op_mode = debugfs_create_dir(op->name, | |
| 1319 | − drv->dbgfs_drv); | |
| 1320 | − dbgfs_dir = drv->dbgfs_op_mode; | |
| 1321 | + drv->dbgfs_op_mode = debugfs_create_dir(op->name, | |
| 1322 | + drv->dbgfs_drv); | |
| 1323 | + dbgfs_dir = drv->dbgfs_op_mode; | |
| 1321 | 1324 | #endif |
| 1322 | 1325 | |
| 1323 | − op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir); | |
| 1326 | + op_mode = ops->start(drv->trans, drv->trans->cfg, | |
| 1327 | + &drv->fw, dbgfs_dir); | |
| 1328 | + | |
| 1329 | + if (op_mode) | |
| 1330 | + return op_mode; | |
| 1331 | + | |
| 1332 | + IWL_ERR(drv, "retry init count %d\n", retry); | |
| 1324 | 1333 | |
| 1325 | 1334 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
| 1326 | − if (!op_mode) { | |
| 1327 | 1335 | debugfs_remove_recursive(drv->dbgfs_op_mode); |
| 1328 | 1336 | drv->dbgfs_op_mode = NULL; |
| 1329 | − } | |
| 1330 | 1337 | #endif |
| 1338 | + } | |
| 1331 | 1339 | |
| 1332 | − return op_mode; | |
| 1340 | + return NULL; | |
| 1333 | 1341 | } |
| 1334 | 1342 | |
| 1335 | 1343 | static void _iwl_op_mode_stop(struct iwl_drv *drv) |
| @@ -89,4 +89,7 @@ void iwl_drv_stop(struct iwl_drv *drv); · 88 unmodified lines | ||
| 89 | 89 | #define IWL_EXPORT_SYMBOL(sym) |
| 90 | 90 | #endif |
| 91 | 91 | |
| 92 | +/* max retry for init flow */ | |
| 93 | +#define IWL_MAX_INIT_RETRY 2 | |
| 94 | + | |
| 92 | 95 | #endif /* __iwl_drv_h__ */ |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <net/ieee80211_radiotap.h> |
| 17 | 17 | #include <net/tcp.h> |
| 18 | 18 | |
| 19 | +#include "iwl-drv.h" | |
| 19 | 20 | #include "iwl-op-mode.h" |
| 20 | 21 | #include "iwl-io.h" |
| 21 | 22 | #include "mvm.h" |
| @@ -1117,9 +1118,30 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) · 1095 unmodified lines | ||
| 1117 | 1118 | { |
| 1118 | 1119 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
| 1119 | 1120 | int ret; |
| 1121 | + int retry, max_retry = 0; | |
| 1120 | 1122 | |
| 1121 | 1123 | mutex_lock(&mvm->mutex); |
| 1122 | − ret = __iwl_mvm_mac_start(mvm); | |
| 1124 | + | |
| 1125 | + /* we are starting the mac not in error flow, and restart is enabled */ | |
| 1126 | + if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) && | |
| 1127 | + iwlwifi_mod_params.fw_restart) { | |
| 1128 | + max_retry = IWL_MAX_INIT_RETRY; | |
| 1129 | + /* | |
| 1130 | + * This will prevent mac80211 recovery flows to trigger during | |
| 1131 | + * init failures | |
| 1132 | + */ | |
| 1133 | + set_bit(IWL_MVM_STATUS_STARTING, &mvm->status); | |
| 1134 | + } | |
| 1135 | + | |
| 1136 | + for (retry = 0; retry <= max_retry; retry++) { | |
| 1137 | + ret = __iwl_mvm_mac_start(mvm); | |
| 1138 | + if (!ret) | |
| 1139 | + break; | |
| 1140 | + | |
| 1141 | + IWL_ERR(mvm, "mac start retry %d\n", retry); | |
| 1142 | + } | |
| 1143 | + clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status); | |
| 1144 | + | |
| 1123 | 1145 | mutex_unlock(&mvm->mutex); |
| 1124 | 1146 | |
| 1125 | 1147 | return ret; |
| @@ -1123,6 +1123,8 @@ struct iwl_mvm { · 1122 unmodified lines | ||
| 1123 | 1123 | * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running |
| 1124 | 1124 | * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA |
| 1125 | 1125 | * @IWL_MVM_STATUS_IN_D3: in D3 (or at least about to go into it) |
| 1126 | + * @IWL_MVM_STATUS_STARTING: starting mac, | |
| 1127 | + * used to disable restart flow while in STARTING state | |
| 1126 | 1128 | */ |
| 1127 | 1129 | enum iwl_mvm_status { |
| 1128 | 1130 | IWL_MVM_STATUS_HW_RFKILL, |
| @@ -1134,6 +1136,7 @@ enum iwl_mvm_status { · 5 unmodified lines | ||
| 1134 | 1136 | IWL_MVM_STATUS_FIRMWARE_RUNNING, |
| 1135 | 1137 | IWL_MVM_STATUS_NEED_FLUSH_P2P, |
| 1136 | 1138 | IWL_MVM_STATUS_IN_D3, |
| 1139 | + IWL_MVM_STATUS_STARTING, | |
| 1137 | 1140 | }; |
| 1138 | 1141 | |
| 1139 | 1142 | /* Keep track of completed init configuration */ |
| @@ -686,6 +686,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) · 685 unmodified lines | ||
| 686 | 686 | int ret; |
| 687 | 687 | |
| 688 | 688 | rtnl_lock(); |
| 689 | + wiphy_lock(mvm->hw->wiphy); | |
| 689 | 690 | mutex_lock(&mvm->mutex); |
| 690 | 691 | |
| 691 | 692 | ret = iwl_run_init_mvm_ucode(mvm); |
| @@ -701,6 +702,7 @@ static int iwl_mvm_start_get_nvm(struct iwl_mvm *mvm) · 9 unmodified lines | ||
| 701 | 702 | iwl_mvm_stop_device(mvm); |
| 702 | 703 | |
| 703 | 704 | mutex_unlock(&mvm->mutex); |
| 705 | + wiphy_unlock(mvm->hw->wiphy); | |
| 704 | 706 | rtnl_unlock(); |
| 705 | 707 | |
| 706 | 708 | if (ret < 0) |
| @@ -1600,6 +1602,9 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) · 893 unmodified lines | ||
| 1600 | 1602 | */ |
| 1601 | 1603 | if (!mvm->fw_restart && fw_error) { |
| 1602 | 1604 | iwl_fw_error_collect(&mvm->fwrt, false); |
| 1605 | + } else if (test_bit(IWL_MVM_STATUS_STARTING, | |
| 1606 | + &mvm->status)) { | |
| 1607 | + IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n"); | |
| 1603 | 1608 | } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { |
| 1604 | 1609 | struct iwl_mvm_reprobe *reprobe; |
| 1605 | 1610 | |
| @@ -1339,9 +1339,13 @@ iwl_pci_find_dev_info(u16 device, u16 subsystem_device, · 1338 unmodified lines | ||
| 1339 | 1339 | u16 mac_type, u8 mac_step, |
| 1340 | 1340 | u16 rf_type, u8 cdb, u8 rf_id, u8 no_160, u8 cores) |
| 1341 | 1341 | { |
| 1342 | + int num_devices = ARRAY_SIZE(iwl_dev_info_table); | |
| 1342 | 1343 | int i; |
| 1343 | 1344 | |
| 1344 | − for (i = ARRAY_SIZE(iwl_dev_info_table) - 1; i >= 0; i--) { | |
| 1345 | + if (!num_devices) | |
| 1346 | + return NULL; | |
| 1347 | + | |
| 1348 | + for (i = num_devices - 1; i >= 0; i--) { | |
| 1345 | 1349 | const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i]; |
| 1346 | 1350 | |
| 1347 | 1351 | if (dev_info->device != (u16)IWL_CFG_ANY && |
| @@ -1442,8 +1446,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 94 unmodified lines | ||
| 1442 | 1446 | */ |
| 1443 | 1447 | if (iwl_trans->trans_cfg->rf_id && |
| 1444 | 1448 | iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 && |
| 1445 | − !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) | |
| 1449 | + !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans)) { | |
| 1450 | + ret = -EINVAL; | |
| 1446 | 1451 | goto out_free_trans; |
| 1452 | + } | |
| 1447 | 1453 | |
| 1448 | 1454 | dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device, |
| 1449 | 1455 | CSR_HW_REV_TYPE(iwl_trans->hw_rev), |
| @@ -143,8 +143,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 142 unmodified lines | ||
| 143 | 143 | if (!wcid) |
| 144 | 144 | wcid = &dev->mt76.global_wcid; |
| 145 | 145 | |
| 146 | − pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); | |
| 147 | − | |
| 148 | 146 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) { |
| 149 | 147 | struct mt7615_phy *phy = &dev->phy; |
| 150 | 148 | |
| @@ -164,6 +162,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 13 unmodified lines | ||
| 164 | 162 | if (id < 0) |
| 165 | 163 | return id; |
| 166 | 164 | |
| 165 | + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); | |
| 167 | 166 | mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta, |
| 168 | 167 | pid, key, false); |
| 169 | 168 | |
| @@ -43,19 +43,11 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_reg_map); · 42 unmodified lines | ||
| 43 | 43 | static void |
| 44 | 44 | mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid, |
| 45 | 45 | enum mt76_txq_id qid, struct ieee80211_sta *sta, |
| 46 | + struct ieee80211_key_conf *key, int pid, | |
| 46 | 47 | struct sk_buff *skb) |
| 47 | 48 | { |
| 48 | − struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | |
| 49 | − struct ieee80211_key_conf *key = info->control.hw_key; | |
| 50 | − __le32 *txwi; | |
| 51 | − int pid; | |
| 52 | − | |
| 53 | − if (!wcid) | |
| 54 | − wcid = &dev->mt76.global_wcid; | |
| 55 | − | |
| 56 | − pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); | |
| 49 | + __le32 *txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE); | |
| 57 | 50 | |
| 58 | − txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE); | |
| 59 | 51 | memset(txwi, 0, MT_USB_TXD_SIZE); |
| 60 | 52 | mt7615_mac_write_txwi(dev, txwi, skb, wcid, sta, pid, key, false); |
| 61 | 53 | skb_push(skb, MT_USB_TXD_SIZE); |
| @@ -194,10 +186,14 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 132 unmodified lines | ||
| 194 | 186 | struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); |
| 195 | 187 | struct sk_buff *skb = tx_info->skb; |
| 196 | 188 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 189 | + struct ieee80211_key_conf *key = info->control.hw_key; | |
| 197 | 190 | struct mt7615_sta *msta; |
| 198 | − int pad; | |
| 191 | + int pad, err, pktid; | |
| 199 | 192 | |
| 200 | 193 | msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL; |
| 194 | + if (!wcid) | |
| 195 | + wcid = &dev->mt76.global_wcid; | |
| 196 | + | |
| 201 | 197 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && |
| 202 | 198 | msta && !msta->rate_probe) { |
| 203 | 199 | /* request to configure sampling rate */ |
| @@ -207,7 +203,8 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 3 unmodified lines | ||
| 207 | 203 | spin_unlock_bh(&dev->mt76.lock); |
| 208 | 204 | } |
| 209 | 205 | |
| 210 | − mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, skb); | |
| 206 | + pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); | |
| 207 | + mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, key, pktid, skb); | |
| 211 | 208 | if (mt76_is_usb(mdev)) { |
| 212 | 209 | u32 len = skb->len; |
| 213 | 210 | |
| @@ -217,7 +214,12 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 3 unmodified lines | ||
| 217 | 214 | pad = round_up(skb->len, 4) - skb->len; |
| 218 | 215 | } |
| 219 | 216 | |
| 220 | − return mt76_skb_adjust_pad(skb, pad); | |
| 217 | + err = mt76_skb_adjust_pad(skb, pad); | |
| 218 | + if (err) | |
| 219 | + /* Release pktid in case of error. */ | |
| 220 | + idr_remove(&wcid->pktid, pktid); | |
| 221 | + | |
| 222 | + return err; | |
| 221 | 223 | } |
| 222 | 224 | EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb); |
| 223 | 225 | |
| @@ -72,6 +72,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, · 71 unmodified lines | ||
| 72 | 72 | bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU; |
| 73 | 73 | enum mt76_qsel qsel; |
| 74 | 74 | u32 flags; |
| 75 | + int err; | |
| 75 | 76 | |
| 76 | 77 | mt76_insert_hdr_pad(tx_info->skb); |
| 77 | 78 | |
| @@ -106,7 +107,12 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data, · 28 unmodified lines | ||
| 106 | 107 | ewma_pktlen_add(&msta->pktlen, tx_info->skb->len); |
| 107 | 108 | } |
| 108 | 109 | |
| 109 | − return mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags); | |
| 110 | + err = mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags); | |
| 111 | + if (err && wcid) | |
| 112 | + /* Release pktid in case of error. */ | |
| 113 | + idr_remove(&wcid->pktid, pid); | |
| 114 | + | |
| 115 | + return err; | |
| 110 | 116 | } |
| 111 | 117 | EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb); |
| 112 | 118 | |
| @@ -1151,8 +1151,14 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 1150 unmodified lines | ||
| 1151 | 1151 | } |
| 1152 | 1152 | } |
| 1153 | 1153 | |
| 1154 | − pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); | |
| 1154 | + t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); | |
| 1155 | + t->skb = tx_info->skb; | |
| 1156 | + | |
| 1157 | + id = mt76_token_consume(mdev, &t); | |
| 1158 | + if (id < 0) | |
| 1159 | + return id; | |
| 1155 | 1160 | |
| 1161 | + pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); | |
| 1156 | 1162 | mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key, |
| 1157 | 1163 | false); |
| 1158 | 1164 | |
| @@ -1178,13 +1184,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 19 unmodified lines | ||
| 1178 | 1184 | txp->bss_idx = mvif->idx; |
| 1179 | 1185 | } |
| 1180 | 1186 | |
| 1181 | − t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); | |
| 1182 | − t->skb = tx_info->skb; | |
| 1183 | − | |
| 1184 | − id = mt76_token_consume(mdev, &t); | |
| 1185 | − if (id < 0) | |
| 1186 | − return id; | |
| 1187 | − | |
| 1188 | 1187 | txp->token = cpu_to_le16(id); |
| 1189 | 1188 | if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) |
| 1190 | 1189 | txp->rept_wds_wcid = cpu_to_le16(wcid->idx); |
| @@ -176,7 +176,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) · 175 unmodified lines | ||
| 176 | 176 | if (ht_cap->ht_supported) |
| 177 | 177 | mode |= PHY_MODE_GN; |
| 178 | 178 | |
| 179 | − if (he_cap->has_he) | |
| 179 | + if (he_cap && he_cap->has_he) | |
| 180 | 180 | mode |= PHY_MODE_AX_24G; |
| 181 | 181 | } else if (band == NL80211_BAND_5GHZ) { |
| 182 | 182 | mode |= PHY_MODE_A; |
| @@ -187,7 +187,7 @@ mt7915_get_phy_mode(struct ieee80211_vif *vif, struct ieee80211_sta *sta) · 4 unmodified lines | ||
| 187 | 187 | if (vht_cap->vht_supported) |
| 188 | 188 | mode |= PHY_MODE_AC; |
| 189 | 189 | |
| 190 | − if (he_cap->has_he) | |
| 190 | + if (he_cap && he_cap->has_he) | |
| 191 | 191 | mode |= PHY_MODE_AX_5G; |
| 192 | 192 | } |
| 193 | 193 | |
| @@ -142,15 +142,11 @@ out: · 141 unmodified lines | ||
| 142 | 142 | static void |
| 143 | 143 | mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid, |
| 144 | 144 | enum mt76_txq_id qid, struct ieee80211_sta *sta, |
| 145 | + struct ieee80211_key_conf *key, int pid, | |
| 145 | 146 | struct sk_buff *skb) |
| 146 | 147 | { |
| 147 | − struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | |
| 148 | − struct ieee80211_key_conf *key = info->control.hw_key; | |
| 149 | − __le32 *txwi; | |
| 150 | − int pid; | |
| 148 | + __le32 *txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); | |
| 151 | 149 | |
| 152 | − pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); | |
| 153 | − txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE); | |
| 154 | 150 | memset(txwi, 0, MT_SDIO_TXD_SIZE); |
| 155 | 151 | mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false); |
| 156 | 152 | skb_push(skb, MT_SDIO_TXD_SIZE); |
| @@ -163,8 +159,9 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 6 unmodified lines | ||
| 163 | 159 | { |
| 164 | 160 | struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); |
| 165 | 161 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); |
| 162 | + struct ieee80211_key_conf *key = info->control.hw_key; | |
| 166 | 163 | struct sk_buff *skb = tx_info->skb; |
| 167 | − int pad; | |
| 164 | + int err, pad, pktid; | |
| 168 | 165 | |
| 169 | 166 | if (unlikely(tx_info->skb->len <= ETH_HLEN)) |
| 170 | 167 | return -EINVAL; |
| @@ -181,12 +178,18 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, · 10 unmodified lines | ||
| 181 | 178 | } |
| 182 | 179 | } |
| 183 | 180 | |
| 184 | − mt7921s_write_txwi(dev, wcid, qid, sta, skb); | |
| 181 | + pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb); | |
| 182 | + mt7921s_write_txwi(dev, wcid, qid, sta, key, pktid, skb); | |
| 185 | 183 | |
| 186 | 184 | mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA); |
| 187 | 185 | pad = round_up(skb->len, 4) - skb->len; |
| 188 | 186 | |
| 189 | − return mt76_skb_adjust_pad(skb, pad); | |
| 187 | + err = mt76_skb_adjust_pad(skb, pad); | |
| 188 | + if (err) | |
| 189 | + /* Release pktid in case of error. */ | |
| 190 | + idr_remove(&wcid->pktid, pktid); | |
| 191 | + | |
| 192 | + return err; | |
| 190 | 193 | } |
| 191 | 194 | |
| 192 | 195 | void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) |
| @@ -173,7 +173,7 @@ mt76_tx_status_skb_get(struct mt76_dev *dev, struct mt76_wcid *wcid, int pktid, · 172 unmodified lines | ||
| 173 | 173 | if (!(cb->flags & MT_TX_CB_DMA_DONE)) |
| 174 | 174 | continue; |
| 175 | 175 | |
| 176 | − if (!time_is_after_jiffies(cb->jiffies + | |
| 176 | + if (time_is_after_jiffies(cb->jiffies + | |
| 177 | 177 | MT_TX_STATUS_SKB_TIMEOUT)) |
| 178 | 178 | continue; |
| 179 | 179 | } |
| @@ -25,6 +25,9 @@ static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status) · 24 unmodified lines | ||
| 25 | 25 | if (status == -ENODEV || status == -ENOENT) |
| 26 | 26 | return true; |
| 27 | 27 | |
| 28 | + if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | |
| 29 | + return false; | |
| 30 | + | |
| 28 | 31 | if (status == -EPROTO || status == -ETIMEDOUT) |
| 29 | 32 | rt2x00dev->num_proto_errs++; |
| 30 | 33 | else |
| @@ -91,7 +91,6 @@ static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev, const u8 *fw, u32 len, · 90 unmodified lines | ||
| 91 | 91 | info->section_num = GET_FW_HDR_SEC_NUM(fw); |
| 92 | 92 | info->hdr_len = RTW89_FW_HDR_SIZE + |
| 93 | 93 | info->section_num * RTW89_FW_SECTION_HDR_SIZE; |
| 94 | − SET_FW_HDR_PART_SIZE(fw, FWDL_SECTION_PER_PKT_LEN); | |
| 95 | 94 | |
| 96 | 95 | bin = fw + info->hdr_len; |
| 97 | 96 | |
| @@ -275,6 +274,7 @@ static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev, const u8 *fw, u32 l · 177 unmodified lines | ||
| 275 | 274 | } |
| 276 | 275 | |
| 277 | 276 | skb_put_data(skb, fw, len); |
| 277 | + SET_FW_HDR_PART_SIZE(skb->data, FWDL_SECTION_PER_PKT_LEN); | |
| 278 | 278 | rtw89_h2c_pkt_set_hdr_fwdl(rtwdev, skb, FWCMD_TYPE_H2C, |
| 279 | 279 | H2C_CAT_MAC, H2C_CL_MAC_FWDL, |
| 280 | 280 | H2C_FUNC_MAC_FWHDR_DL, len); |
| @@ -282,8 +282,10 @@ struct rtw89_h2creg_sch_tx_en { · 281 unmodified lines | ||
| 282 | 282 | le32_get_bits(*((__le32 *)(fwhdr) + 6), GENMASK(15, 8)) |
| 283 | 283 | #define GET_FW_HDR_CMD_VERSERION(fwhdr) \ |
| 284 | 284 | le32_get_bits(*((__le32 *)(fwhdr) + 7), GENMASK(31, 24)) |
| 285 | −#define SET_FW_HDR_PART_SIZE(fwhdr, val) \ | |
| 286 | − le32p_replace_bits((__le32 *)(fwhdr) + 7, val, GENMASK(15, 0)) | |
| 285 | +static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val) | |
| 286 | +{ | |
| 287 | + le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0)); | |
| 288 | +} | |
| 287 | 289 | |
| 288 | 290 | #define SET_CTRL_INFO_MACID(table, val) \ |
| 289 | 291 | le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0)) |
| @@ -181,9 +181,9 @@ void ipc_imem_hrtimer_stop(struct hrtimer *hr_timer) · 180 unmodified lines | ||
| 181 | 181 | bool ipc_imem_ul_write_td(struct iosm_imem *ipc_imem) |
| 182 | 182 | { |
| 183 | 183 | struct ipc_mem_channel *channel; |
| 184 | + bool hpda_ctrl_pending = false; | |
| 184 | 185 | struct sk_buff_head *ul_list; |
| 185 | 186 | bool hpda_pending = false; |
| 186 | − bool forced_hpdu = false; | |
| 187 | 187 | struct ipc_pipe *pipe; |
| 188 | 188 | int i; |
| 189 | 189 | |
| @@ -200,15 +200,19 @@ bool ipc_imem_ul_write_td(struct iosm_imem *ipc_imem) · 10 unmodified lines | ||
| 200 | 200 | ul_list = &channel->ul_list; |
| 201 | 201 | |
| 202 | 202 | /* Fill the transfer descriptor with the uplink buffer info. */ |
| 203 | − hpda_pending |= ipc_protocol_ul_td_send(ipc_imem->ipc_protocol, | |
| 203 | + if (!ipc_imem_check_wwan_ips(channel)) { | |
| 204 | + hpda_ctrl_pending |= | |
| 205 | + ipc_protocol_ul_td_send(ipc_imem->ipc_protocol, | |
| 204 | 206 | pipe, ul_list); |
| 205 | − | |
| 206 | − /* forced HP update needed for non data channels */ | |
| 207 | − if (hpda_pending && !ipc_imem_check_wwan_ips(channel)) | |
| 208 | − forced_hpdu = true; | |
| 207 | + } else { | |
| 208 | + hpda_pending |= | |
| 209 | + ipc_protocol_ul_td_send(ipc_imem->ipc_protocol, | |
| 210 | + pipe, ul_list); | |
| 211 | + } | |
| 209 | 212 | } |
| 210 | 213 | |
| 211 | − if (forced_hpdu) { | |
| 214 | + /* forced HP update needed for non data channels */ | |
| 215 | + if (hpda_ctrl_pending) { | |
| 212 | 216 | hpda_pending = false; |
| 213 | 217 | ipc_protocol_doorbell_trigger(ipc_imem->ipc_protocol, |
| 214 | 218 | IPC_HP_UL_WRITE_TD); |
| @@ -527,6 +531,9 @@ static void ipc_imem_run_state_worker(struct work_struct *instance) · 312 unmodified lines | ||
| 527 | 531 | return; |
| 528 | 532 | } |
| 529 | 533 | |
| 534 | + if (test_and_clear_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag)) | |
| 535 | + ipc_devlink_deinit(ipc_imem->ipc_devlink); | |
| 536 | + | |
| 530 | 537 | if (!ipc_imem_setup_cp_mux_cap_init(ipc_imem, &mux_cfg)) |
| 531 | 538 | ipc_imem->mux = ipc_mux_init(&mux_cfg, ipc_imem); |
| 532 | 539 | |
| @@ -1167,7 +1174,7 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) · 634 unmodified lines | ||
| 1167 | 1174 | ipc_port_deinit(ipc_imem->ipc_port); |
| 1168 | 1175 | } |
| 1169 | 1176 | |
| 1170 | − if (ipc_imem->ipc_devlink) | |
| 1177 | + if (test_and_clear_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag)) | |
| 1171 | 1178 | ipc_devlink_deinit(ipc_imem->ipc_devlink); |
| 1172 | 1179 | |
| 1173 | 1180 | ipc_imem_device_ipc_uninit(ipc_imem); |
| @@ -1263,7 +1270,6 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, · 89 unmodified lines | ||
| 1263 | 1270 | |
| 1264 | 1271 | ipc_imem->pci_device_id = device_id; |
| 1265 | 1272 | |
| 1266 | − ipc_imem->ev_cdev_write_pending = false; | |
| 1267 | 1273 | ipc_imem->cp_version = 0; |
| 1268 | 1274 | ipc_imem->device_sleep = IPC_HOST_SLEEP_ENTER_SLEEP; |
| 1269 | 1275 | |
| @@ -1331,6 +1337,8 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, · 61 unmodified lines | ||
| 1331 | 1337 | |
| 1332 | 1338 | if (ipc_flash_link_establish(ipc_imem)) |
| 1333 | 1339 | goto devlink_channel_fail; |
| 1340 | + | |
| 1341 | + set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag); | |
| 1334 | 1342 | } |
| 1335 | 1343 | return ipc_imem; |
| 1336 | 1344 | devlink_channel_fail: |
| @@ -101,6 +101,7 @@ struct ipc_chnl_cfg; · 100 unmodified lines | ||
| 101 | 101 | #define IOSM_CHIP_INFO_SIZE_MAX 100 |
| 102 | 102 | |
| 103 | 103 | #define FULLY_FUNCTIONAL 0 |
| 104 | +#define IOSM_DEVLINK_INIT 1 | |
| 104 | 105 | |
| 105 | 106 | /* List of the supported UL/DL pipes. */ |
| 106 | 107 | enum ipc_mem_pipes { |
| @@ -335,8 +336,6 @@ enum ipc_phase { · 228 unmodified lines | ||
| 335 | 336 | * process the irq actions. |
| 336 | 337 | * @flag: Flag to monitor the state of driver |
| 337 | 338 | * @td_update_timer_suspended: if true then td update timer suspend |
| 338 | − * @ev_cdev_write_pending: 0 means inform the IPC tasklet to pass | |
| 339 | − * the accumulated uplink buffers to CP. | |
| 340 | 339 | * @ev_mux_net_transmit_pending:0 means inform the IPC tasklet to pass |
| 341 | 340 | * @reset_det_n: Reset detect flag |
| 342 | 341 | * @pcie_wake_n: Pcie wake flag |
| @@ -374,7 +373,6 @@ struct iosm_imem { · 31 unmodified lines | ||
| 374 | 373 | u8 ev_irq_pending[IPC_IRQ_VECTORS]; |
| 375 | 374 | unsigned long flag; |
| 376 | 375 | u8 td_update_timer_suspended:1, |
| 377 | − ev_cdev_write_pending:1, | |
| 378 | 376 | ev_mux_net_transmit_pending:1, |
| 379 | 377 | reset_det_n:1, |
| 380 | 378 | pcie_wake_n:1; |
| @@ -41,7 +41,6 @@ void ipc_imem_sys_wwan_close(struct iosm_imem *ipc_imem, int if_id, · 40 unmodified lines | ||
| 41 | 41 | static int ipc_imem_tq_cdev_write(struct iosm_imem *ipc_imem, int arg, |
| 42 | 42 | void *msg, size_t size) |
| 43 | 43 | { |
| 44 | − ipc_imem->ev_cdev_write_pending = false; | |
| 45 | 44 | ipc_imem_ul_send(ipc_imem); |
| 46 | 45 | |
| 47 | 46 | return 0; |
| @@ -50,11 +49,6 @@ static int ipc_imem_tq_cdev_write(struct iosm_imem *ipc_imem, int arg, · 2 unmodified lines | ||
| 50 | 49 | /* Through tasklet to do sio write. */ |
| 51 | 50 | static int ipc_imem_call_cdev_write(struct iosm_imem *ipc_imem) |
| 52 | 51 | { |
| 53 | − if (ipc_imem->ev_cdev_write_pending) | |
| 54 | − return -1; | |
| 55 | − | |
| 56 | − ipc_imem->ev_cdev_write_pending = true; | |
| 57 | − | |
| 58 | 52 | return ipc_task_queue_send_task(ipc_imem, ipc_imem_tq_cdev_write, 0, |
| 59 | 53 | NULL, 0, false); |
| 60 | 54 | } |
| @@ -450,6 +444,7 @@ void ipc_imem_sys_devlink_close(struct iosm_devlink *ipc_devlink) · 389 unmodified lines | ||
| 450 | 444 | /* Release the pipe resources */ |
| 451 | 445 | ipc_imem_pipe_cleanup(ipc_imem, &channel->ul_pipe); |
| 452 | 446 | ipc_imem_pipe_cleanup(ipc_imem, &channel->dl_pipe); |
| 447 | + ipc_imem->nr_of_channels--; | |
| 453 | 448 | } |
| 454 | 449 | |
| 455 | 450 | void ipc_imem_sys_devlink_notify_rx(struct iosm_devlink *ipc_devlink, |
| @@ -666,6 +666,7 @@ blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, · 665 unmodified lines | ||
| 666 | 666 | struct request *rq) |
| 667 | 667 | { |
| 668 | 668 | if (ctrl->state != NVME_CTRL_DELETING_NOIO && |
| 669 | + ctrl->state != NVME_CTRL_DELETING && | |
| 669 | 670 | ctrl->state != NVME_CTRL_DEAD && |
| 670 | 671 | !test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) && |
| 671 | 672 | !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) |
| @@ -1749,9 +1750,20 @@ static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) · 1077 unmodified lines | ||
| 1749 | 1750 | */ |
| 1750 | 1751 | if (WARN_ON_ONCE(!(id->flbas & NVME_NS_FLBAS_META_EXT))) |
| 1751 | 1752 | return -EINVAL; |
| 1752 | − if (ctrl->max_integrity_segments) | |
| 1753 | − ns->features |= | |
| 1754 | − (NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS); | |
| 1753 | + | |
| 1754 | + ns->features |= NVME_NS_EXT_LBAS; | |
| 1755 | + | |
| 1756 | + /* | |
| 1757 | + * The current fabrics transport drivers support namespace | |
| 1758 | + * metadata formats only if nvme_ns_has_pi() returns true. | |
| 1759 | + * Suppress support for all other formats so the namespace will | |
| 1760 | + * have a 0 capacity and not be usable through the block stack. | |
| 1761 | + * | |
| 1762 | + * Note, this check will need to be modified if any drivers | |
| 1763 | + * gain the ability to use other metadata formats. | |
| 1764 | + */ | |
| 1765 | + if (ctrl->max_integrity_segments && nvme_ns_has_pi(ns)) | |
| 1766 | + ns->features |= NVME_NS_METADATA_SUPPORTED; | |
| 1755 | 1767 | } else { |
| 1756 | 1768 | /* |
| 1757 | 1769 | * For PCIe controllers, we can't easily remap the separate |
| @@ -2696,8 +2708,9 @@ static bool nvme_validate_cntlid(struct nvme_subsystem *subsys, · 938 unmodified lines | ||
| 2696 | 2708 | |
| 2697 | 2709 | if (tmp->cntlid == ctrl->cntlid) { |
| 2698 | 2710 | dev_err(ctrl->device, |
| 2699 | − "Duplicate cntlid %u with %s, rejecting\n", | |
| 2700 | − ctrl->cntlid, dev_name(tmp->device)); | |
| 2711 | + "Duplicate cntlid %u with %s, subsys %s, rejecting\n", | |
| 2712 | + ctrl->cntlid, dev_name(tmp->device), | |
| 2713 | + subsys->subnqn); | |
| 2701 | 2714 | return false; |
| 2702 | 2715 | } |
| 2703 | 2716 | |
| @@ -866,7 +866,7 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) · 865 unmodified lines | ||
| 866 | 866 | } |
| 867 | 867 | if (ana_log_size > ctrl->ana_log_size) { |
| 868 | 868 | nvme_mpath_stop(ctrl); |
| 869 | − kfree(ctrl->ana_log_buf); | |
| 869 | + nvme_mpath_uninit(ctrl); | |
| 870 | 870 | ctrl->ana_log_buf = kmalloc(ana_log_size, GFP_KERNEL); |
| 871 | 871 | if (!ctrl->ana_log_buf) |
| 872 | 872 | return -ENOMEM; |
| @@ -886,4 +886,5 @@ void nvme_mpath_uninit(struct nvme_ctrl *ctrl) · 13 unmodified lines | ||
| 886 | 886 | { |
| 887 | 887 | kfree(ctrl->ana_log_buf); |
| 888 | 888 | ctrl->ana_log_buf = NULL; |
| 889 | + ctrl->ana_log_size = 0; | |
| 889 | 890 | } |
| @@ -709,7 +709,7 @@ static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, · 708 unmodified lines | ||
| 709 | 709 | return true; |
| 710 | 710 | if (ctrl->ops->flags & NVME_F_FABRICS && |
| 711 | 711 | ctrl->state == NVME_CTRL_DELETING) |
| 712 | − return true; | |
| 712 | + return queue_live; | |
| 713 | 713 | return __nvme_check_ready(ctrl, rq, queue_live); |
| 714 | 714 | } |
| 715 | 715 | int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, |
| @@ -166,7 +166,10 @@ static int nvme_zone_parse_entry(struct nvme_ns *ns, · 165 unmodified lines | ||
| 166 | 166 | zone.len = ns->zsze; |
| 167 | 167 | zone.capacity = nvme_lba_to_sect(ns, le64_to_cpu(entry->zcap)); |
| 168 | 168 | zone.start = nvme_lba_to_sect(ns, le64_to_cpu(entry->zslba)); |
| 169 | − zone.wp = nvme_lba_to_sect(ns, le64_to_cpu(entry->wp)); | |
| 169 | + if (zone.cond == BLK_ZONE_COND_FULL) | |
| 170 | + zone.wp = zone.start + zone.len; | |
| 171 | + else | |
| 172 | + zone.wp = nvme_lba_to_sect(ns, le64_to_cpu(entry->wp)); | |
| 170 | 173 | |
| 171 | 174 | return cb(&zone, idx, data); |
| 172 | 175 | } |
| @@ -922,7 +922,14 @@ static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue, · 921 unmodified lines | ||
| 922 | 922 | size_t data_len = le32_to_cpu(req->cmd->common.dptr.sgl.length); |
| 923 | 923 | int ret; |
| 924 | 924 | |
| 925 | − if (!nvme_is_write(cmd->req.cmd) || | |
| 925 | + /* | |
| 926 | + * This command has not been processed yet, hence we are trying to | |
| 927 | + * figure out if there is still pending data left to receive. If | |
| 928 | + * we don't, we can simply prepare for the next pdu and bail out, | |
| 929 | + * otherwise we will need to prepare a buffer and receive the | |
| 930 | + * stale data before continuing forward. | |
| 931 | + */ | |
| 932 | + if (!nvme_is_write(cmd->req.cmd) || !data_len || | |
| 926 | 933 | data_len > cmd->req.port->inline_data_size) { |
| 927 | 934 | nvmet_prepare_receive_pdu(queue); |
| 928 | 935 | return; |
| @@ -76,6 +76,26 @@ struct device_node *of_irq_find_parent(struct device_node *child) · 75 unmodified lines | ||
| 76 | 76 | } |
| 77 | 77 | EXPORT_SYMBOL_GPL(of_irq_find_parent); |
| 78 | 78 | |
| 79 | +/* | |
| 80 | + * These interrupt controllers abuse interrupt-map for unspeakable | |
| 81 | + * reasons and rely on the core code to *ignore* it (the drivers do | |
| 82 | + * their own parsing of the property). | |
| 83 | + * | |
| 84 | + * If you think of adding to the list for something *new*, think | |
| 85 | + * again. There is a high chance that you will be sent back to the | |
| 86 | + * drawing board. | |
| 87 | + */ | |
| 88 | +static const char * const of_irq_imap_abusers[] = { | |
| 89 | + "CBEA,platform-spider-pic", | |
| 90 | + "sti,platform-spider-pic", | |
| 91 | + "realtek,rtl-intc", | |
| 92 | + "fsl,ls1021a-extirq", | |
| 93 | + "fsl,ls1043a-extirq", | |
| 94 | + "fsl,ls1088a-extirq", | |
| 95 | + "renesas,rza1-irqc", | |
| 96 | + NULL, | |
| 97 | +}; | |
| 98 | + | |
| 79 | 99 | /** |
| 80 | 100 | * of_irq_parse_raw - Low level interrupt tree parsing |
| 81 | 101 | * @addr: address specifier (start of "reg" property of the device) in be32 format |
| @@ -159,12 +179,15 @@ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) · 77 unmodified lines | ||
| 159 | 179 | /* |
| 160 | 180 | * Now check if cursor is an interrupt-controller and |
| 161 | 181 | * if it is then we are done, unless there is an |
| 162 | − * interrupt-map which takes precedence. | |
| 182 | + * interrupt-map which takes precedence except on one | |
| 183 | + * of these broken platforms that want to parse | |
| 184 | + * interrupt-map themselves for $reason. | |
| 163 | 185 | */ |
| 164 | 186 | bool intc = of_property_read_bool(ipar, "interrupt-controller"); |
| 165 | 187 | |
| 166 | 188 | imap = of_get_property(ipar, "interrupt-map", &imaplen); |
| 167 | − if (imap == NULL && intc) { | |
| 189 | + if (intc && | |
| 190 | + (!imap || of_device_compatible_match(ipar, of_irq_imap_abusers))) { | |
| 168 | 191 | pr_debug(" -> got it !\n"); |
| 169 | 192 | return 0; |
| 170 | 193 | } |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/platform_device.h> |
| 20 | 20 | #include <linux/phy/phy.h> |
| 21 | 21 | #include <linux/regulator/consumer.h> |
| 22 | +#include <linux/module.h> | |
| 22 | 23 | |
| 23 | 24 | #include "pcie-designware.h" |
| 24 | 25 | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/pm_domain.h> |
| 19 | 19 | #include <linux/regmap.h> |
| 20 | 20 | #include <linux/reset.h> |
| 21 | +#include <linux/module.h> | |
| 21 | 22 | |
| 22 | 23 | #include "pcie-designware.h" |
| 23 | 24 | |
| @@ -32,7 +32,6 @@ · 31 unmodified lines | ||
| 32 | 32 | #define PCIE_CORE_DEV_ID_REG 0x0 |
| 33 | 33 | #define PCIE_CORE_CMD_STATUS_REG 0x4 |
| 34 | 34 | #define PCIE_CORE_DEV_REV_REG 0x8 |
| 35 | −#define PCIE_CORE_EXP_ROM_BAR_REG 0x30 | |
| 36 | 35 | #define PCIE_CORE_PCIEXP_CAP 0xc0 |
| 37 | 36 | #define PCIE_CORE_ERR_CAPCTL_REG 0x118 |
| 38 | 37 | #define PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX BIT(5) |
| @@ -774,10 +773,6 @@ advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge, · 735 unmodified lines | ||
| 774 | 773 | *value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG); |
| 775 | 774 | return PCI_BRIDGE_EMUL_HANDLED; |
| 776 | 775 | |
| 777 | − case PCI_ROM_ADDRESS1: | |
| 778 | − *value = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG); | |
| 779 | − return PCI_BRIDGE_EMUL_HANDLED; | |
| 780 | − | |
| 781 | 776 | case PCI_INTERRUPT_LINE: { |
| 782 | 777 | /* |
| 783 | 778 | * From the whole 32bit register we support reading from HW only |
| @@ -810,10 +805,6 @@ advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, · 26 unmodified lines | ||
| 810 | 805 | advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG); |
| 811 | 806 | break; |
| 812 | 807 | |
| 813 | − case PCI_ROM_ADDRESS1: | |
| 814 | − advk_writel(pcie, new, PCIE_CORE_EXP_ROM_BAR_REG); | |
| 815 | − break; | |
| 816 | − | |
| 817 | 808 | case PCI_INTERRUPT_LINE: |
| 818 | 809 | if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) { |
| 819 | 810 | u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG); |
| @@ -516,7 +516,7 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, · 515 unmodified lines | ||
| 516 | 516 | int ret, i; |
| 517 | 517 | |
| 518 | 518 | reset = gpiod_get_from_of_node(np, "reset-gpios", 0, |
| 519 | − GPIOD_OUT_LOW, "#PERST"); | |
| 519 | + GPIOD_OUT_LOW, "PERST#"); | |
| 520 | 520 | if (IS_ERR(reset)) |
| 521 | 521 | return PTR_ERR(reset); |
| 522 | 522 | |
| @@ -539,12 +539,22 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, · 16 unmodified lines | ||
| 539 | 539 | |
| 540 | 540 | rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK); |
| 541 | 541 | |
| 542 | + /* Assert PERST# before setting up the clock */ | |
| 543 | + gpiod_set_value(reset, 1); | |
| 544 | + | |
| 542 | 545 | ret = apple_pcie_setup_refclk(pcie, port); |
| 543 | 546 | if (ret < 0) |
| 544 | 547 | return ret; |
| 545 | 548 | |
| 549 | + /* The minimal Tperst-clk value is 100us (PCIe CEM r5.0, 2.9.2) */ | |
| 550 | + usleep_range(100, 200); | |
| 551 | + | |
| 552 | + /* Deassert PERST# */ | |
| 546 | 553 | rmw_set(PORT_PERST_OFF, port->base + PORT_PERST); |
| 547 | − gpiod_set_value(reset, 1); | |
| 554 | + gpiod_set_value(reset, 0); | |
| 555 | + | |
| 556 | + /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ | |
| 557 | + msleep(100); | |
| 548 | 558 | |
| 549 | 559 | ret = readl_relaxed_poll_timeout(port->base + PORT_STATUS, stat, |
| 550 | 560 | stat & PORT_STATUS_READY, 100, 250000); |
| @@ -757,8 +757,8 @@ static int hi3670_pcie_phy_get_resources(struct hi3670_pcie_phy *phy, · 756 unmodified lines | ||
| 757 | 757 | return PTR_ERR(phy->sysctrl); |
| 758 | 758 | |
| 759 | 759 | phy->pmctrl = syscon_regmap_lookup_by_compatible("hisilicon,hi3670-pmctrl"); |
| 760 | − if (IS_ERR(phy->sysctrl)) | |
| 761 | − return PTR_ERR(phy->sysctrl); | |
| 760 | + if (IS_ERR(phy->pmctrl)) | |
| 761 | + return PTR_ERR(phy->pmctrl); | |
| 762 | 762 | |
| 763 | 763 | /* clocks */ |
| 764 | 764 | phy->phy_ref_clk = devm_clk_get(dev, "phy_ref"); |
| @@ -82,9 +82,9 @@ · 81 unmodified lines | ||
| 82 | 82 | * struct mvebu_cp110_utmi - PHY driver data |
| 83 | 83 | * |
| 84 | 84 | * @regs: PHY registers |
| 85 | − * @syscom: Regmap with system controller registers | |
| 85 | + * @syscon: Regmap with system controller registers | |
| 86 | 86 | * @dev: device driver handle |
| 87 | − * @caps: PHY capabilities | |
| 87 | + * @ops: phy ops | |
| 88 | 88 | */ |
| 89 | 89 | struct mvebu_cp110_utmi { |
| 90 | 90 | void __iomem *regs; |
| @@ -127,12 +127,13 @@ struct phy_drvdata { · 126 unmodified lines | ||
| 127 | 127 | }; |
| 128 | 128 | |
| 129 | 129 | /** |
| 130 | − * Write register and read back masked value to confirm it is written | |
| 130 | + * usb_phy_write_readback() - Write register and read back masked value to | |
| 131 | + * confirm it is written | |
| 131 | 132 | * |
| 132 | − * @base - QCOM DWC3 PHY base virtual address. | |
| 133 | − * @offset - register offset. | |
| 134 | − * @mask - register bitmask specifying what should be updated | |
| 135 | − * @val - value to write. | |
| 133 | + * @phy_dwc3: QCOM DWC3 phy context | |
| 134 | + * @offset: register offset. | |
| 135 | + * @mask: register bitmask specifying what should be updated | |
| 136 | + * @val: value to write. | |
| 136 | 137 | */ |
| 137 | 138 | static inline void usb_phy_write_readback(struct usb_phy *phy_dwc3, |
| 138 | 139 | u32 offset, |
| @@ -171,11 +172,11 @@ static int wait_for_latch(void __iomem *addr) · 32 unmodified lines | ||
| 171 | 172 | } |
| 172 | 173 | |
| 173 | 174 | /** |
| 174 | − * Write SSPHY register | |
| 175 | + * usb_ss_write_phycreg() - Write SSPHY register | |
| 175 | 176 | * |
| 176 | − * @base - QCOM DWC3 PHY base virtual address. | |
| 177 | − * @addr - SSPHY address to write. | |
| 178 | − * @val - value to write. | |
| 177 | + * @phy_dwc3: QCOM DWC3 phy context | |
| 178 | + * @addr: SSPHY address to write. | |
| 179 | + * @val: value to write. | |
| 179 | 180 | */ |
| 180 | 181 | static int usb_ss_write_phycreg(struct usb_phy *phy_dwc3, |
| 181 | 182 | u32 addr, u32 val) |
| @@ -209,10 +210,11 @@ err_wait: · 27 unmodified lines | ||
| 209 | 210 | } |
| 210 | 211 | |
| 211 | 212 | /** |
| 212 | − * Read SSPHY register. | |
| 213 | + * usb_ss_read_phycreg() - Read SSPHY register. | |
| 213 | 214 | * |
| 214 | − * @base - QCOM DWC3 PHY base virtual address. | |
| 215 | − * @addr - SSPHY address to read. | |
| 215 | + * @phy_dwc3: QCOM DWC3 phy context | |
| 216 | + * @addr: SSPHY address to read. | |
| 217 | + * @val: pointer in which read is store. | |
| 216 | 218 | */ |
| 217 | 219 | static int usb_ss_read_phycreg(struct usb_phy *phy_dwc3, |
| 218 | 220 | u32 addr, u32 *val) |
| @@ -2973,6 +2973,9 @@ struct qmp_phy_combo_cfg { · 2972 unmodified lines | ||
| 2973 | 2973 | * @qmp: QMP phy to which this lane belongs |
| 2974 | 2974 | * @lane_rst: lane's reset controller |
| 2975 | 2975 | * @mode: current PHY mode |
| 2976 | + * @dp_aux_cfg: Display port aux config | |
| 2977 | + * @dp_opts: Display port optional config | |
| 2978 | + * @dp_clks: Display port clocks | |
| 2976 | 2979 | */ |
| 2977 | 2980 | struct qmp_phy { |
| 2978 | 2981 | struct phy *phy; |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | −/** | |
| 2 | +/* | |
| 3 | 3 | * Copyright (C) 2016 Linaro Ltd |
| 4 | 4 | */ |
| 5 | 5 | #include <linux/module.h> |
| @@ -478,7 +478,7 @@ static void stm32_usbphyc_phy_tuning(struct stm32_usbphyc *usbphyc, · 477 unmodified lines | ||
| 478 | 478 | if (!of_property_read_bool(np, "st,no-lsfs-fb-cap")) |
| 479 | 479 | usbphyc_phy->tune |= LFSCAPEN; |
| 480 | 480 | |
| 481 | − if (of_property_read_bool(np, "st,slow-hs-slew-rate")) | |
| 481 | + if (of_property_read_bool(np, "st,decrease-hs-slew-rate")) | |
| 482 | 482 | usbphyc_phy->tune |= HSDRVSLEW; |
| 483 | 483 | |
| 484 | 484 | ret = of_property_read_u32(np, "st,tune-hs-dc-level", &val); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/** | |
| 2 | +/* | |
| 3 | 3 | * PCIe SERDES driver for AM654x SoC |
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2018 - 2019 Texas Instruments Incorporated - http://www.ti.com/ |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | −/** | |
| 2 | +/* | |
| 3 | 3 | * Wrapper driver for SERDES used in J721E |
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ |
| @@ -89,9 +89,9 @@ static inline void omap_usb_writel(void __iomem *addr, unsigned int offset, · 88 unmodified lines | ||
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | /** |
| 92 | − * omap_usb2_set_comparator - links the comparator present in the system with | |
| 93 | − * this phy | |
| 94 | − * @comparator - the companion phy(comparator) for this phy | |
| 92 | + * omap_usb2_set_comparator() - links the comparator present in the system with this phy | |
| 93 | + * | |
| 94 | + * @comparator: the companion phy(comparator) for this phy | |
| 95 | 95 | * |
| 96 | 96 | * The phy companion driver should call this API passing the phy_companion |
| 97 | 97 | * filled with set_vbus and start_srp to be used by usb phy. |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | −/** | |
| 2 | +/* | |
| 3 | 3 | * tusb1210.c - TUSB1210 USB ULPI PHY driver |
| 4 | 4 | * |
| 5 | 5 | * Copyright (C) 2015 Intel Corporation |
| @@ -76,7 +76,7 @@ · 75 unmodified lines | ||
| 76 | 76 | #define AMD_CPU_ID_CZN AMD_CPU_ID_RN |
| 77 | 77 | #define AMD_CPU_ID_YC 0x14B5 |
| 78 | 78 | |
| 79 | −#define PMC_MSG_DELAY_MIN_US 100 | |
| 79 | +#define PMC_MSG_DELAY_MIN_US 50 | |
| 80 | 80 | #define RESPONSE_REGISTER_LOOP_MAX 20000 |
| 81 | 81 | |
| 82 | 82 | #define SOC_SUBSYSTEM_IP_MAX 12 |
| @@ -99,6 +99,13 @@ static const struct dmi_system_id button_array_table[] = { · 98 unmodified lines | ||
| 99 | 99 | DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Tablet Gen 2"), |
| 100 | 100 | }, |
| 101 | 101 | }, |
| 102 | + { | |
| 103 | + .ident = "Microsoft Surface Go 3", | |
| 104 | + .matches = { | |
| 105 | + DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), | |
| 106 | + DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"), | |
| 107 | + }, | |
| 108 | + }, | |
| 102 | 109 | { } |
| 103 | 110 | }; |
| 104 | 111 | |
| @@ -657,6 +657,18 @@ static int acpi_add(struct acpi_device *device) · 656 unmodified lines | ||
| 657 | 657 | if (product && strlen(product) > 4) |
| 658 | 658 | switch (product[4]) { |
| 659 | 659 | case '5': |
| 660 | + if (strlen(product) > 5) | |
| 661 | + switch (product[5]) { | |
| 662 | + case 'N': | |
| 663 | + year = 2021; | |
| 664 | + break; | |
| 665 | + case '0': | |
| 666 | + year = 2016; | |
| 667 | + break; | |
| 668 | + default: | |
| 669 | + year = 2022; | |
| 670 | + } | |
| 671 | + break; | |
| 660 | 672 | case '6': |
| 661 | 673 | year = 2016; |
| 662 | 674 | break; |
| @@ -3015,6 +3015,8 @@ static struct attribute *hotkey_attributes[] = { · 3014 unmodified lines | ||
| 3015 | 3015 | &dev_attr_hotkey_all_mask.attr, |
| 3016 | 3016 | &dev_attr_hotkey_adaptive_all_mask.attr, |
| 3017 | 3017 | &dev_attr_hotkey_recommended_mask.attr, |
| 3018 | + &dev_attr_hotkey_tablet_mode.attr, | |
| 3019 | + &dev_attr_hotkey_radio_sw.attr, | |
| 3018 | 3020 | #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL |
| 3019 | 3021 | &dev_attr_hotkey_source_mask.attr, |
| 3020 | 3022 | &dev_attr_hotkey_poll_freq.attr, |
| @@ -5726,11 +5728,11 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { · 2705 unmodified lines | ||
| 5726 | 5728 | "tpacpi::standby", |
| 5727 | 5729 | "tpacpi::dock_status1", |
| 5728 | 5730 | "tpacpi::dock_status2", |
| 5729 | − "tpacpi::unknown_led2", | |
| 5731 | + "tpacpi::lid_logo_dot", | |
| 5730 | 5732 | "tpacpi::unknown_led3", |
| 5731 | 5733 | "tpacpi::thinkvantage", |
| 5732 | 5734 | }; |
| 5733 | −#define TPACPI_SAFE_LEDS 0x1081U | |
| 5735 | +#define TPACPI_SAFE_LEDS 0x1481U | |
| 5734 | 5736 | |
| 5735 | 5737 | static inline bool tpacpi_is_led_restricted(const unsigned int led) |
| 5736 | 5738 | { |
| @@ -905,6 +905,16 @@ static const struct ts_dmi_data trekstor_primetab_t13b_data = { · 904 unmodified lines | ||
| 905 | 905 | .properties = trekstor_primetab_t13b_props, |
| 906 | 906 | }; |
| 907 | 907 | |
| 908 | +static const struct property_entry trekstor_surftab_duo_w1_props[] = { | |
| 909 | + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), | |
| 910 | + { } | |
| 911 | +}; | |
| 912 | + | |
| 913 | +static const struct ts_dmi_data trekstor_surftab_duo_w1_data = { | |
| 914 | + .acpi_name = "GDIX1001:00", | |
| 915 | + .properties = trekstor_surftab_duo_w1_props, | |
| 916 | +}; | |
| 917 | + | |
| 908 | 918 | static const struct property_entry trekstor_surftab_twin_10_1_props[] = { |
| 909 | 919 | PROPERTY_ENTRY_U32("touchscreen-min-x", 20), |
| 910 | 920 | PROPERTY_ENTRY_U32("touchscreen-min-y", 0), |
| @@ -1502,6 +1512,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 591 unmodified lines | ||
| 1502 | 1512 | DMI_MATCH(DMI_PRODUCT_NAME, "Primetab T13B"), |
| 1503 | 1513 | }, |
| 1504 | 1514 | }, |
| 1515 | + { | |
| 1516 | + /* TrekStor SurfTab duo W1 10.1 ST10432-10b */ | |
| 1517 | + .driver_data = (void *)&trekstor_surftab_duo_w1_data, | |
| 1518 | + .matches = { | |
| 1519 | + DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"), | |
| 1520 | + DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab duo W1 10.1 (VT4)"), | |
| 1521 | + }, | |
| 1522 | + }, | |
| 1505 | 1523 | { |
| 1506 | 1524 | /* TrekStor SurfTab twin 10.1 ST10432-8 */ |
| 1507 | 1525 | .driver_data = (void *)&trekstor_surftab_twin_10_1_data, |
| @@ -463,17 +463,12 @@ int dtpm_register(const char *name, struct dtpm *dtpm, struct dtpm *parent) · 462 unmodified lines | ||
| 463 | 463 | |
| 464 | 464 | static int __init init_dtpm(void) |
| 465 | 465 | { |
| 466 | − struct dtpm_descr *dtpm_descr; | |
| 467 | − | |
| 468 | 466 | pct = powercap_register_control_type(NULL, "dtpm", NULL); |
| 469 | 467 | if (IS_ERR(pct)) { |
| 470 | 468 | pr_err("Failed to register control type\n"); |
| 471 | 469 | return PTR_ERR(pct); |
| 472 | 470 | } |
| 473 | 471 | |
| 474 | − for_each_dtpm_table(dtpm_descr) | |
| 475 | − dtpm_descr->init(); | |
| 476 | − | |
| 477 | 472 | return 0; |
| 478 | 473 | } |
| 479 | 474 | late_initcall(init_dtpm); |
| @@ -5095,14 +5095,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, · 5094 unmodified lines | ||
| 5095 | 5095 | /* NPort Recovery mode or node is just allocated */ |
| 5096 | 5096 | if (!lpfc_nlp_not_used(ndlp)) { |
| 5097 | 5097 | /* A LOGO is completing and the node is in NPR state. |
| 5098 | − * If this a fabric node that cleared its transport | |
| 5099 | − * registration, release the rpi. | |
| 5098 | + * Just unregister the RPI because the node is still | |
| 5099 | + * required. | |
| 5100 | 5100 | */ |
| 5101 | − spin_lock_irq(&ndlp->lock); | |
| 5102 | − ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | |
| 5103 | − if (phba->sli_rev == LPFC_SLI_REV4) | |
| 5104 | − ndlp->nlp_flag |= NLP_RELEASE_RPI; | |
| 5105 | − spin_unlock_irq(&ndlp->lock); | |
| 5106 | 5101 | lpfc_unreg_rpi(vport, ndlp); |
| 5107 | 5102 | } else { |
| 5108 | 5103 | /* Indicate the node has already released, should |
| @@ -282,12 +282,12 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, · 281 unmodified lines | ||
| 282 | 282 | if (rc) { |
| 283 | 283 | pm8001_dbg(pm8001_ha, FAIL, |
| 284 | 284 | "pm8001_setup_irq failed [ret: %d]\n", rc); |
| 285 | − goto err_out_shost; | |
| 285 | + goto err_out; | |
| 286 | 286 | } |
| 287 | 287 | /* Request Interrupt */ |
| 288 | 288 | rc = pm8001_request_irq(pm8001_ha); |
| 289 | 289 | if (rc) |
| 290 | − goto err_out_shost; | |
| 290 | + goto err_out; | |
| 291 | 291 | |
| 292 | 292 | count = pm8001_ha->max_q_num; |
| 293 | 293 | /* Queues are chosen based on the number of cores/msix availability */ |
| @@ -423,8 +423,6 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, · 129 unmodified lines | ||
| 423 | 423 | pm8001_tag_init(pm8001_ha); |
| 424 | 424 | return 0; |
| 425 | 425 | |
| 426 | −err_out_shost: | |
| 427 | − scsi_remove_host(pm8001_ha->shost); | |
| 428 | 426 | err_out_nodev: |
| 429 | 427 | for (i = 0; i < pm8001_ha->max_memcnt; i++) { |
| 430 | 428 | if (pm8001_ha->memoryMap.region[i].virt_ptr != NULL) { |
| @@ -732,7 +732,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, · 731 unmodified lines | ||
| 732 | 732 | { |
| 733 | 733 | struct qedi_work_map *work, *work_tmp; |
| 734 | 734 | u32 proto_itt = cqe->itid; |
| 735 | − itt_t protoitt = 0; | |
| 736 | 735 | int found = 0; |
| 737 | 736 | struct qedi_cmd *qedi_cmd = NULL; |
| 738 | 737 | u32 iscsi_cid; |
| @@ -812,16 +811,12 @@ unlock: · 73 unmodified lines | ||
| 812 | 811 | return; |
| 813 | 812 | |
| 814 | 813 | check_cleanup_reqs: |
| 815 | − if (qedi_conn->cmd_cleanup_req > 0) { | |
| 816 | − QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_TID, | |
| 814 | + if (atomic_inc_return(&qedi_conn->cmd_cleanup_cmpl) == | |
| 815 | + qedi_conn->cmd_cleanup_req) { | |
| 816 | + QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_SCSI_TM, | |
| 817 | 817 | "Freeing tid=0x%x for cid=0x%x\n", |
| 818 | 818 | cqe->itid, qedi_conn->iscsi_conn_id); |
| 819 | − qedi_conn->cmd_cleanup_cmpl++; | |
| 820 | 819 | wake_up(&qedi_conn->wait_queue); |
| 821 | − } else { | |
| 822 | − QEDI_ERR(&qedi->dbg_ctx, | |
| 823 | − "Delayed or untracked cleanup response, itt=0x%x, tid=0x%x, cid=0x%x\n", | |
| 824 | − protoitt, cqe->itid, qedi_conn->iscsi_conn_id); | |
| 825 | 820 | } |
| 826 | 821 | } |
| 827 | 822 | |
| @@ -1163,7 +1158,7 @@ int qedi_cleanup_all_io(struct qedi_ctx *qedi, struct qedi_conn *qedi_conn, · 335 unmodified lines | ||
| 1163 | 1158 | } |
| 1164 | 1159 | |
| 1165 | 1160 | qedi_conn->cmd_cleanup_req = 0; |
| 1166 | − qedi_conn->cmd_cleanup_cmpl = 0; | |
| 1161 | + atomic_set(&qedi_conn->cmd_cleanup_cmpl, 0); | |
| 1167 | 1162 | |
| 1168 | 1163 | QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_SCSI_TM, |
| 1169 | 1164 | "active_cmd_count=%d, cid=0x%x, in_recovery=%d, lun_reset=%d\n", |
| @@ -1215,16 +1210,15 @@ int qedi_cleanup_all_io(struct qedi_ctx *qedi, struct qedi_conn *qedi_conn, · 45 unmodified lines | ||
| 1215 | 1210 | qedi_conn->iscsi_conn_id); |
| 1216 | 1211 | |
| 1217 | 1212 | rval = wait_event_interruptible_timeout(qedi_conn->wait_queue, |
| 1218 | − ((qedi_conn->cmd_cleanup_req == | |
| 1219 | − qedi_conn->cmd_cleanup_cmpl) || | |
| 1220 | − test_bit(QEDI_IN_RECOVERY, | |
| 1221 | − &qedi->flags)), | |
| 1222 | − 5 * HZ); | |
| 1213 | + (qedi_conn->cmd_cleanup_req == | |
| 1214 | + atomic_read(&qedi_conn->cmd_cleanup_cmpl)) || | |
| 1215 | + test_bit(QEDI_IN_RECOVERY, &qedi->flags), | |
| 1216 | + 5 * HZ); | |
| 1223 | 1217 | if (rval) { |
| 1224 | 1218 | QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_SCSI_TM, |
| 1225 | 1219 | "i/o cmd_cleanup_req=%d, equal to cmd_cleanup_cmpl=%d, cid=0x%x\n", |
| 1226 | 1220 | qedi_conn->cmd_cleanup_req, |
| 1227 | − qedi_conn->cmd_cleanup_cmpl, | |
| 1221 | + atomic_read(&qedi_conn->cmd_cleanup_cmpl), | |
| 1228 | 1222 | qedi_conn->iscsi_conn_id); |
| 1229 | 1223 | |
| 1230 | 1224 | return 0; |
| @@ -1233,7 +1227,7 @@ int qedi_cleanup_all_io(struct qedi_ctx *qedi, struct qedi_conn *qedi_conn, · 2 unmodified lines | ||
| 1233 | 1227 | QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_SCSI_TM, |
| 1234 | 1228 | "i/o cmd_cleanup_req=%d, not equal to cmd_cleanup_cmpl=%d, cid=0x%x\n", |
| 1235 | 1229 | qedi_conn->cmd_cleanup_req, |
| 1236 | − qedi_conn->cmd_cleanup_cmpl, | |
| 1230 | + atomic_read(&qedi_conn->cmd_cleanup_cmpl), | |
| 1237 | 1231 | qedi_conn->iscsi_conn_id); |
| 1238 | 1232 | |
| 1239 | 1233 | iscsi_host_for_each_session(qedi->shost, |
| @@ -1242,11 +1236,10 @@ int qedi_cleanup_all_io(struct qedi_ctx *qedi, struct qedi_conn *qedi_conn, · 2 unmodified lines | ||
| 1242 | 1236 | |
| 1243 | 1237 | /* Enable IOs for all other sessions except current.*/ |
| 1244 | 1238 | if (!wait_event_interruptible_timeout(qedi_conn->wait_queue, |
| 1245 | − (qedi_conn->cmd_cleanup_req == | |
| 1246 | − qedi_conn->cmd_cleanup_cmpl) || | |
| 1247 | − test_bit(QEDI_IN_RECOVERY, | |
| 1248 | − &qedi->flags), | |
| 1249 | − 5 * HZ)) { | |
| 1239 | + (qedi_conn->cmd_cleanup_req == | |
| 1240 | + atomic_read(&qedi_conn->cmd_cleanup_cmpl)) || | |
| 1241 | + test_bit(QEDI_IN_RECOVERY, &qedi->flags), | |
| 1242 | + 5 * HZ)) { | |
| 1250 | 1243 | iscsi_host_for_each_session(qedi->shost, |
| 1251 | 1244 | qedi_mark_device_available); |
| 1252 | 1245 | return -1; |
| @@ -1266,7 +1259,7 @@ void qedi_clearsq(struct qedi_ctx *qedi, struct qedi_conn *qedi_conn, · 13 unmodified lines | ||
| 1266 | 1259 | |
| 1267 | 1260 | qedi_ep = qedi_conn->ep; |
| 1268 | 1261 | qedi_conn->cmd_cleanup_req = 0; |
| 1269 | − qedi_conn->cmd_cleanup_cmpl = 0; | |
| 1262 | + atomic_set(&qedi_conn->cmd_cleanup_cmpl, 0); | |
| 1270 | 1263 | |
| 1271 | 1264 | if (!qedi_ep) { |
| 1272 | 1265 | QEDI_WARN(&qedi->dbg_ctx, |
| @@ -412,7 +412,7 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session, · 411 unmodified lines | ||
| 412 | 412 | qedi_conn->iscsi_conn_id = qedi_ep->iscsi_cid; |
| 413 | 413 | qedi_conn->fw_cid = qedi_ep->fw_cid; |
| 414 | 414 | qedi_conn->cmd_cleanup_req = 0; |
| 415 | − qedi_conn->cmd_cleanup_cmpl = 0; | |
| 415 | + atomic_set(&qedi_conn->cmd_cleanup_cmpl, 0); | |
| 416 | 416 | |
| 417 | 417 | if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn)) { |
| 418 | 418 | rc = -EINVAL; |
| @@ -155,7 +155,7 @@ struct qedi_conn { · 154 unmodified lines | ||
| 155 | 155 | spinlock_t list_lock; /* internal conn lock */ |
| 156 | 156 | u32 active_cmd_count; |
| 157 | 157 | u32 cmd_cleanup_req; |
| 158 | − u32 cmd_cleanup_cmpl; | |
| 158 | + atomic_t cmd_cleanup_cmpl; | |
| 159 | 159 | |
| 160 | 160 | u32 iscsi_conn_id; |
| 161 | 161 | int itt; |
| @@ -2491,6 +2491,9 @@ ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...) · 2490 unmodified lines | ||
| 2491 | 2491 | struct va_format vaf; |
| 2492 | 2492 | char pbuf[64]; |
| 2493 | 2493 | |
| 2494 | + if (!ql_mask_match(level) && !trace_ql_dbg_log_enabled()) | |
| 2495 | + return; | |
| 2496 | + | |
| 2494 | 2497 | va_start(va, fmt); |
| 2495 | 2498 | |
| 2496 | 2499 | vaf.fmt = fmt; |
| @@ -4342,7 +4342,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, · 4341 unmodified lines | ||
| 4342 | 4342 | rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD), |
| 4343 | 4343 | max_zones); |
| 4344 | 4344 | |
| 4345 | − arr = kcalloc(RZONES_DESC_HD, alloc_len, GFP_ATOMIC); | |
| 4345 | + arr = kzalloc(alloc_len, GFP_ATOMIC); | |
| 4346 | 4346 | if (!arr) { |
| 4347 | 4347 | mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, |
| 4348 | 4348 | INSUFF_RES_ASCQ); |
| @@ -421,6 +421,13 @@ static int ufs_intel_lkf_init(struct ufs_hba *hba) · 420 unmodified lines | ||
| 421 | 421 | return err; |
| 422 | 422 | } |
| 423 | 423 | |
| 424 | +static int ufs_intel_adl_init(struct ufs_hba *hba) | |
| 425 | +{ | |
| 426 | + hba->nop_out_timeout = 200; | |
| 427 | + hba->quirks |= UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8; | |
| 428 | + return ufs_intel_common_init(hba); | |
| 429 | +} | |
| 430 | + | |
| 424 | 431 | static struct ufs_hba_variant_ops ufs_intel_cnl_hba_vops = { |
| 425 | 432 | .name = "intel-pci", |
| 426 | 433 | .init = ufs_intel_common_init, |
| @@ -449,6 +456,15 @@ static struct ufs_hba_variant_ops ufs_intel_lkf_hba_vops = { · 22 unmodified lines | ||
| 449 | 456 | .device_reset = ufs_intel_device_reset, |
| 450 | 457 | }; |
| 451 | 458 | |
| 459 | +static struct ufs_hba_variant_ops ufs_intel_adl_hba_vops = { | |
| 460 | + .name = "intel-pci", | |
| 461 | + .init = ufs_intel_adl_init, | |
| 462 | + .exit = ufs_intel_common_exit, | |
| 463 | + .link_startup_notify = ufs_intel_link_startup_notify, | |
| 464 | + .resume = ufs_intel_resume, | |
| 465 | + .device_reset = ufs_intel_device_reset, | |
| 466 | +}; | |
| 467 | + | |
| 452 | 468 | #ifdef CONFIG_PM_SLEEP |
| 453 | 469 | static int ufshcd_pci_restore(struct device *dev) |
| 454 | 470 | { |
| @@ -563,6 +579,8 @@ static const struct pci_device_id ufshcd_pci_tbl[] = { · 108 unmodified lines | ||
| 563 | 579 | { PCI_VDEVICE(INTEL, 0x4B41), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, |
| 564 | 580 | { PCI_VDEVICE(INTEL, 0x4B43), (kernel_ulong_t)&ufs_intel_ehl_hba_vops }, |
| 565 | 581 | { PCI_VDEVICE(INTEL, 0x98FA), (kernel_ulong_t)&ufs_intel_lkf_hba_vops }, |
| 582 | + { PCI_VDEVICE(INTEL, 0x51FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, | |
| 583 | + { PCI_VDEVICE(INTEL, 0x54FF), (kernel_ulong_t)&ufs_intel_adl_hba_vops }, | |
| 566 | 584 | { } /* terminate list */ |
| 567 | 585 | }; |
| 568 | 586 | |
| @@ -29,7 +29,7 @@ static const char * const fivr_strings[] = { · 28 unmodified lines | ||
| 29 | 29 | }; |
| 30 | 30 | |
| 31 | 31 | static const struct mmio_reg tgl_fivr_mmio_regs[] = { |
| 32 | − { 0, 0x5A18, 3, 0x7, 12}, /* vco_ref_code_lo */ | |
| 32 | + { 0, 0x5A18, 3, 0x7, 11}, /* vco_ref_code_lo */ | |
| 33 | 33 | { 0, 0x5A18, 8, 0xFF, 16}, /* vco_ref_code_hi */ |
| 34 | 34 | { 0, 0x5A08, 8, 0xFF, 0}, /* spread_spectrum_pct */ |
| 35 | 35 | { 0, 0x5A08, 1, 0x1, 8}, /* spread_spectrum_clk_enable */ |
| @@ -237,6 +237,7 @@ struct brcmuart_priv { · 236 unmodified lines | ||
| 237 | 237 | u32 rx_err; |
| 238 | 238 | u32 rx_timeout; |
| 239 | 239 | u32 rx_abort; |
| 240 | + u32 saved_mctrl; | |
| 240 | 241 | }; |
| 241 | 242 | |
| 242 | 243 | static struct dentry *brcmuart_debugfs_root; |
| @@ -1133,16 +1134,27 @@ static int brcmuart_remove(struct platform_device *pdev) · 890 unmodified lines | ||
| 1133 | 1134 | static int __maybe_unused brcmuart_suspend(struct device *dev) |
| 1134 | 1135 | { |
| 1135 | 1136 | struct brcmuart_priv *priv = dev_get_drvdata(dev); |
| 1137 | + struct uart_8250_port *up = serial8250_get_port(priv->line); | |
| 1138 | + struct uart_port *port = &up->port; | |
| 1136 | 1139 | |
| 1137 | 1140 | serial8250_suspend_port(priv->line); |
| 1138 | 1141 | clk_disable_unprepare(priv->baud_mux_clk); |
| 1139 | 1142 | |
| 1143 | + /* | |
| 1144 | + * This will prevent resume from enabling RTS before the | |
| 1145 | + * baud rate has been resored. | |
| 1146 | + */ | |
| 1147 | + priv->saved_mctrl = port->mctrl; | |
| 1148 | + port->mctrl = 0; | |
| 1149 | + | |
| 1140 | 1150 | return 0; |
| 1141 | 1151 | } |
| 1142 | 1152 | |
| 1143 | 1153 | static int __maybe_unused brcmuart_resume(struct device *dev) |
| 1144 | 1154 | { |
| 1145 | 1155 | struct brcmuart_priv *priv = dev_get_drvdata(dev); |
| 1156 | + struct uart_8250_port *up = serial8250_get_port(priv->line); | |
| 1157 | + struct uart_port *port = &up->port; | |
| 1146 | 1158 | int ret; |
| 1147 | 1159 | |
| 1148 | 1160 | ret = clk_prepare_enable(priv->baud_mux_clk); |
| @@ -1165,6 +1177,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev) · 16 unmodified lines | ||
| 1165 | 1177 | start_rx_dma(serial8250_get_port(priv->line)); |
| 1166 | 1178 | } |
| 1167 | 1179 | serial8250_resume_port(priv->line); |
| 1180 | + port->mctrl = priv->saved_mctrl; | |
| 1168 | 1181 | return 0; |
| 1169 | 1182 | } |
| 1170 | 1183 | |
| @@ -1324,29 +1324,33 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud, · 1323 unmodified lines | ||
| 1324 | 1324 | { |
| 1325 | 1325 | int scr; |
| 1326 | 1326 | int lcr; |
| 1327 | − int actual_baud; | |
| 1328 | − int tolerance; | |
| 1329 | 1327 | |
| 1330 | − for (scr = 5 ; scr <= 15 ; scr++) { | |
| 1331 | − actual_baud = 921600 * 16 / scr; | |
| 1332 | − tolerance = actual_baud / 50; | |
| 1328 | + for (scr = 16; scr > 4; scr--) { | |
| 1329 | + unsigned int maxrate = port->uartclk / scr; | |
| 1330 | + unsigned int divisor = max(maxrate / baud, 1U); | |
| 1331 | + int delta = maxrate / divisor - baud; | |
| 1333 | 1332 | |
| 1334 | − if ((baud < actual_baud + tolerance) && | |
| 1335 | − (baud > actual_baud - tolerance)) { | |
| 1333 | + if (baud > maxrate + baud / 50) | |
| 1334 | + continue; | |
| 1336 | 1335 | |
| 1336 | + if (delta > baud / 50) | |
| 1337 | + divisor++; | |
| 1338 | + | |
| 1339 | + if (divisor > 0xffff) | |
| 1340 | + continue; | |
| 1341 | + | |
| 1342 | + /* Update delta due to possible divisor change */ | |
| 1343 | + delta = maxrate / divisor - baud; | |
| 1344 | + if (abs(delta) < baud / 50) { | |
| 1337 | 1345 | lcr = serial_port_in(port, UART_LCR); |
| 1338 | 1346 | serial_port_out(port, UART_LCR, lcr | 0x80); |
| 1339 | − | |
| 1340 | − serial_port_out(port, UART_DLL, 1); | |
| 1341 | − serial_port_out(port, UART_DLM, 0); | |
| 1347 | + serial_port_out(port, UART_DLL, divisor & 0xff); | |
| 1348 | + serial_port_out(port, UART_DLM, divisor >> 8 & 0xff); | |
| 1342 | 1349 | serial_port_out(port, 2, 16 - scr); |
| 1343 | 1350 | serial_port_out(port, UART_LCR, lcr); |
| 1344 | 1351 | return; |
| 1345 | − } else if (baud > actual_baud) { | |
| 1346 | − break; | |
| 1347 | 1352 | } |
| 1348 | 1353 | } |
| 1349 | − serial8250_do_set_divisor(port, baud, quot, quot_frac); | |
| 1350 | 1354 | } |
| 1351 | 1355 | static int pci_pericom_setup(struct serial_private *priv, |
| 1352 | 1356 | const struct pciserial_board *board, |
| @@ -2291,12 +2295,19 @@ static struct pci_serial_quirk pci_serial_quirks[] = { · 938 unmodified lines | ||
| 2291 | 2295 | .setup = pci_pericom_setup_four_at_eight, |
| 2292 | 2296 | }, |
| 2293 | 2297 | { |
| 2294 | − .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, | |
| 2298 | + .vendor = PCI_VENDOR_ID_ACCESIO, | |
| 2295 | 2299 | .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, |
| 2296 | 2300 | .subvendor = PCI_ANY_ID, |
| 2297 | 2301 | .subdevice = PCI_ANY_ID, |
| 2298 | 2302 | .setup = pci_pericom_setup_four_at_eight, |
| 2299 | 2303 | }, |
| 2304 | + { | |
| 2305 | + .vendor = PCI_VENDOR_ID_ACCESIO, | |
| 2306 | + .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, | |
| 2307 | + .subvendor = PCI_ANY_ID, | |
| 2308 | + .subdevice = PCI_ANY_ID, | |
| 2309 | + .setup = pci_pericom_setup_four_at_eight, | |
| 2310 | + }, | |
| 2300 | 2311 | { |
| 2301 | 2312 | .vendor = PCI_VENDOR_ID_ACCESIO, |
| 2302 | 2313 | .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, |
| @@ -2024,13 +2024,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) · 2023 unmodified lines | ||
| 2024 | 2024 | struct uart_8250_port *up = up_to_u8250p(port); |
| 2025 | 2025 | unsigned char mcr; |
| 2026 | 2026 | |
| 2027 | − if (port->rs485.flags & SER_RS485_ENABLED) { | |
| 2028 | − if (serial8250_in_MCR(up) & UART_MCR_RTS) | |
| 2029 | − mctrl |= TIOCM_RTS; | |
| 2030 | − else | |
| 2031 | − mctrl &= ~TIOCM_RTS; | |
| 2032 | − } | |
| 2033 | − | |
| 2034 | 2027 | mcr = serial8250_TIOCM_to_MCR(mctrl); |
| 2035 | 2028 | |
| 2036 | 2029 | mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; |
| @@ -1533,7 +1533,7 @@ config SERIAL_LITEUART · 1532 unmodified lines | ||
| 1533 | 1533 | tristate "LiteUART serial port support" |
| 1534 | 1534 | depends on HAS_IOMEM |
| 1535 | 1535 | depends on OF || COMPILE_TEST |
| 1536 | − depends on LITEX | |
| 1536 | + depends on LITEX || COMPILE_TEST | |
| 1537 | 1537 | select SERIAL_CORE |
| 1538 | 1538 | help |
| 1539 | 1539 | This driver is for the FPGA-based LiteUART serial controller from LiteX |
| @@ -2947,6 +2947,7 @@ MODULE_DEVICE_TABLE(of, sbsa_uart_of_match); · 2946 unmodified lines | ||
| 2947 | 2947 | |
| 2948 | 2948 | static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = { |
| 2949 | 2949 | { "ARMH0011", 0 }, |
| 2950 | + { "ARMHB000", 0 }, | |
| 2950 | 2951 | {}, |
| 2951 | 2952 | }; |
| 2952 | 2953 | MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match); |
| @@ -2625,6 +2625,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup); · 2624 unmodified lines | ||
| 2625 | 2625 | OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); |
| 2626 | 2626 | OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); |
| 2627 | 2627 | OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); |
| 2628 | +OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup); | |
| 2628 | 2629 | EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); |
| 2629 | 2630 | EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); |
| 2630 | 2631 | |
| @@ -270,8 +270,10 @@ static int liteuart_probe(struct platform_device *pdev) · 269 unmodified lines | ||
| 270 | 270 | |
| 271 | 271 | /* get membase */ |
| 272 | 272 | port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); |
| 273 | − if (IS_ERR(port->membase)) | |
| 274 | − return PTR_ERR(port->membase); | |
| 273 | + if (IS_ERR(port->membase)) { | |
| 274 | + ret = PTR_ERR(port->membase); | |
| 275 | + goto err_erase_id; | |
| 276 | + } | |
| 275 | 277 | |
| 276 | 278 | /* values not from device tree */ |
| 277 | 279 | port->dev = &pdev->dev; |
| @@ -285,7 +287,18 @@ static int liteuart_probe(struct platform_device *pdev) · 7 unmodified lines | ||
| 285 | 287 | port->line = dev_id; |
| 286 | 288 | spin_lock_init(&port->lock); |
| 287 | 289 | |
| 288 | − return uart_add_one_port(&liteuart_driver, &uart->port); | |
| 290 | + platform_set_drvdata(pdev, port); | |
| 291 | + | |
| 292 | + ret = uart_add_one_port(&liteuart_driver, &uart->port); | |
| 293 | + if (ret) | |
| 294 | + goto err_erase_id; | |
| 295 | + | |
| 296 | + return 0; | |
| 297 | + | |
| 298 | +err_erase_id: | |
| 299 | + xa_erase(&liteuart_array, uart->id); | |
| 300 | + | |
| 301 | + return ret; | |
| 289 | 302 | } |
| 290 | 303 | |
| 291 | 304 | static int liteuart_remove(struct platform_device *pdev) |
| @@ -293,6 +306,7 @@ static int liteuart_remove(struct platform_device *pdev) · 1 unmodified line | ||
| 293 | 306 | struct uart_port *port = platform_get_drvdata(pdev); |
| 294 | 307 | struct liteuart_port *uart = to_liteuart_port(port); |
| 295 | 308 | |
| 309 | + uart_remove_one_port(&liteuart_driver, port); | |
| 296 | 310 | xa_erase(&liteuart_array, uart->id); |
| 297 | 311 | |
| 298 | 312 | return 0; |
| @@ -598,6 +598,9 @@ static void msm_start_rx_dma(struct msm_port *msm_port) · 597 unmodified lines | ||
| 598 | 598 | u32 val; |
| 599 | 599 | int ret; |
| 600 | 600 | |
| 601 | + if (IS_ENABLED(CONFIG_CONSOLE_POLL)) | |
| 602 | + return; | |
| 603 | + | |
| 601 | 604 | if (!dma->chan) |
| 602 | 605 | return; |
| 603 | 606 | |
| @@ -1506,7 +1506,7 @@ static struct tegra_uart_chip_data tegra20_uart_chip_data = { · 1505 unmodified lines | ||
| 1506 | 1506 | .fifo_mode_enable_status = false, |
| 1507 | 1507 | .uart_max_port = 5, |
| 1508 | 1508 | .max_dma_burst_bytes = 4, |
| 1509 | − .error_tolerance_low_range = 0, | |
| 1509 | + .error_tolerance_low_range = -4, | |
| 1510 | 1510 | .error_tolerance_high_range = 4, |
| 1511 | 1511 | }; |
| 1512 | 1512 | |
| @@ -1517,7 +1517,7 @@ static struct tegra_uart_chip_data tegra30_uart_chip_data = { · 4 unmodified lines | ||
| 1517 | 1517 | .fifo_mode_enable_status = false, |
| 1518 | 1518 | .uart_max_port = 5, |
| 1519 | 1519 | .max_dma_burst_bytes = 4, |
| 1520 | − .error_tolerance_low_range = 0, | |
| 1520 | + .error_tolerance_low_range = -4, | |
| 1521 | 1521 | .error_tolerance_high_range = 4, |
| 1522 | 1522 | }; |
| 1523 | 1523 | |
| @@ -1075,6 +1075,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) · 1074 unmodified lines | ||
| 1075 | 1075 | goto out; |
| 1076 | 1076 | |
| 1077 | 1077 | if (!tty_io_error(tty)) { |
| 1078 | + if (uport->rs485.flags & SER_RS485_ENABLED) { | |
| 1079 | + set &= ~TIOCM_RTS; | |
| 1080 | + clear &= ~TIOCM_RTS; | |
| 1081 | + } | |
| 1082 | + | |
| 1078 | 1083 | uart_update_mctrl(uport, set, clear); |
| 1079 | 1084 | ret = 0; |
| 1080 | 1085 | } |
| @@ -1549,6 +1554,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) · 468 unmodified lines | ||
| 1549 | 1554 | { |
| 1550 | 1555 | struct uart_state *state = container_of(port, struct uart_state, port); |
| 1551 | 1556 | struct uart_port *uport = uart_port_check(state); |
| 1557 | + char *buf; | |
| 1552 | 1558 | |
| 1553 | 1559 | /* |
| 1554 | 1560 | * At this point, we stop accepting input. To do this, we |
| @@ -1570,8 +1576,18 @@ static void uart_tty_port_shutdown(struct tty_port *port) · 15 unmodified lines | ||
| 1570 | 1576 | */ |
| 1571 | 1577 | tty_port_set_suspended(port, 0); |
| 1572 | 1578 | |
| 1573 | − uart_change_pm(state, UART_PM_STATE_OFF); | |
| 1579 | + /* | |
| 1580 | + * Free the transmit buffer. | |
| 1581 | + */ | |
| 1582 | + spin_lock_irq(&uport->lock); | |
| 1583 | + buf = state->xmit.buf; | |
| 1584 | + state->xmit.buf = NULL; | |
| 1585 | + spin_unlock_irq(&uport->lock); | |
| 1574 | 1586 | |
| 1587 | + if (buf) | |
| 1588 | + free_page((unsigned long)buf); | |
| 1589 | + | |
| 1590 | + uart_change_pm(state, UART_PM_STATE_OFF); | |
| 1575 | 1591 | } |
| 1576 | 1592 | |
| 1577 | 1593 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) |
| @@ -337,19 +337,6 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep) · 336 unmodified lines | ||
| 337 | 337 | cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); |
| 338 | 338 | } |
| 339 | 339 | |
| 340 | −static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) | |
| 341 | −{ | |
| 342 | − struct cdns3_endpoint *priv_ep = priv_req->priv_ep; | |
| 343 | − int current_trb = priv_req->start_trb; | |
| 344 | − | |
| 345 | − while (current_trb != priv_req->end_trb) { | |
| 346 | − cdns3_ep_inc_deq(priv_ep); | |
| 347 | − current_trb = priv_ep->dequeue; | |
| 348 | − } | |
| 349 | − | |
| 350 | − cdns3_ep_inc_deq(priv_ep); | |
| 351 | −} | |
| 352 | − | |
| 353 | 340 | /** |
| 354 | 341 | * cdns3_allow_enable_l1 - enable/disable permits to transition to L1. |
| 355 | 342 | * @priv_dev: Extended gadget object |
| @@ -1517,10 +1504,11 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, · 1161 unmodified lines | ||
| 1517 | 1504 | |
| 1518 | 1505 | trb = priv_ep->trb_pool + priv_ep->dequeue; |
| 1519 | 1506 | |
| 1520 | − /* Request was dequeued and TRB was changed to TRB_LINK. */ | |
| 1521 | − if (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { | |
| 1507 | + /* The TRB was changed as link TRB, and the request was handled at ep_dequeue */ | |
| 1508 | + while (TRB_FIELD_TO_TYPE(le32_to_cpu(trb->control)) == TRB_LINK) { | |
| 1522 | 1509 | trace_cdns3_complete_trb(priv_ep, trb); |
| 1523 | − cdns3_move_deq_to_next_trb(priv_req); | |
| 1510 | + cdns3_ep_inc_deq(priv_ep); | |
| 1511 | + trb = priv_ep->trb_pool + priv_ep->dequeue; | |
| 1524 | 1512 | } |
| 1525 | 1513 | |
| 1526 | 1514 | if (!request->stream_id) { |
| @@ -987,6 +987,9 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev, · 986 unmodified lines | ||
| 987 | 987 | |
| 988 | 988 | /* Set up the endpoint ring. */ |
| 989 | 989 | pep->ring = cdnsp_ring_alloc(pdev, 2, ring_type, max_packet, mem_flags); |
| 990 | + if (!pep->ring) | |
| 991 | + return -ENOMEM; | |
| 992 | + | |
| 990 | 993 | pep->skip = false; |
| 991 | 994 | |
| 992 | 995 | /* Fill the endpoint context */ |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | 12 | #include <linux/platform_device.h> |
| 13 | +#include <linux/slab.h> | |
| 13 | 14 | #include "core.h" |
| 14 | 15 | #include "drd.h" |
| 15 | 16 | #include "host-export.h" |
| @@ -406,7 +406,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, · 405 unmodified lines | ||
| 406 | 406 | * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0 |
| 407 | 407 | * (see the end of section 5.6.3), so don't warn about them. |
| 408 | 408 | */ |
| 409 | − maxp = usb_endpoint_maxp(&endpoint->desc); | |
| 409 | + maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize); | |
| 410 | 410 | if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) { |
| 411 | 411 | dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n", |
| 412 | 412 | cfgno, inum, asnum, d->bEndpointAddress); |
| @@ -422,9 +422,9 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, · 9 unmodified lines | ||
| 422 | 422 | maxpacket_maxes = full_speed_maxpacket_maxes; |
| 423 | 423 | break; |
| 424 | 424 | case USB_SPEED_HIGH: |
| 425 | − /* Bits 12..11 are allowed only for HS periodic endpoints */ | |
| 425 | + /* Multiple-transactions bits are allowed only for HS periodic endpoints */ | |
| 426 | 426 | if (usb_endpoint_xfer_int(d) || usb_endpoint_xfer_isoc(d)) { |
| 427 | − i = maxp & (BIT(12) | BIT(11)); | |
| 427 | + i = maxp & USB_EP_MAXP_MULT_MASK; | |
| 428 | 428 | maxp &= ~i; |
| 429 | 429 | } |
| 430 | 430 | fallthrough; |
| @@ -434,6 +434,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 433 unmodified lines | ||
| 434 | 434 | { USB_DEVICE(0x1532, 0x0116), .driver_info = |
| 435 | 435 | USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, |
| 436 | 436 | |
| 437 | + /* Lenovo Powered USB-C Travel Hub (4X90S92381, RTL8153 GigE) */ | |
| 438 | + { USB_DEVICE(0x17ef, 0x721e), .driver_info = USB_QUIRK_NO_LPM }, | |
| 439 | + | |
| 437 | 440 | /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */ |
| 438 | 441 | { USB_DEVICE(0x17ef, 0xa012), .driver_info = |
| 439 | 442 | USB_QUIRK_DISCONNECT_SUSPEND }, |
| @@ -649,7 +649,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) · 648 unmodified lines | ||
| 649 | 649 | struct dwc3_qcom *qcom = platform_get_drvdata(pdev); |
| 650 | 650 | struct device_node *np = pdev->dev.of_node, *dwc3_np; |
| 651 | 651 | struct device *dev = &pdev->dev; |
| 652 | − struct property *prop; | |
| 653 | 652 | int ret; |
| 654 | 653 | |
| 655 | 654 | dwc3_np = of_get_compatible_child(np, "snps,dwc3"); |
| @@ -658,20 +657,6 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) · 2 unmodified lines | ||
| 658 | 657 | return -ENODEV; |
| 659 | 658 | } |
| 660 | 659 | |
| 661 | − prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL); | |
| 662 | − if (!prop) { | |
| 663 | − ret = -ENOMEM; | |
| 664 | − dev_err(dev, "unable to allocate memory for property\n"); | |
| 665 | − goto node_put; | |
| 666 | − } | |
| 667 | − | |
| 668 | − prop->name = "tx-fifo-resize"; | |
| 669 | − ret = of_add_property(dwc3_np, prop); | |
| 670 | − if (ret) { | |
| 671 | − dev_err(dev, "unable to add property\n"); | |
| 672 | − goto node_put; | |
| 673 | − } | |
| 674 | − | |
| 675 | 660 | ret = of_platform_populate(np, NULL, NULL, dev); |
| 676 | 661 | if (ret) { |
| 677 | 662 | dev_err(dev, "failed to register dwc3 core - %d\n", ret); |
| @@ -1679,6 +1679,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · 1678 unmodified lines | ||
| 1679 | 1679 | struct usb_function *f = NULL; |
| 1680 | 1680 | u8 endp; |
| 1681 | 1681 | |
| 1682 | + if (w_length > USB_COMP_EP0_BUFSIZ) { | |
| 1683 | + if (ctrl->bRequestType == USB_DIR_OUT) { | |
| 1684 | + goto done; | |
| 1685 | + } else { | |
| 1686 | + /* Cast away the const, we are going to overwrite on purpose. */ | |
| 1687 | + __le16 *temp = (__le16 *)&ctrl->wLength; | |
| 1688 | + | |
| 1689 | + *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); | |
| 1690 | + w_length = USB_COMP_EP0_BUFSIZ; | |
| 1691 | + } | |
| 1692 | + } | |
| 1693 | + | |
| 1682 | 1694 | /* partial re-init of the response message; the function or the |
| 1683 | 1695 | * gadget might need to intercept e.g. a control-OUT completion |
| 1684 | 1696 | * when we delegate to it. |
| @@ -2209,7 +2221,7 @@ int composite_dev_prepare(struct usb_composite_driver *composite, · 524 unmodified lines | ||
| 2209 | 2221 | if (!cdev->req) |
| 2210 | 2222 | return -ENOMEM; |
| 2211 | 2223 | |
| 2212 | − cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); | |
| 2224 | + cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); | |
| 2213 | 2225 | if (!cdev->req->buf) |
| 2214 | 2226 | goto fail; |
| 2215 | 2227 | |
| @@ -137,7 +137,7 @@ static int dbgp_enable_ep_req(struct usb_ep *ep) · 136 unmodified lines | ||
| 137 | 137 | goto fail_1; |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | − req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL); | |
| 140 | + req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL); | |
| 141 | 141 | if (!req->buf) { |
| 142 | 142 | err = -ENOMEM; |
| 143 | 143 | stp = 2; |
| @@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget, · 201 unmodified lines | ||
| 345 | 345 | void *data = NULL; |
| 346 | 346 | u16 len = 0; |
| 347 | 347 | |
| 348 | + if (length > DBGP_REQ_LEN) { | |
| 349 | + if (ctrl->bRequestType == USB_DIR_OUT) { | |
| 350 | + return err; | |
| 351 | + } else { | |
| 352 | + /* Cast away the const, we are going to overwrite on purpose. */ | |
| 353 | + __le16 *temp = (__le16 *)&ctrl->wLength; | |
| 354 | + | |
| 355 | + *temp = cpu_to_le16(DBGP_REQ_LEN); | |
| 356 | + length = DBGP_REQ_LEN; | |
| 357 | + } | |
| 358 | + } | |
| 359 | + | |
| 360 | + | |
| 348 | 361 | if (request == USB_REQ_GET_DESCRIPTOR) { |
| 349 | 362 | switch (value>>8) { |
| 350 | 363 | case USB_DT_DEVICE: |
| @@ -110,6 +110,8 @@ enum ep0_state { · 109 unmodified lines | ||
| 110 | 110 | /* enough for the whole queue: most events invalidate others */ |
| 111 | 111 | #define N_EVENT 5 |
| 112 | 112 | |
| 113 | +#define RBUF_SIZE 256 | |
| 114 | + | |
| 113 | 115 | struct dev_data { |
| 114 | 116 | spinlock_t lock; |
| 115 | 117 | refcount_t count; |
| @@ -144,7 +146,7 @@ struct dev_data { · 28 unmodified lines | ||
| 144 | 146 | struct dentry *dentry; |
| 145 | 147 | |
| 146 | 148 | /* except this scratch i/o buffer for ep0 */ |
| 147 | − u8 rbuf [256]; | |
| 149 | + u8 rbuf[RBUF_SIZE]; | |
| 148 | 150 | }; |
| 149 | 151 | |
| 150 | 152 | static inline void get_dev (struct dev_data *data) |
| @@ -1331,6 +1333,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · 1180 unmodified lines | ||
| 1331 | 1333 | u16 w_value = le16_to_cpu(ctrl->wValue); |
| 1332 | 1334 | u16 w_length = le16_to_cpu(ctrl->wLength); |
| 1333 | 1335 | |
| 1336 | + if (w_length > RBUF_SIZE) { | |
| 1337 | + if (ctrl->bRequestType == USB_DIR_OUT) { | |
| 1338 | + return value; | |
| 1339 | + } else { | |
| 1340 | + /* Cast away the const, we are going to overwrite on purpose. */ | |
| 1341 | + __le16 *temp = (__le16 *)&ctrl->wLength; | |
| 1342 | + | |
| 1343 | + *temp = cpu_to_le16(RBUF_SIZE); | |
| 1344 | + w_length = RBUF_SIZE; | |
| 1345 | + } | |
| 1346 | + } | |
| 1347 | + | |
| 1334 | 1348 | spin_lock (&dev->lock); |
| 1335 | 1349 | dev->setup_abort = 0; |
| 1336 | 1350 | if (dev->state == STATE_DEV_UNCONNECTED) { |
| @@ -717,6 +717,7 @@ static int xhci_enter_test_mode(struct xhci_hcd *xhci, · 716 unmodified lines | ||
| 717 | 717 | continue; |
| 718 | 718 | |
| 719 | 719 | retval = xhci_disable_slot(xhci, i); |
| 720 | + xhci_free_virt_device(xhci, i); | |
| 720 | 721 | if (retval) |
| 721 | 722 | xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", |
| 722 | 723 | i, retval); |
| @@ -366,7 +366,9 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci, · 365 unmodified lines | ||
| 366 | 366 | /* Must be called with xhci->lock held, releases and aquires lock back */ |
| 367 | 367 | static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) |
| 368 | 368 | { |
| 369 | − u32 temp_32; | |
| 369 | + struct xhci_segment *new_seg = xhci->cmd_ring->deq_seg; | |
| 370 | + union xhci_trb *new_deq = xhci->cmd_ring->dequeue; | |
| 371 | + u64 crcr; | |
| 370 | 372 | int ret; |
| 371 | 373 | |
| 372 | 374 | xhci_dbg(xhci, "Abort command ring\n"); |
| @@ -375,13 +377,18 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags) · 2 unmodified lines | ||
| 375 | 377 | |
| 376 | 378 | /* |
| 377 | 379 | * The control bits like command stop, abort are located in lower |
| 378 | − * dword of the command ring control register. Limit the write | |
| 379 | − * to the lower dword to avoid corrupting the command ring pointer | |
| 380 | − * in case if the command ring is stopped by the time upper dword | |
| 381 | − * is written. | |
| 380 | + * dword of the command ring control register. | |
| 381 | + * Some controllers require all 64 bits to be written to abort the ring. | |
| 382 | + * Make sure the upper dword is valid, pointing to the next command, | |
| 383 | + * avoiding corrupting the command ring pointer in case the command ring | |
| 384 | + * is stopped by the time the upper dword is written. | |
| 382 | 385 | */ |
| 383 | − temp_32 = readl(&xhci->op_regs->cmd_ring); | |
| 384 | − writel(temp_32 | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); | |
| 386 | + next_trb(xhci, NULL, &new_seg, &new_deq); | |
| 387 | + if (trb_is_link(new_deq)) | |
| 388 | + next_trb(xhci, NULL, &new_seg, &new_deq); | |
| 389 | + | |
| 390 | + crcr = xhci_trb_virt_to_dma(new_seg, new_deq); | |
| 391 | + xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring); | |
| 385 | 392 | |
| 386 | 393 | /* Section 4.6.1.2 of xHCI 1.0 spec says software should also time the |
| 387 | 394 | * completion of the Command Abort operation. If CRR is not negated in 5 |
| @@ -1518,7 +1525,6 @@ static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) · 1130 unmodified lines | ||
| 1518 | 1525 | if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) |
| 1519 | 1526 | /* Delete default control endpoint resources */ |
| 1520 | 1527 | xhci_free_device_endpoint_resources(xhci, virt_dev, true); |
| 1521 | − xhci_free_virt_device(xhci, slot_id); | |
| 1522 | 1528 | } |
| 1523 | 1529 | |
| 1524 | 1530 | static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id, |
| @@ -3934,7 +3934,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) · 3933 unmodified lines | ||
| 3934 | 3934 | struct xhci_slot_ctx *slot_ctx; |
| 3935 | 3935 | int i, ret; |
| 3936 | 3936 | |
| 3937 | −#ifndef CONFIG_USB_DEFAULT_PERSIST | |
| 3938 | 3937 | /* |
| 3939 | 3938 | * We called pm_runtime_get_noresume when the device was attached. |
| 3940 | 3939 | * Decrement the counter here to allow controller to runtime suspend |
| @@ -3942,7 +3941,6 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) · 1 unmodified line | ||
| 3942 | 3941 | */ |
| 3943 | 3942 | if (xhci->quirks & XHCI_RESET_ON_RESUME) |
| 3944 | 3943 | pm_runtime_put_noidle(hcd->self.controller); |
| 3945 | −#endif | |
| 3946 | 3944 | |
| 3947 | 3945 | ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); |
| 3948 | 3946 | /* If the host is halted due to driver unload, we still need to free the |
| @@ -3961,9 +3959,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) · 12 unmodified lines | ||
| 3961 | 3959 | del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); |
| 3962 | 3960 | } |
| 3963 | 3961 | virt_dev->udev = NULL; |
| 3964 | − ret = xhci_disable_slot(xhci, udev->slot_id); | |
| 3965 | − if (ret) | |
| 3966 | − xhci_free_virt_device(xhci, udev->slot_id); | |
| 3962 | + xhci_disable_slot(xhci, udev->slot_id); | |
| 3963 | + xhci_free_virt_device(xhci, udev->slot_id); | |
| 3967 | 3964 | } |
| 3968 | 3965 | |
| 3969 | 3966 | int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) |
| @@ -3973,7 +3970,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) · 3 unmodified lines | ||
| 3973 | 3970 | u32 state; |
| 3974 | 3971 | int ret = 0; |
| 3975 | 3972 | |
| 3976 | − command = xhci_alloc_command(xhci, false, GFP_KERNEL); | |
| 3973 | + command = xhci_alloc_command(xhci, true, GFP_KERNEL); | |
| 3977 | 3974 | if (!command) |
| 3978 | 3975 | return -ENOMEM; |
| 3979 | 3976 | |
| @@ -3998,6 +3995,15 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) · 18 unmodified lines | ||
| 3998 | 3995 | } |
| 3999 | 3996 | xhci_ring_cmd_db(xhci); |
| 4000 | 3997 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 3998 | + | |
| 3999 | + wait_for_completion(command->completion); | |
| 4000 | + | |
| 4001 | + if (command->status != COMP_SUCCESS) | |
| 4002 | + xhci_warn(xhci, "Unsuccessful disable slot %u command, status %d\n", | |
| 4003 | + slot_id, command->status); | |
| 4004 | + | |
| 4005 | + xhci_free_command(xhci, command); | |
| 4006 | + | |
| 4001 | 4007 | return ret; |
| 4002 | 4008 | } |
| 4003 | 4009 | |
| @@ -4094,23 +4100,20 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) · 90 unmodified lines | ||
| 4094 | 4100 | |
| 4095 | 4101 | xhci_debugfs_create_slot(xhci, slot_id); |
| 4096 | 4102 | |
| 4097 | −#ifndef CONFIG_USB_DEFAULT_PERSIST | |
| 4098 | 4103 | /* |
| 4099 | 4104 | * If resetting upon resume, we can't put the controller into runtime |
| 4100 | 4105 | * suspend if there is a device attached. |
| 4101 | 4106 | */ |
| 4102 | 4107 | if (xhci->quirks & XHCI_RESET_ON_RESUME) |
| 4103 | 4108 | pm_runtime_get_noresume(hcd->self.controller); |
| 4104 | −#endif | |
| 4105 | 4109 | |
| 4106 | 4110 | /* Is this a LS or FS device under a HS hub? */ |
| 4107 | 4111 | /* Hub or peripherial? */ |
| 4108 | 4112 | return 1; |
| 4109 | 4113 | |
| 4110 | 4114 | disable_slot: |
| 4111 | − ret = xhci_disable_slot(xhci, udev->slot_id); | |
| 4112 | − if (ret) | |
| 4113 | − xhci_free_virt_device(xhci, udev->slot_id); | |
| 4115 | + xhci_disable_slot(xhci, udev->slot_id); | |
| 4116 | + xhci_free_virt_device(xhci, udev->slot_id); | |
| 4114 | 4117 | |
| 4115 | 4118 | return 0; |
| 4116 | 4119 | } |
| @@ -4240,6 +4243,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev, · 123 unmodified lines | ||
| 4240 | 4243 | |
| 4241 | 4244 | mutex_unlock(&xhci->mutex); |
| 4242 | 4245 | ret = xhci_disable_slot(xhci, udev->slot_id); |
| 4246 | + xhci_free_virt_device(xhci, udev->slot_id); | |
| 4243 | 4247 | if (!ret) |
| 4244 | 4248 | xhci_alloc_dev(hcd, udev); |
| 4245 | 4249 | kfree(command->completion); |
| @@ -4110,11 +4110,7 @@ static void run_state_machine(struct tcpm_port *port) · 4109 unmodified lines | ||
| 4110 | 4110 | tcpm_try_src(port) ? SRC_TRY |
| 4111 | 4111 | : SNK_ATTACHED, |
| 4112 | 4112 | 0); |
| 4113 | − else | |
| 4114 | − /* Wait for VBUS, but not forever */ | |
| 4115 | − tcpm_set_state(port, PORT_RESET, PD_T_PS_SOURCE_ON); | |
| 4116 | 4113 | break; |
| 4117 | − | |
| 4118 | 4114 | case SRC_TRY: |
| 4119 | 4115 | port->try_src_count++; |
| 4120 | 4116 | tcpm_set_cc(port, tcpm_rp_cc(port)); |
| @@ -98,7 +98,8 @@ static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev, · 97 unmodified lines | ||
| 98 | 98 | version = cpu_to_le16(0x0201); |
| 99 | 99 | |
| 100 | 100 | if (igd_opregion_shift_copy(buf, &off, |
| 101 | − &version + (pos - OPREGION_VERSION), | |
| 101 | + (u8 *)&version + | |
| 102 | + (pos - OPREGION_VERSION), | |
| 102 | 103 | &pos, &remaining, bytes)) |
| 103 | 104 | return -EFAULT; |
| 104 | 105 | } |
| @@ -121,7 +122,7 @@ static ssize_t vfio_pci_igd_rw(struct vfio_pci_core_device *vdev, · 16 unmodified lines | ||
| 121 | 122 | OPREGION_SIZE : 0); |
| 122 | 123 | |
| 123 | 124 | if (igd_opregion_shift_copy(buf, &off, |
| 124 | − &rvda + (pos - OPREGION_RVDA), | |
| 125 | + (u8 *)&rvda + (pos - OPREGION_RVDA), | |
| 125 | 126 | &pos, &remaining, bytes)) |
| 126 | 127 | return -EFAULT; |
| 127 | 128 | } |
| @@ -232,7 +232,7 @@ static inline bool vfio_iommu_driver_allowed(struct vfio_container *container, · 231 unmodified lines | ||
| 232 | 232 | } |
| 233 | 233 | #endif /* CONFIG_VFIO_NOIOMMU */ |
| 234 | 234 | |
| 235 | −/** | |
| 235 | +/* | |
| 236 | 236 | * IOMMU driver registration |
| 237 | 237 | */ |
| 238 | 238 | int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops) |
| @@ -285,7 +285,7 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, · 46 unmodified lines | ||
| 285 | 285 | unsigned long action, void *data); |
| 286 | 286 | static void vfio_group_get(struct vfio_group *group); |
| 287 | 287 | |
| 288 | −/** | |
| 288 | +/* | |
| 289 | 289 | * Container objects - containers are created when /dev/vfio/vfio is |
| 290 | 290 | * opened, but their lifecycle extends until the last user is done, so |
| 291 | 291 | * it's freed via kref. Must support container/group/device being |
| @@ -309,7 +309,7 @@ static void vfio_container_put(struct vfio_container *container) · 17 unmodified lines | ||
| 309 | 309 | kref_put(&container->kref, vfio_container_release); |
| 310 | 310 | } |
| 311 | 311 | |
| 312 | −/** | |
| 312 | +/* | |
| 313 | 313 | * Group objects - create, release, get, put, search |
| 314 | 314 | */ |
| 315 | 315 | static struct vfio_group * |
| @@ -488,7 +488,7 @@ static struct vfio_group *vfio_group_get_from_dev(struct device *dev) · 172 unmodified lines | ||
| 488 | 488 | return group; |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | −/** | |
| 491 | +/* | |
| 492 | 492 | * Device objects - create, release, get, put, search |
| 493 | 493 | */ |
| 494 | 494 | /* Device reference always implies a group reference */ |
| @@ -595,7 +595,7 @@ static int vfio_dev_viable(struct device *dev, void *data) · 100 unmodified lines | ||
| 595 | 595 | return ret; |
| 596 | 596 | } |
| 597 | 597 | |
| 598 | −/** | |
| 598 | +/* | |
| 599 | 599 | * Async device support |
| 600 | 600 | */ |
| 601 | 601 | static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev) |
| @@ -689,7 +689,7 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb, · 87 unmodified lines | ||
| 689 | 689 | return NOTIFY_OK; |
| 690 | 690 | } |
| 691 | 691 | |
| 692 | −/** | |
| 692 | +/* | |
| 693 | 693 | * VFIO driver API |
| 694 | 694 | */ |
| 695 | 695 | void vfio_init_group_dev(struct vfio_device *device, struct device *dev, |
| @@ -831,7 +831,7 @@ int vfio_register_emulated_iommu_dev(struct vfio_device *device) · 135 unmodified lines | ||
| 831 | 831 | } |
| 832 | 832 | EXPORT_SYMBOL_GPL(vfio_register_emulated_iommu_dev); |
| 833 | 833 | |
| 834 | −/** | |
| 834 | +/* | |
| 835 | 835 | * Get a reference to the vfio_device for a device. Even if the |
| 836 | 836 | * caller thinks they own the device, they could be racing with a |
| 837 | 837 | * release call path, so we can't trust drvdata for the shortcut. |
| @@ -965,7 +965,7 @@ void vfio_unregister_group_dev(struct vfio_device *device) · 127 unmodified lines | ||
| 965 | 965 | } |
| 966 | 966 | EXPORT_SYMBOL_GPL(vfio_unregister_group_dev); |
| 967 | 967 | |
| 968 | −/** | |
| 968 | +/* | |
| 969 | 969 | * VFIO base fd, /dev/vfio/vfio |
| 970 | 970 | */ |
| 971 | 971 | static long vfio_ioctl_check_extension(struct vfio_container *container, |
| @@ -1183,7 +1183,7 @@ static const struct file_operations vfio_fops = { · 211 unmodified lines | ||
| 1183 | 1183 | .compat_ioctl = compat_ptr_ioctl, |
| 1184 | 1184 | }; |
| 1185 | 1185 | |
| 1186 | −/** | |
| 1186 | +/* | |
| 1187 | 1187 | * VFIO Group fd, /dev/vfio/$GROUP |
| 1188 | 1188 | */ |
| 1189 | 1189 | static void __vfio_group_unset_container(struct vfio_group *group) |
| @@ -1536,7 +1536,7 @@ static const struct file_operations vfio_group_fops = { · 346 unmodified lines | ||
| 1536 | 1536 | .release = vfio_group_fops_release, |
| 1537 | 1537 | }; |
| 1538 | 1538 | |
| 1539 | −/** | |
| 1539 | +/* | |
| 1540 | 1540 | * VFIO Device fd |
| 1541 | 1541 | */ |
| 1542 | 1542 | static int vfio_device_fops_release(struct inode *inode, struct file *filep) |
| @@ -1611,7 +1611,7 @@ static const struct file_operations vfio_device_fops = { · 68 unmodified lines | ||
| 1611 | 1611 | .mmap = vfio_device_fops_mmap, |
| 1612 | 1612 | }; |
| 1613 | 1613 | |
| 1614 | −/** | |
| 1614 | +/* | |
| 1615 | 1615 | * External user API, exported by symbols to be linked dynamically. |
| 1616 | 1616 | * |
| 1617 | 1617 | * The protocol includes: |
| @@ -1659,7 +1659,7 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep) · 41 unmodified lines | ||
| 1659 | 1659 | } |
| 1660 | 1660 | EXPORT_SYMBOL_GPL(vfio_group_get_external_user); |
| 1661 | 1661 | |
| 1662 | −/** | |
| 1662 | +/* | |
| 1663 | 1663 | * External user API, exported by symbols to be linked dynamically. |
| 1664 | 1664 | * The external user passes in a device pointer |
| 1665 | 1665 | * to verify that: |
| @@ -1725,7 +1725,7 @@ long vfio_external_check_extension(struct vfio_group *group, unsigned long arg) · 59 unmodified lines | ||
| 1725 | 1725 | } |
| 1726 | 1726 | EXPORT_SYMBOL_GPL(vfio_external_check_extension); |
| 1727 | 1727 | |
| 1728 | −/** | |
| 1728 | +/* | |
| 1729 | 1729 | * Sub-module support |
| 1730 | 1730 | */ |
| 1731 | 1731 | /* |
| @@ -2272,7 +2272,7 @@ struct iommu_domain *vfio_group_iommu_domain(struct vfio_group *group) · 540 unmodified lines | ||
| 2272 | 2272 | } |
| 2273 | 2273 | EXPORT_SYMBOL_GPL(vfio_group_iommu_domain); |
| 2274 | 2274 | |
| 2275 | −/** | |
| 2275 | +/* | |
| 2276 | 2276 | * Module/class support |
| 2277 | 2277 | */ |
| 2278 | 2278 | static char *vfio_devnode(struct device *dev, umode_t *mode) |
| @@ -366,11 +366,17 @@ static void vgacon_init(struct vc_data *c, int init) · 365 unmodified lines | ||
| 366 | 366 | struct uni_pagedir *p; |
| 367 | 367 | |
| 368 | 368 | /* |
| 369 | − * We cannot be loaded as a module, therefore init is always 1, | |
| 370 | − * but vgacon_init can be called more than once, and init will | |
| 371 | − * not be 1. | |
| 369 | + * We cannot be loaded as a module, therefore init will be 1 | |
| 370 | + * if we are the default console, however if we are a fallback | |
| 371 | + * console, for example if fbcon has failed registration, then | |
| 372 | + * init will be 0, so we need to make sure our boot parameters | |
| 373 | + * have been copied to the console structure for vgacon_resize | |
| 374 | + * ultimately called by vc_resize. Any subsequent calls to | |
| 375 | + * vgacon_init init will have init set to 0 too. | |
| 372 | 376 | */ |
| 373 | 377 | c->vc_can_do_color = vga_can_do_color; |
| 378 | + c->vc_scan_lines = vga_scan_lines; | |
| 379 | + c->vc_font.height = c->vc_cell_height = vga_video_font_height; | |
| 374 | 380 | |
| 375 | 381 | /* set dimensions manually if init != 0 since vc_resize() will fail */ |
| 376 | 382 | if (init) { |
| @@ -379,8 +385,6 @@ static void vgacon_init(struct vc_data *c, int init) · 2 unmodified lines | ||
| 379 | 385 | } else |
| 380 | 386 | vc_resize(c, vga_video_num_columns, vga_video_num_lines); |
| 381 | 387 | |
| 382 | − c->vc_scan_lines = vga_scan_lines; | |
| 383 | − c->vc_font.height = c->vc_cell_height = vga_video_font_height; | |
| 384 | 388 | c->vc_complement_mask = 0x7700; |
| 385 | 389 | if (vga_512_chars) |
| 386 | 390 | c->vc_hi_font_mask = 0x0800; |
| @@ -181,8 +181,9 @@ struct poll_iocb { · 180 unmodified lines | ||
| 181 | 181 | struct file *file; |
| 182 | 182 | struct wait_queue_head *head; |
| 183 | 183 | __poll_t events; |
| 184 | − bool done; | |
| 185 | 184 | bool cancelled; |
| 185 | + bool work_scheduled; | |
| 186 | + bool work_need_resched; | |
| 186 | 187 | struct wait_queue_entry wait; |
| 187 | 188 | struct work_struct work; |
| 188 | 189 | }; |
| @@ -1619,6 +1620,51 @@ static void aio_poll_put_work(struct work_struct *work) · 1430 unmodified lines | ||
| 1619 | 1620 | iocb_put(iocb); |
| 1620 | 1621 | } |
| 1621 | 1622 | |
| 1623 | +/* | |
| 1624 | + * Safely lock the waitqueue which the request is on, synchronizing with the | |
| 1625 | + * case where the ->poll() provider decides to free its waitqueue early. | |
| 1626 | + * | |
| 1627 | + * Returns true on success, meaning that req->head->lock was locked, req->wait | |
| 1628 | + * is on req->head, and an RCU read lock was taken. Returns false if the | |
| 1629 | + * request was already removed from its waitqueue (which might no longer exist). | |
| 1630 | + */ | |
| 1631 | +static bool poll_iocb_lock_wq(struct poll_iocb *req) | |
| 1632 | +{ | |
| 1633 | + wait_queue_head_t *head; | |
| 1634 | + | |
| 1635 | + /* | |
| 1636 | + * While we hold the waitqueue lock and the waitqueue is nonempty, | |
| 1637 | + * wake_up_pollfree() will wait for us. However, taking the waitqueue | |
| 1638 | + * lock in the first place can race with the waitqueue being freed. | |
| 1639 | + * | |
| 1640 | + * We solve this as eventpoll does: by taking advantage of the fact that | |
| 1641 | + * all users of wake_up_pollfree() will RCU-delay the actual free. If | |
| 1642 | + * we enter rcu_read_lock() and see that the pointer to the queue is | |
| 1643 | + * non-NULL, we can then lock it without the memory being freed out from | |
| 1644 | + * under us, then check whether the request is still on the queue. | |
| 1645 | + * | |
| 1646 | + * Keep holding rcu_read_lock() as long as we hold the queue lock, in | |
| 1647 | + * case the caller deletes the entry from the queue, leaving it empty. | |
| 1648 | + * In that case, only RCU prevents the queue memory from being freed. | |
| 1649 | + */ | |
| 1650 | + rcu_read_lock(); | |
| 1651 | + head = smp_load_acquire(&req->head); | |
| 1652 | + if (head) { | |
| 1653 | + spin_lock(&head->lock); | |
| 1654 | + if (!list_empty(&req->wait.entry)) | |
| 1655 | + return true; | |
| 1656 | + spin_unlock(&head->lock); | |
| 1657 | + } | |
| 1658 | + rcu_read_unlock(); | |
| 1659 | + return false; | |
| 1660 | +} | |
| 1661 | + | |
| 1662 | +static void poll_iocb_unlock_wq(struct poll_iocb *req) | |
| 1663 | +{ | |
| 1664 | + spin_unlock(&req->head->lock); | |
| 1665 | + rcu_read_unlock(); | |
| 1666 | +} | |
| 1667 | + | |
| 1622 | 1668 | static void aio_poll_complete_work(struct work_struct *work) |
| 1623 | 1669 | { |
| 1624 | 1670 | struct poll_iocb *req = container_of(work, struct poll_iocb, work); |
| @@ -1638,14 +1684,27 @@ static void aio_poll_complete_work(struct work_struct *work) · 13 unmodified lines | ||
| 1638 | 1684 | * avoid further branches in the fast path. |
| 1639 | 1685 | */ |
| 1640 | 1686 | spin_lock_irq(&ctx->ctx_lock); |
| 1641 | − if (!mask && !READ_ONCE(req->cancelled)) { | |
| 1642 | − add_wait_queue(req->head, &req->wait); | |
| 1643 | − spin_unlock_irq(&ctx->ctx_lock); | |
| 1644 | − return; | |
| 1645 | − } | |
| 1687 | + if (poll_iocb_lock_wq(req)) { | |
| 1688 | + if (!mask && !READ_ONCE(req->cancelled)) { | |
| 1689 | + /* | |
| 1690 | + * The request isn't actually ready to be completed yet. | |
| 1691 | + * Reschedule completion if another wakeup came in. | |
| 1692 | + */ | |
| 1693 | + if (req->work_need_resched) { | |
| 1694 | + schedule_work(&req->work); | |
| 1695 | + req->work_need_resched = false; | |
| 1696 | + } else { | |
| 1697 | + req->work_scheduled = false; | |
| 1698 | + } | |
| 1699 | + poll_iocb_unlock_wq(req); | |
| 1700 | + spin_unlock_irq(&ctx->ctx_lock); | |
| 1701 | + return; | |
| 1702 | + } | |
| 1703 | + list_del_init(&req->wait.entry); | |
| 1704 | + poll_iocb_unlock_wq(req); | |
| 1705 | + } /* else, POLLFREE has freed the waitqueue, so we must complete */ | |
| 1646 | 1706 | list_del_init(&iocb->ki_list); |
| 1647 | 1707 | iocb->ki_res.res = mangle_poll(mask); |
| 1648 | − req->done = true; | |
| 1649 | 1708 | spin_unlock_irq(&ctx->ctx_lock); |
| 1650 | 1709 | |
| 1651 | 1710 | iocb_put(iocb); |
| @@ -1657,13 +1716,14 @@ static int aio_poll_cancel(struct kiocb *iocb) · 5 unmodified lines | ||
| 1657 | 1716 | struct aio_kiocb *aiocb = container_of(iocb, struct aio_kiocb, rw); |
| 1658 | 1717 | struct poll_iocb *req = &aiocb->poll; |
| 1659 | 1718 | |
| 1660 | − spin_lock(&req->head->lock); | |
| 1661 | − WRITE_ONCE(req->cancelled, true); | |
| 1662 | − if (!list_empty(&req->wait.entry)) { | |
| 1663 | − list_del_init(&req->wait.entry); | |
| 1664 | − schedule_work(&aiocb->poll.work); | |
| 1665 | − } | |
| 1666 | − spin_unlock(&req->head->lock); | |
| 1719 | + if (poll_iocb_lock_wq(req)) { | |
| 1720 | + WRITE_ONCE(req->cancelled, true); | |
| 1721 | + if (!req->work_scheduled) { | |
| 1722 | + schedule_work(&aiocb->poll.work); | |
| 1723 | + req->work_scheduled = true; | |
| 1724 | + } | |
| 1725 | + poll_iocb_unlock_wq(req); | |
| 1726 | + } /* else, the request was force-cancelled by POLLFREE already */ | |
| 1667 | 1727 | |
| 1668 | 1728 | return 0; |
| 1669 | 1729 | } |
| @@ -1680,21 +1740,27 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, · 10 unmodified lines | ||
| 1680 | 1740 | if (mask && !(mask & req->events)) |
| 1681 | 1741 | return 0; |
| 1682 | 1742 | |
| 1683 | − list_del_init(&req->wait.entry); | |
| 1684 | − | |
| 1685 | − if (mask && spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { | |
| 1743 | + /* | |
| 1744 | + * Complete the request inline if possible. This requires that three | |
| 1745 | + * conditions be met: | |
| 1746 | + * 1. An event mask must have been passed. If a plain wakeup was done | |
| 1747 | + * instead, then mask == 0 and we have to call vfs_poll() to get | |
| 1748 | + * the events, so inline completion isn't possible. | |
| 1749 | + * 2. The completion work must not have already been scheduled. | |
| 1750 | + * 3. ctx_lock must not be busy. We have to use trylock because we | |
| 1751 | + * already hold the waitqueue lock, so this inverts the normal | |
| 1752 | + * locking order. Use irqsave/irqrestore because not all | |
| 1753 | + * filesystems (e.g. fuse) call this function with IRQs disabled, | |
| 1754 | + * yet IRQs have to be disabled before ctx_lock is obtained. | |
| 1755 | + */ | |
| 1756 | + if (mask && !req->work_scheduled && | |
| 1757 | + spin_trylock_irqsave(&iocb->ki_ctx->ctx_lock, flags)) { | |
| 1686 | 1758 | struct kioctx *ctx = iocb->ki_ctx; |
| 1687 | 1759 | |
| 1688 | − /* | |
| 1689 | − * Try to complete the iocb inline if we can. Use | |
| 1690 | − * irqsave/irqrestore because not all filesystems (e.g. fuse) | |
| 1691 | − * call this function with IRQs disabled and because IRQs | |
| 1692 | − * have to be disabled before ctx_lock is obtained. | |
| 1693 | − */ | |
| 1760 | + list_del_init(&req->wait.entry); | |
| 1694 | 1761 | list_del(&iocb->ki_list); |
| 1695 | 1762 | iocb->ki_res.res = mangle_poll(mask); |
| 1696 | − req->done = true; | |
| 1697 | − if (iocb->ki_eventfd && eventfd_signal_allowed()) { | |
| 1763 | + if (iocb->ki_eventfd && !eventfd_signal_allowed()) { | |
| 1698 | 1764 | iocb = NULL; |
| 1699 | 1765 | INIT_WORK(&req->work, aio_poll_put_work); |
| 1700 | 1766 | schedule_work(&req->work); |
| @@ -1703,7 +1769,43 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, · 2 unmodified lines | ||
| 1703 | 1769 | if (iocb) |
| 1704 | 1770 | iocb_put(iocb); |
| 1705 | 1771 | } else { |
| 1706 | − schedule_work(&req->work); | |
| 1772 | + /* | |
| 1773 | + * Schedule the completion work if needed. If it was already | |
| 1774 | + * scheduled, record that another wakeup came in. | |
| 1775 | + * | |
| 1776 | + * Don't remove the request from the waitqueue here, as it might | |
| 1777 | + * not actually be complete yet (we won't know until vfs_poll() | |
| 1778 | + * is called), and we must not miss any wakeups. POLLFREE is an | |
| 1779 | + * exception to this; see below. | |
| 1780 | + */ | |
| 1781 | + if (req->work_scheduled) { | |
| 1782 | + req->work_need_resched = true; | |
| 1783 | + } else { | |
| 1784 | + schedule_work(&req->work); | |
| 1785 | + req->work_scheduled = true; | |
| 1786 | + } | |
| 1787 | + | |
| 1788 | + /* | |
| 1789 | + * If the waitqueue is being freed early but we can't complete | |
| 1790 | + * the request inline, we have to tear down the request as best | |
| 1791 | + * we can. That means immediately removing the request from its | |
| 1792 | + * waitqueue and preventing all further accesses to the | |
| 1793 | + * waitqueue via the request. We also need to schedule the | |
| 1794 | + * completion work (done above). Also mark the request as | |
| 1795 | + * cancelled, to potentially skip an unneeded call to ->poll(). | |
| 1796 | + */ | |
| 1797 | + if (mask & POLLFREE) { | |
| 1798 | + WRITE_ONCE(req->cancelled, true); | |
| 1799 | + list_del_init(&req->wait.entry); | |
| 1800 | + | |
| 1801 | + /* | |
| 1802 | + * Careful: this *must* be the last step, since as soon | |
| 1803 | + * as req->head is NULL'ed out, the request can be | |
| 1804 | + * completed and freed, since aio_poll_complete_work() | |
| 1805 | + * will no longer need to take the waitqueue lock. | |
| 1806 | + */ | |
| 1807 | + smp_store_release(&req->head, NULL); | |
| 1808 | + } | |
| 1707 | 1809 | } |
| 1708 | 1810 | return 1; |
| 1709 | 1811 | } |
| @@ -1711,6 +1813,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, · 1 unmodified line | ||
| 1711 | 1813 | struct aio_poll_table { |
| 1712 | 1814 | struct poll_table_struct pt; |
| 1713 | 1815 | struct aio_kiocb *iocb; |
| 1816 | + bool queued; | |
| 1714 | 1817 | int error; |
| 1715 | 1818 | }; |
| 1716 | 1819 | |
| @@ -1721,11 +1824,12 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head, · 4 unmodified lines | ||
| 1721 | 1824 | struct aio_poll_table *pt = container_of(p, struct aio_poll_table, pt); |
| 1722 | 1825 | |
| 1723 | 1826 | /* multiple wait queues per file are not supported */ |
| 1724 | − if (unlikely(pt->iocb->poll.head)) { | |
| 1827 | + if (unlikely(pt->queued)) { | |
| 1725 | 1828 | pt->error = -EINVAL; |
| 1726 | 1829 | return; |
| 1727 | 1830 | } |
| 1728 | 1831 | |
| 1832 | + pt->queued = true; | |
| 1729 | 1833 | pt->error = 0; |
| 1730 | 1834 | pt->iocb->poll.head = head; |
| 1731 | 1835 | add_wait_queue(head, &pt->iocb->poll.wait); |
| @@ -1750,12 +1854,14 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) · 18 unmodified lines | ||
| 1750 | 1854 | req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP; |
| 1751 | 1855 | |
| 1752 | 1856 | req->head = NULL; |
| 1753 | − req->done = false; | |
| 1754 | 1857 | req->cancelled = false; |
| 1858 | + req->work_scheduled = false; | |
| 1859 | + req->work_need_resched = false; | |
| 1755 | 1860 | |
| 1756 | 1861 | apt.pt._qproc = aio_poll_queue_proc; |
| 1757 | 1862 | apt.pt._key = req->events; |
| 1758 | 1863 | apt.iocb = aiocb; |
| 1864 | + apt.queued = false; | |
| 1759 | 1865 | apt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */ |
| 1760 | 1866 | |
| 1761 | 1867 | /* initialized the list so that we can do list_empty checks */ |
| @@ -1764,23 +1870,35 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) · 2 unmodified lines | ||
| 1764 | 1870 | |
| 1765 | 1871 | mask = vfs_poll(req->file, &apt.pt) & req->events; |
| 1766 | 1872 | spin_lock_irq(&ctx->ctx_lock); |
| 1767 | − if (likely(req->head)) { | |
| 1768 | − spin_lock(&req->head->lock); | |
| 1769 | − if (unlikely(list_empty(&req->wait.entry))) { | |
| 1770 | − if (apt.error) | |
| 1873 | + if (likely(apt.queued)) { | |
| 1874 | + bool on_queue = poll_iocb_lock_wq(req); | |
| 1875 | + | |
| 1876 | + if (!on_queue || req->work_scheduled) { | |
| 1877 | + /* | |
| 1878 | + * aio_poll_wake() already either scheduled the async | |
| 1879 | + * completion work, or completed the request inline. | |
| 1880 | + */ | |
| 1881 | + if (apt.error) /* unsupported case: multiple queues */ | |
| 1771 | 1882 | cancel = true; |
| 1772 | 1883 | apt.error = 0; |
| 1773 | 1884 | mask = 0; |
| 1774 | 1885 | } |
| 1775 | 1886 | if (mask || apt.error) { |
| 1887 | + /* Steal to complete synchronously. */ | |
| 1776 | 1888 | list_del_init(&req->wait.entry); |
| 1777 | 1889 | } else if (cancel) { |
| 1890 | + /* Cancel if possible (may be too late though). */ | |
| 1778 | 1891 | WRITE_ONCE(req->cancelled, true); |
| 1779 | − } else if (!req->done) { /* actually waiting for an event */ | |
| 1892 | + } else if (on_queue) { | |
| 1893 | + /* | |
| 1894 | + * Actually waiting for an event, so add the request to | |
| 1895 | + * active_reqs so that it can be cancelled if needed. | |
| 1896 | + */ | |
| 1780 | 1897 | list_add_tail(&aiocb->ki_list, &ctx->active_reqs); |
| 1781 | 1898 | aiocb->ki_cancel = aio_poll_cancel; |
| 1782 | 1899 | } |
| 1783 | − spin_unlock(&req->head->lock); | |
| 1900 | + if (on_queue) | |
| 1901 | + poll_iocb_unlock_wq(req); | |
| 1784 | 1902 | } |
| 1785 | 1903 | if (mask) { /* no async, we'd stolen it */ |
| 1786 | 1904 | aiocb->ki_res.res = mangle_poll(mask); |
| @@ -143,10 +143,13 @@ int btrfs_check_data_free_space(struct btrfs_inode *inode, · 142 unmodified lines | ||
| 143 | 143 | |
| 144 | 144 | /* Use new btrfs_qgroup_reserve_data to reserve precious data space. */ |
| 145 | 145 | ret = btrfs_qgroup_reserve_data(inode, reserved, start, len); |
| 146 | − if (ret < 0) | |
| 146 | + if (ret < 0) { | |
| 147 | 147 | btrfs_free_reserved_data_space_noquota(fs_info, len); |
| 148 | − else | |
| 148 | + extent_changeset_free(*reserved); | |
| 149 | + *reserved = NULL; | |
| 150 | + } else { | |
| 149 | 151 | ret = 0; |
| 152 | + } | |
| 150 | 153 | return ret; |
| 151 | 154 | } |
| 152 | 155 | |
| @@ -452,8 +455,11 @@ int btrfs_delalloc_reserve_space(struct btrfs_inode *inode, · 299 unmodified lines | ||
| 452 | 455 | if (ret < 0) |
| 453 | 456 | return ret; |
| 454 | 457 | ret = btrfs_delalloc_reserve_metadata(inode, len); |
| 455 | − if (ret < 0) | |
| 458 | + if (ret < 0) { | |
| 456 | 459 | btrfs_free_reserved_data_space(inode, *reserved, start, len); |
| 460 | + extent_changeset_free(*reserved); | |
| 461 | + *reserved = NULL; | |
| 462 | + } | |
| 457 | 463 | return ret; |
| 458 | 464 | } |
| 459 | 465 | |
| @@ -6051,6 +6051,9 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) · 6050 unmodified lines | ||
| 6051 | 6051 | int dev_ret = 0; |
| 6052 | 6052 | int ret = 0; |
| 6053 | 6053 | |
| 6054 | + if (range->start == U64_MAX) | |
| 6055 | + return -EINVAL; | |
| 6056 | + | |
| 6054 | 6057 | /* |
| 6055 | 6058 | * Check range overflow if range->len is set. |
| 6056 | 6059 | * The default range->len is U64_MAX. |
| @@ -4313,6 +4313,20 @@ static void set_btree_ioerr(struct page *page, struct extent_buffer *eb) · 4312 unmodified lines | ||
| 4313 | 4313 | if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) |
| 4314 | 4314 | return; |
| 4315 | 4315 | |
| 4316 | + /* | |
| 4317 | + * A read may stumble upon this buffer later, make sure that it gets an | |
| 4318 | + * error and knows there was an error. | |
| 4319 | + */ | |
| 4320 | + clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | |
| 4321 | + | |
| 4322 | + /* | |
| 4323 | + * We need to set the mapping with the io error as well because a write | |
| 4324 | + * error will flip the file system readonly, and then syncfs() will | |
| 4325 | + * return a 0 because we are readonly if we don't modify the err seq for | |
| 4326 | + * the superblock. | |
| 4327 | + */ | |
| 4328 | + mapping_set_error(page->mapping, -EIO); | |
| 4329 | + | |
| 4316 | 4330 | /* |
| 4317 | 4331 | * If we error out, we should add back the dirty_metadata_bytes |
| 4318 | 4332 | * to make it consistent. |
| @@ -3187,10 +3187,8 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg) · 3186 unmodified lines | ||
| 3187 | 3187 | return -EPERM; |
| 3188 | 3188 | |
| 3189 | 3189 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
| 3190 | − if (IS_ERR(vol_args)) { | |
| 3191 | − ret = PTR_ERR(vol_args); | |
| 3192 | − goto out; | |
| 3193 | − } | |
| 3190 | + if (IS_ERR(vol_args)) | |
| 3191 | + return PTR_ERR(vol_args); | |
| 3194 | 3192 | |
| 3195 | 3193 | if (vol_args->flags & ~BTRFS_DEVICE_REMOVE_ARGS_MASK) { |
| 3196 | 3194 | ret = -EOPNOTSUPP; |
| @@ -334,7 +334,8 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id, · 333 unmodified lines | ||
| 334 | 334 | key.offset = ref_id; |
| 335 | 335 | again: |
| 336 | 336 | ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); |
| 337 | − BUG_ON(ret < 0); | |
| 337 | + if (ret < 0) | |
| 338 | + goto out; | |
| 338 | 339 | if (ret == 0) { |
| 339 | 340 | leaf = path->nodes[0]; |
| 340 | 341 | ref = btrfs_item_ptr(leaf, path->slots[0], |
| @@ -2908,6 +2908,8 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans, · 2907 unmodified lines | ||
| 2908 | 2908 | path->nodes[*level]->len); |
| 2909 | 2909 | if (ret) |
| 2910 | 2910 | return ret; |
| 2911 | + btrfs_redirty_list_add(trans->transaction, | |
| 2912 | + next); | |
| 2911 | 2913 | } else { |
| 2912 | 2914 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) |
| 2913 | 2915 | clear_extent_buffer_dirty(next); |
| @@ -2988,6 +2990,7 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, · 74 unmodified lines | ||
| 2988 | 2990 | next->start, next->len); |
| 2989 | 2991 | if (ret) |
| 2990 | 2992 | goto out; |
| 2993 | + btrfs_redirty_list_add(trans->transaction, next); | |
| 2991 | 2994 | } else { |
| 2992 | 2995 | if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &next->bflags)) |
| 2993 | 2996 | clear_extent_buffer_dirty(next); |
| @@ -3438,8 +3441,6 @@ static void free_log_tree(struct btrfs_trans_handle *trans, · 444 unmodified lines | ||
| 3438 | 3441 | EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT); |
| 3439 | 3442 | extent_io_tree_release(&log->log_csum_range); |
| 3440 | 3443 | |
| 3441 | − if (trans && log->node) | |
| 3442 | − btrfs_redirty_list_add(trans->transaction, log->node); | |
| 3443 | 3444 | btrfs_put_root(log); |
| 3444 | 3445 | } |
| 3445 | 3446 | |
| @@ -1860,6 +1860,7 @@ int btrfs_zone_finish(struct btrfs_block_group *block_group) · 1859 unmodified lines | ||
| 1860 | 1860 | block_group->alloc_offset = block_group->zone_capacity; |
| 1861 | 1861 | block_group->free_space_ctl->free_space = 0; |
| 1862 | 1862 | btrfs_clear_treelog_bg(block_group); |
| 1863 | + btrfs_clear_data_reloc_bg(block_group); | |
| 1863 | 1864 | spin_unlock(&block_group->lock); |
| 1864 | 1865 | |
| 1865 | 1866 | ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH, |
| @@ -1942,6 +1943,7 @@ void btrfs_zone_finish_endio(struct btrfs_fs_info *fs_info, u64 logical, u64 len · 76 unmodified lines | ||
| 1942 | 1943 | ASSERT(block_group->alloc_offset == block_group->zone_capacity); |
| 1943 | 1944 | ASSERT(block_group->free_space_ctl->free_space == 0); |
| 1944 | 1945 | btrfs_clear_treelog_bg(block_group); |
| 1946 | + btrfs_clear_data_reloc_bg(block_group); | |
| 1945 | 1947 | spin_unlock(&block_group->lock); |
| 1946 | 1948 | |
| 1947 | 1949 | map = block_group->physical_map; |
| @@ -1562,6 +1562,10 @@ smbd_connected: · 1561 unmodified lines | ||
| 1562 | 1562 | /* fscache server cookies are based on primary channel only */ |
| 1563 | 1563 | if (!CIFS_SERVER_IS_CHAN(tcp_ses)) |
| 1564 | 1564 | cifs_fscache_get_client_cookie(tcp_ses); |
| 1565 | +#ifdef CONFIG_CIFS_FSCACHE | |
| 1566 | + else | |
| 1567 | + tcp_ses->fscache = tcp_ses->primary_server->fscache; | |
| 1568 | +#endif /* CONFIG_CIFS_FSCACHE */ | |
| 1565 | 1569 | |
| 1566 | 1570 | /* queue echo request delayed work */ |
| 1567 | 1571 | queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); |
| @@ -3046,12 +3050,6 @@ static int mount_get_conns(struct mount_ctx *mnt_ctx) · 1478 unmodified lines | ||
| 3046 | 3050 | cifs_dbg(VFS, "read only mount of RW share\n"); |
| 3047 | 3051 | /* no need to log a RW mount of a typical RW share */ |
| 3048 | 3052 | } |
| 3049 | − /* | |
| 3050 | − * The cookie is initialized from volume info returned above. | |
| 3051 | − * Inside cifs_fscache_get_super_cookie it checks | |
| 3052 | − * that we do not get super cookie twice. | |
| 3053 | − */ | |
| 3054 | − cifs_fscache_get_super_cookie(tcon); | |
| 3055 | 3053 | } |
| 3056 | 3054 | |
| 3057 | 3055 | /* |
| @@ -3426,6 +3424,7 @@ static int connect_dfs_root(struct mount_ctx *mnt_ctx, struct dfs_cache_tgt_list · 368 unmodified lines | ||
| 3426 | 3424 | */ |
| 3427 | 3425 | mount_put_conns(mnt_ctx); |
| 3428 | 3426 | mount_get_dfs_conns(mnt_ctx); |
| 3427 | + set_root_ses(mnt_ctx); | |
| 3429 | 3428 | |
| 3430 | 3429 | full_path = build_unc_path_to_root(ctx, cifs_sb, true); |
| 3431 | 3430 | if (IS_ERR(full_path)) |
| @@ -16,14 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | * Key layout of CIFS server cache index object |
| 17 | 17 | */ |
| 18 | 18 | struct cifs_server_key { |
| 19 | − struct { | |
| 20 | − uint16_t family; /* address family */ | |
| 21 | − __be16 port; /* IP port */ | |
| 22 | − } hdr; | |
| 23 | − union { | |
| 24 | − struct in_addr ipv4_addr; | |
| 25 | − struct in6_addr ipv6_addr; | |
| 26 | − }; | |
| 19 | + __u64 conn_id; | |
| 27 | 20 | } __packed; |
| 28 | 21 | |
| 29 | 22 | /* |
| @@ -31,42 +24,23 @@ struct cifs_server_key { · 1 unmodified line | ||
| 31 | 24 | */ |
| 32 | 25 | void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) |
| 33 | 26 | { |
| 34 | − const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr; | |
| 35 | − const struct sockaddr_in *addr = (struct sockaddr_in *) sa; | |
| 36 | − const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa; | |
| 37 | 27 | struct cifs_server_key key; |
| 38 | − uint16_t key_len = sizeof(key.hdr); | |
| 39 | − | |
| 40 | − memset(&key, 0, sizeof(key)); | |
| 41 | 28 | |
| 42 | 29 | /* |
| 43 | − * Should not be a problem as sin_family/sin6_family overlays | |
| 44 | − * sa_family field | |
| 30 | + * Check if cookie was already initialized so don't reinitialize it. | |
| 31 | + * In the future, as we integrate with newer fscache features, | |
| 32 | + * we may want to instead add a check if cookie has changed | |
| 45 | 33 | */ |
| 46 | − key.hdr.family = sa->sa_family; | |
| 47 | − switch (sa->sa_family) { | |
| 48 | − case AF_INET: | |
| 49 | − key.hdr.port = addr->sin_port; | |
| 50 | − key.ipv4_addr = addr->sin_addr; | |
| 51 | − key_len += sizeof(key.ipv4_addr); | |
| 52 | − break; | |
| 53 | − | |
| 54 | − case AF_INET6: | |
| 55 | − key.hdr.port = addr6->sin6_port; | |
| 56 | − key.ipv6_addr = addr6->sin6_addr; | |
| 57 | − key_len += sizeof(key.ipv6_addr); | |
| 58 | − break; | |
| 59 | − | |
| 60 | − default: | |
| 61 | − cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family); | |
| 62 | − server->fscache = NULL; | |
| 34 | + if (server->fscache) | |
| 63 | 35 | return; |
| 64 | − } | |
| 36 | + | |
| 37 | + memset(&key, 0, sizeof(key)); | |
| 38 | + key.conn_id = server->conn_id; | |
| 65 | 39 | |
| 66 | 40 | server->fscache = |
| 67 | 41 | fscache_acquire_cookie(cifs_fscache_netfs.primary_index, |
| 68 | 42 | &cifs_fscache_server_index_def, |
| 69 | − &key, key_len, | |
| 43 | + &key, sizeof(key), | |
| 70 | 44 | NULL, 0, |
| 71 | 45 | server, 0, true); |
| 72 | 46 | cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", |
| @@ -92,7 +66,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) · 19 unmodified lines | ||
| 92 | 66 | * In the future, as we integrate with newer fscache features, |
| 93 | 67 | * we may want to instead add a check if cookie has changed |
| 94 | 68 | */ |
| 95 | − if (tcon->fscache == NULL) | |
| 69 | + if (tcon->fscache) | |
| 96 | 70 | return; |
| 97 | 71 | |
| 98 | 72 | sharename = extract_sharename(tcon->treeName); |
| @@ -1376,6 +1376,13 @@ iget_no_retry: · 1375 unmodified lines | ||
| 1376 | 1376 | inode = ERR_PTR(rc); |
| 1377 | 1377 | } |
| 1378 | 1378 | |
| 1379 | + /* | |
| 1380 | + * The cookie is initialized from volume info returned above. | |
| 1381 | + * Inside cifs_fscache_get_super_cookie it checks | |
| 1382 | + * that we do not get super cookie twice. | |
| 1383 | + */ | |
| 1384 | + cifs_fscache_get_super_cookie(tcon); | |
| 1385 | + | |
| 1379 | 1386 | out: |
| 1380 | 1387 | kfree(path); |
| 1381 | 1388 | free_xid(xid); |
| @@ -590,8 +590,8 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, · 589 unmodified lines | ||
| 590 | 590 | { |
| 591 | 591 | unsigned int tioffset; /* challenge message target info area */ |
| 592 | 592 | unsigned int tilen; /* challenge message target info area length */ |
| 593 | − | |
| 594 | 593 | CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; |
| 594 | + __u32 server_flags; | |
| 595 | 595 | |
| 596 | 596 | if (blob_len < sizeof(CHALLENGE_MESSAGE)) { |
| 597 | 597 | cifs_dbg(VFS, "challenge blob len %d too small\n", blob_len); |
| @@ -609,12 +609,37 @@ int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, · 11 unmodified lines | ||
| 609 | 609 | return -EINVAL; |
| 610 | 610 | } |
| 611 | 611 | |
| 612 | + server_flags = le32_to_cpu(pblob->NegotiateFlags); | |
| 613 | + cifs_dbg(FYI, "%s: negotiate=0x%08x challenge=0x%08x\n", __func__, | |
| 614 | + ses->ntlmssp->client_flags, server_flags); | |
| 615 | + | |
| 616 | + if ((ses->ntlmssp->client_flags & (NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN)) && | |
| 617 | + (!(server_flags & NTLMSSP_NEGOTIATE_56) && !(server_flags & NTLMSSP_NEGOTIATE_128))) { | |
| 618 | + cifs_dbg(VFS, "%s: requested signing/encryption but server did not return either 56-bit or 128-bit session key size\n", | |
| 619 | + __func__); | |
| 620 | + return -EINVAL; | |
| 621 | + } | |
| 622 | + if (!(server_flags & NTLMSSP_NEGOTIATE_NTLM) && !(server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) { | |
| 623 | + cifs_dbg(VFS, "%s: server does not seem to support either NTLMv1 or NTLMv2\n", __func__); | |
| 624 | + return -EINVAL; | |
| 625 | + } | |
| 626 | + if (ses->server->sign && !(server_flags & NTLMSSP_NEGOTIATE_SIGN)) { | |
| 627 | + cifs_dbg(VFS, "%s: forced packet signing but server does not seem to support it\n", | |
| 628 | + __func__); | |
| 629 | + return -EOPNOTSUPP; | |
| 630 | + } | |
| 631 | + if ((ses->ntlmssp->client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && | |
| 632 | + !(server_flags & NTLMSSP_NEGOTIATE_KEY_XCH)) | |
| 633 | + pr_warn_once("%s: authentication has been weakened as server does not support key exchange\n", | |
| 634 | + __func__); | |
| 635 | + | |
| 636 | + ses->ntlmssp->server_flags = server_flags; | |
| 637 | + | |
| 612 | 638 | memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); |
| 613 | − /* BB we could decode pblob->NegotiateFlags; some may be useful */ | |
| 614 | 639 | /* In particular we can examine sign flags */ |
| 615 | 640 | /* BB spec says that if AvId field of MsvAvTimestamp is populated then |
| 616 | 641 | we must set the MIC field of the AUTHENTICATE_MESSAGE */ |
| 617 | − ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); | |
| 642 | + | |
| 618 | 643 | tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); |
| 619 | 644 | tilen = le16_to_cpu(pblob->TargetInfoArray.Length); |
| 620 | 645 | if (tioffset > blob_len || tioffset + tilen > blob_len) { |
| @@ -721,13 +746,13 @@ int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, · 100 unmodified lines | ||
| 721 | 746 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
| 722 | 747 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
| 723 | 748 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | |
| 724 | − NTLMSSP_NEGOTIATE_SEAL; | |
| 725 | − if (server->sign) | |
| 726 | − flags |= NTLMSSP_NEGOTIATE_SIGN; | |
| 749 | + NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL | | |
| 750 | + NTLMSSP_NEGOTIATE_SIGN; | |
| 727 | 751 | if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) |
| 728 | 752 | flags |= NTLMSSP_NEGOTIATE_KEY_XCH; |
| 729 | 753 | |
| 730 | 754 | tmp = *pbuffer + sizeof(NEGOTIATE_MESSAGE); |
| 755 | + ses->ntlmssp->client_flags = flags; | |
| 731 | 756 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
| 732 | 757 | |
| 733 | 758 | /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */ |
| @@ -779,15 +804,8 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer, · 45 unmodified lines | ||
| 779 | 804 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); |
| 780 | 805 | sec_blob->MessageType = NtLmAuthenticate; |
| 781 | 806 | |
| 782 | − flags = NTLMSSP_NEGOTIATE_56 | | |
| 783 | − NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | | |
| 784 | − NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | |
| 785 | − NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | | |
| 786 | − NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; | |
| 787 | − if (ses->server->sign) | |
| 788 | − flags |= NTLMSSP_NEGOTIATE_SIGN; | |
| 789 | − if (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) | |
| 790 | − flags |= NTLMSSP_NEGOTIATE_KEY_XCH; | |
| 807 | + flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET | | |
| 808 | + NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED; | |
| 791 | 809 | |
| 792 | 810 | tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE); |
| 793 | 811 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
| @@ -834,9 +852,9 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer, · 40 unmodified lines | ||
| 834 | 852 | *pbuffer, &tmp, |
| 835 | 853 | nls_cp); |
| 836 | 854 | |
| 837 | − if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) || | |
| 838 | − (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) | |
| 839 | − && !calc_seckey(ses)) { | |
| 855 | + if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && | |
| 856 | + (!ses->server->session_estab || ses->ntlmssp->sesskey_per_smbsess) && | |
| 857 | + !calc_seckey(ses)) { | |
| 840 | 858 | memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); |
| 841 | 859 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer); |
| 842 | 860 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); |
| @@ -858,6 +858,10 @@ loop: · 857 unmodified lines | ||
| 858 | 858 | file = NULL; |
| 859 | 859 | else if (!get_file_rcu_many(file, refs)) |
| 860 | 860 | goto loop; |
| 861 | + else if (files_lookup_fd_raw(files, fd) != file) { | |
| 862 | + fput_many(file, refs); | |
| 863 | + goto loop; | |
| 864 | + } | |
| 861 | 865 | } |
| 862 | 866 | rcu_read_unlock(); |
| 863 | 867 | |
| @@ -1857,7 +1857,6 @@ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs) · 1856 unmodified lines | ||
| 1857 | 1857 | |
| 1858 | 1858 | void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) |
| 1859 | 1859 | { |
| 1860 | − struct gfs2_holder mock_gh = { .gh_gl = gl, .gh_state = state, }; | |
| 1861 | 1860 | unsigned long delay = 0; |
| 1862 | 1861 | unsigned long holdtime; |
| 1863 | 1862 | unsigned long now = jiffies; |
| @@ -1890,8 +1889,13 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) · 26 unmodified lines | ||
| 1890 | 1889 | * keep the glock until the last strong holder is done with it. |
| 1891 | 1890 | */ |
| 1892 | 1891 | if (!find_first_strong_holder(gl)) { |
| 1893 | − if (state == LM_ST_UNLOCKED) | |
| 1894 | − mock_gh.gh_state = LM_ST_EXCLUSIVE; | |
| 1892 | + struct gfs2_holder mock_gh = { | |
| 1893 | + .gh_gl = gl, | |
| 1894 | + .gh_state = (state == LM_ST_UNLOCKED) ? | |
| 1895 | + LM_ST_EXCLUSIVE : state, | |
| 1896 | + .gh_iflags = BIT(HIF_HOLDER) | |
| 1897 | + }; | |
| 1898 | + | |
| 1895 | 1899 | demote_incompat_holders(gl, &mock_gh); |
| 1896 | 1900 | } |
| 1897 | 1901 | handle_callback(gl, state, delay, true); |
| @@ -40,37 +40,6 @@ static const struct inode_operations gfs2_file_iops; · 39 unmodified lines | ||
| 40 | 40 | static const struct inode_operations gfs2_dir_iops; |
| 41 | 41 | static const struct inode_operations gfs2_symlink_iops; |
| 42 | 42 | |
| 43 | −static int iget_test(struct inode *inode, void *opaque) | |
| 44 | −{ | |
| 45 | − u64 no_addr = *(u64 *)opaque; | |
| 46 | − | |
| 47 | − return GFS2_I(inode)->i_no_addr == no_addr; | |
| 48 | −} | |
| 49 | − | |
| 50 | −static int iget_set(struct inode *inode, void *opaque) | |
| 51 | −{ | |
| 52 | − u64 no_addr = *(u64 *)opaque; | |
| 53 | − | |
| 54 | − GFS2_I(inode)->i_no_addr = no_addr; | |
| 55 | − inode->i_ino = no_addr; | |
| 56 | − return 0; | |
| 57 | −} | |
| 58 | − | |
| 59 | −static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr) | |
| 60 | −{ | |
| 61 | − struct inode *inode; | |
| 62 | − | |
| 63 | −repeat: | |
| 64 | − inode = iget5_locked(sb, no_addr, iget_test, iget_set, &no_addr); | |
| 65 | − if (!inode) | |
| 66 | − return inode; | |
| 67 | − if (is_bad_inode(inode)) { | |
| 68 | − iput(inode); | |
| 69 | − goto repeat; | |
| 70 | − } | |
| 71 | − return inode; | |
| 72 | −} | |
| 73 | − | |
| 74 | 43 | /** |
| 75 | 44 | * gfs2_set_iop - Sets inode operations |
| 76 | 45 | * @inode: The inode with correct i_mode filled in |
| @@ -104,6 +73,22 @@ static void gfs2_set_iop(struct inode *inode) · 27 unmodified lines | ||
| 104 | 73 | } |
| 105 | 74 | } |
| 106 | 75 | |
| 76 | +static int iget_test(struct inode *inode, void *opaque) | |
| 77 | +{ | |
| 78 | + u64 no_addr = *(u64 *)opaque; | |
| 79 | + | |
| 80 | + return GFS2_I(inode)->i_no_addr == no_addr; | |
| 81 | +} | |
| 82 | + | |
| 83 | +static int iget_set(struct inode *inode, void *opaque) | |
| 84 | +{ | |
| 85 | + u64 no_addr = *(u64 *)opaque; | |
| 86 | + | |
| 87 | + GFS2_I(inode)->i_no_addr = no_addr; | |
| 88 | + inode->i_ino = no_addr; | |
| 89 | + return 0; | |
| 90 | +} | |
| 91 | + | |
| 107 | 92 | /** |
| 108 | 93 | * gfs2_inode_lookup - Lookup an inode |
| 109 | 94 | * @sb: The super block |
| @@ -132,12 +117,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, · 22 unmodified lines | ||
| 132 | 117 | { |
| 133 | 118 | struct inode *inode; |
| 134 | 119 | struct gfs2_inode *ip; |
| 135 | − struct gfs2_glock *io_gl = NULL; | |
| 136 | 120 | struct gfs2_holder i_gh; |
| 137 | 121 | int error; |
| 138 | 122 | |
| 139 | 123 | gfs2_holder_mark_uninitialized(&i_gh); |
| 140 | − inode = gfs2_iget(sb, no_addr); | |
| 124 | + inode = iget5_locked(sb, no_addr, iget_test, iget_set, &no_addr); | |
| 141 | 125 | if (!inode) |
| 142 | 126 | return ERR_PTR(-ENOMEM); |
| 143 | 127 | |
| @@ -145,22 +129,16 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, · 1 unmodified line | ||
| 145 | 129 | |
| 146 | 130 | if (inode->i_state & I_NEW) { |
| 147 | 131 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
| 132 | + struct gfs2_glock *io_gl; | |
| 148 | 133 | |
| 149 | 134 | error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
| 150 | 135 | if (unlikely(error)) |
| 151 | 136 | goto fail; |
| 152 | − flush_delayed_work(&ip->i_gl->gl_work); | |
| 153 | − | |
| 154 | − error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); | |
| 155 | − if (unlikely(error)) | |
| 156 | − goto fail; | |
| 157 | − if (blktype != GFS2_BLKST_UNLINKED) | |
| 158 | − gfs2_cancel_delete_work(io_gl); | |
| 159 | 137 | |
| 160 | 138 | if (type == DT_UNKNOWN || blktype != GFS2_BLKST_FREE) { |
| 161 | 139 | /* |
| 162 | 140 | * The GL_SKIP flag indicates to skip reading the inode |
| 163 | − * block. We read the inode with gfs2_inode_refresh | |
| 141 | + * block. We read the inode when instantiating it | |
| 164 | 142 | * after possibly checking the block type. |
| 165 | 143 | */ |
| 166 | 144 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, |
| @@ -181,24 +159,31 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, · 14 unmodified lines | ||
| 181 | 159 | } |
| 182 | 160 | } |
| 183 | 161 | |
| 184 | − glock_set_object(ip->i_gl, ip); | |
| 185 | 162 | set_bit(GLF_INSTANTIATE_NEEDED, &ip->i_gl->gl_flags); |
| 186 | − error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); | |
| 163 | + | |
| 164 | + error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); | |
| 187 | 165 | if (unlikely(error)) |
| 188 | 166 | goto fail; |
| 189 | − glock_set_object(ip->i_iopen_gh.gh_gl, ip); | |
| 167 | + if (blktype != GFS2_BLKST_UNLINKED) | |
| 168 | + gfs2_cancel_delete_work(io_gl); | |
| 169 | + error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh); | |
| 190 | 170 | gfs2_glock_put(io_gl); |
| 191 | − io_gl = NULL; | |
| 171 | + if (unlikely(error)) | |
| 172 | + goto fail; | |
| 192 | 173 | |
| 193 | 174 | /* Lowest possible timestamp; will be overwritten in gfs2_dinode_in. */ |
| 194 | 175 | inode->i_atime.tv_sec = 1LL << (8 * sizeof(inode->i_atime.tv_sec) - 1); |
| 195 | 176 | inode->i_atime.tv_nsec = 0; |
| 196 | 177 | |
| 178 | + glock_set_object(ip->i_gl, ip); | |
| 179 | + | |
| 197 | 180 | if (type == DT_UNKNOWN) { |
| 198 | 181 | /* Inode glock must be locked already */ |
| 199 | 182 | error = gfs2_instantiate(&i_gh); |
| 200 | − if (error) | |
| 183 | + if (error) { | |
| 184 | + glock_clear_object(ip->i_gl, ip); | |
| 201 | 185 | goto fail; |
| 186 | + } | |
| 202 | 187 | } else { |
| 203 | 188 | ip->i_no_formal_ino = no_formal_ino; |
| 204 | 189 | inode->i_mode = DT2IF(type); |
| @@ -206,31 +191,23 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, · 1 unmodified line | ||
| 206 | 191 | |
| 207 | 192 | if (gfs2_holder_initialized(&i_gh)) |
| 208 | 193 | gfs2_glock_dq_uninit(&i_gh); |
| 194 | + glock_set_object(ip->i_iopen_gh.gh_gl, ip); | |
| 209 | 195 | |
| 210 | 196 | gfs2_set_iop(inode); |
| 197 | + unlock_new_inode(inode); | |
| 211 | 198 | } |
| 212 | 199 | |
| 213 | 200 | if (no_formal_ino && ip->i_no_formal_ino && |
| 214 | 201 | no_formal_ino != ip->i_no_formal_ino) { |
| 215 | − error = -ESTALE; | |
| 216 | − if (inode->i_state & I_NEW) | |
| 217 | − goto fail; | |
| 218 | 202 | iput(inode); |
| 219 | − return ERR_PTR(error); | |
| 203 | + return ERR_PTR(-ESTALE); | |
| 220 | 204 | } |
| 221 | 205 | |
| 222 | − if (inode->i_state & I_NEW) | |
| 223 | − unlock_new_inode(inode); | |
| 224 | − | |
| 225 | 206 | return inode; |
| 226 | 207 | |
| 227 | 208 | fail: |
| 228 | − if (gfs2_holder_initialized(&ip->i_iopen_gh)) { | |
| 229 | − glock_clear_object(ip->i_iopen_gh.gh_gl, ip); | |
| 209 | + if (gfs2_holder_initialized(&ip->i_iopen_gh)) | |
| 230 | 210 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
| 231 | − } | |
| 232 | − if (io_gl) | |
| 233 | − gfs2_glock_put(io_gl); | |
| 234 | 211 | if (gfs2_holder_initialized(&i_gh)) |
| 235 | 212 | gfs2_glock_dq_uninit(&i_gh); |
| 236 | 213 | iget_failed(inode); |
| @@ -730,18 +707,19 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 493 unmodified lines | ||
| 730 | 707 | error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); |
| 731 | 708 | if (error) |
| 732 | 709 | goto fail_free_inode; |
| 733 | − flush_delayed_work(&ip->i_gl->gl_work); | |
| 734 | 710 | |
| 735 | 711 | error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl); |
| 736 | 712 | if (error) |
| 737 | 713 | goto fail_free_inode; |
| 738 | 714 | gfs2_cancel_delete_work(io_gl); |
| 739 | 715 | |
| 716 | + error = insert_inode_locked4(inode, ip->i_no_addr, iget_test, &ip->i_no_addr); | |
| 717 | + BUG_ON(error); | |
| 718 | + | |
| 740 | 719 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1); |
| 741 | 720 | if (error) |
| 742 | 721 | goto fail_gunlock2; |
| 743 | 722 | |
| 744 | − glock_set_object(ip->i_gl, ip); | |
| 745 | 723 | error = gfs2_trans_begin(sdp, blocks, 0); |
| 746 | 724 | if (error) |
| 747 | 725 | goto fail_gunlock2; |
| @@ -757,9 +735,9 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 9 unmodified lines | ||
| 757 | 735 | if (error) |
| 758 | 736 | goto fail_gunlock2; |
| 759 | 737 | |
| 738 | + glock_set_object(ip->i_gl, ip); | |
| 760 | 739 | glock_set_object(io_gl, ip); |
| 761 | 740 | gfs2_set_iop(inode); |
| 762 | − insert_inode_hash(inode); | |
| 763 | 741 | |
| 764 | 742 | free_vfs_inode = 0; /* After this point, the inode is no longer |
| 765 | 743 | considered free. Any failures need to undo |
| @@ -801,17 +779,17 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, · 35 unmodified lines | ||
| 801 | 779 | gfs2_glock_dq_uninit(ghs + 1); |
| 802 | 780 | gfs2_glock_put(io_gl); |
| 803 | 781 | gfs2_qa_put(dip); |
| 782 | + unlock_new_inode(inode); | |
| 804 | 783 | return error; |
| 805 | 784 | |
| 806 | 785 | fail_gunlock3: |
| 786 | + glock_clear_object(ip->i_gl, ip); | |
| 807 | 787 | glock_clear_object(io_gl, ip); |
| 808 | 788 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
| 809 | 789 | fail_gunlock2: |
| 810 | − glock_clear_object(io_gl, ip); | |
| 811 | 790 | gfs2_glock_put(io_gl); |
| 812 | 791 | fail_free_inode: |
| 813 | 792 | if (ip->i_gl) { |
| 814 | − glock_clear_object(ip->i_gl, ip); | |
| 815 | 793 | if (free_vfs_inode) /* else evict will do the put for us */ |
| 816 | 794 | gfs2_glock_put(ip->i_gl); |
| 817 | 795 | } |
| @@ -829,7 +807,10 @@ fail_gunlock: · 11 unmodified lines | ||
| 829 | 807 | mark_inode_dirty(inode); |
| 830 | 808 | set_bit(free_vfs_inode ? GIF_FREE_VFS_INODE : GIF_ALLOC_FAILED, |
| 831 | 809 | &GFS2_I(inode)->i_flags); |
| 832 | − iput(inode); | |
| 810 | + if (inode->i_state & I_NEW) | |
| 811 | + iget_failed(inode); | |
| 812 | + else | |
| 813 | + iput(inode); | |
| 833 | 814 | } |
| 834 | 815 | if (gfs2_holder_initialized(ghs + 1)) |
| 835 | 816 | gfs2_glock_dq_uninit(ghs + 1); |
| @@ -142,6 +142,7 @@ static bool io_acct_cancel_pending_work(struct io_wqe *wqe, · 141 unmodified lines | ||
| 142 | 142 | struct io_wqe_acct *acct, |
| 143 | 143 | struct io_cb_cancel_data *match); |
| 144 | 144 | static void create_worker_cb(struct callback_head *cb); |
| 145 | +static void io_wq_cancel_tw_create(struct io_wq *wq); | |
| 145 | 146 | |
| 146 | 147 | static bool io_worker_get(struct io_worker *worker) |
| 147 | 148 | { |
| @@ -357,12 +358,22 @@ static bool io_queue_worker_create(struct io_worker *worker, · 209 unmodified lines | ||
| 357 | 358 | test_and_set_bit_lock(0, &worker->create_state)) |
| 358 | 359 | goto fail_release; |
| 359 | 360 | |
| 361 | + atomic_inc(&wq->worker_refs); | |
| 360 | 362 | init_task_work(&worker->create_work, func); |
| 361 | 363 | worker->create_index = acct->index; |
| 362 | 364 | if (!task_work_add(wq->task, &worker->create_work, TWA_SIGNAL)) { |
| 363 | − clear_bit_unlock(0, &worker->create_state); | |
| 365 | + /* | |
| 366 | + * EXIT may have been set after checking it above, check after | |
| 367 | + * adding the task_work and remove any creation item if it is | |
| 368 | + * now set. wq exit does that too, but we can have added this | |
| 369 | + * work item after we canceled in io_wq_exit_workers(). | |
| 370 | + */ | |
| 371 | + if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) | |
| 372 | + io_wq_cancel_tw_create(wq); | |
| 373 | + io_worker_ref_put(wq); | |
| 364 | 374 | return true; |
| 365 | 375 | } |
| 376 | + io_worker_ref_put(wq); | |
| 366 | 377 | clear_bit_unlock(0, &worker->create_state); |
| 367 | 378 | fail_release: |
| 368 | 379 | io_worker_release(worker); |
| @@ -714,6 +725,13 @@ static bool io_wq_work_match_all(struct io_wq_work *work, void *data) · 345 unmodified lines | ||
| 714 | 725 | |
| 715 | 726 | static inline bool io_should_retry_thread(long err) |
| 716 | 727 | { |
| 728 | + /* | |
| 729 | + * Prevent perpetual task_work retry, if the task (or its group) is | |
| 730 | + * exiting. | |
| 731 | + */ | |
| 732 | + if (fatal_signal_pending(current)) | |
| 733 | + return false; | |
| 734 | + | |
| 717 | 735 | switch (err) { |
| 718 | 736 | case -EAGAIN: |
| 719 | 737 | case -ERESTARTSYS: |
| @@ -1191,13 +1209,9 @@ void io_wq_exit_start(struct io_wq *wq) · 471 unmodified lines | ||
| 1191 | 1209 | set_bit(IO_WQ_BIT_EXIT, &wq->state); |
| 1192 | 1210 | } |
| 1193 | 1211 | |
| 1194 | −static void io_wq_exit_workers(struct io_wq *wq) | |
| 1212 | +static void io_wq_cancel_tw_create(struct io_wq *wq) | |
| 1195 | 1213 | { |
| 1196 | 1214 | struct callback_head *cb; |
| 1197 | − int node; | |
| 1198 | − | |
| 1199 | − if (!wq->task) | |
| 1200 | − return; | |
| 1201 | 1215 | |
| 1202 | 1216 | while ((cb = task_work_cancel_match(wq->task, io_task_work_match, wq)) != NULL) { |
| 1203 | 1217 | struct io_worker *worker; |
| @@ -1205,6 +1219,16 @@ static void io_wq_exit_workers(struct io_wq *wq) · 1 unmodified line | ||
| 1205 | 1219 | worker = container_of(cb, struct io_worker, create_work); |
| 1206 | 1220 | io_worker_cancel_cb(worker); |
| 1207 | 1221 | } |
| 1222 | +} | |
| 1223 | + | |
| 1224 | +static void io_wq_exit_workers(struct io_wq *wq) | |
| 1225 | +{ | |
| 1226 | + int node; | |
| 1227 | + | |
| 1228 | + if (!wq->task) | |
| 1229 | + return; | |
| 1230 | + | |
| 1231 | + io_wq_cancel_tw_create(wq); | |
| 1208 | 1232 | |
| 1209 | 1233 | rcu_read_lock(); |
| 1210 | 1234 | for_each_node(node) { |
| @@ -9824,7 +9824,7 @@ static __cold void io_uring_drop_tctx_refs(struct task_struct *task) · 9823 unmodified lines | ||
| 9824 | 9824 | |
| 9825 | 9825 | /* |
| 9826 | 9826 | * Find any io_uring ctx that this task has registered or done IO on, and cancel |
| 9827 | − * requests. @sqd should be not-null IIF it's an SQPOLL thread cancellation. | |
| 9827 | + * requests. @sqd should be not-null IFF it's an SQPOLL thread cancellation. | |
| 9828 | 9828 | */ |
| 9829 | 9829 | static __cold void io_uring_cancel_generic(bool cancel_all, |
| 9830 | 9830 | struct io_sq_data *sqd) |
| @@ -9866,8 +9866,10 @@ static __cold void io_uring_cancel_generic(bool cancel_all, · 35 unmodified lines | ||
| 9866 | 9866 | cancel_all); |
| 9867 | 9867 | } |
| 9868 | 9868 | |
| 9869 | − prepare_to_wait(&tctx->wait, &wait, TASK_UNINTERRUPTIBLE); | |
| 9869 | + prepare_to_wait(&tctx->wait, &wait, TASK_INTERRUPTIBLE); | |
| 9870 | + io_run_task_work(); | |
| 9870 | 9871 | io_uring_drop_tctx_refs(current); |
| 9872 | + | |
| 9871 | 9873 | /* |
| 9872 | 9874 | * If we've seen completions, retry without waiting. This |
| 9873 | 9875 | * avoids a race where a completion comes in before we did |
| @@ -354,16 +354,11 @@ static void netfs_rreq_write_to_cache_work(struct work_struct *work) · 353 unmodified lines | ||
| 354 | 354 | netfs_rreq_do_write_to_cache(rreq); |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | −static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq, | |
| 358 | − bool was_async) | |
| 357 | +static void netfs_rreq_write_to_cache(struct netfs_read_request *rreq) | |
| 359 | 358 | { |
| 360 | − if (was_async) { | |
| 361 | − rreq->work.func = netfs_rreq_write_to_cache_work; | |
| 362 | − if (!queue_work(system_unbound_wq, &rreq->work)) | |
| 363 | − BUG(); | |
| 364 | − } else { | |
| 365 | − netfs_rreq_do_write_to_cache(rreq); | |
| 366 | − } | |
| 359 | + rreq->work.func = netfs_rreq_write_to_cache_work; | |
| 360 | + if (!queue_work(system_unbound_wq, &rreq->work)) | |
| 361 | + BUG(); | |
| 367 | 362 | } |
| 368 | 363 | |
| 369 | 364 | /* |
| @@ -558,7 +553,7 @@ again: · 188 unmodified lines | ||
| 558 | 553 | wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS); |
| 559 | 554 | |
| 560 | 555 | if (test_bit(NETFS_RREQ_WRITE_TO_CACHE, &rreq->flags)) |
| 561 | − return netfs_rreq_write_to_cache(rreq, was_async); | |
| 556 | + return netfs_rreq_write_to_cache(rreq); | |
| 562 | 557 | |
| 563 | 558 | netfs_rreq_completed(rreq, was_async); |
| 564 | 559 | } |
| @@ -960,7 +955,7 @@ int netfs_readpage(struct file *file, · 395 unmodified lines | ||
| 960 | 955 | rreq = netfs_alloc_read_request(ops, netfs_priv, file); |
| 961 | 956 | if (!rreq) { |
| 962 | 957 | if (netfs_priv) |
| 963 | − ops->cleanup(netfs_priv, folio_file_mapping(folio)); | |
| 958 | + ops->cleanup(folio_file_mapping(folio), netfs_priv); | |
| 964 | 959 | folio_unlock(folio); |
| 965 | 960 | return -ENOMEM; |
| 966 | 961 | } |
| @@ -1008,8 +1003,8 @@ out: · 41 unmodified lines | ||
| 1008 | 1003 | } |
| 1009 | 1004 | EXPORT_SYMBOL(netfs_readpage); |
| 1010 | 1005 | |
| 1011 | −/** | |
| 1012 | − * netfs_skip_folio_read - prep a folio for writing without reading first | |
| 1006 | +/* | |
| 1007 | + * Prepare a folio for writing without reading first | |
| 1013 | 1008 | * @folio: The folio being prepared |
| 1014 | 1009 | * @pos: starting position for the write |
| 1015 | 1010 | * @len: length of write |
| @@ -1191,7 +1186,7 @@ have_folio: · 175 unmodified lines | ||
| 1191 | 1186 | goto error; |
| 1192 | 1187 | have_folio_no_wait: |
| 1193 | 1188 | if (netfs_priv) |
| 1194 | − ops->cleanup(netfs_priv, mapping); | |
| 1189 | + ops->cleanup(mapping, netfs_priv); | |
| 1195 | 1190 | *_folio = folio; |
| 1196 | 1191 | _leave(" = 0"); |
| 1197 | 1192 | return 0; |
| @@ -1202,7 +1197,7 @@ error: · 4 unmodified lines | ||
| 1202 | 1197 | folio_unlock(folio); |
| 1203 | 1198 | folio_put(folio); |
| 1204 | 1199 | if (netfs_priv) |
| 1205 | − ops->cleanup(netfs_priv, mapping); | |
| 1200 | + ops->cleanup(mapping, netfs_priv); | |
| 1206 | 1201 | _leave(" = %d", ret); |
| 1207 | 1202 | return ret; |
| 1208 | 1203 | } |
| @@ -2156,6 +2156,7 @@ static struct notifier_block nfsd4_cld_block = { · 2155 unmodified lines | ||
| 2156 | 2156 | int |
| 2157 | 2157 | register_cld_notifier(void) |
| 2158 | 2158 | { |
| 2159 | + WARN_ON(!nfsd_net_id); | |
| 2159 | 2160 | return rpc_pipefs_notifier_register(&nfsd4_cld_block); |
| 2160 | 2161 | } |
| 2161 | 2162 | |
| @@ -1207,6 +1207,11 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp) · 1206 unmodified lines | ||
| 1207 | 1207 | return 0; |
| 1208 | 1208 | } |
| 1209 | 1209 | |
| 1210 | +static bool delegation_hashed(struct nfs4_delegation *dp) | |
| 1211 | +{ | |
| 1212 | + return !(list_empty(&dp->dl_perfile)); | |
| 1213 | +} | |
| 1214 | + | |
| 1210 | 1215 | static bool |
| 1211 | 1216 | unhash_delegation_locked(struct nfs4_delegation *dp) |
| 1212 | 1217 | { |
| @@ -1214,7 +1219,7 @@ unhash_delegation_locked(struct nfs4_delegation *dp) · 1 unmodified line | ||
| 1214 | 1219 | |
| 1215 | 1220 | lockdep_assert_held(&state_lock); |
| 1216 | 1221 | |
| 1217 | − if (list_empty(&dp->dl_perfile)) | |
| 1222 | + if (!delegation_hashed(dp)) | |
| 1218 | 1223 | return false; |
| 1219 | 1224 | |
| 1220 | 1225 | dp->dl_stid.sc_type = NFS4_CLOSED_DELEG_STID; |
| @@ -4598,7 +4603,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) · 3377 unmodified lines | ||
| 4598 | 4603 | * queued for a lease break. Don't queue it again. |
| 4599 | 4604 | */ |
| 4600 | 4605 | spin_lock(&state_lock); |
| 4601 | − if (dp->dl_time == 0) { | |
| 4606 | + if (delegation_hashed(dp) && dp->dl_time == 0) { | |
| 4602 | 4607 | dp->dl_time = ktime_get_boottime_seconds(); |
| 4603 | 4608 | list_add_tail(&dp->dl_recall_lru, &nn->del_recall_lru); |
| 4604 | 4609 | } |
| @@ -1521,12 +1521,9 @@ static int __init init_nfsd(void) · 1520 unmodified lines | ||
| 1521 | 1521 | int retval; |
| 1522 | 1522 | printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); |
| 1523 | 1523 | |
| 1524 | − retval = register_cld_notifier(); | |
| 1525 | − if (retval) | |
| 1526 | − return retval; | |
| 1527 | 1524 | retval = nfsd4_init_slabs(); |
| 1528 | 1525 | if (retval) |
| 1529 | − goto out_unregister_notifier; | |
| 1526 | + return retval; | |
| 1530 | 1527 | retval = nfsd4_init_pnfs(); |
| 1531 | 1528 | if (retval) |
| 1532 | 1529 | goto out_free_slabs; |
| @@ -1545,9 +1542,14 @@ static int __init init_nfsd(void) · 12 unmodified lines | ||
| 1545 | 1542 | goto out_free_exports; |
| 1546 | 1543 | retval = register_pernet_subsys(&nfsd_net_ops); |
| 1547 | 1544 | if (retval < 0) |
| 1545 | + goto out_free_filesystem; | |
| 1546 | + retval = register_cld_notifier(); | |
| 1547 | + if (retval) | |
| 1548 | 1548 | goto out_free_all; |
| 1549 | 1549 | return 0; |
| 1550 | 1550 | out_free_all: |
| 1551 | + unregister_pernet_subsys(&nfsd_net_ops); | |
| 1552 | +out_free_filesystem: | |
| 1551 | 1553 | unregister_filesystem(&nfsd_fs_type); |
| 1552 | 1554 | out_free_exports: |
| 1553 | 1555 | remove_proc_entry("fs/nfs/exports", NULL); |
| @@ -1561,13 +1563,12 @@ out_free_pnfs: · 7 unmodified lines | ||
| 1561 | 1563 | nfsd4_exit_pnfs(); |
| 1562 | 1564 | out_free_slabs: |
| 1563 | 1565 | nfsd4_free_slabs(); |
| 1564 | −out_unregister_notifier: | |
| 1565 | − unregister_cld_notifier(); | |
| 1566 | 1566 | return retval; |
| 1567 | 1567 | } |
| 1568 | 1568 | |
| 1569 | 1569 | static void __exit exit_nfsd(void) |
| 1570 | 1570 | { |
| 1571 | + unregister_cld_notifier(); | |
| 1571 | 1572 | unregister_pernet_subsys(&nfsd_net_ops); |
| 1572 | 1573 | nfsd_drc_slab_free(); |
| 1573 | 1574 | remove_proc_entry("fs/nfs/exports", NULL); |
| @@ -1577,7 +1578,6 @@ static void __exit exit_nfsd(void) · 3 unmodified lines | ||
| 1577 | 1578 | nfsd4_free_slabs(); |
| 1578 | 1579 | nfsd4_exit_pnfs(); |
| 1579 | 1580 | unregister_filesystem(&nfsd_fs_type); |
| 1580 | − unregister_cld_notifier(); | |
| 1581 | 1581 | } |
| 1582 | 1582 | |
| 1583 | 1583 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); |
| @@ -35,17 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | void signalfd_cleanup(struct sighand_struct *sighand) |
| 37 | 37 | { |
| 38 | − wait_queue_head_t *wqh = &sighand->signalfd_wqh; | |
| 39 | − /* | |
| 40 | − * The lockless check can race with remove_wait_queue() in progress, | |
| 41 | − * but in this case its caller should run under rcu_read_lock() and | |
| 42 | − * sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return. | |
| 43 | − */ | |
| 44 | − if (likely(!waitqueue_active(wqh))) | |
| 45 | − return; | |
| 46 | − | |
| 47 | − /* wait_queue_entry_t->func(POLLFREE) should do remove_wait_queue() */ | |
| 48 | − wake_up_poll(wqh, EPOLLHUP | POLLFREE); | |
| 38 | + wake_up_pollfree(&sighand->signalfd_wqh); | |
| 49 | 39 | } |
| 50 | 40 | |
| 51 | 41 | struct signalfd_ctx { |
| @@ -72,16 +72,3 @@ void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int l · 71 unmodified lines | ||
| 72 | 72 | ctx->y = y; |
| 73 | 73 | } |
| 74 | 74 | EXPORT_SYMBOL_GPL(cifs_arc4_crypt); |
| 75 | − | |
| 76 | −static int __init | |
| 77 | −init_smbfs_common(void) | |
| 78 | −{ | |
| 79 | − return 0; | |
| 80 | −} | |
| 81 | −static void __init | |
| 82 | −exit_smbfs_common(void) | |
| 83 | −{ | |
| 84 | −} | |
| 85 | − | |
| 86 | −module_init(init_smbfs_common) | |
| 87 | −module_exit(exit_smbfs_common) | |
| @@ -161,6 +161,77 @@ struct tracefs_fs_info { · 160 unmodified lines | ||
| 161 | 161 | struct tracefs_mount_opts mount_opts; |
| 162 | 162 | }; |
| 163 | 163 | |
| 164 | +static void change_gid(struct dentry *dentry, kgid_t gid) | |
| 165 | +{ | |
| 166 | + if (!dentry->d_inode) | |
| 167 | + return; | |
| 168 | + dentry->d_inode->i_gid = gid; | |
| 169 | +} | |
| 170 | + | |
| 171 | +/* | |
| 172 | + * Taken from d_walk, but without he need for handling renames. | |
| 173 | + * Nothing can be renamed while walking the list, as tracefs | |
| 174 | + * does not support renames. This is only called when mounting | |
| 175 | + * or remounting the file system, to set all the files to | |
| 176 | + * the given gid. | |
| 177 | + */ | |
| 178 | +static void set_gid(struct dentry *parent, kgid_t gid) | |
| 179 | +{ | |
| 180 | + struct dentry *this_parent; | |
| 181 | + struct list_head *next; | |
| 182 | + | |
| 183 | + this_parent = parent; | |
| 184 | + spin_lock(&this_parent->d_lock); | |
| 185 | + | |
| 186 | + change_gid(this_parent, gid); | |
| 187 | +repeat: | |
| 188 | + next = this_parent->d_subdirs.next; | |
| 189 | +resume: | |
| 190 | + while (next != &this_parent->d_subdirs) { | |
| 191 | + struct list_head *tmp = next; | |
| 192 | + struct dentry *dentry = list_entry(tmp, struct dentry, d_child); | |
| 193 | + next = tmp->next; | |
| 194 | + | |
| 195 | + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); | |
| 196 | + | |
| 197 | + change_gid(dentry, gid); | |
| 198 | + | |
| 199 | + if (!list_empty(&dentry->d_subdirs)) { | |
| 200 | + spin_unlock(&this_parent->d_lock); | |
| 201 | + spin_release(&dentry->d_lock.dep_map, _RET_IP_); | |
| 202 | + this_parent = dentry; | |
| 203 | + spin_acquire(&this_parent->d_lock.dep_map, 0, 1, _RET_IP_); | |
| 204 | + goto repeat; | |
| 205 | + } | |
| 206 | + spin_unlock(&dentry->d_lock); | |
| 207 | + } | |
| 208 | + /* | |
| 209 | + * All done at this level ... ascend and resume the search. | |
| 210 | + */ | |
| 211 | + rcu_read_lock(); | |
| 212 | +ascend: | |
| 213 | + if (this_parent != parent) { | |
| 214 | + struct dentry *child = this_parent; | |
| 215 | + this_parent = child->d_parent; | |
| 216 | + | |
| 217 | + spin_unlock(&child->d_lock); | |
| 218 | + spin_lock(&this_parent->d_lock); | |
| 219 | + | |
| 220 | + /* go into the first sibling still alive */ | |
| 221 | + do { | |
| 222 | + next = child->d_child.next; | |
| 223 | + if (next == &this_parent->d_subdirs) | |
| 224 | + goto ascend; | |
| 225 | + child = list_entry(next, struct dentry, d_child); | |
| 226 | + } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); | |
| 227 | + rcu_read_unlock(); | |
| 228 | + goto resume; | |
| 229 | + } | |
| 230 | + rcu_read_unlock(); | |
| 231 | + spin_unlock(&this_parent->d_lock); | |
| 232 | + return; | |
| 233 | +} | |
| 234 | + | |
| 164 | 235 | static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) |
| 165 | 236 | { |
| 166 | 237 | substring_t args[MAX_OPT_ARGS]; |
| @@ -193,6 +264,7 @@ static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts) · 26 unmodified lines | ||
| 193 | 264 | if (!gid_valid(gid)) |
| 194 | 265 | return -EINVAL; |
| 195 | 266 | opts->gid = gid; |
| 267 | + set_gid(tracefs_mount->mnt_root, gid); | |
| 196 | 268 | break; |
| 197 | 269 | case Opt_mode: |
| 198 | 270 | if (match_octal(&args[0], &option)) |
| @@ -414,6 +486,8 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode, · 215 unmodified lines | ||
| 414 | 486 | inode->i_mode = mode; |
| 415 | 487 | inode->i_fop = fops ? fops : &tracefs_file_operations; |
| 416 | 488 | inode->i_private = data; |
| 489 | + inode->i_uid = d_inode(dentry->d_parent)->i_uid; | |
| 490 | + inode->i_gid = d_inode(dentry->d_parent)->i_gid; | |
| 417 | 491 | d_instantiate(dentry, inode); |
| 418 | 492 | fsnotify_create(dentry->d_parent->d_inode, dentry); |
| 419 | 493 | return end_creating(dentry); |
| @@ -436,6 +510,8 @@ static struct dentry *__create_dir(const char *name, struct dentry *parent, · 16 unmodified lines | ||
| 436 | 510 | inode->i_mode = S_IFDIR | S_IRWXU | S_IRUSR| S_IRGRP | S_IXUSR | S_IXGRP; |
| 437 | 511 | inode->i_op = ops; |
| 438 | 512 | inode->i_fop = &simple_dir_operations; |
| 513 | + inode->i_uid = d_inode(dentry->d_parent)->i_uid; | |
| 514 | + inode->i_gid = d_inode(dentry->d_parent)->i_gid; | |
| 439 | 515 | |
| 440 | 516 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
| 441 | 517 | inc_nlink(inode); |
| @@ -3122,7 +3122,6 @@ xfs_rename( · 3121 unmodified lines | ||
| 3122 | 3122 | * appropriately. |
| 3123 | 3123 | */ |
| 3124 | 3124 | if (flags & RENAME_WHITEOUT) { |
| 3125 | − ASSERT(!(flags & (RENAME_NOREPLACE | RENAME_EXCHANGE))); | |
| 3126 | 3125 | error = xfs_rename_alloc_whiteout(mnt_userns, target_dp, &wip); |
| 3127 | 3126 | if (error) |
| 3128 | 3127 | return error; |
| @@ -1765,7 +1765,10 @@ static int · 1764 unmodified lines | ||
| 1765 | 1765 | xfs_remount_ro( |
| 1766 | 1766 | struct xfs_mount *mp) |
| 1767 | 1767 | { |
| 1768 | − int error; | |
| 1768 | + struct xfs_icwalk icw = { | |
| 1769 | + .icw_flags = XFS_ICWALK_FLAG_SYNC, | |
| 1770 | + }; | |
| 1771 | + int error; | |
| 1769 | 1772 | |
| 1770 | 1773 | /* |
| 1771 | 1774 | * Cancel background eofb scanning so it cannot race with the final |
| @@ -1773,8 +1776,13 @@ xfs_remount_ro( · 1 unmodified line | ||
| 1773 | 1776 | */ |
| 1774 | 1777 | xfs_blockgc_stop(mp); |
| 1775 | 1778 | |
| 1776 | − /* Get rid of any leftover CoW reservations... */ | |
| 1777 | − error = xfs_blockgc_free_space(mp, NULL); | |
| 1779 | + /* | |
| 1780 | + * Clear out all remaining COW staging extents and speculative post-EOF | |
| 1781 | + * preallocations so that we don't leave inodes requiring inactivation | |
| 1782 | + * cleanups during reclaim on a read-only mount. We must process every | |
| 1783 | + * cached inode, so this requires a synchronous cache scan. | |
| 1784 | + */ | |
| 1785 | + error = xfs_blockgc_free_space(mp, &icw); | |
| 1778 | 1786 | if (error) { |
| 1779 | 1787 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
| 1780 | 1788 | return error; |
| @@ -732,6 +732,7 @@ int bpf_trampoline_unlink_prog(struct bpf_prog *prog, struct bpf_trampoline *tr) · 731 unmodified lines | ||
| 732 | 732 | struct bpf_trampoline *bpf_trampoline_get(u64 key, |
| 733 | 733 | struct bpf_attach_target_info *tgt_info); |
| 734 | 734 | void bpf_trampoline_put(struct bpf_trampoline *tr); |
| 735 | +int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs); | |
| 735 | 736 | #define BPF_DISPATCHER_INIT(_name) { \ |
| 736 | 737 | .mutex = __MUTEX_INITIALIZER(_name.mutex), \ |
| 737 | 738 | .func = &_name##_func, \ |
| @@ -1352,28 +1353,16 @@ extern struct mutex bpf_stats_enabled_mutex; · 614 unmodified lines | ||
| 1352 | 1353 | * kprobes, tracepoints) to prevent deadlocks on map operations as any of |
| 1353 | 1354 | * these events can happen inside a region which holds a map bucket lock |
| 1354 | 1355 | * and can deadlock on it. |
| 1355 | − * | |
| 1356 | − * Use the preemption safe inc/dec variants on RT because migrate disable | |
| 1357 | − * is preemptible on RT and preemption in the middle of the RMW operation | |
| 1358 | − * might lead to inconsistent state. Use the raw variants for non RT | |
| 1359 | − * kernels as migrate_disable() maps to preempt_disable() so the slightly | |
| 1360 | − * more expensive save operation can be avoided. | |
| 1361 | 1356 | */ |
| 1362 | 1357 | static inline void bpf_disable_instrumentation(void) |
| 1363 | 1358 | { |
| 1364 | 1359 | migrate_disable(); |
| 1365 | − if (IS_ENABLED(CONFIG_PREEMPT_RT)) | |
| 1366 | − this_cpu_inc(bpf_prog_active); | |
| 1367 | − else | |
| 1368 | − __this_cpu_inc(bpf_prog_active); | |
| 1360 | + this_cpu_inc(bpf_prog_active); | |
| 1369 | 1361 | } |
| 1370 | 1362 | |
| 1371 | 1363 | static inline void bpf_enable_instrumentation(void) |
| 1372 | 1364 | { |
| 1373 | − if (IS_ENABLED(CONFIG_PREEMPT_RT)) | |
| 1374 | − this_cpu_dec(bpf_prog_active); | |
| 1375 | − else | |
| 1376 | − __this_cpu_dec(bpf_prog_active); | |
| 1365 | + this_cpu_dec(bpf_prog_active); | |
| 1377 | 1366 | migrate_enable(); |
| 1378 | 1367 | } |
| 1379 | 1368 | |
| @@ -245,7 +245,10 @@ struct kfunc_btf_id_set { · 244 unmodified lines | ||
| 245 | 245 | struct module *owner; |
| 246 | 246 | }; |
| 247 | 247 | |
| 248 | −struct kfunc_btf_id_list; | |
| 248 | +struct kfunc_btf_id_list { | |
| 249 | + struct list_head list; | |
| 250 | + struct mutex mutex; | |
| 251 | +}; | |
| 249 | 252 | |
| 250 | 253 | #ifdef CONFIG_DEBUG_INFO_BTF_MODULES |
| 251 | 254 | void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l, |
| @@ -254,6 +257,9 @@ void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l, · 2 unmodified lines | ||
| 254 | 257 | struct kfunc_btf_id_set *s); |
| 255 | 258 | bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id, |
| 256 | 259 | struct module *owner); |
| 260 | + | |
| 261 | +extern struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list; | |
| 262 | +extern struct kfunc_btf_id_list prog_test_kfunc_list; | |
| 257 | 263 | #else |
| 258 | 264 | static inline void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l, |
| 259 | 265 | struct kfunc_btf_id_set *s) |
| @@ -268,13 +274,13 @@ static inline bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, · 8 unmodified lines | ||
| 268 | 274 | { |
| 269 | 275 | return false; |
| 270 | 276 | } |
| 277 | + | |
| 278 | +static struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list __maybe_unused; | |
| 279 | +static struct kfunc_btf_id_list prog_test_kfunc_list __maybe_unused; | |
| 271 | 280 | #endif |
| 272 | 281 | |
| 273 | 282 | #define DEFINE_KFUNC_BTF_ID_SET(set, name) \ |
| 274 | 283 | struct kfunc_btf_id_set name = { LIST_HEAD_INIT(name.list), (set), \ |
| 275 | 284 | THIS_MODULE } |
| 276 | 285 | |
| 277 | −extern struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list; | |
| 278 | −extern struct kfunc_btf_id_list prog_test_kfunc_list; | |
| 279 | − | |
| 280 | 286 | #endif |
| @@ -3,7 +3,6 @@ · 2 unmodified lines | ||
| 3 | 3 | #define _LINUX_CACHEINFO_H |
| 4 | 4 | |
| 5 | 5 | #include <linux/bitops.h> |
| 6 | −#include <linux/cpu.h> | |
| 7 | 6 | #include <linux/cpumask.h> |
| 8 | 7 | #include <linux/smp.h> |
| 9 | 8 | |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | */ |
| 21 | 21 | |
| 22 | 22 | #include <linux/math.h> |
| 23 | +#include <linux/sched.h> | |
| 23 | 24 | |
| 24 | 25 | extern unsigned long loops_per_jiffy; |
| 25 | 26 | |
| @@ -58,7 +59,18 @@ void calibrate_delay(void); · 32 unmodified lines | ||
| 58 | 59 | void __attribute__((weak)) calibration_delay_done(void); |
| 59 | 60 | void msleep(unsigned int msecs); |
| 60 | 61 | unsigned long msleep_interruptible(unsigned int msecs); |
| 61 | −void usleep_range(unsigned long min, unsigned long max); | |
| 62 | +void usleep_range_state(unsigned long min, unsigned long max, | |
| 63 | + unsigned int state); | |
| 64 | + | |
| 65 | +static inline void usleep_range(unsigned long min, unsigned long max) | |
| 66 | +{ | |
| 67 | + usleep_range_state(min, max, TASK_UNINTERRUPTIBLE); | |
| 68 | +} | |
| 69 | + | |
| 70 | +static inline void usleep_idle_range(unsigned long min, unsigned long max) | |
| 71 | +{ | |
| 72 | + usleep_range_state(min, max, TASK_IDLE); | |
| 73 | +} | |
| 62 | 74 | |
| 63 | 75 | static inline void ssleep(unsigned int seconds) |
| 64 | 76 | { |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/klist.h> |
| 19 | 19 | #include <linux/pm.h> |
| 20 | 20 | #include <linux/device/bus.h> |
| 21 | +#include <linux/module.h> | |
| 21 | 22 | |
| 22 | 23 | /** |
| 23 | 24 | * enum probe_type - device driver probe type to try |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #define __LINUX_FILTER_H__ |
| 7 | 7 | |
| 8 | 8 | #include <linux/atomic.h> |
| 9 | +#include <linux/bpf.h> | |
| 9 | 10 | #include <linux/refcount.h> |
| 10 | 11 | #include <linux/compat.h> |
| 11 | 12 | #include <linux/skbuff.h> |
| @@ -26,7 +27,6 @@ · 14 unmodified lines | ||
| 26 | 27 | |
| 27 | 28 | #include <asm/byteorder.h> |
| 28 | 29 | #include <uapi/linux/filter.h> |
| 29 | −#include <uapi/linux/bpf.h> | |
| 30 | 30 | |
| 31 | 31 | struct sk_buff; |
| 32 | 32 | struct sock; |
| @@ -640,9 +640,6 @@ static __always_inline u32 bpf_prog_run(const struct bpf_prog *prog, const void · 607 unmodified lines | ||
| 640 | 640 | * This uses migrate_disable/enable() explicitly to document that the |
| 641 | 641 | * invocation of a BPF program does not require reentrancy protection |
| 642 | 642 | * against a BPF program which is invoked from a preempting task. |
| 643 | − * | |
| 644 | − * For non RT enabled kernels migrate_disable/enable() maps to | |
| 645 | − * preempt_disable/enable(), i.e. it disables also preemption. | |
| 646 | 643 | */ |
| 647 | 644 | static inline u32 bpf_prog_run_pin_on_cpu(const struct bpf_prog *prog, |
| 648 | 645 | const void *ctx) |
| @@ -840,6 +840,11 @@ static inline bool hid_is_using_ll_driver(struct hid_device *hdev, · 839 unmodified lines | ||
| 840 | 840 | return hdev->ll_driver == driver; |
| 841 | 841 | } |
| 842 | 842 | |
| 843 | +static inline bool hid_is_usb(struct hid_device *hdev) | |
| 844 | +{ | |
| 845 | + return hid_is_using_ll_driver(hdev, &usb_hid_driver); | |
| 846 | +} | |
| 847 | + | |
| 843 | 848 | #define PM_HINT_FULLON 1<<5 |
| 844 | 849 | #define PM_HINT_NORMAL 1<<1 |
| 845 | 850 | |
| @@ -153,6 +153,8 @@ struct kretprobe { · 152 unmodified lines | ||
| 153 | 153 | struct kretprobe_holder *rph; |
| 154 | 154 | }; |
| 155 | 155 | |
| 156 | +#define KRETPROBE_MAX_DATA_SIZE 4096 | |
| 157 | + | |
| 156 | 158 | struct kretprobe_instance { |
| 157 | 159 | union { |
| 158 | 160 | struct freelist_node freelist; |
| @@ -663,6 +663,19 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); · 662 unmodified lines | ||
| 663 | 663 | */ |
| 664 | 664 | int mhi_pm_resume(struct mhi_controller *mhi_cntrl); |
| 665 | 665 | |
| 666 | +/** | |
| 667 | + * mhi_pm_resume_force - Force resume MHI from suspended state | |
| 668 | + * @mhi_cntrl: MHI controller | |
| 669 | + * | |
| 670 | + * Resume the device irrespective of its MHI state. As per the MHI spec, devices | |
| 671 | + * has to be in M3 state during resume. But some devices seem to be in a | |
| 672 | + * different MHI state other than M3 but they continue working fine if allowed. | |
| 673 | + * This API is intented to be used for such devices. | |
| 674 | + * | |
| 675 | + * Return: 0 if the resume succeeds, a negative error code otherwise | |
| 676 | + */ | |
| 677 | +int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl); | |
| 678 | + | |
| 666 | 679 | /** |
| 667 | 680 | * mhi_download_rddm_image - Download ramdump image from device for |
| 668 | 681 | * debugging purpose. |
| @@ -9698,7 +9698,10 @@ struct mlx5_ifc_mcam_access_reg_bits { · 9697 unmodified lines | ||
| 9698 | 9698 | u8 regs_84_to_68[0x11]; |
| 9699 | 9699 | u8 tracer_registers[0x4]; |
| 9700 | 9700 | |
| 9701 | − u8 regs_63_to_32[0x20]; | |
| 9701 | + u8 regs_63_to_46[0x12]; | |
| 9702 | + u8 mrtc[0x1]; | |
| 9703 | + u8 regs_44_to_32[0xd]; | |
| 9704 | + | |
| 9702 | 9705 | u8 regs_31_to_0[0x20]; |
| 9703 | 9706 | }; |
| 9704 | 9707 | |
| @@ -4404,7 +4404,8 @@ static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) · 4403 unmodified lines | ||
| 4404 | 4404 | static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu) |
| 4405 | 4405 | { |
| 4406 | 4406 | spin_lock(&txq->_xmit_lock); |
| 4407 | − txq->xmit_lock_owner = cpu; | |
| 4407 | + /* Pairs with READ_ONCE() in __dev_queue_xmit() */ | |
| 4408 | + WRITE_ONCE(txq->xmit_lock_owner, cpu); | |
| 4408 | 4409 | } |
| 4409 | 4410 | |
| 4410 | 4411 | static inline bool __netif_tx_acquire(struct netdev_queue *txq) |
| @@ -4421,26 +4422,32 @@ static inline void __netif_tx_release(struct netdev_queue *txq) · 10 unmodified lines | ||
| 4421 | 4422 | static inline void __netif_tx_lock_bh(struct netdev_queue *txq) |
| 4422 | 4423 | { |
| 4423 | 4424 | spin_lock_bh(&txq->_xmit_lock); |
| 4424 | − txq->xmit_lock_owner = smp_processor_id(); | |
| 4425 | + /* Pairs with READ_ONCE() in __dev_queue_xmit() */ | |
| 4426 | + WRITE_ONCE(txq->xmit_lock_owner, smp_processor_id()); | |
| 4425 | 4427 | } |
| 4426 | 4428 | |
| 4427 | 4429 | static inline bool __netif_tx_trylock(struct netdev_queue *txq) |
| 4428 | 4430 | { |
| 4429 | 4431 | bool ok = spin_trylock(&txq->_xmit_lock); |
| 4430 | − if (likely(ok)) | |
| 4431 | − txq->xmit_lock_owner = smp_processor_id(); | |
| 4432 | + | |
| 4433 | + if (likely(ok)) { | |
| 4434 | + /* Pairs with READ_ONCE() in __dev_queue_xmit() */ | |
| 4435 | + WRITE_ONCE(txq->xmit_lock_owner, smp_processor_id()); | |
| 4436 | + } | |
| 4432 | 4437 | return ok; |
| 4433 | 4438 | } |
| 4434 | 4439 | |
| 4435 | 4440 | static inline void __netif_tx_unlock(struct netdev_queue *txq) |
| 4436 | 4441 | { |
| 4437 | − txq->xmit_lock_owner = -1; | |
| 4442 | + /* Pairs with READ_ONCE() in __dev_queue_xmit() */ | |
| 4443 | + WRITE_ONCE(txq->xmit_lock_owner, -1); | |
| 4438 | 4444 | spin_unlock(&txq->_xmit_lock); |
| 4439 | 4445 | } |
| 4440 | 4446 | |
| 4441 | 4447 | static inline void __netif_tx_unlock_bh(struct netdev_queue *txq) |
| 4442 | 4448 | { |
| 4443 | − txq->xmit_lock_owner = -1; | |
| 4449 | + /* Pairs with READ_ONCE() in __dev_queue_xmit() */ | |
| 4450 | + WRITE_ONCE(txq->xmit_lock_owner, -1); | |
| 4444 | 4451 | spin_unlock_bh(&txq->_xmit_lock); |
| 4445 | 4452 | } |
| 4446 | 4453 | |
| @@ -51,9 +51,9 @@ · 50 unmodified lines | ||
| 51 | 51 | #define _LINUX_PERCPU_REFCOUNT_H |
| 52 | 52 | |
| 53 | 53 | #include <linux/atomic.h> |
| 54 | −#include <linux/kernel.h> | |
| 55 | 54 | #include <linux/percpu.h> |
| 56 | 55 | #include <linux/rcupdate.h> |
| 56 | +#include <linux/types.h> | |
| 57 | 57 | #include <linux/gfp.h> |
| 58 | 58 | |
| 59 | 59 | struct percpu_ref; |
| @@ -538,11 +538,12 @@ struct macsec_ops; · 537 unmodified lines | ||
| 538 | 538 | * @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY |
| 539 | 539 | * @state: State of the PHY for management purposes |
| 540 | 540 | * @dev_flags: Device-specific flags used by the PHY driver. |
| 541 | − * Bits [15:0] are free to use by the PHY driver to communicate | |
| 542 | − * driver specific behavior. | |
| 543 | − * Bits [23:16] are currently reserved for future use. | |
| 544 | − * Bits [31:24] are reserved for defining generic | |
| 545 | − * PHY driver behavior. | |
| 541 | + * | |
| 542 | + * - Bits [15:0] are free to use by the PHY driver to communicate | |
| 543 | + * driver specific behavior. | |
| 544 | + * - Bits [23:16] are currently reserved for future use. | |
| 545 | + * - Bits [31:24] are reserved for defining generic | |
| 546 | + * PHY driver behavior. | |
| 546 | 547 | * @irq: IRQ number of the PHY's interrupt (-1 if none) |
| 547 | 548 | * @phy_timer: The timer for handling the state machine |
| 548 | 549 | * @phylink: Pointer to phylink instance for this PHY |
| @@ -129,7 +129,7 @@ static inline bool pm_runtime_suspended(struct device *dev) · 128 unmodified lines | ||
| 129 | 129 | * pm_runtime_active - Check whether or not a device is runtime-active. |
| 130 | 130 | * @dev: Target device. |
| 131 | 131 | * |
| 132 | − * Return %true if runtime PM is enabled for @dev and its runtime PM status is | |
| 132 | + * Return %true if runtime PM is disabled for @dev or its runtime PM status is | |
| 133 | 133 | * %RPM_ACTIVE, or %false otherwise. |
| 134 | 134 | * |
| 135 | 135 | * Note that the return value of this function can only be trusted if it is |
| @@ -499,7 +499,8 @@ struct regulator_irq_data { · 498 unmodified lines | ||
| 499 | 499 | * best to shut-down regulator(s) or reboot the SOC if error |
| 500 | 500 | * handling is repeatedly failing. If fatal_cnt is given the IRQ |
| 501 | 501 | * handling is aborted if it fails for fatal_cnt times and die() |
| 502 | − * callback (if populated) or BUG() is called to try to prevent | |
| 502 | + * callback (if populated) is called. If die() is not populated | |
| 503 | + * poweroff for the system is attempted in order to prevent any | |
| 503 | 504 | * further damage. |
| 504 | 505 | * @reread_ms: The time which is waited before attempting to re-read status |
| 505 | 506 | * at the worker if IC reading fails. Immediate re-read is done |
| @@ -516,11 +517,12 @@ struct regulator_irq_data { · 10 unmodified lines | ||
| 516 | 517 | * @data: Driver private data pointer which will be passed as such to |
| 517 | 518 | * the renable, map_event and die callbacks in regulator_irq_data. |
| 518 | 519 | * @die: Protection callback. If IC status reading or recovery actions |
| 519 | − * fail fatal_cnt times this callback or BUG() is called. This | |
| 520 | − * callback should implement a final protection attempt like | |
| 521 | − * disabling the regulator. If protection succeeded this may | |
| 522 | − * return 0. If anything else is returned the core assumes final | |
| 523 | − * protection failed and calls BUG() as a last resort. | |
| 520 | + * fail fatal_cnt times this callback is called or system is | |
| 521 | + * powered off. This callback should implement a final protection | |
| 522 | + * attempt like disabling the regulator. If protection succeeded | |
| 523 | + * die() may return 0. If anything else is returned the core | |
| 524 | + * assumes final protection failed and attempts to perform a | |
| 525 | + * poweroff as a last resort. | |
| 524 | 526 | * @map_event: Driver callback to map IRQ status into regulator devices with |
| 525 | 527 | * events / errors. NOTE: callback MUST initialize both the |
| 526 | 528 | * errors and notifs for all rdevs which it signals having |
| @@ -18,15 +18,16 @@ · 17 unmodified lines | ||
| 18 | 18 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
| 19 | 19 | |
| 20 | 20 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN |
| 21 | −extern void task_cputime(struct task_struct *t, | |
| 21 | +extern bool task_cputime(struct task_struct *t, | |
| 22 | 22 | u64 *utime, u64 *stime); |
| 23 | 23 | extern u64 task_gtime(struct task_struct *t); |
| 24 | 24 | #else |
| 25 | −static inline void task_cputime(struct task_struct *t, | |
| 25 | +static inline bool task_cputime(struct task_struct *t, | |
| 26 | 26 | u64 *utime, u64 *stime) |
| 27 | 27 | { |
| 28 | 28 | *utime = t->utime; |
| 29 | 29 | *stime = t->stime; |
| 30 | + return false; | |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | 33 | static inline u64 task_gtime(struct task_struct *t) |
| @@ -27,9 +27,7 @@ static inline bool siphash_key_is_zero(const siphash_key_t *key) · 26 unmodified lines | ||
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key); |
| 30 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 31 | 30 | u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key); |
| 32 | −#endif | |
| 33 | 31 | |
| 34 | 32 | u64 siphash_1u64(const u64 a, const siphash_key_t *key); |
| 35 | 33 | u64 siphash_2u64(const u64 a, const u64 b, const siphash_key_t *key); |
| @@ -82,10 +80,9 @@ static inline u64 ___siphash_aligned(const __le64 *data, size_t len, · 46 unmodified lines | ||
| 82 | 80 | static inline u64 siphash(const void *data, size_t len, |
| 83 | 81 | const siphash_key_t *key) |
| 84 | 82 | { |
| 85 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 86 | − if (!IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) | |
| 83 | + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || | |
| 84 | + !IS_ALIGNED((unsigned long)data, SIPHASH_ALIGNMENT)) | |
| 87 | 85 | return __siphash_unaligned(data, len, key); |
| 88 | −#endif | |
| 89 | 86 | return ___siphash_aligned(data, len, key); |
| 90 | 87 | } |
| 91 | 88 | |
| @@ -96,10 +93,8 @@ typedef struct { · 4 unmodified lines | ||
| 96 | 93 | |
| 97 | 94 | u32 __hsiphash_aligned(const void *data, size_t len, |
| 98 | 95 | const hsiphash_key_t *key); |
| 99 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 100 | 96 | u32 __hsiphash_unaligned(const void *data, size_t len, |
| 101 | 97 | const hsiphash_key_t *key); |
| 102 | −#endif | |
| 103 | 98 | |
| 104 | 99 | u32 hsiphash_1u32(const u32 a, const hsiphash_key_t *key); |
| 105 | 100 | u32 hsiphash_2u32(const u32 a, const u32 b, const hsiphash_key_t *key); |
| @@ -135,10 +130,9 @@ static inline u32 ___hsiphash_aligned(const __le32 *data, size_t len, · 29 unmodified lines | ||
| 135 | 130 | static inline u32 hsiphash(const void *data, size_t len, |
| 136 | 131 | const hsiphash_key_t *key) |
| 137 | 132 | { |
| 138 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 139 | − if (!IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) | |
| 133 | + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || | |
| 134 | + !IS_ALIGNED((unsigned long)data, HSIPHASH_ALIGNMENT)) | |
| 140 | 135 | return __hsiphash_unaligned(data, len, key); |
| 141 | −#endif | |
| 142 | 136 | return ___hsiphash_aligned(data, len, key); |
| 143 | 137 | } |
| 144 | 138 | |
| @@ -217,6 +217,7 @@ void __wake_up_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void · 216 unmodified lines | ||
| 217 | 217 | void __wake_up_locked_sync_key(struct wait_queue_head *wq_head, unsigned int mode, void *key); |
| 218 | 218 | void __wake_up_locked(struct wait_queue_head *wq_head, unsigned int mode, int nr); |
| 219 | 219 | void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); |
| 220 | +void __wake_up_pollfree(struct wait_queue_head *wq_head); | |
| 220 | 221 | |
| 221 | 222 | #define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) |
| 222 | 223 | #define wake_up_nr(x, nr) __wake_up(x, TASK_NORMAL, nr, NULL) |
| @@ -245,6 +246,31 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode); · 22 unmodified lines | ||
| 245 | 246 | #define wake_up_interruptible_sync_poll_locked(x, m) \ |
| 246 | 247 | __wake_up_locked_sync_key((x), TASK_INTERRUPTIBLE, poll_to_key(m)) |
| 247 | 248 | |
| 249 | +/** | |
| 250 | + * wake_up_pollfree - signal that a polled waitqueue is going away | |
| 251 | + * @wq_head: the wait queue head | |
| 252 | + * | |
| 253 | + * In the very rare cases where a ->poll() implementation uses a waitqueue whose | |
| 254 | + * lifetime is tied to a task rather than to the 'struct file' being polled, | |
| 255 | + * this function must be called before the waitqueue is freed so that | |
| 256 | + * non-blocking polls (e.g. epoll) are notified that the queue is going away. | |
| 257 | + * | |
| 258 | + * The caller must also RCU-delay the freeing of the wait_queue_head, e.g. via | |
| 259 | + * an explicit synchronize_rcu() or call_rcu(), or via SLAB_TYPESAFE_BY_RCU. | |
| 260 | + */ | |
| 261 | +static inline void wake_up_pollfree(struct wait_queue_head *wq_head) | |
| 262 | +{ | |
| 263 | + /* | |
| 264 | + * For performance reasons, we don't always take the queue lock here. | |
| 265 | + * Therefore, we might race with someone removing the last entry from | |
| 266 | + * the queue, and proceed while they still hold the queue lock. | |
| 267 | + * However, rcu_read_lock() is required to be held in such cases, so we | |
| 268 | + * can safely proceed with an RCU-delayed free. | |
| 269 | + */ | |
| 270 | + if (waitqueue_active(wq_head)) | |
| 271 | + __wake_up_pollfree(wq_head); | |
| 272 | +} | |
| 273 | + | |
| 248 | 274 | #define ___wait_cond_timeout(condition) \ |
| 249 | 275 | ({ \ |
| 250 | 276 | bool __cond = (condition); \ |
| @@ -126,7 +126,7 @@ struct tlb_slave_info { · 125 unmodified lines | ||
| 126 | 126 | struct alb_bond_info { |
| 127 | 127 | struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */ |
| 128 | 128 | u32 unbalanced_load; |
| 129 | − int tx_rebalance_counter; | |
| 129 | + atomic_t tx_rebalance_counter; | |
| 130 | 130 | int lp_counter; |
| 131 | 131 | /* -------- rlb parameters -------- */ |
| 132 | 132 | int rlb_enabled; |
| @@ -132,6 +132,19 @@ static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb) · 131 unmodified lines | ||
| 132 | 132 | #ifdef CONFIG_NET_RX_BUSY_POLL |
| 133 | 133 | if (unlikely(READ_ONCE(sk->sk_napi_id) != skb->napi_id)) |
| 134 | 134 | WRITE_ONCE(sk->sk_napi_id, skb->napi_id); |
| 135 | +#endif | |
| 136 | + sk_rx_queue_update(sk, skb); | |
| 137 | +} | |
| 138 | + | |
| 139 | +/* Variant of sk_mark_napi_id() for passive flow setup, | |
| 140 | + * as sk->sk_napi_id and sk->sk_rx_queue_mapping content | |
| 141 | + * needs to be set. | |
| 142 | + */ | |
| 143 | +static inline void sk_mark_napi_id_set(struct sock *sk, | |
| 144 | + const struct sk_buff *skb) | |
| 145 | +{ | |
| 146 | +#ifdef CONFIG_NET_RX_BUSY_POLL | |
| 147 | + WRITE_ONCE(sk->sk_napi_id, skb->napi_id); | |
| 135 | 148 | #endif |
| 136 | 149 | sk_rx_queue_set(sk, skb); |
| 137 | 150 | } |
| @@ -79,6 +79,17 @@ static inline void dst_cache_reset(struct dst_cache *dst_cache) · 78 unmodified lines | ||
| 79 | 79 | dst_cache->reset_ts = jiffies; |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | +/** | |
| 83 | + * dst_cache_reset_now - invalidate the cache contents immediately | |
| 84 | + * @dst_cache: the cache | |
| 85 | + * | |
| 86 | + * The caller must be sure there are no concurrent users, as this frees | |
| 87 | + * all dst_cache users immediately, rather than waiting for the next | |
| 88 | + * per-cpu usage like dst_cache_reset does. Most callers should use the | |
| 89 | + * higher speed lazily-freed dst_cache_reset function instead. | |
| 90 | + */ | |
| 91 | +void dst_cache_reset_now(struct dst_cache *dst_cache); | |
| 92 | + | |
| 82 | 93 | /** |
| 83 | 94 | * dst_cache_init - initialize the cache, allocating the required storage |
| 84 | 95 | * @dst_cache: the cache |
| @@ -69,7 +69,7 @@ struct fib_rules_ops { · 68 unmodified lines | ||
| 69 | 69 | int (*action)(struct fib_rule *, |
| 70 | 70 | struct flowi *, int, |
| 71 | 71 | struct fib_lookup_arg *); |
| 72 | − bool (*suppress)(struct fib_rule *, | |
| 72 | + bool (*suppress)(struct fib_rule *, int, | |
| 73 | 73 | struct fib_lookup_arg *); |
| 74 | 74 | int (*match)(struct fib_rule *, |
| 75 | 75 | struct flowi *, int); |
| @@ -218,7 +218,9 @@ INDIRECT_CALLABLE_DECLARE(int fib4_rule_action(struct fib_rule *rule, · 142 unmodified lines | ||
| 218 | 218 | struct fib_lookup_arg *arg)); |
| 219 | 219 | |
| 220 | 220 | INDIRECT_CALLABLE_DECLARE(bool fib6_rule_suppress(struct fib_rule *rule, |
| 221 | + int flags, | |
| 221 | 222 | struct fib_lookup_arg *arg)); |
| 222 | 223 | INDIRECT_CALLABLE_DECLARE(bool fib4_rule_suppress(struct fib_rule *rule, |
| 224 | + int flags, | |
| 223 | 225 | struct fib_lookup_arg *arg)); |
| 224 | 226 | #endif |
| @@ -438,7 +438,7 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, · 437 unmodified lines | ||
| 438 | 438 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 439 | 439 | static inline int fib_num_tclassid_users(struct net *net) |
| 440 | 440 | { |
| 441 | − return net->ipv4.fib_num_tclassid_users; | |
| 441 | + return atomic_read(&net->ipv4.fib_num_tclassid_users); | |
| 442 | 442 | } |
| 443 | 443 | #else |
| 444 | 444 | static inline int fib_num_tclassid_users(struct net *net) |
| @@ -276,14 +276,14 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb) · 275 unmodified lines | ||
| 276 | 276 | /* jiffies until ct expires, 0 if already expired */ |
| 277 | 277 | static inline unsigned long nf_ct_expires(const struct nf_conn *ct) |
| 278 | 278 | { |
| 279 | − s32 timeout = ct->timeout - nfct_time_stamp; | |
| 279 | + s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; | |
| 280 | 280 | |
| 281 | 281 | return timeout > 0 ? timeout : 0; |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | 284 | static inline bool nf_ct_is_expired(const struct nf_conn *ct) |
| 285 | 285 | { |
| 286 | − return (__s32)(ct->timeout - nfct_time_stamp) <= 0; | |
| 286 | + return (__s32)(READ_ONCE(ct->timeout) - nfct_time_stamp) <= 0; | |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | 289 | /* use after obtaining a reference count */ |
| @@ -302,7 +302,7 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct) · 12 unmodified lines | ||
| 302 | 302 | static inline void nf_ct_offload_timeout(struct nf_conn *ct) |
| 303 | 303 | { |
| 304 | 304 | if (nf_ct_expires(ct) < NF_CT_DAY / 2) |
| 305 | − ct->timeout = nfct_time_stamp + NF_CT_DAY; | |
| 305 | + WRITE_ONCE(ct->timeout, nfct_time_stamp + NF_CT_DAY); | |
| 306 | 306 | } |
| 307 | 307 | |
| 308 | 308 | struct kernel_param; |
| @@ -65,7 +65,7 @@ struct netns_ipv4 { · 64 unmodified lines | ||
| 65 | 65 | bool fib_has_custom_local_routes; |
| 66 | 66 | bool fib_offload_disabled; |
| 67 | 67 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 68 | − int fib_num_tclassid_users; | |
| 68 | + atomic_t fib_num_tclassid_users; | |
| 69 | 69 | #endif |
| 70 | 70 | struct hlist_head *fib_table_hash; |
| 71 | 71 | struct sock *fibnl; |
| @@ -1913,18 +1913,31 @@ static inline int sk_tx_queue_get(const struct sock *sk) · 1912 unmodified lines | ||
| 1913 | 1913 | return -1; |
| 1914 | 1914 | } |
| 1915 | 1915 | |
| 1916 | −static inline void sk_rx_queue_set(struct sock *sk, const struct sk_buff *skb) | |
| 1916 | +static inline void __sk_rx_queue_set(struct sock *sk, | |
| 1917 | + const struct sk_buff *skb, | |
| 1918 | + bool force_set) | |
| 1917 | 1919 | { |
| 1918 | 1920 | #ifdef CONFIG_SOCK_RX_QUEUE_MAPPING |
| 1919 | 1921 | if (skb_rx_queue_recorded(skb)) { |
| 1920 | 1922 | u16 rx_queue = skb_get_rx_queue(skb); |
| 1921 | 1923 | |
| 1922 | − if (unlikely(READ_ONCE(sk->sk_rx_queue_mapping) != rx_queue)) | |
| 1924 | + if (force_set || | |
| 1925 | + unlikely(READ_ONCE(sk->sk_rx_queue_mapping) != rx_queue)) | |
| 1923 | 1926 | WRITE_ONCE(sk->sk_rx_queue_mapping, rx_queue); |
| 1924 | 1927 | } |
| 1925 | 1928 | #endif |
| 1926 | 1929 | } |
| 1927 | 1930 | |
| 1931 | +static inline void sk_rx_queue_set(struct sock *sk, const struct sk_buff *skb) | |
| 1932 | +{ | |
| 1933 | + __sk_rx_queue_set(sk, skb, true); | |
| 1934 | +} | |
| 1935 | + | |
| 1936 | +static inline void sk_rx_queue_update(struct sock *sk, const struct sk_buff *skb) | |
| 1937 | +{ | |
| 1938 | + __sk_rx_queue_set(sk, skb, false); | |
| 1939 | +} | |
| 1940 | + | |
| 1928 | 1941 | static inline void sk_rx_queue_clear(struct sock *sk) |
| 1929 | 1942 | { |
| 1930 | 1943 | #ifdef CONFIG_SOCK_RX_QUEUE_MAPPING |
| @@ -2430,19 +2443,22 @@ static inline void sk_stream_moderate_sndbuf(struct sock *sk) · 499 unmodified lines | ||
| 2430 | 2443 | * @sk: socket |
| 2431 | 2444 | * |
| 2432 | 2445 | * Use the per task page_frag instead of the per socket one for |
| 2433 | − * optimization when we know that we're in the normal context and owns | |
| 2446 | + * optimization when we know that we're in process context and own | |
| 2434 | 2447 | * everything that's associated with %current. |
| 2435 | 2448 | * |
| 2436 | − * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest | |
| 2437 | − * inside other socket operations and end up recursing into sk_page_frag() | |
| 2438 | − * while it's already in use. | |
| 2449 | + * Both direct reclaim and page faults can nest inside other | |
| 2450 | + * socket operations and end up recursing into sk_page_frag() | |
| 2451 | + * while it's already in use: explicitly avoid task page_frag | |
| 2452 | + * usage if the caller is potentially doing any of them. | |
| 2453 | + * This assumes that page fault handlers use the GFP_NOFS flags. | |
| 2439 | 2454 | * |
| 2440 | 2455 | * Return: a per task page_frag if context allows that, |
| 2441 | 2456 | * otherwise a per socket one. |
| 2442 | 2457 | */ |
| 2443 | 2458 | static inline struct page_frag *sk_page_frag(struct sock *sk) |
| 2444 | 2459 | { |
| 2445 | − if (gfpflags_normal_context(sk->sk_allocation)) | |
| 2460 | + if ((sk->sk_allocation & (__GFP_DIRECT_RECLAIM | __GFP_MEMALLOC | __GFP_FS)) == | |
| 2461 | + (__GFP_DIRECT_RECLAIM | __GFP_FS)) | |
| 2446 | 2462 | return ¤t->task_frag; |
| 2447 | 2463 | |
| 2448 | 2464 | return &sk->sk_frag; |
| @@ -147,7 +147,7 @@ struct snd_soc_acpi_link_adr { · 146 unmodified lines | ||
| 147 | 147 | */ |
| 148 | 148 | /* Descriptor for SST ASoC machine driver */ |
| 149 | 149 | struct snd_soc_acpi_mach { |
| 150 | − const u8 id[ACPI_ID_LEN]; | |
| 150 | + u8 id[ACPI_ID_LEN]; | |
| 151 | 151 | const struct snd_soc_acpi_codecs *comp_ids; |
| 152 | 152 | const u32 link_mask; |
| 153 | 153 | const struct snd_soc_acpi_link_adr *links; |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #define POLLRDHUP 0x2000 |
| 30 | 30 | #endif |
| 31 | 31 | |
| 32 | −#define POLLFREE (__force __poll_t)0x4000 /* currently only for epoll */ | |
| 32 | +#define POLLFREE (__force __poll_t)0x4000 | |
| 33 | 33 | |
| 34 | 34 | #define POLL_BUSY_LOOP (__force __poll_t)0x8000 |
| 35 | 35 | |
| @@ -196,6 +196,13 @@ struct drm_virtgpu_context_init { · 195 unmodified lines | ||
| 196 | 196 | __u64 ctx_set_params; |
| 197 | 197 | }; |
| 198 | 198 | |
| 199 | +/* | |
| 200 | + * Event code that's given when VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK is in | |
| 201 | + * effect. The event size is sizeof(drm_event), since there is no additional | |
| 202 | + * payload. | |
| 203 | + */ | |
| 204 | +#define VIRTGPU_EVENT_FENCE_SIGNALED 0x90000000 | |
| 205 | + | |
| 199 | 206 | #define DRM_IOCTL_VIRTGPU_MAP \ |
| 200 | 207 | DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) |
| 201 | 208 | |
| @@ -117,7 +117,7 @@ · 116 unmodified lines | ||
| 117 | 117 | #define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ |
| 118 | 118 | #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ |
| 119 | 119 | |
| 120 | −#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value | |
| 120 | +#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is more than this value | |
| 121 | 121 | * then the frame is Ethernet II. Else it is 802.3 */ |
| 122 | 122 | |
| 123 | 123 | /* |
| @@ -66,10 +66,17 @@ struct rlimit64 { · 65 unmodified lines | ||
| 66 | 66 | #define _STK_LIM (8*1024*1024) |
| 67 | 67 | |
| 68 | 68 | /* |
| 69 | − * GPG2 wants 64kB of mlocked memory, to make sure pass phrases | |
| 70 | − * and other sensitive information are never written to disk. | |
| 69 | + * Limit the amount of locked memory by some sane default: | |
| 70 | + * root can always increase this limit if needed. | |
| 71 | + * | |
| 72 | + * The main use-cases are (1) preventing sensitive memory | |
| 73 | + * from being swapped; (2) real-time operations; (3) via | |
| 74 | + * IOURING_REGISTER_BUFFERS. | |
| 75 | + * | |
| 76 | + * The first two don't need much. The latter will take as | |
| 77 | + * much as it can get. 8MB is a reasonably sane default. | |
| 71 | 78 | */ |
| 72 | −#define MLOCK_LIMIT ((PAGE_SIZE > 64*1024) ? PAGE_SIZE : 64*1024) | |
| 79 | +#define MLOCK_LIMIT (8*1024*1024) | |
| 73 | 80 | |
| 74 | 81 | /* |
| 75 | 82 | * Due to binary compatibility, the actual resource numbers |
| @@ -6346,11 +6346,6 @@ BTF_ID_LIST_GLOBAL_SINGLE(btf_task_struct_ids, struct, task_struct) · 6345 unmodified lines | ||
| 6346 | 6346 | |
| 6347 | 6347 | /* BTF ID set registration API for modules */ |
| 6348 | 6348 | |
| 6349 | −struct kfunc_btf_id_list { | |
| 6350 | − struct list_head list; | |
| 6351 | − struct mutex mutex; | |
| 6352 | −}; | |
| 6353 | − | |
| 6354 | 6349 | #ifdef CONFIG_DEBUG_INFO_BTF_MODULES |
| 6355 | 6350 | |
| 6356 | 6351 | void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l, |
| @@ -6376,8 +6371,6 @@ bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id, · 19 unmodified lines | ||
| 6376 | 6371 | { |
| 6377 | 6372 | struct kfunc_btf_id_set *s; |
| 6378 | 6373 | |
| 6379 | − if (!owner) | |
| 6380 | − return false; | |
| 6381 | 6374 | mutex_lock(&klist->mutex); |
| 6382 | 6375 | list_for_each_entry(s, &klist->list, list) { |
| 6383 | 6376 | if (s->owner == owner && btf_id_set_contains(s->set, kfunc_id)) { |
| @@ -6389,8 +6382,6 @@ bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id, · 5 unmodified lines | ||
| 6389 | 6382 | return false; |
| 6390 | 6383 | } |
| 6391 | 6384 | |
| 6392 | −#endif | |
| 6393 | − | |
| 6394 | 6385 | #define DEFINE_KFUNC_BTF_ID_LIST(name) \ |
| 6395 | 6386 | struct kfunc_btf_id_list name = { LIST_HEAD_INIT(name.list), \ |
| 6396 | 6387 | __MUTEX_INITIALIZER(name.mutex) }; \ |
| @@ -6398,3 +6389,5 @@ bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id, · 1 unmodified line | ||
| 6398 | 6389 | |
| 6399 | 6390 | DEFINE_KFUNC_BTF_ID_LIST(bpf_tcp_ca_kfunc_list); |
| 6400 | 6391 | DEFINE_KFUNC_BTF_ID_LIST(prog_test_kfunc_list); |
| 6392 | + | |
| 6393 | +#endif | |
| @@ -8422,7 +8422,7 @@ static void find_good_pkt_pointers(struct bpf_verifier_state *vstate, · 8421 unmodified lines | ||
| 8422 | 8422 | |
| 8423 | 8423 | new_range = dst_reg->off; |
| 8424 | 8424 | if (range_right_open) |
| 8425 | − new_range--; | |
| 8425 | + new_range++; | |
| 8426 | 8426 | |
| 8427 | 8427 | /* Examples for register markings: |
| 8428 | 8428 | * |
| @@ -2086,6 +2086,9 @@ int register_kretprobe(struct kretprobe *rp) · 2085 unmodified lines | ||
| 2086 | 2086 | } |
| 2087 | 2087 | } |
| 2088 | 2088 | |
| 2089 | + if (rp->data_size > KRETPROBE_MAX_DATA_SIZE) | |
| 2090 | + return -E2BIG; | |
| 2091 | + | |
| 2089 | 2092 | rp->kp.pre_handler = pre_handler_kretprobe; |
| 2090 | 2093 | rp->kp.post_handler = NULL; |
| 2091 | 2094 | |
| @@ -1918,7 +1918,7 @@ static void __init init_uclamp_rq(struct rq *rq) · 1917 unmodified lines | ||
| 1918 | 1918 | }; |
| 1919 | 1919 | } |
| 1920 | 1920 | |
| 1921 | − rq->uclamp_flags = 0; | |
| 1921 | + rq->uclamp_flags = UCLAMP_FLAG_IDLE; | |
| 1922 | 1922 | } |
| 1923 | 1923 | |
| 1924 | 1924 | static void __init init_uclamp(void) |
| @@ -6617,11 +6617,11 @@ static int __init setup_preempt_mode(char *str) · 4692 unmodified lines | ||
| 6617 | 6617 | int mode = sched_dynamic_mode(str); |
| 6618 | 6618 | if (mode < 0) { |
| 6619 | 6619 | pr_warn("Dynamic Preempt: unsupported mode: %s\n", str); |
| 6620 | − return 1; | |
| 6620 | + return 0; | |
| 6621 | 6621 | } |
| 6622 | 6622 | |
| 6623 | 6623 | sched_dynamic_update(mode); |
| 6624 | − return 0; | |
| 6624 | + return 1; | |
| 6625 | 6625 | } |
| 6626 | 6626 | __setup("preempt=", setup_preempt_mode); |
| 6627 | 6627 | |
| @@ -615,7 +615,8 @@ void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) · 614 unmodified lines | ||
| 615 | 615 | .sum_exec_runtime = p->se.sum_exec_runtime, |
| 616 | 616 | }; |
| 617 | 617 | |
| 618 | − task_cputime(p, &cputime.utime, &cputime.stime); | |
| 618 | + if (task_cputime(p, &cputime.utime, &cputime.stime)) | |
| 619 | + cputime.sum_exec_runtime = task_sched_runtime(p); | |
| 619 | 620 | cputime_adjust(&cputime, &p->prev_cputime, ut, st); |
| 620 | 621 | } |
| 621 | 622 | EXPORT_SYMBOL_GPL(task_cputime_adjusted); |
| @@ -828,19 +829,21 @@ u64 task_gtime(struct task_struct *t) · 206 unmodified lines | ||
| 828 | 829 | * add up the pending nohz execution time since the last |
| 829 | 830 | * cputime snapshot. |
| 830 | 831 | */ |
| 831 | −void task_cputime(struct task_struct *t, u64 *utime, u64 *stime) | |
| 832 | +bool task_cputime(struct task_struct *t, u64 *utime, u64 *stime) | |
| 832 | 833 | { |
| 833 | 834 | struct vtime *vtime = &t->vtime; |
| 834 | 835 | unsigned int seq; |
| 835 | 836 | u64 delta; |
| 837 | + int ret; | |
| 836 | 838 | |
| 837 | 839 | if (!vtime_accounting_enabled()) { |
| 838 | 840 | *utime = t->utime; |
| 839 | 841 | *stime = t->stime; |
| 840 | − return; | |
| 842 | + return false; | |
| 841 | 843 | } |
| 842 | 844 | |
| 843 | 845 | do { |
| 846 | + ret = false; | |
| 844 | 847 | seq = read_seqcount_begin(&vtime->seqcount); |
| 845 | 848 | |
| 846 | 849 | *utime = t->utime; |
| @@ -850,6 +853,7 @@ void task_cputime(struct task_struct *t, u64 *utime, u64 *stime) · 3 unmodified lines | ||
| 850 | 853 | if (vtime->state < VTIME_SYS) |
| 851 | 854 | continue; |
| 852 | 855 | |
| 856 | + ret = true; | |
| 853 | 857 | delta = vtime_delta(vtime); |
| 854 | 858 | |
| 855 | 859 | /* |
| @@ -861,6 +865,8 @@ void task_cputime(struct task_struct *t, u64 *utime, u64 *stime) · 5 unmodified lines | ||
| 861 | 865 | else |
| 862 | 866 | *utime += vtime->utime + delta; |
| 863 | 867 | } while (read_seqcount_retry(&vtime->seqcount, seq)); |
| 868 | + | |
| 869 | + return ret; | |
| 864 | 870 | } |
| 865 | 871 | |
| 866 | 872 | static int vtime_state_fetch(struct vtime *vtime, int cpu) |
| @@ -238,6 +238,13 @@ void __wake_up_sync(struct wait_queue_head *wq_head, unsigned int mode) · 237 unmodified lines | ||
| 238 | 238 | } |
| 239 | 239 | EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ |
| 240 | 240 | |
| 241 | +void __wake_up_pollfree(struct wait_queue_head *wq_head) | |
| 242 | +{ | |
| 243 | + __wake_up(wq_head, TASK_NORMAL, 0, poll_to_key(EPOLLHUP | POLLFREE)); | |
| 244 | + /* POLLFREE must have cleared the queue. */ | |
| 245 | + WARN_ON_ONCE(waitqueue_active(wq_head)); | |
| 246 | +} | |
| 247 | + | |
| 241 | 248 | /* |
| 242 | 249 | * Note: we use "set_current_state()" _after_ the wait-queue add, |
| 243 | 250 | * because we need a memory barrier there on SMP, so that any |
| @@ -595,7 +595,8 @@ void irq_enter_rcu(void) · 594 unmodified lines | ||
| 595 | 595 | { |
| 596 | 596 | __irq_enter_raw(); |
| 597 | 597 | |
| 598 | − if (is_idle_task(current) && (irq_count() == HARDIRQ_OFFSET)) | |
| 598 | + if (tick_nohz_full_cpu(smp_processor_id()) || | |
| 599 | + (is_idle_task(current) && (irq_count() == HARDIRQ_OFFSET))) | |
| 599 | 600 | tick_irq_enter(); |
| 600 | 601 | |
| 601 | 602 | account_hardirq_enter(current); |
| @@ -1375,6 +1375,13 @@ static inline void tick_nohz_irq_enter(void) · 1374 unmodified lines | ||
| 1375 | 1375 | now = ktime_get(); |
| 1376 | 1376 | if (ts->idle_active) |
| 1377 | 1377 | tick_nohz_stop_idle(ts, now); |
| 1378 | + /* | |
| 1379 | + * If all CPUs are idle. We may need to update a stale jiffies value. | |
| 1380 | + * Note nohz_full is a special case: a timekeeper is guaranteed to stay | |
| 1381 | + * alive but it might be busy looping with interrupts disabled in some | |
| 1382 | + * rare case (typically stop machine). So we must make sure we have a | |
| 1383 | + * last resort. | |
| 1384 | + */ | |
| 1378 | 1385 | if (ts->tick_stopped) |
| 1379 | 1386 | tick_nohz_update_jiffies(now); |
| 1380 | 1387 | } |
| @@ -2054,26 +2054,28 @@ unsigned long msleep_interruptible(unsigned int msecs) · 2053 unmodified lines | ||
| 2054 | 2054 | EXPORT_SYMBOL(msleep_interruptible); |
| 2055 | 2055 | |
| 2056 | 2056 | /** |
| 2057 | − * usleep_range - Sleep for an approximate time | |
| 2058 | − * @min: Minimum time in usecs to sleep | |
| 2059 | − * @max: Maximum time in usecs to sleep | |
| 2057 | + * usleep_range_state - Sleep for an approximate time in a given state | |
| 2058 | + * @min: Minimum time in usecs to sleep | |
| 2059 | + * @max: Maximum time in usecs to sleep | |
| 2060 | + * @state: State of the current task that will be while sleeping | |
| 2060 | 2061 | * |
| 2061 | 2062 | * In non-atomic context where the exact wakeup time is flexible, use |
| 2062 | − * usleep_range() instead of udelay(). The sleep improves responsiveness | |
| 2063 | + * usleep_range_state() instead of udelay(). The sleep improves responsiveness | |
| 2063 | 2064 | * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces |
| 2064 | 2065 | * power usage by allowing hrtimers to take advantage of an already- |
| 2065 | 2066 | * scheduled interrupt instead of scheduling a new one just for this sleep. |
| 2066 | 2067 | */ |
| 2067 | −void __sched usleep_range(unsigned long min, unsigned long max) | |
| 2068 | +void __sched usleep_range_state(unsigned long min, unsigned long max, | |
| 2069 | + unsigned int state) | |
| 2068 | 2070 | { |
| 2069 | 2071 | ktime_t exp = ktime_add_us(ktime_get(), min); |
| 2070 | 2072 | u64 delta = (u64)(max - min) * NSEC_PER_USEC; |
| 2071 | 2073 | |
| 2072 | 2074 | for (;;) { |
| 2073 | − __set_current_state(TASK_UNINTERRUPTIBLE); | |
| 2075 | + __set_current_state(state); | |
| 2074 | 2076 | /* Do not return before the requested sleep time has elapsed */ |
| 2075 | 2077 | if (!schedule_hrtimeout_range(&exp, delta, HRTIMER_MODE_ABS)) |
| 2076 | 2078 | break; |
| 2077 | 2079 | } |
| 2078 | 2080 | } |
| 2079 | −EXPORT_SYMBOL(usleep_range); | |
| 2081 | +EXPORT_SYMBOL(usleep_range_state); | |
| @@ -5217,6 +5217,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) · 5216 unmodified lines | ||
| 5217 | 5217 | { |
| 5218 | 5218 | struct ftrace_direct_func *direct; |
| 5219 | 5219 | struct ftrace_func_entry *entry; |
| 5220 | + struct ftrace_hash *hash; | |
| 5220 | 5221 | int ret = -ENODEV; |
| 5221 | 5222 | |
| 5222 | 5223 | mutex_lock(&direct_mutex); |
| @@ -5225,7 +5226,8 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr) · 2 unmodified lines | ||
| 5225 | 5226 | if (!entry) |
| 5226 | 5227 | goto out_unlock; |
| 5227 | 5228 | |
| 5228 | − if (direct_functions->count == 1) | |
| 5229 | + hash = direct_ops.func_hash->filter_hash; | |
| 5230 | + if (hash->count == 1) | |
| 5229 | 5231 | unregister_ftrace_function(&direct_ops); |
| 5230 | 5232 | |
| 5231 | 5233 | ret = ftrace_set_filter_ip(&direct_ops, ip, 1, 0); |
| @@ -5540,6 +5542,10 @@ int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr) · 308 unmodified lines | ||
| 5540 | 5542 | err = unregister_ftrace_function(ops); |
| 5541 | 5543 | remove_direct_functions_hash(hash, addr); |
| 5542 | 5544 | mutex_unlock(&direct_mutex); |
| 5545 | + | |
| 5546 | + /* cleanup for possible another register call */ | |
| 5547 | + ops->func = NULL; | |
| 5548 | + ops->trampoline = 0; | |
| 5543 | 5549 | return err; |
| 5544 | 5550 | } |
| 5545 | 5551 | EXPORT_SYMBOL_GPL(unregister_ftrace_direct_multi); |
| @@ -3757,7 +3757,7 @@ static int check_synth_field(struct synth_event *event, · 3756 unmodified lines | ||
| 3757 | 3757 | |
| 3758 | 3758 | if (strcmp(field->type, hist_field->type) != 0) { |
| 3759 | 3759 | if (field->size != hist_field->size || |
| 3760 | − field->is_signed != hist_field->is_signed) | |
| 3760 | + (!field->is_string && field->is_signed != hist_field->is_signed)) | |
| 3761 | 3761 | return -EINVAL; |
| 3762 | 3762 | } |
| 3763 | 3763 | |
| @@ -1237,9 +1237,8 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 1236 unmodified lines | ||
| 1237 | 1237 | argv + consumed, &consumed, |
| 1238 | 1238 | &field_version); |
| 1239 | 1239 | if (IS_ERR(field)) { |
| 1240 | − argv_free(argv); | |
| 1241 | 1240 | ret = PTR_ERR(field); |
| 1242 | − goto err; | |
| 1241 | + goto err_free_arg; | |
| 1243 | 1242 | } |
| 1244 | 1243 | |
| 1245 | 1244 | /* |
| @@ -1262,18 +1261,19 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 16 unmodified lines | ||
| 1262 | 1261 | if (cmd_version > 1 && n_fields_this_loop >= 1) { |
| 1263 | 1262 | synth_err(SYNTH_ERR_INVALID_CMD, errpos(field_str)); |
| 1264 | 1263 | ret = -EINVAL; |
| 1265 | − goto err; | |
| 1264 | + goto err_free_arg; | |
| 1266 | 1265 | } |
| 1267 | 1266 | |
| 1268 | 1267 | fields[n_fields++] = field; |
| 1269 | 1268 | if (n_fields == SYNTH_FIELDS_MAX) { |
| 1270 | 1269 | synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0); |
| 1271 | 1270 | ret = -EINVAL; |
| 1272 | − goto err; | |
| 1271 | + goto err_free_arg; | |
| 1273 | 1272 | } |
| 1274 | 1273 | |
| 1275 | 1274 | n_fields_this_loop++; |
| 1276 | 1275 | } |
| 1276 | + argv_free(argv); | |
| 1277 | 1277 | |
| 1278 | 1278 | if (consumed < argc) { |
| 1279 | 1279 | synth_err(SYNTH_ERR_INVALID_CMD, 0); |
| @@ -1281,7 +1281,6 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 1 unmodified line | ||
| 1281 | 1281 | goto err; |
| 1282 | 1282 | } |
| 1283 | 1283 | |
| 1284 | − argv_free(argv); | |
| 1285 | 1284 | } |
| 1286 | 1285 | |
| 1287 | 1286 | if (n_fields == 0) { |
| @@ -1307,6 +1306,8 @@ static int __create_synth_event(const char *name, const char *raw_fields) · 19 unmodified lines | ||
| 1307 | 1306 | kfree(saved_fields); |
| 1308 | 1307 | |
| 1309 | 1308 | return ret; |
| 1309 | + err_free_arg: | |
| 1310 | + argv_free(argv); | |
| 1310 | 1311 | err: |
| 1311 | 1312 | for (i = 0; i < n_fields; i++) |
| 1312 | 1313 | free_synth_field(fields[i]); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/jhash.h> |
| 16 | 16 | #include <linux/slab.h> |
| 17 | 17 | #include <linux/sort.h> |
| 18 | +#include <linux/kmemleak.h> | |
| 18 | 19 | |
| 19 | 20 | #include "tracing_map.h" |
| 20 | 21 | #include "trace.h" |
| @@ -307,6 +308,7 @@ static void tracing_map_array_free(struct tracing_map_array *a) · 286 unmodified lines | ||
| 307 | 308 | for (i = 0; i < a->n_pages; i++) { |
| 308 | 309 | if (!a->pages[i]) |
| 309 | 310 | break; |
| 311 | + kmemleak_free(a->pages[i]); | |
| 310 | 312 | free_page((unsigned long)a->pages[i]); |
| 311 | 313 | } |
| 312 | 314 | |
| @@ -342,6 +344,7 @@ static struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, · 29 unmodified lines | ||
| 342 | 344 | a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL); |
| 343 | 345 | if (!a->pages[i]) |
| 344 | 346 | goto free; |
| 347 | + kmemleak_alloc(a->pages[i], PAGE_SIZE, 1, GFP_KERNEL); | |
| 345 | 348 | } |
| 346 | 349 | out: |
| 347 | 350 | return a; |
| @@ -316,6 +316,7 @@ config DEBUG_INFO_BTF · 315 unmodified lines | ||
| 316 | 316 | bool "Generate BTF typeinfo" |
| 317 | 317 | depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED |
| 318 | 318 | depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST |
| 319 | + depends on BPF_SYSCALL | |
| 319 | 320 | help |
| 320 | 321 | Generate deduplicated BTF type information from DWARF debug info. |
| 321 | 322 | Turning this on expects presence of pahole tool, which will convert |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | SIPROUND; \ |
| 50 | 50 | return (v0 ^ v1) ^ (v2 ^ v3); |
| 51 | 51 | |
| 52 | +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 52 | 53 | u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) |
| 53 | 54 | { |
| 54 | 55 | const u8 *end = data + len - (len % sizeof(u64)); |
| @@ -80,8 +81,8 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) · 25 unmodified lines | ||
| 80 | 81 | POSTAMBLE |
| 81 | 82 | } |
| 82 | 83 | EXPORT_SYMBOL(__siphash_aligned); |
| 84 | +#endif | |
| 83 | 85 | |
| 84 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 85 | 86 | u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) |
| 86 | 87 | { |
| 87 | 88 | const u8 *end = data + len - (len % sizeof(u64)); |
| @@ -113,7 +114,6 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) · 25 unmodified lines | ||
| 113 | 114 | POSTAMBLE |
| 114 | 115 | } |
| 115 | 116 | EXPORT_SYMBOL(__siphash_unaligned); |
| 116 | −#endif | |
| 117 | 117 | |
| 118 | 118 | /** |
| 119 | 119 | * siphash_1u64 - compute 64-bit siphash PRF value of a u64 |
| @@ -250,6 +250,7 @@ EXPORT_SYMBOL(siphash_3u32); · 130 unmodified lines | ||
| 250 | 250 | HSIPROUND; \ |
| 251 | 251 | return (v0 ^ v1) ^ (v2 ^ v3); |
| 252 | 252 | |
| 253 | +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 253 | 254 | u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) |
| 254 | 255 | { |
| 255 | 256 | const u8 *end = data + len - (len % sizeof(u64)); |
| @@ -280,8 +281,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) · 24 unmodified lines | ||
| 280 | 281 | HPOSTAMBLE |
| 281 | 282 | } |
| 282 | 283 | EXPORT_SYMBOL(__hsiphash_aligned); |
| 284 | +#endif | |
| 283 | 285 | |
| 284 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 285 | 286 | u32 __hsiphash_unaligned(const void *data, size_t len, |
| 286 | 287 | const hsiphash_key_t *key) |
| 287 | 288 | { |
| @@ -313,7 +314,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len, · 25 unmodified lines | ||
| 313 | 314 | HPOSTAMBLE |
| 314 | 315 | } |
| 315 | 316 | EXPORT_SYMBOL(__hsiphash_unaligned); |
| 316 | −#endif | |
| 317 | 317 | |
| 318 | 318 | /** |
| 319 | 319 | * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32 |
| @@ -418,6 +418,7 @@ EXPORT_SYMBOL(hsiphash_4u32); · 98 unmodified lines | ||
| 418 | 418 | HSIPROUND; \ |
| 419 | 419 | return v1 ^ v3; |
| 420 | 420 | |
| 421 | +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 421 | 422 | u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) |
| 422 | 423 | { |
| 423 | 424 | const u8 *end = data + len - (len % sizeof(u32)); |
| @@ -438,8 +439,8 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) · 14 unmodified lines | ||
| 438 | 439 | HPOSTAMBLE |
| 439 | 440 | } |
| 440 | 441 | EXPORT_SYMBOL(__hsiphash_aligned); |
| 442 | +#endif | |
| 441 | 443 | |
| 442 | −#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS | |
| 443 | 444 | u32 __hsiphash_unaligned(const void *data, size_t len, |
| 444 | 445 | const hsiphash_key_t *key) |
| 445 | 446 | { |
| @@ -461,7 +462,6 @@ u32 __hsiphash_unaligned(const void *data, size_t len, · 15 unmodified lines | ||
| 461 | 462 | HPOSTAMBLE |
| 462 | 463 | } |
| 463 | 464 | EXPORT_SYMBOL(__hsiphash_unaligned); |
| 464 | −#endif | |
| 465 | 465 | |
| 466 | 466 | /** |
| 467 | 467 | * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32 |
| @@ -428,7 +428,7 @@ config THP_SWAP · 427 unmodified lines | ||
| 428 | 428 | # UP and nommu archs use km based percpu allocator |
| 429 | 429 | # |
| 430 | 430 | config NEED_PER_CPU_KM |
| 431 | − depends on !SMP | |
| 431 | + depends on !SMP || !MMU | |
| 432 | 432 | bool |
| 433 | 433 | default y |
| 434 | 434 | |
| @@ -945,6 +945,13 @@ void bdi_unregister(struct backing_dev_info *bdi) · 944 unmodified lines | ||
| 945 | 945 | wb_shutdown(&bdi->wb); |
| 946 | 946 | cgwb_bdi_unregister(bdi); |
| 947 | 947 | |
| 948 | + /* | |
| 949 | + * If this BDI's min ratio has been set, use bdi_set_min_ratio() to | |
| 950 | + * update the global bdi_min_ratio. | |
| 951 | + */ | |
| 952 | + if (bdi->min_ratio) | |
| 953 | + bdi_set_min_ratio(bdi, 0); | |
| 954 | + | |
| 948 | 955 | if (bdi->dev) { |
| 949 | 956 | bdi_debug_unregister(bdi); |
| 950 | 957 | device_unregister(bdi->dev); |
| @@ -282,7 +282,6 @@ int damon_set_targets(struct damon_ctx *ctx, · 281 unmodified lines | ||
| 282 | 282 | for (i = 0; i < nr_ids; i++) { |
| 283 | 283 | t = damon_new_target(ids[i]); |
| 284 | 284 | if (!t) { |
| 285 | − pr_err("Failed to alloc damon_target\n"); | |
| 286 | 285 | /* The caller should do cleanup of the ids itself */ |
| 287 | 286 | damon_for_each_target_safe(t, next, ctx) |
| 288 | 287 | damon_destroy_target(t); |
| @@ -312,16 +311,10 @@ int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int, · 23 unmodified lines | ||
| 312 | 311 | unsigned long aggr_int, unsigned long primitive_upd_int, |
| 313 | 312 | unsigned long min_nr_reg, unsigned long max_nr_reg) |
| 314 | 313 | { |
| 315 | − if (min_nr_reg < 3) { | |
| 316 | − pr_err("min_nr_regions (%lu) must be at least 3\n", | |
| 317 | − min_nr_reg); | |
| 314 | + if (min_nr_reg < 3) | |
| 318 | 315 | return -EINVAL; |
| 319 | − } | |
| 320 | − if (min_nr_reg > max_nr_reg) { | |
| 321 | − pr_err("invalid nr_regions. min (%lu) > max (%lu)\n", | |
| 322 | − min_nr_reg, max_nr_reg); | |
| 316 | + if (min_nr_reg > max_nr_reg) | |
| 323 | 317 | return -EINVAL; |
| 324 | − } | |
| 325 | 318 | |
| 326 | 319 | ctx->sample_interval = sample_int; |
| 327 | 320 | ctx->aggr_interval = aggr_int; |
| @@ -980,10 +973,11 @@ static unsigned long damos_wmark_wait_us(struct damos *scheme) · 652 unmodified lines | ||
| 980 | 973 | |
| 981 | 974 | static void kdamond_usleep(unsigned long usecs) |
| 982 | 975 | { |
| 983 | − if (usecs > 100 * 1000) | |
| 984 | − schedule_timeout_interruptible(usecs_to_jiffies(usecs)); | |
| 976 | + /* See Documentation/timers/timers-howto.rst for the thresholds */ | |
| 977 | + if (usecs > 20 * USEC_PER_MSEC) | |
| 978 | + schedule_timeout_idle(usecs_to_jiffies(usecs)); | |
| 985 | 979 | else |
| 986 | − usleep_range(usecs, usecs + 1); | |
| 980 | + usleep_idle_range(usecs, usecs + 1); | |
| 987 | 981 | } |
| 988 | 982 | |
| 989 | 983 | /* Returns negative error code if it's not activated but should return */ |
| @@ -1038,7 +1032,7 @@ static int kdamond_fn(void *data) · 48 unmodified lines | ||
| 1038 | 1032 | ctx->callback.after_sampling(ctx)) |
| 1039 | 1033 | done = true; |
| 1040 | 1034 | |
| 1041 | − usleep_range(ctx->sample_interval, ctx->sample_interval + 1); | |
| 1035 | + kdamond_usleep(ctx->sample_interval); | |
| 1042 | 1036 | |
| 1043 | 1037 | if (ctx->primitive.check_accesses) |
| 1044 | 1038 | max_nr_accesses = ctx->primitive.check_accesses(ctx); |
| @@ -210,10 +210,8 @@ static struct damos **str_to_schemes(const char *str, ssize_t len, · 209 unmodified lines | ||
| 210 | 210 | &wmarks.low, &parsed); |
| 211 | 211 | if (ret != 18) |
| 212 | 212 | break; |
| 213 | − if (!damos_action_valid(action)) { | |
| 214 | − pr_err("wrong action %d\n", action); | |
| 213 | + if (!damos_action_valid(action)) | |
| 215 | 214 | goto fail; |
| 216 | − } | |
| 217 | 215 | |
| 218 | 216 | pos += parsed; |
| 219 | 217 | scheme = damon_new_scheme(min_sz, max_sz, min_nr_a, max_nr_a, |
| @@ -135,7 +135,6 @@ static void damon_do_test_apply_three_regions(struct kunit *test, · 134 unmodified lines | ||
| 135 | 135 | struct damon_addr_range *three_regions, |
| 136 | 136 | unsigned long *expected, int nr_expected) |
| 137 | 137 | { |
| 138 | − struct damon_ctx *ctx = damon_new_ctx(); | |
| 139 | 138 | struct damon_target *t; |
| 140 | 139 | struct damon_region *r; |
| 141 | 140 | int i; |
| @@ -145,7 +144,6 @@ static void damon_do_test_apply_three_regions(struct kunit *test, · 3 unmodified lines | ||
| 145 | 144 | r = damon_new_region(regions[i * 2], regions[i * 2 + 1]); |
| 146 | 145 | damon_add_region(r, t); |
| 147 | 146 | } |
| 148 | − damon_add_target(ctx, t); | |
| 149 | 147 | |
| 150 | 148 | damon_va_apply_three_regions(t, three_regions); |
| 151 | 149 | |
| @@ -154,8 +152,6 @@ static void damon_do_test_apply_three_regions(struct kunit *test, · 2 unmodified lines | ||
| 154 | 152 | KUNIT_EXPECT_EQ(test, r->ar.start, expected[i * 2]); |
| 155 | 153 | KUNIT_EXPECT_EQ(test, r->ar.end, expected[i * 2 + 1]); |
| 156 | 154 | } |
| 157 | − | |
| 158 | − damon_destroy_ctx(ctx); | |
| 159 | 155 | } |
| 160 | 156 | |
| 161 | 157 | /* |
| @@ -252,60 +248,59 @@ static void damon_test_apply_three_regions4(struct kunit *test) · 90 unmodified lines | ||
| 252 | 248 | new_three_regions, expected, ARRAY_SIZE(expected)); |
| 253 | 249 | } |
| 254 | 250 | |
| 255 | −static void damon_test_split_evenly(struct kunit *test) | |
| 251 | +static void damon_test_split_evenly_fail(struct kunit *test, | |
| 252 | + unsigned long start, unsigned long end, unsigned int nr_pieces) | |
| 256 | 253 | { |
| 257 | − struct damon_ctx *c = damon_new_ctx(); | |
| 258 | − struct damon_target *t; | |
| 259 | − struct damon_region *r; | |
| 260 | − unsigned long i; | |
| 261 | − | |
| 262 | − KUNIT_EXPECT_EQ(test, damon_va_evenly_split_region(NULL, NULL, 5), | |
| 263 | − -EINVAL); | |
| 264 | − | |
| 265 | − t = damon_new_target(42); | |
| 266 | − r = damon_new_region(0, 100); | |
| 267 | − KUNIT_EXPECT_EQ(test, damon_va_evenly_split_region(t, r, 0), -EINVAL); | |
| 254 | + struct damon_target *t = damon_new_target(42); | |
| 255 | + struct damon_region *r = damon_new_region(start, end); | |
| 268 | 256 | |
| 269 | 257 | damon_add_region(r, t); |
| 270 | − KUNIT_EXPECT_EQ(test, damon_va_evenly_split_region(t, r, 10), 0); | |
| 271 | − KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 10u); | |
| 258 | + KUNIT_EXPECT_EQ(test, | |
| 259 | + damon_va_evenly_split_region(t, r, nr_pieces), -EINVAL); | |
| 260 | + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1u); | |
| 272 | 261 | |
| 273 | − i = 0; | |
| 274 | 262 | damon_for_each_region(r, t) { |
| 275 | − KUNIT_EXPECT_EQ(test, r->ar.start, i++ * 10); | |
| 276 | − KUNIT_EXPECT_EQ(test, r->ar.end, i * 10); | |
| 263 | + KUNIT_EXPECT_EQ(test, r->ar.start, start); | |
| 264 | + KUNIT_EXPECT_EQ(test, r->ar.end, end); | |
| 277 | 265 | } |
| 266 | + | |
| 278 | 267 | damon_free_target(t); |
| 268 | +} | |
| 269 | + | |
| 270 | +static void damon_test_split_evenly_succ(struct kunit *test, | |
| 271 | + unsigned long start, unsigned long end, unsigned int nr_pieces) | |
| 272 | +{ | |
| 273 | + struct damon_target *t = damon_new_target(42); | |
| 274 | + struct damon_region *r = damon_new_region(start, end); | |
| 275 | + unsigned long expected_width = (end - start) / nr_pieces; | |
| 276 | + unsigned long i = 0; | |
| 279 | 277 | |
| 280 | − t = damon_new_target(42); | |
| 281 | − r = damon_new_region(5, 59); | |
| 282 | 278 | damon_add_region(r, t); |
| 283 | − KUNIT_EXPECT_EQ(test, damon_va_evenly_split_region(t, r, 5), 0); | |
| 284 | − KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 5u); | |
| 279 | + KUNIT_EXPECT_EQ(test, | |
| 280 | + damon_va_evenly_split_region(t, r, nr_pieces), 0); | |
| 281 | + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), nr_pieces); | |
| 285 | 282 | |
| 286 | − i = 0; | |
| 287 | 283 | damon_for_each_region(r, t) { |
| 288 | − if (i == 4) | |
| 284 | + if (i == nr_pieces - 1) | |
| 289 | 285 | break; |
| 290 | − KUNIT_EXPECT_EQ(test, r->ar.start, 5 + 10 * i++); | |
| 291 | − KUNIT_EXPECT_EQ(test, r->ar.end, 5 + 10 * i); | |
| 286 | + KUNIT_EXPECT_EQ(test, | |
| 287 | + r->ar.start, start + i++ * expected_width); | |
| 288 | + KUNIT_EXPECT_EQ(test, r->ar.end, start + i * expected_width); | |
| 292 | 289 | } |
| 293 | − KUNIT_EXPECT_EQ(test, r->ar.start, 5 + 10 * i); | |
| 294 | − KUNIT_EXPECT_EQ(test, r->ar.end, 59ul); | |
| 290 | + KUNIT_EXPECT_EQ(test, r->ar.start, start + i * expected_width); | |
| 291 | + KUNIT_EXPECT_EQ(test, r->ar.end, end); | |
| 295 | 292 | damon_free_target(t); |
| 293 | +} | |
| 296 | 294 | |
| 297 | − t = damon_new_target(42); | |
| 298 | − r = damon_new_region(5, 6); | |
| 299 | − damon_add_region(r, t); | |
| 300 | − KUNIT_EXPECT_EQ(test, damon_va_evenly_split_region(t, r, 2), -EINVAL); | |
| 301 | − KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1u); | |
| 295 | +static void damon_test_split_evenly(struct kunit *test) | |
| 296 | +{ | |
| 297 | + KUNIT_EXPECT_EQ(test, damon_va_evenly_split_region(NULL, NULL, 5), | |
| 298 | + -EINVAL); | |
| 302 | 299 | |
| 303 | − damon_for_each_region(r, t) { | |
| 304 | − KUNIT_EXPECT_EQ(test, r->ar.start, 5ul); | |
| 305 | − KUNIT_EXPECT_EQ(test, r->ar.end, 6ul); | |
| 306 | − } | |
| 307 | − damon_free_target(t); | |
| 308 | − damon_destroy_ctx(c); | |
| 300 | + damon_test_split_evenly_fail(test, 0, 100, 0); | |
| 301 | + damon_test_split_evenly_succ(test, 0, 100, 10); | |
| 302 | + damon_test_split_evenly_succ(test, 5, 59, 5); | |
| 303 | + damon_test_split_evenly_fail(test, 5, 6, 2); | |
| 309 | 304 | } |
| 310 | 305 | |
| 311 | 306 | static struct kunit_case damon_test_cases[] = { |
| @@ -13,6 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/mmu_notifier.h> |
| 14 | 14 | #include <linux/page_idle.h> |
| 15 | 15 | #include <linux/pagewalk.h> |
| 16 | +#include <linux/sched/mm.h> | |
| 16 | 17 | |
| 17 | 18 | #include "prmtv-common.h" |
| 18 | 19 | |
| @@ -626,7 +627,6 @@ int damon_va_apply_scheme(struct damon_ctx *ctx, struct damon_target *t, · 607 unmodified lines | ||
| 626 | 627 | case DAMOS_STAT: |
| 627 | 628 | return 0; |
| 628 | 629 | default: |
| 629 | − pr_warn("Wrong action %d\n", scheme->action); | |
| 630 | 630 | return -EINVAL; |
| 631 | 631 | } |
| 632 | 632 | |
| @@ -3253,8 +3253,6 @@ static struct page *next_uptodate_page(struct page *page, · 3252 unmodified lines | ||
| 3253 | 3253 | goto skip; |
| 3254 | 3254 | if (!PageUptodate(page) || PageReadahead(page)) |
| 3255 | 3255 | goto skip; |
| 3256 | − if (PageHWPoison(page)) | |
| 3257 | − goto skip; | |
| 3258 | 3256 | if (!trylock_page(page)) |
| 3259 | 3257 | goto skip; |
| 3260 | 3258 | if (page->mapping != mapping) |
| @@ -2973,7 +2973,7 @@ int __alloc_bootmem_huge_page(struct hstate *h, int nid) · 2972 unmodified lines | ||
| 2973 | 2973 | struct huge_bootmem_page *m = NULL; /* initialize for clang */ |
| 2974 | 2974 | int nr_nodes, node; |
| 2975 | 2975 | |
| 2976 | − if (nid >= nr_online_nodes) | |
| 2976 | + if (nid != NUMA_NO_NODE && nid >= nr_online_nodes) | |
| 2977 | 2977 | return 0; |
| 2978 | 2978 | /* do node specific alloc */ |
| 2979 | 2979 | if (nid != NUMA_NO_NODE) { |
| @@ -776,24 +776,6 @@ void __mod_lruvec_kmem_state(void *p, enum node_stat_item idx, int val) · 775 unmodified lines | ||
| 776 | 776 | rcu_read_unlock(); |
| 777 | 777 | } |
| 778 | 778 | |
| 779 | −/* | |
| 780 | − * mod_objcg_mlstate() may be called with irq enabled, so | |
| 781 | − * mod_memcg_lruvec_state() should be used. | |
| 782 | − */ | |
| 783 | −static inline void mod_objcg_mlstate(struct obj_cgroup *objcg, | |
| 784 | − struct pglist_data *pgdat, | |
| 785 | − enum node_stat_item idx, int nr) | |
| 786 | −{ | |
| 787 | − struct mem_cgroup *memcg; | |
| 788 | − struct lruvec *lruvec; | |
| 789 | − | |
| 790 | − rcu_read_lock(); | |
| 791 | − memcg = obj_cgroup_memcg(objcg); | |
| 792 | − lruvec = mem_cgroup_lruvec(memcg, pgdat); | |
| 793 | − mod_memcg_lruvec_state(lruvec, idx, nr); | |
| 794 | − rcu_read_unlock(); | |
| 795 | −} | |
| 796 | − | |
| 797 | 779 | /** |
| 798 | 780 | * __count_memcg_events - account VM events in a cgroup |
| 799 | 781 | * @memcg: the memory cgroup |
| @@ -2137,41 +2119,6 @@ static bool obj_stock_flush_required(struct memcg_stock_pcp *stock, · 1337 unmodified lines | ||
| 2137 | 2119 | } |
| 2138 | 2120 | #endif |
| 2139 | 2121 | |
| 2140 | −/* | |
| 2141 | − * Most kmem_cache_alloc() calls are from user context. The irq disable/enable | |
| 2142 | − * sequence used in this case to access content from object stock is slow. | |
| 2143 | − * To optimize for user context access, there are now two object stocks for | |
| 2144 | − * task context and interrupt context access respectively. | |
| 2145 | − * | |
| 2146 | − * The task context object stock can be accessed by disabling preemption only | |
| 2147 | − * which is cheap in non-preempt kernel. The interrupt context object stock | |
| 2148 | − * can only be accessed after disabling interrupt. User context code can | |
| 2149 | − * access interrupt object stock, but not vice versa. | |
| 2150 | − */ | |
| 2151 | −static inline struct obj_stock *get_obj_stock(unsigned long *pflags) | |
| 2152 | −{ | |
| 2153 | − struct memcg_stock_pcp *stock; | |
| 2154 | − | |
| 2155 | − if (likely(in_task())) { | |
| 2156 | − *pflags = 0UL; | |
| 2157 | − preempt_disable(); | |
| 2158 | − stock = this_cpu_ptr(&memcg_stock); | |
| 2159 | − return &stock->task_obj; | |
| 2160 | − } | |
| 2161 | − | |
| 2162 | − local_irq_save(*pflags); | |
| 2163 | − stock = this_cpu_ptr(&memcg_stock); | |
| 2164 | − return &stock->irq_obj; | |
| 2165 | −} | |
| 2166 | − | |
| 2167 | −static inline void put_obj_stock(unsigned long flags) | |
| 2168 | −{ | |
| 2169 | − if (likely(in_task())) | |
| 2170 | − preempt_enable(); | |
| 2171 | − else | |
| 2172 | − local_irq_restore(flags); | |
| 2173 | −} | |
| 2174 | − | |
| 2175 | 2122 | /** |
| 2176 | 2123 | * consume_stock: Try to consume stocked charge on this cpu. |
| 2177 | 2124 | * @memcg: memcg to consume from. |
| @@ -2816,6 +2763,59 @@ retry: · 638 unmodified lines | ||
| 2816 | 2763 | */ |
| 2817 | 2764 | #define OBJCGS_CLEAR_MASK (__GFP_DMA | __GFP_RECLAIMABLE | __GFP_ACCOUNT) |
| 2818 | 2765 | |
| 2766 | +/* | |
| 2767 | + * Most kmem_cache_alloc() calls are from user context. The irq disable/enable | |
| 2768 | + * sequence used in this case to access content from object stock is slow. | |
| 2769 | + * To optimize for user context access, there are now two object stocks for | |
| 2770 | + * task context and interrupt context access respectively. | |
| 2771 | + * | |
| 2772 | + * The task context object stock can be accessed by disabling preemption only | |
| 2773 | + * which is cheap in non-preempt kernel. The interrupt context object stock | |
| 2774 | + * can only be accessed after disabling interrupt. User context code can | |
| 2775 | + * access interrupt object stock, but not vice versa. | |
| 2776 | + */ | |
| 2777 | +static inline struct obj_stock *get_obj_stock(unsigned long *pflags) | |
| 2778 | +{ | |
| 2779 | + struct memcg_stock_pcp *stock; | |
| 2780 | + | |
| 2781 | + if (likely(in_task())) { | |
| 2782 | + *pflags = 0UL; | |
| 2783 | + preempt_disable(); | |
| 2784 | + stock = this_cpu_ptr(&memcg_stock); | |
| 2785 | + return &stock->task_obj; | |
| 2786 | + } | |
| 2787 | + | |
| 2788 | + local_irq_save(*pflags); | |
| 2789 | + stock = this_cpu_ptr(&memcg_stock); | |
| 2790 | + return &stock->irq_obj; | |
| 2791 | +} | |
| 2792 | + | |
| 2793 | +static inline void put_obj_stock(unsigned long flags) | |
| 2794 | +{ | |
| 2795 | + if (likely(in_task())) | |
| 2796 | + preempt_enable(); | |
| 2797 | + else | |
| 2798 | + local_irq_restore(flags); | |
| 2799 | +} | |
| 2800 | + | |
| 2801 | +/* | |
| 2802 | + * mod_objcg_mlstate() may be called with irq enabled, so | |
| 2803 | + * mod_memcg_lruvec_state() should be used. | |
| 2804 | + */ | |
| 2805 | +static inline void mod_objcg_mlstate(struct obj_cgroup *objcg, | |
| 2806 | + struct pglist_data *pgdat, | |
| 2807 | + enum node_stat_item idx, int nr) | |
| 2808 | +{ | |
| 2809 | + struct mem_cgroup *memcg; | |
| 2810 | + struct lruvec *lruvec; | |
| 2811 | + | |
| 2812 | + rcu_read_lock(); | |
| 2813 | + memcg = obj_cgroup_memcg(objcg); | |
| 2814 | + lruvec = mem_cgroup_lruvec(memcg, pgdat); | |
| 2815 | + mod_memcg_lruvec_state(lruvec, idx, nr); | |
| 2816 | + rcu_read_unlock(); | |
| 2817 | +} | |
| 2818 | + | |
| 2819 | 2819 | int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s, |
| 2820 | 2820 | gfp_t gfp, bool new_page) |
| 2821 | 2821 | { |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <linux/memblock.h> |
| 36 | 36 | #include <linux/compaction.h> |
| 37 | 37 | #include <linux/rmap.h> |
| 38 | +#include <linux/module.h> | |
| 38 | 39 | |
| 39 | 40 | #include <asm/tlbflush.h> |
| 40 | 41 | |
| @@ -5081,6 +5081,7 @@ struct loc_track { · 5080 unmodified lines | ||
| 5081 | 5081 | unsigned long max; |
| 5082 | 5082 | unsigned long count; |
| 5083 | 5083 | struct location *loc; |
| 5084 | + loff_t idx; | |
| 5084 | 5085 | }; |
| 5085 | 5086 | |
| 5086 | 5087 | static struct dentry *slab_debugfs_root; |
| @@ -6052,11 +6053,11 @@ __initcall(slab_sysfs_init); · 965 unmodified lines | ||
| 6052 | 6053 | #if defined(CONFIG_SLUB_DEBUG) && defined(CONFIG_DEBUG_FS) |
| 6053 | 6054 | static int slab_debugfs_show(struct seq_file *seq, void *v) |
| 6054 | 6055 | { |
| 6055 | − | |
| 6056 | − struct location *l; | |
| 6057 | − unsigned int idx = *(unsigned int *)v; | |
| 6058 | 6056 | struct loc_track *t = seq->private; |
| 6057 | + struct location *l; | |
| 6058 | + unsigned long idx; | |
| 6059 | 6059 | |
| 6060 | + idx = (unsigned long) t->idx; | |
| 6060 | 6061 | if (idx < t->count) { |
| 6061 | 6062 | l = &t->loc[idx]; |
| 6062 | 6063 | |
| @@ -6105,16 +6106,18 @@ static void *slab_debugfs_next(struct seq_file *seq, void *v, loff_t *ppos) · 42 unmodified lines | ||
| 6105 | 6106 | { |
| 6106 | 6107 | struct loc_track *t = seq->private; |
| 6107 | 6108 | |
| 6108 | − v = ppos; | |
| 6109 | − ++*ppos; | |
| 6109 | + t->idx = ++(*ppos); | |
| 6110 | 6110 | if (*ppos <= t->count) |
| 6111 | − return v; | |
| 6111 | + return ppos; | |
| 6112 | 6112 | |
| 6113 | 6113 | return NULL; |
| 6114 | 6114 | } |
| 6115 | 6115 | |
| 6116 | 6116 | static void *slab_debugfs_start(struct seq_file *seq, loff_t *ppos) |
| 6117 | 6117 | { |
| 6118 | + struct loc_track *t = seq->private; | |
| 6119 | + | |
| 6120 | + t->idx = *ppos; | |
| 6118 | 6121 | return ppos; |
| 6119 | 6122 | } |
| 6120 | 6123 | |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/swap_slots.h> |
| 31 | 31 | #include <linux/cpu.h> |
| 32 | 32 | #include <linux/cpumask.h> |
| 33 | +#include <linux/slab.h> | |
| 33 | 34 | #include <linux/vmalloc.h> |
| 34 | 35 | #include <linux/mutex.h> |
| 35 | 36 | #include <linux/mm.h> |
| @@ -4210,7 +4210,10 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) · 4209 unmodified lines | ||
| 4210 | 4210 | if (dev->flags & IFF_UP) { |
| 4211 | 4211 | int cpu = smp_processor_id(); /* ok because BHs are off */ |
| 4212 | 4212 | |
| 4213 | − if (txq->xmit_lock_owner != cpu) { | |
| 4213 | + /* Other cpus might concurrently change txq->xmit_lock_owner | |
| 4214 | + * to -1 or to their cpu id, but not to our id. | |
| 4215 | + */ | |
| 4216 | + if (READ_ONCE(txq->xmit_lock_owner) != cpu) { | |
| 4214 | 4217 | if (dev_xmit_recursion()) |
| 4215 | 4218 | goto recursion_alert; |
| 4216 | 4219 | |
| @@ -4110,14 +4110,6 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) · 4109 unmodified lines | ||
| 4110 | 4110 | return err; |
| 4111 | 4111 | } |
| 4112 | 4112 | |
| 4113 | − if (info->attrs[DEVLINK_ATTR_NETNS_PID] || | |
| 4114 | − info->attrs[DEVLINK_ATTR_NETNS_FD] || | |
| 4115 | − info->attrs[DEVLINK_ATTR_NETNS_ID]) { | |
| 4116 | − dest_net = devlink_netns_get(skb, info); | |
| 4117 | − if (IS_ERR(dest_net)) | |
| 4118 | − return PTR_ERR(dest_net); | |
| 4119 | − } | |
| 4120 | − | |
| 4121 | 4113 | if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION]) |
| 4122 | 4114 | action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]); |
| 4123 | 4115 | else |
| @@ -4160,6 +4152,14 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) · 36 unmodified lines | ||
| 4160 | 4152 | return -EINVAL; |
| 4161 | 4153 | } |
| 4162 | 4154 | } |
| 4155 | + if (info->attrs[DEVLINK_ATTR_NETNS_PID] || | |
| 4156 | + info->attrs[DEVLINK_ATTR_NETNS_FD] || | |
| 4157 | + info->attrs[DEVLINK_ATTR_NETNS_ID]) { | |
| 4158 | + dest_net = devlink_netns_get(skb, info); | |
| 4159 | + if (IS_ERR(dest_net)) | |
| 4160 | + return PTR_ERR(dest_net); | |
| 4161 | + } | |
| 4162 | + | |
| 4163 | 4163 | err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack); |
| 4164 | 4164 | |
| 4165 | 4165 | if (dest_net) |
| @@ -162,3 +162,22 @@ void dst_cache_destroy(struct dst_cache *dst_cache) · 161 unmodified lines | ||
| 162 | 162 | free_percpu(dst_cache->cache); |
| 163 | 163 | } |
| 164 | 164 | EXPORT_SYMBOL_GPL(dst_cache_destroy); |
| 165 | + | |
| 166 | +void dst_cache_reset_now(struct dst_cache *dst_cache) | |
| 167 | +{ | |
| 168 | + int i; | |
| 169 | + | |
| 170 | + if (!dst_cache->cache) | |
| 171 | + return; | |
| 172 | + | |
| 173 | + dst_cache->reset_ts = jiffies; | |
| 174 | + for_each_possible_cpu(i) { | |
| 175 | + struct dst_cache_pcpu *idst = per_cpu_ptr(dst_cache->cache, i); | |
| 176 | + struct dst_entry *dst = idst->dst; | |
| 177 | + | |
| 178 | + idst->cookie = 0; | |
| 179 | + idst->dst = NULL; | |
| 180 | + dst_release(dst); | |
| 181 | + } | |
| 182 | +} | |
| 183 | +EXPORT_SYMBOL_GPL(dst_cache_reset_now); | |
| @@ -323,7 +323,7 @@ jumped: · 322 unmodified lines | ||
| 323 | 323 | if (!err && ops->suppress && INDIRECT_CALL_MT(ops->suppress, |
| 324 | 324 | fib6_rule_suppress, |
| 325 | 325 | fib4_rule_suppress, |
| 326 | − rule, arg)) | |
| 326 | + rule, flags, arg)) | |
| 327 | 327 | continue; |
| 328 | 328 | |
| 329 | 329 | if (err != -EAGAIN) { |
| @@ -763,11 +763,10 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, · 762 unmodified lines | ||
| 763 | 763 | |
| 764 | 764 | ASSERT_RTNL(); |
| 765 | 765 | |
| 766 | − n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL); | |
| 766 | + n = kzalloc(sizeof(*n) + key_len, GFP_KERNEL); | |
| 767 | 767 | if (!n) |
| 768 | 768 | goto out; |
| 769 | 769 | |
| 770 | − n->protocol = 0; | |
| 771 | 770 | write_pnet(&n->net, net); |
| 772 | 771 | memcpy(n->key, pkey, key_len); |
| 773 | 772 | n->dev = dev; |
| @@ -1124,6 +1124,8 @@ void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock) · 1123 unmodified lines | ||
| 1124 | 1124 | |
| 1125 | 1125 | void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) |
| 1126 | 1126 | { |
| 1127 | + psock_set_prog(&psock->progs.stream_parser, NULL); | |
| 1128 | + | |
| 1127 | 1129 | if (!psock->saved_data_ready) |
| 1128 | 1130 | return; |
| 1129 | 1131 | |
| @@ -1212,6 +1214,9 @@ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) · 82 unmodified lines | ||
| 1212 | 1214 | |
| 1213 | 1215 | void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) |
| 1214 | 1216 | { |
| 1217 | + psock_set_prog(&psock->progs.stream_verdict, NULL); | |
| 1218 | + psock_set_prog(&psock->progs.skb_verdict, NULL); | |
| 1219 | + | |
| 1215 | 1220 | if (!psock->saved_data_ready) |
| 1216 | 1221 | return; |
| 1217 | 1222 | |
| @@ -167,8 +167,11 @@ static void sock_map_del_link(struct sock *sk, · 166 unmodified lines | ||
| 167 | 167 | write_lock_bh(&sk->sk_callback_lock); |
| 168 | 168 | if (strp_stop) |
| 169 | 169 | sk_psock_stop_strp(sk, psock); |
| 170 | − else | |
| 170 | + if (verdict_stop) | |
| 171 | 171 | sk_psock_stop_verdict(sk, psock); |
| 172 | + | |
| 173 | + if (psock->psock_update_sk_prot) | |
| 174 | + psock->psock_update_sk_prot(sk, psock, false); | |
| 172 | 175 | write_unlock_bh(&sk->sk_callback_lock); |
| 173 | 176 | } |
| 174 | 177 | } |
| @@ -282,6 +285,12 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk) · 107 unmodified lines | ||
| 282 | 285 | |
| 283 | 286 | if (msg_parser) |
| 284 | 287 | psock_set_prog(&psock->progs.msg_parser, msg_parser); |
| 288 | + if (stream_parser) | |
| 289 | + psock_set_prog(&psock->progs.stream_parser, stream_parser); | |
| 290 | + if (stream_verdict) | |
| 291 | + psock_set_prog(&psock->progs.stream_verdict, stream_verdict); | |
| 292 | + if (skb_verdict) | |
| 293 | + psock_set_prog(&psock->progs.skb_verdict, skb_verdict); | |
| 285 | 294 | |
| 286 | 295 | ret = sock_map_init_proto(sk, psock); |
| 287 | 296 | if (ret < 0) |
| @@ -292,14 +301,10 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk) · 4 unmodified lines | ||
| 292 | 301 | ret = sk_psock_init_strp(sk, psock); |
| 293 | 302 | if (ret) |
| 294 | 303 | goto out_unlock_drop; |
| 295 | − psock_set_prog(&psock->progs.stream_verdict, stream_verdict); | |
| 296 | − psock_set_prog(&psock->progs.stream_parser, stream_parser); | |
| 297 | 304 | sk_psock_start_strp(sk, psock); |
| 298 | 305 | } else if (!stream_parser && stream_verdict && !psock->saved_data_ready) { |
| 299 | − psock_set_prog(&psock->progs.stream_verdict, stream_verdict); | |
| 300 | 306 | sk_psock_start_verdict(sk,psock); |
| 301 | 307 | } else if (!stream_verdict && skb_verdict && !psock->saved_data_ready) { |
| 302 | − psock_set_prog(&psock->progs.skb_verdict, skb_verdict); | |
| 303 | 308 | sk_psock_start_verdict(sk, psock); |
| 304 | 309 | } |
| 305 | 310 | write_unlock_bh(&sk->sk_callback_lock); |
| @@ -40,7 +40,8 @@ int ethnl_ops_begin(struct net_device *dev) · 39 unmodified lines | ||
| 40 | 40 | if (dev->dev.parent) |
| 41 | 41 | pm_runtime_get_sync(dev->dev.parent); |
| 42 | 42 | |
| 43 | − if (!netif_device_present(dev)) { | |
| 43 | + if (!netif_device_present(dev) || | |
| 44 | + dev->reg_state == NETREG_UNREGISTERING) { | |
| 44 | 45 | ret = -ENODEV; |
| 45 | 46 | goto err; |
| 46 | 47 | } |
| @@ -1582,7 +1582,7 @@ static int __net_init fib_net_init(struct net *net) · 1581 unmodified lines | ||
| 1582 | 1582 | int error; |
| 1583 | 1583 | |
| 1584 | 1584 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 1585 | − net->ipv4.fib_num_tclassid_users = 0; | |
| 1585 | + atomic_set(&net->ipv4.fib_num_tclassid_users, 0); | |
| 1586 | 1586 | #endif |
| 1587 | 1587 | error = ip_fib_net_init(net); |
| 1588 | 1588 | if (error < 0) |
| @@ -141,6 +141,7 @@ INDIRECT_CALLABLE_SCOPE int fib4_rule_action(struct fib_rule *rule, · 140 unmodified lines | ||
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | INDIRECT_CALLABLE_SCOPE bool fib4_rule_suppress(struct fib_rule *rule, |
| 144 | + int flags, | |
| 144 | 145 | struct fib_lookup_arg *arg) |
| 145 | 146 | { |
| 146 | 147 | struct fib_result *result = (struct fib_result *) arg->result; |
| @@ -263,7 +264,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, · 116 unmodified lines | ||
| 263 | 264 | if (tb[FRA_FLOW]) { |
| 264 | 265 | rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); |
| 265 | 266 | if (rule4->tclassid) |
| 266 | − net->ipv4.fib_num_tclassid_users++; | |
| 267 | + atomic_inc(&net->ipv4.fib_num_tclassid_users); | |
| 267 | 268 | } |
| 268 | 269 | #endif |
| 269 | 270 | |
| @@ -295,7 +296,7 @@ static int fib4_rule_delete(struct fib_rule *rule) · 25 unmodified lines | ||
| 295 | 296 | |
| 296 | 297 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 297 | 298 | if (((struct fib4_rule *)rule)->tclassid) |
| 298 | − net->ipv4.fib_num_tclassid_users--; | |
| 299 | + atomic_dec(&net->ipv4.fib_num_tclassid_users); | |
| 299 | 300 | #endif |
| 300 | 301 | net->ipv4.fib_has_custom_rules = true; |
| 301 | 302 | |
| @@ -220,7 +220,7 @@ void fib_nh_release(struct net *net, struct fib_nh *fib_nh) · 219 unmodified lines | ||
| 220 | 220 | { |
| 221 | 221 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 222 | 222 | if (fib_nh->nh_tclassid) |
| 223 | − net->ipv4.fib_num_tclassid_users--; | |
| 223 | + atomic_dec(&net->ipv4.fib_num_tclassid_users); | |
| 224 | 224 | #endif |
| 225 | 225 | fib_nh_common_release(&fib_nh->nh_common); |
| 226 | 226 | } |
| @@ -632,7 +632,7 @@ int fib_nh_init(struct net *net, struct fib_nh *nh, · 405 unmodified lines | ||
| 632 | 632 | #ifdef CONFIG_IP_ROUTE_CLASSID |
| 633 | 633 | nh->nh_tclassid = cfg->fc_flow; |
| 634 | 634 | if (nh->nh_tclassid) |
| 635 | − net->ipv4.fib_num_tclassid_users++; | |
| 635 | + atomic_inc(&net->ipv4.fib_num_tclassid_users); | |
| 636 | 636 | #endif |
| 637 | 637 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
| 638 | 638 | nh->fib_nh_weight = nh_weight; |
| @@ -721,7 +721,7 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req, · 720 unmodified lines | ||
| 721 | 721 | |
| 722 | 722 | sk_node_init(&nreq_sk->sk_node); |
| 723 | 723 | nreq_sk->sk_tx_queue_mapping = req_sk->sk_tx_queue_mapping; |
| 724 | −#ifdef CONFIG_XPS | |
| 724 | +#ifdef CONFIG_SOCK_RX_QUEUE_MAPPING | |
| 725 | 725 | nreq_sk->sk_rx_queue_mapping = req_sk->sk_rx_queue_mapping; |
| 726 | 726 | #endif |
| 727 | 727 | nreq_sk->sk_incoming_cpu = req_sk->sk_incoming_cpu; |
| @@ -829,8 +829,8 @@ int tcp_child_process(struct sock *parent, struct sock *child, · 828 unmodified lines | ||
| 829 | 829 | int ret = 0; |
| 830 | 830 | int state = child->sk_state; |
| 831 | 831 | |
| 832 | − /* record NAPI ID of child */ | |
| 833 | − sk_mark_napi_id(child, skb); | |
| 832 | + /* record sk_napi_id and sk_rx_queue_mapping of child. */ | |
| 833 | + sk_mark_napi_id_set(child, skb); | |
| 834 | 834 | |
| 835 | 835 | tcp_segs_in(tcp_sk(child), skb); |
| 836 | 836 | if (!sock_owned_by_user(child)) { |
| @@ -916,7 +916,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4, · 915 unmodified lines | ||
| 916 | 916 | kfree_skb(skb); |
| 917 | 917 | return -EINVAL; |
| 918 | 918 | } |
| 919 | − if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { | |
| 919 | + if (datalen > cork->gso_size * UDP_MAX_SEGMENTS) { | |
| 920 | 920 | kfree_skb(skb); |
| 921 | 921 | return -EINVAL; |
| 922 | 922 | } |
| @@ -267,6 +267,7 @@ INDIRECT_CALLABLE_SCOPE int fib6_rule_action(struct fib_rule *rule, · 266 unmodified lines | ||
| 267 | 267 | } |
| 268 | 268 | |
| 269 | 269 | INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, |
| 270 | + int flags, | |
| 270 | 271 | struct fib_lookup_arg *arg) |
| 271 | 272 | { |
| 272 | 273 | struct fib6_result *res = arg->result; |
| @@ -294,8 +295,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule, · 21 unmodified lines | ||
| 294 | 295 | return false; |
| 295 | 296 | |
| 296 | 297 | suppress_route: |
| 297 | − if (!(arg->flags & FIB_LOOKUP_NOREF)) | |
| 298 | − ip6_rt_put(rt); | |
| 298 | + ip6_rt_put_flags(rt, flags); | |
| 299 | 299 | return true; |
| 300 | 300 | } |
| 301 | 301 | |
| @@ -248,9 +248,9 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head, · 247 unmodified lines | ||
| 248 | 248 | * memcmp() alone below is sufficient, right? |
| 249 | 249 | */ |
| 250 | 250 | if ((first_word & htonl(0xF00FFFFF)) || |
| 251 | − !ipv6_addr_equal(&iph->saddr, &iph2->saddr) || | |
| 252 | − !ipv6_addr_equal(&iph->daddr, &iph2->daddr) || | |
| 253 | − *(u16 *)&iph->nexthdr != *(u16 *)&iph2->nexthdr) { | |
| 251 | + !ipv6_addr_equal(&iph->saddr, &iph2->saddr) || | |
| 252 | + !ipv6_addr_equal(&iph->daddr, &iph2->daddr) || | |
| 253 | + *(u16 *)&iph->nexthdr != *(u16 *)&iph2->nexthdr) { | |
| 254 | 254 | not_same_flow: |
| 255 | 255 | NAPI_GRO_CB(p)->same_flow = 0; |
| 256 | 256 | continue; |
| @@ -161,6 +161,14 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto) · 160 unmodified lines | ||
| 161 | 161 | hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb)); |
| 162 | 162 | |
| 163 | 163 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); |
| 164 | + | |
| 165 | + /* the control block has been erased, so we have to set the | |
| 166 | + * iif once again. | |
| 167 | + * We read the receiving interface index directly from the | |
| 168 | + * skb->skb_iif as it is done in the IPv4 receiving path (i.e.: | |
| 169 | + * ip_rcv_core(...)). | |
| 170 | + */ | |
| 171 | + IP6CB(skb)->iif = skb->skb_iif; | |
| 164 | 172 | } |
| 165 | 173 | |
| 166 | 174 | hdr->nexthdr = NEXTHDR_ROUTING; |
| @@ -952,7 +952,7 @@ static int mctp_route_add(struct mctp_dev *mdev, mctp_eid_t daddr_start, · 951 unmodified lines | ||
| 952 | 952 | } |
| 953 | 953 | |
| 954 | 954 | static int mctp_route_remove(struct mctp_dev *mdev, mctp_eid_t daddr_start, |
| 955 | − unsigned int daddr_extent) | |
| 955 | + unsigned int daddr_extent, unsigned char type) | |
| 956 | 956 | { |
| 957 | 957 | struct net *net = dev_net(mdev->dev); |
| 958 | 958 | struct mctp_route *rt, *tmp; |
| @@ -969,7 +969,8 @@ static int mctp_route_remove(struct mctp_dev *mdev, mctp_eid_t daddr_start, · 10 unmodified lines | ||
| 969 | 969 | |
| 970 | 970 | list_for_each_entry_safe(rt, tmp, &net->mctp.routes, list) { |
| 971 | 971 | if (rt->dev == mdev && |
| 972 | − rt->min == daddr_start && rt->max == daddr_end) { | |
| 972 | + rt->min == daddr_start && rt->max == daddr_end && | |
| 973 | + rt->type == type) { | |
| 973 | 974 | list_del_rcu(&rt->list); |
| 974 | 975 | /* TODO: immediate RTM_DELROUTE */ |
| 975 | 976 | mctp_route_release(rt); |
| @@ -987,7 +988,7 @@ int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr) · 11 unmodified lines | ||
| 987 | 988 | |
| 988 | 989 | int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr) |
| 989 | 990 | { |
| 990 | − return mctp_route_remove(mdev, addr, 0); | |
| 991 | + return mctp_route_remove(mdev, addr, 0, RTN_LOCAL); | |
| 991 | 992 | } |
| 992 | 993 | |
| 993 | 994 | /* removes all entries for a given device */ |
| @@ -1195,7 +1196,7 @@ static int mctp_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, · 201 unmodified lines | ||
| 1195 | 1196 | if (rtm->rtm_type != RTN_UNICAST) |
| 1196 | 1197 | return -EINVAL; |
| 1197 | 1198 | |
| 1198 | − rc = mctp_route_remove(mdev, daddr_start, rtm->rtm_dst_len); | |
| 1199 | + rc = mctp_route_remove(mdev, daddr_start, rtm->rtm_dst_len, RTN_UNICAST); | |
| 1199 | 1200 | return rc; |
| 1200 | 1201 | } |
| 1201 | 1202 | |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | static netdev_tx_t mctp_test_dev_tx(struct sk_buff *skb, |
| 13 | 13 | struct net_device *ndev) |
| 14 | 14 | { |
| 15 | − kfree(skb); | |
| 15 | + kfree_skb(skb); | |
| 16 | 16 | return NETDEV_TX_OK; |
| 17 | 17 | } |
| 18 | 18 | |
| @@ -409,7 +409,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev, · 408 unmodified lines | ||
| 409 | 409 | goto err; |
| 410 | 410 | |
| 411 | 411 | /* Find the output device */ |
| 412 | − out_dev = rcu_dereference(nh->nh_dev); | |
| 412 | + out_dev = nh->nh_dev; | |
| 413 | 413 | if (!mpls_output_possible(out_dev)) |
| 414 | 414 | goto tx_err; |
| 415 | 415 | |
| @@ -698,7 +698,7 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt, · 282 unmodified lines | ||
| 698 | 698 | (dev->addr_len != nh->nh_via_alen)) |
| 699 | 699 | goto errout; |
| 700 | 700 | |
| 701 | − RCU_INIT_POINTER(nh->nh_dev, dev); | |
| 701 | + nh->nh_dev = dev; | |
| 702 | 702 | |
| 703 | 703 | if (!(dev->flags & IFF_UP)) { |
| 704 | 704 | nh->nh_flags |= RTNH_F_DEAD; |
| @@ -1491,26 +1491,53 @@ static void mpls_dev_destroy_rcu(struct rcu_head *head) · 786 unmodified lines | ||
| 1491 | 1491 | kfree(mdev); |
| 1492 | 1492 | } |
| 1493 | 1493 | |
| 1494 | −static void mpls_ifdown(struct net_device *dev, int event) | |
| 1494 | +static int mpls_ifdown(struct net_device *dev, int event) | |
| 1495 | 1495 | { |
| 1496 | 1496 | struct mpls_route __rcu **platform_label; |
| 1497 | 1497 | struct net *net = dev_net(dev); |
| 1498 | − u8 alive, deleted; | |
| 1499 | 1498 | unsigned index; |
| 1500 | 1499 | |
| 1501 | 1500 | platform_label = rtnl_dereference(net->mpls.platform_label); |
| 1502 | 1501 | for (index = 0; index < net->mpls.platform_labels; index++) { |
| 1503 | 1502 | struct mpls_route *rt = rtnl_dereference(platform_label[index]); |
| 1503 | + bool nh_del = false; | |
| 1504 | + u8 alive = 0; | |
| 1504 | 1505 | |
| 1505 | 1506 | if (!rt) |
| 1506 | 1507 | continue; |
| 1507 | 1508 | |
| 1508 | − alive = 0; | |
| 1509 | − deleted = 0; | |
| 1509 | + if (event == NETDEV_UNREGISTER) { | |
| 1510 | + u8 deleted = 0; | |
| 1511 | + | |
| 1512 | + for_nexthops(rt) { | |
| 1513 | + if (!nh->nh_dev || nh->nh_dev == dev) | |
| 1514 | + deleted++; | |
| 1515 | + if (nh->nh_dev == dev) | |
| 1516 | + nh_del = true; | |
| 1517 | + } endfor_nexthops(rt); | |
| 1518 | + | |
| 1519 | + /* if there are no more nexthops, delete the route */ | |
| 1520 | + if (deleted == rt->rt_nhn) { | |
| 1521 | + mpls_route_update(net, index, NULL, NULL); | |
| 1522 | + continue; | |
| 1523 | + } | |
| 1524 | + | |
| 1525 | + if (nh_del) { | |
| 1526 | + size_t size = sizeof(*rt) + rt->rt_nhn * | |
| 1527 | + rt->rt_nh_size; | |
| 1528 | + struct mpls_route *orig = rt; | |
| 1529 | + | |
| 1530 | + rt = kmalloc(size, GFP_KERNEL); | |
| 1531 | + if (!rt) | |
| 1532 | + return -ENOMEM; | |
| 1533 | + memcpy(rt, orig, size); | |
| 1534 | + } | |
| 1535 | + } | |
| 1536 | + | |
| 1510 | 1537 | change_nexthops(rt) { |
| 1511 | 1538 | unsigned int nh_flags = nh->nh_flags; |
| 1512 | 1539 | |
| 1513 | − if (rtnl_dereference(nh->nh_dev) != dev) | |
| 1540 | + if (nh->nh_dev != dev) | |
| 1514 | 1541 | goto next; |
| 1515 | 1542 | |
| 1516 | 1543 | switch (event) { |
| @@ -1523,23 +1550,22 @@ static void mpls_ifdown(struct net_device *dev, int event) · 6 unmodified lines | ||
| 1523 | 1550 | break; |
| 1524 | 1551 | } |
| 1525 | 1552 | if (event == NETDEV_UNREGISTER) |
| 1526 | − RCU_INIT_POINTER(nh->nh_dev, NULL); | |
| 1553 | + nh->nh_dev = NULL; | |
| 1527 | 1554 | |
| 1528 | 1555 | if (nh->nh_flags != nh_flags) |
| 1529 | 1556 | WRITE_ONCE(nh->nh_flags, nh_flags); |
| 1530 | 1557 | next: |
| 1531 | 1558 | if (!(nh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN))) |
| 1532 | 1559 | alive++; |
| 1533 | − if (!rtnl_dereference(nh->nh_dev)) | |
| 1534 | − deleted++; | |
| 1535 | 1560 | } endfor_nexthops(rt); |
| 1536 | 1561 | |
| 1537 | 1562 | WRITE_ONCE(rt->rt_nhn_alive, alive); |
| 1538 | 1563 | |
| 1539 | − /* if there are no more nexthops, delete the route */ | |
| 1540 | − if (event == NETDEV_UNREGISTER && deleted == rt->rt_nhn) | |
| 1541 | − mpls_route_update(net, index, NULL, NULL); | |
| 1564 | + if (nh_del) | |
| 1565 | + mpls_route_update(net, index, rt, NULL); | |
| 1542 | 1566 | } |
| 1567 | + | |
| 1568 | + return 0; | |
| 1543 | 1569 | } |
| 1544 | 1570 | |
| 1545 | 1571 | static void mpls_ifup(struct net_device *dev, unsigned int flags) |
| @@ -1559,14 +1585,12 @@ static void mpls_ifup(struct net_device *dev, unsigned int flags) · 13 unmodified lines | ||
| 1559 | 1585 | alive = 0; |
| 1560 | 1586 | change_nexthops(rt) { |
| 1561 | 1587 | unsigned int nh_flags = nh->nh_flags; |
| 1562 | − struct net_device *nh_dev = | |
| 1563 | − rtnl_dereference(nh->nh_dev); | |
| 1564 | 1588 | |
| 1565 | 1589 | if (!(nh_flags & flags)) { |
| 1566 | 1590 | alive++; |
| 1567 | 1591 | continue; |
| 1568 | 1592 | } |
| 1569 | − if (nh_dev != dev) | |
| 1593 | + if (nh->nh_dev != dev) | |
| 1570 | 1594 | continue; |
| 1571 | 1595 | alive++; |
| 1572 | 1596 | nh_flags &= ~flags; |
| @@ -1597,8 +1621,12 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, · 24 unmodified lines | ||
| 1597 | 1621 | return NOTIFY_OK; |
| 1598 | 1622 | |
| 1599 | 1623 | switch (event) { |
| 1624 | + int err; | |
| 1625 | + | |
| 1600 | 1626 | case NETDEV_DOWN: |
| 1601 | − mpls_ifdown(dev, event); | |
| 1627 | + err = mpls_ifdown(dev, event); | |
| 1628 | + if (err) | |
| 1629 | + return notifier_from_errno(err); | |
| 1602 | 1630 | break; |
| 1603 | 1631 | case NETDEV_UP: |
| 1604 | 1632 | flags = dev_get_flags(dev); |
| @@ -1609,13 +1637,18 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, · 4 unmodified lines | ||
| 1609 | 1637 | break; |
| 1610 | 1638 | case NETDEV_CHANGE: |
| 1611 | 1639 | flags = dev_get_flags(dev); |
| 1612 | − if (flags & (IFF_RUNNING | IFF_LOWER_UP)) | |
| 1640 | + if (flags & (IFF_RUNNING | IFF_LOWER_UP)) { | |
| 1613 | 1641 | mpls_ifup(dev, RTNH_F_DEAD | RTNH_F_LINKDOWN); |
| 1614 | − else | |
| 1615 | − mpls_ifdown(dev, event); | |
| 1642 | + } else { | |
| 1643 | + err = mpls_ifdown(dev, event); | |
| 1644 | + if (err) | |
| 1645 | + return notifier_from_errno(err); | |
| 1646 | + } | |
| 1616 | 1647 | break; |
| 1617 | 1648 | case NETDEV_UNREGISTER: |
| 1618 | − mpls_ifdown(dev, event); | |
| 1649 | + err = mpls_ifdown(dev, event); | |
| 1650 | + if (err) | |
| 1651 | + return notifier_from_errno(err); | |
| 1619 | 1652 | mdev = mpls_dev_get(dev); |
| 1620 | 1653 | if (mdev) { |
| 1621 | 1654 | mpls_dev_sysctl_unregister(dev, mdev); |
| @@ -1626,8 +1659,6 @@ static int mpls_dev_notify(struct notifier_block *this, unsigned long event, · 4 unmodified lines | ||
| 1626 | 1659 | case NETDEV_CHANGENAME: |
| 1627 | 1660 | mdev = mpls_dev_get(dev); |
| 1628 | 1661 | if (mdev) { |
| 1629 | − int err; | |
| 1630 | − | |
| 1631 | 1662 | mpls_dev_sysctl_unregister(dev, mdev); |
| 1632 | 1663 | err = mpls_dev_sysctl_register(dev, mdev); |
| 1633 | 1664 | if (err) |
| @@ -1994,7 +2025,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, · 360 unmodified lines | ||
| 1994 | 2025 | nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), |
| 1995 | 2026 | nh->nh_via_alen)) |
| 1996 | 2027 | goto nla_put_failure; |
| 1997 | − dev = rtnl_dereference(nh->nh_dev); | |
| 2028 | + dev = nh->nh_dev; | |
| 1998 | 2029 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) |
| 1999 | 2030 | goto nla_put_failure; |
| 2000 | 2031 | if (nh->nh_flags & RTNH_F_LINKDOWN) |
| @@ -2012,7 +2043,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event, · 11 unmodified lines | ||
| 2012 | 2043 | goto nla_put_failure; |
| 2013 | 2044 | |
| 2014 | 2045 | for_nexthops(rt) { |
| 2015 | − dev = rtnl_dereference(nh->nh_dev); | |
| 2046 | + dev = nh->nh_dev; | |
| 2016 | 2047 | if (!dev) |
| 2017 | 2048 | continue; |
| 2018 | 2049 | |
| @@ -2123,18 +2154,14 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, · 104 unmodified lines | ||
| 2123 | 2154 | static bool mpls_rt_uses_dev(struct mpls_route *rt, |
| 2124 | 2155 | const struct net_device *dev) |
| 2125 | 2156 | { |
| 2126 | − struct net_device *nh_dev; | |
| 2127 | − | |
| 2128 | 2157 | if (rt->rt_nhn == 1) { |
| 2129 | 2158 | struct mpls_nh *nh = rt->rt_nh; |
| 2130 | 2159 | |
| 2131 | − nh_dev = rtnl_dereference(nh->nh_dev); | |
| 2132 | − if (dev == nh_dev) | |
| 2160 | + if (nh->nh_dev == dev) | |
| 2133 | 2161 | return true; |
| 2134 | 2162 | } else { |
| 2135 | 2163 | for_nexthops(rt) { |
| 2136 | − nh_dev = rtnl_dereference(nh->nh_dev); | |
| 2137 | − if (nh_dev == dev) | |
| 2164 | + if (nh->nh_dev == dev) | |
| 2138 | 2165 | return true; |
| 2139 | 2166 | } endfor_nexthops(rt); |
| 2140 | 2167 | } |
| @@ -2222,7 +2249,7 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt) · 81 unmodified lines | ||
| 2222 | 2249 | size_t nhsize = 0; |
| 2223 | 2250 | |
| 2224 | 2251 | for_nexthops(rt) { |
| 2225 | − if (!rtnl_dereference(nh->nh_dev)) | |
| 2252 | + if (!nh->nh_dev) | |
| 2226 | 2253 | continue; |
| 2227 | 2254 | nhsize += nla_total_size(sizeof(struct rtnexthop)); |
| 2228 | 2255 | /* RTA_VIA */ |
| @@ -2468,7 +2495,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, · 239 unmodified lines | ||
| 2468 | 2495 | nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh), |
| 2469 | 2496 | nh->nh_via_alen)) |
| 2470 | 2497 | goto nla_put_failure; |
| 2471 | − dev = rtnl_dereference(nh->nh_dev); | |
| 2498 | + dev = nh->nh_dev; | |
| 2472 | 2499 | if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex)) |
| 2473 | 2500 | goto nla_put_failure; |
| 2474 | 2501 | |
| @@ -2507,7 +2534,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) · 32 unmodified lines | ||
| 2507 | 2534 | rt0 = mpls_rt_alloc(1, lo->addr_len, 0); |
| 2508 | 2535 | if (IS_ERR(rt0)) |
| 2509 | 2536 | goto nort0; |
| 2510 | − RCU_INIT_POINTER(rt0->rt_nh->nh_dev, lo); | |
| 2537 | + rt0->rt_nh->nh_dev = lo; | |
| 2511 | 2538 | rt0->rt_protocol = RTPROT_KERNEL; |
| 2512 | 2539 | rt0->rt_payload_type = MPT_IPV4; |
| 2513 | 2540 | rt0->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT; |
| @@ -2521,7 +2548,7 @@ static int resize_platform_label_table(struct net *net, size_t limit) · 7 unmodified lines | ||
| 2521 | 2548 | rt2 = mpls_rt_alloc(1, lo->addr_len, 0); |
| 2522 | 2549 | if (IS_ERR(rt2)) |
| 2523 | 2550 | goto nort2; |
| 2524 | − RCU_INIT_POINTER(rt2->rt_nh->nh_dev, lo); | |
| 2551 | + rt2->rt_nh->nh_dev = lo; | |
| 2525 | 2552 | rt2->rt_protocol = RTPROT_KERNEL; |
| 2526 | 2553 | rt2->rt_payload_type = MPT_IPV6; |
| 2527 | 2554 | rt2->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT; |
| @@ -87,7 +87,7 @@ enum mpls_payload_type { · 86 unmodified lines | ||
| 87 | 87 | }; |
| 88 | 88 | |
| 89 | 89 | struct mpls_nh { /* next hop label forwarding entry */ |
| 90 | − struct net_device __rcu *nh_dev; | |
| 90 | + struct net_device *nh_dev; | |
| 91 | 91 | |
| 92 | 92 | /* nh_flags is accessed under RCU in the packet path; it is |
| 93 | 93 | * modified handling netdev events with rtnl lock held |
| @@ -684,7 +684,7 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) · 683 unmodified lines | ||
| 684 | 684 | |
| 685 | 685 | tstamp = nf_conn_tstamp_find(ct); |
| 686 | 686 | if (tstamp) { |
| 687 | − s32 timeout = ct->timeout - nfct_time_stamp; | |
| 687 | + s32 timeout = READ_ONCE(ct->timeout) - nfct_time_stamp; | |
| 688 | 688 | |
| 689 | 689 | tstamp->stop = ktime_get_real_ns(); |
| 690 | 690 | if (timeout < 0) |
| @@ -1036,7 +1036,7 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx) · 345 unmodified lines | ||
| 1036 | 1036 | } |
| 1037 | 1037 | |
| 1038 | 1038 | /* We want the clashing entry to go away real soon: 1 second timeout. */ |
| 1039 | − loser_ct->timeout = nfct_time_stamp + HZ; | |
| 1039 | + WRITE_ONCE(loser_ct->timeout, nfct_time_stamp + HZ); | |
| 1040 | 1040 | |
| 1041 | 1041 | /* IPS_NAT_CLASH removes the entry automatically on the first |
| 1042 | 1042 | * reply. Also prevents UDP tracker from moving the entry to |
| @@ -1560,7 +1560,7 @@ __nf_conntrack_alloc(struct net *net, · 517 unmodified lines | ||
| 1560 | 1560 | /* save hash for reusing when confirming */ |
| 1561 | 1561 | *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash; |
| 1562 | 1562 | ct->status = 0; |
| 1563 | − ct->timeout = 0; | |
| 1563 | + WRITE_ONCE(ct->timeout, 0); | |
| 1564 | 1564 | write_pnet(&ct->ct_net, net); |
| 1565 | 1565 | memset(&ct->__nfct_init_offset, 0, |
| 1566 | 1566 | offsetof(struct nf_conn, proto) - |
| @@ -1998,7 +1998,7 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, · 1997 unmodified lines | ||
| 1998 | 1998 | |
| 1999 | 1999 | if (timeout > INT_MAX) |
| 2000 | 2000 | timeout = INT_MAX; |
| 2001 | − ct->timeout = nfct_time_stamp + (u32)timeout; | |
| 2001 | + WRITE_ONCE(ct->timeout, nfct_time_stamp + (u32)timeout); | |
| 2002 | 2002 | |
| 2003 | 2003 | if (test_bit(IPS_DYING_BIT, &ct->status)) |
| 2004 | 2004 | return -ETIME; |
| @@ -201,8 +201,8 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) · 200 unmodified lines | ||
| 201 | 201 | if (timeout < 0) |
| 202 | 202 | timeout = 0; |
| 203 | 203 | |
| 204 | − if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout) | |
| 205 | − ct->timeout = nfct_time_stamp + timeout; | |
| 204 | + if (nf_flow_timeout_delta(READ_ONCE(ct->timeout)) > (__s32)timeout) | |
| 205 | + WRITE_ONCE(ct->timeout, nfct_time_stamp + timeout); | |
| 206 | 206 | } |
| 207 | 207 | |
| 208 | 208 | static void flow_offload_fixup_ct_state(struct nf_conn *ct) |
| @@ -387,7 +387,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, · 386 unmodified lines | ||
| 387 | 387 | struct net_device *indev; |
| 388 | 388 | struct net_device *outdev; |
| 389 | 389 | struct nf_conn *ct = NULL; |
| 390 | − enum ip_conntrack_info ctinfo; | |
| 390 | + enum ip_conntrack_info ctinfo = 0; | |
| 391 | 391 | struct nfnl_ct_hook *nfnl_ct; |
| 392 | 392 | bool csum_verify; |
| 393 | 393 | char *secdata = NULL; |
| @@ -236,7 +236,7 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, · 235 unmodified lines | ||
| 236 | 236 | |
| 237 | 237 | tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, &tcphdr_len); |
| 238 | 238 | if (!tcph) |
| 239 | − return; | |
| 239 | + goto err; | |
| 240 | 240 | |
| 241 | 241 | opt = (u8 *)tcph; |
| 242 | 242 | for (i = sizeof(*tcph); i < tcphdr_len - 1; i += optl) { |
| @@ -251,16 +251,16 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, · 8 unmodified lines | ||
| 251 | 251 | continue; |
| 252 | 252 | |
| 253 | 253 | if (i + optl > tcphdr_len || priv->len + priv->offset > optl) |
| 254 | − return; | |
| 254 | + goto err; | |
| 255 | 255 | |
| 256 | 256 | if (skb_ensure_writable(pkt->skb, |
| 257 | 257 | nft_thoff(pkt) + i + priv->len)) |
| 258 | − return; | |
| 258 | + goto err; | |
| 259 | 259 | |
| 260 | 260 | tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff, |
| 261 | 261 | &tcphdr_len); |
| 262 | 262 | if (!tcph) |
| 263 | − return; | |
| 263 | + goto err; | |
| 264 | 264 | |
| 265 | 265 | offset = i + priv->offset; |
| 266 | 266 | |
| @@ -303,6 +303,9 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr, · 36 unmodified lines | ||
| 303 | 303 | |
| 304 | 304 | return; |
| 305 | 305 | } |
| 306 | + return; | |
| 307 | +err: | |
| 308 | + regs->verdict.code = NFT_BREAK; | |
| 306 | 309 | } |
| 307 | 310 | |
| 308 | 311 | static void nft_exthdr_sctp_eval(const struct nft_expr *expr, |
| @@ -886,7 +886,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill, · 885 unmodified lines | ||
| 886 | 886 | NFT_PIPAPO_AVX2_BUCKET_LOAD8(4, lt, 4, pkt[4], bsize); |
| 887 | 887 | |
| 888 | 888 | NFT_PIPAPO_AVX2_AND(5, 0, 1); |
| 889 | − NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 6, pkt[5], bsize); | |
| 889 | + NFT_PIPAPO_AVX2_BUCKET_LOAD8(6, lt, 5, pkt[5], bsize); | |
| 890 | 890 | NFT_PIPAPO_AVX2_AND(7, 2, 3); |
| 891 | 891 | |
| 892 | 892 | /* Stall */ |
| @@ -1852,6 +1852,11 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) · 1851 unmodified lines | ||
| 1852 | 1852 | if (msg->msg_flags & MSG_OOB) |
| 1853 | 1853 | return -EOPNOTSUPP; |
| 1854 | 1854 | |
| 1855 | + if (len == 0) { | |
| 1856 | + pr_warn_once("Zero length message leads to an empty skb\n"); | |
| 1857 | + return -ENODATA; | |
| 1858 | + } | |
| 1859 | + | |
| 1855 | 1860 | err = scm_send(sock, msg, &scm, true); |
| 1856 | 1861 | if (err < 0) |
| 1857 | 1862 | return err; |
| @@ -636,8 +636,10 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) · 635 unmodified lines | ||
| 636 | 636 | { |
| 637 | 637 | struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; |
| 638 | 638 | |
| 639 | − nfc_device_iter_exit(iter); | |
| 640 | − kfree(iter); | |
| 639 | + if (iter) { | |
| 640 | + nfc_device_iter_exit(iter); | |
| 641 | + kfree(iter); | |
| 642 | + } | |
| 641 | 643 | |
| 642 | 644 | return 0; |
| 643 | 645 | } |
| @@ -1392,8 +1394,10 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) · 748 unmodified lines | ||
| 1392 | 1394 | { |
| 1393 | 1395 | struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; |
| 1394 | 1396 | |
| 1395 | − nfc_device_iter_exit(iter); | |
| 1396 | − kfree(iter); | |
| 1397 | + if (iter) { | |
| 1398 | + nfc_device_iter_exit(iter); | |
| 1399 | + kfree(iter); | |
| 1400 | + } | |
| 1397 | 1401 | |
| 1398 | 1402 | return 0; |
| 1399 | 1403 | } |
| @@ -500,7 +500,7 @@ void rds_tcp_tune(struct socket *sock) · 499 unmodified lines | ||
| 500 | 500 | sk->sk_userlocks |= SOCK_SNDBUF_LOCK; |
| 501 | 501 | } |
| 502 | 502 | if (rtn->rcvbuf_size > 0) { |
| 503 | − sk->sk_sndbuf = rtn->rcvbuf_size; | |
| 503 | + sk->sk_rcvbuf = rtn->rcvbuf_size; | |
| 504 | 504 | sk->sk_userlocks |= SOCK_RCVBUF_LOCK; |
| 505 | 505 | } |
| 506 | 506 | release_sock(sk); |
| @@ -135,16 +135,20 @@ struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle) · 134 unmodified lines | ||
| 135 | 135 | return bundle; |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | +static void rxrpc_free_bundle(struct rxrpc_bundle *bundle) | |
| 139 | +{ | |
| 140 | + rxrpc_put_peer(bundle->params.peer); | |
| 141 | + kfree(bundle); | |
| 142 | +} | |
| 143 | + | |
| 138 | 144 | void rxrpc_put_bundle(struct rxrpc_bundle *bundle) |
| 139 | 145 | { |
| 140 | 146 | unsigned int d = bundle->debug_id; |
| 141 | 147 | unsigned int u = atomic_dec_return(&bundle->usage); |
| 142 | 148 | |
| 143 | 149 | _debug("PUT B=%x %u", d, u); |
| 144 | − if (u == 0) { | |
| 145 | − rxrpc_put_peer(bundle->params.peer); | |
| 146 | − kfree(bundle); | |
| 147 | − } | |
| 150 | + if (u == 0) | |
| 151 | + rxrpc_free_bundle(bundle); | |
| 148 | 152 | } |
| 149 | 153 | |
| 150 | 154 | /* |
| @@ -328,7 +332,7 @@ static struct rxrpc_bundle *rxrpc_look_up_bundle(struct rxrpc_conn_parameters *c · 177 unmodified lines | ||
| 328 | 332 | return candidate; |
| 329 | 333 | |
| 330 | 334 | found_bundle_free: |
| 331 | − kfree(candidate); | |
| 335 | + rxrpc_free_bundle(candidate); | |
| 332 | 336 | found_bundle: |
| 333 | 337 | rxrpc_get_bundle(bundle); |
| 334 | 338 | spin_unlock(&local->client_bundles_lock); |
| @@ -299,6 +299,12 @@ static struct rxrpc_peer *rxrpc_create_peer(struct rxrpc_sock *rx, · 298 unmodified lines | ||
| 299 | 299 | return peer; |
| 300 | 300 | } |
| 301 | 301 | |
| 302 | +static void rxrpc_free_peer(struct rxrpc_peer *peer) | |
| 303 | +{ | |
| 304 | + rxrpc_put_local(peer->local); | |
| 305 | + kfree_rcu(peer, rcu); | |
| 306 | +} | |
| 307 | + | |
| 302 | 308 | /* |
| 303 | 309 | * Set up a new incoming peer. There shouldn't be any other matching peers |
| 304 | 310 | * since we've already done a search in the list from the non-reentrant context |
| @@ -365,7 +371,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_sock *rx, · 60 unmodified lines | ||
| 365 | 371 | spin_unlock_bh(&rxnet->peer_hash_lock); |
| 366 | 372 | |
| 367 | 373 | if (peer) |
| 368 | − kfree(candidate); | |
| 374 | + rxrpc_free_peer(candidate); | |
| 369 | 375 | else |
| 370 | 376 | peer = candidate; |
| 371 | 377 | } |
| @@ -420,8 +426,7 @@ static void __rxrpc_put_peer(struct rxrpc_peer *peer) · 48 unmodified lines | ||
| 420 | 426 | list_del_init(&peer->keepalive_link); |
| 421 | 427 | spin_unlock_bh(&rxnet->peer_hash_lock); |
| 422 | 428 | |
| 423 | − rxrpc_put_local(peer->local); | |
| 424 | − kfree_rcu(peer, rcu); | |
| 429 | + rxrpc_free_peer(peer); | |
| 425 | 430 | } |
| 426 | 431 | |
| 427 | 432 | /* |
| @@ -457,8 +462,7 @@ void rxrpc_put_peer_locked(struct rxrpc_peer *peer) · 29 unmodified lines | ||
| 457 | 462 | if (n == 0) { |
| 458 | 463 | hash_del_rcu(&peer->hash_link); |
| 459 | 464 | list_del_init(&peer->keepalive_link); |
| 460 | − rxrpc_put_local(peer->local); | |
| 461 | − kfree_rcu(peer, rcu); | |
| 465 | + rxrpc_free_peer(peer); | |
| 462 | 466 | } |
| 463 | 467 | } |
| 464 | 468 | |
| @@ -531,6 +531,7 @@ static void fq_pie_destroy(struct Qdisc *sch) · 530 unmodified lines | ||
| 531 | 531 | struct fq_pie_sched_data *q = qdisc_priv(sch); |
| 532 | 532 | |
| 533 | 533 | tcf_block_put(q->block); |
| 534 | + q->p_params.tupdate = 0; | |
| 534 | 535 | del_timer_sync(&q->adapt_timer); |
| 535 | 536 | kvfree(q->flows); |
| 536 | 537 | } |
| @@ -195,6 +195,7 @@ int smc_close_active(struct smc_sock *smc) · 194 unmodified lines | ||
| 195 | 195 | int old_state; |
| 196 | 196 | long timeout; |
| 197 | 197 | int rc = 0; |
| 198 | + int rc1 = 0; | |
| 198 | 199 | |
| 199 | 200 | timeout = current->flags & PF_EXITING ? |
| 200 | 201 | 0 : sock_flag(sk, SOCK_LINGER) ? |
| @@ -232,8 +233,11 @@ again: · 31 unmodified lines | ||
| 232 | 233 | /* actively shutdown clcsock before peer close it, |
| 233 | 234 | * prevent peer from entering TIME_WAIT state. |
| 234 | 235 | */ |
| 235 | − if (smc->clcsock && smc->clcsock->sk) | |
| 236 | − rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); | |
| 236 | + if (smc->clcsock && smc->clcsock->sk) { | |
| 237 | + rc1 = kernel_sock_shutdown(smc->clcsock, | |
| 238 | + SHUT_RDWR); | |
| 239 | + rc = rc ? rc : rc1; | |
| 240 | + } | |
| 237 | 241 | } else { |
| 238 | 242 | /* peer event has changed the state */ |
| 239 | 243 | goto again; |
| @@ -625,18 +625,17 @@ int smcd_nl_get_lgr(struct sk_buff *skb, struct netlink_callback *cb) · 624 unmodified lines | ||
| 625 | 625 | void smc_lgr_cleanup_early(struct smc_connection *conn) |
| 626 | 626 | { |
| 627 | 627 | struct smc_link_group *lgr = conn->lgr; |
| 628 | − struct list_head *lgr_list; | |
| 629 | 628 | spinlock_t *lgr_lock; |
| 630 | 629 | |
| 631 | 630 | if (!lgr) |
| 632 | 631 | return; |
| 633 | 632 | |
| 634 | 633 | smc_conn_free(conn); |
| 635 | − lgr_list = smc_lgr_list_head(lgr, &lgr_lock); | |
| 634 | + smc_lgr_list_head(lgr, &lgr_lock); | |
| 636 | 635 | spin_lock_bh(lgr_lock); |
| 637 | 636 | /* do not use this link group for new connections */ |
| 638 | − if (!list_empty(lgr_list)) | |
| 639 | − list_del_init(lgr_list); | |
| 637 | + if (!list_empty(&lgr->list)) | |
| 638 | + list_del_init(&lgr->list); | |
| 640 | 639 | spin_unlock_bh(lgr_lock); |
| 641 | 640 | __smc_lgr_terminate(lgr, true); |
| 642 | 641 | } |
| @@ -521,7 +521,7 @@ static int tls_do_encryption(struct sock *sk, · 520 unmodified lines | ||
| 521 | 521 | memcpy(&rec->iv_data[iv_offset], tls_ctx->tx.iv, |
| 522 | 522 | prot->iv_size + prot->salt_size); |
| 523 | 523 | |
| 524 | − xor_iv_with_seq(prot, rec->iv_data, tls_ctx->tx.rec_seq); | |
| 524 | + xor_iv_with_seq(prot, rec->iv_data + iv_offset, tls_ctx->tx.rec_seq); | |
| 525 | 525 | |
| 526 | 526 | sge->offset += prot->prepend_size; |
| 527 | 527 | sge->length -= prot->prepend_size; |
| @@ -1499,7 +1499,7 @@ static int decrypt_internal(struct sock *sk, struct sk_buff *skb, · 971 unmodified lines | ||
| 1499 | 1499 | else |
| 1500 | 1500 | memcpy(iv + iv_offset, tls_ctx->rx.iv, prot->salt_size); |
| 1501 | 1501 | |
| 1502 | − xor_iv_with_seq(prot, iv, tls_ctx->rx.rec_seq); | |
| 1502 | + xor_iv_with_seq(prot, iv + iv_offset, tls_ctx->rx.rec_seq); | |
| 1503 | 1503 | |
| 1504 | 1504 | /* Prepare AAD */ |
| 1505 | 1505 | tls_make_aad(aad, rxm->full_len - prot->overhead_size + |
| @@ -4,6 +4,7 @@ obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct.o · 3 unmodified lines | ||
| 4 | 4 | obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o |
| 5 | 5 | obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o |
| 6 | 6 | obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi.o |
| 7 | +obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi-modify.o | |
| 7 | 8 | |
| 8 | 9 | CFLAGS_sample-trace-array.o := -I$(src) |
| 9 | 10 | obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += sample-trace-array.o |
| @@ -0,0 +1,152 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +#include <linux/module.h> | |
| 3 | +#include <linux/kthread.h> | |
| 4 | +#include <linux/ftrace.h> | |
| 5 | +#include <asm/asm-offsets.h> | |
| 6 | + | |
| 7 | +void my_direct_func1(unsigned long ip) | |
| 8 | +{ | |
| 9 | + trace_printk("my direct func1 ip %lx\n", ip); | |
| 10 | +} | |
| 11 | + | |
| 12 | +void my_direct_func2(unsigned long ip) | |
| 13 | +{ | |
| 14 | + trace_printk("my direct func2 ip %lx\n", ip); | |
| 15 | +} | |
| 16 | + | |
| 17 | +extern void my_tramp1(void *); | |
| 18 | +extern void my_tramp2(void *); | |
| 19 | + | |
| 20 | +#ifdef CONFIG_X86_64 | |
| 21 | + | |
| 22 | +asm ( | |
| 23 | +" .pushsection .text, \"ax\", @progbits\n" | |
| 24 | +" .type my_tramp1, @function\n" | |
| 25 | +" .globl my_tramp1\n" | |
| 26 | +" my_tramp1:" | |
| 27 | +" pushq %rbp\n" | |
| 28 | +" movq %rsp, %rbp\n" | |
| 29 | +" pushq %rdi\n" | |
| 30 | +" movq 8(%rbp), %rdi\n" | |
| 31 | +" call my_direct_func1\n" | |
| 32 | +" popq %rdi\n" | |
| 33 | +" leave\n" | |
| 34 | +" ret\n" | |
| 35 | +" .size my_tramp1, .-my_tramp1\n" | |
| 36 | +" .type my_tramp2, @function\n" | |
| 37 | +"\n" | |
| 38 | +" .globl my_tramp2\n" | |
| 39 | +" my_tramp2:" | |
| 40 | +" pushq %rbp\n" | |
| 41 | +" movq %rsp, %rbp\n" | |
| 42 | +" pushq %rdi\n" | |
| 43 | +" movq 8(%rbp), %rdi\n" | |
| 44 | +" call my_direct_func2\n" | |
| 45 | +" popq %rdi\n" | |
| 46 | +" leave\n" | |
| 47 | +" ret\n" | |
| 48 | +" .size my_tramp2, .-my_tramp2\n" | |
| 49 | +" .popsection\n" | |
| 50 | +); | |
| 51 | + | |
| 52 | +#endif /* CONFIG_X86_64 */ | |
| 53 | + | |
| 54 | +#ifdef CONFIG_S390 | |
| 55 | + | |
| 56 | +asm ( | |
| 57 | +" .pushsection .text, \"ax\", @progbits\n" | |
| 58 | +" .type my_tramp1, @function\n" | |
| 59 | +" .globl my_tramp1\n" | |
| 60 | +" my_tramp1:" | |
| 61 | +" lgr %r1,%r15\n" | |
| 62 | +" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" | |
| 63 | +" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" | |
| 64 | +" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n" | |
| 65 | +" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n" | |
| 66 | +" lgr %r2,%r0\n" | |
| 67 | +" brasl %r14,my_direct_func1\n" | |
| 68 | +" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n" | |
| 69 | +" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" | |
| 70 | +" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" | |
| 71 | +" lgr %r1,%r0\n" | |
| 72 | +" br %r1\n" | |
| 73 | +" .size my_tramp1, .-my_tramp1\n" | |
| 74 | +"\n" | |
| 75 | +" .type my_tramp2, @function\n" | |
| 76 | +" .globl my_tramp2\n" | |
| 77 | +" my_tramp2:" | |
| 78 | +" lgr %r1,%r15\n" | |
| 79 | +" stmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" | |
| 80 | +" stg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" | |
| 81 | +" aghi %r15,"__stringify(-STACK_FRAME_OVERHEAD)"\n" | |
| 82 | +" stg %r1,"__stringify(__SF_BACKCHAIN)"(%r15)\n" | |
| 83 | +" lgr %r2,%r0\n" | |
| 84 | +" brasl %r14,my_direct_func2\n" | |
| 85 | +" aghi %r15,"__stringify(STACK_FRAME_OVERHEAD)"\n" | |
| 86 | +" lmg %r0,%r5,"__stringify(__SF_GPRS)"(%r15)\n" | |
| 87 | +" lg %r14,"__stringify(__SF_GPRS+8*8)"(%r15)\n" | |
| 88 | +" lgr %r1,%r0\n" | |
| 89 | +" br %r1\n" | |
| 90 | +" .size my_tramp2, .-my_tramp2\n" | |
| 91 | +" .popsection\n" | |
| 92 | +); | |
| 93 | + | |
| 94 | +#endif /* CONFIG_S390 */ | |
| 95 | + | |
| 96 | +static unsigned long my_tramp = (unsigned long)my_tramp1; | |
| 97 | +static unsigned long tramps[2] = { | |
| 98 | + (unsigned long)my_tramp1, | |
| 99 | + (unsigned long)my_tramp2, | |
| 100 | +}; | |
| 101 | + | |
| 102 | +static struct ftrace_ops direct; | |
| 103 | + | |
| 104 | +static int simple_thread(void *arg) | |
| 105 | +{ | |
| 106 | + static int t; | |
| 107 | + int ret = 0; | |
| 108 | + | |
| 109 | + while (!kthread_should_stop()) { | |
| 110 | + set_current_state(TASK_INTERRUPTIBLE); | |
| 111 | + schedule_timeout(2 * HZ); | |
| 112 | + | |
| 113 | + if (ret) | |
| 114 | + continue; | |
| 115 | + t ^= 1; | |
| 116 | + ret = modify_ftrace_direct_multi(&direct, tramps[t]); | |
| 117 | + if (!ret) | |
| 118 | + my_tramp = tramps[t]; | |
| 119 | + WARN_ON_ONCE(ret); | |
| 120 | + } | |
| 121 | + | |
| 122 | + return 0; | |
| 123 | +} | |
| 124 | + | |
| 125 | +static struct task_struct *simple_tsk; | |
| 126 | + | |
| 127 | +static int __init ftrace_direct_multi_init(void) | |
| 128 | +{ | |
| 129 | + int ret; | |
| 130 | + | |
| 131 | + ftrace_set_filter_ip(&direct, (unsigned long) wake_up_process, 0, 0); | |
| 132 | + ftrace_set_filter_ip(&direct, (unsigned long) schedule, 0, 0); | |
| 133 | + | |
| 134 | + ret = register_ftrace_direct_multi(&direct, my_tramp); | |
| 135 | + | |
| 136 | + if (!ret) | |
| 137 | + simple_tsk = kthread_run(simple_thread, NULL, "event-sample-fn"); | |
| 138 | + return ret; | |
| 139 | +} | |
| 140 | + | |
| 141 | +static void __exit ftrace_direct_multi_exit(void) | |
| 142 | +{ | |
| 143 | + kthread_stop(simple_tsk); | |
| 144 | + unregister_ftrace_direct_multi(&direct, my_tramp); | |
| 145 | +} | |
| 146 | + | |
| 147 | +module_init(ftrace_direct_multi_init); | |
| 148 | +module_exit(ftrace_direct_multi_exit); | |
| 149 | + | |
| 150 | +MODULE_AUTHOR("Jiri Olsa"); | |
| 151 | +MODULE_DESCRIPTION("Example use case of using modify_ftrace_direct_multi()"); | |
| 152 | +MODULE_LICENSE("GPL"); | |
| @@ -264,6 +264,7 @@ static int copy_ctl_value_to_user(void __user *userdata, · 263 unmodified lines | ||
| 264 | 264 | struct snd_ctl_elem_value *data, |
| 265 | 265 | int type, int count) |
| 266 | 266 | { |
| 267 | + struct snd_ctl_elem_value32 __user *data32 = userdata; | |
| 267 | 268 | int i, size; |
| 268 | 269 | |
| 269 | 270 | if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN || |
| @@ -280,6 +281,8 @@ static int copy_ctl_value_to_user(void __user *userdata, · 10 unmodified lines | ||
| 280 | 281 | if (copy_to_user(valuep, data->value.bytes.data, size)) |
| 281 | 282 | return -EFAULT; |
| 282 | 283 | } |
| 284 | + if (copy_to_user(&data32->id, &data->id, sizeof(data32->id))) | |
| 285 | + return -EFAULT; | |
| 283 | 286 | return 0; |
| 284 | 287 | } |
| 285 | 288 | |
| @@ -147,7 +147,7 @@ snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, · 146 unmodified lines | ||
| 147 | 147 | * |
| 148 | 148 | * Return the maximum value for field PAR. |
| 149 | 149 | */ |
| 150 | −static unsigned int | |
| 150 | +static int | |
| 151 | 151 | snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, |
| 152 | 152 | snd_pcm_hw_param_t var, int *dir) |
| 153 | 153 | { |
| @@ -682,18 +682,24 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, · 528 unmodified lines | ||
| 682 | 682 | struct snd_pcm_hw_params *oss_params, |
| 683 | 683 | struct snd_pcm_hw_params *slave_params) |
| 684 | 684 | { |
| 685 | − size_t s; | |
| 686 | − size_t oss_buffer_size, oss_period_size, oss_periods; | |
| 687 | − size_t min_period_size, max_period_size; | |
| 685 | + ssize_t s; | |
| 686 | + ssize_t oss_buffer_size; | |
| 687 | + ssize_t oss_period_size, oss_periods; | |
| 688 | + ssize_t min_period_size, max_period_size; | |
| 688 | 689 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 689 | 690 | size_t oss_frame_size; |
| 690 | 691 | |
| 691 | 692 | oss_frame_size = snd_pcm_format_physical_width(params_format(oss_params)) * |
| 692 | 693 | params_channels(oss_params) / 8; |
| 693 | 694 | |
| 695 | + oss_buffer_size = snd_pcm_hw_param_value_max(slave_params, | |
| 696 | + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | |
| 697 | + NULL); | |
| 698 | + if (oss_buffer_size <= 0) | |
| 699 | + return -EINVAL; | |
| 694 | 700 | oss_buffer_size = snd_pcm_plug_client_size(substream, |
| 695 | − snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; | |
| 696 | − if (!oss_buffer_size) | |
| 701 | + oss_buffer_size * oss_frame_size); | |
| 702 | + if (oss_buffer_size <= 0) | |
| 697 | 703 | return -EINVAL; |
| 698 | 704 | oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); |
| 699 | 705 | if (atomic_read(&substream->mmap_count)) { |
| @@ -730,7 +736,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, · 30 unmodified lines | ||
| 730 | 736 | |
| 731 | 737 | min_period_size = snd_pcm_plug_client_size(substream, |
| 732 | 738 | snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); |
| 733 | − if (min_period_size) { | |
| 739 | + if (min_period_size > 0) { | |
| 734 | 740 | min_period_size *= oss_frame_size; |
| 735 | 741 | min_period_size = roundup_pow_of_two(min_period_size); |
| 736 | 742 | if (oss_period_size < min_period_size) |
| @@ -739,7 +745,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, · 2 unmodified lines | ||
| 739 | 745 | |
| 740 | 746 | max_period_size = snd_pcm_plug_client_size(substream, |
| 741 | 747 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); |
| 742 | − if (max_period_size) { | |
| 748 | + if (max_period_size > 0) { | |
| 743 | 749 | max_period_size *= oss_frame_size; |
| 744 | 750 | max_period_size = rounddown_pow_of_two(max_period_size); |
| 745 | 751 | if (oss_period_size > max_period_size) |
| @@ -752,7 +758,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, · 6 unmodified lines | ||
| 752 | 758 | oss_periods = substream->oss.setup.periods; |
| 753 | 759 | |
| 754 | 760 | s = snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIODS, NULL); |
| 755 | − if (runtime->oss.maxfrags && s > runtime->oss.maxfrags) | |
| 761 | + if (s > 0 && runtime->oss.maxfrags && s > runtime->oss.maxfrags) | |
| 756 | 762 | s = runtime->oss.maxfrags; |
| 757 | 763 | if (oss_periods > s) |
| 758 | 764 | oss_periods = s; |
| @@ -878,8 +884,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) · 119 unmodified lines | ||
| 878 | 884 | err = -EINVAL; |
| 879 | 885 | goto failure; |
| 880 | 886 | } |
| 881 | − choose_rate(substream, sparams, runtime->oss.rate); | |
| 882 | − snd_pcm_hw_param_near(substream, sparams, SNDRV_PCM_HW_PARAM_CHANNELS, runtime->oss.channels, NULL); | |
| 887 | + | |
| 888 | + err = choose_rate(substream, sparams, runtime->oss.rate); | |
| 889 | + if (err < 0) | |
| 890 | + goto failure; | |
| 891 | + err = snd_pcm_hw_param_near(substream, sparams, | |
| 892 | + SNDRV_PCM_HW_PARAM_CHANNELS, | |
| 893 | + runtime->oss.channels, NULL); | |
| 894 | + if (err < 0) | |
| 895 | + goto failure; | |
| 883 | 896 | |
| 884 | 897 | format = snd_pcm_oss_format_from(runtime->oss.format); |
| 885 | 898 | |
| @@ -1956,7 +1969,7 @@ static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsign · 1070 unmodified lines | ||
| 1956 | 1969 | if (runtime->oss.subdivision || runtime->oss.fragshift) |
| 1957 | 1970 | return -EINVAL; |
| 1958 | 1971 | fragshift = val & 0xffff; |
| 1959 | − if (fragshift >= 31) | |
| 1972 | + if (fragshift >= 25) /* should be large enough */ | |
| 1960 | 1973 | return -EINVAL; |
| 1961 | 1974 | runtime->oss.fragshift = fragshift; |
| 1962 | 1975 | runtime->oss.maxfrags = (val >> 16) & 0xffff; |
| @@ -252,6 +252,11 @@ static const struct config_entry config_table[] = { · 251 unmodified lines | ||
| 252 | 252 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 253 | 253 | .device = 0x02c8, |
| 254 | 254 | }, |
| 255 | + { | |
| 256 | + .flags = FLAG_SOF, | |
| 257 | + .device = 0x02c8, | |
| 258 | + .codec_hid = "ESSX8336", | |
| 259 | + }, | |
| 255 | 260 | /* Cometlake-H */ |
| 256 | 261 | { |
| 257 | 262 | .flags = FLAG_SOF, |
| @@ -276,6 +281,11 @@ static const struct config_entry config_table[] = { · 18 unmodified lines | ||
| 276 | 281 | .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, |
| 277 | 282 | .device = 0x06c8, |
| 278 | 283 | }, |
| 284 | + { | |
| 285 | + .flags = FLAG_SOF, | |
| 286 | + .device = 0x06c8, | |
| 287 | + .codec_hid = "ESSX8336", | |
| 288 | + }, | |
| 279 | 289 | #endif |
| 280 | 290 | |
| 281 | 291 | /* Icelake */ |
| @@ -335,7 +335,10 @@ enum { · 334 unmodified lines | ||
| 335 | 335 | ((pci)->device == 0x0c0c) || \ |
| 336 | 336 | ((pci)->device == 0x0d0c) || \ |
| 337 | 337 | ((pci)->device == 0x160c) || \ |
| 338 | − ((pci)->device == 0x490d)) | |
| 338 | + ((pci)->device == 0x490d) || \ | |
| 339 | + ((pci)->device == 0x4f90) || \ | |
| 340 | + ((pci)->device == 0x4f91) || \ | |
| 341 | + ((pci)->device == 0x4f92)) | |
| 339 | 342 | |
| 340 | 343 | #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) |
| 341 | 344 | |
| @@ -2473,6 +2476,13 @@ static const struct pci_device_id azx_ids[] = { · 2131 unmodified lines | ||
| 2473 | 2476 | /* DG1 */ |
| 2474 | 2477 | { PCI_DEVICE(0x8086, 0x490d), |
| 2475 | 2478 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
| 2479 | + /* DG2 */ | |
| 2480 | + { PCI_DEVICE(0x8086, 0x4f90), | |
| 2481 | + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2482 | + { PCI_DEVICE(0x8086, 0x4f91), | |
| 2483 | + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2484 | + { PCI_DEVICE(0x8086, 0x4f92), | |
| 2485 | + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, | |
| 2476 | 2486 | /* Alderlake-S */ |
| 2477 | 2487 | { PCI_DEVICE(0x8086, 0x7ad0), |
| 2478 | 2488 | .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, |
| @@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid, · 437 unmodified lines | ||
| 438 | 438 | #define for_each_hda_codec_node(nid, codec) \ |
| 439 | 439 | for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) |
| 440 | 440 | |
| 441 | +/* Set the codec power_state flag to indicate to allow unsol event handling; | |
| 442 | + * see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the | |
| 443 | + * state tracking, so use with care. | |
| 444 | + */ | |
| 445 | +static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec) | |
| 446 | +{ | |
| 447 | + codec->core.dev.power.power_state = PMSG_ON; | |
| 448 | +} | |
| 449 | + | |
| 441 | 450 | /* |
| 442 | 451 | * get widget capabilities |
| 443 | 452 | */ |
| @@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42) · 749 unmodified lines | ||
| 750 | 750 | if (cs42l42->full_scale_vol) |
| 751 | 751 | cs8409_i2c_write(cs42l42, 0x2001, 0x01); |
| 752 | 752 | |
| 753 | + /* we have to explicitly allow unsol event handling even during the | |
| 754 | + * resume phase so that the jack event is processed properly | |
| 755 | + */ | |
| 756 | + snd_hda_codec_allow_unsol_events(cs42l42->codec); | |
| 757 | + | |
| 753 | 758 | cs42l42_enable_jack_detect(cs42l42); |
| 754 | 759 | } |
| 755 | 760 | |
| @@ -4380,10 +4380,11 @@ HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), · 4379 unmodified lines | ||
| 4380 | 4380 | HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), |
| 4381 | 4381 | HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI", patch_i915_tgl_hdmi), |
| 4382 | 4382 | HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI", patch_i915_tgl_hdmi), |
| 4383 | −HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi), | |
| 4384 | 4383 | HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi), |
| 4384 | +HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI", patch_i915_tgl_hdmi), | |
| 4385 | 4385 | HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi), |
| 4386 | 4386 | HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI", patch_i915_icl_hdmi), |
| 4387 | +HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_tgl_hdmi), | |
| 4387 | 4388 | HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), |
| 4388 | 4389 | HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), |
| 4389 | 4390 | HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), |
| @@ -6503,22 +6503,26 @@ static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec, · 6502 unmodified lines | ||
| 6503 | 6503 | /* for alc285_fixup_ideapad_s740_coef() */ |
| 6504 | 6504 | #include "ideapad_s740_helper.c" |
| 6505 | 6505 | |
| 6506 | −static void alc256_fixup_tongfang_reset_persistent_settings(struct hda_codec *codec, | |
| 6507 | − const struct hda_fixup *fix, | |
| 6508 | − int action) | |
| 6506 | +static const struct coef_fw alc256_fixup_set_coef_defaults_coefs[] = { | |
| 6507 | + WRITE_COEF(0x10, 0x0020), WRITE_COEF(0x24, 0x0000), | |
| 6508 | + WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x29, 0x3000), | |
| 6509 | + WRITE_COEF(0x37, 0xfe05), WRITE_COEF(0x45, 0x5089), | |
| 6510 | + {} | |
| 6511 | +}; | |
| 6512 | + | |
| 6513 | +static void alc256_fixup_set_coef_defaults(struct hda_codec *codec, | |
| 6514 | + const struct hda_fixup *fix, | |
| 6515 | + int action) | |
| 6509 | 6516 | { |
| 6510 | 6517 | /* |
| 6511 | − * A certain other OS sets these coeffs to different values. On at least one TongFang | |
| 6512 | − * barebone these settings might survive even a cold reboot. So to restore a clean slate the | |
| 6513 | − * values are explicitly reset to default here. Without this, the external microphone is | |
| 6514 | − * always in a plugged-in state, while the internal microphone is always in an unplugged | |
| 6515 | − * state, breaking the ability to use the internal microphone. | |
| 6516 | − */ | |
| 6517 | − alc_write_coef_idx(codec, 0x24, 0x0000); | |
| 6518 | − alc_write_coef_idx(codec, 0x26, 0x0000); | |
| 6519 | − alc_write_coef_idx(codec, 0x29, 0x3000); | |
| 6520 | − alc_write_coef_idx(codec, 0x37, 0xfe05); | |
| 6521 | − alc_write_coef_idx(codec, 0x45, 0x5089); | |
| 6518 | + * A certain other OS sets these coeffs to different values. On at least | |
| 6519 | + * one TongFang barebone these settings might survive even a cold | |
| 6520 | + * reboot. So to restore a clean slate the values are explicitly reset | |
| 6521 | + * to default here. Without this, the external microphone is always in a | |
| 6522 | + * plugged-in state, while the internal microphone is always in an | |
| 6523 | + * unplugged state, breaking the ability to use the internal microphone. | |
| 6524 | + */ | |
| 6525 | + alc_process_coef_fw(codec, alc256_fixup_set_coef_defaults_coefs); | |
| 6522 | 6526 | } |
| 6523 | 6527 | |
| 6524 | 6528 | static const struct coef_fw alc233_fixup_no_audio_jack_coefs[] = { |
| @@ -6759,7 +6763,7 @@ enum { · 234 unmodified lines | ||
| 6759 | 6763 | ALC287_FIXUP_LEGION_15IMHG05_AUTOMUTE, |
| 6760 | 6764 | ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, |
| 6761 | 6765 | ALC287_FIXUP_13S_GEN2_SPEAKERS, |
| 6762 | − ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS, | |
| 6766 | + ALC256_FIXUP_SET_COEF_DEFAULTS, | |
| 6763 | 6767 | ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, |
| 6764 | 6768 | ALC233_FIXUP_NO_AUDIO_JACK, |
| 6765 | 6769 | }; |
| @@ -8465,9 +8469,9 @@ static const struct hda_fixup alc269_fixups[] = { · 1699 unmodified lines | ||
| 8465 | 8469 | .chained = true, |
| 8466 | 8470 | .chain_id = ALC269_FIXUP_HEADSET_MODE, |
| 8467 | 8471 | }, |
| 8468 | − [ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS] = { | |
| 8472 | + [ALC256_FIXUP_SET_COEF_DEFAULTS] = { | |
| 8469 | 8473 | .type = HDA_FIXUP_FUNC, |
| 8470 | − .v.func = alc256_fixup_tongfang_reset_persistent_settings, | |
| 8474 | + .v.func = alc256_fixup_set_coef_defaults, | |
| 8471 | 8475 | }, |
| 8472 | 8476 | [ALC245_FIXUP_HP_GPIO_LED] = { |
| 8473 | 8477 | .type = HDA_FIXUP_FUNC, |
| @@ -8929,7 +8933,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 455 unmodified lines | ||
| 8929 | 8933 | SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ |
| 8930 | 8934 | SND_PCI_QUIRK(0x1c06, 0x2013, "Lemote A1802", ALC269_FIXUP_LEMOTE_A1802), |
| 8931 | 8935 | SND_PCI_QUIRK(0x1c06, 0x2015, "Lemote A190X", ALC269_FIXUP_LEMOTE_A190X), |
| 8932 | − SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_TONGFANG_RESET_PERSISTENT_SETTINGS), | |
| 8936 | + SND_PCI_QUIRK(0x1d05, 0x1132, "TongFang PHxTxX1", ALC256_FIXUP_SET_COEF_DEFAULTS), | |
| 8933 | 8937 | SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), |
| 8934 | 8938 | SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), |
| 8935 | 8939 | SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), |
| @@ -10231,6 +10235,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, · 1295 unmodified lines | ||
| 10231 | 10235 | } |
| 10232 | 10236 | } |
| 10233 | 10237 | |
| 10238 | +static void alc897_hp_automute_hook(struct hda_codec *codec, | |
| 10239 | + struct hda_jack_callback *jack) | |
| 10240 | +{ | |
| 10241 | + struct alc_spec *spec = codec->spec; | |
| 10242 | + int vref; | |
| 10243 | + | |
| 10244 | + snd_hda_gen_hp_automute(codec, jack); | |
| 10245 | + vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP; | |
| 10246 | + snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | |
| 10247 | + vref); | |
| 10248 | +} | |
| 10249 | + | |
| 10250 | +static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec, | |
| 10251 | + const struct hda_fixup *fix, int action) | |
| 10252 | +{ | |
| 10253 | + struct alc_spec *spec = codec->spec; | |
| 10254 | + if (action == HDA_FIXUP_ACT_PRE_PROBE) { | |
| 10255 | + spec->gen.hp_automute_hook = alc897_hp_automute_hook; | |
| 10256 | + } | |
| 10257 | +} | |
| 10258 | + | |
| 10234 | 10259 | static const struct coef_fw alc668_coefs[] = { |
| 10235 | 10260 | WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), |
| 10236 | 10261 | WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), |
| @@ -10311,6 +10336,8 @@ enum { · 74 unmodified lines | ||
| 10311 | 10336 | ALC668_FIXUP_ASUS_NO_HEADSET_MIC, |
| 10312 | 10337 | ALC668_FIXUP_HEADSET_MIC, |
| 10313 | 10338 | ALC668_FIXUP_MIC_DET_COEF, |
| 10339 | + ALC897_FIXUP_LENOVO_HEADSET_MIC, | |
| 10340 | + ALC897_FIXUP_HEADSET_MIC_PIN, | |
| 10314 | 10341 | }; |
| 10315 | 10342 | |
| 10316 | 10343 | static const struct hda_fixup alc662_fixups[] = { |
| @@ -10717,6 +10744,19 @@ static const struct hda_fixup alc662_fixups[] = { · 400 unmodified lines | ||
| 10717 | 10744 | {} |
| 10718 | 10745 | }, |
| 10719 | 10746 | }, |
| 10747 | + [ALC897_FIXUP_LENOVO_HEADSET_MIC] = { | |
| 10748 | + .type = HDA_FIXUP_FUNC, | |
| 10749 | + .v.func = alc897_fixup_lenovo_headset_mic, | |
| 10750 | + }, | |
| 10751 | + [ALC897_FIXUP_HEADSET_MIC_PIN] = { | |
| 10752 | + .type = HDA_FIXUP_PINS, | |
| 10753 | + .v.pins = (const struct hda_pintbl[]) { | |
| 10754 | + { 0x1a, 0x03a11050 }, | |
| 10755 | + { } | |
| 10756 | + }, | |
| 10757 | + .chained = true, | |
| 10758 | + .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC | |
| 10759 | + }, | |
| 10720 | 10760 | }; |
| 10721 | 10761 | |
| 10722 | 10762 | static const struct snd_pci_quirk alc662_fixup_tbl[] = { |
| @@ -10761,6 +10801,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { · 38 unmodified lines | ||
| 10761 | 10801 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), |
| 10762 | 10802 | SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), |
| 10763 | 10803 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), |
| 10804 | + SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN), | |
| 10805 | + SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), | |
| 10806 | + SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), | |
| 10807 | + SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), | |
| 10764 | 10808 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), |
| 10765 | 10809 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), |
| 10766 | 10810 | SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), |
| @@ -146,10 +146,11 @@ static int snd_acp6x_probe(struct pci_dev *pci, · 145 unmodified lines | ||
| 146 | 146 | { |
| 147 | 147 | struct acp6x_dev_data *adata; |
| 148 | 148 | struct platform_device_info pdevinfo[ACP6x_DEVS]; |
| 149 | − int ret, index; | |
| 149 | + int index = 0; | |
| 150 | 150 | int val = 0x00; |
| 151 | 151 | u32 addr; |
| 152 | 152 | unsigned int irqflags; |
| 153 | + int ret; | |
| 153 | 154 | |
| 154 | 155 | irqflags = IRQF_SHARED; |
| 155 | 156 | /* Yellow Carp device check */ |
| @@ -42,34 +42,6 @@ static const struct spi_device_id cs35l41_id_spi[] = { · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | MODULE_DEVICE_TABLE(spi, cs35l41_id_spi); |
| 44 | 44 | |
| 45 | −static void cs35l41_spi_otp_setup(struct cs35l41_private *cs35l41, | |
| 46 | − bool is_pre_setup, unsigned int *freq) | |
| 47 | −{ | |
| 48 | − struct spi_device *spi; | |
| 49 | − u32 orig_spi_freq; | |
| 50 | − | |
| 51 | − spi = to_spi_device(cs35l41->dev); | |
| 52 | − | |
| 53 | − if (!spi) { | |
| 54 | − dev_err(cs35l41->dev, "%s: No SPI device\n", __func__); | |
| 55 | − return; | |
| 56 | − } | |
| 57 | − | |
| 58 | − if (is_pre_setup) { | |
| 59 | − orig_spi_freq = spi->max_speed_hz; | |
| 60 | − if (orig_spi_freq > CS35L41_SPI_MAX_FREQ_OTP) { | |
| 61 | − spi->max_speed_hz = CS35L41_SPI_MAX_FREQ_OTP; | |
| 62 | − spi_setup(spi); | |
| 63 | − } | |
| 64 | − *freq = orig_spi_freq; | |
| 65 | − } else { | |
| 66 | − if (spi->max_speed_hz != *freq) { | |
| 67 | − spi->max_speed_hz = *freq; | |
| 68 | − spi_setup(spi); | |
| 69 | − } | |
| 70 | − } | |
| 71 | −} | |
| 72 | − | |
| 73 | 45 | static int cs35l41_spi_probe(struct spi_device *spi) |
| 74 | 46 | { |
| 75 | 47 | const struct regmap_config *regmap_config = &cs35l41_regmap_spi; |
| @@ -81,6 +53,9 @@ static int cs35l41_spi_probe(struct spi_device *spi) · 5 unmodified lines | ||
| 81 | 53 | if (!cs35l41) |
| 82 | 54 | return -ENOMEM; |
| 83 | 55 | |
| 56 | + spi->max_speed_hz = CS35L41_SPI_MAX_FREQ; | |
| 57 | + spi_setup(spi); | |
| 58 | + | |
| 84 | 59 | spi_set_drvdata(spi, cs35l41); |
| 85 | 60 | cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config); |
| 86 | 61 | if (IS_ERR(cs35l41->regmap)) { |
| @@ -91,7 +66,6 @@ static int cs35l41_spi_probe(struct spi_device *spi) · 4 unmodified lines | ||
| 91 | 66 | |
| 92 | 67 | cs35l41->dev = &spi->dev; |
| 93 | 68 | cs35l41->irq = spi->irq; |
| 94 | − cs35l41->otp_setup = cs35l41_spi_otp_setup; | |
| 95 | 69 | |
| 96 | 70 | return cs35l41_probe(cs35l41, pdata); |
| 97 | 71 | } |
| @@ -302,7 +302,6 @@ static int cs35l41_otp_unpack(void *data) · 301 unmodified lines | ||
| 302 | 302 | const struct cs35l41_otp_packed_element_t *otp_map; |
| 303 | 303 | struct cs35l41_private *cs35l41 = data; |
| 304 | 304 | int bit_offset, word_offset, ret, i; |
| 305 | − unsigned int orig_spi_freq; | |
| 306 | 305 | unsigned int bit_sum = 8; |
| 307 | 306 | u32 otp_val, otp_id_reg; |
| 308 | 307 | u32 *otp_mem; |
| @@ -326,9 +325,6 @@ static int cs35l41_otp_unpack(void *data) · 17 unmodified lines | ||
| 326 | 325 | goto err_otp_unpack; |
| 327 | 326 | } |
| 328 | 327 | |
| 329 | − if (cs35l41->otp_setup) | |
| 330 | − cs35l41->otp_setup(cs35l41, true, &orig_spi_freq); | |
| 331 | − | |
| 332 | 328 | ret = regmap_bulk_read(cs35l41->regmap, CS35L41_OTP_MEM0, otp_mem, |
| 333 | 329 | CS35L41_OTP_SIZE_WORDS); |
| 334 | 330 | if (ret < 0) { |
| @@ -336,9 +332,6 @@ static int cs35l41_otp_unpack(void *data) · 1 unmodified line | ||
| 336 | 332 | goto err_otp_unpack; |
| 337 | 333 | } |
| 338 | 334 | |
| 339 | − if (cs35l41->otp_setup) | |
| 340 | − cs35l41->otp_setup(cs35l41, false, &orig_spi_freq); | |
| 341 | − | |
| 342 | 335 | otp_map = otp_map_match->map; |
| 343 | 336 | |
| 344 | 337 | bit_offset = otp_map_match->bit_offset; |
| @@ -726,7 +726,7 @@ · 725 unmodified lines | ||
| 726 | 726 | #define CS35L41_FS2_WINDOW_MASK 0x00FFF800 |
| 727 | 727 | #define CS35L41_FS2_WINDOW_SHIFT 12 |
| 728 | 728 | |
| 729 | −#define CS35L41_SPI_MAX_FREQ_OTP 4000000 | |
| 729 | +#define CS35L41_SPI_MAX_FREQ 4000000 | |
| 730 | 730 | |
| 731 | 731 | #define CS35L41_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
| 732 | 732 | #define CS35L41_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) |
| @@ -764,8 +764,6 @@ struct cs35l41_private { · 31 unmodified lines | ||
| 764 | 764 | int irq; |
| 765 | 765 | /* GPIO for /RST */ |
| 766 | 766 | struct gpio_desc *reset_gpio; |
| 767 | − void (*otp_setup)(struct cs35l41_private *cs35l41, bool is_pre_setup, | |
| 768 | − unsigned int *freq); | |
| 769 | 767 | }; |
| 770 | 768 | |
| 771 | 769 | int cs35l41_probe(struct cs35l41_private *cs35l41, |
| @@ -539,3 +539,4 @@ module_platform_driver(rk817_codec_driver); · 538 unmodified lines | ||
| 539 | 539 | MODULE_DESCRIPTION("ASoC RK817 codec driver"); |
| 540 | 540 | MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>"); |
| 541 | 541 | MODULE_LICENSE("GPL v2"); |
| 542 | +MODULE_ALIAS("platform:rk817-codec"); | |
| @@ -2858,6 +2858,8 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682) · 2857 unmodified lines | ||
| 2858 | 2858 | |
| 2859 | 2859 | for (i = 0; i < RT5682_DAI_NUM_CLKS; ++i) { |
| 2860 | 2860 | struct clk_init_data init = { }; |
| 2861 | + struct clk_parent_data parent_data; | |
| 2862 | + const struct clk_hw *parent; | |
| 2861 | 2863 | |
| 2862 | 2864 | dai_clk_hw = &rt5682->dai_clks_hw[i]; |
| 2863 | 2865 | |
| @@ -2865,17 +2867,17 @@ int rt5682_register_dai_clks(struct rt5682_priv *rt5682) · 1 unmodified line | ||
| 2865 | 2867 | case RT5682_DAI_WCLK_IDX: |
| 2866 | 2868 | /* Make MCLK the parent of WCLK */ |
| 2867 | 2869 | if (rt5682->mclk) { |
| 2868 | − init.parent_data = &(struct clk_parent_data){ | |
| 2870 | + parent_data = (struct clk_parent_data){ | |
| 2869 | 2871 | .fw_name = "mclk", |
| 2870 | 2872 | }; |
| 2873 | + init.parent_data = &parent_data; | |
| 2871 | 2874 | init.num_parents = 1; |
| 2872 | 2875 | } |
| 2873 | 2876 | break; |
| 2874 | 2877 | case RT5682_DAI_BCLK_IDX: |
| 2875 | 2878 | /* Make WCLK the parent of BCLK */ |
| 2876 | − init.parent_hws = &(const struct clk_hw *){ | |
| 2877 | − &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX] | |
| 2878 | − }; | |
| 2879 | + parent = &rt5682->dai_clks_hw[RT5682_DAI_WCLK_IDX]; | |
| 2880 | + init.parent_hws = &parent; | |
| 2879 | 2881 | init.num_parents = 1; |
| 2880 | 2882 | break; |
| 2881 | 2883 | default: |
| @@ -2693,6 +2693,8 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component) · 2692 unmodified lines | ||
| 2693 | 2693 | |
| 2694 | 2694 | for (i = 0; i < RT5682S_DAI_NUM_CLKS; ++i) { |
| 2695 | 2695 | struct clk_init_data init = { }; |
| 2696 | + struct clk_parent_data parent_data; | |
| 2697 | + const struct clk_hw *parent; | |
| 2696 | 2698 | |
| 2697 | 2699 | dai_clk_hw = &rt5682s->dai_clks_hw[i]; |
| 2698 | 2700 | |
| @@ -2700,17 +2702,17 @@ static int rt5682s_register_dai_clks(struct snd_soc_component *component) · 1 unmodified line | ||
| 2700 | 2702 | case RT5682S_DAI_WCLK_IDX: |
| 2701 | 2703 | /* Make MCLK the parent of WCLK */ |
| 2702 | 2704 | if (rt5682s->mclk) { |
| 2703 | − init.parent_data = &(struct clk_parent_data){ | |
| 2705 | + parent_data = (struct clk_parent_data){ | |
| 2704 | 2706 | .fw_name = "mclk", |
| 2705 | 2707 | }; |
| 2708 | + init.parent_data = &parent_data; | |
| 2706 | 2709 | init.num_parents = 1; |
| 2707 | 2710 | } |
| 2708 | 2711 | break; |
| 2709 | 2712 | case RT5682S_DAI_BCLK_IDX: |
| 2710 | 2713 | /* Make WCLK the parent of BCLK */ |
| 2711 | − init.parent_hws = &(const struct clk_hw *){ | |
| 2712 | − &rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX] | |
| 2713 | − }; | |
| 2714 | + parent = &rt5682s->dai_clks_hw[RT5682S_DAI_WCLK_IDX]; | |
| 2715 | + init.parent_hws = &parent; | |
| 2714 | 2716 | init.num_parents = 1; |
| 2715 | 2717 | break; |
| 2716 | 2718 | default: |
| @@ -3256,6 +3256,9 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, · 3255 unmodified lines | ||
| 3256 | 3256 | int value = ucontrol->value.integer.value[0]; |
| 3257 | 3257 | int sel; |
| 3258 | 3258 | |
| 3259 | + if (wcd->comp_enabled[comp] == value) | |
| 3260 | + return 0; | |
| 3261 | + | |
| 3259 | 3262 | wcd->comp_enabled[comp] = value; |
| 3260 | 3263 | sel = value ? WCD934X_HPH_GAIN_SRC_SEL_COMPANDER : |
| 3261 | 3264 | WCD934X_HPH_GAIN_SRC_SEL_REGISTER; |
| @@ -3279,10 +3282,10 @@ static int wcd934x_compander_set(struct snd_kcontrol *kc, · 17 unmodified lines | ||
| 3279 | 3282 | case COMPANDER_8: |
| 3280 | 3283 | break; |
| 3281 | 3284 | default: |
| 3282 | − break; | |
| 3285 | + return 0; | |
| 3283 | 3286 | } |
| 3284 | 3287 | |
| 3285 | − return 0; | |
| 3288 | + return 1; | |
| 3286 | 3289 | } |
| 3287 | 3290 | |
| 3288 | 3291 | static int wcd934x_rx_hph_mode_get(struct snd_kcontrol *kc, |
| @@ -3326,6 +3329,31 @@ static int slim_rx_mux_get(struct snd_kcontrol *kc, · 37 unmodified lines | ||
| 3326 | 3329 | return 0; |
| 3327 | 3330 | } |
| 3328 | 3331 | |
| 3332 | +static int slim_rx_mux_to_dai_id(int mux) | |
| 3333 | +{ | |
| 3334 | + int aif_id; | |
| 3335 | + | |
| 3336 | + switch (mux) { | |
| 3337 | + case 1: | |
| 3338 | + aif_id = AIF1_PB; | |
| 3339 | + break; | |
| 3340 | + case 2: | |
| 3341 | + aif_id = AIF2_PB; | |
| 3342 | + break; | |
| 3343 | + case 3: | |
| 3344 | + aif_id = AIF3_PB; | |
| 3345 | + break; | |
| 3346 | + case 4: | |
| 3347 | + aif_id = AIF4_PB; | |
| 3348 | + break; | |
| 3349 | + default: | |
| 3350 | + aif_id = -1; | |
| 3351 | + break; | |
| 3352 | + } | |
| 3353 | + | |
| 3354 | + return aif_id; | |
| 3355 | +} | |
| 3356 | + | |
| 3329 | 3357 | static int slim_rx_mux_put(struct snd_kcontrol *kc, |
| 3330 | 3358 | struct snd_ctl_elem_value *ucontrol) |
| 3331 | 3359 | { |
| @@ -3333,43 +3361,59 @@ static int slim_rx_mux_put(struct snd_kcontrol *kc, · 1 unmodified line | ||
| 3333 | 3361 | struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev); |
| 3334 | 3362 | struct soc_enum *e = (struct soc_enum *)kc->private_value; |
| 3335 | 3363 | struct snd_soc_dapm_update *update = NULL; |
| 3364 | + struct wcd934x_slim_ch *ch, *c; | |
| 3336 | 3365 | u32 port_id = w->shift; |
| 3366 | + bool found = false; | |
| 3367 | + int mux_idx; | |
| 3368 | + int prev_mux_idx = wcd->rx_port_value[port_id]; | |
| 3369 | + int aif_id; | |
| 3337 | 3370 | |
| 3338 | − if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0]) | |
| 3339 | − return 0; | |
| 3371 | + mux_idx = ucontrol->value.enumerated.item[0]; | |
| 3340 | 3372 | |
| 3341 | − wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0]; | |
| 3373 | + if (mux_idx == prev_mux_idx) | |
| 3374 | + return 0; | |
| 3342 | 3375 | |
| 3343 | − switch (wcd->rx_port_value[port_id]) { | |
| 3376 | + switch(mux_idx) { | |
| 3344 | 3377 | case 0: |
| 3345 | − list_del_init(&wcd->rx_chs[port_id].list); | |
| 3346 | − break; | |
| 3347 | − case 1: | |
| 3348 | − list_add_tail(&wcd->rx_chs[port_id].list, | |
| 3349 | − &wcd->dai[AIF1_PB].slim_ch_list); | |
| 3350 | − break; | |
| 3351 | − case 2: | |
| 3352 | − list_add_tail(&wcd->rx_chs[port_id].list, | |
| 3353 | − &wcd->dai[AIF2_PB].slim_ch_list); | |
| 3354 | − break; | |
| 3355 | − case 3: | |
| 3356 | − list_add_tail(&wcd->rx_chs[port_id].list, | |
| 3357 | − &wcd->dai[AIF3_PB].slim_ch_list); | |
| 3378 | + aif_id = slim_rx_mux_to_dai_id(prev_mux_idx); | |
| 3379 | + if (aif_id < 0) | |
| 3380 | + return 0; | |
| 3381 | + | |
| 3382 | + list_for_each_entry_safe(ch, c, &wcd->dai[aif_id].slim_ch_list, list) { | |
| 3383 | + if (ch->port == port_id + WCD934X_RX_START) { | |
| 3384 | + found = true; | |
| 3385 | + list_del_init(&ch->list); | |
| 3386 | + break; | |
| 3387 | + } | |
| 3388 | + } | |
| 3389 | + if (!found) | |
| 3390 | + return 0; | |
| 3391 | + | |
| 3358 | 3392 | break; |
| 3359 | − case 4: | |
| 3360 | − list_add_tail(&wcd->rx_chs[port_id].list, | |
| 3361 | − &wcd->dai[AIF4_PB].slim_ch_list); | |
| 3393 | + case 1 ... 4: | |
| 3394 | + aif_id = slim_rx_mux_to_dai_id(mux_idx); | |
| 3395 | + if (aif_id < 0) | |
| 3396 | + return 0; | |
| 3397 | + | |
| 3398 | + if (list_empty(&wcd->rx_chs[port_id].list)) { | |
| 3399 | + list_add_tail(&wcd->rx_chs[port_id].list, | |
| 3400 | + &wcd->dai[aif_id].slim_ch_list); | |
| 3401 | + } else { | |
| 3402 | + dev_err(wcd->dev ,"SLIM_RX%d PORT is busy\n", port_id); | |
| 3403 | + return 0; | |
| 3404 | + } | |
| 3362 | 3405 | break; |
| 3406 | + | |
| 3363 | 3407 | default: |
| 3364 | − dev_err(wcd->dev, "Unknown AIF %d\n", | |
| 3365 | − wcd->rx_port_value[port_id]); | |
| 3408 | + dev_err(wcd->dev, "Unknown AIF %d\n", mux_idx); | |
| 3366 | 3409 | goto err; |
| 3367 | 3410 | } |
| 3368 | 3411 | |
| 3412 | + wcd->rx_port_value[port_id] = mux_idx; | |
| 3369 | 3413 | snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id], |
| 3370 | 3414 | e, update); |
| 3371 | 3415 | |
| 3372 | − return 0; | |
| 3416 | + return 1; | |
| 3373 | 3417 | err: |
| 3374 | 3418 | return -EINVAL; |
| 3375 | 3419 | } |
| @@ -3815,6 +3859,7 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, · 439 unmodified lines | ||
| 3815 | 3859 | struct soc_mixer_control *mixer = |
| 3816 | 3860 | (struct soc_mixer_control *)kc->private_value; |
| 3817 | 3861 | int enable = ucontrol->value.integer.value[0]; |
| 3862 | + struct wcd934x_slim_ch *ch, *c; | |
| 3818 | 3863 | int dai_id = widget->shift; |
| 3819 | 3864 | int port_id = mixer->shift; |
| 3820 | 3865 | |
| @@ -3822,17 +3867,32 @@ static int slim_tx_mixer_put(struct snd_kcontrol *kc, · 1 unmodified line | ||
| 3822 | 3867 | if (enable == wcd->tx_port_value[port_id]) |
| 3823 | 3868 | return 0; |
| 3824 | 3869 | |
| 3825 | − wcd->tx_port_value[port_id] = enable; | |
| 3826 | − | |
| 3827 | − if (enable) | |
| 3828 | − list_add_tail(&wcd->tx_chs[port_id].list, | |
| 3829 | − &wcd->dai[dai_id].slim_ch_list); | |
| 3830 | − else | |
| 3831 | − list_del_init(&wcd->tx_chs[port_id].list); | |
| 3870 | + if (enable) { | |
| 3871 | + if (list_empty(&wcd->tx_chs[port_id].list)) { | |
| 3872 | + list_add_tail(&wcd->tx_chs[port_id].list, | |
| 3873 | + &wcd->dai[dai_id].slim_ch_list); | |
| 3874 | + } else { | |
| 3875 | + dev_err(wcd->dev ,"SLIM_TX%d PORT is busy\n", port_id); | |
| 3876 | + return 0; | |
| 3877 | + } | |
| 3878 | + } else { | |
| 3879 | + bool found = false; | |
| 3880 | + | |
| 3881 | + list_for_each_entry_safe(ch, c, &wcd->dai[dai_id].slim_ch_list, list) { | |
| 3882 | + if (ch->port == port_id) { | |
| 3883 | + found = true; | |
| 3884 | + list_del_init(&wcd->tx_chs[port_id].list); | |
| 3885 | + break; | |
| 3886 | + } | |
| 3887 | + } | |
| 3888 | + if (!found) | |
| 3889 | + return 0; | |
| 3890 | + } | |
| 3832 | 3891 | |
| 3892 | + wcd->tx_port_value[port_id] = enable; | |
| 3833 | 3893 | snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update); |
| 3834 | 3894 | |
| 3835 | − return 0; | |
| 3895 | + return 1; | |
| 3836 | 3896 | } |
| 3837 | 3897 | |
| 3838 | 3898 | static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = { |
| @@ -772,7 +772,8 @@ static int wsa881x_put_pa_gain(struct snd_kcontrol *kc, · 771 unmodified lines | ||
| 772 | 772 | |
| 773 | 773 | usleep_range(1000, 1010); |
| 774 | 774 | } |
| 775 | − return 0; | |
| 775 | + | |
| 776 | + return 1; | |
| 776 | 777 | } |
| 777 | 778 | |
| 778 | 779 | static int wsa881x_get_port(struct snd_kcontrol *kcontrol, |
| @@ -816,15 +817,22 @@ static int wsa881x_set_port(struct snd_kcontrol *kcontrol, · 37 unmodified lines | ||
| 816 | 817 | (struct soc_mixer_control *)kcontrol->private_value; |
| 817 | 818 | int portidx = mixer->reg; |
| 818 | 819 | |
| 819 | − if (ucontrol->value.integer.value[0]) | |
| 820 | + if (ucontrol->value.integer.value[0]) { | |
| 821 | + if (data->port_enable[portidx]) | |
| 822 | + return 0; | |
| 823 | + | |
| 820 | 824 | data->port_enable[portidx] = true; |
| 821 | − else | |
| 825 | + } else { | |
| 826 | + if (!data->port_enable[portidx]) | |
| 827 | + return 0; | |
| 828 | + | |
| 822 | 829 | data->port_enable[portidx] = false; |
| 830 | + } | |
| 823 | 831 | |
| 824 | 832 | if (portidx == WSA881X_PORT_BOOST) /* Boost Switch */ |
| 825 | 833 | wsa881x_boost_ctrl(comp, data->port_enable[portidx]); |
| 826 | 834 | |
| 827 | − return 0; | |
| 835 | + return 1; | |
| 828 | 836 | } |
| 829 | 837 | |
| 830 | 838 | static const char * const smart_boost_lvl_text[] = { |
| @@ -81,6 +81,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { · 80 unmodified lines | ||
| 81 | 81 | .sof_fw_filename = "sof-cml.ri", |
| 82 | 82 | .sof_tplg_filename = "sof-cml-da7219-max98390.tplg", |
| 83 | 83 | }, |
| 84 | + { | |
| 85 | + .id = "ESSX8336", | |
| 86 | + .drv_name = "sof-essx8336", | |
| 87 | + .sof_fw_filename = "sof-cml.ri", | |
| 88 | + .sof_tplg_filename = "sof-cml-es8336.tplg", | |
| 89 | + }, | |
| 84 | 90 | {}, |
| 85 | 91 | }; |
| 86 | 92 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_cml_machines); |
| @@ -498,14 +498,16 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, · 497 unmodified lines | ||
| 498 | 498 | struct session_data *session = &data->sessions[session_id]; |
| 499 | 499 | |
| 500 | 500 | if (ucontrol->value.integer.value[0]) { |
| 501 | + if (session->port_id == be_id) | |
| 502 | + return 0; | |
| 503 | + | |
| 501 | 504 | session->port_id = be_id; |
| 502 | 505 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, 1, update); |
| 503 | 506 | } else { |
| 504 | − if (session->port_id == be_id) { | |
| 505 | − session->port_id = -1; | |
| 507 | + if (session->port_id == -1 || session->port_id != be_id) | |
| 506 | 508 | return 0; |
| 507 | − } | |
| 508 | 509 | |
| 510 | + session->port_id = -1; | |
| 509 | 511 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, 0, update); |
| 510 | 512 | } |
| 511 | 513 | |
| @@ -95,6 +95,7 @@ struct rk_i2s_tdm_dev { · 94 unmodified lines | ||
| 95 | 95 | spinlock_t lock; /* xfer lock */ |
| 96 | 96 | bool has_playback; |
| 97 | 97 | bool has_capture; |
| 98 | + struct snd_soc_dai_driver *dai; | |
| 98 | 99 | }; |
| 99 | 100 | |
| 100 | 101 | static int to_ch_num(unsigned int val) |
| @@ -1310,19 +1311,14 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = { · 1209 unmodified lines | ||
| 1310 | 1311 | {}, |
| 1311 | 1312 | }; |
| 1312 | 1313 | |
| 1313 | −static struct snd_soc_dai_driver i2s_tdm_dai = { | |
| 1314 | +static const struct snd_soc_dai_driver i2s_tdm_dai = { | |
| 1314 | 1315 | .probe = rockchip_i2s_tdm_dai_probe, |
| 1315 | − .playback = { | |
| 1316 | − .stream_name = "Playback", | |
| 1317 | − }, | |
| 1318 | − .capture = { | |
| 1319 | − .stream_name = "Capture", | |
| 1320 | − }, | |
| 1321 | 1316 | .ops = &rockchip_i2s_tdm_dai_ops, |
| 1322 | 1317 | }; |
| 1323 | 1318 | |
| 1324 | −static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) | |
| 1319 | +static int rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) | |
| 1325 | 1320 | { |
| 1321 | + struct snd_soc_dai_driver *dai; | |
| 1326 | 1322 | struct property *dma_names; |
| 1327 | 1323 | const char *dma_name; |
| 1328 | 1324 | u64 formats = (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | |
| @@ -1337,19 +1333,33 @@ static void rockchip_i2s_tdm_init_dai(struct rk_i2s_tdm_dev *i2s_tdm) · 8 unmodified lines | ||
| 1337 | 1333 | i2s_tdm->has_capture = true; |
| 1338 | 1334 | } |
| 1339 | 1335 | |
| 1336 | + dai = devm_kmemdup(i2s_tdm->dev, &i2s_tdm_dai, | |
| 1337 | + sizeof(*dai), GFP_KERNEL); | |
| 1338 | + if (!dai) | |
| 1339 | + return -ENOMEM; | |
| 1340 | + | |
| 1340 | 1341 | if (i2s_tdm->has_playback) { |
| 1341 | − i2s_tdm_dai.playback.channels_min = 2; | |
| 1342 | − i2s_tdm_dai.playback.channels_max = 8; | |
| 1343 | − i2s_tdm_dai.playback.rates = SNDRV_PCM_RATE_8000_192000; | |
| 1344 | − i2s_tdm_dai.playback.formats = formats; | |
| 1342 | + dai->playback.stream_name = "Playback"; | |
| 1343 | + dai->playback.channels_min = 2; | |
| 1344 | + dai->playback.channels_max = 8; | |
| 1345 | + dai->playback.rates = SNDRV_PCM_RATE_8000_192000; | |
| 1346 | + dai->playback.formats = formats; | |
| 1345 | 1347 | } |
| 1346 | 1348 | |
| 1347 | 1349 | if (i2s_tdm->has_capture) { |
| 1348 | − i2s_tdm_dai.capture.channels_min = 2; | |
| 1349 | − i2s_tdm_dai.capture.channels_max = 8; | |
| 1350 | − i2s_tdm_dai.capture.rates = SNDRV_PCM_RATE_8000_192000; | |
| 1351 | − i2s_tdm_dai.capture.formats = formats; | |
| 1350 | + dai->capture.stream_name = "Capture"; | |
| 1351 | + dai->capture.channels_min = 2; | |
| 1352 | + dai->capture.channels_max = 8; | |
| 1353 | + dai->capture.rates = SNDRV_PCM_RATE_8000_192000; | |
| 1354 | + dai->capture.formats = formats; | |
| 1352 | 1355 | } |
| 1356 | + | |
| 1357 | + if (i2s_tdm->clk_trcm != TRCM_TXRX) | |
| 1358 | + dai->symmetric_rate = 1; | |
| 1359 | + | |
| 1360 | + i2s_tdm->dai = dai; | |
| 1361 | + | |
| 1362 | + return 0; | |
| 1353 | 1363 | } |
| 1354 | 1364 | |
| 1355 | 1365 | static int rockchip_i2s_tdm_path_check(struct rk_i2s_tdm_dev *i2s_tdm, |
| @@ -1541,8 +1551,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) · 185 unmodified lines | ||
| 1541 | 1551 | spin_lock_init(&i2s_tdm->lock); |
| 1542 | 1552 | i2s_tdm->soc_data = (struct rk_i2s_soc_data *)of_id->data; |
| 1543 | 1553 | |
| 1544 | − rockchip_i2s_tdm_init_dai(i2s_tdm); | |
| 1545 | − | |
| 1546 | 1554 | i2s_tdm->frame_width = 64; |
| 1547 | 1555 | |
| 1548 | 1556 | i2s_tdm->clk_trcm = TRCM_TXRX; |
| @@ -1555,8 +1563,10 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) · 6 unmodified lines | ||
| 1555 | 1563 | } |
| 1556 | 1564 | i2s_tdm->clk_trcm = TRCM_RX; |
| 1557 | 1565 | } |
| 1558 | − if (i2s_tdm->clk_trcm != TRCM_TXRX) | |
| 1559 | − i2s_tdm_dai.symmetric_rate = 1; | |
| 1566 | + | |
| 1567 | + ret = rockchip_i2s_tdm_init_dai(i2s_tdm); | |
| 1568 | + if (ret) | |
| 1569 | + return ret; | |
| 1560 | 1570 | |
| 1561 | 1571 | i2s_tdm->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); |
| 1562 | 1572 | if (IS_ERR(i2s_tdm->grf)) |
| @@ -1678,7 +1688,7 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev) · 115 unmodified lines | ||
| 1678 | 1688 | |
| 1679 | 1689 | ret = devm_snd_soc_register_component(&pdev->dev, |
| 1680 | 1690 | &rockchip_i2s_tdm_component, |
| 1681 | − &i2s_tdm_dai, 1); | |
| 1691 | + i2s_tdm->dai, 1); | |
| 1682 | 1692 | |
| 1683 | 1693 | if (ret) { |
| 1684 | 1694 | dev_err(&pdev->dev, "Could not register DAI\n"); |
| @@ -20,8 +20,10 @@ static bool snd_soc_acpi_id_present(struct snd_soc_acpi_mach *machine) · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | if (comp_ids) { |
| 22 | 22 | for (i = 0; i < comp_ids->num_codecs; i++) { |
| 23 | − if (acpi_dev_present(comp_ids->codecs[i], NULL, -1)) | |
| 23 | + if (acpi_dev_present(comp_ids->codecs[i], NULL, -1)) { | |
| 24 | + strscpy(machine->id, comp_ids->codecs[i], ACPI_ID_LEN); | |
| 24 | 25 | return true; |
| 26 | + } | |
| 25 | 27 | } |
| 26 | 28 | } |
| 27 | 29 | |
| @@ -22,6 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) |
| 24 | 24 | #define IDISP_VID_INTEL 0x80860000 |
| 25 | +#define CODEC_PROBE_RETRIES 3 | |
| 25 | 26 | |
| 26 | 27 | /* load the legacy HDA codec driver */ |
| 27 | 28 | static int request_codec_module(struct hda_codec *codec) |
| @@ -121,12 +122,15 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, · 93 unmodified lines | ||
| 121 | 122 | u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | |
| 122 | 123 | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; |
| 123 | 124 | u32 resp = -1; |
| 124 | − int ret; | |
| 125 | + int ret, retry = 0; | |
| 126 | + | |
| 127 | + do { | |
| 128 | + mutex_lock(&hbus->core.cmd_mutex); | |
| 129 | + snd_hdac_bus_send_cmd(&hbus->core, hda_cmd); | |
| 130 | + snd_hdac_bus_get_response(&hbus->core, address, &resp); | |
| 131 | + mutex_unlock(&hbus->core.cmd_mutex); | |
| 132 | + } while (resp == -1 && retry++ < CODEC_PROBE_RETRIES); | |
| 125 | 133 | |
| 126 | − mutex_lock(&hbus->core.cmd_mutex); | |
| 127 | − snd_hdac_bus_send_cmd(&hbus->core, hda_cmd); | |
| 128 | − snd_hdac_bus_get_response(&hbus->core, address, &resp); | |
| 129 | − mutex_unlock(&hbus->core.cmd_mutex); | |
| 130 | 134 | if (resp == -1) |
| 131 | 135 | return -EIO; |
| 132 | 136 | dev_dbg(sdev->dev, "HDA codec #%d probed OK: response: %x\n", |
| @@ -58,6 +58,13 @@ int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w) · 57 unmodified lines | ||
| 58 | 58 | return -EINVAL; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | + /* DAI already configured, reset it before reconfiguring it */ | |
| 62 | + if (sof_dai->configured) { | |
| 63 | + ret = hda_ctrl_dai_widget_free(w); | |
| 64 | + if (ret < 0) | |
| 65 | + return ret; | |
| 66 | + } | |
| 67 | + | |
| 61 | 68 | config = &sof_dai->dai_config[sof_dai->current_config]; |
| 62 | 69 | |
| 63 | 70 | /* |
| @@ -26,51 +26,162 @@ static const struct reg_default tegra186_dspk_reg_defaults[] = { · 25 unmodified lines | ||
| 26 | 26 | { TEGRA186_DSPK_CODEC_CTRL, 0x03000000 }, |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | −static int tegra186_dspk_get_control(struct snd_kcontrol *kcontrol, | |
| 29 | +static int tegra186_dspk_get_fifo_th(struct snd_kcontrol *kcontrol, | |
| 30 | 30 | struct snd_ctl_elem_value *ucontrol) |
| 31 | 31 | { |
| 32 | 32 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
| 33 | 33 | struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); |
| 34 | 34 | |
| 35 | − if (strstr(kcontrol->id.name, "FIFO Threshold")) | |
| 36 | − ucontrol->value.integer.value[0] = dspk->rx_fifo_th; | |
| 37 | − else if (strstr(kcontrol->id.name, "OSR Value")) | |
| 38 | − ucontrol->value.integer.value[0] = dspk->osr_val; | |
| 39 | − else if (strstr(kcontrol->id.name, "LR Polarity Select")) | |
| 40 | − ucontrol->value.integer.value[0] = dspk->lrsel; | |
| 41 | − else if (strstr(kcontrol->id.name, "Channel Select")) | |
| 42 | − ucontrol->value.integer.value[0] = dspk->ch_sel; | |
| 43 | − else if (strstr(kcontrol->id.name, "Mono To Stereo")) | |
| 44 | − ucontrol->value.integer.value[0] = dspk->mono_to_stereo; | |
| 45 | − else if (strstr(kcontrol->id.name, "Stereo To Mono")) | |
| 46 | − ucontrol->value.integer.value[0] = dspk->stereo_to_mono; | |
| 35 | + ucontrol->value.integer.value[0] = dspk->rx_fifo_th; | |
| 47 | 36 | |
| 48 | 37 | return 0; |
| 49 | 38 | } |
| 50 | 39 | |
| 51 | −static int tegra186_dspk_put_control(struct snd_kcontrol *kcontrol, | |
| 40 | +static int tegra186_dspk_put_fifo_th(struct snd_kcontrol *kcontrol, | |
| 52 | 41 | struct snd_ctl_elem_value *ucontrol) |
| 53 | 42 | { |
| 54 | 43 | struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); |
| 55 | 44 | struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); |
| 56 | − int val = ucontrol->value.integer.value[0]; | |
| 57 | − | |
| 58 | − if (strstr(kcontrol->id.name, "FIFO Threshold")) | |
| 59 | − dspk->rx_fifo_th = val; | |
| 60 | − else if (strstr(kcontrol->id.name, "OSR Value")) | |
| 61 | − dspk->osr_val = val; | |
| 62 | − else if (strstr(kcontrol->id.name, "LR Polarity Select")) | |
| 63 | − dspk->lrsel = val; | |
| 64 | − else if (strstr(kcontrol->id.name, "Channel Select")) | |
| 65 | − dspk->ch_sel = val; | |
| 66 | − else if (strstr(kcontrol->id.name, "Mono To Stereo")) | |
| 67 | − dspk->mono_to_stereo = val; | |
| 68 | − else if (strstr(kcontrol->id.name, "Stereo To Mono")) | |
| 69 | − dspk->stereo_to_mono = val; | |
| 45 | + int value = ucontrol->value.integer.value[0]; | |
| 46 | + | |
| 47 | + if (value == dspk->rx_fifo_th) | |
| 48 | + return 0; | |
| 49 | + | |
| 50 | + dspk->rx_fifo_th = value; | |
| 51 | + | |
| 52 | + return 1; | |
| 53 | +} | |
| 54 | + | |
| 55 | +static int tegra186_dspk_get_osr_val(struct snd_kcontrol *kcontrol, | |
| 56 | + struct snd_ctl_elem_value *ucontrol) | |
| 57 | +{ | |
| 58 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 59 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 60 | + | |
| 61 | + ucontrol->value.enumerated.item[0] = dspk->osr_val; | |
| 70 | 62 | |
| 71 | 63 | return 0; |
| 72 | 64 | } |
| 73 | 65 | |
| 66 | +static int tegra186_dspk_put_osr_val(struct snd_kcontrol *kcontrol, | |
| 67 | + struct snd_ctl_elem_value *ucontrol) | |
| 68 | +{ | |
| 69 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 70 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 71 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 72 | + | |
| 73 | + if (value == dspk->osr_val) | |
| 74 | + return 0; | |
| 75 | + | |
| 76 | + dspk->osr_val = value; | |
| 77 | + | |
| 78 | + return 1; | |
| 79 | +} | |
| 80 | + | |
| 81 | +static int tegra186_dspk_get_pol_sel(struct snd_kcontrol *kcontrol, | |
| 82 | + struct snd_ctl_elem_value *ucontrol) | |
| 83 | +{ | |
| 84 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 85 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 86 | + | |
| 87 | + ucontrol->value.enumerated.item[0] = dspk->lrsel; | |
| 88 | + | |
| 89 | + return 0; | |
| 90 | +} | |
| 91 | + | |
| 92 | +static int tegra186_dspk_put_pol_sel(struct snd_kcontrol *kcontrol, | |
| 93 | + struct snd_ctl_elem_value *ucontrol) | |
| 94 | +{ | |
| 95 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 96 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 97 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 98 | + | |
| 99 | + if (value == dspk->lrsel) | |
| 100 | + return 0; | |
| 101 | + | |
| 102 | + dspk->lrsel = value; | |
| 103 | + | |
| 104 | + return 1; | |
| 105 | +} | |
| 106 | + | |
| 107 | +static int tegra186_dspk_get_ch_sel(struct snd_kcontrol *kcontrol, | |
| 108 | + struct snd_ctl_elem_value *ucontrol) | |
| 109 | +{ | |
| 110 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 111 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 112 | + | |
| 113 | + ucontrol->value.enumerated.item[0] = dspk->ch_sel; | |
| 114 | + | |
| 115 | + return 0; | |
| 116 | +} | |
| 117 | + | |
| 118 | +static int tegra186_dspk_put_ch_sel(struct snd_kcontrol *kcontrol, | |
| 119 | + struct snd_ctl_elem_value *ucontrol) | |
| 120 | +{ | |
| 121 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 122 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 123 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 124 | + | |
| 125 | + if (value == dspk->ch_sel) | |
| 126 | + return 0; | |
| 127 | + | |
| 128 | + dspk->ch_sel = value; | |
| 129 | + | |
| 130 | + return 1; | |
| 131 | +} | |
| 132 | + | |
| 133 | +static int tegra186_dspk_get_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 134 | + struct snd_ctl_elem_value *ucontrol) | |
| 135 | +{ | |
| 136 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 137 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 138 | + | |
| 139 | + ucontrol->value.enumerated.item[0] = dspk->mono_to_stereo; | |
| 140 | + | |
| 141 | + return 0; | |
| 142 | +} | |
| 143 | + | |
| 144 | +static int tegra186_dspk_put_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 145 | + struct snd_ctl_elem_value *ucontrol) | |
| 146 | +{ | |
| 147 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 148 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 149 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 150 | + | |
| 151 | + if (value == dspk->mono_to_stereo) | |
| 152 | + return 0; | |
| 153 | + | |
| 154 | + dspk->mono_to_stereo = value; | |
| 155 | + | |
| 156 | + return 1; | |
| 157 | +} | |
| 158 | + | |
| 159 | +static int tegra186_dspk_get_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 160 | + struct snd_ctl_elem_value *ucontrol) | |
| 161 | +{ | |
| 162 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 163 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 164 | + | |
| 165 | + ucontrol->value.enumerated.item[0] = dspk->stereo_to_mono; | |
| 166 | + | |
| 167 | + return 0; | |
| 168 | +} | |
| 169 | + | |
| 170 | +static int tegra186_dspk_put_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 171 | + struct snd_ctl_elem_value *ucontrol) | |
| 172 | +{ | |
| 173 | + struct snd_soc_component *codec = snd_soc_kcontrol_component(kcontrol); | |
| 174 | + struct tegra186_dspk *dspk = snd_soc_component_get_drvdata(codec); | |
| 175 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 176 | + | |
| 177 | + if (value == dspk->stereo_to_mono) | |
| 178 | + return 0; | |
| 179 | + | |
| 180 | + dspk->stereo_to_mono = value; | |
| 181 | + | |
| 182 | + return 1; | |
| 183 | +} | |
| 184 | + | |
| 74 | 185 | static int __maybe_unused tegra186_dspk_runtime_suspend(struct device *dev) |
| 75 | 186 | { |
| 76 | 187 | struct tegra186_dspk *dspk = dev_get_drvdata(dev); |
| @@ -279,17 +390,19 @@ static const struct soc_enum tegra186_dspk_lrsel_enum = · 202 unmodified lines | ||
| 279 | 390 | static const struct snd_kcontrol_new tegrat186_dspk_controls[] = { |
| 280 | 391 | SOC_SINGLE_EXT("FIFO Threshold", SND_SOC_NOPM, 0, |
| 281 | 392 | TEGRA186_DSPK_RX_FIFO_DEPTH - 1, 0, |
| 282 | − tegra186_dspk_get_control, tegra186_dspk_put_control), | |
| 393 | + tegra186_dspk_get_fifo_th, tegra186_dspk_put_fifo_th), | |
| 283 | 394 | SOC_ENUM_EXT("OSR Value", tegra186_dspk_osr_enum, |
| 284 | − tegra186_dspk_get_control, tegra186_dspk_put_control), | |
| 395 | + tegra186_dspk_get_osr_val, tegra186_dspk_put_osr_val), | |
| 285 | 396 | SOC_ENUM_EXT("LR Polarity Select", tegra186_dspk_lrsel_enum, |
| 286 | − tegra186_dspk_get_control, tegra186_dspk_put_control), | |
| 397 | + tegra186_dspk_get_pol_sel, tegra186_dspk_put_pol_sel), | |
| 287 | 398 | SOC_ENUM_EXT("Channel Select", tegra186_dspk_ch_sel_enum, |
| 288 | − tegra186_dspk_get_control, tegra186_dspk_put_control), | |
| 399 | + tegra186_dspk_get_ch_sel, tegra186_dspk_put_ch_sel), | |
| 289 | 400 | SOC_ENUM_EXT("Mono To Stereo", tegra186_dspk_mono_conv_enum, |
| 290 | − tegra186_dspk_get_control, tegra186_dspk_put_control), | |
| 401 | + tegra186_dspk_get_mono_to_stereo, | |
| 402 | + tegra186_dspk_put_mono_to_stereo), | |
| 291 | 403 | SOC_ENUM_EXT("Stereo To Mono", tegra186_dspk_stereo_conv_enum, |
| 292 | − tegra186_dspk_get_control, tegra186_dspk_put_control), | |
| 404 | + tegra186_dspk_get_stereo_to_mono, | |
| 405 | + tegra186_dspk_put_stereo_to_mono), | |
| 293 | 406 | }; |
| 294 | 407 | |
| 295 | 408 | static const struct snd_soc_component_driver tegra186_dspk_cmpnt = { |
| @@ -424,46 +424,122 @@ static const struct snd_soc_dai_ops tegra_admaif_dai_ops = { · 423 unmodified lines | ||
| 424 | 424 | .trigger = tegra_admaif_trigger, |
| 425 | 425 | }; |
| 426 | 426 | |
| 427 | −static int tegra_admaif_get_control(struct snd_kcontrol *kcontrol, | |
| 428 | − struct snd_ctl_elem_value *ucontrol) | |
| 427 | +static int tegra210_admaif_pget_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 428 | + struct snd_ctl_elem_value *ucontrol) | |
| 429 | 429 | { |
| 430 | 430 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 431 | + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); | |
| 432 | + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | |
| 433 | + | |
| 434 | + ucontrol->value.enumerated.item[0] = | |
| 435 | + admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; | |
| 436 | + | |
| 437 | + return 0; | |
| 438 | +} | |
| 439 | + | |
| 440 | +static int tegra210_admaif_pput_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 441 | + struct snd_ctl_elem_value *ucontrol) | |
| 442 | +{ | |
| 443 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 444 | + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); | |
| 445 | + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | |
| 446 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 447 | + | |
| 448 | + if (value == admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]) | |
| 449 | + return 0; | |
| 450 | + | |
| 451 | + admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; | |
| 452 | + | |
| 453 | + return 1; | |
| 454 | +} | |
| 455 | + | |
| 456 | +static int tegra210_admaif_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 457 | + struct snd_ctl_elem_value *ucontrol) | |
| 458 | +{ | |
| 459 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 460 | + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); | |
| 461 | + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | |
| 462 | + | |
| 463 | + ucontrol->value.enumerated.item[0] = | |
| 464 | + admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; | |
| 465 | + | |
| 466 | + return 0; | |
| 467 | +} | |
| 468 | + | |
| 469 | +static int tegra210_admaif_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 470 | + struct snd_ctl_elem_value *ucontrol) | |
| 471 | +{ | |
| 472 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 473 | + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); | |
| 431 | 474 | struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| 475 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 476 | + | |
| 477 | + if (value == admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]) | |
| 478 | + return 0; | |
| 479 | + | |
| 480 | + admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; | |
| 481 | + | |
| 482 | + return 1; | |
| 483 | +} | |
| 484 | + | |
| 485 | +static int tegra210_admaif_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 486 | + struct snd_ctl_elem_value *ucontrol) | |
| 487 | +{ | |
| 488 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 432 | 489 | struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| 433 | − long *uctl_val = &ucontrol->value.integer.value[0]; | |
| 490 | + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | |
| 434 | 491 | |
| 435 | − if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) | |
| 436 | − *uctl_val = admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg]; | |
| 437 | − else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) | |
| 438 | − *uctl_val = admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg]; | |
| 439 | − else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) | |
| 440 | − *uctl_val = admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; | |
| 441 | − else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) | |
| 442 | − *uctl_val = admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; | |
| 492 | + ucontrol->value.enumerated.item[0] = | |
| 493 | + admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]; | |
| 443 | 494 | |
| 444 | 495 | return 0; |
| 445 | 496 | } |
| 446 | 497 | |
| 447 | −static int tegra_admaif_put_control(struct snd_kcontrol *kcontrol, | |
| 448 | − struct snd_ctl_elem_value *ucontrol) | |
| 498 | +static int tegra210_admaif_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 499 | + struct snd_ctl_elem_value *ucontrol) | |
| 449 | 500 | { |
| 450 | 501 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 502 | + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); | |
| 451 | 503 | struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; |
| 504 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 505 | + | |
| 506 | + if (value == admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg]) | |
| 507 | + return 0; | |
| 508 | + | |
| 509 | + admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; | |
| 510 | + | |
| 511 | + return 1; | |
| 512 | +} | |
| 513 | + | |
| 514 | +static int tegra210_admaif_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 515 | + struct snd_ctl_elem_value *ucontrol) | |
| 516 | +{ | |
| 517 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 452 | 518 | struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); |
| 453 | − int value = ucontrol->value.integer.value[0]; | |
| 519 | + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | |
| 454 | 520 | |
| 455 | − if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) | |
| 456 | − admaif->mono_to_stereo[ADMAIF_TX_PATH][ec->reg] = value; | |
| 457 | − else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) | |
| 458 | − admaif->mono_to_stereo[ADMAIF_RX_PATH][ec->reg] = value; | |
| 459 | − else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) | |
| 460 | − admaif->stereo_to_mono[ADMAIF_TX_PATH][ec->reg] = value; | |
| 461 | − else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) | |
| 462 | − admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; | |
| 521 | + ucontrol->value.enumerated.item[0] = | |
| 522 | + admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]; | |
| 463 | 523 | |
| 464 | 524 | return 0; |
| 465 | 525 | } |
| 466 | 526 | |
| 527 | +static int tegra210_admaif_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 528 | + struct snd_ctl_elem_value *ucontrol) | |
| 529 | +{ | |
| 530 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 531 | + struct tegra_admaif *admaif = snd_soc_component_get_drvdata(cmpnt); | |
| 532 | + struct soc_enum *ec = (struct soc_enum *)kcontrol->private_value; | |
| 533 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 534 | + | |
| 535 | + if (value == admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg]) | |
| 536 | + return 0; | |
| 537 | + | |
| 538 | + admaif->stereo_to_mono[ADMAIF_RX_PATH][ec->reg] = value; | |
| 539 | + | |
| 540 | + return 1; | |
| 541 | +} | |
| 542 | + | |
| 467 | 543 | static int tegra_admaif_dai_probe(struct snd_soc_dai *dai) |
| 468 | 544 | { |
| 469 | 545 | struct tegra_admaif *admaif = snd_soc_dai_get_drvdata(dai); |
| @@ -559,17 +635,21 @@ static const char * const tegra_admaif_mono_conv_text[] = { · 89 unmodified lines | ||
| 559 | 635 | } |
| 560 | 636 | |
| 561 | 637 | #define TEGRA_ADMAIF_CIF_CTRL(reg) \ |
| 562 | − NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1,\ | |
| 563 | − tegra_admaif_get_control, tegra_admaif_put_control, \ | |
| 638 | + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Mono To Stereo", reg - 1, \ | |
| 639 | + tegra210_admaif_pget_mono_to_stereo, \ | |
| 640 | + tegra210_admaif_pput_mono_to_stereo, \ | |
| 564 | 641 | tegra_admaif_mono_conv_text), \ |
| 565 | − NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1,\ | |
| 566 | − tegra_admaif_get_control, tegra_admaif_put_control, \ | |
| 642 | + NV_SOC_ENUM_EXT("ADMAIF" #reg " Playback Stereo To Mono", reg - 1, \ | |
| 643 | + tegra210_admaif_pget_stereo_to_mono, \ | |
| 644 | + tegra210_admaif_pput_stereo_to_mono, \ | |
| 567 | 645 | tegra_admaif_stereo_conv_text), \ |
| 568 | − NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ | |
| 569 | − tegra_admaif_get_control, tegra_admaif_put_control, \ | |
| 646 | + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Mono To Stereo", reg - 1, \ | |
| 647 | + tegra210_admaif_cget_mono_to_stereo, \ | |
| 648 | + tegra210_admaif_cput_mono_to_stereo, \ | |
| 570 | 649 | tegra_admaif_mono_conv_text), \ |
| 571 | − NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ | |
| 572 | − tegra_admaif_get_control, tegra_admaif_put_control, \ | |
| 650 | + NV_SOC_ENUM_EXT("ADMAIF" #reg " Capture Stereo To Mono", reg - 1, \ | |
| 651 | + tegra210_admaif_cget_stereo_to_mono, \ | |
| 652 | + tegra210_admaif_cput_stereo_to_mono, \ | |
| 573 | 653 | tegra_admaif_stereo_conv_text) |
| 574 | 654 | |
| 575 | 655 | static struct snd_kcontrol_new tegra210_admaif_controls[] = { |
| @@ -193,6 +193,9 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol, · 192 unmodified lines | ||
| 193 | 193 | struct soc_mixer_control *mc = |
| 194 | 194 | (struct soc_mixer_control *)kcontrol->private_value;; |
| 195 | 195 | |
| 196 | + if (value == bytes_map[mc->reg]) | |
| 197 | + return 0; | |
| 198 | + | |
| 196 | 199 | if (value >= 0 && value <= 255) { |
| 197 | 200 | /* update byte map and enable slot */ |
| 198 | 201 | bytes_map[mc->reg] = value; |
| @@ -511,8 +514,8 @@ static int tegra210_adx_platform_remove(struct platform_device *pdev) · 312 unmodified lines | ||
| 511 | 514 | static const struct dev_pm_ops tegra210_adx_pm_ops = { |
| 512 | 515 | SET_RUNTIME_PM_OPS(tegra210_adx_runtime_suspend, |
| 513 | 516 | tegra210_adx_runtime_resume, NULL) |
| 514 | − SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 515 | − pm_runtime_force_resume) | |
| 517 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 518 | + pm_runtime_force_resume) | |
| 516 | 519 | }; |
| 517 | 520 | |
| 518 | 521 | static struct platform_driver tegra210_adx_driver = { |
| @@ -62,6 +62,7 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, · 61 unmodified lines | ||
| 62 | 62 | unsigned int *item = uctl->value.enumerated.item; |
| 63 | 63 | unsigned int value = e->values[item[0]]; |
| 64 | 64 | unsigned int i, bit_pos, reg_idx = 0, reg_val = 0; |
| 65 | + int change = 0; | |
| 65 | 66 | |
| 66 | 67 | if (item[0] >= e->items) |
| 67 | 68 | return -EINVAL; |
| @@ -86,12 +87,14 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl, · 18 unmodified lines | ||
| 86 | 87 | |
| 87 | 88 | /* Update widget power if state has changed */ |
| 88 | 89 | if (snd_soc_component_test_bits(cmpnt, update[i].reg, |
| 89 | − update[i].mask, update[i].val)) | |
| 90 | − snd_soc_dapm_mux_update_power(dapm, kctl, item[0], e, | |
| 91 | − &update[i]); | |
| 90 | + update[i].mask, | |
| 91 | + update[i].val)) | |
| 92 | + change |= snd_soc_dapm_mux_update_power(dapm, kctl, | |
| 93 | + item[0], e, | |
| 94 | + &update[i]); | |
| 92 | 95 | } |
| 93 | 96 | |
| 94 | − return 0; | |
| 97 | + return change; | |
| 95 | 98 | } |
| 96 | 99 | |
| 97 | 100 | static struct snd_soc_dai_driver tegra210_ahub_dais[] = { |
| @@ -222,6 +222,9 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol, · 221 unmodified lines | ||
| 222 | 222 | int reg = mc->reg; |
| 223 | 223 | int value = ucontrol->value.integer.value[0]; |
| 224 | 224 | |
| 225 | + if (value == bytes_map[reg]) | |
| 226 | + return 0; | |
| 227 | + | |
| 225 | 228 | if (value >= 0 && value <= 255) { |
| 226 | 229 | /* Update byte map and enable slot */ |
| 227 | 230 | bytes_map[reg] = value; |
| @@ -580,8 +583,8 @@ static int tegra210_amx_platform_remove(struct platform_device *pdev) · 352 unmodified lines | ||
| 580 | 583 | static const struct dev_pm_ops tegra210_amx_pm_ops = { |
| 581 | 584 | SET_RUNTIME_PM_OPS(tegra210_amx_runtime_suspend, |
| 582 | 585 | tegra210_amx_runtime_resume, NULL) |
| 583 | − SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 584 | − pm_runtime_force_resume) | |
| 586 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 587 | + pm_runtime_force_resume) | |
| 585 | 588 | }; |
| 586 | 589 | |
| 587 | 590 | static struct platform_driver tegra210_amx_driver = { |
| @@ -156,51 +156,162 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream, · 155 unmodified lines | ||
| 156 | 156 | return 0; |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | −static int tegra210_dmic_get_control(struct snd_kcontrol *kcontrol, | |
| 159 | +static int tegra210_dmic_get_boost_gain(struct snd_kcontrol *kcontrol, | |
| 160 | + struct snd_ctl_elem_value *ucontrol) | |
| 161 | +{ | |
| 162 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 163 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 164 | + | |
| 165 | + ucontrol->value.integer.value[0] = dmic->boost_gain; | |
| 166 | + | |
| 167 | + return 0; | |
| 168 | +} | |
| 169 | + | |
| 170 | +static int tegra210_dmic_put_boost_gain(struct snd_kcontrol *kcontrol, | |
| 171 | + struct snd_ctl_elem_value *ucontrol) | |
| 172 | +{ | |
| 173 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 174 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 175 | + int value = ucontrol->value.integer.value[0]; | |
| 176 | + | |
| 177 | + if (value == dmic->boost_gain) | |
| 178 | + return 0; | |
| 179 | + | |
| 180 | + dmic->boost_gain = value; | |
| 181 | + | |
| 182 | + return 1; | |
| 183 | +} | |
| 184 | + | |
| 185 | +static int tegra210_dmic_get_ch_select(struct snd_kcontrol *kcontrol, | |
| 186 | + struct snd_ctl_elem_value *ucontrol) | |
| 187 | +{ | |
| 188 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 189 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 190 | + | |
| 191 | + ucontrol->value.enumerated.item[0] = dmic->ch_select; | |
| 192 | + | |
| 193 | + return 0; | |
| 194 | +} | |
| 195 | + | |
| 196 | +static int tegra210_dmic_put_ch_select(struct snd_kcontrol *kcontrol, | |
| 197 | + struct snd_ctl_elem_value *ucontrol) | |
| 198 | +{ | |
| 199 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 200 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 201 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 202 | + | |
| 203 | + if (value == dmic->ch_select) | |
| 204 | + return 0; | |
| 205 | + | |
| 206 | + dmic->ch_select = value; | |
| 207 | + | |
| 208 | + return 1; | |
| 209 | +} | |
| 210 | + | |
| 211 | +static int tegra210_dmic_get_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 212 | + struct snd_ctl_elem_value *ucontrol) | |
| 213 | +{ | |
| 214 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 215 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 216 | + | |
| 217 | + ucontrol->value.enumerated.item[0] = dmic->mono_to_stereo; | |
| 218 | + | |
| 219 | + return 0; | |
| 220 | +} | |
| 221 | + | |
| 222 | +static int tegra210_dmic_put_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 223 | + struct snd_ctl_elem_value *ucontrol) | |
| 224 | +{ | |
| 225 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 226 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 227 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 228 | + | |
| 229 | + if (value == dmic->mono_to_stereo) | |
| 230 | + return 0; | |
| 231 | + | |
| 232 | + dmic->mono_to_stereo = value; | |
| 233 | + | |
| 234 | + return 1; | |
| 235 | +} | |
| 236 | + | |
| 237 | +static int tegra210_dmic_get_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 238 | + struct snd_ctl_elem_value *ucontrol) | |
| 239 | +{ | |
| 240 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 241 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 242 | + | |
| 243 | + ucontrol->value.enumerated.item[0] = dmic->stereo_to_mono; | |
| 244 | + | |
| 245 | + return 0; | |
| 246 | +} | |
| 247 | + | |
| 248 | +static int tegra210_dmic_put_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 249 | + struct snd_ctl_elem_value *ucontrol) | |
| 250 | +{ | |
| 251 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 252 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 253 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 254 | + | |
| 255 | + if (value == dmic->stereo_to_mono) | |
| 256 | + return 0; | |
| 257 | + | |
| 258 | + dmic->stereo_to_mono = value; | |
| 259 | + | |
| 260 | + return 1; | |
| 261 | +} | |
| 262 | + | |
| 263 | +static int tegra210_dmic_get_osr_val(struct snd_kcontrol *kcontrol, | |
| 160 | 264 | struct snd_ctl_elem_value *ucontrol) |
| 161 | 265 | { |
| 162 | 266 | struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); |
| 163 | 267 | struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); |
| 164 | 268 | |
| 165 | − if (strstr(kcontrol->id.name, "Boost Gain Volume")) | |
| 166 | − ucontrol->value.integer.value[0] = dmic->boost_gain; | |
| 167 | − else if (strstr(kcontrol->id.name, "Channel Select")) | |
| 168 | − ucontrol->value.integer.value[0] = dmic->ch_select; | |
| 169 | − else if (strstr(kcontrol->id.name, "Mono To Stereo")) | |
| 170 | − ucontrol->value.integer.value[0] = dmic->mono_to_stereo; | |
| 171 | − else if (strstr(kcontrol->id.name, "Stereo To Mono")) | |
| 172 | − ucontrol->value.integer.value[0] = dmic->stereo_to_mono; | |
| 173 | − else if (strstr(kcontrol->id.name, "OSR Value")) | |
| 174 | − ucontrol->value.integer.value[0] = dmic->osr_val; | |
| 175 | − else if (strstr(kcontrol->id.name, "LR Polarity Select")) | |
| 176 | − ucontrol->value.integer.value[0] = dmic->lrsel; | |
| 269 | + ucontrol->value.enumerated.item[0] = dmic->osr_val; | |
| 177 | 270 | |
| 178 | 271 | return 0; |
| 179 | 272 | } |
| 180 | 273 | |
| 181 | −static int tegra210_dmic_put_control(struct snd_kcontrol *kcontrol, | |
| 274 | +static int tegra210_dmic_put_osr_val(struct snd_kcontrol *kcontrol, | |
| 182 | 275 | struct snd_ctl_elem_value *ucontrol) |
| 183 | 276 | { |
| 184 | 277 | struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); |
| 185 | 278 | struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); |
| 186 | − int value = ucontrol->value.integer.value[0]; | |
| 279 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 187 | 280 | |
| 188 | − if (strstr(kcontrol->id.name, "Boost Gain Volume")) | |
| 189 | − dmic->boost_gain = value; | |
| 190 | − else if (strstr(kcontrol->id.name, "Channel Select")) | |
| 191 | − dmic->ch_select = ucontrol->value.integer.value[0]; | |
| 192 | − else if (strstr(kcontrol->id.name, "Mono To Stereo")) | |
| 193 | − dmic->mono_to_stereo = value; | |
| 194 | − else if (strstr(kcontrol->id.name, "Stereo To Mono")) | |
| 195 | − dmic->stereo_to_mono = value; | |
| 196 | − else if (strstr(kcontrol->id.name, "OSR Value")) | |
| 197 | − dmic->osr_val = value; | |
| 198 | − else if (strstr(kcontrol->id.name, "LR Polarity Select")) | |
| 199 | − dmic->lrsel = value; | |
| 281 | + if (value == dmic->osr_val) | |
| 282 | + return 0; | |
| 283 | + | |
| 284 | + dmic->osr_val = value; | |
| 285 | + | |
| 286 | + return 1; | |
| 287 | +} | |
| 288 | + | |
| 289 | +static int tegra210_dmic_get_pol_sel(struct snd_kcontrol *kcontrol, | |
| 290 | + struct snd_ctl_elem_value *ucontrol) | |
| 291 | +{ | |
| 292 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 293 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 294 | + | |
| 295 | + ucontrol->value.enumerated.item[0] = dmic->lrsel; | |
| 200 | 296 | |
| 201 | 297 | return 0; |
| 202 | 298 | } |
| 203 | 299 | |
| 300 | +static int tegra210_dmic_put_pol_sel(struct snd_kcontrol *kcontrol, | |
| 301 | + struct snd_ctl_elem_value *ucontrol) | |
| 302 | +{ | |
| 303 | + struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); | |
| 304 | + struct tegra210_dmic *dmic = snd_soc_component_get_drvdata(comp); | |
| 305 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 306 | + | |
| 307 | + if (value == dmic->lrsel) | |
| 308 | + return 0; | |
| 309 | + | |
| 310 | + dmic->lrsel = value; | |
| 311 | + | |
| 312 | + return 1; | |
| 313 | +} | |
| 314 | + | |
| 204 | 315 | static const struct snd_soc_dai_ops tegra210_dmic_dai_ops = { |
| 205 | 316 | .hw_params = tegra210_dmic_hw_params, |
| 206 | 317 | }; |
| @@ -287,19 +398,22 @@ static const struct soc_enum tegra210_dmic_lrsel_enum = · 80 unmodified lines | ||
| 287 | 398 | |
| 288 | 399 | static const struct snd_kcontrol_new tegra210_dmic_controls[] = { |
| 289 | 400 | SOC_SINGLE_EXT("Boost Gain Volume", 0, 0, MAX_BOOST_GAIN, 0, |
| 290 | − tegra210_dmic_get_control, tegra210_dmic_put_control), | |
| 401 | + tegra210_dmic_get_boost_gain, | |
| 402 | + tegra210_dmic_put_boost_gain), | |
| 291 | 403 | SOC_ENUM_EXT("Channel Select", tegra210_dmic_ch_enum, |
| 292 | − tegra210_dmic_get_control, tegra210_dmic_put_control), | |
| 404 | + tegra210_dmic_get_ch_select, tegra210_dmic_put_ch_select), | |
| 293 | 405 | SOC_ENUM_EXT("Mono To Stereo", |
| 294 | − tegra210_dmic_mono_conv_enum, tegra210_dmic_get_control, | |
| 295 | − tegra210_dmic_put_control), | |
| 406 | + tegra210_dmic_mono_conv_enum, | |
| 407 | + tegra210_dmic_get_mono_to_stereo, | |
| 408 | + tegra210_dmic_put_mono_to_stereo), | |
| 296 | 409 | SOC_ENUM_EXT("Stereo To Mono", |
| 297 | − tegra210_dmic_stereo_conv_enum, tegra210_dmic_get_control, | |
| 298 | − tegra210_dmic_put_control), | |
| 410 | + tegra210_dmic_stereo_conv_enum, | |
| 411 | + tegra210_dmic_get_stereo_to_mono, | |
| 412 | + tegra210_dmic_put_stereo_to_mono), | |
| 299 | 413 | SOC_ENUM_EXT("OSR Value", tegra210_dmic_osr_enum, |
| 300 | − tegra210_dmic_get_control, tegra210_dmic_put_control), | |
| 414 | + tegra210_dmic_get_osr_val, tegra210_dmic_put_osr_val), | |
| 301 | 415 | SOC_ENUM_EXT("LR Polarity Select", tegra210_dmic_lrsel_enum, |
| 302 | − tegra210_dmic_get_control, tegra210_dmic_put_control), | |
| 416 | + tegra210_dmic_get_pol_sel, tegra210_dmic_put_pol_sel), | |
| 303 | 417 | }; |
| 304 | 418 | |
| 305 | 419 | static const struct snd_soc_component_driver tegra210_dmic_compnt = { |
| @@ -302,85 +302,235 @@ static int tegra210_i2s_set_tdm_slot(struct snd_soc_dai *dai, · 301 unmodified lines | ||
| 302 | 302 | return 0; |
| 303 | 303 | } |
| 304 | 304 | |
| 305 | −static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, | |
| 306 | − unsigned int ratio) | |
| 305 | +static int tegra210_i2s_get_loopback(struct snd_kcontrol *kcontrol, | |
| 306 | + struct snd_ctl_elem_value *ucontrol) | |
| 307 | 307 | { |
| 308 | − struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); | |
| 308 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 309 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 309 | 310 | |
| 310 | − i2s->bclk_ratio = ratio; | |
| 311 | + ucontrol->value.integer.value[0] = i2s->loopback; | |
| 311 | 312 | |
| 312 | 313 | return 0; |
| 313 | 314 | } |
| 314 | 315 | |
| 315 | −static int tegra210_i2s_get_control(struct snd_kcontrol *kcontrol, | |
| 316 | − struct snd_ctl_elem_value *ucontrol) | |
| 316 | +static int tegra210_i2s_put_loopback(struct snd_kcontrol *kcontrol, | |
| 317 | + struct snd_ctl_elem_value *ucontrol) | |
| 318 | +{ | |
| 319 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 320 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 321 | + int value = ucontrol->value.integer.value[0]; | |
| 322 | + | |
| 323 | + if (value == i2s->loopback) | |
| 324 | + return 0; | |
| 325 | + | |
| 326 | + i2s->loopback = value; | |
| 327 | + | |
| 328 | + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK, | |
| 329 | + i2s->loopback << I2S_CTRL_LPBK_SHIFT); | |
| 330 | + | |
| 331 | + return 1; | |
| 332 | +} | |
| 333 | + | |
| 334 | +static int tegra210_i2s_get_fsync_width(struct snd_kcontrol *kcontrol, | |
| 335 | + struct snd_ctl_elem_value *ucontrol) | |
| 317 | 336 | { |
| 318 | 337 | struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); |
| 319 | 338 | struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); |
| 320 | − long *uctl_val = &ucontrol->value.integer.value[0]; | |
| 321 | − | |
| 322 | − if (strstr(kcontrol->id.name, "Loopback")) | |
| 323 | − *uctl_val = i2s->loopback; | |
| 324 | − else if (strstr(kcontrol->id.name, "FSYNC Width")) | |
| 325 | − *uctl_val = i2s->fsync_width; | |
| 326 | − else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) | |
| 327 | − *uctl_val = i2s->stereo_to_mono[I2S_TX_PATH]; | |
| 328 | − else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) | |
| 329 | − *uctl_val = i2s->mono_to_stereo[I2S_TX_PATH]; | |
| 330 | − else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) | |
| 331 | − *uctl_val = i2s->stereo_to_mono[I2S_RX_PATH]; | |
| 332 | − else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) | |
| 333 | − *uctl_val = i2s->mono_to_stereo[I2S_RX_PATH]; | |
| 334 | − else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) | |
| 335 | − *uctl_val = i2s->rx_fifo_th; | |
| 336 | − else if (strstr(kcontrol->id.name, "BCLK Ratio")) | |
| 337 | − *uctl_val = i2s->bclk_ratio; | |
| 339 | + | |
| 340 | + ucontrol->value.integer.value[0] = i2s->fsync_width; | |
| 338 | 341 | |
| 339 | 342 | return 0; |
| 340 | 343 | } |
| 341 | 344 | |
| 342 | −static int tegra210_i2s_put_control(struct snd_kcontrol *kcontrol, | |
| 343 | − struct snd_ctl_elem_value *ucontrol) | |
| 345 | +static int tegra210_i2s_put_fsync_width(struct snd_kcontrol *kcontrol, | |
| 346 | + struct snd_ctl_elem_value *ucontrol) | |
| 344 | 347 | { |
| 345 | 348 | struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); |
| 346 | 349 | struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); |
| 347 | 350 | int value = ucontrol->value.integer.value[0]; |
| 348 | 351 | |
| 349 | − if (strstr(kcontrol->id.name, "Loopback")) { | |
| 350 | − i2s->loopback = value; | |
| 352 | + if (value == i2s->fsync_width) | |
| 353 | + return 0; | |
| 351 | 354 | |
| 352 | − regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, | |
| 353 | − I2S_CTRL_LPBK_MASK, | |
| 354 | − i2s->loopback << I2S_CTRL_LPBK_SHIFT); | |
| 355 | + i2s->fsync_width = value; | |
| 355 | 356 | |
| 356 | − } else if (strstr(kcontrol->id.name, "FSYNC Width")) { | |
| 357 | − /* | |
| 358 | − * Frame sync width is used only for FSYNC modes and not | |
| 359 | − * applicable for LRCK modes. Reset value for this field is "0", | |
| 360 | − * which means the width is one bit clock wide. | |
| 361 | − * The width requirement may depend on the codec and in such | |
| 362 | − * cases mixer control is used to update custom values. A value | |
| 363 | − * of "N" here means, width is "N + 1" bit clock wide. | |
| 364 | − */ | |
| 365 | − i2s->fsync_width = value; | |
| 366 | − | |
| 367 | − regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, | |
| 368 | − I2S_CTRL_FSYNC_WIDTH_MASK, | |
| 369 | − i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); | |
| 370 | − | |
| 371 | − } else if (strstr(kcontrol->id.name, "Capture Stereo To Mono")) { | |
| 372 | − i2s->stereo_to_mono[I2S_TX_PATH] = value; | |
| 373 | − } else if (strstr(kcontrol->id.name, "Capture Mono To Stereo")) { | |
| 374 | − i2s->mono_to_stereo[I2S_TX_PATH] = value; | |
| 375 | − } else if (strstr(kcontrol->id.name, "Playback Stereo To Mono")) { | |
| 376 | − i2s->stereo_to_mono[I2S_RX_PATH] = value; | |
| 377 | − } else if (strstr(kcontrol->id.name, "Playback Mono To Stereo")) { | |
| 378 | − i2s->mono_to_stereo[I2S_RX_PATH] = value; | |
| 379 | − } else if (strstr(kcontrol->id.name, "Playback FIFO Threshold")) { | |
| 380 | − i2s->rx_fifo_th = value; | |
| 381 | − } else if (strstr(kcontrol->id.name, "BCLK Ratio")) { | |
| 382 | − i2s->bclk_ratio = value; | |
| 383 | − } | |
| 357 | + /* | |
| 358 | + * Frame sync width is used only for FSYNC modes and not | |
| 359 | + * applicable for LRCK modes. Reset value for this field is "0", | |
| 360 | + * which means the width is one bit clock wide. | |
| 361 | + * The width requirement may depend on the codec and in such | |
| 362 | + * cases mixer control is used to update custom values. A value | |
| 363 | + * of "N" here means, width is "N + 1" bit clock wide. | |
| 364 | + */ | |
| 365 | + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, | |
| 366 | + I2S_CTRL_FSYNC_WIDTH_MASK, | |
| 367 | + i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); | |
| 368 | + | |
| 369 | + return 1; | |
| 370 | +} | |
| 371 | + | |
| 372 | +static int tegra210_i2s_cget_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 373 | + struct snd_ctl_elem_value *ucontrol) | |
| 374 | +{ | |
| 375 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 376 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 377 | + | |
| 378 | + ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_TX_PATH]; | |
| 379 | + | |
| 380 | + return 0; | |
| 381 | +} | |
| 382 | + | |
| 383 | +static int tegra210_i2s_cput_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 384 | + struct snd_ctl_elem_value *ucontrol) | |
| 385 | +{ | |
| 386 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 387 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 388 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 389 | + | |
| 390 | + if (value == i2s->stereo_to_mono[I2S_TX_PATH]) | |
| 391 | + return 0; | |
| 392 | + | |
| 393 | + i2s->stereo_to_mono[I2S_TX_PATH] = value; | |
| 394 | + | |
| 395 | + return 1; | |
| 396 | +} | |
| 397 | + | |
| 398 | +static int tegra210_i2s_cget_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 399 | + struct snd_ctl_elem_value *ucontrol) | |
| 400 | +{ | |
| 401 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 402 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 403 | + | |
| 404 | + ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_TX_PATH]; | |
| 405 | + | |
| 406 | + return 0; | |
| 407 | +} | |
| 408 | + | |
| 409 | +static int tegra210_i2s_cput_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 410 | + struct snd_ctl_elem_value *ucontrol) | |
| 411 | +{ | |
| 412 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 413 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 414 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 415 | + | |
| 416 | + if (value == i2s->mono_to_stereo[I2S_TX_PATH]) | |
| 417 | + return 0; | |
| 418 | + | |
| 419 | + i2s->mono_to_stereo[I2S_TX_PATH] = value; | |
| 420 | + | |
| 421 | + return 1; | |
| 422 | +} | |
| 423 | + | |
| 424 | +static int tegra210_i2s_pget_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 425 | + struct snd_ctl_elem_value *ucontrol) | |
| 426 | +{ | |
| 427 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 428 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 429 | + | |
| 430 | + ucontrol->value.enumerated.item[0] = i2s->stereo_to_mono[I2S_RX_PATH]; | |
| 431 | + | |
| 432 | + return 0; | |
| 433 | +} | |
| 434 | + | |
| 435 | +static int tegra210_i2s_pput_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 436 | + struct snd_ctl_elem_value *ucontrol) | |
| 437 | +{ | |
| 438 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 439 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 440 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 441 | + | |
| 442 | + if (value == i2s->stereo_to_mono[I2S_RX_PATH]) | |
| 443 | + return 0; | |
| 444 | + | |
| 445 | + i2s->stereo_to_mono[I2S_RX_PATH] = value; | |
| 446 | + | |
| 447 | + return 1; | |
| 448 | +} | |
| 449 | + | |
| 450 | +static int tegra210_i2s_pget_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 451 | + struct snd_ctl_elem_value *ucontrol) | |
| 452 | +{ | |
| 453 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 454 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 455 | + | |
| 456 | + ucontrol->value.enumerated.item[0] = i2s->mono_to_stereo[I2S_RX_PATH]; | |
| 457 | + | |
| 458 | + return 0; | |
| 459 | +} | |
| 460 | + | |
| 461 | +static int tegra210_i2s_pput_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 462 | + struct snd_ctl_elem_value *ucontrol) | |
| 463 | +{ | |
| 464 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 465 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 466 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 467 | + | |
| 468 | + if (value == i2s->mono_to_stereo[I2S_RX_PATH]) | |
| 469 | + return 0; | |
| 470 | + | |
| 471 | + i2s->mono_to_stereo[I2S_RX_PATH] = value; | |
| 472 | + | |
| 473 | + return 1; | |
| 474 | +} | |
| 475 | + | |
| 476 | +static int tegra210_i2s_pget_fifo_th(struct snd_kcontrol *kcontrol, | |
| 477 | + struct snd_ctl_elem_value *ucontrol) | |
| 478 | +{ | |
| 479 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 480 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 481 | + | |
| 482 | + ucontrol->value.integer.value[0] = i2s->rx_fifo_th; | |
| 483 | + | |
| 484 | + return 0; | |
| 485 | +} | |
| 486 | + | |
| 487 | +static int tegra210_i2s_pput_fifo_th(struct snd_kcontrol *kcontrol, | |
| 488 | + struct snd_ctl_elem_value *ucontrol) | |
| 489 | +{ | |
| 490 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 491 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 492 | + int value = ucontrol->value.integer.value[0]; | |
| 493 | + | |
| 494 | + if (value == i2s->rx_fifo_th) | |
| 495 | + return 0; | |
| 496 | + | |
| 497 | + i2s->rx_fifo_th = value; | |
| 498 | + | |
| 499 | + return 1; | |
| 500 | +} | |
| 501 | + | |
| 502 | +static int tegra210_i2s_get_bclk_ratio(struct snd_kcontrol *kcontrol, | |
| 503 | + struct snd_ctl_elem_value *ucontrol) | |
| 504 | +{ | |
| 505 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 506 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 507 | + | |
| 508 | + ucontrol->value.integer.value[0] = i2s->bclk_ratio; | |
| 509 | + | |
| 510 | + return 0; | |
| 511 | +} | |
| 512 | + | |
| 513 | +static int tegra210_i2s_put_bclk_ratio(struct snd_kcontrol *kcontrol, | |
| 514 | + struct snd_ctl_elem_value *ucontrol) | |
| 515 | +{ | |
| 516 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); | |
| 517 | + struct tegra210_i2s *i2s = snd_soc_component_get_drvdata(compnt); | |
| 518 | + int value = ucontrol->value.integer.value[0]; | |
| 519 | + | |
| 520 | + if (value == i2s->bclk_ratio) | |
| 521 | + return 0; | |
| 522 | + | |
| 523 | + i2s->bclk_ratio = value; | |
| 524 | + | |
| 525 | + return 1; | |
| 526 | +} | |
| 527 | + | |
| 528 | +static int tegra210_i2s_set_dai_bclk_ratio(struct snd_soc_dai *dai, | |
| 529 | + unsigned int ratio) | |
| 530 | +{ | |
| 531 | + struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai); | |
| 532 | + | |
| 533 | + i2s->bclk_ratio = ratio; | |
| 384 | 534 | |
| 385 | 535 | return 0; |
| 386 | 536 | } |
| @@ -598,22 +748,28 @@ static const struct soc_enum tegra210_i2s_stereo_conv_enum = · 211 unmodified lines | ||
| 598 | 748 | tegra210_i2s_stereo_conv_text); |
| 599 | 749 | |
| 600 | 750 | static const struct snd_kcontrol_new tegra210_i2s_controls[] = { |
| 601 | − SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_control, | |
| 602 | − tegra210_i2s_put_control), | |
| 603 | − SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, tegra210_i2s_get_control, | |
| 604 | − tegra210_i2s_put_control), | |
| 751 | + SOC_SINGLE_EXT("Loopback", 0, 0, 1, 0, tegra210_i2s_get_loopback, | |
| 752 | + tegra210_i2s_put_loopback), | |
| 753 | + SOC_SINGLE_EXT("FSYNC Width", 0, 0, 255, 0, | |
| 754 | + tegra210_i2s_get_fsync_width, | |
| 755 | + tegra210_i2s_put_fsync_width), | |
| 605 | 756 | SOC_ENUM_EXT("Capture Stereo To Mono", tegra210_i2s_stereo_conv_enum, |
| 606 | − tegra210_i2s_get_control, tegra210_i2s_put_control), | |
| 757 | + tegra210_i2s_cget_stereo_to_mono, | |
| 758 | + tegra210_i2s_cput_stereo_to_mono), | |
| 607 | 759 | SOC_ENUM_EXT("Capture Mono To Stereo", tegra210_i2s_mono_conv_enum, |
| 608 | − tegra210_i2s_get_control, tegra210_i2s_put_control), | |
| 760 | + tegra210_i2s_cget_mono_to_stereo, | |
| 761 | + tegra210_i2s_cput_mono_to_stereo), | |
| 609 | 762 | SOC_ENUM_EXT("Playback Stereo To Mono", tegra210_i2s_stereo_conv_enum, |
| 610 | − tegra210_i2s_get_control, tegra210_i2s_put_control), | |
| 763 | + tegra210_i2s_pget_mono_to_stereo, | |
| 764 | + tegra210_i2s_pput_mono_to_stereo), | |
| 611 | 765 | SOC_ENUM_EXT("Playback Mono To Stereo", tegra210_i2s_mono_conv_enum, |
| 612 | − tegra210_i2s_get_control, tegra210_i2s_put_control), | |
| 766 | + tegra210_i2s_pget_stereo_to_mono, | |
| 767 | + tegra210_i2s_pput_stereo_to_mono), | |
| 613 | 768 | SOC_SINGLE_EXT("Playback FIFO Threshold", 0, 0, I2S_RX_FIFO_DEPTH - 1, |
| 614 | − 0, tegra210_i2s_get_control, tegra210_i2s_put_control), | |
| 615 | − SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, tegra210_i2s_get_control, | |
| 616 | − tegra210_i2s_put_control), | |
| 769 | + 0, tegra210_i2s_pget_fifo_th, tegra210_i2s_pput_fifo_th), | |
| 770 | + SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, | |
| 771 | + tegra210_i2s_get_bclk_ratio, | |
| 772 | + tegra210_i2s_put_bclk_ratio), | |
| 617 | 773 | }; |
| 618 | 774 | |
| 619 | 775 | static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] = { |
| @@ -192,24 +192,24 @@ static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol, · 191 unmodified lines | ||
| 192 | 192 | return 0; |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | −static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol, | |
| 196 | − struct snd_ctl_elem_value *ucontrol) | |
| 195 | +static int tegra210_mixer_apply_gain(struct snd_kcontrol *kcontrol, | |
| 196 | + struct snd_ctl_elem_value *ucontrol, | |
| 197 | + bool instant_gain) | |
| 197 | 198 | { |
| 198 | 199 | struct soc_mixer_control *mc = |
| 199 | 200 | (struct soc_mixer_control *)kcontrol->private_value; |
| 200 | 201 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 201 | 202 | struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt); |
| 202 | 203 | unsigned int reg = mc->reg, id; |
| 203 | − bool instant_gain = false; | |
| 204 | 204 | int err; |
| 205 | 205 | |
| 206 | − if (strstr(kcontrol->id.name, "Instant Gain Volume")) | |
| 207 | − instant_gain = true; | |
| 208 | − | |
| 209 | 206 | /* Save gain value for specific MIXER input */ |
| 210 | 207 | id = (reg - TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_0) / |
| 211 | 208 | TEGRA210_MIXER_GAIN_CFG_RAM_ADDR_STRIDE; |
| 212 | 209 | |
| 210 | + if (mixer->gain_value[id] == ucontrol->value.integer.value[0]) | |
| 211 | + return 0; | |
| 212 | + | |
| 213 | 213 | mixer->gain_value[id] = ucontrol->value.integer.value[0]; |
| 214 | 214 | |
| 215 | 215 | err = tegra210_mixer_configure_gain(cmpnt, id, instant_gain); |
| @@ -221,6 +221,18 @@ static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol, · 5 unmodified lines | ||
| 221 | 221 | return 1; |
| 222 | 222 | } |
| 223 | 223 | |
| 224 | +static int tegra210_mixer_put_gain(struct snd_kcontrol *kcontrol, | |
| 225 | + struct snd_ctl_elem_value *ucontrol) | |
| 226 | +{ | |
| 227 | + return tegra210_mixer_apply_gain(kcontrol, ucontrol, false); | |
| 228 | +} | |
| 229 | + | |
| 230 | +static int tegra210_mixer_put_instant_gain(struct snd_kcontrol *kcontrol, | |
| 231 | + struct snd_ctl_elem_value *ucontrol) | |
| 232 | +{ | |
| 233 | + return tegra210_mixer_apply_gain(kcontrol, ucontrol, true); | |
| 234 | +} | |
| 235 | + | |
| 224 | 236 | static int tegra210_mixer_set_audio_cif(struct tegra210_mixer *mixer, |
| 225 | 237 | struct snd_pcm_hw_params *params, |
| 226 | 238 | unsigned int reg, |
| @@ -388,7 +400,7 @@ ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG); · 161 unmodified lines | ||
| 388 | 400 | SOC_SINGLE_EXT("RX" #id " Instant Gain Volume", \ |
| 389 | 401 | MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \ |
| 390 | 402 | 0x20000, 0, tegra210_mixer_get_gain, \ |
| 391 | − tegra210_mixer_put_gain), | |
| 403 | + tegra210_mixer_put_instant_gain), | |
| 392 | 404 | |
| 393 | 405 | /* Volume controls for all MIXER inputs */ |
| 394 | 406 | static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = { |
| @@ -654,8 +666,8 @@ static int tegra210_mixer_platform_remove(struct platform_device *pdev) · 259 unmodified lines | ||
| 654 | 666 | static const struct dev_pm_ops tegra210_mixer_pm_ops = { |
| 655 | 667 | SET_RUNTIME_PM_OPS(tegra210_mixer_runtime_suspend, |
| 656 | 668 | tegra210_mixer_runtime_resume, NULL) |
| 657 | − SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 658 | − pm_runtime_force_resume) | |
| 669 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 670 | + pm_runtime_force_resume) | |
| 659 | 671 | }; |
| 660 | 672 | |
| 661 | 673 | static struct platform_driver tegra210_mixer_driver = { |
| @@ -136,7 +136,7 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, · 135 unmodified lines | ||
| 136 | 136 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 137 | 137 | struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); |
| 138 | 138 | unsigned int value; |
| 139 | − u8 mute_mask; | |
| 139 | + u8 new_mask, old_mask; | |
| 140 | 140 | int err; |
| 141 | 141 | |
| 142 | 142 | pm_runtime_get_sync(cmpnt->dev); |
| @@ -148,15 +148,23 @@ static int tegra210_mvc_put_mute(struct snd_kcontrol *kcontrol, · 5 unmodified lines | ||
| 148 | 148 | if (err < 0) |
| 149 | 149 | goto end; |
| 150 | 150 | |
| 151 | − mute_mask = ucontrol->value.integer.value[0]; | |
| 151 | + regmap_read(mvc->regmap, TEGRA210_MVC_CTRL, &value); | |
| 152 | + | |
| 153 | + old_mask = (value >> TEGRA210_MVC_MUTE_SHIFT) & TEGRA210_MUTE_MASK_EN; | |
| 154 | + new_mask = ucontrol->value.integer.value[0]; | |
| 155 | + | |
| 156 | + if (new_mask == old_mask) { | |
| 157 | + err = 0; | |
| 158 | + goto end; | |
| 159 | + } | |
| 152 | 160 | |
| 153 | 161 | err = regmap_update_bits(mvc->regmap, mc->reg, |
| 154 | 162 | TEGRA210_MVC_MUTE_MASK, |
| 155 | − mute_mask << TEGRA210_MVC_MUTE_SHIFT); | |
| 163 | + new_mask << TEGRA210_MVC_MUTE_SHIFT); | |
| 156 | 164 | if (err < 0) |
| 157 | 165 | goto end; |
| 158 | 166 | |
| 159 | − return 1; | |
| 167 | + err = 1; | |
| 160 | 168 | |
| 161 | 169 | end: |
| 162 | 170 | pm_runtime_put(cmpnt->dev); |
| @@ -195,7 +203,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, · 32 unmodified lines | ||
| 195 | 203 | unsigned int reg = mc->reg; |
| 196 | 204 | unsigned int value; |
| 197 | 205 | u8 chan; |
| 198 | − int err; | |
| 206 | + int err, old_volume; | |
| 199 | 207 | |
| 200 | 208 | pm_runtime_get_sync(cmpnt->dev); |
| 201 | 209 | |
| @@ -207,10 +215,16 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, · 5 unmodified lines | ||
| 207 | 215 | goto end; |
| 208 | 216 | |
| 209 | 217 | chan = (reg - TEGRA210_MVC_TARGET_VOL) / REG_SIZE; |
| 218 | + old_volume = mvc->volume[chan]; | |
| 210 | 219 | |
| 211 | 220 | tegra210_mvc_conv_vol(mvc, chan, |
| 212 | 221 | ucontrol->value.integer.value[0]); |
| 213 | 222 | |
| 223 | + if (mvc->volume[chan] == old_volume) { | |
| 224 | + err = 0; | |
| 225 | + goto end; | |
| 226 | + } | |
| 227 | + | |
| 214 | 228 | /* Configure init volume same as target volume */ |
| 215 | 229 | regmap_write(mvc->regmap, |
| 216 | 230 | TEGRA210_MVC_REG_OFFSET(TEGRA210_MVC_INIT_VOL, chan), |
| @@ -222,7 +236,7 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, · 5 unmodified lines | ||
| 222 | 236 | TEGRA210_MVC_VOLUME_SWITCH_MASK, |
| 223 | 237 | TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); |
| 224 | 238 | |
| 225 | − return 1; | |
| 239 | + err = 1; | |
| 226 | 240 | |
| 227 | 241 | end: |
| 228 | 242 | pm_runtime_put(cmpnt->dev); |
| @@ -275,7 +289,7 @@ static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol, · 46 unmodified lines | ||
| 275 | 289 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 276 | 290 | struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); |
| 277 | 291 | |
| 278 | − ucontrol->value.integer.value[0] = mvc->curve_type; | |
| 292 | + ucontrol->value.enumerated.item[0] = mvc->curve_type; | |
| 279 | 293 | |
| 280 | 294 | return 0; |
| 281 | 295 | } |
| @@ -285,7 +299,7 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol, · 3 unmodified lines | ||
| 285 | 299 | { |
| 286 | 300 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 287 | 301 | struct tegra210_mvc *mvc = snd_soc_component_get_drvdata(cmpnt); |
| 288 | − int value; | |
| 302 | + unsigned int value; | |
| 289 | 303 | |
| 290 | 304 | regmap_read(mvc->regmap, TEGRA210_MVC_ENABLE, &value); |
| 291 | 305 | if (value & TEGRA210_MVC_EN) { |
| @@ -294,10 +308,10 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol, · 2 unmodified lines | ||
| 294 | 308 | return -EINVAL; |
| 295 | 309 | } |
| 296 | 310 | |
| 297 | − if (mvc->curve_type == ucontrol->value.integer.value[0]) | |
| 311 | + if (mvc->curve_type == ucontrol->value.enumerated.item[0]) | |
| 298 | 312 | return 0; |
| 299 | 313 | |
| 300 | − mvc->curve_type = ucontrol->value.integer.value[0]; | |
| 314 | + mvc->curve_type = ucontrol->value.enumerated.item[0]; | |
| 301 | 315 | |
| 302 | 316 | tegra210_mvc_reset_vol_settings(mvc, cmpnt->dev); |
| 303 | 317 | |
| @@ -625,8 +639,8 @@ static int tegra210_mvc_platform_remove(struct platform_device *pdev) · 321 unmodified lines | ||
| 625 | 639 | static const struct dev_pm_ops tegra210_mvc_pm_ops = { |
| 626 | 640 | SET_RUNTIME_PM_OPS(tegra210_mvc_runtime_suspend, |
| 627 | 641 | tegra210_mvc_runtime_resume, NULL) |
| 628 | − SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 629 | − pm_runtime_force_resume) | |
| 642 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 643 | + pm_runtime_force_resume) | |
| 630 | 644 | }; |
| 631 | 645 | |
| 632 | 646 | static struct platform_driver tegra210_mvc_driver = { |
| @@ -3244,46 +3244,107 @@ static int tegra210_sfc_init(struct snd_soc_dapm_widget *w, · 3243 unmodified lines | ||
| 3244 | 3244 | return tegra210_sfc_write_coeff_ram(cmpnt); |
| 3245 | 3245 | } |
| 3246 | 3246 | |
| 3247 | −static int tegra210_sfc_get_control(struct snd_kcontrol *kcontrol, | |
| 3247 | +static int tegra210_sfc_iget_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 3248 | 3248 | struct snd_ctl_elem_value *ucontrol) |
| 3249 | 3249 | { |
| 3250 | 3250 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 3251 | 3251 | struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); |
| 3252 | 3252 | |
| 3253 | − if (strstr(kcontrol->id.name, "Input Stereo To Mono")) | |
| 3254 | − ucontrol->value.integer.value[0] = | |
| 3255 | − sfc->stereo_to_mono[SFC_RX_PATH]; | |
| 3256 | − else if (strstr(kcontrol->id.name, "Input Mono To Stereo")) | |
| 3257 | − ucontrol->value.integer.value[0] = | |
| 3258 | − sfc->mono_to_stereo[SFC_RX_PATH]; | |
| 3259 | − else if (strstr(kcontrol->id.name, "Output Stereo To Mono")) | |
| 3260 | − ucontrol->value.integer.value[0] = | |
| 3261 | − sfc->stereo_to_mono[SFC_TX_PATH]; | |
| 3262 | − else if (strstr(kcontrol->id.name, "Output Mono To Stereo")) | |
| 3263 | − ucontrol->value.integer.value[0] = | |
| 3264 | − sfc->mono_to_stereo[SFC_TX_PATH]; | |
| 3253 | + ucontrol->value.enumerated.item[0] = sfc->stereo_to_mono[SFC_RX_PATH]; | |
| 3265 | 3254 | |
| 3266 | 3255 | return 0; |
| 3267 | 3256 | } |
| 3268 | 3257 | |
| 3269 | −static int tegra210_sfc_put_control(struct snd_kcontrol *kcontrol, | |
| 3258 | +static int tegra210_sfc_iput_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 3270 | 3259 | struct snd_ctl_elem_value *ucontrol) |
| 3271 | 3260 | { |
| 3272 | 3261 | struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); |
| 3273 | 3262 | struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); |
| 3274 | − int value = ucontrol->value.integer.value[0]; | |
| 3275 | − | |
| 3276 | − if (strstr(kcontrol->id.name, "Input Stereo To Mono")) | |
| 3277 | − sfc->stereo_to_mono[SFC_RX_PATH] = value; | |
| 3278 | − else if (strstr(kcontrol->id.name, "Input Mono To Stereo")) | |
| 3279 | − sfc->mono_to_stereo[SFC_RX_PATH] = value; | |
| 3280 | − else if (strstr(kcontrol->id.name, "Output Stereo To Mono")) | |
| 3281 | − sfc->stereo_to_mono[SFC_TX_PATH] = value; | |
| 3282 | − else if (strstr(kcontrol->id.name, "Output Mono To Stereo")) | |
| 3283 | − sfc->mono_to_stereo[SFC_TX_PATH] = value; | |
| 3284 | − else | |
| 3263 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 3264 | + | |
| 3265 | + if (value == sfc->stereo_to_mono[SFC_RX_PATH]) | |
| 3266 | + return 0; | |
| 3267 | + | |
| 3268 | + sfc->stereo_to_mono[SFC_RX_PATH] = value; | |
| 3269 | + | |
| 3270 | + return 1; | |
| 3271 | +} | |
| 3272 | + | |
| 3273 | +static int tegra210_sfc_iget_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 3274 | + struct snd_ctl_elem_value *ucontrol) | |
| 3275 | +{ | |
| 3276 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 3277 | + struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); | |
| 3278 | + | |
| 3279 | + ucontrol->value.enumerated.item[0] = sfc->mono_to_stereo[SFC_RX_PATH]; | |
| 3280 | + | |
| 3281 | + return 0; | |
| 3282 | +} | |
| 3283 | + | |
| 3284 | +static int tegra210_sfc_iput_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 3285 | + struct snd_ctl_elem_value *ucontrol) | |
| 3286 | +{ | |
| 3287 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 3288 | + struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); | |
| 3289 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 3290 | + | |
| 3291 | + if (value == sfc->mono_to_stereo[SFC_RX_PATH]) | |
| 3285 | 3292 | return 0; |
| 3286 | 3293 | |
| 3294 | + sfc->mono_to_stereo[SFC_RX_PATH] = value; | |
| 3295 | + | |
| 3296 | + return 1; | |
| 3297 | +} | |
| 3298 | + | |
| 3299 | +static int tegra210_sfc_oget_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 3300 | + struct snd_ctl_elem_value *ucontrol) | |
| 3301 | +{ | |
| 3302 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 3303 | + struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); | |
| 3304 | + | |
| 3305 | + ucontrol->value.enumerated.item[0] = sfc->stereo_to_mono[SFC_TX_PATH]; | |
| 3306 | + | |
| 3307 | + return 0; | |
| 3308 | +} | |
| 3309 | + | |
| 3310 | +static int tegra210_sfc_oput_stereo_to_mono(struct snd_kcontrol *kcontrol, | |
| 3311 | + struct snd_ctl_elem_value *ucontrol) | |
| 3312 | +{ | |
| 3313 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 3314 | + struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); | |
| 3315 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 3316 | + | |
| 3317 | + if (value == sfc->stereo_to_mono[SFC_TX_PATH]) | |
| 3318 | + return 0; | |
| 3319 | + | |
| 3320 | + sfc->stereo_to_mono[SFC_TX_PATH] = value; | |
| 3321 | + | |
| 3322 | + return 1; | |
| 3323 | +} | |
| 3324 | + | |
| 3325 | +static int tegra210_sfc_oget_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 3326 | + struct snd_ctl_elem_value *ucontrol) | |
| 3327 | +{ | |
| 3328 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 3329 | + struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); | |
| 3330 | + | |
| 3331 | + ucontrol->value.enumerated.item[0] = sfc->mono_to_stereo[SFC_TX_PATH]; | |
| 3332 | + | |
| 3333 | + return 0; | |
| 3334 | +} | |
| 3335 | + | |
| 3336 | +static int tegra210_sfc_oput_mono_to_stereo(struct snd_kcontrol *kcontrol, | |
| 3337 | + struct snd_ctl_elem_value *ucontrol) | |
| 3338 | +{ | |
| 3339 | + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); | |
| 3340 | + struct tegra210_sfc *sfc = snd_soc_component_get_drvdata(cmpnt); | |
| 3341 | + unsigned int value = ucontrol->value.enumerated.item[0]; | |
| 3342 | + | |
| 3343 | + if (value == sfc->mono_to_stereo[SFC_TX_PATH]) | |
| 3344 | + return 0; | |
| 3345 | + | |
| 3346 | + sfc->mono_to_stereo[SFC_TX_PATH] = value; | |
| 3347 | + | |
| 3287 | 3348 | return 1; |
| 3288 | 3349 | } |
| 3289 | 3350 | |
| @@ -3384,13 +3445,17 @@ static const struct soc_enum tegra210_sfc_mono_conv_enum = · 94 unmodified lines | ||
| 3384 | 3445 | |
| 3385 | 3446 | static const struct snd_kcontrol_new tegra210_sfc_controls[] = { |
| 3386 | 3447 | SOC_ENUM_EXT("Input Stereo To Mono", tegra210_sfc_stereo_conv_enum, |
| 3387 | − tegra210_sfc_get_control, tegra210_sfc_put_control), | |
| 3448 | + tegra210_sfc_iget_stereo_to_mono, | |
| 3449 | + tegra210_sfc_iput_stereo_to_mono), | |
| 3388 | 3450 | SOC_ENUM_EXT("Input Mono To Stereo", tegra210_sfc_mono_conv_enum, |
| 3389 | − tegra210_sfc_get_control, tegra210_sfc_put_control), | |
| 3451 | + tegra210_sfc_iget_mono_to_stereo, | |
| 3452 | + tegra210_sfc_iput_mono_to_stereo), | |
| 3390 | 3453 | SOC_ENUM_EXT("Output Stereo To Mono", tegra210_sfc_stereo_conv_enum, |
| 3391 | − tegra210_sfc_get_control, tegra210_sfc_put_control), | |
| 3454 | + tegra210_sfc_oget_stereo_to_mono, | |
| 3455 | + tegra210_sfc_oput_stereo_to_mono), | |
| 3392 | 3456 | SOC_ENUM_EXT("Output Mono To Stereo", tegra210_sfc_mono_conv_enum, |
| 3393 | − tegra210_sfc_get_control, tegra210_sfc_put_control), | |
| 3457 | + tegra210_sfc_oget_mono_to_stereo, | |
| 3458 | + tegra210_sfc_oput_mono_to_stereo), | |
| 3394 | 3459 | }; |
| 3395 | 3460 | |
| 3396 | 3461 | static const struct snd_soc_component_driver tegra210_sfc_cmpnt = { |
| @@ -3529,8 +3594,8 @@ static int tegra210_sfc_platform_remove(struct platform_device *pdev) · 132 unmodified lines | ||
| 3529 | 3594 | static const struct dev_pm_ops tegra210_sfc_pm_ops = { |
| 3530 | 3595 | SET_RUNTIME_PM_OPS(tegra210_sfc_runtime_suspend, |
| 3531 | 3596 | tegra210_sfc_runtime_resume, NULL) |
| 3532 | − SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 3533 | − pm_runtime_force_resume) | |
| 3597 | + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 3598 | + pm_runtime_force_resume) | |
| 3534 | 3599 | }; |
| 3535 | 3600 | |
| 3536 | 3601 | static struct platform_driver tegra210_sfc_driver = { |
| @@ -3016,11 +3016,11 @@ static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = { · 3015 unmodified lines | ||
| 3016 | 3016 | |
| 3017 | 3017 | |
| 3018 | 3018 | static const struct snd_djm_device snd_djm_devices[] = { |
| 3019 | − SND_DJM_DEVICE(250mk2), | |
| 3020 | − SND_DJM_DEVICE(750), | |
| 3021 | − SND_DJM_DEVICE(750mk2), | |
| 3022 | − SND_DJM_DEVICE(850), | |
| 3023 | − SND_DJM_DEVICE(900nxs2) | |
| 3019 | + [SND_DJM_250MK2_IDX] = SND_DJM_DEVICE(250mk2), | |
| 3020 | + [SND_DJM_750_IDX] = SND_DJM_DEVICE(750), | |
| 3021 | + [SND_DJM_850_IDX] = SND_DJM_DEVICE(850), | |
| 3022 | + [SND_DJM_900NXS2_IDX] = SND_DJM_DEVICE(900nxs2), | |
| 3023 | + [SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2), | |
| 3024 | 3024 | }; |
| 3025 | 3025 | |
| 3026 | 3026 | |
| @@ -83,6 +83,7 @@ struct btf_id { · 82 unmodified lines | ||
| 83 | 83 | int cnt; |
| 84 | 84 | }; |
| 85 | 85 | int addr_cnt; |
| 86 | + bool is_set; | |
| 86 | 87 | Elf64_Addr addr[ADDR_CNT]; |
| 87 | 88 | }; |
| 88 | 89 | |
| @@ -451,8 +452,10 @@ static int symbols_collect(struct object *obj) · 362 unmodified lines | ||
| 451 | 452 | * in symbol's size, together with 'cnt' field hence |
| 452 | 453 | * that - 1. |
| 453 | 454 | */ |
| 454 | − if (id) | |
| 455 | + if (id) { | |
| 455 | 456 | id->cnt = sym.st_size / sizeof(int) - 1; |
| 457 | + id->is_set = true; | |
| 458 | + } | |
| 456 | 459 | } else { |
| 457 | 460 | pr_err("FAILED unsupported prefix %s\n", prefix); |
| 458 | 461 | return -1; |
| @@ -568,9 +571,8 @@ static int id_patch(struct object *obj, struct btf_id *id) · 109 unmodified lines | ||
| 568 | 571 | int *ptr = data->d_buf; |
| 569 | 572 | int i; |
| 570 | 573 | |
| 571 | − if (!id->id) { | |
| 574 | + if (!id->id && !id->is_set) | |
| 572 | 575 | pr_err("WARN: resolve_btfids: unresolved symbol %s\n", id->name); |
| 573 | − } | |
| 574 | 576 | |
| 575 | 577 | for (i = 0; i < id->addr_cnt; i++) { |
| 576 | 578 | unsigned long addr = id->addr[i]; |
| @@ -48,7 +48,6 @@ FEATURE_TESTS_BASIC := \ · 47 unmodified lines | ||
| 48 | 48 | numa_num_possible_cpus \ |
| 49 | 49 | libperl \ |
| 50 | 50 | libpython \ |
| 51 | − libpython-version \ | |
| 52 | 51 | libslang \ |
| 53 | 52 | libslang-include-subdir \ |
| 54 | 53 | libtraceevent \ |
| @@ -32,7 +32,6 @@ FILES= \ · 31 unmodified lines | ||
| 32 | 32 | test-numa_num_possible_cpus.bin \ |
| 33 | 33 | test-libperl.bin \ |
| 34 | 34 | test-libpython.bin \ |
| 35 | − test-libpython-version.bin \ | |
| 36 | 35 | test-libslang.bin \ |
| 37 | 36 | test-libslang-include-subdir.bin \ |
| 38 | 37 | test-libtraceevent.bin \ |
| @@ -227,9 +226,6 @@ $(OUTPUT)test-libperl.bin: · 188 unmodified lines | ||
| 227 | 226 | $(OUTPUT)test-libpython.bin: |
| 228 | 227 | $(BUILD) $(FLAGS_PYTHON_EMBED) |
| 229 | 228 | |
| 230 | −$(OUTPUT)test-libpython-version.bin: | |
| 231 | − $(BUILD) | |
| 232 | − | |
| 233 | 229 | $(OUTPUT)test-libbfd.bin: |
| 234 | 230 | $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl |
| 235 | 231 | |
| @@ -14,10 +14,6 @@ · 13 unmodified lines | ||
| 14 | 14 | # include "test-libpython.c" |
| 15 | 15 | #undef main |
| 16 | 16 | |
| 17 | −#define main main_test_libpython_version | |
| 18 | −# include "test-libpython-version.c" | |
| 19 | −#undef main | |
| 20 | − | |
| 21 | 17 | #define main main_test_libperl |
| 22 | 18 | # include "test-libperl.c" |
| 23 | 19 | #undef main |
| @@ -177,7 +173,6 @@ · 153 unmodified lines | ||
| 177 | 173 | int main(int argc, char *argv[]) |
| 178 | 174 | { |
| 179 | 175 | main_test_libpython(); |
| 180 | − main_test_libpython_version(); | |
| 181 | 176 | main_test_libperl(); |
| 182 | 177 | main_test_hello(); |
| 183 | 178 | main_test_libelf(); |
| @@ -1,11 +0,0 @@ | ||
| 1 | −// SPDX-License-Identifier: GPL-2.0 | |
| 2 | −#include <Python.h> | |
| 3 | − | |
| 4 | −#if PY_VERSION_HEX >= 0x03000000 | |
| 5 | − #error | |
| 6 | −#endif | |
| 7 | − | |
| 8 | −int main(void) | |
| 9 | −{ | |
| 10 | − return 0; | |
| 11 | −} | |
| @@ -1,14 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _LIBLOCKDEP_DEBUG_LOCKS_H_ | |
| 3 | −#define _LIBLOCKDEP_DEBUG_LOCKS_H_ | |
| 4 | − | |
| 5 | −#include <stddef.h> | |
| 6 | −#include <linux/compiler.h> | |
| 7 | −#include <asm/bug.h> | |
| 8 | − | |
| 9 | −#define DEBUG_LOCKS_WARN_ON(x) WARN_ON(x) | |
| 10 | − | |
| 11 | −extern bool debug_locks; | |
| 12 | −extern bool debug_locks_silent; | |
| 13 | − | |
| 14 | −#endif | |
| @@ -1,12 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _LIBLOCKDEP_LINUX_HARDIRQ_H_ | |
| 3 | −#define _LIBLOCKDEP_LINUX_HARDIRQ_H_ | |
| 4 | − | |
| 5 | −#define SOFTIRQ_BITS 0UL | |
| 6 | −#define HARDIRQ_BITS 0UL | |
| 7 | −#define SOFTIRQ_SHIFT 0UL | |
| 8 | −#define HARDIRQ_SHIFT 0UL | |
| 9 | −#define hardirq_count() 0UL | |
| 10 | −#define softirq_count() 0UL | |
| 11 | − | |
| 12 | −#endif | |
| @@ -1,39 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ | |
| 3 | −#define _LIBLOCKDEP_LINUX_TRACE_IRQFLAGS_H_ | |
| 4 | − | |
| 5 | −# define lockdep_hardirq_context() 0 | |
| 6 | −# define lockdep_softirq_context(p) 0 | |
| 7 | −# define lockdep_hardirqs_enabled() 0 | |
| 8 | −# define lockdep_softirqs_enabled(p) 0 | |
| 9 | −# define lockdep_hardirq_enter() do { } while (0) | |
| 10 | −# define lockdep_hardirq_exit() do { } while (0) | |
| 11 | −# define lockdep_softirq_enter() do { } while (0) | |
| 12 | −# define lockdep_softirq_exit() do { } while (0) | |
| 13 | −# define INIT_TRACE_IRQFLAGS | |
| 14 | − | |
| 15 | −# define stop_critical_timings() do { } while (0) | |
| 16 | −# define start_critical_timings() do { } while (0) | |
| 17 | − | |
| 18 | −#define raw_local_irq_disable() do { } while (0) | |
| 19 | −#define raw_local_irq_enable() do { } while (0) | |
| 20 | −#define raw_local_irq_save(flags) ((flags) = 0) | |
| 21 | −#define raw_local_irq_restore(flags) ((void)(flags)) | |
| 22 | −#define raw_local_save_flags(flags) ((flags) = 0) | |
| 23 | −#define raw_irqs_disabled_flags(flags) ((void)(flags)) | |
| 24 | −#define raw_irqs_disabled() 0 | |
| 25 | −#define raw_safe_halt() | |
| 26 | − | |
| 27 | −#define local_irq_enable() do { } while (0) | |
| 28 | −#define local_irq_disable() do { } while (0) | |
| 29 | −#define local_irq_save(flags) ((flags) = 0) | |
| 30 | −#define local_irq_restore(flags) ((void)(flags)) | |
| 31 | −#define local_save_flags(flags) ((flags) = 0) | |
| 32 | −#define irqs_disabled() (1) | |
| 33 | −#define irqs_disabled_flags(flags) ((void)(flags), 0) | |
| 34 | −#define safe_halt() do { } while (0) | |
| 35 | − | |
| 36 | −#define trace_lock_release(x, y) | |
| 37 | −#define trace_lock_acquire(a, b, c, d, e, f, g) | |
| 38 | − | |
| 39 | −#endif | |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <assert.h> |
| 8 | 8 | #include <linux/build_bug.h> |
| 9 | 9 | #include <linux/compiler.h> |
| 10 | +#include <linux/math.h> | |
| 10 | 11 | #include <endian.h> |
| 11 | 12 | #include <byteswap.h> |
| 12 | 13 | |
| @@ -14,8 +15,6 @@ · 1 unmodified line | ||
| 14 | 15 | #define UINT_MAX (~0U) |
| 15 | 16 | #endif |
| 16 | 17 | |
| 17 | −#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) | |
| 18 | − | |
| 19 | 18 | #define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1) |
| 20 | 19 | #define __PERF_ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) |
| 21 | 20 | |
| @@ -52,15 +51,6 @@ · 30 unmodified lines | ||
| 52 | 51 | _min1 < _min2 ? _min1 : _min2; }) |
| 53 | 52 | #endif |
| 54 | 53 | |
| 55 | −#ifndef roundup | |
| 56 | −#define roundup(x, y) ( \ | |
| 57 | −{ \ | |
| 58 | − const typeof(y) __y = y; \ | |
| 59 | − (((x) + (__y - 1)) / __y) * __y; \ | |
| 60 | −} \ | |
| 61 | −) | |
| 62 | −#endif | |
| 63 | − | |
| 64 | 54 | #ifndef BUG_ON |
| 65 | 55 | #ifdef NDEBUG |
| 66 | 56 | #define BUG_ON(cond) do { if (cond) {} } while (0) |
| @@ -104,16 +94,6 @@ int scnprintf_pad(char * buf, size_t size, const char * fmt, ...); · 37 unmodified lines | ||
| 104 | 94 | |
| 105 | 95 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) |
| 106 | 96 | |
| 107 | −/* | |
| 108 | − * This looks more complex than it should be. But we need to | |
| 109 | − * get the type for the ~ right in round_down (it needs to be | |
| 110 | − * as wide as the result!), and we want to evaluate the macro | |
| 111 | − * arguments just once each. | |
| 112 | − */ | |
| 113 | −#define __round_mask(x, y) ((__typeof__(x))((y)-1)) | |
| 114 | −#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) | |
| 115 | −#define round_down(x, y) ((x) & ~__round_mask(x, y)) | |
| 116 | − | |
| 117 | 97 | #define current_gfp_context(k) 0 |
| 118 | 98 | #define synchronize_rcu() |
| 119 | 99 | |
| @@ -1,72 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _LIBLOCKDEP_LOCKDEP_H_ | |
| 3 | −#define _LIBLOCKDEP_LOCKDEP_H_ | |
| 4 | − | |
| 5 | −#include <sys/prctl.h> | |
| 6 | −#include <sys/syscall.h> | |
| 7 | −#include <string.h> | |
| 8 | −#include <limits.h> | |
| 9 | −#include <linux/utsname.h> | |
| 10 | −#include <linux/compiler.h> | |
| 11 | −#include <linux/export.h> | |
| 12 | −#include <linux/kern_levels.h> | |
| 13 | −#include <linux/err.h> | |
| 14 | −#include <linux/rcu.h> | |
| 15 | −#include <linux/list.h> | |
| 16 | −#include <linux/hardirq.h> | |
| 17 | −#include <unistd.h> | |
| 18 | − | |
| 19 | −#define MAX_LOCK_DEPTH 63UL | |
| 20 | − | |
| 21 | −#define asmlinkage | |
| 22 | −#define __visible | |
| 23 | − | |
| 24 | −#include "../../../include/linux/lockdep.h" | |
| 25 | − | |
| 26 | −struct task_struct { | |
| 27 | − u64 curr_chain_key; | |
| 28 | − int lockdep_depth; | |
| 29 | − unsigned int lockdep_recursion; | |
| 30 | − struct held_lock held_locks[MAX_LOCK_DEPTH]; | |
| 31 | − gfp_t lockdep_reclaim_gfp; | |
| 32 | − int pid; | |
| 33 | − int state; | |
| 34 | − char comm[17]; | |
| 35 | −}; | |
| 36 | − | |
| 37 | −#define TASK_RUNNING 0 | |
| 38 | − | |
| 39 | −extern struct task_struct *__curr(void); | |
| 40 | − | |
| 41 | −#define current (__curr()) | |
| 42 | − | |
| 43 | −static inline int debug_locks_off(void) | |
| 44 | −{ | |
| 45 | − return 1; | |
| 46 | −} | |
| 47 | − | |
| 48 | −#define task_pid_nr(tsk) ((tsk)->pid) | |
| 49 | − | |
| 50 | −#define KSYM_NAME_LEN 128 | |
| 51 | −#define printk(...) dprintf(STDOUT_FILENO, __VA_ARGS__) | |
| 52 | −#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__) | |
| 53 | −#define pr_warn pr_err | |
| 54 | −#define pr_cont pr_err | |
| 55 | − | |
| 56 | −#define list_del_rcu list_del | |
| 57 | − | |
| 58 | −#define atomic_t unsigned long | |
| 59 | −#define atomic_inc(x) ((*(x))++) | |
| 60 | − | |
| 61 | −#define print_tainted() "" | |
| 62 | −#define static_obj(x) 1 | |
| 63 | − | |
| 64 | −#define debug_show_all_locks() | |
| 65 | −extern void debug_check_no_locks_held(void); | |
| 66 | − | |
| 67 | −static __used bool __is_kernel_percpu_address(unsigned long addr, void *can_addr) | |
| 68 | −{ | |
| 69 | − return false; | |
| 70 | −} | |
| 71 | − | |
| 72 | −#endif | |
| @@ -0,0 +1,25 @@ | ||
| 1 | +#ifndef _TOOLS_MATH_H | |
| 2 | +#define _TOOLS_MATH_H | |
| 3 | + | |
| 4 | +/* | |
| 5 | + * This looks more complex than it should be. But we need to | |
| 6 | + * get the type for the ~ right in round_down (it needs to be | |
| 7 | + * as wide as the result!), and we want to evaluate the macro | |
| 8 | + * arguments just once each. | |
| 9 | + */ | |
| 10 | +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) | |
| 11 | +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) | |
| 12 | +#define round_down(x, y) ((x) & ~__round_mask(x, y)) | |
| 13 | + | |
| 14 | +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) | |
| 15 | + | |
| 16 | +#ifndef roundup | |
| 17 | +#define roundup(x, y) ( \ | |
| 18 | +{ \ | |
| 19 | + const typeof(y) __y = y; \ | |
| 20 | + (((x) + (__y - 1)) / __y) * __y; \ | |
| 21 | +} \ | |
| 22 | +) | |
| 23 | +#endif | |
| 24 | + | |
| 25 | +#endif | |
| @@ -1,4 +0,0 @@ | ||
| 1 | −#ifndef _TOOLS_INCLUDE_LINUX_PROC_FS_H | |
| 2 | −#define _TOOLS_INCLUDE_LINUX_PROC_FS_H | |
| 3 | − | |
| 4 | −#endif /* _TOOLS_INCLUDE_LINUX_PROC_FS_H */ | |
| @@ -37,6 +37,4 @@ static inline bool arch_spin_is_locked(arch_spinlock_t *mutex) · 36 unmodified lines | ||
| 37 | 37 | return true; |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | −#include <linux/lockdep.h> | |
| 41 | − | |
| 42 | 40 | #endif |
| @@ -1,33 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _LIBLOCKDEP_LINUX_STACKTRACE_H_ | |
| 3 | −#define _LIBLOCKDEP_LINUX_STACKTRACE_H_ | |
| 4 | − | |
| 5 | −#include <execinfo.h> | |
| 6 | − | |
| 7 | −struct stack_trace { | |
| 8 | − unsigned int nr_entries, max_entries; | |
| 9 | − unsigned long *entries; | |
| 10 | − int skip; | |
| 11 | −}; | |
| 12 | − | |
| 13 | −static inline void print_stack_trace(struct stack_trace *trace, int spaces) | |
| 14 | −{ | |
| 15 | − backtrace_symbols_fd((void **)trace->entries, trace->nr_entries, 1); | |
| 16 | −} | |
| 17 | − | |
| 18 | −#define save_stack_trace(trace) \ | |
| 19 | − ((trace)->nr_entries = \ | |
| 20 | − backtrace((void **)(trace)->entries, (trace)->max_entries)) | |
| 21 | − | |
| 22 | −static inline int dump_stack(void) | |
| 23 | −{ | |
| 24 | − void *array[64]; | |
| 25 | − size_t size; | |
| 26 | − | |
| 27 | − size = backtrace(array, 64); | |
| 28 | − backtrace_symbols_fd(array, size, 1); | |
| 29 | − | |
| 30 | − return 0; | |
| 31 | −} | |
| 32 | − | |
| 33 | −#endif | |
| @@ -375,6 +375,7 @@ static int read_symbols(struct elf *elf) · 374 unmodified lines | ||
| 375 | 375 | return -1; |
| 376 | 376 | } |
| 377 | 377 | memset(sym, 0, sizeof(*sym)); |
| 378 | + INIT_LIST_HEAD(&sym->pv_target); | |
| 378 | 379 | sym->alias = sym; |
| 379 | 380 | |
| 380 | 381 | sym->idx = i; |
| @@ -153,6 +153,10 @@ void objtool_pv_add(struct objtool_file *f, int idx, struct symbol *func) · 152 unmodified lines | ||
| 153 | 153 | !strcmp(func->name, "_paravirt_ident_64")) |
| 154 | 154 | return; |
| 155 | 155 | |
| 156 | + /* already added this function */ | |
| 157 | + if (!list_empty(&func->pv_target)) | |
| 158 | + return; | |
| 159 | + | |
| 156 | 160 | list_add(&func->pv_target, &f->pv_ops[idx].targets); |
| 157 | 161 | f->pv_ops[idx].clean = false; |
| 158 | 162 | } |
| @@ -271,8 +271,6 @@ endif · 270 unmodified lines | ||
| 271 | 271 | |
| 272 | 272 | FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) |
| 273 | 273 | FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) |
| 274 | −FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) | |
| 275 | −FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) | |
| 276 | 274 | |
| 277 | 275 | FEATURE_CHECK_LDFLAGS-libaio = -lrt |
| 278 | 276 | |
| @@ -528,3 +528,4 @@ · 527 unmodified lines | ||
| 528 | 528 | 446 common landlock_restrict_self sys_landlock_restrict_self |
| 529 | 529 | # 447 reserved for memfd_secret |
| 530 | 530 | 448 common process_mrelease sys_process_mrelease |
| 531 | +449 common futex_waitv sys_futex_waitv | |
| @@ -451,3 +451,4 @@ · 450 unmodified lines | ||
| 451 | 451 | 446 common landlock_restrict_self sys_landlock_restrict_self sys_landlock_restrict_self |
| 452 | 452 | # 447 reserved for memfd_secret |
| 453 | 453 | 448 common process_mrelease sys_process_mrelease sys_process_mrelease |
| 454 | +449 common futex_waitv sys_futex_waitv sys_futex_waitv | |
| @@ -223,8 +223,6 @@ static unsigned int group(pthread_t *pth, · 222 unmodified lines | ||
| 223 | 223 | snd_ctx->out_fds[i] = fds[1]; |
| 224 | 224 | if (!thread_mode) |
| 225 | 225 | close(fds[0]); |
| 226 | − | |
| 227 | − free(ctx); | |
| 228 | 226 | } |
| 229 | 227 | |
| 230 | 228 | /* Now we have all the fds, fork the senders */ |
| @@ -241,8 +239,6 @@ static unsigned int group(pthread_t *pth, · 10 unmodified lines | ||
| 241 | 239 | for (i = 0; i < num_fds; i++) |
| 242 | 240 | close(snd_ctx->out_fds[i]); |
| 243 | 241 | |
| 244 | − free(snd_ctx); | |
| 245 | − | |
| 246 | 242 | /* Return number of children to reap */ |
| 247 | 243 | return num_fds * 2; |
| 248 | 244 | } |
| @@ -820,7 +820,7 @@ static int __cmd_inject(struct perf_inject *inject) · 819 unmodified lines | ||
| 820 | 820 | inject->tool.ordered_events = true; |
| 821 | 821 | inject->tool.ordering_requires_timestamps = true; |
| 822 | 822 | /* Allow space in the header for new attributes */ |
| 823 | − output_data_offset = 4096; | |
| 823 | + output_data_offset = roundup(8192 + session->header.data_offset, 4096); | |
| 824 | 824 | if (inject->strip) |
| 825 | 825 | strip_init(inject); |
| 826 | 826 | } |
| @@ -169,7 +169,9 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u · 168 unmodified lines | ||
| 169 | 169 | TEST_ASSERT_VAL("#num_dies", expr__parse(&num_dies, ctx, "#num_dies") == 0); |
| 170 | 170 | TEST_ASSERT_VAL("#num_cores >= #num_dies", num_cores >= num_dies); |
| 171 | 171 | TEST_ASSERT_VAL("#num_packages", expr__parse(&num_packages, ctx, "#num_packages") == 0); |
| 172 | − TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages); | |
| 172 | + | |
| 173 | + if (num_dies) // Some platforms do not have CPU die support, for example s390 | |
| 174 | + TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages); | |
| 173 | 175 | |
| 174 | 176 | /* |
| 175 | 177 | * Source count returns the number of events aggregating in a leader |
| @@ -109,6 +109,7 @@ static void load_runtime_stat(struct runtime_stat *st, struct evlist *evlist, · 108 unmodified lines | ||
| 109 | 109 | struct evsel *evsel; |
| 110 | 110 | u64 count; |
| 111 | 111 | |
| 112 | + perf_stat__reset_shadow_stats(); | |
| 112 | 113 | evlist__for_each_entry(evlist, evsel) { |
| 113 | 114 | count = find_value(evsel->name, vals); |
| 114 | 115 | perf_stat__update_shadow_stats(evsel, count, 0, st); |
| @@ -1,14 +0,0 @@ | ||
| 1 | −// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | −// Copyright (c) 2021 Facebook | |
| 3 | − | |
| 4 | −#ifndef __BPERF_STAT_H | |
| 5 | −#define __BPERF_STAT_H | |
| 6 | − | |
| 7 | −typedef struct { | |
| 8 | − __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); | |
| 9 | − __uint(key_size, sizeof(__u32)); | |
| 10 | − __uint(value_size, sizeof(struct bpf_perf_event_value)); | |
| 11 | − __uint(max_entries, 1); | |
| 12 | −} reading_map; | |
| 13 | − | |
| 14 | −#endif /* __BPERF_STAT_H */ | |
| @@ -1,14 +1,23 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | // Copyright (c) 2021 Facebook |
| 3 | −#include <linux/bpf.h> | |
| 4 | −#include <linux/perf_event.h> | |
| 3 | +#include "vmlinux.h" | |
| 5 | 4 | #include <bpf/bpf_helpers.h> |
| 6 | 5 | #include <bpf/bpf_tracing.h> |
| 7 | −#include "bperf.h" | |
| 8 | 6 | #include "bperf_u.h" |
| 9 | 7 | |
| 10 | −reading_map diff_readings SEC(".maps"); | |
| 11 | −reading_map accum_readings SEC(".maps"); | |
| 8 | +struct { | |
| 9 | + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); | |
| 10 | + __uint(key_size, sizeof(__u32)); | |
| 11 | + __uint(value_size, sizeof(struct bpf_perf_event_value)); | |
| 12 | + __uint(max_entries, 1); | |
| 13 | +} diff_readings SEC(".maps"); | |
| 14 | + | |
| 15 | +struct { | |
| 16 | + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); | |
| 17 | + __uint(key_size, sizeof(__u32)); | |
| 18 | + __uint(value_size, sizeof(struct bpf_perf_event_value)); | |
| 19 | + __uint(max_entries, 1); | |
| 20 | +} accum_readings SEC(".maps"); | |
| 12 | 21 | |
| 13 | 22 | struct { |
| 14 | 23 | __uint(type, BPF_MAP_TYPE_HASH); |
| @@ -1,10 +1,8 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | // Copyright (c) 2021 Facebook |
| 3 | −#include <linux/bpf.h> | |
| 4 | −#include <linux/perf_event.h> | |
| 3 | +#include "vmlinux.h" | |
| 5 | 4 | #include <bpf/bpf_helpers.h> |
| 6 | 5 | #include <bpf/bpf_tracing.h> |
| 7 | −#include "bperf.h" | |
| 8 | 6 | |
| 9 | 7 | struct { |
| 10 | 8 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| @@ -13,8 +11,19 @@ struct { · 2 unmodified lines | ||
| 13 | 11 | __uint(map_flags, BPF_F_PRESERVE_ELEMS); |
| 14 | 12 | } events SEC(".maps"); |
| 15 | 13 | |
| 16 | −reading_map prev_readings SEC(".maps"); | |
| 17 | −reading_map diff_readings SEC(".maps"); | |
| 14 | +struct { | |
| 15 | + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); | |
| 16 | + __uint(key_size, sizeof(__u32)); | |
| 17 | + __uint(value_size, sizeof(struct bpf_perf_event_value)); | |
| 18 | + __uint(max_entries, 1); | |
| 19 | +} prev_readings SEC(".maps"); | |
| 20 | + | |
| 21 | +struct { | |
| 22 | + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); | |
| 23 | + __uint(key_size, sizeof(__u32)); | |
| 24 | + __uint(value_size, sizeof(struct bpf_perf_event_value)); | |
| 25 | + __uint(max_entries, 1); | |
| 26 | +} diff_readings SEC(".maps"); | |
| 18 | 27 | |
| 19 | 28 | SEC("raw_tp/sched_switch") |
| 20 | 29 | int BPF_PROG(on_switch) |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | 2 | // Copyright (c) 2020 Facebook |
| 3 | −#include <linux/bpf.h> | |
| 3 | +#include "vmlinux.h" | |
| 4 | 4 | #include <bpf/bpf_helpers.h> |
| 5 | 5 | #include <bpf/bpf_tracing.h> |
| 6 | 6 | |
| @@ -44,13 +44,16 @@ struct perf_event_attr; · 43 unmodified lines | ||
| 44 | 44 | /* perf sample has 16 bits size limit */ |
| 45 | 45 | #define PERF_SAMPLE_MAX_SIZE (1 << 16) |
| 46 | 46 | |
| 47 | +/* number of register is bound by the number of bits in regs_dump::mask (64) */ | |
| 48 | +#define PERF_SAMPLE_REGS_CACHE_SIZE (8 * sizeof(u64)) | |
| 49 | + | |
| 47 | 50 | struct regs_dump { |
| 48 | 51 | u64 abi; |
| 49 | 52 | u64 mask; |
| 50 | 53 | u64 *regs; |
| 51 | 54 | |
| 52 | 55 | /* Cached values/mask filled by first register access. */ |
| 53 | − u64 cache_regs[PERF_REGS_MAX]; | |
| 56 | + u64 cache_regs[PERF_SAMPLE_REGS_CACHE_SIZE]; | |
| 54 | 57 | u64 cache_mask; |
| 55 | 58 | }; |
| 56 | 59 | |
| @@ -2321,6 +2321,7 @@ out: · 2320 unmodified lines | ||
| 2321 | 2321 | #define FEAT_PROCESS_STR_FUN(__feat, __feat_env) \ |
| 2322 | 2322 | static int process_##__feat(struct feat_fd *ff, void *data __maybe_unused) \ |
| 2323 | 2323 | {\ |
| 2324 | + free(ff->ph->env.__feat_env); \ | |
| 2324 | 2325 | ff->ph->env.__feat_env = do_read_string(ff); \ |
| 2325 | 2326 | return ff->ph->env.__feat_env ? 0 : -ENOMEM; \ |
| 2326 | 2327 | } |
| @@ -4124,6 +4125,7 @@ int perf_event__process_feature(struct perf_session *session, · 1797 unmodified lines | ||
| 4124 | 4125 | struct perf_record_header_feature *fe = (struct perf_record_header_feature *)event; |
| 4125 | 4126 | int type = fe->header.type; |
| 4126 | 4127 | u64 feat = fe->feat_id; |
| 4128 | + int ret = 0; | |
| 4127 | 4129 | |
| 4128 | 4130 | if (type < 0 || type >= PERF_RECORD_HEADER_MAX) { |
| 4129 | 4131 | pr_warning("invalid record type %d in pipe-mode\n", type); |
| @@ -4141,11 +4143,13 @@ int perf_event__process_feature(struct perf_session *session, · 11 unmodified lines | ||
| 4141 | 4143 | ff.size = event->header.size - sizeof(*fe); |
| 4142 | 4144 | ff.ph = &session->header; |
| 4143 | 4145 | |
| 4144 | − if (feat_ops[feat].process(&ff, NULL)) | |
| 4145 | − return -1; | |
| 4146 | + if (feat_ops[feat].process(&ff, NULL)) { | |
| 4147 | + ret = -1; | |
| 4148 | + goto out; | |
| 4149 | + } | |
| 4146 | 4150 | |
| 4147 | 4151 | if (!feat_ops[feat].print || !tool->show_feat_hdr) |
| 4148 | − return 0; | |
| 4152 | + goto out; | |
| 4149 | 4153 | |
| 4150 | 4154 | if (!feat_ops[feat].full_only || |
| 4151 | 4155 | tool->show_feat_hdr >= SHOW_FEAT_HEADER_FULL_INFO) { |
| @@ -4154,8 +4158,9 @@ int perf_event__process_feature(struct perf_session *session, · 2 unmodified lines | ||
| 4154 | 4158 | fprintf(stdout, "# %s info available, use -I to display\n", |
| 4155 | 4159 | feat_ops[feat].name); |
| 4156 | 4160 | } |
| 4157 | − | |
| 4158 | − return 0; | |
| 4161 | +out: | |
| 4162 | + free_event_desc(ff.events); | |
| 4163 | + return ret; | |
| 4159 | 4164 | } |
| 4160 | 4165 | |
| 4161 | 4166 | size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp) |
| @@ -1205,61 +1205,69 @@ out_no_progress: · 1204 unmodified lines | ||
| 1205 | 1205 | |
| 1206 | 1206 | static bool intel_pt_fup_event(struct intel_pt_decoder *decoder) |
| 1207 | 1207 | { |
| 1208 | + enum intel_pt_sample_type type = decoder->state.type; | |
| 1208 | 1209 | bool ret = false; |
| 1209 | 1210 | |
| 1211 | + decoder->state.type &= ~INTEL_PT_BRANCH; | |
| 1212 | + | |
| 1210 | 1213 | if (decoder->set_fup_tx_flags) { |
| 1211 | 1214 | decoder->set_fup_tx_flags = false; |
| 1212 | 1215 | decoder->tx_flags = decoder->fup_tx_flags; |
| 1213 | − decoder->state.type = INTEL_PT_TRANSACTION; | |
| 1216 | + decoder->state.type |= INTEL_PT_TRANSACTION; | |
| 1214 | 1217 | if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX) |
| 1215 | 1218 | decoder->state.type |= INTEL_PT_BRANCH; |
| 1216 | − decoder->state.from_ip = decoder->ip; | |
| 1217 | − decoder->state.to_ip = 0; | |
| 1218 | 1219 | decoder->state.flags = decoder->fup_tx_flags; |
| 1219 | − return true; | |
| 1220 | + ret = true; | |
| 1220 | 1221 | } |
| 1221 | 1222 | if (decoder->set_fup_ptw) { |
| 1222 | 1223 | decoder->set_fup_ptw = false; |
| 1223 | − decoder->state.type = INTEL_PT_PTW; | |
| 1224 | + decoder->state.type |= INTEL_PT_PTW; | |
| 1224 | 1225 | decoder->state.flags |= INTEL_PT_FUP_IP; |
| 1225 | − decoder->state.from_ip = decoder->ip; | |
| 1226 | − decoder->state.to_ip = 0; | |
| 1227 | 1226 | decoder->state.ptw_payload = decoder->fup_ptw_payload; |
| 1228 | − return true; | |
| 1227 | + ret = true; | |
| 1229 | 1228 | } |
| 1230 | 1229 | if (decoder->set_fup_mwait) { |
| 1231 | 1230 | decoder->set_fup_mwait = false; |
| 1232 | − decoder->state.type = INTEL_PT_MWAIT_OP; | |
| 1233 | − decoder->state.from_ip = decoder->ip; | |
| 1234 | − decoder->state.to_ip = 0; | |
| 1231 | + decoder->state.type |= INTEL_PT_MWAIT_OP; | |
| 1235 | 1232 | decoder->state.mwait_payload = decoder->fup_mwait_payload; |
| 1236 | 1233 | ret = true; |
| 1237 | 1234 | } |
| 1238 | 1235 | if (decoder->set_fup_pwre) { |
| 1239 | 1236 | decoder->set_fup_pwre = false; |
| 1240 | 1237 | decoder->state.type |= INTEL_PT_PWR_ENTRY; |
| 1241 | − decoder->state.type &= ~INTEL_PT_BRANCH; | |
| 1242 | − decoder->state.from_ip = decoder->ip; | |
| 1243 | − decoder->state.to_ip = 0; | |
| 1244 | 1238 | decoder->state.pwre_payload = decoder->fup_pwre_payload; |
| 1245 | 1239 | ret = true; |
| 1246 | 1240 | } |
| 1247 | 1241 | if (decoder->set_fup_exstop) { |
| 1248 | 1242 | decoder->set_fup_exstop = false; |
| 1249 | 1243 | decoder->state.type |= INTEL_PT_EX_STOP; |
| 1250 | − decoder->state.type &= ~INTEL_PT_BRANCH; | |
| 1251 | 1244 | decoder->state.flags |= INTEL_PT_FUP_IP; |
| 1252 | − decoder->state.from_ip = decoder->ip; | |
| 1253 | − decoder->state.to_ip = 0; | |
| 1254 | 1245 | ret = true; |
| 1255 | 1246 | } |
| 1256 | 1247 | if (decoder->set_fup_bep) { |
| 1257 | 1248 | decoder->set_fup_bep = false; |
| 1258 | 1249 | decoder->state.type |= INTEL_PT_BLK_ITEMS; |
| 1259 | − decoder->state.type &= ~INTEL_PT_BRANCH; | |
| 1250 | + ret = true; | |
| 1251 | + } | |
| 1252 | + if (decoder->overflow) { | |
| 1253 | + decoder->overflow = false; | |
| 1254 | + if (!ret && !decoder->pge) { | |
| 1255 | + if (decoder->hop) { | |
| 1256 | + decoder->state.type = 0; | |
| 1257 | + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; | |
| 1258 | + } | |
| 1259 | + decoder->pge = true; | |
| 1260 | + decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN; | |
| 1261 | + decoder->state.from_ip = 0; | |
| 1262 | + decoder->state.to_ip = decoder->ip; | |
| 1263 | + return true; | |
| 1264 | + } | |
| 1265 | + } | |
| 1266 | + if (ret) { | |
| 1260 | 1267 | decoder->state.from_ip = decoder->ip; |
| 1261 | 1268 | decoder->state.to_ip = 0; |
| 1262 | − ret = true; | |
| 1269 | + } else { | |
| 1270 | + decoder->state.type = type; | |
| 1263 | 1271 | } |
| 1264 | 1272 | return ret; |
| 1265 | 1273 | } |
| @@ -1608,7 +1616,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder) · 342 unmodified lines | ||
| 1608 | 1616 | intel_pt_clear_tx_flags(decoder); |
| 1609 | 1617 | intel_pt_set_nr(decoder); |
| 1610 | 1618 | decoder->timestamp_insn_cnt = 0; |
| 1611 | − decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; | |
| 1619 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; | |
| 1620 | + decoder->state.from_ip = decoder->ip; | |
| 1621 | + decoder->ip = 0; | |
| 1622 | + decoder->pge = false; | |
| 1623 | + decoder->set_fup_tx_flags = false; | |
| 1624 | + decoder->set_fup_ptw = false; | |
| 1625 | + decoder->set_fup_mwait = false; | |
| 1626 | + decoder->set_fup_pwre = false; | |
| 1627 | + decoder->set_fup_exstop = false; | |
| 1628 | + decoder->set_fup_bep = false; | |
| 1612 | 1629 | decoder->overflow = true; |
| 1613 | 1630 | return -EOVERFLOW; |
| 1614 | 1631 | } |
| @@ -2666,6 +2683,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder); · 1051 unmodified lines | ||
| 2666 | 2683 | /* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */ |
| 2667 | 2684 | static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err) |
| 2668 | 2685 | { |
| 2686 | + *err = 0; | |
| 2687 | + | |
| 2669 | 2688 | /* Leap from PSB to PSB, getting ip from FUP within PSB+ */ |
| 2670 | 2689 | if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) { |
| 2671 | 2690 | *err = intel_pt_scan_for_psb(decoder); |
| @@ -2678,6 +2697,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in · 6 unmodified lines | ||
| 2678 | 2697 | return HOP_IGNORE; |
| 2679 | 2698 | |
| 2680 | 2699 | case INTEL_PT_TIP_PGD: |
| 2700 | + decoder->pge = false; | |
| 2681 | 2701 | if (!decoder->packet.count) { |
| 2682 | 2702 | intel_pt_set_nr(decoder); |
| 2683 | 2703 | return HOP_IGNORE; |
| @@ -2705,18 +2725,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in · 21 unmodified lines | ||
| 2705 | 2725 | if (!decoder->packet.count) |
| 2706 | 2726 | return HOP_IGNORE; |
| 2707 | 2727 | intel_pt_set_ip(decoder); |
| 2708 | − if (intel_pt_fup_event(decoder)) | |
| 2709 | − return HOP_RETURN; | |
| 2710 | − if (!decoder->branch_enable) | |
| 2728 | + if (decoder->set_fup_mwait || decoder->set_fup_pwre) | |
| 2729 | + *no_tip = true; | |
| 2730 | + if (!decoder->branch_enable || !decoder->pge) | |
| 2711 | 2731 | *no_tip = true; |
| 2712 | 2732 | if (*no_tip) { |
| 2713 | 2733 | decoder->state.type = INTEL_PT_INSTRUCTION; |
| 2714 | 2734 | decoder->state.from_ip = decoder->ip; |
| 2715 | 2735 | decoder->state.to_ip = 0; |
| 2736 | + intel_pt_fup_event(decoder); | |
| 2716 | 2737 | return HOP_RETURN; |
| 2717 | 2738 | } |
| 2739 | + intel_pt_fup_event(decoder); | |
| 2740 | + decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH; | |
| 2718 | 2741 | *err = intel_pt_walk_fup_tip(decoder); |
| 2719 | − if (!*err) | |
| 2742 | + if (!*err && decoder->state.to_ip) | |
| 2720 | 2743 | decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
| 2721 | 2744 | return HOP_RETURN; |
| 2722 | 2745 | |
| @@ -2897,7 +2920,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err) · 174 unmodified lines | ||
| 2897 | 2920 | { |
| 2898 | 2921 | struct intel_pt_psb_info data = { .fup = false }; |
| 2899 | 2922 | |
| 2900 | − if (!decoder->branch_enable || !decoder->pge) | |
| 2923 | + if (!decoder->branch_enable) | |
| 2901 | 2924 | return false; |
| 2902 | 2925 | |
| 2903 | 2926 | intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data); |
| @@ -2924,6 +2947,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder) · 20 unmodified lines | ||
| 2924 | 2947 | if (err) |
| 2925 | 2948 | return err; |
| 2926 | 2949 | next: |
| 2950 | + err = 0; | |
| 2927 | 2951 | if (decoder->cyc_threshold) { |
| 2928 | 2952 | if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC) |
| 2929 | 2953 | decoder->sample_cyc = false; |
| @@ -2962,6 +2986,7 @@ next: · 32 unmodified lines | ||
| 2962 | 2986 | |
| 2963 | 2987 | case INTEL_PT_TIP_PGE: { |
| 2964 | 2988 | decoder->pge = true; |
| 2989 | + decoder->overflow = false; | |
| 2965 | 2990 | intel_pt_mtc_cyc_cnt_pge(decoder); |
| 2966 | 2991 | intel_pt_set_nr(decoder); |
| 2967 | 2992 | if (decoder->packet.count == 0) { |
| @@ -2999,7 +3024,7 @@ next: · 31 unmodified lines | ||
| 2999 | 3024 | break; |
| 3000 | 3025 | } |
| 3001 | 3026 | intel_pt_set_last_ip(decoder); |
| 3002 | − if (!decoder->branch_enable) { | |
| 3027 | + if (!decoder->branch_enable || !decoder->pge) { | |
| 3003 | 3028 | decoder->ip = decoder->last_ip; |
| 3004 | 3029 | if (intel_pt_fup_event(decoder)) |
| 3005 | 3030 | return 0; |
| @@ -3467,10 +3492,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) · 461 unmodified lines | ||
| 3467 | 3492 | decoder->set_fup_pwre = false; |
| 3468 | 3493 | decoder->set_fup_exstop = false; |
| 3469 | 3494 | decoder->set_fup_bep = false; |
| 3495 | + decoder->overflow = false; | |
| 3470 | 3496 | |
| 3471 | 3497 | if (!decoder->branch_enable) { |
| 3472 | 3498 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
| 3473 | − decoder->overflow = false; | |
| 3474 | 3499 | decoder->state.type = 0; /* Do not have a sample */ |
| 3475 | 3500 | return 0; |
| 3476 | 3501 | } |
| @@ -3485,7 +3510,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder) · 8 unmodified lines | ||
| 3485 | 3510 | decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; |
| 3486 | 3511 | else |
| 3487 | 3512 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; |
| 3488 | − decoder->overflow = false; | |
| 3489 | 3513 | |
| 3490 | 3514 | decoder->state.from_ip = 0; |
| 3491 | 3515 | decoder->state.to_ip = decoder->ip; |
| @@ -3607,7 +3631,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder) · 115 unmodified lines | ||
| 3607 | 3631 | } |
| 3608 | 3632 | |
| 3609 | 3633 | decoder->have_last_ip = true; |
| 3610 | − decoder->pkt_state = INTEL_PT_STATE_NO_IP; | |
| 3634 | + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; | |
| 3611 | 3635 | |
| 3612 | 3636 | err = intel_pt_walk_psb(decoder); |
| 3613 | 3637 | if (err) |
| @@ -3704,7 +3728,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) · 90 unmodified lines | ||
| 3704 | 3728 | |
| 3705 | 3729 | if (err) { |
| 3706 | 3730 | decoder->state.err = intel_pt_ext_err(err); |
| 3707 | − decoder->state.from_ip = decoder->ip; | |
| 3731 | + if (err != -EOVERFLOW) | |
| 3732 | + decoder->state.from_ip = decoder->ip; | |
| 3708 | 3733 | intel_pt_update_sample_time(decoder); |
| 3709 | 3734 | decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; |
| 3710 | 3735 | intel_pt_set_nr(decoder); |
| @@ -2565,6 +2565,7 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) · 2564 unmodified lines | ||
| 2565 | 2565 | ptq->sync_switch = false; |
| 2566 | 2566 | intel_pt_next_tid(pt, ptq); |
| 2567 | 2567 | } |
| 2568 | + ptq->timestamp = state->est_timestamp; | |
| 2568 | 2569 | if (pt->synth_opts.errors) { |
| 2569 | 2570 | err = intel_ptq_synth_error(ptq, state); |
| 2570 | 2571 | if (err) |
| @@ -25,6 +25,9 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) · 24 unmodified lines | ||
| 25 | 25 | int i, idx = 0; |
| 26 | 26 | u64 mask = regs->mask; |
| 27 | 27 | |
| 28 | + if ((u64)id >= PERF_SAMPLE_REGS_CACHE_SIZE) | |
| 29 | + return -EINVAL; | |
| 30 | + | |
| 28 | 31 | if (regs->cache_mask & (1ULL << id)) |
| 29 | 32 | goto out; |
| 30 | 33 | |
| @@ -461,7 +461,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) · 460 unmodified lines | ||
| 461 | 461 | struct tep_event *tp_format; |
| 462 | 462 | |
| 463 | 463 | tp_format = trace_event__tp_format_id(evsel->core.attr.config); |
| 464 | − if (!tp_format) | |
| 464 | + if (IS_ERR_OR_NULL(tp_format)) | |
| 465 | 465 | return NULL; |
| 466 | 466 | |
| 467 | 467 | evsel->tp_format = tp_format; |
| @@ -15,7 +15,7 @@ int smt_on(void) · 14 unmodified lines | ||
| 15 | 15 | if (cached) |
| 16 | 16 | return cached_result; |
| 17 | 17 | |
| 18 | − if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) > 0) | |
| 18 | + if (sysfs__read_int("devices/system/cpu/smt/active", &cached_result) >= 0) | |
| 19 | 19 | goto done; |
| 20 | 20 | |
| 21 | 21 | ncpu = sysconf(_SC_NPROCESSORS_CONF); |
| @@ -69,6 +69,7 @@ KERNEL_INCLUDE := $(OUTPUT)include · 68 unmodified lines | ||
| 69 | 69 | ACPICA_INCLUDE := $(srctree)/../../../drivers/acpi/acpica |
| 70 | 70 | CFLAGS += -D_LINUX -I$(KERNEL_INCLUDE) -I$(ACPICA_INCLUDE) |
| 71 | 71 | CFLAGS += $(WARNINGS) |
| 72 | +MKDIR = mkdir | |
| 72 | 73 | |
| 73 | 74 | ifeq ($(strip $(V)),false) |
| 74 | 75 | QUIET=@ |
| @@ -21,6 +21,7 @@ $(KERNEL_INCLUDE): · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | $(objdir)%.o: %.c $(KERNEL_INCLUDE) |
| 23 | 23 | $(ECHO) " CC " $(subst $(OUTPUT),,$@) |
| 24 | + $(QUIET) $(MKDIR) -p $(objdir) 2>/dev/null | |
| 24 | 25 | $(QUIET) $(CC) -c $(CFLAGS) -o $@ $< |
| 25 | 26 | |
| 26 | 27 | all: $(OUTPUT)$(TOOL) |
| @@ -1,5 +1,8 @@ | ||
| 1 | 1 | #ifndef _LINUX_LOCKDEP_H |
| 2 | 2 | #define _LINUX_LOCKDEP_H |
| 3 | + | |
| 4 | +#include <linux/spinlock.h> | |
| 5 | + | |
| 3 | 6 | struct lock_class_key { |
| 4 | 7 | unsigned int a; |
| 5 | 8 | }; |
| @@ -35,7 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | .prog_type = BPF_PROG_TYPE_XDP, |
| 36 | 36 | }, |
| 37 | 37 | { |
| 38 | − "XDP pkt read, pkt_data' > pkt_end, good access", | |
| 38 | + "XDP pkt read, pkt_data' > pkt_end, corner case, good access", | |
| 39 | 39 | .insns = { |
| 40 | 40 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 41 | 41 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| @@ -87,6 +87,41 @@ · 45 unmodified lines | ||
| 87 | 87 | .prog_type = BPF_PROG_TYPE_XDP, |
| 88 | 88 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 89 | 89 | }, |
| 90 | +{ | |
| 91 | + "XDP pkt read, pkt_data' > pkt_end, corner case +1, good access", | |
| 92 | + .insns = { | |
| 93 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 94 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 95 | + offsetof(struct xdp_md, data_end)), | |
| 96 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 97 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 98 | + BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), | |
| 99 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 100 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 101 | + BPF_EXIT_INSN(), | |
| 102 | + }, | |
| 103 | + .result = ACCEPT, | |
| 104 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 105 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 106 | +}, | |
| 107 | +{ | |
| 108 | + "XDP pkt read, pkt_data' > pkt_end, corner case -1, bad access", | |
| 109 | + .insns = { | |
| 110 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 111 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 112 | + offsetof(struct xdp_md, data_end)), | |
| 113 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 114 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 115 | + BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), | |
| 116 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 117 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 118 | + BPF_EXIT_INSN(), | |
| 119 | + }, | |
| 120 | + .errstr = "R1 offset is outside of the packet", | |
| 121 | + .result = REJECT, | |
| 122 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 123 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 124 | +}, | |
| 90 | 125 | { |
| 91 | 126 | "XDP pkt read, pkt_end > pkt_data', good access", |
| 92 | 127 | .insns = { |
| @@ -106,16 +141,16 @@ · 13 unmodified lines | ||
| 106 | 141 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 107 | 142 | }, |
| 108 | 143 | { |
| 109 | − "XDP pkt read, pkt_end > pkt_data', bad access 1", | |
| 144 | + "XDP pkt read, pkt_end > pkt_data', corner case -1, bad access", | |
| 110 | 145 | .insns = { |
| 111 | 146 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 112 | 147 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| 113 | 148 | offsetof(struct xdp_md, data_end)), |
| 114 | 149 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 115 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 150 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 116 | 151 | BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), |
| 117 | 152 | BPF_JMP_IMM(BPF_JA, 0, 0, 1), |
| 118 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 153 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 119 | 154 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 120 | 155 | BPF_EXIT_INSN(), |
| 121 | 156 | }, |
| @@ -142,6 +177,42 @@ · 20 unmodified lines | ||
| 142 | 177 | .prog_type = BPF_PROG_TYPE_XDP, |
| 143 | 178 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 144 | 179 | }, |
| 180 | +{ | |
| 181 | + "XDP pkt read, pkt_end > pkt_data', corner case, good access", | |
| 182 | + .insns = { | |
| 183 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 184 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 185 | + offsetof(struct xdp_md, data_end)), | |
| 186 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 187 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 188 | + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), | |
| 189 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 190 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 191 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 192 | + BPF_EXIT_INSN(), | |
| 193 | + }, | |
| 194 | + .result = ACCEPT, | |
| 195 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 196 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 197 | +}, | |
| 198 | +{ | |
| 199 | + "XDP pkt read, pkt_end > pkt_data', corner case +1, good access", | |
| 200 | + .insns = { | |
| 201 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 202 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 203 | + offsetof(struct xdp_md, data_end)), | |
| 204 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 205 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 206 | + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), | |
| 207 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 208 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 209 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 210 | + BPF_EXIT_INSN(), | |
| 211 | + }, | |
| 212 | + .result = ACCEPT, | |
| 213 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 214 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 215 | +}, | |
| 145 | 216 | { |
| 146 | 217 | "XDP pkt read, pkt_data' < pkt_end, good access", |
| 147 | 218 | .insns = { |
| @@ -161,16 +232,16 @@ · 13 unmodified lines | ||
| 161 | 232 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 162 | 233 | }, |
| 163 | 234 | { |
| 164 | − "XDP pkt read, pkt_data' < pkt_end, bad access 1", | |
| 235 | + "XDP pkt read, pkt_data' < pkt_end, corner case -1, bad access", | |
| 165 | 236 | .insns = { |
| 166 | 237 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 167 | 238 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| 168 | 239 | offsetof(struct xdp_md, data_end)), |
| 169 | 240 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 170 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 241 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 171 | 242 | BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), |
| 172 | 243 | BPF_JMP_IMM(BPF_JA, 0, 0, 1), |
| 173 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 244 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 174 | 245 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 175 | 246 | BPF_EXIT_INSN(), |
| 176 | 247 | }, |
| @@ -198,7 +269,43 @@ · 21 unmodified lines | ||
| 198 | 269 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 199 | 270 | }, |
| 200 | 271 | { |
| 201 | − "XDP pkt read, pkt_end < pkt_data', good access", | |
| 272 | + "XDP pkt read, pkt_data' < pkt_end, corner case, good access", | |
| 273 | + .insns = { | |
| 274 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 275 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 276 | + offsetof(struct xdp_md, data_end)), | |
| 277 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 278 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 279 | + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), | |
| 280 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 281 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 282 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 283 | + BPF_EXIT_INSN(), | |
| 284 | + }, | |
| 285 | + .result = ACCEPT, | |
| 286 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 287 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 288 | +}, | |
| 289 | +{ | |
| 290 | + "XDP pkt read, pkt_data' < pkt_end, corner case +1, good access", | |
| 291 | + .insns = { | |
| 292 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 293 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 294 | + offsetof(struct xdp_md, data_end)), | |
| 295 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 296 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 297 | + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), | |
| 298 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 299 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 300 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 301 | + BPF_EXIT_INSN(), | |
| 302 | + }, | |
| 303 | + .result = ACCEPT, | |
| 304 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 305 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 306 | +}, | |
| 307 | +{ | |
| 308 | + "XDP pkt read, pkt_end < pkt_data', corner case, good access", | |
| 202 | 309 | .insns = { |
| 203 | 310 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 204 | 311 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| @@ -250,6 +357,41 @@ · 45 unmodified lines | ||
| 250 | 357 | .prog_type = BPF_PROG_TYPE_XDP, |
| 251 | 358 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 252 | 359 | }, |
| 360 | +{ | |
| 361 | + "XDP pkt read, pkt_end < pkt_data', corner case +1, good access", | |
| 362 | + .insns = { | |
| 363 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 364 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 365 | + offsetof(struct xdp_md, data_end)), | |
| 366 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 367 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 368 | + BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), | |
| 369 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 370 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 371 | + BPF_EXIT_INSN(), | |
| 372 | + }, | |
| 373 | + .result = ACCEPT, | |
| 374 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 375 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 376 | +}, | |
| 377 | +{ | |
| 378 | + "XDP pkt read, pkt_end < pkt_data', corner case -1, bad access", | |
| 379 | + .insns = { | |
| 380 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 381 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 382 | + offsetof(struct xdp_md, data_end)), | |
| 383 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 384 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 385 | + BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), | |
| 386 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 387 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 388 | + BPF_EXIT_INSN(), | |
| 389 | + }, | |
| 390 | + .errstr = "R1 offset is outside of the packet", | |
| 391 | + .result = REJECT, | |
| 392 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 393 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 394 | +}, | |
| 253 | 395 | { |
| 254 | 396 | "XDP pkt read, pkt_data' >= pkt_end, good access", |
| 255 | 397 | .insns = { |
| @@ -268,15 +410,15 @@ · 12 unmodified lines | ||
| 268 | 410 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 269 | 411 | }, |
| 270 | 412 | { |
| 271 | − "XDP pkt read, pkt_data' >= pkt_end, bad access 1", | |
| 413 | + "XDP pkt read, pkt_data' >= pkt_end, corner case -1, bad access", | |
| 272 | 414 | .insns = { |
| 273 | 415 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 274 | 416 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| 275 | 417 | offsetof(struct xdp_md, data_end)), |
| 276 | 418 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 277 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 419 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 278 | 420 | BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), |
| 279 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 421 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 280 | 422 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 281 | 423 | BPF_EXIT_INSN(), |
| 282 | 424 | }, |
| @@ -304,7 +446,41 @@ · 21 unmodified lines | ||
| 304 | 446 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 305 | 447 | }, |
| 306 | 448 | { |
| 307 | − "XDP pkt read, pkt_end >= pkt_data', good access", | |
| 449 | + "XDP pkt read, pkt_data' >= pkt_end, corner case, good access", | |
| 450 | + .insns = { | |
| 451 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 452 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 453 | + offsetof(struct xdp_md, data_end)), | |
| 454 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 455 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 456 | + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), | |
| 457 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 458 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 459 | + BPF_EXIT_INSN(), | |
| 460 | + }, | |
| 461 | + .result = ACCEPT, | |
| 462 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 463 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 464 | +}, | |
| 465 | +{ | |
| 466 | + "XDP pkt read, pkt_data' >= pkt_end, corner case +1, good access", | |
| 467 | + .insns = { | |
| 468 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 469 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 470 | + offsetof(struct xdp_md, data_end)), | |
| 471 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 472 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 473 | + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), | |
| 474 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 475 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 476 | + BPF_EXIT_INSN(), | |
| 477 | + }, | |
| 478 | + .result = ACCEPT, | |
| 479 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 480 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 481 | +}, | |
| 482 | +{ | |
| 483 | + "XDP pkt read, pkt_end >= pkt_data', corner case, good access", | |
| 308 | 484 | .insns = { |
| 309 | 485 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 310 | 486 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| @@ -359,7 +535,44 @@ · 48 unmodified lines | ||
| 359 | 535 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 360 | 536 | }, |
| 361 | 537 | { |
| 362 | − "XDP pkt read, pkt_data' <= pkt_end, good access", | |
| 538 | + "XDP pkt read, pkt_end >= pkt_data', corner case +1, good access", | |
| 539 | + .insns = { | |
| 540 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 541 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 542 | + offsetof(struct xdp_md, data_end)), | |
| 543 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 544 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 545 | + BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), | |
| 546 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 547 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 548 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 549 | + BPF_EXIT_INSN(), | |
| 550 | + }, | |
| 551 | + .result = ACCEPT, | |
| 552 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 553 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 554 | +}, | |
| 555 | +{ | |
| 556 | + "XDP pkt read, pkt_end >= pkt_data', corner case -1, bad access", | |
| 557 | + .insns = { | |
| 558 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 559 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 560 | + offsetof(struct xdp_md, data_end)), | |
| 561 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 562 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 563 | + BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), | |
| 564 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 565 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 566 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 567 | + BPF_EXIT_INSN(), | |
| 568 | + }, | |
| 569 | + .errstr = "R1 offset is outside of the packet", | |
| 570 | + .result = REJECT, | |
| 571 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 572 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 573 | +}, | |
| 574 | +{ | |
| 575 | + "XDP pkt read, pkt_data' <= pkt_end, corner case, good access", | |
| 363 | 576 | .insns = { |
| 364 | 577 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 365 | 578 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| @@ -413,6 +626,43 @@ · 47 unmodified lines | ||
| 413 | 626 | .prog_type = BPF_PROG_TYPE_XDP, |
| 414 | 627 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 415 | 628 | }, |
| 629 | +{ | |
| 630 | + "XDP pkt read, pkt_data' <= pkt_end, corner case +1, good access", | |
| 631 | + .insns = { | |
| 632 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 633 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 634 | + offsetof(struct xdp_md, data_end)), | |
| 635 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 636 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 637 | + BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), | |
| 638 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 639 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 640 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 641 | + BPF_EXIT_INSN(), | |
| 642 | + }, | |
| 643 | + .result = ACCEPT, | |
| 644 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 645 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 646 | +}, | |
| 647 | +{ | |
| 648 | + "XDP pkt read, pkt_data' <= pkt_end, corner case -1, bad access", | |
| 649 | + .insns = { | |
| 650 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 651 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 652 | + offsetof(struct xdp_md, data_end)), | |
| 653 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 654 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 655 | + BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), | |
| 656 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 657 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 658 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 659 | + BPF_EXIT_INSN(), | |
| 660 | + }, | |
| 661 | + .errstr = "R1 offset is outside of the packet", | |
| 662 | + .result = REJECT, | |
| 663 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 664 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 665 | +}, | |
| 416 | 666 | { |
| 417 | 667 | "XDP pkt read, pkt_end <= pkt_data', good access", |
| 418 | 668 | .insns = { |
| @@ -431,15 +681,15 @@ · 12 unmodified lines | ||
| 431 | 681 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 432 | 682 | }, |
| 433 | 683 | { |
| 434 | − "XDP pkt read, pkt_end <= pkt_data', bad access 1", | |
| 684 | + "XDP pkt read, pkt_end <= pkt_data', corner case -1, bad access", | |
| 435 | 685 | .insns = { |
| 436 | 686 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 437 | 687 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, |
| 438 | 688 | offsetof(struct xdp_md, data_end)), |
| 439 | 689 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 440 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 690 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 441 | 691 | BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), |
| 442 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 692 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 443 | 693 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 444 | 694 | BPF_EXIT_INSN(), |
| 445 | 695 | }, |
| @@ -467,7 +717,41 @@ · 21 unmodified lines | ||
| 467 | 717 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 468 | 718 | }, |
| 469 | 719 | { |
| 470 | − "XDP pkt read, pkt_meta' > pkt_data, good access", | |
| 720 | + "XDP pkt read, pkt_end <= pkt_data', corner case, good access", | |
| 721 | + .insns = { | |
| 722 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 723 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 724 | + offsetof(struct xdp_md, data_end)), | |
| 725 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 726 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 727 | + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), | |
| 728 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 729 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 730 | + BPF_EXIT_INSN(), | |
| 731 | + }, | |
| 732 | + .result = ACCEPT, | |
| 733 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 734 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 735 | +}, | |
| 736 | +{ | |
| 737 | + "XDP pkt read, pkt_end <= pkt_data', corner case +1, good access", | |
| 738 | + .insns = { | |
| 739 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 740 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, | |
| 741 | + offsetof(struct xdp_md, data_end)), | |
| 742 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 743 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 744 | + BPF_JMP_REG(BPF_JLE, BPF_REG_3, BPF_REG_1, 1), | |
| 745 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 746 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 747 | + BPF_EXIT_INSN(), | |
| 748 | + }, | |
| 749 | + .result = ACCEPT, | |
| 750 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 751 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 752 | +}, | |
| 753 | +{ | |
| 754 | + "XDP pkt read, pkt_meta' > pkt_data, corner case, good access", | |
| 471 | 755 | .insns = { |
| 472 | 756 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 473 | 757 | offsetof(struct xdp_md, data_meta)), |
| @@ -519,6 +803,41 @@ · 45 unmodified lines | ||
| 519 | 803 | .prog_type = BPF_PROG_TYPE_XDP, |
| 520 | 804 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 521 | 805 | }, |
| 806 | +{ | |
| 807 | + "XDP pkt read, pkt_meta' > pkt_data, corner case +1, good access", | |
| 808 | + .insns = { | |
| 809 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 810 | + offsetof(struct xdp_md, data_meta)), | |
| 811 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 812 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 813 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 814 | + BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), | |
| 815 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 816 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 817 | + BPF_EXIT_INSN(), | |
| 818 | + }, | |
| 819 | + .result = ACCEPT, | |
| 820 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 821 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 822 | +}, | |
| 823 | +{ | |
| 824 | + "XDP pkt read, pkt_meta' > pkt_data, corner case -1, bad access", | |
| 825 | + .insns = { | |
| 826 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 827 | + offsetof(struct xdp_md, data_meta)), | |
| 828 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 829 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 830 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 831 | + BPF_JMP_REG(BPF_JGT, BPF_REG_1, BPF_REG_3, 1), | |
| 832 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 833 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 834 | + BPF_EXIT_INSN(), | |
| 835 | + }, | |
| 836 | + .errstr = "R1 offset is outside of the packet", | |
| 837 | + .result = REJECT, | |
| 838 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 839 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 840 | +}, | |
| 522 | 841 | { |
| 523 | 842 | "XDP pkt read, pkt_data > pkt_meta', good access", |
| 524 | 843 | .insns = { |
| @@ -538,16 +857,16 @@ · 13 unmodified lines | ||
| 538 | 857 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 539 | 858 | }, |
| 540 | 859 | { |
| 541 | − "XDP pkt read, pkt_data > pkt_meta', bad access 1", | |
| 860 | + "XDP pkt read, pkt_data > pkt_meta', corner case -1, bad access", | |
| 542 | 861 | .insns = { |
| 543 | 862 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 544 | 863 | offsetof(struct xdp_md, data_meta)), |
| 545 | 864 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 546 | 865 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 547 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 866 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 548 | 867 | BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), |
| 549 | 868 | BPF_JMP_IMM(BPF_JA, 0, 0, 1), |
| 550 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 869 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 551 | 870 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 552 | 871 | BPF_EXIT_INSN(), |
| 553 | 872 | }, |
| @@ -574,6 +893,42 @@ · 20 unmodified lines | ||
| 574 | 893 | .prog_type = BPF_PROG_TYPE_XDP, |
| 575 | 894 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 576 | 895 | }, |
| 896 | +{ | |
| 897 | + "XDP pkt read, pkt_data > pkt_meta', corner case, good access", | |
| 898 | + .insns = { | |
| 899 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 900 | + offsetof(struct xdp_md, data_meta)), | |
| 901 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 902 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 903 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 904 | + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), | |
| 905 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 906 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 907 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 908 | + BPF_EXIT_INSN(), | |
| 909 | + }, | |
| 910 | + .result = ACCEPT, | |
| 911 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 912 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 913 | +}, | |
| 914 | +{ | |
| 915 | + "XDP pkt read, pkt_data > pkt_meta', corner case +1, good access", | |
| 916 | + .insns = { | |
| 917 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 918 | + offsetof(struct xdp_md, data_meta)), | |
| 919 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 920 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 921 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 922 | + BPF_JMP_REG(BPF_JGT, BPF_REG_3, BPF_REG_1, 1), | |
| 923 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 924 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 925 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 926 | + BPF_EXIT_INSN(), | |
| 927 | + }, | |
| 928 | + .result = ACCEPT, | |
| 929 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 930 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 931 | +}, | |
| 577 | 932 | { |
| 578 | 933 | "XDP pkt read, pkt_meta' < pkt_data, good access", |
| 579 | 934 | .insns = { |
| @@ -593,16 +948,16 @@ · 13 unmodified lines | ||
| 593 | 948 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 594 | 949 | }, |
| 595 | 950 | { |
| 596 | − "XDP pkt read, pkt_meta' < pkt_data, bad access 1", | |
| 951 | + "XDP pkt read, pkt_meta' < pkt_data, corner case -1, bad access", | |
| 597 | 952 | .insns = { |
| 598 | 953 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 599 | 954 | offsetof(struct xdp_md, data_meta)), |
| 600 | 955 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 601 | 956 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 602 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 957 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 603 | 958 | BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), |
| 604 | 959 | BPF_JMP_IMM(BPF_JA, 0, 0, 1), |
| 605 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 960 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 606 | 961 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 607 | 962 | BPF_EXIT_INSN(), |
| 608 | 963 | }, |
| @@ -630,7 +985,43 @@ · 21 unmodified lines | ||
| 630 | 985 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 631 | 986 | }, |
| 632 | 987 | { |
| 633 | − "XDP pkt read, pkt_data < pkt_meta', good access", | |
| 988 | + "XDP pkt read, pkt_meta' < pkt_data, corner case, good access", | |
| 989 | + .insns = { | |
| 990 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 991 | + offsetof(struct xdp_md, data_meta)), | |
| 992 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 993 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 994 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 995 | + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), | |
| 996 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 997 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 998 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 999 | + BPF_EXIT_INSN(), | |
| 1000 | + }, | |
| 1001 | + .result = ACCEPT, | |
| 1002 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1003 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1004 | +}, | |
| 1005 | +{ | |
| 1006 | + "XDP pkt read, pkt_meta' < pkt_data, corner case +1, good access", | |
| 1007 | + .insns = { | |
| 1008 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1009 | + offsetof(struct xdp_md, data_meta)), | |
| 1010 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1011 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1012 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 1013 | + BPF_JMP_REG(BPF_JLT, BPF_REG_1, BPF_REG_3, 1), | |
| 1014 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 1015 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 1016 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1017 | + BPF_EXIT_INSN(), | |
| 1018 | + }, | |
| 1019 | + .result = ACCEPT, | |
| 1020 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1021 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1022 | +}, | |
| 1023 | +{ | |
| 1024 | + "XDP pkt read, pkt_data < pkt_meta', corner case, good access", | |
| 634 | 1025 | .insns = { |
| 635 | 1026 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 636 | 1027 | offsetof(struct xdp_md, data_meta)), |
| @@ -682,6 +1073,41 @@ · 45 unmodified lines | ||
| 682 | 1073 | .prog_type = BPF_PROG_TYPE_XDP, |
| 683 | 1074 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 684 | 1075 | }, |
| 1076 | +{ | |
| 1077 | + "XDP pkt read, pkt_data < pkt_meta', corner case +1, good access", | |
| 1078 | + .insns = { | |
| 1079 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1080 | + offsetof(struct xdp_md, data_meta)), | |
| 1081 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1082 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1083 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 1084 | + BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), | |
| 1085 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 1086 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1087 | + BPF_EXIT_INSN(), | |
| 1088 | + }, | |
| 1089 | + .result = ACCEPT, | |
| 1090 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1091 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1092 | +}, | |
| 1093 | +{ | |
| 1094 | + "XDP pkt read, pkt_data < pkt_meta', corner case -1, bad access", | |
| 1095 | + .insns = { | |
| 1096 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1097 | + offsetof(struct xdp_md, data_meta)), | |
| 1098 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1099 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1100 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 1101 | + BPF_JMP_REG(BPF_JLT, BPF_REG_3, BPF_REG_1, 1), | |
| 1102 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 1103 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1104 | + BPF_EXIT_INSN(), | |
| 1105 | + }, | |
| 1106 | + .errstr = "R1 offset is outside of the packet", | |
| 1107 | + .result = REJECT, | |
| 1108 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1109 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1110 | +}, | |
| 685 | 1111 | { |
| 686 | 1112 | "XDP pkt read, pkt_meta' >= pkt_data, good access", |
| 687 | 1113 | .insns = { |
| @@ -700,15 +1126,15 @@ · 12 unmodified lines | ||
| 700 | 1126 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 701 | 1127 | }, |
| 702 | 1128 | { |
| 703 | − "XDP pkt read, pkt_meta' >= pkt_data, bad access 1", | |
| 1129 | + "XDP pkt read, pkt_meta' >= pkt_data, corner case -1, bad access", | |
| 704 | 1130 | .insns = { |
| 705 | 1131 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 706 | 1132 | offsetof(struct xdp_md, data_meta)), |
| 707 | 1133 | BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), |
| 708 | 1134 | BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), |
| 709 | − BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 1135 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 6), | |
| 710 | 1136 | BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), |
| 711 | − BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 1137 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -6), | |
| 712 | 1138 | BPF_MOV64_IMM(BPF_REG_0, 0), |
| 713 | 1139 | BPF_EXIT_INSN(), |
| 714 | 1140 | }, |
| @@ -736,7 +1162,41 @@ · 21 unmodified lines | ||
| 736 | 1162 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 737 | 1163 | }, |
| 738 | 1164 | { |
| 739 | − "XDP pkt read, pkt_data >= pkt_meta', good access", | |
| 1165 | + "XDP pkt read, pkt_meta' >= pkt_data, corner case, good access", | |
| 1166 | + .insns = { | |
| 1167 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1168 | + offsetof(struct xdp_md, data_meta)), | |
| 1169 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1170 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1171 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 1172 | + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), | |
| 1173 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 1174 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1175 | + BPF_EXIT_INSN(), | |
| 1176 | + }, | |
| 1177 | + .result = ACCEPT, | |
| 1178 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1179 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1180 | +}, | |
| 1181 | +{ | |
| 1182 | + "XDP pkt read, pkt_meta' >= pkt_data, corner case +1, good access", | |
| 1183 | + .insns = { | |
| 1184 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1185 | + offsetof(struct xdp_md, data_meta)), | |
| 1186 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1187 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1188 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 8), | |
| 1189 | + BPF_JMP_REG(BPF_JGE, BPF_REG_1, BPF_REG_3, 1), | |
| 1190 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8), | |
| 1191 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1192 | + BPF_EXIT_INSN(), | |
| 1193 | + }, | |
| 1194 | + .result = ACCEPT, | |
| 1195 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1196 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1197 | +}, | |
| 1198 | +{ | |
| 1199 | + "XDP pkt read, pkt_data >= pkt_meta', corner case, good access", | |
| 740 | 1200 | .insns = { |
| 741 | 1201 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 742 | 1202 | offsetof(struct xdp_md, data_meta)), |
| @@ -791,7 +1251,44 @@ · 48 unmodified lines | ||
| 791 | 1251 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 792 | 1252 | }, |
| 793 | 1253 | { |
| 794 | − "XDP pkt read, pkt_meta' <= pkt_data, good access", | |
| 1254 | + "XDP pkt read, pkt_data >= pkt_meta', corner case +1, good access", | |
| 1255 | + .insns = { | |
| 1256 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1257 | + offsetof(struct xdp_md, data_meta)), | |
| 1258 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1259 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1260 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 1261 | + BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), | |
| 1262 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 1263 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 1264 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1265 | + BPF_EXIT_INSN(), | |
| 1266 | + }, | |
| 1267 | + .result = ACCEPT, | |
| 1268 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1269 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1270 | +}, | |
| 1271 | +{ | |
| 1272 | + "XDP pkt read, pkt_data >= pkt_meta', corner case -1, bad access", | |
| 1273 | + .insns = { | |
| 1274 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1275 | + offsetof(struct xdp_md, data_meta)), | |
| 1276 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1277 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1278 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 7), | |
| 1279 | + BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_1, 1), | |
| 1280 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 1281 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -7), | |
| 1282 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1283 | + BPF_EXIT_INSN(), | |
| 1284 | + }, | |
| 1285 | + .errstr = "R1 offset is outside of the packet", | |
| 1286 | + .result = REJECT, | |
| 1287 | + .prog_type = BPF_PROG_TYPE_XDP, | |
| 1288 | + .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, | |
| 1289 | +}, | |
| 1290 | +{ | |
| 1291 | + "XDP pkt read, pkt_meta' <= pkt_data, corner case, good access", | |
| 795 | 1292 | .insns = { |
| 796 | 1293 | BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, |
| 797 | 1294 | offsetof(struct xdp_md, data_meta)), |
| @@ -845,6 +1342,43 @@ · 47 unmodified lines | ||
| 845 | 1342 | .prog_type = BPF_PROG_TYPE_XDP, |
| 846 | 1343 | .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, |
| 847 | 1344 | }, |
| 1345 | +{ | |
| 1346 | + "XDP pkt read, pkt_meta' <= pkt_data, corner case +1, good access", | |
| 1347 | + .insns = { | |
| 1348 | + BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, | |
| 1349 | + offsetof(struct xdp_md, data_meta)), | |
| 1350 | + BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, offsetof(struct xdp_md, data)), | |
| 1351 | + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), | |
| 1352 | + BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 9), | |
| 1353 | + BPF_JMP_REG(BPF_JLE, BPF_REG_1, BPF_REG_3, 1), | |
| 1354 | + BPF_JMP_IMM(BPF_JA, 0, 0, 1), | |
| 1355 | + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -9), | |
| 1356 | + BPF_MOV64_IMM(BPF_REG_0, 0), | |
| 1357 | + BPF_EXIT_INSN(), | |
| 1358 | + }, | |
| 1359 | + .result = ACCEPT, | |
| 1360 | + .prog_type = BPF_PROG_TYPE_XDP, | |
81 more lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 40 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 16 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 9 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 213 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 45 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 35 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 51 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 150 lines aren’t shown here.